diff --git a/pom.xml b/pom.xml index c7bfb79..40925a8 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ edu.unq twitter-modelo - 1.0-SNAPSHOT + 1.0.0 jar edu.unq twitter-modelo diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..027e985 --- /dev/null +++ b/readme.md @@ -0,0 +1,220 @@ +# UNQ » UIs » Dominio » Twitter + +Construcción de Interfaces de Usuario, Universidad Nacional de Quilmes. + +## TP 2023s1 + +### Dependencia + +Agregar el repositorio: + +```xml + + + jitpack.io + https://jitpack.io + + +``` + +Agregar la dependencia: + +```xml + + edu.unq + twitter-modelo + 1.0.0 + +``` + +### Como usar el modelo + + +```kotlin + +val twitterSystem = initTwitterSystem() + +``` + +### Interfaz de uso + +```kotlin +package org.unq + +class TwitterSystem { + + val users = mutableListOf() + val tweets = mutableListOf() + + /** + * Crea un usuario nuevo. + * @throws UserException + * El email se encuentra repetido. + * El username se encuentra repetido. + * + */ + fun addNewUser(user: DraftUser): User + + /** + * Crea un nuevo tweet. + * @throws UserException + * si el userId no existe. + */ + fun addNewTweet(tweet: DraftTweet): Tweet + + /** + * Devuelve el tweet con el id de tweetId. + * + * @throws UserException + * si el userId no existe. + * @throws TweetException + * si el tweetId no existe. + * si el tweetId pertenece al mismo usuario. + */ + fun addReTweet(tweet: DraftReTweet): Tweet + + /** + * Devuelve el tweet con el id de tweetId. + * + * @throws UserException + * si el userId no existe. + * @throws TweetException + * si el tweetId no existe. + */ + fun replyTweet(tweet: DraftReplyTweet): Tweet + + /** + * Devuelve el tweet con el id de tweetId. + * + * @throws UserException + * si el userId no existe. + * @throws TweetException + * si el tweetId no existe. + */ + fun addLike(tweetId: String, userId: String): Tweet + + /** + * Devuelve al usuario con el id userId + * + * @throws UserException + * si el userId o el userToFollowingId no existe. + */ + fun toggleFollow(userId: String, userToFollowingId: String): User + + /** + * Devuelve la lista de tweets donde el content contenga el `text` + */ + fun search(text: String): List + + /** + * Devuelve una lista de tweets de los usuarios que el userId sigue + * @throws UserException + * si el userId no existe. + */ + fun getFollowingTweets(userId: String): List + + /** + * Devuelve los usuarios con mas seguidores que no siga el usuario con el userId + * @throws UserException + * si el userId no existe. + */ + fun getUsersToFollow(userId: String): List + + /** + * Devuelve los post que tengan mas likes + */ + fun getTrendingTopics(): List + + /** + * Devuelve el usuario con el userId + * @throws UserException + * si el userId no existe. + */ + fun getUser(userId: String): User + + /** + * Devuelve el tweet con el tweetId + * @throws TweetException + * si el tweetId no existe. + */ + fun getTweet(tweetId: String): Tweet +} +``` + +### Clases + +```Kotlin + +class User( + val id: String, + val username: String, + var email: String, + var password: String, + var image: String, + var backgroundImage: String, + val following: MutableList = mutableListOf(), + val followers: MutableList = mutableListOf() +) + +open class Tweet( + val id: String, + val type: TweetType, + val user: User, + val content: String, + val date: LocalDateTime = LocalDateTime.now(), + val replies: MutableList = mutableListOf() , + val reTweets: MutableList = mutableListOf(), + val likes: MutableList = mutableListOf(), +) + +open class TweetType(val tweet: Tweet?, val image: String?) { + open fun isReTweet(): Boolean + open fun isReplayTweet(): Boolean + open fun isNormalTweet(): Boolean +} + +class ReTweet(tweet: Tweet) : TweetType(tweet, null) + +class ReplayTweet(image: String?, tweet: Tweet): TweetType(tweet, image) + +class NormalTweet(image: String?): TweetType(null, image) + +``` + +## Información + +* TODA interaccion tiene que pasar por TiktokSystem (con la interfaz definida previamente). + +* El TiktokSystem es el encargado de setear los ids de cada elemento que se agrega el sistema. + * Para simplificar se utilizan objetos draft + +```kotlin +class DraftUser( + val username: String, + val email: String, + val password: String, + val image: String, + val backgroundImage: String +) + +class DraftTweet( + val userId: String, + val content: String, + val image: String?, + val date: LocalDateTime = LocalDateTime.now() +) + +class DraftReTweet( + val userId: String, + val tweetId: String, + val content: String, + val date: LocalDateTime = LocalDateTime.now() +) +class DraftReplyTweet ( + val userId: String, + val tweetId: String, + val content: String, + val image: String?, + val date: LocalDateTime = LocalDateTime.now() +) +``` diff --git a/src/main/kotlin/org/unq/Data.kt b/src/main/kotlin/org/unq/Data.kt index a10fe33..1a7f3ae 100644 --- a/src/main/kotlin/org/unq/Data.kt +++ b/src/main/kotlin/org/unq/Data.kt @@ -1041,7 +1041,7 @@ private fun addRetweets(twitterSystem: TwitterSystem) { .filter { it.user != user } .forEach { twitterSystem.addReTweet( - ReTweetDraft(user.id, it.id, getRandomElement(contents), getRandomDate(it.date)) + DraftReTweet(user.id, it.id, getRandomElement(contents), getRandomDate(it.date)) ) } } @@ -1052,7 +1052,7 @@ private fun addRepliesWithImage(twitterSystem: TwitterSystem) { getRandomList(twitterSystem.tweets, 5) .forEach { twitterSystem.replyTweet( - ReplyTweetDraft(user.id, it.id, getRandomElement(contents), getRandomElement(tweetImages), getRandomDate(it.date)) + DraftReplyTweet(user.id, it.id, getRandomElement(contents), getRandomElement(tweetImages), getRandomDate(it.date)) ) } } @@ -1063,7 +1063,7 @@ private fun addRepliesWithoutImage(twitterSystem: TwitterSystem) { getRandomList(twitterSystem.tweets, 5) .forEach { twitterSystem.replyTweet( - ReplyTweetDraft(user.id, it.id, getRandomElement(contents), null, getRandomDate(it.date)) + DraftReplyTweet(user.id, it.id, getRandomElement(contents), null, getRandomDate(it.date)) ) } } diff --git a/src/main/kotlin/org/unq/Drafts.kt b/src/main/kotlin/org/unq/Drafts.kt index a869d3a..d0fc9fd 100644 --- a/src/main/kotlin/org/unq/Drafts.kt +++ b/src/main/kotlin/org/unq/Drafts.kt @@ -17,13 +17,13 @@ class DraftTweet( val date: LocalDateTime = LocalDateTime.now() ) -class ReTweetDraft( +class DraftReTweet( val userId: String, val tweetId: String, val content: String, val date: LocalDateTime = LocalDateTime.now() ) -class ReplyTweetDraft ( +class DraftReplyTweet ( val userId: String, val tweetId: String, val content: String, diff --git a/src/main/kotlin/org/unq/TwitterSystem.kt b/src/main/kotlin/org/unq/TwitterSystem.kt index ef58a16..b8d8597 100644 --- a/src/main/kotlin/org/unq/TwitterSystem.kt +++ b/src/main/kotlin/org/unq/TwitterSystem.kt @@ -5,7 +5,13 @@ class TwitterSystem { val users = mutableListOf() val tweets = mutableListOf() - // Devuelve el usuario nuevo o excepción si el username o el email no estan disponibles. + /** + * Crea un usuario nuevo. + * @throws UserException + * El email se encuentra repetido. + * El username se encuentra repetido. + * + */ fun addNewUser(user: DraftUser): User { users.forEach { if (it.username == user.username) throw UserException("Username is token") @@ -16,7 +22,11 @@ class TwitterSystem { return newUser } - // Devuelve el tweet nuevo o una excepcion si el usuario no existe. + /** + * Crea un nuevo tweet. + * @throws UserException + * si el userId del draftTweet no existe. + */ fun addNewTweet(tweet: DraftTweet): Tweet { val user = getUser(tweet.userId) val newTweet = Tweet( @@ -30,8 +40,16 @@ class TwitterSystem { return newTweet } - // Devuelve el tweet al que diste retweet o excepcion si el usuario o el tweet no existen - fun addReTweet(tweet: ReTweetDraft): Tweet { + /** + * Devuelve el tweet con el id de tweetId + * + * @throws UserException + * si el userId del DraftReTweet no existe. + * @throws TweetException + * si el tweetId no existe. + * si el tweetId pertenece al mismo usuario. + */ + fun addReTweet(tweet: DraftReTweet): Tweet { val user = getUser(tweet.userId) val originTweet = getTweet(tweet.tweetId) if (originTweet.user == user) throw TweetException("Can not retweet your own tweet") @@ -47,8 +65,15 @@ class TwitterSystem { return originTweet } - // Devuelve el tweet al que diste retweet o excepcion si el usuario o el tweet no existen - fun replyTweet(tweet: ReplyTweetDraft): Tweet { + /** + * Devuelve el tweet con el id de tweetId + * + * @throws UserException + * si el userId del DraftReplyTweet no existe. + * @throws TweetException + * si el tweetId no existe. + */ + fun replyTweet(tweet: DraftReplyTweet): Tweet { val user = getUser(tweet.userId) val originTweet = getTweet(tweet.tweetId) val newTweet = Tweet( @@ -63,7 +88,14 @@ class TwitterSystem { return originTweet } - // Devuelve el tweet al que diste like o excepcion si el usuario o el tweet no existen + /** + * Devuelve el tweet con el id de tweetId + * + * @throws UserException + * si el userId no existe. + * @throws TweetException + * si el tweetId no existe. + */ fun addLike(tweetId: String, userId: String): Tweet { val user = getUser(userId) val originTweet = getTweet(tweetId) @@ -71,7 +103,12 @@ class TwitterSystem { return originTweet } - // Devuelve al primer usuario o excepcion si alguno de los dos usuarios no existen + /** + * Devuelve al usuario con el id userId + * + * @throws UserException + * si el userId o el userToFollowingId no existe. + */ fun toggleFollow(userId: String, userToFollowingId: String): User { val user = getUser(userId) val userToFollow = getUser(userToFollowingId) @@ -89,18 +126,28 @@ class TwitterSystem { return user } - // Devuelve la lista de tweets que el contenido matche con el texto buscado. + /** + * Devuelve la lista de tweets donde el content contenga el `text` + */ fun search(text: String): List { return tweets.filter { it.content.contains(text, true) } } - // Devuelve una lista de tweets de los usuarios que el userId sigue o una excepcion si este no existe. + /** + * Devuelve una lista de tweets de los usuarios que el userId sigue + * @throws UserException + * si el userId no existe. + */ fun getFollowingTweets(userId: String): List { val user = getUser(userId) return tweets.filter { user.following.contains(it.user) }.sortedBy { it.date } } - // Devuelve los usuarios con mas seguidores que no siga el usuario pasado o una excepcion si el usuario no existe + /** + * Devuelve los usuarios con mas seguidores que no siga el usuario con el userId + * @throws UserException + * si el userId no existe. + */ fun getUsersToFollow(userId: String): List { val user = getUser(userId) val allUsers = users.sortedBy { it.followers.size }.toMutableList() @@ -108,17 +155,27 @@ class TwitterSystem { return allUsers.take(10) } - // Devuelve los post que tengan mas likes + /** + * Devuelve los post que tengan mas likes + */ fun getTrendingTopics(): List { return tweets.sortedByDescending { it.likes.size }.take(10).sortedBy { it.date } } - // Devuelve el usuario o una excepcion si este no se encuentra + /** + * Devuelve el usuario con el userId + * @throws UserException + * si el userId no existe. + */ fun getUser(userId: String): User { return users.find { it.id == userId } ?: throw UserException("Not found user id") } - // Devuelve un tweet o una excepcion si este no se encuentra + /** + * Devuelve el tweet con el tweetId + * @throws TweetException + * si el tweetId no existe. + */ fun getTweet(tweetId: String): Tweet { return tweets.find { it.id == tweetId } ?: throw TweetException("Not found user id") } diff --git a/src/test/kotlin/org/unq/TwitterSystemTest.kt b/src/test/kotlin/org/unq/TwitterSystemTest.kt index f817026..7abedae 100644 --- a/src/test/kotlin/org/unq/TwitterSystemTest.kt +++ b/src/test/kotlin/org/unq/TwitterSystemTest.kt @@ -87,21 +87,21 @@ class TwitterSystemTest { twitterSystem.addNewUser(userDraft) twitterSystem.addNewUser(userDraft2) val tweetDraft = DraftTweet("u_1", "content", "image", LocalDateTime.now()) - val reTweetDraft = ReTweetDraft("u_2", "t_1", "content1", LocalDateTime.now()) + val draftReTweet = DraftReTweet("u_2", "t_1", "content1", LocalDateTime.now()) twitterSystem.addNewTweet(tweetDraft) assertEquals(twitterSystem.tweets.size, 1) val tweet = twitterSystem.tweets[0] assertEquals(tweet.reTweets.size, 0) - twitterSystem.addReTweet(reTweetDraft) + twitterSystem.addReTweet(draftReTweet) assertEquals(twitterSystem.tweets.size, 2) assertEquals(tweet.reTweets.size, 1) val reTweet = twitterSystem.tweets[1] assertEquals(reTweet.id, "t_2") - assertEquals(reTweet.content, reTweetDraft.content) + assertEquals(reTweet.content, draftReTweet.content) assertEquals(reTweet.user.id, "u_2") - assertEquals(reTweet.date, reTweetDraft.date) + assertEquals(reTweet.date, draftReTweet.date) } @Test @@ -110,7 +110,7 @@ class TwitterSystemTest { val userDraft = DraftUser("a", "a@gmail.com", "a", "image", "backgroundImage") twitterSystem.addNewUser(userDraft) val tweetDraft = DraftTweet("u_1", "content", "image", LocalDateTime.now()) - val reTweetDraft = ReTweetDraft("u_1", "t_1", "content1", LocalDateTime.now()) + val draftReTweet = DraftReTweet("u_1", "t_1", "content1", LocalDateTime.now()) twitterSystem.addNewTweet(tweetDraft) assertEquals(twitterSystem.tweets.size, 1) @@ -118,7 +118,7 @@ class TwitterSystemTest { assertEquals(tweet.reTweets.size, 0) assertFailsWith("Can not retweet your own tweet") { - twitterSystem.addReTweet(reTweetDraft) + twitterSystem.addReTweet(draftReTweet) } assertEquals(tweet.reTweets.size, 0) } @@ -129,7 +129,7 @@ class TwitterSystemTest { val userDraft = DraftUser("a", "a@gmail.com", "a", "image", "backgroundImage") twitterSystem.addNewUser(userDraft) val tweetDraft = DraftTweet("u_1", "content", "image", LocalDateTime.now()) - val reTweetDraft = ReTweetDraft("u_2", "t_1", "content1", LocalDateTime.now()) + val draftReTweet = DraftReTweet("u_2", "t_1", "content1", LocalDateTime.now()) twitterSystem.addNewTweet(tweetDraft) assertEquals(twitterSystem.tweets.size, 1) @@ -137,7 +137,7 @@ class TwitterSystemTest { assertEquals(tweet.reTweets.size, 0) assertFailsWith("Not found user id") { - twitterSystem.addReTweet(reTweetDraft) + twitterSystem.addReTweet(draftReTweet) } assertEquals(tweet.reTweets.size, 0) } @@ -149,12 +149,12 @@ class TwitterSystemTest { val userDraft2 = DraftUser("b", "b@gmail.com", "b", "image", "backgroundImage") twitterSystem.addNewUser(userDraft) twitterSystem.addNewUser(userDraft2) - val reTweetDraft = ReTweetDraft("u_2", "t_1", "content1", LocalDateTime.now()) + val draftReTweet = DraftReTweet("u_2", "t_1", "content1", LocalDateTime.now()) assertEquals(twitterSystem.tweets.size, 0) assertFailsWith("Not found tweet id") { - twitterSystem.addReTweet(reTweetDraft) + twitterSystem.addReTweet(draftReTweet) } } @@ -164,21 +164,21 @@ class TwitterSystemTest { val userDraft = DraftUser("a", "a@gmail.com", "a", "image", "backgroundImage") twitterSystem.addNewUser(userDraft) val tweetDraft = DraftTweet("u_1", "content", "image", LocalDateTime.now()) - val replyTweetDraft = ReplyTweetDraft("u_1", "t_1", "content1", "image2", LocalDateTime.now()) + val draftReplyTweet = DraftReplyTweet("u_1", "t_1", "content1", "image2", LocalDateTime.now()) twitterSystem.addNewTweet(tweetDraft) assertEquals(twitterSystem.tweets.size, 1) val tweet = twitterSystem.tweets[0] assertEquals(tweet.replies.size, 0) - twitterSystem.replyTweet(replyTweetDraft) + twitterSystem.replyTweet(draftReplyTweet) assertEquals(twitterSystem.tweets.size, 2) assertEquals(tweet.replies.size, 1) val reTweet = twitterSystem.tweets[1] assertEquals(reTweet.id, "t_2") - assertEquals(reTweet.content, replyTweetDraft.content) + assertEquals(reTweet.content, draftReplyTweet.content) assertEquals(reTweet.user.id, "u_1") - assertEquals(reTweet.date, replyTweetDraft.date) + assertEquals(reTweet.date, draftReplyTweet.date) } @Test @@ -187,7 +187,7 @@ class TwitterSystemTest { val userDraft = DraftUser("a", "a@gmail.com", "a", "image", "backgroundImage") twitterSystem.addNewUser(userDraft) val tweetDraft = DraftTweet("u_1", "content", "image", LocalDateTime.now()) - val replyTweetDraft = ReplyTweetDraft("u_2", "t_1", "content1", "image2", LocalDateTime.now()) + val draftReplyTweet = DraftReplyTweet("u_2", "t_1", "content1", "image2", LocalDateTime.now()) twitterSystem.addNewTweet(tweetDraft) assertEquals(twitterSystem.tweets.size, 1) @@ -195,7 +195,7 @@ class TwitterSystemTest { assertEquals(tweet.replies.size, 0) assertFailsWith("Not found user id") { - twitterSystem.replyTweet(replyTweetDraft) + twitterSystem.replyTweet(draftReplyTweet) } assertEquals(twitterSystem.tweets.size, 1) @@ -208,7 +208,7 @@ class TwitterSystemTest { val userDraft = DraftUser("a", "a@gmail.com", "a", "image", "backgroundImage") twitterSystem.addNewUser(userDraft) val tweetDraft = DraftTweet("u_1", "content", "image", LocalDateTime.now()) - val replyTweetDraft = ReplyTweetDraft("u_1", "t_2", "content1", "image2", LocalDateTime.now()) + val draftReplyTweet = DraftReplyTweet("u_1", "t_2", "content1", "image2", LocalDateTime.now()) twitterSystem.addNewTweet(tweetDraft) assertEquals(twitterSystem.tweets.size, 1) @@ -216,7 +216,7 @@ class TwitterSystemTest { assertEquals(tweet.replies.size, 0) assertFailsWith("Not found tweet id") { - twitterSystem.replyTweet(replyTweetDraft) + twitterSystem.replyTweet(draftReplyTweet) } assertEquals(twitterSystem.tweets.size, 1)