Lab 10: Designing and Implementing a Social Network

FAQ - to be created when students start asking questions

Goals

After the lab, you should be proficient at

  1. creating and testing your own classes from a specification
  2. developing a larger program (set of classes) to solve a data management problem

Linux

Instead of creating a lab10 directory, copy the entire /home/courses/cs111/handouts/lab10 directory and all its contents to your labs directory.

REMINDER: Style

This is by far the biggest program we have written this semester. Make sure you adhere to good programming practices, such as putting code in functions and using constants, as appropriate. Also, make sure you comment your methods.

Objective: Creating a Social Network

For this lab, you'll use "real" program names instead of the "lab10.x.py" names we typically use.

Problem: Create FaceSpace, a program to manage social networks. A social network is a set of users, some of whom are friends. You will keep track of the users and allow users to add friends to their social network.

Testing (15 pts)

Before we even discuss the classes, we want to make sure that you know that you need to TEST!

Test your classes before moving on to the driver. You'll need to comment out the calls to the test function(s) when you run the driver program or you'll need to use the if __name__ == "__main__" code segment that you've seen in example programs. Save the output from executing the test function in an appropriately named file.

Writing tests helps you isolate problems and debug more easily. If you were to find a problem when you use the user interface, you won't know if there is a problem with your class or with the user interface's use of the class.

Best practices: Write the constructor and string representation/print method for each class. Then test them in a test function. Then, write another method and test it. Continue in this way.

If you ask us for help and have not sufficiently tested the other methods you already wrote, we will not help until after you have tested and (perhaps) debugged other methods. Your programs are becoming large, more complex, and more difficult to debug if you don't test each part, individually.

Summary of Classes

You can give these classes different names, as long as they make sense.

Organization: The classes should be in their own modules. The driver program will import the SocialNetwork class, and the SocialNetwork will import the Person class. Look at the files that you copied for templates.

Test each class in a function as you go. Every time you write a new method, test it and verify its correctness.

The following summarizes the classes and their data and functionality. Longer descriptions for some methods are after the summaries.

Person (20)

This class represents an individual in a social network. You'll need to use this class in your other classes. You can rename it and add more methods if you want.

Data:

Functionality:

Social Network (35)

Data:

Functionality:

The non-trivial methods are described in more detail below.

String Representation

The string you create should represent the SocialNetwork but does not need to look as "pretty" as the display method, described later. For example, you could just form a string that contains all the Persons in the social network. (You may want to have some order for the Persons so that it's easier to find them.)

Adding People to the Network, from a File

This method will take as input the name of a file and process the file, which contains people that should be added to the social network. (Note that the people do not have friends yet.) To make your life easier, you should leverage a method you already wrote.

An example data file is below:

num_of_users
user_id
name
network
user_id
name
network
...

Test Data

I have provided a number of test files that should be in your data-files directory of your lab10 directory.

The names of the files are named so that you'll know which is the "people" file and which is the "connections" file. For example, the smallest file is "simple.txt", which contains the people, and "simple_connections.txt", which contains the connections.

Adding Connections to the Network, from a File

This method will take as input the name of a file and process the file, which contains the connections between people in the social network. Each line of the file contains two ids and represents the people with those ids are friends.

An example data file is below:

user_id user_id
user_id user_id
...

Displaying the Social Network

Display the people in the network in a pretty, sorted way. For example:

ID     Name                 Network         Num Friends
------------------------------------------------------------
1      George Clooney       Hollywood       7         
10     Jennifer Aniston     Hollywood       3         
2      Don Cheadle          Hollywood       4         
3      Matt Damon           Hollywood       6         
4      Ben Affleck          Hollywood       4         
5      Julia Roberts        Hollywood       4         
6      Bernie Mac           Hollywood       5         
7      Casey Affleck        Hollywood       4         
8      Brad Pitt            Hollywood       4         
9      Angelina Jolie       Hollywood       1  

Exporting the Social Network to a Dot File

This method will write your social network to a dot file, which you can then convert into an image that you can view.

If you're not using the SocialNetwork template I provided in the handouts directory, add the following method to your class:

    def exportDotFile(self, outname):
        "Write a dot graph representing this social network to the file named by outname"

        graph = Dot()
        graph.set_type("graph")
        graph.set_name("SocialNetwork")

        userids = self.getUserIDs()
        userids.sort()

        already_linked = {}
        
        for userid in userids:
           person = self.getPerson(userid)

           label = makeNodeLabel(person)

           for friend in person.getFriends():

               link = friend.getName() + "." + person.getName()

               if link not in already_linked: 
                   edge = Edge( label , makeNodeLabel(friend) )
                   graph.add_edge(edge)
                   already_linked[person.getName() + "." + friend.getName()] = 1

        graph.write(outname)

Note the methods used in this method. If you used different names in your class, you'll need to modify this method to use the appropriate methods.

To use this method, you must include this statement at the top of your class: from pydot import *

If you're not using the template I provided, add the following function inside the module that contains your class. Note: this is not a method. Also note the Person method names/API it assumes.

def makeNodeLabel(person):
    "Helper function that creates a label for a node in the Dot file"
    return person.getID() + ". " + person.getName()

Exporting the people to a file

After updating your social network, you may want to save the network to a file so that you can use it later. There are two parts to the network: the people/users and the connections between the people.

This method should write the people in the social network to a file, named by the parameter to this method. The format of the file is as seen above. A good test of this function is to write out the social network (that you did not update) to another file and then check if the files match.

Exporting the connections to a file

This method handles writing the connections to a file. If you're not using the template, copy this method. Note the assumptions about the method names.

   def exportConnections(self, outname):
        """Write the connections to a file, named by outname, in the
        appropriate format."""
        connFile = file(outname, "w")

        userids = self.getUserIDs()
        userids.sort()

        # don't want any duplicate connections in the file, so keep track of
        # what we've written to the file
        connections = {}

        for id in userids:
            person = self.getPerson(id)

            for friend in person.getFriends():
                connection = person.getID() + " " + friend.getID()
                reverse = friend.getID() + " " + person.getID()

                if connection not in connections and reverse not in connections:
                    connFile.write(connection + "\n")
                    connections[connection] = 1
                
        connFile.close()

FaceSpace Driver Program (25)

This program maintains a SocialNetwork object and provides an interface for users to manage the social network. If you developed the Person and SocialNetwork classes correctly, the majority of this program should be getting input from the user and calling Person and SocialNetwork methods.

Part 0: Welcome Screen (1)

Let the user know what program they're running.

Part 1: Reading in Your Social Network (5)

Your program should allow the user to enter the names of the people file and the connections file as command-line arguments. The program will attempt to call the appropriate methods to read those files to initialize the social network. If you do not give command-line arguments, the program will attempt to read the default data-files/default.txt and data-files/default_friends.txt, which are currently just copies of the 'hollywood' social network.

Part 2: The User Menu (15)

Your program will repeatedly prompt the user to select an option and then execute the option if it's valid. If the option isn't valid, your program should reprompt for a valid option.

Your user menu should allow the user to execute each of the following options:

Example user menu:

Select one of the following options:
        (D)isplay the social network
        (V)iew a person in the social network
        Add (P)eople to the social network from a file
        Add (C)onnections to the social network from a file
        Add a (U)ser to the social network
        Add a pair of (F)riends to the social network
        E(X)port the social network
        (Q)uit the program

Which option do you want? 

Allow the user to enter lower case or capital letters for options. For example, either "D" or "d" is a valid choice for displaying the social network.

HINT: You could write the option validation with a bunch of if statements. Or, you could create a list of valid options and check if the user's selection is in that list.

Use Cases: Example Interactions with the User

Viewing a person's information:
Which option do you want? v

What is the id of the person you want to view? 1
1: John Doe in W & L has 2 friends
Which option do you want? v

What is the id of the person you want to view? a
There is no person with id a
Invalid options and then exporting the network to a dot file:
Which option do you want? s
s is not a valid option.
Select an option: t
t is not a valid option.
Select an option: r
r is not a valid option.
Select an option: x

You can export the social network to one of three types of files:
   1.) dot file
   2.) people file
   3.) connections file
Which type of file do you want? 1

What is the name of the file that you want to export the social network to? graphs/test.dot
Wrote the social network to the file graphs/test.dot
Adding a user and Displaying the Updated Network
Which option do you want? u

What is the id of the user? 4
What is the name of the user? Henry the Eighth
What is the user's network? Royalty

Henry the Eighth has been added to the network.

*************************************
Select one of the following options:
        (D)isplay the social network
        (V)iew a person in the social network
        Add (P)eople to the social network from a file
        Add (C)onnections to the social network from a file
        Add a (U)ser to the social network
        Add a pair of (F)riends to the social network
        E(X)port the social network
        (Q)uit the program
Which option do you want? d

ID     Name                 Network         Num Friends
------------------------------------------------------------
1      John Doe             W & L           2         
2      Jane Smith           W & L           2         
3      James Jones          W & L           2         
4      Henry the Eighth     Royalty         0  
Adding a connection between people and displaying the updated network
Which option do you want? f

What is the userid of the first friend? 3 
What is the userid of the second friend? 4

Added the connection between 3 and 4

*************************************
Select one of the following options:
        (D)isplay the social network
        (V)iew a person in the social network
        Add (P)eople to the social network from a file
        Add (C)onnections to the social network from a file
        Add a (U)ser to the social network
        Add a pair of (F)riends to the social network
        E(X)port the social network
        (Q)uit the program
Which option do you want? d

ID     Name                 Network         Num Friends
------------------------------------------------------------
1      John Doe             W & L           2         
2      Jane Smith           W & L           2         
3      James Jones          W & L           3         
4      Henry the Eighth     Royalty         1         

Part 3: Storing the Social Network Before Quitting (4)

Before exiting the program when the user selects the quit option, you should save the social network to the files specified on the command-line/the default files, as appropriate.

Output from FaceSpace

Run FaceSpace in Idle (which means that it will not test your command-line arguments) and save the output, as usual, in an appropriately named file.

Final Results

You'll show the graphs of the social network for one small (~25 people) and one medium (~50 people) social network on a web page. You can use the sets of data files I gave you or you can create your own social networks.

Using dot

I provided a method that writes your social network into a .dot file. To view the social network, we need to translate that .dot file into a graph. The dot command does that work for us. We can create the graph into an image file (e.g., png) or into a PDF file.

The general format of the command is:
dot -T<filetype> -o <outputfilename> <dotfile>

For example, to generate a PDF file for the file network.dot, I would execute the command:
dot -Tpdf -o network.pdf network.dot

Or, to generate a PNG file for the same network.dot, I would execute the command:
dot -Tpng -o network.png network.dot

To view PDFs, you can use the gv command and to view PNG files, you can use the xv command.

An example image from the Hollywood social network:

Objective: Creating a New Web Page (5 pts)

  1. Go into your public_html directory.
  2. Copy your lab9.html file into a file called lab10.html in the public_html directory.
  3. Copy the PNG graphs you created for the hollywood and one medium social network in the last part into the public_html directory.
  4. Modify the Lab 10 web page to have an appropriate, title, header, and information.
  5. Modify your Lab 10 web page to display the two images of social networks you created earlier.

    You may want to shrink the image displayed using the width or height attributes and a size, in pixels. For example:
    <img src="social_network.png" width="500">
    would make the image display 500 pixels wide and the height would change proportionally. If you right-click and "view image", the image will be its original size.

  6. Add text labeling each image separately.
  7. Note: you should not display the "old" images from the original pages. This page should just contain content about this week's lab.
  8. Modify your index.html page to link to your Lab 10 web page.

Extra Credit

Additional Functionality (up to 12 pts)

We discussed as a class some additional functionality that your classes may have. After you have completed the required functionality, you can add more functionality. (Which class should implement this functionality?) Some of your suggestions included

Additional Social Network Files (up to 5 pts)

Did you create social network files that you want to let others test? This includes the "people" file as well as the "connections" file. If so, mail it to me, and I will post in on the web page.

Finishing up: What to turn in for this lab

  1. IDLE and jEdit may create backup files with the "~" extension. Delete these files from your lab directory to save paper when you print.
  2. Copy your lab10 directory into the turnin directory. (Review the UNIX handout if you don't remember how to do that.)
  3. Remove the .pyc files from your directory.
  4. Use the printLab.sh command to create a file to print out. You should probably print from the labs directory. You may get a warning about the directory containing subdirectories. As long as you don't get an enscript error about unknown special escape, you should be okay.
  5. You can always view the output before you print it, using the gv command, such as
    gv lab10.ps

    Print the file using the lpr command introduced in the first lab.

Labs are due at the beginning of Friday's class. You should hand in the printed copy at the beginning of class, and the electronic version should be in the turnin directory before 1:20 p.m. on Friday.

Ask well before the deadline if you need help turning in your assignment!

Grading (100 pts)