Due date: Sunday, September 1 @ 11:59PM PDT
None
This assignment is an introduction to Classes and ArrayLists in Java. In this assignment, you will create two new classes from scratch with several instance variables and methods.
Simple Reddit [Gradescope, 100 points]
- Implementation [90 points]
- Testing [10 points]
Reddit is a popular social news aggregation, content rating, and discussion website. Users submit content to the site such as links, text posts, images, and videos, which are then voted up or down by other members.
In this programming assignment, we will create a simplified version of Reddit, where users can create, upvote, and downvote posts. In order to do so, we will create two files: Post.java
and User.java
to represent and to implement the functionalities of these objects.
On Reddit, you can either create a post in some community (subreddit), or comment on someone's existing post. In this write-up, we will refer to them as "original posts" and "comments" to avoid confusion with a generic Post
object. In our program, both are considered to be a Post
, with some differences in instance variable values to differentiate them. The Post
instance variables and methods are described below.
Warning
Do NOT add additional imports other than
java.util.ArrayList
.
public class Post {
// ...
private String title;
private String content;
private Post replyTo;
private User author;
private int upvoteCount;
private int downvoteCount;
// ...
}
String title
- the title of a Reddit post. If this post is a comment, thentitle
should benull
.title
should be non-null if this post is an original post.String content
- the content of a Reddit post. If this post is a comment,content
is the comment a User made.Post replyTo
- the original post or comment thisPost
is replying to. If thisPost
is an original post,replyTo
should benull
.replyTo
should be non-null if this post is a comment.User author
- the author of thisPost
.int upvoteCount
- the number of upvotes of thisPost
.int downvoteCount
- the number of downvotes of thisPost
.
public class Post {
// ...
public Post(String title, String content, User author);
public Post(String content, Post replyTo, User author);
public String getTitle();
public Post getReplyTo();
public User getAuthor();
public int getUpvoteCount();
public int getDownvoteCount();
public void updateUpvoteCount(boolean isIncrement);
public void updateDownvoteCount(boolean isIncrement);
public ArrayList<Post> getThread();
public String toString();
// ...
}
public Post(String title, String content, User author)
- The constructor for initializing an original post.
- Initialize the instance variables with the values from parameters.
- Set
upvoteCount
to 1. (The author upvotes their own post by default.) SetdownvoteCount
to 0. - In the constructor, you will only need to initialize the class instance variables.
- You may also assume that after creating a Post, a separate and correct call to addPost will be used to add the post to the User.
public Post(String content, Post replyTo, User author)
- The constructor for initializing a comment.
- Initialize the instance variables with the values from parameters.
- Set
upvoteCount
to 1. SetdownvoteCount
to 0.
public String getTitle()
- Return the title of this
Post
.
public Post getReplyTo()
- Return the
Post
of that thisPost
is replying to.
public User getAuthor()
- Return the author of this
Post
.
public int getUpvoteCount()
- Return the number of upvotes of this
Post
.
public int getDownvoteCount()
- Return the number of downvotes of this
Post
.
public void updateUpvoteCount(boolean isIncrement)
- Increment
upvoteCount
by 1 ifisIncrement
istrue
, otherwise decrementupvoteCount
by 1. - You may assume that we will not call
updateUpvoteCount
that would result in a negativeupvoteCount
.
public void updateDownvoteCount(boolean isIncrement)
- Increment
downvoteCount
by 1 ifisIncrement
istrue
, otherwise decrementdownvoteCount
by 1. - You may assume that we will not call
updateDownvoteCount
that would result in a negativedownvoteCount
.
public ArrayList<Post> getThread()
- Return a list of posts in the current thread, starting with the original post of this post and ending with
this
post. - The original post should be the first item in the list, followed by its comment, then its comment's comment, etc. The last item in the list should be
this
post.- For example, if
Post
P1 is an original post, P2 is a reply (comment) to P1, and P3 is a reply to P2. ThenP3.getThread()
should return[P1, P2, P3]
. Even if P1 has more than one reply comment, callingP3.getThread()
should still return[P1, P2, P3]
. Likewise,P3.getThread()
should return[P1, P2, P3]
even if there are replies to P3 or if P2 has replies other than P3. - If
Post
P1 is an original post, thenP1.getThread()
should return[P1]
since there are no higher-level threads.
- For example, if
- You can implement this method either recursively or iteratively.
public String toString()
- Return a String representation of this
Post
. - If this
Post
is an original post, thetoString()
should have the following format (\t
is a tab):Example:[upvoteCount|downvoteCount]\t Title \t Content
[1|0] Title of Original Post Content of original post
- If this Post is a comment, the
toString()
should have the following format (\t
is a tab):Example:[upvoteCount|downvoteCount]\t Content
[2|0] Content of a comment / reply
- Feel free to use the following format Strings with
String.format()
in your code:String TO_STRING_POST_FORMAT = "[%d|%d]\t%s\n\t%s"; String TO_STRING_COMMENT_FORMAT = "[%d|%d]\t%s";
A User
object represents a user in our simplified Reddit program. The User
instance variables and methods are described below.
Warning
Do NOT add additional imports other than
java.util.ArrayList
.
public class User {
// ...
private int karma;
private String username;
private ArrayList<Post> posts;
private ArrayList<Post> upvoted;
private ArrayList<Post> downvoted;
// ...
}
String username
- thisUser
's usernameint karma
- On Reddit, karma is like a user's score or reputation.
- In our program, karma is calculated as (the total number of upvotes) - (the total number of downvotes) a user has. This value can be negative.
ArrayList<Post> posts
- A list of posts this
User
has made, including original posts and comments.
- A list of posts this
ArrayList<Post> upvoted
- A list of other users' posts that this
User
upvoted.
- A list of other users' posts that this
ArrayList<Post> downvoted
- A list of other users' posts that this
User
downvoted.
- A list of other users' posts that this
public class User {
// ...
public User(String username);
public void addPost(Post post);
public void updateKarma();
public int getKarma();
public void upvote(Post post);
public void downvote(Post post);
public Post getTopPost();
public Post getTopComment();
public ArrayList<Post> getPosts();
public String toString();
// ...
}
public User(String username)
- The constructor for a
User
. - Initialize
username
to the parameter value and all ArrayLists to empty ArrayLists. Initializekarma
to 0.
public void addPost(Post post)
- Add a
Post
to end of thisUser
'sposts
. - If
post
isnull
, do not add it toposts
. - Update this
User
's karma by callingupdateKarma()
. - You may assume that we will only call addPost on the User that has authored the post.
- You may also assume that after creating a Post, a separate and correct call to addPost will be used to add the post to the User.
public void updateKarma()
- Update this
User
's karma by going through the user'sposts
and summing upupvoteCount
$-$ downvoteCount
for each post.
public int getKarma()
- Return the current value of
karma
.
public void upvote(Post post)
- If
post
is null, return immediately. - If
post
has already been upvoted by theUser
or if the author ofpost
is the current user, return immediately as well. - If
post
was originally downvoted by theUser
, remove it fromdownvoted
and updatepost
'sdownvoteCount
accordingly. - Add
post
toupvoted
, updatepost
'supvoteCount
accordingly. - Please add post to the end of the appropriate ArrayList when adding a post.
- Update the author's karma value. Make sure to update the karma of the user that authored the post, not the user that upvoted/downvoted the post. If you are passing the downvote tests but not all the upvote tests, please make sure you have updated the user karma correctly after upvote.
public void downvote(Post post)
- Similar to
upvote
. - If
post
is null, return immediately. - If
post
has already been downvoted by theUser
or if the author ofpost
is the current user, return immediately as well. - If
post
was originally upvoted by theUser
, remove it fromupvoted
and updatepost
'supvoteCount
accordingly. - Add
post
todownvoted
, updatepost
'sdownvoteCount
accordingly. - Please add post to the end of the appropriate ArrayList when adding a post.
- Update the author's karma value. Make sure to update the karma of the user that authored the post, not the user that upvoted/downvoted the post.
public Post getTopPost()
- Return the top original post determined by the greatest (
upvoteCount
$-$ downvoteCount
) value. - If no such original post exists, return
null
. - If there is a tie, return the first original post
Post
in the tie. First meaning the lowest-indexedPost
inposts
.
public Post getTopComment()
- Return the top comment determined by the greatest (
upvoteCount
$-$ downvoteCount
) value. - If no such comment exists, return
null
. - If there is a tie, return the first comment
Post
in the tie. First meaning the lowest-indexedPost
inposts
.
public ArrayList<Post> getPosts()
- Return the list of posts (original posts and comments) made by the
User
.
public String toString()
- Return a String representation of this
User
. - Format:
u/username Karma: #
- Example:
u/CSE11Student Karma: 2
- Feel free to use the following format String:
"u/%s Karma: %d"
For this programming assignment, you will also be graded on your demonstration of testing your code.
Create a file called Tester.java
. In the main
method, create instances of User
and Post
, call the methods you would like to test, and use print statements to verify your code's correctness. For example, the following code tests the constructors, toString()
, addPost()
, getTopPost()
, and getTopComment()
:
public class Tester {
public static void main(String[] args) {
User u1 = new User("CSE11Student");
Post p1 = new Post("Title", "Content", u1);
Post c1 = new Post("Comment", p1, u1);
System.out.println(u1);
System.out.println(p1);
System.out.println(c1);
u1.addPost(p1);
u1.addPost(c1);
System.out.println(u1.getTopPost());
System.out.println(u1.getTopComment());
}
}
Running the tester produces the expected results:
$ javac Post.java User.java Tester.java
$ java Tester
u/CSE11Student Karma: 0
[1|0] Title
Content
[1|0] Comment
[1|0] Title
Content
[1|0] Comment
To receive full credit for this section, make sure your main method tests at least 75% of both methods and lines of your code. You will be able to see your code coverage under "Coverage" on the Gradescope autograder. You'll get partial credits if your coverage is between 55% and 75%. No points will be awarded if your coverage is below 55%.
Submit the following file(s) to Gradescope by Sunday, September 1 @ 11:59PM PDT.
- Post.java
- User.java
- Tester.java
Even if your code does not pass all the tests, you will still be able to submit your work to receive partial points for the tests that you passed. Make sure your code compiles in order to receive partial credit.
- Correctness [90 points] You will earn points based on the autograder tests that your code passes. If the autograder tests are not able to run (e.g., your code does not compile, or it does not match the specifications in this writeup), you may not earn any credit.
- Public Tests [45 points] These are tests of which you can always see the results after submission.
- Hidden Tests [45 points] These are tests not visible to you until grades are published after the deadline.
- Testing [10 points] You will earn full points if your main method tests more than 75% of the lines and methods of
User
andPost
. - The prototypes of the classes
User
andPost
are correct, which means that there are no other methods besides the required methods above and helper methods, and there are no other fields besides the required fields above and constants. Remember that you may create any number of additional helper methods and constants (as fields), but helper methods must beprivate
, and constants must bestatic final
fields of primitive or String types. Incorrect prototypes will result in a 0. - You are only allowed to call methods in the classes
User
andPost
, and in library classes listed below. Calling methods in other library classes will result in a 0.java.lang.Integer
java.lang.Object
java.lang.String
java.lang.StringBuilder
java.util.ArrayList
java.util.Iterator
java.util.ListIterator
- You are only allowed to access fields (i.e. class variables and instance variables) in the classes
User
andPost
, and constants. Accessing fields in other library classes that are not constants will result in a 0. - You may use any library methods and fields in
Tester.java
, except for some methods that may undermine security, such as file I/O, file descriptor I/O, shell command execution, network I/O, access modification, etc. Exceptions will be thrown in the coverage test if you call library methods related to these functions.