Homework 7: PennPals - CIS 120 CIS 120 Homework 7: PennPals Homework 5: PennPals Computing’s core challenge is how not to make a mess of it. — Edsger W. Dijkstra Helpful Links Javadocs for server code (the same information can also be found in the javadoc comments above each method). This should be your first stop for any uncertainty about what a method does or what its arguments mean. CIS 120 Java style guide Frequently Asked Questions If you prefer to work locally (instead of in Codio), download the stub code and the client jar file, then follow the IntelliJ setup instructions. Overview This assignment involves building an internet chat server in Java. Your code will model the internal state of the server and handle communication with chat users. The key content for this assignment are Lectures 27-29 and Chapters 25 and 26 of the lecture notes, which we encourage you to study before getting to work. If you would like to start on the project early, you will need to watch/read the material ahead of the posted schedule. Here are some checkpoints for this assignment: Checkpoint 1 (Monday 11/8): Complete Task 1. Checkpoint 2 (Wednesday 11/10): Complete Task 2 with Lecture 27 (Generic Types and Collections) and 28 (Overriding, Equality) or Chapter 25 and 26. Checkpoint 3 (Friday 11/12): Complete Task 3 with Lecture 27 (Generic Types and Collections) and 29 (Enums, Iteration) or Chapter 25. Checkpoint 4 (Friday 11/12): Complete Task 4 with Lecture 27 (Generic Types and Collections) and 29 (Enums, Iteration) or Chapter 25. Checkpoint 5 (Monday 11/15): Complete Task 5 with Lecture 29 (Enums, Iteration) or Chapter 25. Checkpoint 6 (Tuesday 11/16): Complete Task 6. Task 1: Understanding the Problem Please familiarize yourself with the following terms and design principles for this assignment: Client An end user of a service. We will use “client” and “user” somewhat interchangeably. In this assignment, a client is a user who has connected to the server to chat with other users. Each client is assigned a unique integer ID when they sign in. This integer cannot be changed, and persists as long as the client is connected. If a client later reconnects, they will get a new integer ID. Each client has a nickname - a string that other users can see. A user can change their own nickname at any time. Server A computer system designed to provide a service to many connected clients at once. Channel A group of users who are connected to the server. Every channel has an owner - the user who created the channel. A user in a channel receives all messages sent to that channel after they join. A user in a channel can leave the channel at any time. After they leave, they will no longer get messages from that channel. A user connected to the server can be in any number of channels (including 0). Owner The owner of a channel can remove anyone from that channel (including themselves). If the owner leaves for any reason, the entire channel is removed. Channel Privacy A channel is either public or private. If it is public, any user who knows the name of the channel can join. If it is private, new users can only be added if the owner invites them - in which case they automatically join. Protocol A standardized set of instructions for communicating over the Internet by requesting and transmitting data. In this assignment, clients communicate with the server by sending commands that instruct the server to create new channels, send messages on channels, etc. We represent this communication protocol in the code base by using subclasses of an abstract class Command. NicknameCommand changes the sender’s nickname. CreateCommand creates a new channel with the sender as its owner. JoinCommand lets the sender join a public channel. InviteCommand adds a target user to a private channel owned by the sender. MessageCommand sends a message to all users in a specific channel. LeaveCommand lets the sender leave a channel they are in. KickCommand removes a target user from a private channel owned by the sender. At this point, it would be good to familiarize yourself with the definitions of the Command class and all of its subclasses in the file Command.java. Pay particular attention to the private instance variables of each class and the “getter” methods that provide access to this information. Task 2: Designing ServerModel In this task, you need to: Add necessary instance variables to ServerModel (javadocs) and initialize them in the constructor. Implement user models via the getUserId, getNickname, and getRegisteredUsers methods. Implement channel models via the getChannels, getUsersInChannel, and getOwner methods. Pass all tests in Task2Test.java. Document design choices and justifications in the Task 2 section of PLAN.txt. If you’re unsure what a method does or what its arguments mean, check the online Javadocs or the Javadoc comments above the method definition (it’s the same information, since the online Javadocs are generated from the comments). ServerModel Overview The ServerModel is responsible for processing all incoming Commands and keeping track of the server state. You will need to add data structures to track: All users connected to the server (their IDs and usernames) The channels that users are in Information on each channel, like its owner, members, etc. This is just the information that has to be stored in ServerModel - the way in which that information is stored is entirely up to you. Data Structure Choices You have three data structure options for this assignment: TreeSet, TreeMap, and LinkedList. Pick a data structure whose capabilities fit the nature of the information being stored. Some questions you can ask yourself to pick a data structure include: Are duplicate entries allowed? Is ordering important? What kind of relationship is being stored? You may only use these data structures from java.util. In particular, even though you may be familiar with classes such as HashSet, HashMap, or ArrayList from your past experience, you may not use them for this assignment. One of the goals of this assignment is for you to practice with working with these specific data structures. Do your best to avoid redundancy - having the same information in multiple places will make your life more difficult. You may change your mind later - you need to make a choice now to get started with this point of the assignment, but as you learn more about what you need to do, you might find that you want to change things up. It is normal to need to do this. At each step of this project, we with ask you to document your choices so that you can see how they evolve as you work through the material and add new features. Creating New Classes You might find it helpful to represent parts of the server state using new classes. You are not required to do so for this assignment, but if you do choose to create a new class, you should consider the following guidelines: Define the class in a new file and in the proper package You should define your custom class NewClass in a file named NewClass.java. Each custom class needs to have package org.cis120; at the top of the file. Override equals This is useful for testing, but also required if you use the class as elements of a TreeSet or as keys of a TreeMap. Checking if an equivalent instance of your class is already in a Collection requires equals, since it defines the conditions under which two instances are equal. If you don’t override equals, Java will use == by default, so two instances with the same values in their fields may be marked as “not equal”. Consider implementing the Comparable interface (javadocs) This is required if the class as elements of a TreeSet or as keys of a TreeMap, for reasons that are similar to the reasons to override equals. Since TreeSet and TreeMap are based on insertion into a BST, they need to be able to compare elements to each other and determine positioning. Add Javadoc comments All methods in the new class should have Javadoc comments to describe what they do. Task 3: Connections and Setting Nicknames This task is the first task where you need to start implementing methods that correspond to commands from the chat protocol. Each of these methods are defined in the ServerModel class and are called by a corresponding updateServerModel method of a subclass of Command. For this task, you need to: Implement registerUser, deregisterUser, and changeNickname Pass all tests in Task3Test.java Add your own unit tests for these methods in ServerModelTest. Think about situations that were not covered by Task3Test. Document any design changes made during this task in PLAN.txt. Hints: the isValidName helper method has been provided for you. You may also add additional helper methods to the ServerModel class, as long as they are marked private. What is a Broadcast? The server uses Broadcast objects to send information to one or more clients after processing a command. For example, when a client changes their nickname, everyone who can see that client should be notified of the change so that their client applications can display the new nickname. The Broadcast class constructor is marked private, so the only way to construct a Broadcast is via the following static methods: Broadcast.connected is used when a new client connects. Broadcast.disconnected is used when a client disconnects from the server. Broadcast.names is used when a client joins or is invited to a channel. Broadcast.error is used when it is not possible to complete a command for some reason Broadcast.okay is used when a CreateCommand, MessageCommand, LeaveCommand, or KickCommand executes successfully. More on that later. Please read the instructions for the next few tasks carefully - as well as the Javadocs for Broadcast - to ensure that you pass in the correct parameters when using these Broadcast objects. Task 4: Channels and Messages In this task, you should: Implement all parts of createChannel and joinChannel that don’t involve channel privacy Implement sendMessage and leaveChannel Check that you pass all tests in Task4Test.java Add your own unit tests for these methods in ServerModelTest. Think about situations that were not covered by Task4Test. Run the client application to try out your code for channel creation, joining channels, messaging, and leaving channels. Testing with the Client Application The chat server is now functional enough to try channel creation, joining channels, messaging, and leaving channels with hw07-client.jar (the client application). Running the Client in Codio Start the server with the menu. Launch a client instance with the menu. If you want multiple clients at once, click on the menu option once for each client. Click the “PennPals” option to open up a window to view the client. Running the Client Locally Start the server by running ServerMain.java. Launch a client instance by right-clicking on hw07-client.jar and clicking “Run”. If you need multiple instances of the client, you may need to open a command line (PowerShell for Windows, Terminal for macOS) and run java -jar
, where is replaced by the location of hw07-client.jar. If you’re not sure how to type the path manually, just drag the .jar from File Explorer/Finder to the command line window after typing java -jar Note: Using the client application is not a substitute for writing JUnit tests! Task 5: Channel Privacy In this task, you should: Add channel privacy to your server state, if you don’t have it already Modify createChannel to deal with creation of private channels Modify joinChannel to handle users trying to join private channels Implement inviteUser and kickUser Check that your code passes all provided test cases in Task5Test.java Add your own unit tests to ServerModelTest for these methods. Think about situations that were not covered by Task5Test. Try out these features using multiple instances of the client application Task 6: Refactoring You’ve completed all of the required features! Hooray! Now look for any redundant data, duplicate code, convoluted functions, or other issues that make your code less readable. Don’t be afraid to adjust some data structures, add helpers, and so on. If you are worried about breaking your code, make a zipfile for your current version, before making any modifications. However, this is the point where your unit tests will help: if you do introduce a bug while refactoring, a good test suite should immediate detect and help you isolate it. Make sure to document any changes you make in PLAN.txt (also check that it’s fully filled out), and double check that your code complies with our style guidelines. Submission Instructions As with previous assignments, you will be uploading only the following files: PLAN.txt src/main/java/org/cis120/ServerModel.java src/test/java/org/cis120/ServerModelTest.java Any additional classes you made If you are using Codio These files should be organized similar to above (with a src and test directory). The easiest option is to use the Zip Project menu item in Codio. Do not include any of the other provided files, since doing so may cause your submission to fail to compile. You can directly upload the zip produced by Codio into Gradescope. If you are using IntelliJ Gradescope allows you to easily drag-and-drop files into it, or you can click “Browse” in Gradescope to open up a file browser on your computer to select files. Upload only the files listed above. Grading Breakdown Automated testing (85%) Task 3: Connections and Nicknames (30%) Task 4: Channels and Messages (25%) Task 5: Invite-Only Channels (20%) Model state encapsulation (5%) Style (5%) Manual grading (15%) PLAN.txt (5%) Server model design (5%) Quality of your testing (5%) You have three free submissions for this assignment. Each additional submission will cost you five points from your final score. Task 1: Understanding the Problem Client Server Channel Protocol Task 2: Designing ServerModel ServerModel Overview Data Structure Choices Task 3: Connections and Setting Nicknames What is a Broadcast? Task 4: Channels and Messages Testing with the Client Application Running the Client in Codio Running the Client Locally Task 5: Channel Privacy Task 6: Refactoring Submission Instructions If you are using Codio If you are using IntelliJ Grading Breakdown