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()