Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support other poll types #9

Open
wants to merge 12 commits into
base: develop
Choose a base branch
from
8 changes: 7 additions & 1 deletion poll/data/data_source/data_source.py
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@
from poll.domain.model.poll.option import PollOptionInfo, PollOptionNumber
from poll.domain.model.poll.poll import Poll, PollNumber
from poll.domain.model.poll.publication import PollPublication
from poll.domain.model.poll.vote import OptionPollVote
from poll.domain.model.poll.vote import PollVote, OptionPollVote, OpenPollVote
from poll.domain.model.user.state import State
from poll.domain.model.user.user import User

@@ -57,9 +57,15 @@ def exists_publication(self, publication: PollPublication) -> bool:
def vote_option(self, vote: OptionPollVote):
raise NotImplementedError()

def vote_open(self, vote: OpenPollVote):
raise NotImplementedError()

def unvote_option(self, vote: OptionPollVote):
raise NotImplementedError()

def unvote_poll(self, vote: PollVote):
raise NotImplementedError()

def get_votes(self, poll: Poll, user: User) -> PollVotes:
raise NotImplementedError()

24 changes: 24 additions & 0 deletions poll/data/data_source/sqlite/component/poll/vote/option.py
Original file line number Diff line number Diff line change
@@ -94,6 +94,27 @@
)\
.build()

REMOVE_VOTES = Delete()\
.table(POLL_VOTE_OPTION)\
.where(
MultipleCondition(
AND,
Condition(USER, IN,
Select()
.fields(POLL_USER_ID)
.table(POLL_USER)
.where(Condition(POLL_USER_USER_ID, EQUAL, ":user_id"))
),
Condition(PUBLICATION, IN,
Select()
.fields(PUBLICATION_ID)
.table(POLL_PUBLICATION)
.where(Condition(POLL_ID, EQUAL, ":poll_id"))
)
)
)\
.build()

GET_USER_VOTES = Select()\
.fields(USER, PUBLICATION, OPTION)\
.table(POLL_VOTE_OPTION)\
@@ -142,6 +163,9 @@ def _get_next_number_for(self, vote: OptionPollVoteData) -> int:
def unvote_option(self, user: User, poll: Poll, option: PollOption):
self.statement(REMOVE_VOTE).execute(user_id=user.id, poll_id=poll.id, option=option.id)

def unvote_poll(self, user: User, poll: Poll):
self.statement(REMOVE_VOTES).execute(user_id=user.id, poll_id=poll.id)

def get_user_votes(self, poll: Poll, user: User) -> Iterable[OptionPollVoteData]:
votes = self.statement(GET_USER_VOTES)\
.execute(poll_id=poll.id, user_id=user.id)\
6 changes: 6 additions & 0 deletions poll/data/data_source/sqlite/model/poll/vote.py
Original file line number Diff line number Diff line change
@@ -13,3 +13,9 @@ class OptionPollVoteData(PollVoteData):
def __init__(self, user: PollUserData, publication: PollPublicationData, option: PollOption):
super().__init__(user, publication)
self.option = option


class OpenPollVoteData(PollVoteData):
def __init__(self, user: PollUserData, publication: PollPublicationData, text: str):
super().__init__(user, publication)
self.text = text
9 changes: 8 additions & 1 deletion poll/data/data_source/sqlite/sqlite.py
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@
from poll.domain.model.poll.option import PollOptionInfo, PollOptionNumber
from poll.domain.model.poll.poll import Poll, PollNumber
from poll.domain.model.poll.publication import PollPublication
from poll.domain.model.poll.vote import OptionPollVote
from poll.domain.model.poll.vote import PollVote, OptionPollVote, OpenPollVote
from poll.domain.model.user.state import State
from poll.domain.model.user.user import User

@@ -102,11 +102,18 @@ def vote_option(self, vote: OptionPollVote):
vote = self.mappers.option_vote.map_option_vote(vote, poll_user_id)
self.poll_vote_option.vote_option(vote)

def vote_open(self, vote: OpenPollVote):
raise NotImplementedError("unavailable yet")

def unvote_option(self, vote: OptionPollVote):
poll = self.poll_publication.get_poll(vote.publication)
option = self.poll_option.get_id(poll, vote.option)
self.poll_vote_option.unvote_option(vote.user, poll, option)

def unvote_poll(self, vote: PollVote):
poll = self.poll_publication.get_poll(vote.publication)
self.poll_vote_option.unvote_poll(vote.user, poll)

def get_votes(self, poll: Poll, user: User) -> PollVotes:
votes = self.poll_vote_option.get_user_votes(poll, user)
return self.mappers.option_vote.unmap_option_votes(votes)
14 changes: 13 additions & 1 deletion poll/data/repository.py
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@
from poll.domain.model.poll.option import PollOptionInfo, PollOptionNumber
from poll.domain.model.poll.poll import PollNumber, Poll
from poll.domain.model.poll.publication import PollPublication
from poll.domain.model.poll.vote import OptionPollVote
from poll.domain.model.poll.vote import PollVote, OptionPollVote, OpenPollVote
from poll.domain.model.user.state import State
from poll.domain.model.user.user import User
from poll.domain.repository.poll.get import GetPollRepository
@@ -104,12 +104,24 @@ def vote_option(self, vote: OptionPollVote):
"vote_option"
)

def vote_open(self, vote: OpenPollVote):
self._with_result(
lambda: self.data_source.vote_open(vote),
"vote_open"
)

def unvote_option(self, vote: OptionPollVote):
self._with_result(
lambda: self.data_source.unvote_option(vote),
"unvote_option"
)

def unvote_poll(self, vote: PollVote):
self._with_result(
lambda: self.data_source.unvote_poll(vote),
"unvote_poll"
)

def get_votes(self, poll: Poll, user: User) -> PollVotes:
return self._with_result(
lambda: self.data_source.get_votes(poll, user),
15 changes: 14 additions & 1 deletion poll/domain/interactors/poll/vote.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from poll.domain.check.unique_vote import UniqueVotePollCheck
from poll.domain.model.poll.group.votes import OptionPollVotes
from poll.domain.model.poll.poll import Poll
from poll.domain.model.poll.vote import PollVote, OptionPollVote
from poll.domain.model.poll.vote import PollVote, OptionPollVote, OpenPollVote
from poll.domain.model.vote_result import VoteResult, VOTED, UNVOTED, CHANGED_VOTE
from poll.domain.repository.poll.get import GetPollRepository
from poll.domain.repository.poll.vote import VotePollRepository
@@ -17,6 +17,8 @@ def vote(self, vote: PollVote) -> VoteResult:
poll = self.get.get_from_publication(vote.publication)
if isinstance(vote, OptionPollVote):
return self._vote_option(poll, vote)
elif isinstance(vote, OpenPollVote):
return self._vote_open(poll, vote)
else:
raise Exception("unexpected vote type")

@@ -36,3 +38,14 @@ def _vote_option(self, poll: Poll, vote: OptionPollVote) -> VoteResult:
result = CHANGED_VOTE
self.check.no_more_than_one_vote(previous_votes)
return result

def _vote_open(self, poll: Poll, vote: OpenPollVote) -> VoteResult:
previous_votes = self.repository_vote.get_votes(poll, vote.user)
result = VOTED
if not previous_votes.is_empty():
previous_vote = previous_votes.first()
self.repository_vote.unvote_poll(previous_vote)
result = CHANGED_VOTE
self.repository_vote.vote_open(vote)
self.check.no_more_than_one_vote(previous_votes)
return result
7 changes: 7 additions & 0 deletions poll/domain/model/poll/full/poll.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from poll.domain.model.poll.full.options import FullPollOptions
from poll.domain.model.poll.group.publications import PollPublications
from poll.domain.model.poll.group.votes import OpenPollVotes
from poll.domain.model.poll.info import PollInfo


@@ -13,3 +14,9 @@ class FullOptionPoll(FullPoll):
def __init__(self, info: PollInfo, publications: PollPublications, options: FullPollOptions):
super().__init__(info, publications)
self.options = options


class FullOpenPoll(FullPoll):
def __init__(self, info: PollInfo, publications: PollPublications, votes: OpenPollVotes):
super().__init__(info, publications)
self.votes = votes
8 changes: 7 additions & 1 deletion poll/domain/model/poll/group/votes.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import Sequence

from poll.domain.model.poll.vote import PollVote, OptionPollVote
from poll.domain.model.poll.vote import PollVote, OptionPollVote, OpenPollVote


class PollVotes:
@@ -27,3 +27,9 @@ class OptionPollVotes(PollVotes):
def __init__(self, votes: Sequence[OptionPollVote]):
super().__init__(votes)
self.votes = votes # fix type hinting


class OpenPollVotes(PollVotes):
def __init__(self, votes: Sequence[OpenPollVote]):
super().__init__(votes)
self.votes = votes # fix type hinting
2 changes: 2 additions & 0 deletions poll/domain/model/poll/settings/anonymity.py
Original file line number Diff line number Diff line change
@@ -8,3 +8,5 @@ def __init__(self, anonymity: int):


PERSONAL = PollAnonymity(0)
ANONYMOUS = PollAnonymity(1)
ANONYMOUS_AND_ONLY_TO_CREATOR = PollAnonymity(2)
4 changes: 4 additions & 0 deletions poll/domain/model/poll/settings/type.py
Original file line number Diff line number Diff line change
@@ -8,3 +8,7 @@ def __init__(self, poll_type: int):


SINGLE_VOTE = PollType(0)
MULTI_VOTE = PollType(1)
MULTI_VOTE_LIMITED = PollType(2)
OPEN = PollType(3)
RANGE = PollType(4)
6 changes: 6 additions & 0 deletions poll/domain/model/poll/vote.py
Original file line number Diff line number Diff line change
@@ -13,3 +13,9 @@ class OptionPollVote(PollVote):
def __init__(self, user: PollUser, publication: PollPublication, option: PollOptionNumber):
super().__init__(user, publication)
self.option = option


class OpenPollVote(PollVote):
def __init__(self, user: PollUser, publication: PollPublication, text: str):
super().__init__(user, publication)
self.text = text
5 changes: 5 additions & 0 deletions poll/domain/model/user/user.py
Original file line number Diff line number Diff line change
@@ -5,3 +5,8 @@ class User(Comparable):
def __init__(self, user_id: int):
super().__init__(user_id, User)
self.id = user_id


class AnonymousUser(User):
def __init__(self, anonymized_user_id: int):
super().__init__(anonymized_user_id)
8 changes: 7 additions & 1 deletion poll/domain/repository/poll/vote.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
from poll.domain.model.poll.group.votes import PollVotes
from poll.domain.model.poll.poll import Poll
from poll.domain.model.poll.vote import OptionPollVote
from poll.domain.model.poll.vote import OpenPollVote, OptionPollVote, PollVote
from poll.domain.model.user.user import User


class VotePollRepository:
def vote_option(self, vote: OptionPollVote):
raise NotImplementedError()

def vote_open(self, vote: OpenPollVote):
raise NotImplementedError()

def unvote_option(self, vote: OptionPollVote):
raise NotImplementedError()

def unvote_poll(self, vote: PollVote):
raise NotImplementedError()

def get_votes(self, poll: Poll, user: User) -> PollVotes:
raise NotImplementedError()
14 changes: 10 additions & 4 deletions poll/presentation/model/mapper/settings.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
from poll.domain.model.poll.settings.anonymity import PERSONAL, PollAnonymity
from poll.domain.model.poll.settings.anonymity import PERSONAL, ANONYMOUS, ANONYMOUS_AND_ONLY_TO_CREATOR, PollAnonymity
from poll.domain.model.poll.settings.settings import PollSettings
from poll.domain.model.poll.settings.type import PollType, SINGLE_VOTE
from poll.domain.model.poll.settings.type import PollType, SINGLE_VOTE, MULTI_VOTE, MULTI_VOTE_LIMITED, OPEN, RANGE
from poll.presentation.model.poll.settings import PollTypeViewModel, PollAnonymityViewModel, PollSettingsViewModel


POLL_TYPES = {
SINGLE_VOTE: "single vote"
SINGLE_VOTE: "single vote",
MULTI_VOTE: "doodle",
MULTI_VOTE_LIMITED: "limited doodle",
OPEN: "board",
RANGE: "choose in a range"
}

POLL_ANONYMITIES = {
PERSONAL: "personal"
PERSONAL: "personal",
ANONYMOUS: "anonymous",
ANONYMOUS_AND_ONLY_TO_CREATOR: "anonymous and only creator can see results"
}