Trello | LLD | OOD | Feedback Required | Machine Coding Round

Trello Clone Implementation | Feedback Appreciated
Problem Statement - https://workat.tech/machine-coding/practice/trello-problem-t0nwwqt61buz

# Requirements
# User: Each user should have a userId, name, email.
# Board: Each board should have a id, name, privacy (PUBLIC/PRIVATE), url, members, lists
# List: Each list should have a id, name and cards
# Card: Each card should have a id, name, description, assigned user
# We should be able to create/delete boards, add/remove people from the members list and modify attributes. Deleting a board should delete all lists inside it.
# We should be able to create/delete lists and modify attributes. Deleting a list should delete all cards inside it.
# We should be able to create/delete cards, assign/unassign a member to the card and modify attributes
# We should also be able to move cards across lists in the same board
# Ability to show all boards, a single board, a single list and a single card
# Default privacy should be public
# Cards should be unassigned by default
# Ids should be auto-generated for board/list/card
# URLs should get created based on the id

class Card: 
    def __init__(self, name):
        self.id = name 
        self.name = name 
        self.description = ""
        self.assignedUser = None
    
    # generic attributes update
    def updateName(self, newName):
        self.name = newName
    def updateDescription(self, newDescription):
        self.description = newDescription

    # already checked in userid in main system or not
    def addAssignedUser(self, userId):
        self.assignedUser = userId
    
    def removeAssignedUser(self):
        self.assignedUser = None

class List: 
    def __init__(self, name):
        self.id = name 
        self.name = name 
        self.cards = {}
    
    # generic attributes update
    def updateName(self, newName):
        self.name = newName

    # card in by moving or adding
    def addCard(self, card):
        cardId = card.id 
        if(cardId in self.cards):
            print("card already exists in list")
        else:
            self.cards[cardId] = 1
    
    # card removed either by del or moving
    def removeCard(self, cardId):
        if(cardId not in self.cards):
            print("Card does not exist in List")
        else:
            del self.cards[cardId]

# User in out system
class User:
    def __init__(self, name):
        self.id = name 
        self.userName = name
        self.userEmail = None
    
    # generic attributes update
    def updateName(self, newName):
        self.userName = newName
    def updateEmail(self, newEmail):
        self.userEmail = newEmail

# Board with all Create and delete functionalities
class Board: 
    def __init__(self, name): 
        self.id = name
        self.name = name
        self.privacy = "PUBLIC"
        self.url = "http://fakeTrello/" + str(self.id)
        self.members = {} 
        self.lists = {}
    
    # generic attributes update
    def updateName(self, newName):
        self.name = newName
    def updatePrivacy(self, newPrivacy):
        self.privacy = newPrivacy

    # already checked in userid in main system or not
    def addMember(self, userId): 
        if(userId in self.members): 
            print("user already exists in Board") 
        else:
            self.members[userId] = 1
    
    # already checked in userid in main system or not
    def removeMember(self, userId):
        if(userId not in self.members): 
            print("user does not exist in Board") 
        else:
            del self.members[userId]
    
    # any prev check needed yet to decide
    def addList(self, listId):
        if(listId in self.lists):
            print("list already exists in Board")
        else:
            self.lists[listId] = 1
    
    # any prev check needed yet to decide
    def removeList(self, listId):
        if(listId not in self.lists):
            print("list does not exist in Board")
        else:
            del self.lists[listId]
        
class Trello:
    def __init__(self):
        self.boards = {} 
        self.users = {} 
        self.freeCards = {} # unassigned cards to any board or list
    
    # Board attributes
    def addBoard(self, boardName):
        if(boardName in self.boards):
            print("Board with same name already exists")
        else:
            self.boards[boardName] = Board(boardName)
    
    def removeBoard(self, boardId):
        if(boardId not in self.boards):
            print("Board does not exist in system")
        else:
            del self.boards[boardId]
    
    ## User attributes
    def addUser(self, userName):
        if(userName in self.users):
            print("user with same name already exists")
        else:
            self.users[userName] = User(userName)
    
    def removeUser(self, userId):
        if(userId not in self.users):
            print("User does not exist in system")
        else:
            del self.users[userId]
    
    def validateUser(self, userId):
        if(userId in self.users):
            return True
        return False
    
    def validateBoard(self, boardId):
        if(boardId in self.boards):
            return True
        return False

def main():
    fakeTrello = Trello()
    userInput = []
    while(True):
        temp = list(map(str, input().strip().split()))
        # Exit case
        if(temp[0] == "exit"):
            break
        userInput.append(temp)
    for rawInput in userInput:
        # Cases
        if(rawInput[0] == "BOARD"):
            if(rawInput[1] == "CREATE"):
                fakeTrello.addBoard(rawInput[2])
                print("Board Added")
                continue
            elif(rawInput[1] == "DELETE"):
                fakeTrello.removeBoard(rawInput[2])
                print("Board DELETED")
                continue
            else:
                boardId = rawInput[1]
                if(not fakeTrello.validateBoard(boardId)):
                    print("No such board exists in system")
                    continue
                if(rawInput[2] == "ADD_MEMBER"):
                    userId = rawInput[3]
                    if(fakeTrello.validateUser(userId)):
                        fakeTrello.boards[boardId].addMember(userId)
                    else:
                        print("No such user exists for addtition")
                    continue
                elif(rawInput[2] == "REMOVE_MEMBER"):
                    userId = rawInput[3]
                    if(fakeTrello.validateUser(userId)):
                        fakeTrello.boards[boardId].removeMember(userId)
                    else:
                        print("No such user exists for removal")
                    continue
                elif(rawInput[2] == "name"):
                    fakeTrello.boards[boardId].updateName(rawInput[3])
                    print( {
                        "id": fakeTrello.boards[boardId].id,
                        "name": fakeTrello.boards[boardId].name,
                        "privacy": fakeTrello.boards[boardId].privacy
                    } )
                    continue
                elif(rawInput[2] == "privacy"):
                    fakeTrello.boards[boardId].updatePrivacy(rawInput[3])
                    print( {
                        "id": fakeTrello.boards[boardId].id,
                        "name": fakeTrello.boards[boardId].name,
                        "privacy": fakeTrello.boards[boardId].privacy
                    } )
                    continue
                else:
                    print("Unsupported Action for board")
                    continue
        elif(rawInput[0] == "LIST"):
            if(rawInput[1] == "CREATE"):
                boardId = rawInput[2]
                if(not fakeTrello.validateBoard(boardId)):
                    print("No such board exists in system")
                    continue
                listName = " ".join(rawInput[3:])
                fakeTrello.boards[boardId].addList(listName)
            elif(rawInput[1] == "DELETE"):
                # worst case of no boardId given so we search
                listId = rawInput[2]
                Flag = False
                for board in fakeTrello.boards:
                    if (listId in board.lists):
                        board.removeList(listId)
                        Flag = True
                        break
                if(not Flag):
                    print("List does not exist in system to delete")
                    continue
                else:
                    print("List deleted sucessfully")
            else:
                if(rawInput[2] == "ADD_CARD"):
                    if(rawInput[3] not in self.freeCards):
                        print("Requested addition of card is not free")
                        continue
                    # we have to search for addition
                    listId = rawInput[1]
                    Flag = False
                    for board in fakeTrello.boards:
                        if(listId in board.lists):
                            card = self.freeCards[rawInput[3]]
                            board.lists[listId].addCard(card)
                            Flag = True
                            break
                    if(not Flag):
                        print("Card can't be added as we cant find the list in system")
                        continue
                    else:
                        print("Card added successfully")
                        continue
                elif(rawInput[2] == "REMOVE_CARD"):
                    # we have to search for deletion
                    listId = rawInput[1]
                    Flag = False
                    for board in fakeTrello.boards:
                        if(listId in board.lists):
                            board.lists[listId].removeCard(rawInput[3])
                            Flag = True
                            break
                    if(not Flag):
                        # if free card is there to delete
                        if(rawInput[3] in fakeTrello.freeCards):
                            del fakeTrello.freeCards[rawInput[3]]
                            continue
                        print("Card can't be deleted as we cant find the list in system")
                        continue
                    else:
                        print("Card deleted successfully")
                        continue
                elif(rawInput[2] == "name"):
                    # we have to search for updation
                    listId = rawInput[1]
                    Flag = False
                    for board in fakeTrello.boards:
                        if(listId in board.lists):
                            board.lists[listId].updateName(rawInput[3])
                            Flag = True
                            break
                    if(not Flag):
                        print("List name can't be updated as we cant find the list in system")
                        continue
                    else:
                        print("List name updated successfully")
                        continue
                else:
                    print("Unsupported Action for List")
                    continue
        elif(rawInput[0] == "CARD"):
            if(rawInput[1] == "CREATE"):
                cardName = rawInput[2]
                userEmail = rawInput[3]
                user = None
                for user in fakeTrello.users:
                    if(fakeTrello.users[user].email == userEmail):
                        user = fakeTrello.users[user]
                        break
                if(user is None):
                    print("cant create user as no assigned user exists")
                    print("overriding creation by no assigned user")
                    newCard = Card(cardName)
                else:
                    newCard = Card(cardName)
                    newCard.addAssignedUser(user)
                    print("Card created and assigned to user with email provided")
                fakeTrello.freeCards[newCard.id] = newCard
                continue
            elif(rawInput[1] == "DELETE"):
                cardId = rawInput[2]
                # first search in free cards 
                if(cardId in fakeTrello.freeCards):
                    del fakeTrello.freeCards[cardId]
                    print("Deleted from free cards")
                    continue
                else:
                    megaFlag = False
                    for board in fakeTrello.boards:
                        Flag = False
                        for List in fakeTrello.boards[board].lists:
                            if(cardId in fakeTrello.boards[board].lists[List]):
                                del fakeTrello.boards[board].lists[List].cards[cardId]
                                print("deleted card successfully") 
                                Flag = True
                                megaFlag = True
                                break
                        if(Flag):
                            break
                    if(not megaFlag):
                        print("Card not Found hence can't be deleted")
                    continue
            else:
                if(rawInput[2] == "ASSIGN"):
                    cardId = rawInput[1]
                    userId = rawInput[4]
                    if(userId not in fakeTrello.users):
                        print("Assigned to be user does not exist in system") 
                        continue
                    user = fakeTrello.users[userId]
                    # first search in free cards 
                    if(cardId in fakeTrello.freeCards):
                        fakeTrello.freeCards[cardId].addAssignedUser(user.id)
                        print("User assigned to free card")
                        continue
                    else:
                        megaFlag = False
                        for board in fakeTrello.boards:
                            Flag = False
                            for List in fakeTrello.boards[board].lists:
                                if(cardId in fakeTrello.boards[board].lists[List]):
                                    fakeTrello.boards[board].lists[List].cards[cardId].addAssignedUser(user.id)
                                    print("user assigned to card in specific board and list")
                                    Flag = True
                                    megaFlag = True
                                    break
                            if(Flag):
                                break
                        if(not megaFlag):
                            print("Card not Found hence can't be assigned with user")
                        continue
                elif(rawInput[2] == "UNASSIGN"):
                    cardId = rawInput[1]
                    # first search in free cards 
                    if(cardId in fakeTrello.freeCards):
                        fakeTrello.freeCards[cardId].removeAssignedUser()
                        print("User unassigned to free card")
                        continue
                    else:
                        megaFlag = False
                        for board in fakeTrello.boards:
                            Flag = False
                            for List in fakeTrello.boards[board].lists:
                                if(cardId in fakeTrello.boards[board].lists[List]):
                                    fakeTrello.boards[board].lists[List].cards[cardId].removeAssignedUser()
                                    print("user unassigned to card in specific board and list")
                                    Flag = True
                                    megaFlag = True
                                    break
                            if(Flag):
                                break
                        if(not megaFlag):
                            print("Card not Found hence can't be unassigned")
                        continue
                elif(rawInput[2] == "MOVE"):
                    cardId = rawInput[1]
                    # first search in free cards 
                    if(cardId in fakeTrello.freeCards):
                        card = fakeTrello.freeCards[cardId]
                        del fakeTrello.freeCards[cardId]
                    else:
                        megaFlag = False
                        for board in fakeTrello.boards:
                            Flag = False
                            for List in fakeTrello.boards[board].lists:
                                if(cardId in fakeTrello.boards[board].lists[List]):
                                    card = fakeTrello.boards[board].lists[List].cards[cardId]
                                    del fakeTrello.boards[board].lists[List].cards[cardId]
                                    Flag = True
                                    megaFlag = True
                                    break
                            if(Flag):
                                break
                        if(not megaFlag):
                            print("Card not Found hence can't be moved")
                            continue
                    listId = rawInput[3]
                    for board in fakeTrello.boards:
                        if(listId in fakeTrello.boards[board].lists):
                            fakeTrello.boards[board].lists[listId].cards[cardId] = card
                            break
                    print("Card moved successfully")
                    continue
                elif(rawInput[2] == "DELETE"):
                    cardId = rawInput[2]
                    # first search in free cards 
                    if(cardId in fakeTrello.freeCards):
                        del fakeTrello.freeCards[cardId]
                        print("Deleted from free cards")
                        continue
                    else:
                        megaFlag = False
                        for board in fakeTrello.boards:
                            Flag = False
                            for List in fakeTrello.boards[board].lists:
                                if(cardId in fakeTrello.boards[board].lists[List]):
                                    del fakeTrello.boards[board].lists[List].cards[cardId]
                                    print("deleted card successfully") 
                                    Flag = True
                                    megaFlag = True
                                    break
                            if(Flag):
                                break
                        if(not megaFlag):
                            print("Card not Found hence can't be deleted")
                        continue
                elif(rawInput[2] == "name"):
                    cardId = rawInput[1]
                    newName = " ".join(rawInput[3:])
                    # first search in free cards 
                    if(cardId in fakeTrello.freeCards):
                        fakeTrello.freeCards[cardId].updateName(newName)
                        print("Card name updated in free cards")
                        continue
                    else:
                        megaFlag = False
                        for board in fakeTrello.boards:
                            Flag = False
                            for List in fakeTrello.boards[board].lists:
                                if(cardId in fakeTrello.boards[board].lists[List]):
                                    fakeTrello.boards[board].lists[List].cards[cardId].updateName(newName)
                                    print("Card name updated in list and board")
                                    Flag = True
                                    megaFlag = True
                                    break
                            if(Flag):
                                break
                        if(not megaFlag):
                            print("Card not Found hence can't be updated for name")
                        continue
                elif(rawInput[2] == "description"):
                    cardId = rawInput[1]
                    newDescription = " ".join(rawInput[3:])
                    # first search in free cards 
                    if(cardId in fakeTrello.freeCards):
                        fakeTrello.freeCards[cardId].updateDescription(newDescription)
                        print("Card nadescriptionme updated in free cards")
                        continue
                    else:
                        megaFlag = False
                        for board in fakeTrello.boards:
                            Flag = False
                            for List in fakeTrello.boards[board].lists:
                                if(cardId in fakeTrello.boards[board].lists[List]):
                                    fakeTrello.boards[board].lists[List].cards[cardId].updateDescription(newDescription)
                                    print("Card description updated in list and board")
                                    Flag = True
                                    megaFlag = True
                                    break
                            if(Flag):
                                break
                        if(not megaFlag):
                            print("Card not Found hence can't be updated for description")
                        continue
                else:
                    print("Unsupported Action for Card")
        elif(rawInput[0] == "SHOW"):
            if(len(rawInput) == 1):
                # show all
                res = []
                for board in fakeTrello.boards:
                    res.append( {
                        "id": fakeTrello.boards[board].id,
                        "name": fakeTrello.boards[board].name,
                        "privacy": fakeTrello.boards[board].privacy
                    } )
                if(len(res) == 0):
                    print("No board")
                else:
                    print(res)
                continue
            if(rawInput[1] == "BOARD"):
                boardId = rawInput[2]
                if(boardId in fakeTrello.boards):
                    board = fakeTrello.boards[boardId]
                    print({
                        "id": board.id,
                        "name": board.name,
                        "privacy": board.privacy 
                    })
                    continue
                else:
                    print("Board does not exist in system to show")
                    continue
            elif(rawInput[1] == "LIST"):
                listId = rawInput[2]
                for board in fakeTrello.boards:
                    if(listId in fakeTrello.boards[board].lists):
                        List = fakeTrello.boards[board].lists[listId]
                        print( {
                            "id": List.id,
                            "name": List.name,
                            "cards": [ {
                                "id": card.id,
                                "name": card.name,
                                "description": card.description,
                                "assignedTo": card.assignedUser
                            } for card in List.cards]
                        } )
                        break
                continue
            elif(rawInput[1] == "CARD"):
                cardId = rawInput[2]
                if(cardId in fakeTrello.freeCards):
                    card = fakeTrello.freeCards[cardId]
                    print( {
                        id: card.id,
                        name: card.name
                    } )
                    continue
                else:
                    megaFlag = False
                    for board in fakeTrello.boards:
                        Flag = False
                        for listId in fakeTrello.boards[board].lists:
                            if(cardId in fakeTrello.boards[board].lists[listId].cards):
                                card = fakeTrello.boards[board].lists[listId].cards[cardId]
                                print( {
                                    "id": card.id,
                                    "name": card.name
                                } )
                                Flag = True
                                megaFlag = True
                                break
                        if(Flag):
                            break
                    if(not megaFlag):
                        print("Card not found")
                    continue
            else:
                print("Unsupprted action for showing things in system")
        else:
            print("Unsupported Action Type")
            continue
# start off
main()
Comments (1)