Write a program into a file called js15.js.
The program must accept input of a number from the user. Assume the number is the temperature in Fahrenheit. Your program must convert the temperature to Celsius and print it on the console.
The conversion formula is c = 5/9(f-32)
where c is the result in Celsius, and f
is the temperature in Fahrenheit.
'use strict';
var f = Number(prompt('Indtast fahrenheit'));
var c = 5 / 9 * (f - 32);
console.log(`${f} \xB0F = ${c} \xB0C`);
'use strict';
var f = Number(prompt('Indtast fahrenheit'));
var c = 5 / 9 * (f - 32);
document.write(`<p>${f} °F = ${c} °C</p>`);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>title</title>
</head>
<body>
<h1>js15a.js</h1>
<script src="./js15a.js"></script>
</body>
</html>
Write a program into a file called js201.js.
The program must accept input of a number from the user. Assume the number is a year. Make JavaScript write on the console true or false as to whether the year is a leap year or not. If you don't know what a leap year is, Google it.
Write another program into a file called js202.js.
The program must accept input of a number from the user. Assume the number is a CPR number (a danish social security number). Make JavaScript write on the console true or false as to whether the person holding the number is a woman.
'use strict';
var year = Number(prompt('Enter year'));
var isLeap = (year % 4 == 0 && !(year % 100 == 0)) || year % 400 == 0;
console.log(`Is ${year} a leap year? ${isLeap}`);'use strict';
var cpr = Number(prompt('Enter cpr'));
console.log(cpr);
console.log(`Womans cpr? ${99999999 < cpr && cpr < 9999999999 && cpr % 2 === 0}`);
In todays lesson, re Example 2.7, there was an example of letting JavaScript print the truth table for a negation on the console.
js25c.js
for printing the truth table for the conjunction.
js25d.js with the code for printing the truth
table for the disjunction.
You will have noticed that a conjunction/disjunction of two questions have four possible outcomes, each condition may be true or false. Two conditions, 2 x 2 possible outcomes.
Three conditions that could each result in true or false thus gives you 2 x 2 x 2 = 8 possible outcomes.
js25c3.js
for printing the truth table for a conjunction of 3
conditions: var1, var2, and
var3.
js25d3.js with the code for printing the truth
table for a disjunction with three conditions.
For the latter two, it may be very helpful to visualize by drawing them on paper first.
'use strict';
console.log('Truth table for conjunction and disjunction with 2 vars');
console.log('var1\tvar2\tvar1 && var2\tvar1 || var2');
var var1 = true;
var var2 = true;
console.log(var1 + '\t' + var2 + '\t' + (var1 && var2) + '\t\t' + (var1 || var2));
var2 = false;
console.log(var1 + '\t' + var2 + '\t' + (var1 && var2) + '\t\t' + (var1 || var2));
var1 = false;
var2 = true;
console.log(var1 + '\t' + var2 + '\t' + (var1 && var2) + '\t\t' + (var1 || var2));
var2 = false;
console.log(var1 + '\t' + var2 + '\t' + (var1 && var2) + '\t\t' + (var1 || var2));
'use strict';
document.write('<pre>' + 'Truth table for conjunction and disjunction with 3 vars' + '</pre>');
document.write('<pre>' + 'var1\tvar2\tvar3\tvar1 && var2 && var3\tvar1 || var2 || var3' + '</pre>');
var var1 = true;
var var2 = true;
var var3 = true;
document.write('<pre>' + var1 + '\t' + var2 + '\t' + var3 + '\t' + (var1 && var2 && var3) + '\t\t\t' + (var1 || var2 || var3) + '</pre>');
var3 = false;
document.write('<pre>' + var1 + '\t' + var2 + '\t' + var3 + '\t' + (var1 && var2 && var3) + '\t\t\t' + (var1 || var2 || var3) + '</pre>');
var2 = false;
var3 = true;
document.write('<pre>' + var1 + '\t' + var2 + '\t' + var3 + '\t' + (var1 && var2 && var3) + '\t\t\t' + (var1 || var2 || var3) + '</pre>');
var2 = false;
var3 = false;
document.write('<pre>' + var1 + '\t' + var2 + '\t' + var3 + '\t' + (var1 && var2 && var3) + '\t\t\t' + (var1 || var2 || var3) + '</pre>');
var1 = false;
var2 = true;
var3 = true;
document.write('<pre>' + var1 + '\t' + var2 + '\t' + var3 + '\t' + (var1 && var2 && var3) + '\t\t\t' + (var1 || var2 || var3) + '</pre>');
var3 = false;
document.write('<pre>' + var1 + '\t' + var2 + '\t' + var3 + '\t' + (var1 && var2 && var3) + '\t\t\t' + (var1 || var2 || var3) + '</pre>');
var2 = false;
var3 = true;
document.write('<pre>' + var1 + '\t' + var2 + '\t' + var3 + '\t' + (var1 && var2 && var3) + '\t\t\t' + (var1 || var2 || var3) + '</pre>');
var3 = false;
document.write('<pre>' + var1 + '\t' + var2 + '\t' + var3 + '\t' + (var1 && var2 && var3) + '\t\t\t' + (var1 || var2 || var3) + '</pre>');
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>title</title>
</head>
<body>
<h1>js25c3.js</h1>
<script src="./js25c3a.js"></script>
</body>
</html>
Predict the results of
8 / 2 * (2 + 2) // ?
8 / 2 * 2 + 2 // ?
Then let JavaScript solve it. Print the result on the console.
Hand in as a file called js30.js
'use strict';
console.log(`8 / 2 * (2 + 2) = ${8 / 2 * (2 + 2)}`);
console.log('remember js processes from left to right with respect to precedence rules');
console.log(`the expression is first revalidated to: 8 / 2 * (2 + 2) => 8 / 2 * 4`);
console.log(`8 / 2 * 4 => 4 * 4 = ${4 * 4}`);'use strict';
document.write(`<pre>8 / 2 * (2 + 2) = ${8 / 2 * (2 + 2)}</pre>`);
document.write('<p>remember js processes from left to right with respect to precedence rules');
document.write(`<p>the expression is first revalidated to: <code>8 / 2 * (2 + 2) => 8 / 2 * 4</code></p>`);
document.write(`<pre>8 / 2 * 4 => 4 * 4 = ${4 * 4}</pre>`);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>title</title>
</head>
<body>
<h1>js30.js</h1>
<script src="./js30a.js"></script>
</body>
</html>
Click here ;)
I gave you a naive model solution to the coin flipping problem. It still resides at the repo:
git clone https://phidip@bitbucket.org/phidip/coinflipping.git
After cloning it, copy it into a file jsConds0.js,
then change it into rolling a die 10 times. Let it tally the
outcomes, and print the number of ones, twos, ..., sixes
when it is done.
Hint: You need more counter variables, as a die has 6 sides. Consequently you also need more conditionals.
Place the code in jsConds0.js
jsConds0.js
'use strict';
const play = function() {
return Math.floor(Math.random() * 6 + 1);
}'use strict';
let ones = 0;
let twos = 0;
let threes = 0;
let fours = 0;
let fives = 0;
let sixes = 0;
let r = play();
if (r === 1)
ones++;
else if (r === 2)
twos++;
else if (r === 3)
threes++;
else if (r === 4)
fours++;
else if (r === 5)
fives++;
else
sixes++;
r = play();
if (r === 1)
ones++;
else if (r === 2)
twos++;
else if (r === 3)
threes++;
else if (r === 4)
fours++;
else if (r === 5)
fives++;
else
sixes++;
r = play();
if (r === 1)
ones++;
else if (r === 2)
twos++;
else if (r === 3)
threes++;
else if (r === 4)
fours++;
else if (r === 5)
fives++;
else
sixes++;
r = play();
if (r === 1)
ones++;
else if (r === 2)
twos++;
else if (r === 3)
threes++;
else if (r === 4)
fours++;
else if (r === 5)
fives++;
else
sixes++;
r = play();
if (r === 1)
ones++;
else if (r === 2)
twos++;
else if (r === 3)
threes++;
else if (r === 4)
fours++;
else if (r === 5)
fives++;
else
sixes++;
r = play();
if (r === 1)
ones++;
else if (r === 2)
twos++;
else if (r === 3)
threes++;
else if (r === 4)
fours++;
else if (r === 5)
fives++;
else
sixes++;
r = play();
if (r === 1)
ones++;
else if (r === 2)
twos++;
else if (r === 3)
threes++;
else if (r === 4)
fours++;
else if (r === 5)
fives++;
else
sixes++;
r = play();
if (r === 1)
ones++;
else if (r === 2)
twos++;
else if (r === 3)
threes++;
else if (r === 4)
fours++;
else if (r === 5)
fives++;
else
sixes++;
r = play();
if (r === 1)
ones++;
else if (r === 2)
twos++;
else if (r === 3)
threes++;
else if (r === 4)
fours++;
else if (r === 5)
fives++;
else
sixes++;
r = play();
if (r === 1)
ones++;
else if (r === 2)
twos++;
else if (r === 3)
threes++;
else if (r === 4)
fours++;
else if (r === 5)
fives++;
else
sixes++;
document.write(`<p>`);
document.write(`1's: ${ones}<br/>`);
document.write(`2's: ${twos}<br/>`);
document.write(`3's: ${threes}<br/>`);
document.write(`4's: ${fours}<br/>`);
document.write(`5's: ${fives}<br/>`);
document.write(`6's: ${sixes}<br/>`);
document.write(`total: ${ones+twos+threes+fours+fives+sixes}</p>`);
<!doctype html>
<html>
<head>
<title>jsConds0</title>
<meta charset='utf-8'/>
<script src='jsConds0.js'></script>
</head>
<body>
<h1>jsConds0a</h1>
<script src='jsConds0a.js'></script>
</body>
</html>
Write three functions:
addVat(a), that returns amount including vat
given an amount as input.
subVat(a), that returns amount excluding vat
given an amount as input.
calcVat(a), that returns the vat from the given
amount.
Use the Danish vat of 25.0%.
Hand in as a file called jsFuncs0.js
'use strict';
const VAT = 25;
const addVat = function(a) {
return a * (1 + VAT / 100);
}
const subVat = function(a) {
return a / (1 + VAT / 100);
}
const calcVat = function(a) {
return a - subVat(a);
}'use strict';
let amount = Number(prompt('Enter Amount'));
document.write(`<p>Amount incl vat: ${addVat(amount)}`);
document.write(`<p>Amount excl vat: ${subVat(addVat(amount))}`);
document.write(`<p>Vat: ${calcVat(addVat(amount))}`);
<!doctype html>
<html>
<head>
<title>jsfuncs0</title>
<meta charset='utf-8'/>
<script src='jsFuncs0.js'></script>
</head>
<body>
<h1>jsfuncs0</h1>
<script src='jsFuncs0a.js'></script>
</body>
</html>
Write three functions:
first(s), that returns
the first character of the string s.
last(s), that returns
the last character of the string s.
middle(s), that returns
whatever is between the first and the last character of the
string s.
Hint: Take a look a the string
functions in your
MDN reference, especially
the substr function.
Hand in as one file called jsTextUtils.js
jsTextUtils.js
'use strict';
const first = function (txt) {
return txt.charAt(0);
}
const last = function (txt) {
return txt.charAt(txt.length - 1);
}
const middle = function (txt) {
return txt.substring(1, txt.length - 1);
}
'use strict';
var phrase = prompt('Enter Phrase');
document.write(`<p>First - Middle - Last</p>
<p><b>
${first(phrase)} - ${middle(phrase)} - ${last(phrase)}
</b></p>`);
<!doctype html>
<html>
<head>
<title>jsfuncs1</title>
<meta charset='utf-8'/>
<script src='jsTextUtils0.js'></script>
</head>
<body>
<h1>jsfuncs1</h1>
<script src='jsFuncs1a.js'></script>
</body>
</html>
In todays lesson, I gave you play() that could
flip a coin. We have, in the lesson about conditionals, worked
with throwing a die. On principle this there is only one tiny
difference between the two.
Now, I want you to identify this difference, and then alter
play, so that it accomodates coin flipping, die
throwing, turning a spindle with any number of sides, and even
a roulette.
Place the function in myFuncLib.js.
myFuncLib
'use strict';
/*
* play requires an input arg
* given 2, it will simulate a coin
* given 6, it will simulate a die
* calling sequence for a die: let result = play(6);
*/
const play = function(n) {
return Math.floor(Math.random() * n + 1);
}
/*
* Convert celsius input to fahrenheit
*/
const C2F = function(c) {
return 9 / 5 * c + 32;
}
/*
* Convert fahrenheit input to celsius
*/
const F2C = function(f) {
return 5 / 9 * (f - 32);
}
'use strict';
document.write(`<p>Flip coin: ${play(2)}</p>`);
document.write(`<p>Flip coin: ${play(2)}</p>`);
document.write(`<p>Flip coin: ${play(2)}</p>`);
document.write(`<hr/>`);
document.write(`<p>Throw die: ${play(6)}</p>`);
document.write(`<p>Throw die: ${play(6)}</p>`);
document.write(`<p>Throw die: ${play(6)}</p>`);
document.write(`<p>Throw die: ${play(6)}</p>`);
document.write(`<hr/>`);
document.write(`<p>Spin the wheel: ${play(37)}</p>`);
document.write(`<hr/>`);
document.write(`<h2>Temps</h2>`);
let c = Number(window.prompt('Enter temp in C'));
document.write(`<p>${c} °C = ${C2F(c)}°F</p>`);
let f = Number(window.prompt('Enter temp in F'));
document.write(`<p>${f} °F = ${F2C(f)}°C</p>`);<!doctype html>
<html>
<head>
<title>myFuncLib</title>
<meta charset='utf-8'/>
<script src='myFuncLib.js'></script>
</head>
<body>
<h1>jsfuncs23</h1>
<script src='jsFuncs23.js'></script>
</body>
</html>
In the assignments Conds.0, and Funcs.2, you were flipping a coin of rolling a die. In both cases you used counter variables to tally the number of the various outcomes. Now you must change that to using an array instead of individual variables. Write a comment or two about it in the code.
Hand in as a file called jsArrays1.js
jsArrays1.js
'use strict';
const roll = function(n) {
return Math.floor(Math.random() * n + 1);
}'use strict';
let res;
let tally = [0, 0, 0, 0, 0, 0, 0];
res = roll(6);
tally[res]++;
res = roll(6);
tally[res]++;
res = roll(6);
tally[res]++;
res = roll(6);
tally[res]++;
res = roll(6);
tally[res]++;
res = roll(6);
tally[res]++;
res = roll(6);
tally[res]++;
res = roll(6);
tally[res]++;
res = roll(6);
tally[res]++;
res = roll(6);
tally[res]++;
let i = 1;
console.log(`${i}'s:\t ${tally[i++]}`);
console.log(`${i}'s:\t ${tally[i++]}`);
console.log(`${i}'s:\t ${tally[i++]}`);
console.log(`${i}'s:\t ${tally[i++]}`);
console.log(`${i}'s:\t ${tally[i++]}`);
console.log(`${i}'s:\t ${tally[i++]}`);<!doctype html>
<html>
<head>
<title>jsArrays1</title>
<meta charset='utf-8'/>
<script src='jsArrays1.js'></script>
</head>
<body>
<h1>jsArrays1</h1>
<script src='jsArraysExec1.js'></script>
</body>
</html>
Write a function that checks whether an array is palindromic, ie whether the first and last elements are identical, and the middle is palindromic.
Hand in as a file called jsArrays2.js
jsArrays3.js
'use strict';
const first = function (arr) {
return arr[0];
}
const last = function (arr) {
return arr[arr.length - 1];
}
const middle = function (arr) {
return arr.slice(1,-1)
}
const isPalindrome = function(arr, debug) {
if (arr.length <= 1)
return true;
if (debug)
console.log(`${first(arr)} - ${middle(arr)} - ${last(arr)}`);
return first(arr) === last(arr) && isPalindrome(middle(arr), debug);
}
'use strict';
let arr = [];
let input = null;
do {
if (input === 'qw')
break;
if (input == null)
continue;
arr.push(input);
} while(input = prompt('Enter whatever, "qw" for stop'));
console.log(arr);
console.log(`is the array ${arr} palindromic: ${isPalindrome(arr) ? 'yes' : 'no'}`);<!doctype html>
<html>
<head>
<title>jsArrays2</title>
<meta charset='utf-8'/>
<script src='jsArrays2.js'></script>
</head>
<body>
<h1>jsArrays2</h1>
<script src='jsArraysExec2.js'></script>
</body>
</html>
Write a program that rolls a die i times,
and then two functions that check
n's where
n is between 1-6
Hand in as a file called jsArrays3.js
jsArrays3.js
'use strict';
const play = function(n) {
return Math.floor(Math.random() * n + 1);
}
/*
* n is number of plays, arr is results array
*/
const isOnly = function(n, arr) {
if (arr.includes(n))
return true;
else
return false;
}
/*
* returns number of n's
*/
const howMany = function(n, arr) {
return arr[n];
}'use strict';
let res = [0, 0, 0, 0, 0, 0, 0]
const n = Number(prompt('How many plays?'));
let i = 0;
while(i < n) {
res[play(6)]++;
i++;
}
const q = Number(prompt('What die are you looking for?'));
console.log(`Were all faces the same? ${isOnly(n, res)}`);
console.log(`There were ${howMany(q, res)} ${q}'s`);<!doctype html>
<html>
<head>
<title>jsArrays3</title>
<meta charset='utf-8'/>
<script src='jsArrays3.js'></script>
</head>
<body>
<h1>jsArrays3</h1>
<script src='jsArraysExec3.js'></script>
</body>
</html>
Definition
A natural numberpis called prime ifp ≠ 1and the only numbers that dividepare 1 andpitself.
Fundamental Theorem of Arithmetic
Every natural number greater than 1 is either prime or can be written uniquely as a product of prime numbers.
There is a nice proof of that theorem but since this is no math class, we shall skip that, and just trust that it is so, and use it.
Now you must solve at least number 1 of the following. If you have the energy and skill you may want to have a go at the next ones too, but please solve the rest of this chapter's assignments before spending time on that.
isPrime(p) that returns
true if p is prime, and
false otherwise.
p
if isPrime(p) === false.
p
if isPrime(p) === false.
p more than once.
Write an HTML5 page that allows for testing your function(s).
Hint for beginners:
You may prefer to work with embedded JavaScript while you
test your code. Once it works as desired, separate the JavaScript into an
individual .js file, test again, then hand in your
solution.
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;
}'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}`);<!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>
jsloops71.js
[Dow16] Exercise 7.1
'use strict';
/* Downey: thinkjava, ex 71 */
const loop = function(n) {
let i = n;
while (i > 1) {
console.log(i);
if (i % 2 == 0) {
i = i / 2;
} else {
i = i + 1;
}
}
}
loop(10);
i and n
during the execution of loop.
The table should contain one column for each variable and
one line for each iteration. You might trick the program
into doing it for you.
jsLoops71.js
'use strict';
/* Downey: thinkjava, ex 71 */
const loop = function(n) {
let s = 's ='; // logstring
let i = n;
while (i > 1) {
s += ' ' + i; // build logstring
console.log(s);
if (i % 2 === 0) {
i = i / 2;
} else {
i = i + 1;
if (i % 100 <= 1)
break;
}
}
return s;
}
/* find out if some values makes it divergent */'use strict';
let n = Number(prompt('Chećk function, enter number < 100'));
document.write(`<h4>n = ${n}</h4>`);
document.write(`<p>${loop(n)}</p>`);
<!doctype html>
<html>
<head>
<title>jsLoops71</title>
<meta charset='utf-8'/>
<script src='jsLoops71.js'></script>
</head>
<body>
<h1>jsLoops71exec</h1>
<script src='jsLoops71exec.js'></script>
</body>
</html>
[Hav19] Exercise FizzBuzz, chapter 2.
Write a program that uses console.log to print all the numbers
from 1 to 100, with two exceptions.
For numbers divisible by 3, print "Fizz" instead of the
number,
and for numbers divisible by 5 (and not 3), print "Buzz"
instead. Save as fizzbuzz.js.
When you have that working, modify your program to print
"FizzBuzz" for numbers that are divisible by both 3 and 5
(and still print "Fizz" or "Buzz" for numbers divisible by only
one of those). Save as fizzbuzzBetter.js.
(This is actually a job interview question that has been claimed
to weed out a significant percentage of programmer candidates.
So if you solved it, your labor market value just went up.)
fizzbuzz.js
'use strict';
for (let i = 1; i <= 100; i++) {
if (i % 5 === 0 && i % 3 !== 0)
console.log('Buzz');
else if (i % 3 === 0)
console.log('Fizz');
else
console.log(i)
}
<!doctype html>
<html>
<head>
<title>fizzbuzz</title>
<meta charset='utf-8'/>
</head>
<body>
<h1>fizzbuzz</h1>
<script src='fizzbuzz.js'></script>
</body>
</html>
fizzbuzzBetter.js
'use strict';
for (let i = 1; i <= 100; i++) {
if (i % (3 * 5) === 0)
console.log('FizzBuzz');
else if (i % 5 === 0)
console.log('Buzz');
else if (i % 3 === 0)
console.log('Fizz');
else
console.log(i)
}
<!doctype html>
<html>
<head>
<title>fizzbuzzBetter</title>
<meta charset='utf-8'/>
</head>
<body>
<h1>fizzbuzz</h1>
<script src='fizzbuzzBetter.js'></script>
</body>
</html>
Write an iterative function powi(r, e)
that calculates
the e-th power of r, re.
Document it with a couple of testcases.
Save the function in myFuncLib.js.
jsLoops73.js
'use strict';
const powi = function(r, e) {
let res = 1;
while (e > 0) {
res *= r;
e -= 1;
}
return res;
}'use strict';
let r = Number(prompt('powi: Enter root'));
let e = Number(prompt('powi: Enter exponent'));
document.write(`<p>powi: ${r}<sup>${e}</sup> = ${powi(r, e)}</p>`);
<!doctype html>
<html>
<head>
<title>jsLoops73</title>
<meta charset='utf-8'/>
<script src='jsLoops73.js'></script>
</head>
<body>
<h1>jsLoops73exec</h1>
<script src='jsLoops73exec.js'></script>
</body>
</html>
Write an iterative function facti(n)
that calculates n!.
Document it with a couple of testcases.
Save the function in myFuncLib.js.
jsLoops74.js
'use strict';
const facti = function(n) {
let res = 1;
while (n > 0) {
res *= n;
n -= 1
}
return res;
}'use strict';
let n = Number(prompt('facti: Enter number for factorial'));
document.write(`<p>facti: ${n}! = ${facti(n)}</p>`);
<!doctype html>
<html>
<head>
<title>jsLoops74</title>
<meta charset='utf-8'/>
<script src='jsLoops74.js'></script>
</head>
<body>
<h1>jsLoops74exec</h1>
<script src='jsLoops74exec.js'></script>
</body>
</html>
We have flipped coins and dies 10 times. I want you to change
the code so that the user may enter the number of times she
wants to play dice, say 25, 1000, or even 100000000.
Write a jsPlay75.html that does that, and of course
uses the function we created earlier.
Change the program so that user can choose between flipping coins, rolling dice, playing roulette, etc.
Save them in a repo games.
jsLoops75.js
'use strict';
/*
* n: what do we play, 2:coins, 6:dice, ...
*/
const roll = function(n) {
return Math.floor(Math.random() * n + 1);
}
/*
* n: how many times
* a: what do we play, 2:coins, 6:dice, ...
*/
const play_n_times = function(n, a) {
let res;
let tally = [];
let i = 0;
while (i <= a) { // dim and init array
tally[i] = 0;
i += 1;
}
let then = new Date();
i = 0;
while (i < n) { // play n times
res = roll(a);
tally[res] += 1;
i += 1;
}
let now = new Date();
console.log(`Time: ${now - then} ms`);
return tally; // return results
}
/*
* print results array on log
*/
const print_tally = function(arr) {
for (let i = 1; i < arr.length; i += 1) {
console.log(`${i}'s: ${arr[i]}`);
}
console.log('---------------------------');
}jsPlay75.js
'use strict';
const init = function() {
document.getElementById('play').addEventListener('click', function() {
var howMany = Number(prompt('How many plays?'));
var what = Number(prompt('2 for coins, 6 for dice'));
let arr = play_n_times(howMany, what);
print_tally(arr);
});
}
window.addEventListener('load', init);jsPlay75.html
<!doctype html>
<html>
<head>
<meta charset='utf-8'/>
<script src='jsLoops75.js'></script>
<script src='jsPlay75.js'></script>
</head>
<body>
<h1>Play, Flip, Roll</h1>
<p>
<button id='play'>Play!</button>
</p>
</body>
</html>
Output from 1,000,000,000, one billion, plays with a die and a coin respectively
Time: 6642 ms
1's: 166668770
2's: 166676350
3's: 166655799
4's: 166664282
5's: 166666453
6's: 166668346
---------------------------
Time: 6700 ms
1's: 500011997
2's: 499988003
---------------------------
There is a mathematical koncept, factorial, important in
probability and statistics. The definition of n!:
n! = n * (n-1) * (n - 2) * ... * 2 * 1
There is a genuinely recursive definition that is, perhaps, more elegant:
n! = n * (n - 1)!
Write a recursive function fact(n) that calculates
the factorial of a given natural number n.
Document it with a couple of testcases.
Place the function in myRecurseLib.js.
myRecurseLib.js
'use strict';
/*
* returns nth fibonacci number
*/
const fibo = function(n) {
if (n === 0 || n === 1)
return n;
return fibo(n - 1) + fibo(n - 2);
}
/*
* returns n! iterative
*/
let fact = function(n) {
if (n <= 1)
return 1;
else
return n * fact(n - 1);
}
/*
* returns r to the e
*/
const pow = function(r, e) {
if (e <= 0)
return 1;
return r * pow(r, e-1);
}'use strict';
const n = Number(prompt('Enter n for n!'));
document.write(`<p>${n}! = ${fact(n)}</p>`);<!doctype html>
<html>
<head>
<title>jsLoops0</title>
<meta charset='utf-8'/>
<script src='myRecurseLib.js'></script>
</head>
<body>
<h1>jsLoops0exec</h1>
<script src='jsLoops0exec.js'></script>
</body>
</html>
There is a mathematical koncept, Fibonacci numbers, important in
various contexts eg closely related to calculating the golden
ratio. The definition of the n-th Fibonacci number
Fn:
F0 = 0; F1 = 1;
and:
Fn =
Fn-1 + Fn-2
Write a recursive function fibo(n) that calculates
the n-th Fibonacci number.
Document it with a couple of testcases.
Save the function in myRecurseLib.js.
myRecurseLib.js
'use strict';
/*
* returns nth fibonacci number
*/
const fibo = function(n) {
if (n === 0 || n === 1)
return n;
return fibo(n - 1) + fibo(n - 2);
}
/*
* returns n! iterative
*/
let fact = function(n) {
if (n <= 1)
return 1;
else
return n * fact(n - 1);
}
/*
* returns r to the e
*/
const pow = function(r, e) {
if (e <= 0)
return 1;
return r * pow(r, e-1);
}'use strict';
const n = Number(prompt('Enter n for nth Fibonacci number'));
document.write(`F<sub>${n}</sub> = ${fibo(n)}`);<!doctype html>
<html>
<head>
<title>jsLoops0</title>
<meta charset='utf-8'/>
<script src='myRecurseLib.js'></script>
</head>
<body>
<h1>jsLoops1exec</h1>
<script src='jsLoops1exec.js'></script>
</body>
</html>
The mathematical powers, eg 27, or 34 may be calculated recursively.
Write a recursive function pow(r, e) that
calculates re.
It must work for
r ∈ ℕ,
and e ∈ ℕ.
You might test whether it also works for
r ∈ ℤ,
and e ∈ ℤ
Put it into your myRecurseLib.js.
myRecurseLib.js
'use strict';
/*
* returns nth fibonacci number
*/
const fibo = function(n) {
if (n === 0 || n === 1)
return n;
return fibo(n - 1) + fibo(n - 2);
}
/*
* returns n! iterative
*/
let fact = function(n) {
if (n <= 1)
return 1;
else
return n * fact(n - 1);
}
/*
* returns r to the e
*/
const pow = function(r, e) {
if (e <= 0)
return 1;
return r * pow(r, e-1);
}'use strict';
let r = Number(prompt('Power: Enter root'));
let e = Number(prompt('Power: Enter exponent'));
document.write(`<p>${r}<sup>${e}</sup> = ${pow(r, e)}</p>`)
<!doctype html>
<html>
<head>
<title>jsRecursion3</title>
<meta charset='utf-8'/>
<script src='myRecurseLib.js'></script>
</head>
<body>
<h1>jsLoops3</h1>
<script src='jsLoops3exec.js'></script>
</body>
</html>
Take a look at this page. Play with the left side of the footer. Click, and click again.
Create equivalent handlers for the center and right of the footer so that it is dynamic in the same way. I do want, however, the text in the middle column to be yellow. Do remember, that UX is not to let your users guess what they have to do ;)
<!doctype html>
<html>
<head>
<meta charset='utf-8'/>
<title>Dave Ellis Conventional Page</title>
<link href='daveEllis.css' rel='stylesheet'/>
<script src='nQuery.js'></script>
<script src='davis1.js'></script>
</head>
<body>
<header>
<nav>
<h1>Your Website</h1>
<ul>
<li><a href='#'>Is</a></li>
<li><a href='#'>This</a></li>
<li><a href='#'>Your</a></li>
<li><a href='#'>Website</a></li>
</ul>
</nav>
</header>
<main class='vc1'>
<p>
This page is written, with permission,
from <a href='http://www.novolume.co.uk/blog/all-websites-look-the-same/'>
Dave Ellis' Blog</a> to mimic that page.
</p>
</main>
<footer>
<article id="left"></article>
<article id="center"></article>
<article id="right"></article>
</footer>
<p>
Inspiration: <a href='http://www.novolume.co.uk/'>Dave Ellis</a>
</p>
</body>
</html>
"use strict";
/*
* davis1.js
*/
let filla = function (ev) {
let arri = [];
let arrh = [];
let arrt = [];
arri["left"] = "book-icon.png";
arri["center"] = "cogs-icon.png";
arri["right"] = "shield-icon.png";
arrh["left"] = "Always";
arrh["center"] = "Three";
arrh["right"] = "Columns";
arrt["left"] = "You could have four columns here but you won't. You'll have three like everyone else.";
arrt["center"] = "Have a cog icon above one of these columns if you are really feeling especially creative. ";
arrt["right"] = "The perfect place to talk about your services. Because co-incidentally you have three of them.";
let art = $(ev.target.id);
if (art.innerHTML !== "") {
while (art.firstChild) {
art.removeChild(art.firstChild);
}
} else {
let img = document.createElement("img"); // create element
img.setAttribute("src", arri[ev.target.id]);
img.setAttribute("alt", "icon");
img.setAttribute("width", "64");
let h1 = document.createElement("h1"); // create element
let txt = document.createTextNode(arrh[ev.target.id]); // create text
h1.appendChild(txt); // put on tree
let par = document.createElement("p"); // create element
txt = document.createTextNode(arrt[ev.target.id]); // create text
par.appendChild(txt); // put onto tree
art.appendChild(img);
art.appendChild(h1);
art.appendChild(par);
}
}
let initialize = function () {
$("left").addEventListener("click", filla);
$("center").addEventListener("click", filla);
$("right").addEventListener("click", filla);
}
window.addEventListener("load", initialize);
On the basis of the code from Example 8.20 create a page with two or three links to videos. Adapt the controls with Jeremy's code, and feel free to add eg sound controls as well.
Christian B's solution:
'use strict';
(function() {
function createVideoControls() {
var vids = document.getElementsByTagName('video');
for (var i = 0 ; i < vids.length ; i++) {
addControls( vids[i] );
}
}
function addControls( vid ) {
vid.removeAttribute('controls');
// vid.height = vid.videoHeight;
// vid.width = vid.videoWidth;
// vid.parentNode.style.height = vid.videoHeight + 'px';
// vid.parentNode.style.width = vid.videoWidth + 'px';
vid.removeAttribute('style')
var controls = document.createElement('div');
controls.setAttribute('class','controls');
var play = document.createElement('button');
play.setAttribute('title','Play');
play.innerHTML = '►';
controls.appendChild(play);
vid.parentNode.insertBefore(controls, vid);
play.onclick = function () {
if (vid.ended) {
vid.currentTime = 0;
}
if (vid.paused) {
vid.play();
} else {
vid.pause();
}
};
vid.addEventListener('play', function () {
play.innerHTML = '▐▐';
play.setAttribute('paused', true);
}, false);
vid.addEventListener('pause', function () {
play.removeAttribute('paused');
play.innerHTML = '►';
}, false);
vid.addEventListener('ended', function () {
vid.pause();
}, false);
} // end of addControls
window.addEventListener('load', function() {
createVideoControls();
}
);
})();<!doctype html>
<html>
<head>
<meta charset='utf-8'/>
<title>Video Controle</title>
<!-- <link href='js7_DOM.css' rel='stylesheet'/> -->
<script src='nQuery.js'></script>
<!-- <script src='js10_videoControls.js'></script> -->
</head>
<body>
<header>
<nav>
<h1>Video Controle</h1>
<ul>
<li><a href='#'>vidONE</a></li>
<li><a href='#'>vidTWO</a></li>
<li><a href='#'>vidTHREE</a></li>
</ul>
</nav>
</header>
<main>
<div class="video-wrapper">
<video id="movie" controls>
<source src="http://media.w3.org/2010/05/sintel/trailer.mp4" />
<source src="http://media.w3.org/2010/05/sintel/trailer.webm"
type='video/webm; codecs="vp8, vorbis"' />
<source src="http://media.w3.org/2010/05/sintel/trailer.ogv"
type='video/ogg; codecs="theora, vorbis"' />
<p>Download movie as
<a href="http://media.w3.org/2010/05/sintel/trailer.mp4">MP4</a>,
<a href="http://media.w3.org/2010/05/sintel/trailer.webm">WebM</a>,
or <a href="http://media.w3.org/2010/05/sintel/trailer.ogv">Ogg</a>.</p>
</video>
</div>
</main>
<script type="text/javascript">
(function() {
function createVideoControls() {
var vids = document.getElementsByTagName('video');
for (var i = 0 ; i < vids.length ; i++) {
addControls( vids[i] );
}
}
function addControls( vid ) {
vid.removeAttribute('controls');
// vid.height = vid.videoHeight;
// vid.width = vid.videoWidth;
// vid.parentNode.style.height = vid.videoHeight + 'px';
// vid.parentNode.style.width = vid.videoWidth + 'px';
vid.removeAttribute('style')
var controls = document.createElement('div');
controls.setAttribute('class','controls');
var play = document.createElement('button');
play.setAttribute('title','Play');
play.innerHTML = '►';
controls.appendChild(play);
var speedUp = document.createElement('button');
speedUp.setAttribute('id','speedUp');
speedUp.innerHTML = 'speedUp';
controls.appendChild(speedUp);
var speedDown = document.createElement('button');
speedDown.setAttribute('id','speedDown');
speedDown.innerHTML = 'speedDown';
controls.appendChild(speedDown);
vid.parentNode.insertBefore(controls, vid);
play.onclick = function () {
if (vid.ended) {
vid.currentTime = 0;
}
if (vid.paused) {
vid.play();
} else {
vid.pause();
}
};
speedUp.addEventListener('click', function() {
vid.playbackRate += 0.2;
console.log(vid.playbackRate)
}, false);
speedDown.addEventListener('click', function() {
vid.playbackRate -= 0.2;
console.log(vid.playbackRate)
}, false);
vid.addEventListener('play', function () {
play.innerHTML = '▐▐';
play.setAttribute('paused', true);
}, false);
vid.addEventListener('pause', function () {
play.removeAttribute('paused');
play.innerHTML = '►';
}, false);
vid.addEventListener('ended', function () {
vid.pause();
}, false);
} // end of addControls
window.addEventListener('load', function() {
createVideoControls();
}
);
})()
</script>
</body>
</html>
Create a page with a form containing, at least the following: a date, a slider for a number, and a number. The slider should cover integers from -279 - +6000 °K. The number a value between 0 - 100. The date must be valid. Submit the form to http://x15.dk/hitme.php. Verify results, and iterate until ok.
I want you to test in Opera/Chrome and Firefox. Your hand in must provide screenshots of the form just before submit in both browsers, as well as the code of course.
Kenneths solution
'use strict';
const $ = function (foo) {
return document.getElementById(foo);
}
const isDate = function (date) {
return true;
}
let validate = function (e) {
let date = $('date');
var number = $('number');
if (number.value > 100 || number.value < 0){
number.focus();
e.preventDefault();
window.alert('The number must be between 0 and 100!');
return false;
} else {
return true;
}
if (!isDate(date.value)) {
date.focus();
e.preventDefault();
return false;
}
return true;
}
let dispSlide = function () {
$('ranger').innerHTML =
$('degree').value;
}
let followme = function () {
$('formal').addEventListener('submit', validate);
dispSlide();
$('degree').addEventListener('mousemove', dispSlide);
}
window.addEventListener('load', followme);<!DOCTYPE html>
<html>
<head>
<title>Assignment JS.10.1</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
td { padding: 1em .5em; }
</style>
<script src="validate.js"></script>
</head>
<body>
<h1>HTML5 Form Exercise</h1>
<form action="http://x15.dk/hitme.php" method="post" id="formal">
<table>
<tr>
<td><label for="date">Date</label></td>
<td><input type="date" id="date" name="date" required></td>
</tr>
<tr>
<td><label for="degree">Degree</label></td>
<td><input type="range" id="degree" name="degree" min="-272" max="6000">
<span id='ranger'></span></td>
</tr>
<tr>
<td><label for="number">Number between 0 and 100</label></td>
<td><input type="number" id="number" name="number" required></td>
</tr>
<tr>
<td> </td>
<td><input type="submit" value="Submit"></td>
</tr>
</table>
</form>
</body>
</html>
Find your solution to the section called “Assignment JS.Conds.0”, make a branch and do the following:
switches. Use my first suggestion
without default. Test until it works.
default at the
end. test that it works.
default up, so that it occurs
just before the case 3: clause. Now test
thoroughly, and tell me your conslusion.
'use strict';
const roll = function(n) {
return Math.floor(Math.random() * n + 1);
}
let res;
let ones = 0;
let twos = 0;
let threes = 0;
let fours = 0;
let fives = 0;
let sixes = 0;
res = roll(6);
switch (res) {
case 1:
ones++;
break;
case 2:
twos++;
break;
case 3:
threes++;
break;
case 4:
fours++;
break;
case 5:
fives++;
break;
default:
sixes++;
}
res = roll(6);
switch (res) {
case 1:
ones++;
break;
case 2:
twos++;
break;
case 3:
threes++;
break;
case 4:
fours++;
break;
case 5:
fives++;
break;
default:
sixes++;
}
res = roll(6);
switch (res) {
case 1:
ones++;
break;
case 2:
twos++;
break;
case 3:
threes++;
break;
case 4:
fours++;
break;
case 5:
fives++;
break;
default:
sixes++;
}
res = roll(6);
switch (res) {
case 1:
ones++;
break;
case 2:
twos++;
break;
case 3:
threes++;
break;
case 4:
fours++;
break;
case 5:
fives++;
break;
default:
sixes++;
}
res = roll(6);
switch (res) {
case 1:
ones++;
break;
case 2:
twos++;
break;
case 3:
threes++;
break;
case 4:
fours++;
break;
case 5:
fives++;
break;
default:
sixes++;
}
res = roll(6);
switch (res) {
case 1:
ones++;
break;
case 2:
twos++;
break;
case 3:
threes++;
break;
case 4:
fours++;
break;
case 5:
fives++;
break;
default:
sixes++;
}
res = roll(6);
switch (res) {
case 1:
ones++;
break;
case 2:
twos++;
break;
case 3:
threes++;
break;
case 4:
fours++;
break;
case 5:
fives++;
break;
default:
sixes++;
}
res = roll(6);
switch (res) {
case 1:
ones++;
break;
case 2:
twos++;
break;
case 3:
threes++;
break;
case 4:
fours++;
break;
case 5:
fives++;
break;
default:
sixes++;
}
res = roll(6);
switch (res) {
case 1:
ones++;
break;
case 2:
twos++;
break;
case 3:
threes++;
break;
case 4:
fours++;
break;
case 5:
fives++;
break;
default:
sixes++;
}
res = roll(6);
switch (res) {
case 1:
ones++;
break;
case 2:
twos++;
break;
case 3:
threes++;
break;
case 4:
fours++;
break;
case 5:
fives++;
break;
default:
sixes++;
}
console.log(`ones:\t ${ones}`);
console.log(`twos:\t ${twos}`);
console.log(`threes:\t ${threes}`);
console.log(`fours:\t ${fours}`);
console.log(`fives:\t ${fives}`);
console.log(`sixes:\t ${sixes}`);
Write a page with an HTML5 form to enter a name and a birthday. The name must be more than one character long, and the birthday must be a valid date.
The entered data must be caught by JavaScript and used to make a cookie with a name-value pair. The name must be the concatenation of name and birthday, and the value must be '42' as in 'nml251145=42'. Give the cookie a lifespan of 10 minutes. Ten minutes are 0.00694444 years! Test repeatedly until it works.
You may check the cookie content by means of the log.
Once the JavaScript works, close the browser, take 10, and then restart your browser to ascertain that the expiration mechanism works.
Important Notice: Page must be served by web server, ie by the HTTP protocol, for the cookie mechanism to work.
ppkCookieLib.js
"use strict";
function createCookie(name, value, days) {
let expires;
let samesite = "; sameSite=lax"; // nml
if (days) {
let date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
expires = "; expires=" + date.toGMTString();
}
else {
expires = "";
}
document.cookie = name + "=" + value + expires + samesite + "; path=/"; // nml
}
function readCookie(name) {
let nameEQ = name + "=";
let ca = document.cookie.split(";");
for (let i = 0; i < ca.length; i++) {
let c = ca[i];
while (c.charAt(0) == " ") {
c = c.substring(1,c.length);
}
if (c.indexOf(nameEQ) == 0) {
return c.substring(nameEQ.length, c.length);
}
}
return null;
}
function eraseCookie(name) {
createCookie(name, "", -1);
}
execution.js
'use strict';
const isValid = function(e) {
let name = document.formal.name;
let born = document.formal.born;
if (born.value === "" || name.value === "") {
window.alert("Both fields must be filled in");
name.focus();
e.preventDefault();
return false;
} else {
createCookie(name.value + born.value, 42, 0.00694444);
return true;
}
}
const getstarted = function() {
console.log(`Cookie niels1945-11-25? ${readCookie('niels1945-11-25')}`);
console.log(`Cookies: ${document.cookie}`)
document.formal.addEventListener('submit', isValid);
}
window.addEventListener('load', getstarted);
<!doctype html>
<html>
<head>
<title>NMLs Cookie Demo</title>
<meta charset='utf-8'/>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<style>
form p { font-family: monospace; font-size: 1.6em; }
</style>
<script src='../jsn/ppkCookieLib.js'></script>
<script src='./execution.js'></script>
</head>
<body>
<h1>Cookie Assignment</h1>
<form name='formal' method='post' action='http://x15.dk/hitme.php'>
<p>
Name: <input type='text' name='name' required/>
</p>
<p>
Born: <input type='date' name='born' required/>
</p>
<p>
<input type='submit' value='Go'/>
</p>
</form>
</body>
</html>
Create a JavaScript object for tunes, songs. The have titles, composers, and year as properties as well as an array of performers.
The Tune object must be used in an HTML5 page
allowing the user to enter tunes data through a form.
The entered Tune objects must be stored in an array.
The page has a div element, where the array of
tunes is displayed. Whenever the array is changed, the display
must automatically be updated.
Optional extra: Consider introducing a possibility for deleting tunes from the tunes array.
Tune.js
export class Tune {
constructor(title, composer, year) {
this.title = title;
this.composer = composer;
this.year = year;
this.performers = [];
}
addPerformer(performer) {
this.performers.push(performer);
}
toString() {
let s = '<p>';
s += this.composer + ': ';
s += '<i>' + this.title + '</i>, ';
s += this.year;
s += '</p>';
return s;
}
}
testTuneObj.js
'use strict';
import {$} from './nQuery.js';
import {Tune} from './Tune.js';
let begin = function() {
let tunes = [];
let now = new Date();
$('year').setAttribute('max', now.getFullYear());
/* the following array elements are for test purposes
* with ajax the array might come by json from server file, re ajax lesson
* with php the array may be generated on the server side from json, re REST
*/
let tune = new Tune("Mac the Knife", "Kurt Weil", 1928);
tune.addPerformer("Lotte Lenya");
tunes.push(tune);
tune = new Tune("Ode an der Freude", "Beethoven", 1824);
tune.addPerformer("Berliner");
tune.addPerformer("Wiener");
tunes.push(tune);
tune = new Tune("What a Wonderful World", "George Douglas", 1967);
tune.addPerformer("Louis Armstrong");
tunes.push(tune);
/* end of test data */
let disp = function() {
let div1 = $('tunearea');
while (div1.firstChild) { // Removing all children from an element
div1.removeChild(div1.firstChild);
}
for (let tune of tunes) {
div1.innerHTML += tune.toString();
}
};
disp();
$('butt').addEventListener('click', function() {
let cmp = $('cmp').value;
let title = $('title').value;
let year = $('year').value;
let perf = $('perf').value;
if (cmp !== '' && title !== '' && perf !== '') {
let tune = new Tune(title, cmp, year);
tune.addPerformer(perf);
tunes.push(tune);
disp();
$('cmp').value = '';
$('title').value = '';
$('perf').value = '';
}
}
);
}
window.addEventListener('load', begin);
testTuneObj.html
<!doctype html>
<html>
<head>
<meta charset="utf-8"/>
<title>Object-oriented JavaScript example</title>
<script type='module' src='./testTuneObj.js'></script>
<style>
div {
float: left;
height: 500px;
margin: 1em;
outline: 1px solid blue;
padding: 1em;
width: 40%;
}
</style>
</head>
<body>
<h1>Tunes</h1>
<div id='left'>
<h2>Entry form</h2>
<p>
<label for='title'>Title:</label><br/>
<input type='text' id='title' required/>
</p>
<p>
<label for='cmp'>Composer:</label><br/>
<input type='text' id='cmp' required/>
</p>
<p>
<label for='year'>Year:</label><br/>
<input type='number' id='year' min='1970' value='1999' required/>
</p>
<p>
<label for='perf'>Singer:</label><br/>
<input type='text' id='perf' required/>
</p>
<p>
</p>
<p>
<button id='butt'>Enter</button>
</p>
</div>
<div id='right'>
<h2>List of Tunes</h2>
<div id='tunearea'></div>
</div>
</body>
</html>
Write a Planet class.
Use it to create ten planets storing planetary information.
You may find the info on:
http://www.opencourse.info/astronomy/introduction/05.motion_planets/#sidereal%20period
and
http://www.opencourse.info/astronomy/introduction/05.motion_planets/#aphelion
.
You don't need more than the sample output suggests.
Treat the Sun as the first planet, with all values set to zero.
Write a web information page with a form that allows the user
to choose a planet
via a radio button. Create a change event with
a handler that writes the planet's information on the screen.
Sample output for Jupiter:
Distance = 5.2028 AU
Sidereal Period = 11.862 years
Synodic Period = 398.9 days
Eccentricity = 0.048
Orbital Inclination = 1.31°
planets.js
'use strict';
/*
* array of planets
* ie an array of planet objects
*/
export const planets = [
{
name: "Sun",
distance: 0,
siderialP: 0,
synodicP: 0,
eccentricity: 0,
incline: 0
},
{
name: "Mercury",
distance: 0.3871,
siderialP: 0.2408,
synodicP: 115.88,
eccentricity: 0.206,
incline: 7.0
},
{
name: "Venus",
distance: 0.7233,
siderialP: 0.6152,
synodicP: 583.92,
eccentricity: 0.007,
incline: 3.39
},
{
name: "Earth",
distance: 1,
siderialP: 1.0,
synodicP: 0,
eccentricity: 0.017,
incline: 0
},
{
name: "Mars",
distance: 1.5237,
siderialP: 1.8809,
synodicP: 779.94,
eccentricity: 0.093,
incline: 1.85
},
{
name: "Jupiter",
distance: 5.2028,
siderialP: 11.862,
synodicP: 398.9,
eccentricity: 0.048,
incline: 1.31
},
{
name: "Saturn",
distance: 9.5388,
siderialP: 29.458,
synodicP: 378.1,
eccentricity: 0.056,
incline: 2.49
},
{
name: "Uranus",
distance: 19.1914,
siderialP: 84.01,
synodicP: 369.7,
eccentricity: 0.046,
incline: 0.77
},
{
name: "Neptune",
distance: 30.0611,
siderialP: 164.79,
synodicP: 367.5,
eccentricity: 0.010,
incline: 1.77
},
{
name: "Pluto",
distance: 39.5294,
siderialP: 248.5,
synodicP: 366.7,
eccentricity: 0.248,
incline: 17.15
}
];
obj41M.js
'use strict';
import {planets} from './planets.js';
const $ = function(foo) {
return document.getElementById(foo);
}
/*
* Handler for radio buttons
*/
const dowhatever = function(e) {
// først clear
for (let planet of planets) {
if (planet.name === e.target.id) {
$('output').innerHTML = planet.toString();
break;
}
}
}
/*
* Here we have objects with data
* they have no methods so
* on load we create and assign several methods to the objects
* defined in the array of planets
* this method will be common, ie exist once for all objects
* in planets
*/
const init = function() {
const getName = function() { return this.name; }
const getDistance = function() { return this.distance; }
const getSid = function() { return this.siderialP; }
const getSyn = function() { return this.synodicP; }
const getEcc = function() { return this.eccentricity; }
const getInc = function() { return this.incline; }
const toString = function() {
return '<h3>' + this.getName() + '</h3>' +
'<p>' +
'Distance = ' + this.getDistance() + ' AU<br/>' +
'Siderial Period = ' + this.getSiderialP() + ' years<br/>' +
'Synodic Period = ' + this.getSynodicP() + ' days<br/>' +
'Eccentricity = ' + this.getEccentricity() + '<br/>' +
'Incline = ' + this.getIncline() + '°'
'</p>';
}
const toRadio = function() {
return '<input type="radio" name="planet" id="'
+ this.getName() + '"/>' + this.getName() + '<br/>';
}
/* attach methods to each object */
for (let planet of planets) {
planet.getName = getName;
planet.getDistance = getDistance;
planet.getSiderialP = getSid;
planet.getSynodicP = getSyn;
planet.getEccentricity = getEcc;
planet.getIncline = getInc;
planet.toString = toString;
planet.toRadio = toRadio;
}
/* print radio buttons in form */
$('theradio').innerHTML = "";
for (let planet of planets) {
$('theradio').innerHTML += planet.toRadio();
}
/*
* handler for radio buttons
* invoked as change event on whole form
* no buttons required
*/
$('formid').addEventListener('change', dowhatever);
} // end of init
window.addEventListener('load', init);
obj41M.html
<!doctype html>
<html>
<head>
<meta charset='utf-8'/>
<title>Obj.4.2</title>
<style>
form {
font-family: monospace;
font-size: 1.2em;
}
#output {
background-color: silver;
font-size: 1.4em;
min-height: 2em;
outline: 1px solid black;
padding: .5em;
width: 20em;
}
</style>
<script type='module' src='./obj41M.js'></script>
</head>
<body>
<h1>Obj.4.2 Planets</h1>
<form id='formid' action='#' method='post'>
<p id='theradio'></p>
</form>
<section id='output'></section>
</body>
</html>
Write an HTML5 page with a form for entering credit card information. On submitting the form the content must be validated. For this purpose you must create a credit card object holding the following:
true or
false.
Correct information should be sent to
http://x15.dk/hitme.php.
Incorrect should not be submitted but return an appropriate
error message asking the user for correction.
You may refer to https://www.codeproject.com/tips/253704/test-credit-card-account-numbers for numbers suitable for testing.
The checking mechanism is know as the
Luhn algorithm[20]
also known as the "modulus 10" or
"mod 10" algorithm.
Your validity checking method must
implement the following formulation of the algorithm using
an exemplary number 7992739871x
67 + x.
3 as the last digit
would make a valid number.
'use strict';
class CreditCard {
constructor(ccno, expdate, name, cvv) {
this.ccnumber = ccno;
//...
}
isValid() {
// code for checking
// return false if invalid
// else return true
return true;
}
}
const validate = function(e) {
let ccnumber = document.getElementById('ccno');
let expdate = document.getElementById('exp').value;
// more values from form
let cc = new CreditCard(ccnumber.value, expdate, 'Niels', '666');
if (!cc.isValid()) {
ccnumber.focus();
e.preventDefault();
return false;
} /* if (! other tests)
} */ else {
return true;
}
}
const init = function() {
document.getElementById('formid').addEventListener('submit', validate);
}
window.addEventListener('load', init);obj4Module.js
'use strict';
export const $ = function(foo) {
return document.getElementById(foo);
}
export class CreditCard {
constructor(ccno, expdate, name, cvv) {
this.ccnumber = ccno;
this.expdate = expdate;
}
isValid() {
let s = this.ccnumber;
let a = [];
let sum = 0;
for (let i = 0; i < s.length; i++) { // CCNO to array
a[i] = Number(s.slice(i, i+1));
}
for (let i = a.length - 2; i >= 0; i -= 2) { // backw mul by 2
a[i] *= 2;
}
for (let i = 0; i < a.length; i++) { // sum of all digits
let n = a[i];
if (n > 9) { // phrasing of the algo
n -= 9;
}
sum += n;
}
return !(sum % 10) // zero is valid mod 10, but zero is false, hence !
}
isExpDate() {
let now = new Date();
let a = this.expdate.split("/");
let norm = Number(a[1] * 100) + Number(a[0]);
now = now.getFullYear() % 100 * 100 + now.getMonth() + 1;
if (norm >= now) {
return true;
} else {
return false;
}
}
}
obj4M.js
'use strict';
import {$, CreditCard} from './obj4Module.js';
const validate = function(e) {
let ccnumber = $('ccno');
let expdate = $('exp');
let cc = new CreditCard(ccnumber.value, expdate.value, 'Niels', '666');
if (!cc.isValid()) {
ccnumber.focus();
e.preventDefault();
$('errmsg').innerHTML = 'Erroneous CreditCard Number';
return false;
} else if (!cc.isExpDate()) {
exp.focus();
e.preventDefault();
$('errmsg').innerHTML = 'Erroneous Expiration Date';
return false;
} else {
return true;
}
}
const init = function() {
$('formid').addEventListener('submit', validate);
}
window.addEventListener('load', init);
obj4M.html
<!doctype html>
<html>
<head>
<meta charset='utf-8'/>
<title>Obj.4.2</title>
<style>
form {
font-family: monospace;
font-size: 1.2em;
}
#errmsg {
color: red;
font-weight: 900;
}
</style>
<script type='module' src='./obj4M.js'></script>
</head>
<body>
<h1>Obj.4.2 Credit Card Numbers</h1>
<p id='errmsg'></p>
<form id='formid' action='http://x15.dk/hitme.php' method='post'>
<p>CCNo: <input type='text' name='ccno' id='ccno'/></p>
<p> Exp: <input type='text' name='exp' id='exp'/></p>
<p> <input type='submit' value='go'/></p>
</form>
</body>
</html>
In the beginning were the natural numbers, ℕ, they are the numbers used for counting. Later we got what is today know as the integers, ℤ, by adding zero, 0, and the negative numbers. Later again we got the fractions, in mathematical speak the rational numbers ℚ, and all was good.
The rational numbers are the integers plus the fractions. Fractions are represented as the ratio between two integers. As an example, 3/7 is a rational number. The 3 is called the numerator. The 7 is called the denominator. Integers are fractions with a denominator of 1.
In this assignment you are going to create an object for rational numbers, and several methods for doing calculations with them. You see, some of us love the rational numbers because they are beautiful and exact. The real numbers ℝ, the numbers with decimals, are approximations.
Rational.
It must have two properties, numerator, and
denominator.
The creating code must
give values to these two properties.
0/1.
toString() that will present
the fraction as the string "3/7" for example.
If the fraction is an integer it should be presented as
a string with only the numerator, ie without the
"/1".
negate which will reverse the
sign of the fraction from minus to plus, or vice versa.
invert which will invert the
fraction by swapping the numerator and the denominator.
This is sometimes the reciprocal value of the fraction.
toFloat. It must return the
value of the fraction as a floating point number with
decimals, as approximate asd they may be.
reduce. It must reduce the
fraction as much as possible. The calculation is done by
dividing the numerator and the denominator with their
greatest common denominator, the
biggest number that divides both. I shall provide you
with a function gcd(n, d) that will
return this number given two integers as input.
add, sub,
mul, and div that will
add, subtract, multiply, and divide two fractions that
are both represented as Rational objects. The calculations
must always end with reducing the resulting fractions.
/**
* The world's oldest non trivial algorithm:
* Euclid's Elements, Book 7, ca. 300 BC.
* Based on
* if r = the remainder from the division a/b,
* then a og b's commom divisors are the same as b's and r's.
* This means that gcd(a,b) = gcd(b,r)
*
* By doing this continuously we get:
* gcd(36,20) = gcd(20,16) = gcd(16,4) = gcd(4,0)
* It is possible to prove that we will end with a pair
* where the second number is 0. When that happens
* the first number of the pair equals their gcd.
*
* This is the quintessential example of recursive function programming!
*/
/**
* Euclid's algorithm
*
* calling sequence
* let n = parseInt(prompt('Give me an integer:'));
* let d = parseInt(prompt('Give me an integer:'));
* n = Number(n);
* d = Number(d);
* gcd(n, d);
*/
let gcd = function (a, b) {
if (b == 0) {
return a;
} else {
return gcd(b, a % b);
}
}
Rational.js
'use strict';
import {MyMath} from './MyMath.js';
export class Rational {
constructor(n, d) {
this.numerator = n ? Number(n) : 0;
this.denominator = d ? Number(d) : 1;
this.reduce();
}
toString() {
let s = '';
if (this.numerator * this.denominator < 0) {
s = '-';
}
s += Math.abs(this.numerator);
if (Math.abs(this.denominator) === 1) {
return s;
} else if (this.numerator === 0) {
return this.numerator;
} else {
return s + '/' + Math.abs(this.denominator);
}
}
reduce() {
let g = MyMath.gcd(this.numerator, this.denominator);
this.numerator /= g;
this.denominator /= g;
return;
}
invert() {
let t = new Rational(this.denominator, this.numerator);
return t;
}
negate() {
let t = new Rational(-this.numerator, this.denominator);
return t;
}
toFloat() {
return this.numerator / this.denominator;
}
add(oq) {
let nq = new Rational(this.numerator * oq.denominator + oq.numerator * this.denominator, this.denominator * oq.denominator);
nq.reduce();
return nq;
}
sub(oq) {
return this.add(oq.negate());
}
mul(oq) {
let nq = new Rational(this.numerator * oq.numerator, this.denominator * oq.denominator);
nq.reduce();
return nq;
}
div(oq) {
return this.mul(oq.invert());
}
}
testRational.js
'use strict';
import {Rational} from './Rational.js';
import {$} from './nQuery.js';
let str2frac = function(s) {
let arr = s.value.split('/');
let obj = new Rational(Number(arr[0]), Number(arr[1]));
return obj;
}
let calc = function(ev) {
let f1 = str2frac($('f1'));
let f2 = str2frac($('f2'));
switch(ev.target.id) {
case 'plus': f1 = f1.add(f2);
break;
case 'minus': f1 = f1.sub(f2);
break;
case 'mul': f1 = f1.mul(f2);
break;
case 'div': f1 = f1.div(f2);
}
$('f1').value = f1.toString();
$('f2').value = '';
$('f2').focus();
}
let begin = function() {
$('plus').addEventListener('click', calc);
$('minus').addEventListener('click', calc);
$('mul').addEventListener('click', calc);
$('div').addEventListener('click', calc);
}
window.addEventListener('load', begin);
testRational.html
<!doctype html>
<html>
<head>
<meta charset="utf-8"/>
<title>Object-oriented JavaScript example</title>
<link rel='stylesheet' href='style.css'/>
<script type='module' src='testRational.js'></script>
</head>
<body>
<table>
<tr>
<td><label for="jscode">Enter fraction:</label></td>
<td> </td>
<td><label for="jscode">Enter fraction:</label></td>
</tr>
<tr>
<td><input type="text" id="f1"/></td>
<td>
<button id='plus'>+</button><br/>
<button id='minus'>-</button><br/>
<button id='mul'>*</button><br/>
<button id='div'>/</button>
</td>
<td><input type="text" id="f2"/></td>
</tr>
</table>
<p></p>
</body>
</html>
Please refer to code in Example 11.2. Now alter the drawing of the polygon in such a way that you strike all three sides with the context method lineTo. Use a line width of 10.
Hand in an HTML5 as well as a JavaScript file. HTML5 must validate. JavaScript must be validated without errors on jslint.com, or jshint.org.
Please refer to code in Example 11.2.
Now alter the drawing of the polygon in such a way that
you close the region of the polygon
with the context method closePath. Use a line width of 10.
Hand in an HTML5 as well as a JavaScript file. HTML5 must validate. JavaScript must be validated without errors on jslint.com, or jshint.com.
/*globals document, window */
'use strict';
/*
* assignment 0 solution
*
* function drawing a polygon
*/
var poly35 = function () {
var canvas = document.getElementById('myCanvas35');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
ctx.beginPath(); // new path for polygon
ctx.moveTo(50, 200); // goto coordinate in canvas
ctx.lineTo(150, 50); // line to coordinate
ctx.lineTo(180, 150); // another line to coord
ctx.lineTo(50, 200); // connect to start of polygon
ctx.fillStyle = 'silver';
ctx.strokeStyle = 'black';
ctx.lineWidth = 40;
ctx.fill(); // fills poly
ctx.stroke(); // draws lines
}
}
/*
* assignment 1 solution
* function drawing a polygon
*/
var poly36 = function () {
var canvas = document.getElementById('myCanvas36');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
ctx.beginPath(); // new path for polygon
ctx.moveTo(50, 200); // goto coordinate in canvas
ctx.lineTo(150, 50); // line to coordinate
ctx.lineTo(180, 150); // another line to coord
ctx.closePath(); // close path to start of polygon
ctx.fillStyle = 'silver';
ctx.strokeStyle = 'black';
ctx.lineWidth = 10;
ctx.fill(); // fills poly
ctx.stroke(); // draws lines
}
}
var init = function () {
poly35();
poly36();
}
window.addEventListener('load', init);
<!doctype html>
<html language="en">
<head>
<meta charset="utf-8"/>
<title>Canvas Example II</title>
<script src="jsCan1.js"></script>
</head>
<body>
<h1>Canvas Example II, Solution 0 and 1</h1>
<p>
Polygon assignment 0.
</p>
<canvas id="myCanvas35" width="300" height="300" style="outline: 1px solid blue;">
<p>Powered by &html;5 canvas if only</p>
</canvas>
<p>
Polygon assignment 1.
</p>
<canvas id="myCanvas36" width="300" height="300" style="outline: 1px solid red;">
<p>Powered by &html;5 canvas if only</p>
</canvas>
</body>
</html>
Create a webpage. In the right hand side of the webpage you must create a 'toolbox' canvas with four rectangles of different sizes, and a half circle. They represent the standard shapes in the toolbox.
In addition you must create another, separate canvas on the page. Let us call it the room. The size of that canvas must be with user entered width and height. Please let it's outline be visible.
I expect an html file, a css file, and one or more js files to make up the solution.
Hint for beginners:
You may prefer to work with embedded JavaScript while you
test your code. Once it works as desired, separate the JavaScript into an
individual .js file, test again, then hand in your
solution.
With the webpage created in the previous assignment you must create an event such that you may click on a toolbox shape to select it. Then you must be able to click in the other canvas so that the standard shape will be drawn there.
The shapes must be kept at a minimum distance from the walls of the room.
This assignment should be solved by adding code to the JavaScript code file(s) made in the previous assignment.
nmlCanvas80.html
<!doctype html>
<html language="en">
<!-- nmlCanvas80.html -->
<head>
<meta charset="utf-8"/>
<title>Canvas Experiment LXXX</title>
<style>
canvas {
margin-left: 10px;
outline: 1px solid magenta;
}
</style>
<script type='module' src="./nmlCanvas80.js"></script>
</head>
<body>
<h1>Canvas Experiment LXXX</h1>
<p>
Select shapes from right canvas and reproduce them in the
left canvas where the mouse is clicked.
</p>
<canvas id="myCanvas2" width="400" height="400">
<p>Powered by &html;5 canvas</p>
</canvas>
<canvas id="myCanvas1" width="400" height="400">
<p>Powered by &html;5 canvas</p>
</canvas>
</body>
</html>
nmlCanvas80.js
'use strict';
import {Canvas} from './nmlCanvas.js';
import {Shape} from './nmlShape.js';
/*
* nmlCanvas80.js
*/
export const initialize = function () {
/*
* create two canvases and put two shapes into the right one
* via an array
*/
mycv1 = new Canvas('myCanvas1', 'transparent');
mycv1.canvas.addEventListener('click', select);
mycv2 = new Canvas('myCanvas2', 'transparent');
let shape1 = new Shape(mycv1, 20, 10, 120, 40, 'blue');
let shape2 = new Shape(mycv1, 200, 100, 80, 60, 'green');
shapes.push(shape1);
shapes.push(shape2);
repeater(mycv1, shapes);
}
const redraw = function (cv, arr) {
/* clear and redraw canvas from an array */
cv.clear();
cv.prep();
for (let shape of arr) {
shape.draw();
}
}
const repeater = function (cv, arr) {
/* if this is an animation build a setInterval loop here
* if not, just draw
*/
redraw(cv, arr);
}
const select = function (ev) {
for (let shape of shapes) {
let cx = shape.ctx;
cx.beginPath();
cx.rect(shape.x, shape.y, shape.width, shape.height);
cx.closePath();
let bb = this.getBoundingClientRect(); // get canvas as std obj
// convert mouse coordinates to canvas coordinates
let x = (ev.clientX - bb.left) * (this.width / bb.width);
let y = (ev.clientY - bb.top) * (this.height / bb.height);
if (cx.isPointInPath(x, y)) {
console.log('hit');
// we're in a loop, is this array element the
// one we clicked? If yes click in other canvas
mycv2.canvas.addEventListener('click', function placeInRoom(e) {
console.log('place');
let bb1 = this.getBoundingClientRect(); // yes
// other canvas as std object
// convert mouse coordinates to canvas coordinates
let x1 = (e.clientX - bb1.left) * (this.width / bb1.width);
let y1 = (e.clientY - bb1.top) * (this.height / bb1.height);
let obj = new Shape(mycv2, x1, y1,
shape.width, shape.height,
shape.color);
othershapes.push(obj);
console.log(othershapes);
mycv1.canvas.removeEventListener('click', select);
repeater(mycv2, othershapes);
mycv2.canvas.removeEventListener('click', placeInRoom);
mycv1.canvas.addEventListener('click', select);
});
} else {
// window.alert("nohit: "+x+","+y);
}
}
}
let mycv1;
let mycv2;
let shapes = [];
let othershapes = [];
window.addEventListener('load', initialize);
nmlCanvas.js
import {$} from './nQuery.js';
/**
* Canvas object
*/
export class Canvas {
constructor(canvasId, color) {
this.canvas = $(canvasId);
this.context = this.canvas.getContext("2d");
this.color = color;
this.prep();
}
prep() {
this.context.fillStyle = this.color;
this.context.fillRect(0, 0, this.canvas.width, this.canvas.height);
}
clear() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
getContext() {
return this.context;
}
getHeight() {
return this.canvas.height;
}
getWidth() {
return this.canvas.width;
}
};
nmlShape.js
'use strict';
/**
* Shape object, simple
*/
export class Shape {
constructor(cv, x, y, width, height, color) {
this.ctx = cv.context;
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.color = color;
}
draw() {
this.ctx.fillStyle = this.color;
this.ctx.fillRect(this.x, this.y, this.width, this.height);
}
};
With the result of the previous assignment you must improve the placing of the shapes such that in addition to the minimum distance from the walls, the shapes may touch, but not overlap each other.
Again, this assignment should be solved by adding code to the JavaScript code files resulting from the previous assignment.
Shape.isOverlapping(obj) method
as part of the Shape class.
Internally this refers to the
current object. The parameter obj
must refer to the object with which we test for
overlap. The method must return true
if there's an overlap, otherwise it must result
false.
myCanvas0. Show it to your
prof.
fillStyle = 'silver'. Show it to your
prof.
Play!
button such that when you click it, the code
rolls the die; wipes the canvas; and redraws the
canvas with the die reflecting its new value.
lock to a die when you click
it. If locked, the die does not change its
value when you click Play!
If you click a locked die, it must be released.
index.html
<!doctype html>
<html>
<head>
<title>Assignment 5.0</title>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<link rel='stylesheet' href='./css/index.css'/>
<script type='module' src='./js/index.js'></script>
</head>
<body>
<header>
<h1>Canvas Dice</h1>
</header>
<main id='main'>
<section id='divr'></div>
<section id='divl'></div>
</main>
</body>
</html>
nmlCanvas.js
import {$} from './nQuery.js';
/**
* Canvas object
*/
export class Canvas {
constructor(canvasId, color) {
this.canvas = $(canvasId);
this.context = this.canvas.getContext("2d");
this.color = color;
this.prep();
}
prep() {
this.context.fillStyle = this.color;
this.context.fillRect(0, 0, this.canvas.width, this.canvas.height);
}
clear() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
getContext() {
return this.context;
}
getHeight() {
return this.canvas.height;
}
getWidth() {
return this.canvas.width;
}
};
nDie.js
/**
* Die object
*/
export class Die {
constructor(cv, x, y, width, height, color) {
this.ctx = cv.getContext();
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.color = color;
this.locked = false;
this.value = 0;
this.roll();
}
draw() {
this.ctx.clearRect(this.x, this.y, this.width, this.height);
this.ctx.beginPath();
this.ctx.fillStyle = this.color;
this.ctx.rect(this.x, this.y, this.width, this.height);
if (this.locked) {
this.ctx.fillStyle = "yellow";
this.ctx.strokeStyle = "black";
this.ctx.lineWidth = 2;
this.ctx.stroke();
}
this.ctx.fill();
this.ctx.closePath();
this.drawFace();
}
drawFace() {
var offset = 12;
var r = 5;
this.ctx.fillStyle = 'black';
if (this.value % 2 === 1) {
this.ctx.beginPath();
this.ctx.arc(this.x + this.width / 2, this.y + this.height / 2,
r, 0, Math.PI * 2, true);
this.ctx.fill();
this.ctx.closePath();
}
if (this.value > 1) {
this.ctx.beginPath();
this.ctx.arc(this.x + this.width - offset, this.y + offset,
r, 0, Math.PI * 2, true);
this.ctx.arc(this.x + offset, this.y + this.height - offset,
r, 0, Math.PI * 2, true);
this.ctx.fill();
this.ctx.closePath();
}
if (this.value >= 4) {
this.ctx.beginPath();
this.ctx.arc(this.x + offset, this.y + offset,
r, 0, Math.PI * 2, true);
this.ctx.arc(this.x + this.width - offset, this.y + this.height - offset,
r, 0, Math.PI * 2, true);
this.ctx.fill();
this.ctx.closePath();
}
if (this.value === 6) {
this.ctx.beginPath();
this.ctx.arc(this.x + offset, this.y + this.height / 2,
r, 0, Math.PI * 2, true);
this.ctx.arc(this.x + this.width - offset, this.y + this.height / 2,
r, 0, Math.PI * 2, true);
this.ctx.fill();
this.ctx.closePath();
}
}
move(dx, dy) {
this.x += dx;
this.y += dy;
}
roll() {
let e = Math.floor(Math.random() * 6 ) + 1;
this.value = e;
}
lockUnlock() {
this.locked = this.locked ? false : true;
}
};
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);
}
Today we, you shall write a tic-tac-toe game. The game is also known as naughts and crosses.
Take a look at this page: Click here :)
And then consider
The playing ground, the board, is a 3x3 matrix. The obvious choice will be to map the board into an array. You have two choices. A one dimensional array such as
[0, 1, 2, 3, 4, 5, 6, 7, 8]
which you may decide to look at as
[0, 1, 2
3, 4, 5
6, 7, 8]
is definitely simpler. You may also choose
[ [0, 1, 2],
[0, 1, 2],
[0, 1, 2] ]
Either way, looping through the board to check
for points will be finding three rows, three columns,
two diagonals, and counting points in them. Associating
a 4 with an X, and a 1 with an O, a play
means placing an X or an O on the screen, and a 4, or a 1 in the array.
We need the following functionality:
Write the handlers, functions, and create the proper event listeners to activate them.
Test and repeat until it works.
index.html
<!doctype html>
<html>
<head>
<meta charset='utf-8'/>
<meta name='viewport' content='width=device-width, initial-scale=1.0'/>
<title>TicTacToe NOO</title>
<link href='./css/index.css' rel='stylesheet'/>
<script src='./js/nQuery.js'></script>
<script src='./js/tictactoe.js'></script>
</head>
<body>
<header id='head'></header>
<div id='ttt'></div>
<footer id='foot'></footer>
</body>
</html>
tictactoe.js
'use strict';
const SIZE = 58;
const DIM = 3;
const STRATEGY = [4, 0, 2, 6, 8, 1, 3, 5, 7];
let foot;
let head;
let node;
let squares = [];
/*
* Check rows, columns, and diagonals
* for a winning situation
* n is the winning score
* if n == 12 human wins
* if n == 3 program wins
*/
const check = function (n) {
console.log(`check, squares = ${squares}`)
for (let i = 0; i < 7; i += 3) { // check rows
let sum = squares[i] + squares [i + 1] + squares[i + 2];
if (sum === n) {
return true;
}
}
for (let i = 0; i < 3; ++i) { // check columns
let sum = squares[i] + squares [i + 3] + squares[i + 6];
if (sum === n) {
return true;
}
}
let sum = squares[0] + squares[4] + squares[8]; // check diag \
if (sum === n) {
return true;
}
sum = squares[2] + squares[4] + squares[6]; // check diag /
if (sum === n) {
return true;
}
return false;
};
/*
* Check for blocking, winning, or optimal move
* if a row, column, or diagonal has
* an 8, play to block
* a 2, play to win
* else find optimal move in STRATEGY
*/
const whereToPlay = function() {
for (let i = 0; i < 7; i += 3) { // check rows
let sum = squares[i] + squares [i + 1] + squares[i + 2];
if (sum === 8 || sum === 2) {
for (let j = 0; j < 3; ++j) {
if (squares[i + j] === 0)
return i + j;
}
}
}
for (let i = 0; i < 3; ++i) { // check columns
let sum = squares[i] + squares [i + 3] + squares[i + 6];
if (sum === 8 || sum === 2) {
for (let j = 0; j < 7; j += 3) {
if (squares[i + j] === 0)
return i + j;
}
}
}
let sum = squares[0] + squares[4] + squares[8]; // check diag \
if (sum === 8 || sum === 2) {
for (let i = 0; i < 9; i += 4) {
if (squares[i] === 0)
return i;
}
}
sum = squares[2] + squares[4] + squares[6]; // check diag /
if (sum === 8 || sum === 2) {
for (let i = 0; i < 7; i += 2) {
if (squares[i] === 0)
return i;
}
}
for (let i = 0; i < DIM * DIM; ++i) {
let j = STRATEGY[i];
if (squares[j] === 0)
return j;
}
};
/*
* Computer plays after human move
* function whereToPlay decides where
*/
const playO = function () {
let i = whereToPlay();
if (squares[i] === 0) {
$('ij'+i).removeEventListener('click', play);
let cx = $('ij'+i).getContext('2d');
cx.lineWidth = 5;
cx.strokeStyle = 'red'
cx.arc(SIZE/2, SIZE/2, SIZE/2 - cx.lineWidth/2, 0, Math.PI * 2, false);
cx.stroke();
squares[i] = 1;
}
if (check(3)) { // score the x
$('feedback').innerHTML = 'I win!'; // and go check
freeze();
}
// dont call play for human to play.
// It operates on click
};
/*
* Human plays by click event
* if no win pass to computer
*/
const play = function (e) {
$(e.target.id).removeEventListener('click', play);
let cx = $(e.target.id).getContext('2d'); // draw an x
cx.lineWidth = 5;
cx.strokeStyle = 'blue'
cx.moveTo(0, 0);
cx.lineTo(SIZE, SIZE);
cx.moveTo(SIZE, 0);
cx.lineTo(0, SIZE);
cx.stroke();
let i = e.target.id.charAt(2);
squares[i] = 4;
if (check(12)) { // score the x
$('feedback').innerHTML = 'Human wins!'; // and go check
freeze();
} else {
playO();
}
};
/*
* Remove eventlisteners if game is over
*/
const freeze = function () {
for (let i = 0; i < DIM * DIM; ++i) {
$('ij' + i).removeEventListener('click', play);
}
};
const wipeHTML = function (elm) {
let dombranch = $(elm);
while (dombranch.firstChild) {
dombranch.removeChild(dombranch.firstChild);
}
};
const initLogics = function () {
for (let i = 0; i < DIM * DIM; i++) {
squares[i] = 0;
}
return;
};
const setupPage = function () {
node = $('ttt');
head = $('head');
foot = $('foot');
// create board
let h1 = document.createElement('h1');
let h1t = document.createTextNode('TicTacToe');
h1.appendChild(h1t);
head.appendChild(h1);
let k = 0;
for (let i = 0; i < DIM; ++i) {
for (let j = 0; j < DIM; ++j) {
let sq = document.createElement('canvas');
sq.setAttribute('width', SIZE);
sq.setAttribute('height', SIZE);
sq.setAttribute('id', 'ij' + k++);
sq.addEventListener('click', play);
node.appendChild(sq);
}
}
let p = document.createElement('p');
p.setAttribute('id', 'feedback');
foot.appendChild(p);
p = document.createElement('p');
let butt = document.createElement('button');
butt.setAttribute('type', 'button');
let t = document.createTextNode('Reset/New Game!');
butt.appendChild(t);
p.appendChild(butt);
foot.appendChild(p);
butt.addEventListener('click', restart);
};
const restart = function () {
wipeHTML('head');
wipeHTML('ttt');
wipeHTML('foot');
initLogics();
setupPage();
};
window.addEventListener('load', restart);
On the basis of the code from today's lesson please place 10 or more moving disks on a 500 x 600 canvas. They must all move linearly and bounce when hitting the wall. They must have different colors, and different sizes. Their trajectories and their speeds must be randomized.
Hand in as jsanimN0.js, and jsanimN0.html
nmlUmo0.js
'use strict';
/**
* Umo object, version 0.9.1
*/
export class Umo {
constructor(canvas, color) {
this.canvas = canvas;
this.r = Math.random() * 9 + 3;
this.x = Math.random() * (this.canvas.getWidth() - this.r - 2);
this.y = Math.random() * (this.canvas.getHeight() - this.r - 2);
this.dx = Math.random() * 3;
this.dy = Math.random() * 3;
this.color = color;
}
draw() {
this.canvas.getContext().beginPath();
this.canvas.getContext().strokeStyle = '#222';
this.canvas.getContext().fillStyle = this.color;
this.canvas.getContext().arc(this.x, this.y, this.r,
0, Math.PI * 2,
false);
this.canvas.getContext().fill();
this.canvas.getContext().stroke();
this.canvas.getContext().closePath();
}
move() {
if (this.x + this.dx + this.r > this.canvas.getWidth()
|| this.x + this.dx - this.r < 0)
this.dx = -this.dx;
if (this.y + this.dy + this.r > this.canvas.getHeight()
|| this.y + this.dy - this.r < 0)
this.dy = -this.dy;
this.x += this.dx;
this.y += this.dy;
}
toString() {
s = '';
s += this.x + ':' + this.y + ', ' + this.r + " \n " + this.color;
return s;
}
};
jsanimN0.html
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>Canvas Animation of at Least 10 Objects</title>
<script type='module'>
import {Canvas} from './nmlCanvas.js';
import {Umo} from './nmlUmo0.js';
import {randomColor, animate} from './nQuery.js';
const initialize = function () {
canvas = new Canvas('canvas', '#ffff88');
for (let i = 0; i < COUNT; i += 1) {
let bubble = new Umo(canvas, randomColor());
bubbles.push(bubble);
}
animate(canvas, bubbles, null, 25);
}
let bubbles = [];
let canvas;
let COUNT = 3;
window.addEventListener('load', initialize);
</script>
</head>
<body>
<h1><code>jsanimN0.html</code></h1>
<section>
<canvas id='canvas' width='500' height='600'>
If you see this text, your browser is very old.
</canvas>
</section>
</body>
</html>
On the basis of the code from today's lesson please place 10 or more moving disks on a 500 x 600 canvas. They must all move linearly and bounce when hitting the wall. They must have different colors, and different sizes. Their trajectories and their speeds must be randomized.
The above is equivalent to the previous assignment. Now you must change the coding, so that when a moving disk hits another disk, the bigger disk swallows the the smaller disk, and its area grows with the area of the swallowed disk. When there is but one disk left, the animation must stop, and an appropriate message must appear.
Hand in as jsanimN1.js, and jsanimN1.html
nmlUmo1.js
'use strict';
import {roll} from './nQuery.js';
/**
* Umo object, version 1.0 with hittest
*/
export class Umo {
constructor(canvas, color, id) {
this.canvas = canvas;
this.r = roll(15, 3);
this.x = roll(this.canvas.getWidth() - 2 * this.r, this.r);
this.y = roll(this.canvas.getHeight() - 2 * this.r, this.r);
this.dx = roll(2, 2);
this.dy = roll(2, 2);
this.color = color;
this.id = id;
}
draw() {
this.canvas.getContext().beginPath();
this.canvas.getContext().strokeStyle = '#222';
this.canvas.getContext().fillStyle = this.color;
this.canvas.getContext().arc(this.x, this.y, this.r,
0, Math.PI * 2,
false);
this.canvas.getContext().fill();
this.canvas.getContext().stroke();
this.canvas.getContext().strokeText(this.id, this.x -3, this.y+3);
this.canvas.getContext().closePath();
}
move() {
if (this.x + this.dx + this.r > this.canvas.getWidth()
|| this.x + this.dx - this.r < 0)
this.dx = -this.dx;
if (this.y + this.dy + this.r > this.canvas.getHeight()
|| this.y + this.dy - this.r < 0)
this.dy = -this.dy;
this.x += this.dx;
this.y += this.dy;
}
getArea() {
return Math.PI * Math.pow(this.r, 2);
}
hittest(ob) {
return Math.sqrt(Math.pow(this.x - ob.x, 2) + Math.pow(this.y - ob.y, 2)) <= (this.r + ob.r)
}
toString() {
let s = '';
s += this.x + ':' + this.y + ', ' + this.r + " \n " + this.color;
return s;
}
};
jsanimN1.html
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>Canvas Animation of at Least 10 Objects</title>
<script type='module'>
import {Canvas} from './nmlCanvas.js';
import {Umo} from './nmlUmo1.js';
import {randomColor} from './nQuery.js';
const redraw = function () {
canvas.clear(); // clear canvas
canvas.prep(); // prep canvas with background color
for (let i = 0; i < bubbles.length; i++) {
bubbles[i].move();
for (let j = i + 1; j < bubbles.length; j++) {
if (bubbles[i].hittest(bubbles[j])) {
let a1 = bubbles[i].getArea();
let a2 = bubbles[j].getArea();
a1 += a2;
a1 /= Math.PI;
a1 = Math.sqrt(a1);
if (bubbles[i].r >= bubbles[j].r) {
bubbles[i].r = a1;
console.log('ll ' + bubbles.length);
bubbles.splice(j, 1);
console.log('go away ' + j);
console.log('ll ' + bubbles.length);
} else {
bubbles[j].r = a1;
console.log('ll ' + bubbles.length);
bubbles.splice(i, 1);
console.log('go away ' + i);
console.log('ll ' + bubbles.length);
}
}
}
bubbles[i].draw();
}
}
const repeater = function () {
setInterval(redraw, 25);
}
const initialize = function () {
console.log('big bang');
console.log('--------');
canvas = new Canvas('canvas', '#ffff88');
for (let i = 0; i < COUNT; i += 1) {
let bubble = new Umo(canvas, randomColor(), i);
bubbles.push(bubble);
}
repeater();
}
let bubbles = [];
let canvas;
const COUNT = 12;
window.addEventListener('load', initialize);
</script>
</head>
<body>
<h1><code>jsanimN1.html</code></h1>
<section>
<canvas id='canvas' width='500' height='600'>
If you see this text, your browser is very old.
</canvas>
</section>
</body>
</html>
Copy the results of the previous assignment so that
jsanimN1.js becomes jsanimN2.js, and
jsanimN1.html becomes jsanimN2.html.
Change the moving objects so that half of them are squares or rectangles and the other half remain disks (circles). When they move around, occasionally one hits another. The assignement is the same as the previous one. The shape with the larger area swallows the smaller and grows proportionately. When one shape is left the animation must stop with an appropriate message.
Hand in as jsanimN2.js, and jsanimN2.html
If you have time create a pale blue disk, small in relation to a 800 x 400 canvas, and animate it so that it moves around the canvas in an elliptical orbit around the yellow center of the black canvas.
Hand in as jsanimN3.js, and jsanimN3.html
jsanimN3.html
<!doctype html>
<html>
<head>
<title>NMLs JS Ellipse</title>
<meta charset='utf-8'/>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<style>
canvas {
margin: 1em auto;
padding: 0;
}
</style>
<script type='module'>
import {Canvas} from './nmlCanvas.js';
import {Disk} from './nmlDisk.js';
import {animate} from './nQuery.js';
const go = function() {
let cv = new Canvas('ellipsen', 'black');
let dot = new Disk(cv, 0, 0, 5, '#afeeee', 0, 2, 390, 190); // the pale blue dot
things.push(dot);
dot = new Disk(cv, 0, 0, 5, 'yellow', 0, 0, 0, 0); // the gravitational center
things.push(dot);
animate(cv, things, onoff, 100)
}
let onoff;
let things = [];
window.addEventListener('load', go);
</script>
</head>
<body>
<header><h1>TODO write content</h1></header>
<canvas id='ellipsen' width='800' height='400'></canvas>
<footer>footer</footer>
</body>
</html>
[20] This adapted from https://en.wikipedia.org/wiki/Luhn_algorithm. If you refer to that beware of the psudocode implementation. It is in a programming language quite different from JavaScript