CSE 190 M, Summer 2011
Final Exam Key

  1. HTML/CSS Tracing
  2. HTML/CSS Coding
  3. JavaScript/DOM
  4. AJAX – Find-It!
  5. PHP – Elevate-It!
  6. SQL – Actors with same director

1. HTML/CSS Tracing

1a – Happy day! (Thu)

Solution files:

Expected output:

expected output

1b – Yee-haw! (Fri)

Solution files:

Expected output:

expected output

2. HTML/CSS Coding

2a – WA.B.L (Thu)

Solution files:

<div id="page">
  <h1><img src="header.gif" alt="Washington Beer - Home of the WASHINGTON BEER Commission" /></h1>
  
  <ul>
    <li><a href="">Home</a></li>
    <li><a href="">Festivals</a></li>
    <li><a href="">Breweries</a></li>
    <li><a href="">News</a></li>
    <li><a href="">WABL</a></li>
    <li><a href="">About Us</a></li>
    <li><a href="">Contact</a></li>
  </ul>
  
  <div id="content">
    
    <h2>What is WA.B.L?</h2>
    <p>WA.B.L. is a community of <strong>WA</strong>shington <strong>B</strong>eer <strong>L</strong>overs celebrating the <strong>FRESH, LOCAL, AWARD-WINNING</strong> craft beer produced in our state.</p>
    <p>It's a Washington Beer Fan Club!</p>
    
    <div id="join">
      <img src="wabl.jpg" alt="WA.B.L - Washington Beer Lovers" /><br/>
      <a href="">JOIN WA.B.L NOW!</a>
    </div>
    
    <h2>WA.B.L. Perks</h2>
    <p>WA.B.L.'ers enjoy monthly <strong>invitation-only</strong> events at various breweries, brewpubs, tasting rooms, and other businesses promoting tasty Washington beer.</p>
    <p>Each year, upon renewal of their membership, WA.B.L.'ers receive a <strong>cool t-shirt</strong> with a design unique to that year, listing all member breweries.</p>
    
    <h2>WA.B.L. Passport</h2>
    <p>WA.B.L.'ers are also encouraged to visit breweries when they're out traveling around the state. Each member is issued a <strong>passport</strong> in which they collect stamps from the breweries they visit.</p>
    <p>Collecting stamps from WA breweries can get you some great prizes!</p>
  </div>
</div>
body {
  background-color: #FFB131;
  font-family: sans-serif;
}

#page {
  width: 950px;
  margin: 0 auto;
  background-color: white;
  border-bottom: solid 5px black;
}

#main {
  padding: 0 1.5em; /* margin also works */
}

#join {
  float: right;
  background-color: #FBC57B;
  padding: .75em;
  margin: 1em;
  font-size: 190%;
  font-weight: bold; /* not specified in problem */
}

ul {
  text-align: center;
  font-weight: bold;
  padding: 0; /* will let slide */
/* list-style-type: none; -- not needed but OK */
  background-color: black; /* not specified in problem */
}

li {
  display: inline;
  padding: 0 1.5em; /* margin DOES NOT work */
  line-height: 2em;
/* height: 2em; -- not correct but allowed */
}

li a {
  color: #FFB131;
  text-decoration: none;
}

h2 {
  text-decoration: underline;
}

2b – S.N.O.B. (Fri)

Solution files:

<div id="page">
  <div id="left" class="column">
    <h1><img src="logo.gif" alt="Oregon Brewers Guild" /></h1>
    <ul>
      <li><a href="">BEER</a></li>
      <li><a href="">BREWERIES</a></li>
      <li><a href="">S.N.O.B</a></li>
      <li><a href="">BLOG</a></li>
      <li><a href="">EVENTS</a></li>
      <li><a href="">PRESS</a></li>
      <li><a href="">ABOUT</a></li>
    </ul>
    <p><img src="map.jpg" alt="Hit the Oregon beer trail! Search our interactive pub map." /></p>
  </div>
  
  <div id="center" class="column">
    <h2>S.N.O.B</h2>
    <p>Now you can show your support for our world-class beers by becoming an <a href="">Enthusiast Member</a> of the Oregon Brewers Guild. Our Enthusiast Members — we call them SNOBs (Supporters of Native Oregon Beer) are an integral link in what we like to call the “beer chain” that connects suppliers, brewers, retailers and consumers.</p>
    <p>As a SNOB, you will be able to show off your impeccable taste in malt beverages and at the same time get a <a href="">backstage pass</a> to see what’s going on behind the scenes in Oregon’s craft brewing industry.</p>
    <p><strong>SNOBs receive the following Membership Benefits:</strong></p>
    <ul>
      <li>Current SNOB shirt is Dusk Blue with Vermillion lettering and list of members on the back.</li>
      <li>An official SNOB membership card.</li>
      <li>Think Oregon Drink Oregon Bumper Sticker.</li>
      <li>“SNOB Stories” monthly <a href="">e-mail newsletter</a></li>
      <li>Invitation to regional “Guild Gatherings”</li>
      <li>A “SNOB” T-shirt</li>
      <li>Discount on tickets on events.</li>
    </ul>
    <p><img src="snob.jpg" alt="2010 SNOB logo" /></p>
  </div>
</div>
body {
  background-color: #1A1A19;
  font-family: Georgia, serif;
}

#page {
  background-color: #E2D1BB;
  width: 50em;
  margin: 0 auto;
  overflow: hidden;
}

.column {
  float: left;
  margin: 1em;
}

#left {
  width: 8em;
}

h1 {
  text-align: center;
}

#left ul {
  list-style-type: none;
  padding: 0;
}

#left a {
  font-weight: bold;
  color: #C5833B;
  text-decoration: none;
  line-height: 1.75em;
}

#center {
  width: 30em;
  padding: 0 4em;
  background-color: white;
}

3. JavaScript / DOM

3a – Mash-It! (Thu)

Solution files:

window.onload = function() {
    document.getElementById('calculate').onclick = calculate;
    document.getElementById('add_grain').onclick = create_row;
};

function calculate() {
    var sum = 0;
    var amounts = document.querySelectorAll('input.amount');
    var yields = document.querySelectorAll('input.yield');
    for (var i = 0; i < amounts.length; i++) {
        sum += amounts[i].value * yields[i].value;
    }
    document.getElementById('specific_gravity').innerHTML = Math.round(sum / 5.5) / 1000 + 1;
}

function create_row() {
    var row = document.createElement('tr');
    row.appendChild(create_cell('amount'));
    row.appendChild(create_cell('name'));
    row.appendChild(create_cell('yield'));
    document.getElementById('malt_bill').appendChild(row);
}

function create_cell(class) {
    var cell = document.createElement('td');
    var input = document.createElement('input');
    input.type = 'text';
    input.className = class;
    cell.appendChild(input);
    return cell;
}

3b – Pace-It! (Thu)

Solution files:

window.onload = function() {
    document.getElementById('pace_chart').style.display = 'none';
    document.getElementById('calculate').onclick = calculate;
};

function calculate() {
    var rows = document.querySelectorAll('#pace_chart tr');
    for (var i = 0; i < rows.length; i++) {
        if (rows[i].id != 'header_row') {
            rows[i].parentNode.removeChild(rows[i]);
        }
    }

    var distance = document.getElementById('distance').value;
    var target_pace = document.getElementById('target_pace').value;

    for (var i = 1; i < distance; i++) {
        create_row(i, multiplyTime(target_pace, i));
    }
    create_row(distance, multiplyTime(target_pace, distance));

    document.getElementById('pace_chart').style.display = '';
}

function create_row(mile, time) {
    var row = document.createElement('tr');
    row.appendChild(create_cell(mile));
    row.appendChild(create_cell(time));
    document.getElementById('pace_chart').appendChild(row);
}

function create_cell(contents) {
    var cell = document.createElement('td');
    cell.innerHTML = contents;
    return cell;
}

4. AJAX – Find-It!

Solution file:

window.onload = function() {
    document.getElementById('find').onclick = findRequest;
};

function findRequest() {
    var from = document.getElementById('from').value;
    var to = document.getElementById('to').value;
    
    var ajax = new XMLHttpRequest();
    ajax.onload = injectDirections;
    ajax.open('GET', 'find-it.php?from=' + from + '&to=' + to, true);
    ajax.send();
}

function injectDirections() {
    var directions = this.responseXML.getElementsByTagName('direction');
    for (var i = 0; i < directions; i++) {
        var li = document.createElement('li');
        var direction = directions[i];
        var turn = direction.getAttribute('turn');
        var distance = direction.getAttribute('distance');
        var street = direction.getAttribute('street');
        var img = document.createElement('img');
        img.src = turn + '.png';
        li.appendChild(img);
        if (street) {
            li.innerHTML += " in " + distance + " miles turn " + turn + " on " + street;
        } else {
            var destinationlist = this.responseXML.getElementsByTagName('directionlist')[0];
            var destination = destinationlist.getAttribute('to');
            li.innerHTML += " in " + distance + " miles arrive at " + destination;
        }
    }
}

5. PHP

Solution files:

<h1>Elevate-It!</h1>

<?php
if (!isset($_GET['profile'])) {
  ?>
  <form action="">
    <p>Select an elevation profile:</p>
    <p><select name="profile">
  <?php
  foreach(glob("*.dat") as $name) {
    ?>
      <option><?= $name ?></option>
    <?php
  }?>
    </select></p>
    <p><input type="submit" value="Elevate-It!" /></p>
  </form>
  <?php
} else {
  ?>
  <p>Elevation data for <?= $_GET['profile'] ?>:</p>
  
  <table>
    <tr><th>distance</th><th>elevation</th></tr>
  <?php
  $sum = 0;
  foreach(file($_GET['profile']) as $line) {
    list($dist, $elev) = explode(',', $line);
    $sum += $elev;
    ?>
    <tr><td><?= $dist ?></td><td><?= $elev ?></td></tr>
    <?php
  }
  ?>
  </table>
  <p>Total gain/loss: <?= $sum; ?></p>
  <?php
}
?>

6. SQL

-- actors who have appeared twice with the same director --
SELECT DISTINCT d.first_name, d.last_name, a.first_name, a.last_name
FROM actors a
JOIN roles r1 ON r1.actor_id = a.id
JOIN roles r2 ON r2.actor_id = a.id
JOIN movies_directors md1 ON md1.movie_id = r1.movie_id
JOIN movies_directors md2 ON md2.movie_id = r2.movie_id
JOIN directors d ON md1.movie_id = d.id AND md2.movie_id = d.id
WHERE md1.movie_id != md2.movie_id;