University of Washington, CSE 190 M, Spring 2008
Homework Assignment 7: NerdLuv

due Wednesday, May 28, 2008, 11:00pm electronically

This assignment asks you to use HTML forms, PHP, and regular expressions. You will write the following pages:

Online dating has become mainstream with popular sites such as eHarmony,, OkCupid, and Plenty of Fish. Your task for this assignment is to write the HTML and PHP code for a fictional online dating web site for extremely desperate single nerds, called The site will consist of two pages: a front page called nerdluv.php (mostly provided to you) that contains a form for a user to submit information, and a result page called results.php (that you will write entirely) that displays single people who match well with the applicant.

CSE non-majors do not need to submit any .js file, since by default this assignment needs no client-side scripting. Turn in the following files:

Part of your grade comes from uploading your files to Webster at the following URL. Please do not place a solution to this assignment online on a publicly accessible (un-passworded) web site.

Signup Page (nerdluv.php):

A default appearance has been provided for you in the skeleton HTML and CSS files, but you may customize it in any way you like, so long as the functionality described in this document still works as specified.

returning user form The nerdluv.php page begins with the NerdLuv logo image, nerdluv.png. The text where meek geeks meet appears under the image. 2em below this text are two HTML forms. The first form is the "Returning User" form, which allows a user who has already joined the site to view his/her latest matches. The second, larger form is the "New User Signup" form, which allows a user to join the dating site.

Each overall set of form fields is 30em wide, centered within the overall page, and has a background color of #E0E0FF and a 1px black border. Each field set's label has a white background and a 1px black border. The default font for all text on the page is 12pt in Century Gothic, Arial, or any sans-serif font available on the system. 1em of vertical spacing separates adjacent controls on the form.

The "Returning User" form contains the following elements:

signup form The "New User Signup" form contains the following elements:

Results Page (results.php):

The results.php receives input from nerdluv.php and outputs HTML. The page operates in two modes:

You can test whether a given request to it is a GET or POST with the following PHP code:

    # a POST request
} else {
    # a GET request

results page In either mode, the page begins with the same nerdluv.png banner image and slogan as the nerdluv.php. (If you want to remove the redundant HTML content between the nerdluv and results pages, you may want to read about the PHP include function.)

2em below the banner slogan should be a level 1 heading saying "Matches for APPLICANT NAME" where APPLICANT NAME is the name of the person who just submitted the form. Below this is a list of singles that "match" the applicant. A "match" is a person in the dataset who has a "strength of match" score of at least 6 points when compared to the current user. Strength of match points are earned for the following qualities:

You have probably noticed that these "strength of match" rules can lead to results outside the applicant's specified preferred gender and/or age range. For example, if you are a man seeking women but have a lot in common with a man in the dataset, NerdLuv will show his data anyway. This is a little odd, but let's face it, if you are using this dating site in the first place, you should probably keep all your options open.

Each matching single should have have his/her name displayed on a line 30em wide, centered within the page, with a background color of #E0E0FF. 1em below this is an image of the single, shown with a width of 150px. 1em to the right of this image is text about the single, including age, what he/she is seeking, the personality type, OS, and strength of match. There is 3em of space below the image for each match.

Underneath all the matches, the results page shows a paragraph with the total number of matches found. It is possible for this number to be 0 if no singles match the applicant.

Both pages have a title of Both pages have a "favorites icon" of heart.gif. At the bottom right of both pages is the standard pair of W3C validator buttons.

Screenshots in this document are from Windows XP in Firefox 2.0, which may differ from your system.

Data and Validation:

Your results.php page reads its data about singles from a file named singles.txt, which is placed in the same folder as the script itself. This file contains data records in exactly the following format, where each line contains the user's name, gender (M or F), age, Keirsey type, favorite operating system, seeking gender(s) (M, F, or MF), minimum seeking age, and maximum seeking age, separated by commas:

Ada Lovelace,F,96,ISTJ,Linux,M,59,99
Donald Knuth,M,70,INTJ,other,MF,12,17
Marty Stepp,M,28,ISTJ,Windows,F,18,39

Each time the script is run, it should read this file's contents to find the singles that match the applicant based on the above criteria. If results.php is contacted as a GET request, then the file is only read and not modified. If results.php is contacted as a POST request, the file is read, the new user's information is added, and the new information is written to the file. You can add the new user's information to the end of the file and do not have to maintain any particular order to the singles in the file. Recall that you can break apart strings and put them back together using the PHP's explode and implode functions.

When you initially upload your files to Webster, you will need to change the file permissions on singles.txt so that PHP is able to write changes to this file. In your SSH Tectia window, right-click singles.txt in the right-side pane and choose Properties. In the Properties window, enable Group Write permission by checking the box shown in the screenshot below.

permissions permissions

The image for each single is stored in a file in the images subfolder relative to the PHP script. The image for a single is a file with the .jpg extension whose name is equal to the person's name in lowercase with all non-alphabetic characters converted into underscores. For example, the image for Bill Gates is stored in bill_gates.jpg, and the image for Rosie O'Donnell is stored in rosie_o_donnell.jpg. You can replace characters in a string using the preg_replace function and regular expressions, to help you map from a given user's name to his/her image filename. File names are case-sensitive, so you may want to use functions such as strtoupper or strtolower.

A default set of user data and image files will be provided on the course web site. Some users may not have images; in particular, any user who submits new data into the app will not have an image (unless you choose to add that feature, described in the CSE Majors section). To deal with such cases, your results.php code should test whether each user's image exists (using PHP's file_exists function), and if it doesn't, you should instead display the image default_user.jpg.

Your page should also perform a minimal amount of validation on the data that is submitted. In either a GET or POST request, if the name submitted is blank, the results.php page should show an error message rather than attempting to show the user's matches. Similarly, in a POST request, if the Keirsey personality type is not valid, the results.php page should show an error message and should not save any data or display any matches. A valid Keirsey type is a string of exactly 4 characters, where the first character is either I or E, the second character is S or N, the third character is T or F, and the fourth character is J or P. For full credit, you must validate the Keirsey type using a single regular expression and call to the preg_match function.

For CSE Majors:

CSE majors must complete the following additional features:

Regardless of how many additions you choose to implement, the main program behavior and appearance described previously should still work as specified. If you have a different idea for a creative addition to this program, please ask us and we may approve it for credit as a substitution for one of the above. Non-CSE-majors may choose to implement the above features if so desired, but it will be ignored for grading purposes so long as it does not break any other functionality.

Hints and Suggestions:

We suggest the following development strategy for this assignment:

  1. Modify nerdluv.php code to use forms.
  2. Write a basic results.php that works for returning users.
  3. Modify results.php to work for new user signup, writing the new user's information to the file in the proper format and then displaying the same information you did previously.

Before working on the results PHP code, get the initial nerdluv.php behaving properly. You will have to modify the provided nerdluv.php file to add the proper forms and query parameter names to it. Remember that controls whose values are to be submitted as form query parameters must have suitable name attributes. For example, if you want an input text box to submit its text as a query parameter named "creditcard", you'd say something like:

<input type="text" name="creditcard" size="16" />

Also remember that sometimes you must add a value attribute to a form control to affect the way it is submitted (for example, when dealing with radio buttons, and possibly select and check boxes).

You can test your form to see that it is submitting the proper parameters by temporarily setting its action attribute to:

When you're working on your results.php code, we suggest that you implement the "Returning User" (GET) code first, before working on the new user signup (POST). This will require you to look up the returning user's information in the input file. Write the code to look up this information and print it. Then you'll need to compute the strength of match with this user compared to every other user. Do this in a separate pass over the file.

You can test the GET code by typing in names of users already in the system, such as Ada Lovelace or Marty Stepp. We suggest that you use temporary print statements to display which aspects of the user lead to strength of match points. For example, if the operating systems match, print a message along with the strength of match computed so far. This will help you debug problems with the scores. Also consider using the print_r function to print the contents of arrays for debugging, such as $_REQUEST. If things don't look the way you expect, you may want to View Source of the page to see what HTML code has been printed.

Be wary of redundancy in results.php. Try to combine as much of the GET and POST cases' code as possible. All actions related to GET vs. POST (saving the new user's data, or looking up the existing data from the file) can be handled at the start of the code, and then everything else between the two cases (looking through all singles and displaying matches) is the same after that. We suggest that you extract the query values from the $_REQUEST array into variables such as $name, $age, and $operating_system so that you can use these same values whether it's a POST (in which case their values come from $_REQUEST) or a GET (in which case their values come from parts of a line in the input file).

Submission and Grading:

Submit your assignment online from the turnin area of the course web site. For reference, our results.php file has roughly 100-140 lines of PHP, but you do not need to match this total.

Your HTML and CSS code should be W3C valid and have comment headers. (The HTML is generated by PHP in this case. You don't put your PHP source code into the validator, but rather the HTML output that it generates.) Your CSS code should avoid redundancy as much as possible. Stylistic information should be placed into CSS and not into HTML/JS.

Your PHP and JavaScript (if any) code should follow reasonable stylistic guidelines similar to those you would follow on a CSE 14x programming assignment. Minimize redundant code, decompose the problem into functions intelligently, minimize the number of global variables, utilize parameters and return values properly, correctly use indentation and spacing, avoid long lines over 100 characters in length, and place a comment header at the top of your code files and atop every function explaining that function's behavior. You should only use material that has been discussed during the first eight weeks of the course, unless given explicit permission from the instructor.

Your JavaScript code (if any) should follow similar style guidelines to those just stated for PHP, should also pass the JSLint validator, and should correctly utilize XHTML DOM objects for manipulating the page contents.

Your PHP code should generate no error or warning messages when run using reasonable sets of parameters. The source code that is output by your PHP pages will be graded by the same criteria as normal HTML code, meaning that it should be valid XHTML, should be properly formatted and indented, and so on. Your PHP code should use the "embedded PHP" style shown in class, and for full credit, it should not contain any print or echo statements. Produce all output by writing pure HTML in "HTML mode", and insert variables' values using PHP expression blocks.