Stanford CS106A FacePamphlet Solution

27 Nov

Wow, I cannot believe that I’ve gotten all the way to the end of this class!! I actually just finished FacePamphlet and couldn’t me more excited.

So, without further adiu, here is my solution the last Stanford CS106, which you can also find on github.

FacePamphlet.java

/* 
 * File: FacePamphlet.java
 * -----------------------
 * When it is finished, this program will implement a basic social network
 * management system.
 */

import acm.program.*;
import acm.graphics.*;
import acm.util.*;
import java.awt.event.*;
import javax.swing.*;

public class FacePamphlet extends Program 
					implements FacePamphletConstants {

	/* Private instance variables*/
	//text fields
	private JTextField name;
	private JTextField status;
	private JTextField picture;
	private JTextField friend;
	
	//creates a new database and a new canvas
	private FacePamphletDatabase profileInfo = new FacePamphletDatabase();
	private FacePamphletCanvas canvas = new FacePamphletCanvas();
	
	//keeps track of the current profile
	private FacePamphletProfile currentProfile = null;
	
	
	/**
	 * This method has the responsibility for initializing the 
	 * interactors in the application, and taking care of any other 
	 * initialization that needs to be performed.
	 */
	public void init() {
		
		//fields on the North Side of the screen
		add(new JLabel("Name "), NORTH); 
		
		name = new JTextField(TEXT_FIELD_SIZE);
		add(name, NORTH);
		
		add(new JButton("Add"), NORTH);
		
		add(new JButton("Delete"), NORTH);
		
		add(new JButton("Lookup"), NORTH);
		
		//fields on the West Side of the screen
		status = new JTextField(TEXT_FIELD_SIZE);
		add(status, WEST);
		
		add(new JButton("Change Status"), WEST);
		
		add(new JLabel(EMPTY_LABEL_TEXT), WEST); //space holder
		
		picture = new JTextField(TEXT_FIELD_SIZE);
		add(picture, WEST);
		
		add(new JButton("Change Picture"), WEST);
		
		add(new JLabel(EMPTY_LABEL_TEXT), WEST); //space holder
		
		friend = new JTextField(TEXT_FIELD_SIZE);
		add(friend, WEST);
		
		add(new JButton("Add Friend"), WEST);
		
		//Action listeners
		addActionListeners();
		status.addActionListener(this);
		picture.addActionListener(this);
		friend.addActionListener(this);
		
		add(canvas);
    }
  
    /**
     * This class is responsible for detecting when the buttons are
     * clicked or interactors are used, so you will have to add code
     * to respond to these actions.
     */
	
    public void actionPerformed(ActionEvent e) {
    	
    	String enteredName = name.getText();
    	
    	//Add button is clicked
    	if(e.getActionCommand().equals("Add") && !name.getText().equals("")) {
    		//if the entered name does not exist in the database, a profile is created
    		if(profileInfo.containsProfile(enteredName) == false) {
    			FacePamphletProfile profile = new FacePamphletProfile(enteredName);
    			profileInfo.addProfile(profile);
    			canvas.displayProfile(profile);
    			canvas.showMessage("New profile created");
    			currentProfile = profile;
    		}
    		//if the entered name is already an existing profile, displays the profile
    		//and tells the user that the profile already exists
    		else{
    			FacePamphletProfile profile = profileInfo.getProfile(enteredName);
    			canvas.displayProfile(profile);
    			canvas.showMessage("A profile with name " + enteredName + " already exists.");
    			currentProfile = profile;
    		}
    	}
    	
    	//Delete button is clicked
    	else if (e.getActionCommand().equals("Delete") && !name.getText().equals("")){
    		//clears the canvas and sets the current profile to null
    		canvas.removeAll();
    		currentProfile = null;
    		//if the entered name exists as a profile, the profile is deleted
    		if(profileInfo.containsProfile(enteredName) == true) {
    			profileInfo.deleteProfile(enteredName);
    			canvas.showMessage("Profile of " + enteredName + " deleted");
    		}
    		//if the entered name is not an actual profile, tells the user 
    		//that the profile does not exist
    		else{
    			canvas.showMessage("A profile with name " + enteredName + " does not exist.");
    		}
    	}
    	
    	//Lookup button is clicked
    	else if (e.getActionCommand().equals("Lookup") && !name.getText().equals("")){
    		canvas.removeAll(); //clears everything off the canvas
    		//if the entered name exists in the database, displays the profile
    		if(profileInfo.containsProfile(enteredName) == true) {
    			FacePamphletProfile profile = profileInfo.getProfile(enteredName);
    			canvas.displayProfile(profile);
    			canvas.showMessage("Displaying " + enteredName);
    			currentProfile = profile;
    		}
    		//if the entered name does not exists, tells the user it doesn't exist
    		//and sets current profile to null
    		else{
    			canvas.showMessage("A profile with name " + enteredName + " does not exist.");
    			currentProfile = null;
    		}
    	}
    	
    	//Change Status is clicked or user clicked enter after entering a status in the text field
    	else if (e.getActionCommand().equals("Change Status") || e.getSource() == status && !status.getText().equals("")){
    		String statusMessage = status.getText();
    		if(currentProfile != null) {
    			FacePamphletProfile profile = profileInfo.getProfile(currentProfile.getName());
    			profile.setStatus(profile.getName() + " is " + statusMessage);
    			canvas.displayProfile(profile);
    			canvas.showMessage("Status updated to " + statusMessage);
    		}
    		else{
    			canvas.showMessage("Please select a profile to change status");
    		}
    	}
    	
    	//Change Picture is clicked or user clicked enter after entering picture name into the text field
    	else if (e.getActionCommand().equals("Change Picture") || e.getSource() == picture && !picture.getText().equals("")){
    		String filename = picture.getText();
    		if(currentProfile != null) {
    			FacePamphletProfile profile = profileInfo.getProfile(currentProfile.getName());
    			GImage image = null;
    			try {
    				image = new GImage(filename);
    				profile.setImage(image);
    			} catch (ErrorException ex) {
    				image = null;
    			}
    			canvas.displayProfile(profile);
    			if(image == null) {
    				canvas.showMessage("Unable to open image file: " + filename);
    			}
    			else{
    				canvas.showMessage("Picture updated");
    			}
    		}
    		else{
    			println("Please select a profile to change picture");
    		}
    	}
    	
    	//Add Friend is clicked or user clicked enter after entering a friends name into the text field
    	else if (e.getActionCommand().equals("Add Friend") || e.getSource() == friend && !friend.getText().equals("")){
    		String friendName = friend.getText();
    		//checks to see if there is a current profile
    		if(currentProfile != null) {
    			FacePamphletProfile profile = profileInfo.getProfile(currentProfile.getName());
    			//checks to see if the name entered is the users name. The user can't friend him/herself. 
    			if(profile.getName().equals(friendName)) {
    				canvas.showMessage("You cannot friend yourself");
    			}
    			//checks to see if the friend exists in the database
    			else if(profileInfo.containsProfile(friendName)) {
    				FacePamphletProfile friendProfile = profileInfo.getProfile(friendName);
    				//checks to see if the user is already friends with the friend name entered
    				
    				//if the user and the friend entered are not friends, makes them friends
    				if(profile.addFriend(friendName) == true) {
    					profile.addFriend(friendName);
    					friendProfile.addFriend(enteredName);
    					canvas.displayProfile(profile);
    					canvas.showMessage(friendName + " added as a friend.");
    				}
    				//if the user is already friends with the friend name entered, displays this message
    				else {
    					canvas.showMessage(profile.getName() + " already has " + friendName + " as a friend.");
    				}
    			}
    			//if the friend does not exist in the database, displays this message
    			else{
    				canvas.showMessage(friendName + " does not exist.");
    			}
    		}	
    		//if there is not current profile, asks user to select a profile
    		else{
    			canvas.showMessage("Please select a profile to add friend");
    		}	
    	}		
    }
}

FacePamphletCanvas.java

/*
 * File: FacePamphletCanvas.java
 * -----------------------------
 * This class represents the canvas on which the profiles in the social
 * network are displayed.  NOTE: This class does NOT need to update the
 * display when the window is resized.
 */


import acm.graphics.*;
import java.awt.*;
import java.awt.Image.*;
import java.util.*;

public class FacePamphletCanvas extends GCanvas 
					implements FacePamphletConstants {
	
	/* Private instance variables*/
	double nameHeight = 0;
	double lastX = 0;
	double lastY = 0;
	
	/** 
	 * Constructor
	 * This method takes care of any initialization needed for 
	 * the display
	 */
	public FacePamphletCanvas() {
		// You fill this in
	}
	
	/** 
	 * This method displays a message string near the bottom of the 
	 * canvas.  Every time this method is called, the previously 
	 * displayed message (if any) is replaced by the new message text 
	 * passed in.
	 */
	public void showMessage(String msg) {
		GLabel message = new GLabel(msg);
		double x = getWidth()/2 - message.getWidth()*3/4;
		double y = getHeight() - BOTTOM_MESSAGE_MARGIN;
		if(getElementAt(lastX, lastY) != null) {
			remove(getElementAt(lastX, lastY));
		}
		lastX = x;
		lastY = y;
		message.setFont(MESSAGE_FONT);
		add(message, x, y);
	}
	
	
	/** 
	 * This method displays the given profile on the canvas.  The 
	 * canvas is first cleared of all existing items (including 
	 * messages displayed near the bottom of the screen) and then the 
	 * given profile is displayed.  The profile display includes the 
	 * name of the user from the profile, the corresponding image 
	 * (or an indication that an image does not exist), the status of
	 * the user, and a list of the user's friends in the social network.
	 */
	public void displayProfile(FacePamphletProfile profile) {
		removeAll();
		addName(profile.getName());
		addImage(profile.getImage());
		addStatus(profile.getStatus());
		addFriends(profile.getFriends());
	}
	
	private void addName(String name) {
		GLabel Name = new GLabel(name);
		Name.setFont(PROFILE_NAME_FONT);
		Name.setColor(Color.BLUE);
		double x = LEFT_MARGIN;
		nameHeight = Name.getHeight();
		double y = TOP_MARGIN + nameHeight;
		add(Name, x, y);
	}
	
	private void addImage(GImage image) {
		double x = LEFT_MARGIN;
		double y = TOP_MARGIN + nameHeight + IMAGE_MARGIN; 
		if(image != null) {
			image.setBounds(x, y, IMAGE_WIDTH, IMAGE_HEIGHT);
			add(image);
		}
		else {
			GRect imageRect = new GRect(x, y, IMAGE_WIDTH, IMAGE_HEIGHT);
			add(imageRect);
			GLabel noImage = new GLabel("No Image");
			noImage.setFont(PROFILE_IMAGE_FONT);
			double labelWidth = x + IMAGE_WIDTH/2 - noImage.getWidth()/2;
			double labelHeight = y + IMAGE_HEIGHT/2;
			add(noImage, labelWidth, labelHeight);
		}
	}
	
	private void addStatus(String status) {
		GLabel Status = new GLabel(status);
		Status.setFont(PROFILE_STATUS_FONT);
		double x = LEFT_MARGIN;
		double y = TOP_MARGIN + nameHeight + IMAGE_MARGIN + IMAGE_HEIGHT + STATUS_MARGIN + Status.getHeight();
		if(getElementAt(x, y) != null) {
			remove(getElementAt(x, y));
		}
		add(Status, x, y);
	}

	private void addFriends(Iterator<String>friends) {
		GLabel Friends = new GLabel("Friends:");
		Friends.setFont(PROFILE_FRIEND_LABEL_FONT);
		double x = getWidth()/2;
		double y = TOP_MARGIN + nameHeight;
		add(Friends, x, y);
		Iterator<String> it = friends;
		for(int i = 1; it.hasNext(); i++) {
			GLabel friendName = new GLabel(it.next());
			friendName.setFont(PROFILE_FRIEND_FONT);
			double height = y + Friends.getHeight() * i;
			add(friendName, x, height);
		}
	}
	
}

FacePamphletDatabase.java

/*
 * File: FacePamphletDatabase.java
 * -------------------------------
 * This class keeps track of the profiles of all users in the
 * FacePamphlet application.  Note that profile names are case
 * sensitive, so that "ALICE" and "alice" are NOT the same name.
 */

import java.util.*;

public class FacePamphletDatabase implements FacePamphletConstants {
	
	/* private instance variables */
	private Map<String, FacePamphletProfile> profiles = new HashMap<String, FacePamphletProfile>();
	
	/** 
	 * Constructor
	 * This method takes care of any initialization needed for 
	 * the database.
	 */
	public FacePamphletDatabase() {
		// You fill this in
	}
	
	
	/** 
	 * This method adds the given profile to the database.  If the 
	 * name associated with the profile is the same as an existing 
	 * name in the database, the existing profile is replaced by 
	 * the new profile passed in.
	 */
	public void addProfile(FacePamphletProfile profile) {
		if(!profiles.containsKey(profile.getName())) {
			profiles.put(profile.getName(), profile);
		}
		else{
			profiles.remove(profile.getName());
			profiles.put(profile.getName(), profile);
		}
	}

	
	/** 
	 * This method returns the profile associated with the given name 
	 * in the database.  If there is no profile in the database with 
	 * the given name, the method returns null.
	 */
	public FacePamphletProfile getProfile(String name) {
		if(profiles.containsKey(name)) {
			return profiles.get(name);
		}
		else{
			return null;
		}
		
	}
	
	
	/** 
	 * This method removes the profile associated with the given name
	 * from the database.  It also updates the list of friends of all
	 * other profiles in the database to make sure that this name is
	 * removed from the list of friends of any other profile.
	 * 
	 * If there is no profile in the database with the given name, then
	 * the database is unchanged after calling this method.
	 */
	public void deleteProfile(String name) {
		if(profiles.containsKey(name)) {
			FacePamphletProfile profileToRemove = profiles.get(name);
			Iterator<String>it = profileToRemove.getFriends();
			while(it.hasNext()) {
				String friendName = it.next();
				FacePamphletProfile friendsProfile = profiles.get(friendName);
				friendsProfile.removeFriend(name);
			}
			profiles.remove(name);
		}
	}

	
	/** 
	 * This method returns true if there is a profile in the database 
	 * that has the given name.  It returns false otherwise.
	 */
	public boolean containsProfile(String name) {
		if(profiles.containsKey(name)) {
			return true;
		}
		else {
			return false;
		}
	}

}

FacePamphletProfile.java

/*
 * File: FacePamphletProfile.java
 * ------------------------------
 * This class keeps track of all the information for one profile
 * in the FacePamphlet social network.  Each profile contains a
 * name, an image (which may not always be set), a status (what 
 * the person is currently doing, which may not always be set),
 * and a list of friends.
 */

import acm.graphics.*;
import java.util.*;

public class FacePamphletProfile implements FacePamphletConstants {
	
	/* Private instance variables*/
	private String Name = "";
	private GImage Image = null;
	private String Status = "No current status";
	private ArrayList <String> friends = new ArrayList<String>();
	
	/** 
	 * Constructor
	 * This method takes care of any initialization needed for
	 * the profile.
	 */
	public FacePamphletProfile(String name) {
		Name = name;
	}

	/** This method returns the name associated with the profile. */ 
	public String getName() {
		return Name;
	}

	/** 
	 * This method returns the image associated with the profile.  
	 * If there is no image associated with the profile, the method
	 * returns null. */ 
	public GImage getImage() {
		if(Image == null) {
			return null;
		}
		else{
			return Image;
		}
	}

	/** This method sets the image associated with the profile. */ 
	public void setImage(GImage image) {
		Image = image;
	}
	
	/** 
	 * This method returns the status associated with the profile.
	 * If there is no status associated with the profile, the method
	 * returns the empty string ("").
	 */ 
	public String getStatus() {
		return Status;
	}
	
	/** This method sets the status associated with the profile. */ 
	public void setStatus(String status) {
		Status = status;
	}

	/** 
	 * This method adds the named friend to this profile's list of 
	 * friends.  It returns true if the friend's name was not already
	 * in the list of friends for this profile (and the name is added 
	 * to the list).  The method returns false if the given friend name
	 * was already in the list of friends for this profile (in which 
	 * case, the given friend name is not added to the list of friends 
	 * a second time.)
	 */
	public boolean addFriend(String friend) {
		if(friends.contains(friend)) {
			return false;
		}
		else{
			friends.add(friend);
			return true;
		}
	}

	/** 
	 * This method removes the named friend from this profile's list
	 * of friends.  It returns true if the friend's name was in the 
	 * list of friends for this profile (and the name was removed from
	 * the list).  The method returns false if the given friend name 
	 * was not in the list of friends for this profile (in which case,
	 * the given friend name could not be removed.)
	 */
	public boolean removeFriend(String friend) {
		if(friends.contains(friend)) {
			friends.remove(friends.indexOf(friend));
			return true;
		}
		else{
			return false;
		}
	}

	/** 
	 * This method returns an iterator over the list of friends 
	 * associated with the profile.
	 */ 
	public Iterator<String> getFriends() {
		return friends.iterator();
	}
	
	/** 
	 * This method returns a string representation of the profile.  
	 * This string is of the form: "name (status): list of friends", 
	 * where name and status are set accordingly and the list of 
	 * friends is a comma separated list of the names of all of the 
	 * friends in this profile.
	 * 
	 * For example, in a profile with name "Alice" whose status is 
	 * "coding" and who has friends Don, Chelsea, and Bob, this method 
	 * would return the string: "Alice (coding): Don, Chelsea, Bob"
	 */ 
	public String toString() {
		String profile = Name + " (" + Status + "): ";
		Iterator<String>it = friends.iterator();
		while(it.hasNext()) {
			profile += it.next() + ", ";
		}
		return profile;
	}
	
}

FacePamphletConstants.java

/*
 * File: FacePamphletConstants.java
 * --------------------------------
 * This file declares several constants that are shared by the
 * different modules in the FacePamphlet application.  Any class
 * that implements this interface can use these constants.
 */

public interface FacePamphletConstants {

	/** The width of the application window */
	public static final int APPLICATION_WIDTH = 800;

	/** The height of the application window */
	public static final int APPLICATION_HEIGHT = 500;

	/** Number of characters for each of the text input fields */
	public static final int TEXT_FIELD_SIZE = 15;

	/** Text to be used to create an "empty" label to put space
	 *  between interactors on EAST border of application.  Note this
	 *  label is not actually the empty string, but rather a single space */
	public static final String EMPTY_LABEL_TEXT = " ";

	/** Name of font used to display the application message at the
	 *  bottom of the display canvas */
	public static final String MESSAGE_FONT = "Dialog-18";

	/** Name of font used to display the name in a user's profile */
	public static final String PROFILE_NAME_FONT = "Dialog-24";
	
	/** Name of font used to display the text "No Image" in user
	 *  profiles that do not contain an actual image */
	public static final String PROFILE_IMAGE_FONT = "Dialog-24";
	
	/** Name of font used to display the status in a user's profile */
	public static final String PROFILE_STATUS_FONT = "Dialog-16-bold";

	/** Name of font used to display the label "Friends" above the
	 *  user's list of friends in a profile */
	public static final String PROFILE_FRIEND_LABEL_FONT = "Dialog-16-bold";

	/** Name of font used to display the names from the user's list
	 *  of friends in a profile */
	public static final String PROFILE_FRIEND_FONT = "Dialog-16";

	/** The width (in pixels) that profile images should be displayed */
	public static final double IMAGE_WIDTH = 200;

	/** The height (in pixels) that profile images should be displayed */
	public static final double IMAGE_HEIGHT = 200;	

	/** The number of pixels in the vertical margin between the bottom 
	 *  of the canvas display area and the baseline for the message 
	 *  text that appears near the bottom of the display */
	public static final double BOTTOM_MESSAGE_MARGIN = 20;

	/** The number of pixels in the hortizontal margin between the 
	 *  left side of the canvas display area and the Name, Image, and 
	 *  Status components that are display in the profile */	
	public static final double LEFT_MARGIN = 20;	

	/** The number of pixels in the vertical margin between the top 
	 *  of the canvas display area and the top (NOT the baseline) of 
	 *  the Name component that is displayed in the profile */	
	public static final double TOP_MARGIN = 20;	
	
	/** The number of pixels in the vertical margin between the 
	 *  baseline of the Name component and the top of the Image 
	 *  displayed in the profile */	
	public static final double IMAGE_MARGIN = 20;

	/** The number of vertical pixels in the vertical margin between 
	 *  the bottom of the Image and the top of the Status component 
	 *  in the profile */		
	public static final double STATUS_MARGIN = 20;

}
Advertisements

3 Responses to “Stanford CS106A FacePamphlet Solution”

  1. Jeffk July 23, 2012 at 1:42 pm #

    Congrats!! I just started a few weeks ago following this entire course online and I’m currently at lecture 6!! It’s getting a little bit more harder 🙂

  2. Hunter M August 1, 2012 at 12:11 pm #

    I have been following this course online, and have stumbled upon a problem. In the Hierarchy code, I managed to get all of it to run, save that my GRect commands aren’t executing, therefore making none of the rectangles show up on screen. If you’ve encountered this, maybe you could help me out. All the imports are there, as the other GObjects show up.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s