Build your own adoptables website - Part 3

If you've followed the instructions in Part 1 and Part 2 of the tutorial, you should have an adoptables system where you can add a list of adoptables to a text file, and have pets grow up automatically when the date changes.

With our system so far, everyone who adopts a pet gets the same adoption code. It'd be cool if you got a different variation of the adoptable, chosen at random, when you went to adopt a pet. So the goal for this part is:

We'll have to store this extra information in our XML file which describes the adoptables. Here's the new format:

<adoptables>

<adoptable id="1">
    <variation id="1" chance="1.0">
        <age image="dogbaby.png" />
        <age date="2008-11-20" image="dogpuppyrare.png" />
        <age date="2008-11-25" image="dogadultrare.png" />
    </variation>
    <variation id="2" chance="5.0">
        <age image="dogbaby.png" />
        <age date="2008-11-20" image="dogpuppy.png" />
        <age date="2008-11-25" image="dogadult.png" />
    </variation>
</adoptable>

<adoptable id="2">
    <variation id="1" chance="1.0">
        <age image="ratbaby.png" />
        <age date="2008-11-23" image="ratadult.png" />
    </variation>
</adoptable>

</adoptables>

Notice that each adoptable is now made up of one or more 'variations'. Each variation has a 'chance' attribute which says how likely it is that someone adopting from that adoptable will get that particular variation. Since the second dog variation has 5 times the 'chance' of the first dog variation, the second variation is 5 times more likely to happen than the first one (the first variation is a rare pet!). Both variations have the same picture for their first age, so that you can't tell them apart until they grow up.

There's only one variation of the rat.

Since we need to give people different adoption codes randomly, we will make them click a link to pick an adoptable. When they do, we'll send them to a new PHP page which will randomly choose which variation they will get and give them the code for their new pet. First we'll make the main adoption page (I called mine "mainpage.php") to give our visitor a choice of our different adoptables:

<html>
<head>
</head>
<body>
<p>Adopt one of my pets!</p>
<table width="400" border="0" cellspacing="0" cellpadding="4">
  <tr>
    <td><img src="dogbaby.png"></td>
    <td><a href="adopt.php?id=1">Adopt a dog!</a></td>
  </tr>
  <tr>
    <td><img src="ratbaby.png"></td>
    <td><a href="adopt.php?id=2">Adopt a rat!</a></td>
  </tr>
</table>
</body>
</html>

Notice that both links go to the same page, 'adopt.php', but each link has the ID number of the adoptable you want to show. Our adopt.php page will use the ID number to find the correct entry in adoptables.xml. Our mainpage.php page will look like this:

Adopt one of my pets!

Adopt a dog!
Adopt a rat!

Now we need to make adopt.php. Adopt.php will need to decide which variation our visitor is going to get, and write out the adoption code for them. Here's adopt.php:

<html>
<head>
</head>

<body>
<?php

require("adopttools.php");

/* Our visitor has picked an adoptable they want, its id is in $_REQUEST['id']. Find that
 * adoptable in adoptables.xml
 */
$adoptable=find_adoptable($_REQUEST['id']);

/* To randomly pick a variation from that adoptable, we're going have to do a little maths with
 * random numbers.
 *
 * First we find the sum of all the 'chance' attributes for this adoptable...
 */

$sum=0;
foreach (
$adoptable->variation as $variation) {
    
$sum=$sum $variation['chance'];
}

/* Now we can generate a random number which goes from 0.0 to that sum. This will help us
 * pick a variation.
 */
$random=lcg_value()*$sum;

$sum=0;
foreach (
$adoptable->variation as $variation) {
    
$sum $sum $variation['chance'];
    
    if (
$random <= $sum) {
        
//Choose this variation
        
$v_id=$variation['id'];
        break;
    }
}

?>

<p><img src="simple.php?a=<?php echo $_REQUEST['id'];?>&amp;v=<?php echo $v_id;?>"></p>
<p>Thanks for adopting this pet! :). Here is the adoption code for your pet:</p>
<p><textarea cols="60" rows="2"><img src="http://www.mywebsite.com/simple.php?a=<?php echo $_REQUEST['id'];?>&amp;v=<?php echo $v_id;?>"></textarea></p>
</body>
</html>

Here's the new Simple.php:

<?php

//Tell the browser that we are sending it a PNG image to display
header("Content-Type: image/png");

require("adopttools.php");

//Find the variation with the given adoptable id ('a') and variation id ('v')
$variation=find_variation($_REQUEST['a'], $_REQUEST['v']);

//Decide which of the ages we want to show for the adoptable
        
$pickedAge=NULL//We'll store the age we eventually pick into the variable $pickedAge
        
/* Check the ages in order. The age we end up picking will be the last age
 * in the file where the current date is after the 'date' attribute
 */
foreach ($variation->age as $age) {
    if (!isset(
$age['date']) || time() > strtotime($age['date'])) {
        
$pickedAge=$age;
    }
}

//Now that we've picked the age, display the image that that age uses
readfile($pickedAge['image']);    

exit(
);

?>

Note that both simple.php and adopt.php include the line 'require("adopttools.php")'. This is so that they can both access code that we write into adopttools.php - Adopt.php and simple.php share code, so that we don't have to write the same code into both files. Here's adopttools.php:

<?php

//Load the adoptables XML file
$adoptxml=simplexml_load_file("adoptables.xml");

//Find the adoptable from adoptables.xml which has the right id
function find_adoptable($id) {
    global 
$adoptxml;

    
//For each 'adoptable' tag which is available
    
foreach ($adoptxml->adoptable as $adoptable) {
    
        
//Is this adoptable's id the same as the one that the user wants to see?
        
if ($adoptable['id']==$id) {
            
//Yes, it is
            
return $adoptable;
        }
    }
    
    return 
NULL//We couldn't find an adoptable with that ID
}

//Find the variation with the given adoptable id and variation id
function find_variation($adoptid$varid) {

    
$adoptable=find_adoptable($adoptid);

    
//For each 'variation' tag which is available
    
foreach ($adoptable->variation as $variation) {
    
        
//Is this variation's id the same as the one that the user wants to see?
        
if ($variation['id']==$varid) {
            
//Yes, it is
            
return $variation;
        }
    }
    
    return 
NULL//We couldn't find the variation with that ID
}

?>

Upload the new simple.php, adopttools.php, mainpage.php, adopt.php, and adoptables.xml, along with the new rare pet pictures dogpuppyrare.png and dogadultrare.png. You can download all these files in a zip file.

Once finished, your website should look like this. Notice that the rare dog (the rare dogs have a cross in the background) doesn't appear very often when you adopt!

You can discuss this part of the tutorial in the forums, or move on to Part 4.