You are on page 1of 12

CISC181(S21) Lab 3

This lab requires that you download the file Lab03.zip from onQ. Don't be dismayed by the length
of the lab: The text is mostly explanatory. You will have to pay attention to what you're doing,
however.
Submission guidelines
The problems on this lab require a mix of solution types. Part 1 requires you to type a solution into text
boxes on this document and to edit an HTML file. Part 2 requires you to copy and edit another HTML
file. Place the following into a zip file called Lab03_solutions.zip:
 Your completed Lab03.docx file
 Your completed beancounter.html file
 Your completed binary_search.html file
Upload that .zip file to onQ by the lab's due date and time.
Part 1 (10 marks)
Programming requires that you type everything to an exact specification, and this is not as easy as it may
seem. Professional programmers frequently work in pairs, partly so that one programmer can spot
typographical errors or omissions made by the other programmer. Unfortunately, working on this lab by
yourself, you do not have the luxury of the extra pair of eyes, but you do have the advantage of being
able to copy and paste some code from this document.

As with Lab 2, for this lab you will need a plain text editor; ideally one that knows just a little about the
web markup language, HTML (which we will look at in more detail later in the course) and JavaScript
program code. My preference, again, is for Visual Studio Code. You will not lose points on this lab for
using a different editor, but you should not try using Microsoft Word or any program like it that inserts
formatting codes into its documents.

JavaScript is a programming language that all modern web browsers understand. As a programming
language, it has its strengths and weaknesses, but one of its strengths is its ubiquity; it is everywhere! All
but the very simplest websites use it extensively, so it is worth your while to understand a bit about it.

I have written a JavaScript program for this lab and built it into the webpage beancounter.html which
you can extract to a folder on your computer from Lab03Files.zip (available from onQ). Have a look at it
by dragging it from a file listing on your computer onto an open web browser. The program will run
automatically, waiting for you to place a fake coffee shop order. It should look very much like this:

1
Okay, start your text editor and then open beancounter.html in it. It's quite a long file. On my Windows
machine, the top part of the file looks like this in Visual Studio Code:

On a Mac, in a different editor, or even in the same programs but with a different configuration, the file
may look a little different, but here are some things to note:
 Good code editors try to make the programmer's job easier by colouring certain kinds of elements
differently from others. Thus, for example, all the numbers are a sort of pink (fuchsia, maybe?) in
VS Code.
 The file's text begins with the line "<!DOCTYPE html>". The editors use line numbering to
identify this as line 1. If the editor you are using does not show line numbers by default, see if
there is an option to turn them on. (If there is no such option, there may be an indicator
somewhere on your editor's interface showing you the number of the line that is currently being
edited.)
 The file has two large sections of note. The first lies between the <script> and </script> tags
(lines 6 and 164, respectively) and is where most of the JavaScript code can be found. The
second sits lower down inside the <form> and </form> tags (lines 172 and 223), and it provides
both the raw elements of the user interface (the button inputs and text box outputs) and some
values for many of the JavaScript variables. Think of the form, therefore, as providing the input
and output devices for the program found within the <script> and </script> tags. When you load
the page into a web browser – whether from a distant server or from your own computer – the
browser interprets the form and some style information it retrieves from the server.

2
 Styling for the user interface – details of colour, how the boxes and buttons are drawn and
placed, etc. – are contained in a file on the sites.cs.queensu.ca server that is imported on line 5.
We will learn a bit about styling HTML and about HTML itself later in the course.

SAVE YOUR WORK IN YOUR EDITOR FREQUENTLY! Ctrl-S (holding down your Control or Ctrl
key and pressing S) will likely do this quickly and easily. If you really mess up, it may be best to start
again with a freshly extracted copy of beancounter.html. When you are asked to do any editing, make the
changes in your text editor, save your work, then refresh your browser window or drag the revised file to
your browser again to see how those changes are reflected in the running program.

1. (1 mark) The program has a keypad to enter quantities, and it runs subtotals (updated using the button
marked "Enter") so that the user can, for example, enter complex orders like "2 espressos, 3 short
lattes with two espresso shots, 4 tall cappuccinos, and 4 grande Americanos." Use the program to
enter this order,
 click on "2" on the keypad
 then click on "ESPRESSO" (in the "Drink Type" box)
 then click on "Enter" (in the "Calculations" box)
 then click on "3" on the keypad
 then click on "Short" (in the "Cup Size" box)
 then click on "2" (in the "Shots (of espresso)" box)
 then click on "LATTE"
 then click on "Enter"
 … and so on…
 then, finally, click on "Total"

How much, tax included, is 2 espressos, 3 short lattes with two shots of espresso, 4 tall cappuccinos,
and 4 grande Americanos? (Note: Espresso only comes in one size, so if you place an order for
espresso, the "Cup Size" will be ignored.)

$
Go here, http://sites.cs.queensu.ca/courses/cisc181/lab03-01.txt to check your answer, and if you do
not get the same amount, try clicking on the "Clear" button and starting over. It is rather important to
the rest of the lab that you understand how to use the program.

2. (1 mark) cupSize is the name (or identifier) of a variable in my JavaScript program, and clicking on
any of the buttons labeled "Short," "Tall," or "Grande" causes that variable to be loaded with a
different value. A JavaScript variable should be declared in a var statement before it is used. Note
the line numbers that your editor puts down the left side of the code in its editing window. Which
line is the variable cupSize declared on? (Hint: Look for the "var" keyword in front of the identifier
"cupSize.").

3. (1 mark) When a variable is declared, it may also be initialized (given its initial – meaning first –
value) using the assignment operator (an equals sign). What is the initial value of cupSize?

3
4. (2 marks) Nationalist sentiments being what they are, Head Office wants us to "Canadianize" our
product line, and of course, our Canadian sales taxes are different from the American taxes built into
the program currently, so that needs to be changed, too. As you make each change, test it in your
browser. For both marks, your program must run correctly after making these changes. Here
are the changes you are to make:

a) The drink known as Americano is to become Canadiano. (Note that there are nine occurrences of
Americano, spelled with upper- and/or lower-case letters, forming parts of identifiers in some
cases, in the program and the form. Make sure you change them all, preserving the case, upper
and/or lower, of the characters as you go.) Your editor likely has a search-and-replace feature
that lets you specify whether you want to consider character case in your search. Make sure you
select that option. Getting the character case incorrect may mean the difference between
your program working and not working.
b) There is a variable called taxRate that is currently being initialized to 0.0848 (which is the tax
rate for some American state). This value should be changed to 0.13, representing Ontario's 13%
Harmonized Sales Tax (HST). (Note that Ontario charges a reduced tax rate for total restaurant
orders of $4.00 or less, but we will not worry about that.)
Having made these changes, save your work, then "Preview" your revised document, and tell me the
cost, tax included, of 2 espressos, 3 short lattes with two shots of espresso, 4 tall cappuccinos, and 4
grande Canadianos?

$
Check your answer using a calculator or a spreadsheet program (like Excel) before continuing.

5. This is the trickiest part of the lab. For full marks, your program must run correctly after making
these changes. Try to preserve the indenting patterns used in the original code.

You are going to introduce a new control on the interface and change the program logic to work with
the information it provides. As with all the foregoing, make sure everything is typed exactly as
shown, paying special attention to the names of elements like "staffDiscount" with mixed upper- and
lowercase letters.
Here is the idea: Head office has decided to offer employees a discount on purchases. It is to be
applied to the subtotal amount when the user clicks on the "Total" button and will show up as a
separate line item in the "Amounts Owing" box as "Staff Disc". The system user indicates whether a
staff discount is to apply to a purchase by means of a checkbox control placed to the right of the
"Enter" button. If this control is checked…

… then the discount will be applied when the user clicks on "Total." If it is left unchecked (the
default state)…

4
… then the discount will not be applied.
I have already made some adjustments to the styling of the web page to accommodate the new control
and its output field. Here is what you need to do to incorporate them and make them work:
a) (1 mark) We'll make changes to the interface first, starting with the checkbox and its label. Find
this line down in the <body>…</body> section of the HMTL:
<input type="button" id="enterItem" value="Enter">
Insert these four lines immediately below it:

<label for="staffDiscountCheckbox">
<input type="checkbox" id="staffDiscountCheckbox">
Staff discount
</label>

Try to preserve the indenting at that point in the file. Save your work and preview it to see that
the checkbox and its "Staff discount" label appear as in the second image above. (You should be
able to check and uncheck it at this time, but it will not affect calculations yet.)
b) (1 mark) Now we will add the output box for the staff discount amount in the "Amounts Owing"
area. Find this HTML:
<label for="subtotal">Subtotal</label>
and insert the following lines below it:

<input class="number" type="text" id="staffDiscount" value="$0.00" readonly>


<label for="staffDiscount">Staff Disc</label>
Save your work and look at it in your browser to see that the "Staff Disc" label and its field
appear under the "Subtotal" field in the "Amounts Owing" section of the interface. At this stage,
the interface is complete, but the new additions still do not affect the operation of the
program because you have not done any actual programming with them. That comes next.
c) (1 mark) Head office has said that it wants to experiment with the concept by first giving a 6%
discount to staff. As this might change in future, it makes sense for you to introduce a variable
that is declared and initialized near the top of the program, perhaps where a great many other
variables are declared and initialized. So, find where the variable called price is declared and
initialized to 0.00 up in the JavaScript code, and insert a declaration and initialization for a new
variable, staffDiscountRate, below it as follows:
var staffDiscountRate = 0.06;
Save your work.

d) (2 marks) When the user clicks on the "Total" button, the function called total() is executed,
causing calculations to happen and numbers to appear in the "Tax" and "Total" fields. This is
where we are going to add the logic to test whether the user has "checked" the "Staff discount"
checkbox, and, if so, make the amount showing beside "Staff Disc" change from $0.00 to
whatever the calculated discount should be, and then to have this amount be used in the "Tax" and
"Total" calculations. First, find the code for a function called calculateTotal(), then replace that
code with this,

5
function calculateTotal () {
var staffDiscount = 0.00;
if (document.getElementById("staffDiscountCheckbox").checked) {
staffDiscount = Math.round(subtl * staffDiscountRate * 100)/100;
}
document.getElementById("staffDiscount").value = "$" + formatPrice(staffDiscount);
var taxes = Math.round((subtl - staffDiscount) * taxRate * 100)/100;
document.getElementById("tax").value = "$" + formatPrice(taxes);
document.getElementById("amountOwing").value =
"$" + formatPrice(subtl - staffDiscount + taxes);
}

Having made these changes, save your work, then refresh your browser window and find out the cost,
tax included, of 1 espresso, 2 short lattes with three shots of espresso, 3 tall cappuccinos, and 3
grande Canadianos, first without a staff discount, and then with?

$ $
(without staff discount) (with staff discount)

Part 2 (15 marks)

As was the case with Part 1, this portion of the lab will again have you making some changes to a
JavaScript program using a program editor such as Visual Studio Code. This time, however, you are
going to be working from a pseudocode algorithm that you have seen before, that is, the one presented in
the Algorithms module for binary search, to implement the algorithm in JavaScript so that it works on
real data.
To begin:
 Extract the linear_search.html file from Lab03Files.zip to a convenient place for working on it, like
your computer's desktop.
 Open linear_search.html in your editor.
Here is the algorithm for binary search in pseudocode. You will be referring to it a lot while you
gradually turn it into JavaScript code that can be compiled and executed in your browser.

let n be the length of the list of numbers


let a be the list of numbers (a0, a1, a2, ..., an-1)
let val be number being searched for
let low be 0
let high be n - 1
while low ≤ high
let mid be floor((low + high)/2)
if amid = val
report position of val as mid
stop
if amid < val
let low be mid + 1
otherwise
let high be mid - 1
report val is not in the list

6
Something to keep in mind: The indenting in the pseudocode, above, is significant. It shows us which
statements belong to the while loop, and which belong to the two if statements and the otherwise
statements. Importantly, it tells us that the report statement is not in the while loop. Your final
JavaScript code should retain this indenting structure. It will help you (and a TA!) to spot potential
problems in your code.

Since there are two levels of indenting in this pseudocode, your finished code should contain
corresponding JavaScript blocks, each of which begins with a "{" curly bracket and ends with a "}" curly
bracket. To make it more obvious where the blocks are, I have expanded my pseudocode below to
include "{" and "}" block markers and made them bold so they are easier to see…
let n be the length of the list of numbers
let a be the list of numbers (a0, a1, a2, ..., an-1)
let val be number being searched for
let low be 0
let high be n - 1
while low ≤ high {
let mid be floor((low + high)/2)
if amid = val {
report position of val as mid
stop
}
if amid < val {
let low be mid + 1
}
otherwise {
let high be mid – 1
}
}
report val is not in the list

Refer to the above pseudocode frequently during this lab, as it accurately reflects the indenting and
correct placement of the curly brackets in the JavaScript program you are about to create.

We're going to start with a big advantage: An existing program that demonstrates a linear search. It's in
the Lab03.zip file, stored as linear_search.html, so extract it, open it in your text editor, and have a look
at it there or on the next page.

7
<!DOCTYPE html>
<html>
    <head>
        <title>Linear Search demo</title>
        <script>
            // Test lists
            var word_list = ["cat", "duck", "frog", "rat", "unicorn"];
            var number_list = [-12, -7, 0, 4, 5, 10];

            function find(a, val) {
                var n = a.length, i = 0;
                while (i < n && a[i] != val) {
                    i = i + 1;
                }
                return i;
            }

            function report_result(a, val) {
                var pos = find(a, val);
                var list = a.join(", ");
                if (pos < a.length) {
                    alert(val + " is at position " + pos + " in " + list + ".");
                } else {
                    alert(val + " is not in " + list + ".");
                }
            }

            // Test code
            report_result (word_list, "cat"); // found
            report_result (word_list, "cow"); // not found
            report_result (word_list, "rat"); // found
            report_result (number_list, 0); // found
            report_result (number_list, 10); // found
            report_result (number_list, -11); // not found
        </script>
    </head>
    <body>
    </body>
</html>

The first thing you should notice about this file is that it is a lot shorter than the beancounter.html file
from Part 1. Yay!

Drag the linear_search.html file from a file listing onto an open browser so you can see how it looks
when it is working. It just produces a series of pop-up messages showing where test values were (or were
not) found in the test arrays.

8
From the code, you'll see that it uses two so-called array variables, word_list, and number_list, to test its
six-line find function (the code in the middle). You can see other array variables being used in an
example in the Programming 2 slides. The object of this exercise is to change the code in the find
function so instead of performing a linear search, it performs a binary search.

From the Algorithm module's slides, you will learn that for a binary search to work, the data it is
searching through must already be sorted. Happily, the six strings in the word_list array and the six
values in the number_list array are already sorted! (If they weren't, we could apply the exchange sort
algorithm to them to get them sorted.)

Save the file under the new name, binary_search.html. Now to make a purely cosmetic change.

 Change the contents of the <title> tags from "Linear Search demo" to "Binary Search
demo". (This changes what appears in your web browser's tab.)
Before we start messing with the actual code, I'll explain a very little bit about how the find function
works. It does a linear search, using a variable called i (for "index") to keep track of which element of the
array called a (just like in the pseudocode!) is being compared with the search value (called val) during a
specific execution of the while loop. i has an initial value of 0, because array positions start at 0 in
JavaScript, as mentioned in the slides. The while loop will exit for one of two reasons:

 the value of i is no longer less than the length of the array, in which case the linear search
has not found value val in a, or
 value val has been matched to an element of array a, in which case the value of i is the
position of value val in a.
So, what does that mean? It means that if variable i ends up with a value less than the length of the list
being searched (a), the search value, val was, indeed found in the list. Otherwise (the value of i reached
the length of the list being searched), the value val is not one of the elements of the list a and the search
failed. The rest of the program learns of this by way of the statement
return i;
in the find function. return causes the function to end and for any value that follows the word "return" to
be given back to whichever statement called the find function. In this test program, that happens to be the
statement
var pos = find(a, val);
in the report_result function. (I chose the variable name pos because, as you may have suspected, it is
short for "position", as in the position at which value val was found.)
Okay, this all means that if we're going to use the same test code when we create our binary search
version of find, we need to make sure it returns either the position (or index) of the search value in the
list/array being considered, or the length of the list if the search value isn't in the list.
Back to the code:
 Delete all the statements in the block of the find function but leave its opening and closing
curly brackets in place.

9
            function find(a, val) {

            }
Everything else you must do for this lab will go on new lines between those curly brackets.
Now let's look back at that pseudocode. It starts off by creating a bunch of what look like variables, two
of which (conveniently!) have the same names we've been using, a to represent the array or list containing
the various sorted values, and val representing the value we want the function to search for. Now, the
Programming 1 slides talk about information being conveyed to functions by way of arguments, which
are the things that go inside the round brackets in a function call like
report_result (word_list, "cat");

Inside the function itself, the values of the arguments become the values of the corresponding parameters,
which is what the a and val are in
function find(a, val) {

So that means, we already have our a and our val from the pseudocode and don't need to recreate them
with variable declarations. We DO need to do that, however, for the other variable-like things in the
pseudocode, namely n, low, high, and – when we get to it – mid.
Start with n. It's needs to be initialized (have its first value set) to the length of a. You can see from the
original code that there are a couple of references to a.length. Length is a property of arrays in JavaScript,
and a.length computes to the length of a. That means your line declaring n, the first line inside those curly
brackets, should be
var n = a.length;

(and yes, I know, we already had a statement that contained that, and I told you to erase it. What can I
say? Sometimes it pays to start over.)
All right, so that's how you declare a variable. Now,

 do the same for low and high, letting the pseudocode guide you as to what their initial values
should be. Remember the var keyword, and the semicolons (;) statement terminators at the end of
each line.
You should be ready to write your while loop. For guidance to the syntax, look at the while loop in the
original code. It has a reasonably elaborate Boolean expression in its round brackets. Your replacement
will be much simpler. Note that the "less than or equal to" operator you'll need is this: <=, a less than sign
immediately followed by an equals sign. Remember the while loop's opening and closing curly brackets!
All right,

 create the first and last lines of your while loop with its opening and closing curly brackets (which
you'll fill in later). Remember to put your Boolean expression in round brackets.
Notice from the pseudocode that all the statements in it are indented at least one level. Make sure yours
match! It just makes the code tidier and easier to understand.

10
Inside your while loop:
 Declare and initialize the mid variable. For this, you'll need to know how to do a floor operation
in JavaScript. (If you're not sure what floor functions do, Google it!) It happens that JavaScript
has a library of mathematics functions called Math, and one of those functions is called floor!
Here's how you'd get the floor you're looking for:
Math.floor((low + high) / 2)
(Note the round brackets around the low + high. They're important!) So, when you are
declaring your mid variable, initialize it with the expression I've given you above.
Next, the pseudocode has an if compound (multi-line) statement. JavaScript has one of those, too, of
course, and its syntax can be seen in the report_result function in the original code. The pseudocode
doesn't call for an else part as is used in report_result, so you can ignore that for now. Anyway,
continuing inside the while loop:
 Create the first and last lines of the first if statement with its opening and closing curly brackets.
Like while, if requires a Boolean expression that must be enclosed in round brackets. To compare
two values for equality in JavaScript, you don't use an equals sign, you use two of them together
like this:
==
To write
amid
in JavaScript, you'd use this array notation
a[mid]
resulting in the complete Boolean expression:
a[mid] == val
Now we go inside the curly brackets of the if, indenting the contents another level as indicated in the
pseudocode.
 The two statement in the pseudocode,
report position of val as mid
stop
get replaced with just one: a return of mid. See the syntax of the return statement in the original
linear search version of the find function.
Okay, that's the end of the first if statement, so move past its closing curly bracket and onto the second if
statement. This one uses an otherwise clause in the pseudocode, and for that in JavaScript, you use else
instead as you can see in the report_result function. So:
 Create your second if and an else (in place of the pseudocode's otherwise). If you've already
declared a variable, don't use the var keyword with it again, just assign a new value to it as in
low = mid + 1;
Remember that the Boolean expression of the if (the else doesn't have or need one) needs to go in round
brackets and your indenting should match the pseudocode. It's your choice if you write
} else {

11
or
}
else {
JavaScript doesn't care (and neither do I! Some code styling is at the programmer's discretion).
Nearly there, folks! All that's missing is a return statement, after the closing while curly bracket but
BEFORE the closing function curly bracket. This is the return that needs to indicate to the rest of the
program that val does not occur in the array, so the value returned should be, if you recall, the length of
the array, a. And somewhere back there a couple of pages is that information. So:
 Write the last statement of your find function. It returns the length of array a.
Save your work, then refresh your browser window to see if your program works. If it doesn't, you may
have to close your browser window and open it again. Before you try running it a second time, check your
code against the pseudocode first to see if you've missed anything. In my own attempt, I ended up with a
find function that was 17 lines long, top to bottom. Depending how you write your else, you may end up
with 18 lines instead, but it shouldn't be longer than that unless you've got some blank lines. The 15
marks Part 2 of this lab is worth corresponds to each of the 15 essential lines of code inside your find
function's opening and closing curly brackets. Good luck!

12

You might also like