forked from ashishps1/awesome-low-level-design
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcontent.py
More file actions
134 lines (99 loc) · 4.16 KB
/
content.py
File metadata and controls
134 lines (99 loc) · 4.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import threading
import uuid
from abc import ABC
from datetime import datetime
from typing import Dict, List, Optional, Set, TYPE_CHECKING
from enums import VoteType, EventType
from user import User
from tag import Tag
if TYPE_CHECKING:
from event import Event
from post_observer import PostObserver
class Content(ABC):
def __init__(self, content_id: str, body: str, author: User):
self.id = content_id
self.body = body
self.author = author
self.creation_time = datetime.now()
def get_id(self) -> str:
return self.id
def get_body(self) -> str:
return self.body
def get_author(self) -> User:
return self.author
class Post(Content):
def __init__(self, post_id: str, body: str, author: User):
super().__init__(post_id, body, author)
self.vote_count = 0
self.voters: Dict[str, VoteType] = {}
self.comments: List['Comment'] = []
self.observers: List['PostObserver'] = []
self._lock = threading.Lock()
def add_observer(self, observer: 'PostObserver'):
self.observers.append(observer)
def notify_observers(self, event: 'Event'):
for observer in self.observers:
observer.on_post_event(event)
def vote(self, user: User, vote_type: VoteType):
with self._lock:
user_id = user.get_id()
if self.voters.get(user_id) == vote_type:
return # Already voted
score_change = 0
if user_id in self.voters: # User is changing their vote
score_change = 2 if vote_type == VoteType.UPVOTE else -2
else: # New vote
score_change = 1 if vote_type == VoteType.UPVOTE else -1
self.voters[user_id] = vote_type
self.vote_count += score_change
# Import here to avoid circular dependency
from event import Event
if isinstance(self, Question):
event_type = EventType.UPVOTE_QUESTION if vote_type == VoteType.UPVOTE else EventType.DOWNVOTE_QUESTION
else:
event_type = EventType.UPVOTE_ANSWER if vote_type == VoteType.UPVOTE else EventType.DOWNVOTE_ANSWER
self.notify_observers(Event(event_type, user, self))
def get_vote_count(self) -> int:
return self.vote_count
def add_comment(self, comment: 'Comment'):
self.comments.append(comment)
def get_comments(self) -> List['Comment']:
return self.comments
class Question(Post):
def __init__(self, title: str, body: str, author: User, tags: Set[Tag]):
super().__init__(str(uuid.uuid4()), body, author)
self.title = title
self.tags = tags
self.answers: List['Answer'] = []
self.accepted_answer: Optional['Answer'] = None
def add_answer(self, answer: 'Answer'):
self.answers.append(answer)
def accept_answer(self, answer: 'Answer'):
with self._lock:
# Only the question author can accept an answer, and it shouldn't be their own answer
if (self.author.get_id() != answer.get_author().get_id() and
self.accepted_answer is None):
self.accepted_answer = answer
answer.set_accepted(True)
# Import here to avoid circular dependency
from event import Event
self.notify_observers(Event(EventType.ACCEPT_ANSWER, answer.get_author(), answer))
def get_title(self) -> str:
return self.title
def get_tags(self) -> Set[Tag]:
return self.tags
def get_answers(self) -> List['Answer']:
return self.answers
def get_accepted_answer(self) -> Optional['Answer']:
return self.accepted_answer
class Answer(Post):
def __init__(self, body: str, author: User):
super().__init__(str(uuid.uuid4()), body, author)
self.is_accepted = False
def set_accepted(self, accepted: bool):
self.is_accepted = accepted
def is_accepted_answer(self) -> bool:
return self.is_accepted
class Comment(Content):
def __init__(self, body: str, author: User):
super().__init__(str(uuid.uuid4()), body, author)