Commit 50a621c9 authored by Sorrel Harriet's avatar Sorrel Harriet
Browse files

Merge branch 'master' of gitlab.doc.gold.ac.uk:data-networks-web/lab-exercises

parents 00069613 5d9e88cd
Live Demo
---------
A live deployment of this app can be viewed at:
http://doc.gold.ac.uk/~sharr003/dnw/lab-6/music-store-app/
http://doc.gold.ac.uk/~sharr003/dnw/lab-exercises/lab-6/music-store-app/
Configuration
-------------
......
Live Demo
---------
A live deployment of this app can be viewed at:
http://doc.gold.ac.uk/~sharr003/dnw/lab-6/music-store-app/
http://doc.gold.ac.uk/~sharr003/dnw/lab-exercises/lab-7/music-store-app/
Configuration
-------------
......
......@@ -3,9 +3,9 @@
// define a connection 'handle'
$link = mysqli_connect(
'localhost',
'sorrel',
'password123',
'musicstore'
'USERNAME',
'PASSWORD',
'DATABASE_NAME'
);
// check connection succeeded
......
Live Demo
---------
A live deployment of this app can be viewed at:
http://doc.gold.ac.uk/~sharr003/dnw/lab-exercises/lab-8/music-store-app/
Configuration
-------------
- Create a blank MySQL database
- Run the statements in sql/schema.sql on your MySQL database to set up the app schema
- Run the statements in sql/dummy-data.sql on your MySQL database to insert some dummy data (optional)- Edit includes/db_connect.php with your database connection details
......@@ -3,9 +3,9 @@
// define a connection 'handle'
$link = mysqli_connect(
'localhost',
'sorrel',
'password123',
'musicstore'
'USERNAME',
'PASSWORD',
'DATABASE_NAME'
);
// check connection succeeded
......
......@@ -60,10 +60,6 @@ $content .= $form_html;
// ------- START form processing code... -------
// define variables and set to empty values
$title = $artist_id = $price = $year = $genre = "";
// check if there was a POST request
if ($_SERVER["REQUEST_METHOD"] == "POST") {
// validate the form data
......
Live Demo
---------
A live deployment of this app can be viewed at:
http://doc.gold.ac.uk/~sharr003/dnw/lab-exercises/resit-app/hangman/
Configuration
-------------
- Clone this repo (or pull latest changes if you already did that at the start of term 1)
- Create a blank MySQL database (CLUE: see lab 2 in the wiki)
- Look at the application code to figure out what tables need to be created, and what fields they should have
- Create the tables and insert some dummy data!
- Hook the database up to the application code (CLUE: edit includes/db_connect.php)
Other notes
-----------
You can only play the game as player 1 because, as yet, no login system has been implemented.
It is supposed here that a login script would pass player_id to other views as a GET parameter.
You don't *have* to do it like that...in fact, you're free to edit any of this application code as you see fit!
*HOWEVER* it is probably not in your interests to edit hangman.js or hangman.css, since you aren't being credited for client-side scripting.
/* Source: https://jsfiddle.net/phollott/x29ym2ag/ */
* {
box-sizing: border-box;
}
body {
font-family: sans-serif;
}
/* Keep it simple - improvement would be to not display characters */
.letter {
display: inline-block;
list-style: none;
width: 20px;
margin: 0 5px;
border-bottom: 1px solid black;
text-align: center;
color: white;
}
.current-word {
list-style: none;
}
.output {
opacity: 0;
transition: opacity 1s ease;
}
.correct {
background-color: green;
transition: all 1s ease;
}
.error {
color: red;
opacity: 1;
}
.warning {
color: orange;
opacity: 1;
}
.win {
color: green;
opacity: 1;
}
.hint {
font-style: italic;
}
<?php
// define a connection 'handle'
$link = mysqli_connect(
'localhost',
'sorrel',
'password123',
'hangman'
);
// check connection succeeded
if (mysqli_connect_errno()) {
exit(mysqli_connect_error());
}
?>
<?php
/* Helper functions.
Include once from index.php */
/* define a function to sanitise user input
(this would ideally be in includes folder)
helps protect against XSS */
function clean_input($data) {
$data = trim($data); // strips unnecessary characters from beginning/end
$data = stripslashes($data); // remove backslashes
$data = htmlspecialchars($data); // replace special characters with HTML entities
return $data;
}
?>
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
// include the HTML for the page header
include "templates/header.html";
// include the HTML for the navigation bar
include "templates/nav.html";
// open a new MySQL database connection
require "includes/db_connect.php";
// require the helper functions script
require "includes/functions.php";
// check if 'page' parameter is set in query string
if (isset($_GET['page'])) {
$page = $_GET['page']; // if so, set page variable to value of 'page' parameter
} else {
$page = 'home'; // if not, set page variable to home
}
// define a variable to store content HTML
$content = "";
// determine which view to serve based on value of $page
switch ($page) {
case 'home' :
include 'views/home.php';
break;
case 'leaderboard' :
include 'views/leaderboard.php';
break;
case 'play' :
include 'views/play.php';
break;
case 'add-game' :
include 'views/add-game.php';
break;
default :
include 'views/404.php';
}
// close the connection to the database */
mysqli_close($link);
// output the HTML
echo $content;
//
include "templates/footer.html";
?>
// Adapted from: https://jsfiddle.net/phollott/x29ym2ag/
function playHangman(word, hint, player_id) {
"use strict";
var availableLetters, guessInput, guess, guessButton, hintButton, lettersGuessed, lettersMatched, output, man, letters, lives, currentWord, numLettersMatched, messages;
/* update the value of the player_id and word fields in the form */
document.getElementById("player_id").value = player_id;
document.getElementById("guessed_word").value = word;
function setup() {
/* start config options */
availableLetters = "abcdefghijklmnopqrstuvwxyz";
lives = 5;
currentWord = word.toLowerCase();
messages = {
win: 'You win!',
lose: 'Game over!',
guessed: ' already guessed, please try again...',
validLetter: 'Please enter a letter from A-Z',
hint: hint
};
/* end config options */
lettersGuessed = lettersMatched = '';
numLettersMatched = 0;
/* make #man and #output blank, create vars for later access */
output = document.getElementById("output");
man = document.getElementById("man");
guessInput = document.getElementById("letter");
man.innerHTML = 'You have ' + lives + ' lives remaining';
output.innerHTML = '';
document.getElementById("letter").value = '';
/* attach click behaviour to hint button */
document.getElementById("hint").onclick = function () {
document.getElementById("hintText").innerHTML = messages.hint;
}
/* make sure guess button is enabled */
guessButton = document.getElementById("guess");
guessInput.style.display = 'inline';
guessButton.style.display = 'inline';
/* set up display of letters in current word */
letters = document.getElementById("letters");
letters.innerHTML = '<li class="current-word">Current word:</li>';
var letter, i;
for (i = 0; i < currentWord.length; i++) {
letter = '<li class="letter letter' + currentWord.charAt(i).toUpperCase() + '">' + currentWord.charAt(i).toUpperCase() + '</li>';
letters.insertAdjacentHTML('beforeend', letter);
}
}
function gameOver(win) {
if (win) {
output.innerHTML = messages.win;
output.classList.add('win');
/* update the value of won field to true */
document.getElementById("won").value = "1";
/* submit form to database */
document.getElementById("hangman").submit();
} else {
output.innerHTML = messages.lose;
output.classList.add('error');
/* submit form to database */
document.getElementById("hangman").submit();
}
guessInput.style.display = guessButton.style.display = 'none';
guessInput.value = '';
}
/* Start game */
setup();
/* reset letter to guess on click */
guessInput.onclick = function () {
this.value = '';
};
/* main guess function when user clicks #guess */
document.getElementById('hangman').onsubmit = function (e) {
if (e.preventDefault) e.preventDefault();
output.innerHTML = '';
output.classList.remove('error', 'warning');
guess = guessInput.value.toLowerCase();
/* does guess have a value? if yes continue, if no, error */
if (guess) {
/* is guess a valid letter? if so carry on, else error */
if (availableLetters.indexOf(guess) > -1) {
/* has it been guessed (missed or matched) already? if so, abandon & add notice */
if ((lettersMatched && lettersMatched.indexOf(guess) > -1) || (lettersGuessed && lettersGuessed.indexOf(guess) > -1)) {
output.innerHTML = '"' + guess.toUpperCase() + '"' + messages.guessed;
output.classList.add("warning");
}
/* does guess exist in current word? if so, add to letters already matched, if final letter added, game over with win message */
else if (currentWord.indexOf(guess) > -1) {
var lettersToShow;
lettersToShow = document.querySelectorAll(".letter" + guess.toUpperCase());
for (var i = 0; i < lettersToShow.length; i++) {
lettersToShow[i].classList.add("correct");
}
/* check to see if letter appears multiple times */
for (var j = 0; j < currentWord.length; j++) {
if (currentWord.charAt(j) === guess) {
numLettersMatched += 1;
}
}
lettersMatched += guess;
if (numLettersMatched === currentWord.length) {
gameOver(true);
}
}
/* guess doesn't exist in current word and hasn't been guessed before, add to lettersGuessed, reduce lives & update user */
else {
lettersGuessed += guess;
lives--;
man.innerHTML = 'You have ' + lives + ' lives remaining';
if (lives === 0) gameOver();
}
}
/* not a valid letter, error */
else {
output.classList.add('error');
output.innerHTML = messages.validLetter;
}
}
/* no letter entered, error */
else {
output.classList.add('error');
output.innerHTML = messages.validLetter;
}
return false;
};
};
<!-- Source: https://jsfiddle.net/phollott/x29ym2ag/ -->
<form id="hangman" method="POST" action="index.php?page=add-game">
<input type="hidden" id="won" name="won" value="0" />
<input type="hidden" id="player_id" name="player_id" value="2" />
<input type="hidden" id="guessed_word" name="guessed_word" value="" />
<input type="text" maxlength="1" minlength="1" name="letter" id="letter" placeholder="Guess a letter" />
<input id="hint" name="hint" type="button" value="Hint" />
<input id="guess" name="guess" type="submit" value="Guess" />
</form>
<ul id="letters"></ul>
<p id="man"></p>
<p id="hintText" class="hint"></p>
<p id="output" class="output"></p>
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'/>
<title>Hang Man Game</title>
<link href="css/hangman.css" type="text/css" rel="stylesheet">
<script src="js/hangman.js" type="text/javascript"></script>
</head>
<body>
<nav>
<ul>
<li><a href='index.php?page=home'>Home</a></li>
<li><a href='index.php?page=play'>Play Hangman</a></li>
<li><a href='index.php?page=leaderboard'>Leaderboard</a></li>
</ul>
</nav>
<?php
// add a new game to database
// define variables and set to empty values
$player_id = $won = $guessed_word = "";
// check if there was a POST request
if ($_SERVER["REQUEST_METHOD"] == "POST") {
// validate the form data
$player_id = mysqli_real_escape_string($link, clean_input($_POST["player_id"]));
$won = mysqli_real_escape_string($link, clean_input($_POST["won"]));
$guessed_word = mysqli_real_escape_string($link, clean_input($_POST["guessed_word"]));
// define a string to tell us if they won/lost
if ($won == 1) {
$outcome = "win";
} else {
$outcome = "loss";
}
// define the insertion query
$sql = sprintf("INSERT INTO Game (player_id, won, guessed_word)
VALUES (%d, %d, '%s')", $player_id, $won, $guessed_word);
// run the query to insert the data
$result = mysqli_query($link, $sql);
// check if the query went ok
if ($result === false) {
mysqli_rollback($link); // if query returns false, rollback transaction
// output error message
echo mysqli_error($link);
} else {
mysqli_commit($link); // else, commit transaction
$content .= "Your $outcome has been recorded!";
}
}
// ------- END form processing code... -------
?>
<?php
// check if player id is set in query string
if (!isset($_GET['player_id'])) {
// it is not set, so make them player 1 by default
$player_id = 1;
}
else {
// set player_id based on GET parameter (imagining it was passed by some login script)
$player_id = $_GET['player_id'];
}
// define the SQL queries to run...
// this query will fetch the details about the player
$sql = "SELECT username, forename, surname FROM Player WHERE id=$player_id";
// query the database
$result = mysqli_query($link, $sql);
// get number of rows in result-set
$row_cnt = mysqli_num_rows($result);
// check if there are rows to display...
if ($row_cnt == 0) {
// if not, output a suitable message
$content .= "<p>Sorry, I don't know who you are...</p>";
} else {
// otherwise set a variable with their name
while ($row = mysqli_fetch_assoc($result)) {
$forename = $row['forename'];
}
// free result set
mysqli_free_result($result);
// update content
$content .= "<h1>Welcome to Hang Man $forename!</h1>";
$content .= "<p>An exciting word game for 1 player.</p>";
}
?>
<?php
// define query to fetch game stats using nested queries
// and aggregate function with GROUP BY clause
// order by ranking (success rate)
$sql = "SELECT Player.username AS player,
(SELECT COUNT(*) FROM Game WHERE Game.player_id=Player.id) AS num_plays,
(SELECT COUNT(*) FROM Game WHERE Game.player_id=Player.id AND Game.won=1) AS num_wins
FROM Player
INNER JOIN Game ON Game.player_id=Player.id
GROUP BY username
ORDER BY num_wins/num_plays DESC";
// query the database
$result = mysqli_query($link, $sql);
// update HTML content string with page title
$content .= "<h1>Leaderboard</h1>";
// get number of rows in result-set
$row_cnt = mysqli_num_rows($result);
// check if there are rows to display...
if ($row_cnt == 0) {
// if not, output a suitable message
$content .= "<p>There are no games in the database!</p>";
} else {
// otherwise, update the HTML in $content
$content .= "<table cellpadding='4' border='1'>
<thead align='left'>
<tr>
<th>Rank</th>
<th>Player</th>
<th>Number of plays</th>
<th>Number of wins</th>
<th>Success rate (%)</th>
</tr>
</thead>
<tbody>";
// while there are rows, fetch each row as an associative array
$i = 1;
while ($row = mysqli_fetch_assoc($result)) {
// calculate the success rate as percent
$success = round($row['num_wins']/$row['num_plays']*100,0);
// append the content with more HTML containing row data
$content .= "<tr>
<td>".$i."</td>
<td>".$row['player']."</td>
<td>".$row['num_wins']."</td>
<td>".$row['num_plays']."</td>
<td>".$success."</td>
</tr>"; // reference a field value in the array by its key!
}
// free result set
mysqli_free_result($result);
$content .= "</tbody></table>";
}
?>
<?php
// check if player id is set in query string
if (!isset($_GET['player_id'])) {
// it is not set, so make them player 1 by default
$player_id = 1;
}
else {
// set a variable to store player_id
$player_id = $_GET['player_id'];
}
// define the SQL queries to run...
// this query will return a random row from the Word table
$sql = "SELECT letters, hint FROM Word ORDER BY RAND() LIMIT 1";
// query the database
$result = mysqli_query($link, $sql);
// get number of rows in result-set
$row_cnt = mysqli_num_rows($result);
// check if there are rows to display...
if ($row_cnt == 0) {
// if not, output a suitable message
$content .= "<p>Sorry, something went wrong...there is no word to guess!</p>";
} else {
// otherwise, play the game
// include the html for the game
include("templates/hangman.html");
// fetch each row from result set as an associative array (there should only be one)
while ($row = mysqli_fetch_assoc($result)) {
$word = $row['letters'];
$hint = $row['hint'];
}
// free result set
mysqli_free_result($result);
// call the playGame function
$content .= "<script type='text/javascript'>playHangman('$word','$hint', '$player_id');</script>";
}
?>