class Cron(MyBaseRequestHandler):
    """Execute periodic tasks, such as poll LQFB event table."""
    dummy = None
    ims = None

    def get(self):
        self.dummy = dummyFactory()
        self.ims = ImsConnectorFactory(LqfbDB)
        self.ims.connect(host=conf['lqfb.host'],
                         password=conf['lqfb.password'])
        self.getIssuesForVoting()
        self.getPublicVotes()
        self.getIssuesToCalculate()
        self.calculateResults()
        self.returnResults()
        self.write("Execution of periodic tasks completed.")

    def getIssuesForVoting(self):
        dummy = self.dummy
        ims = self.ims
        leid = dummy.getLastEventId('voting')
        issues = ims.getIssuesForVoting(leid)
        if issues.isEmpty():
            return
        else:
            dummy.insertIssuesForVoting(issues)

    def getPublicVotes(self):
        dummy = self.dummy
        ims = self.ims
        leid = dummy.getLastEventId('public_voting_closed')
        (public_votes, leid) = ims.getPublicVotes(leid)
        if len(public_votes) > 0:
            dummy.insertPublicVotes(public_votes, leid)

    def getIssuesToCalculate(self):
        dummy = self.dummy
        ims = self.ims
        leid = dummy.getLastEventId('private_voting_closed')
        (issue_id_list, leid) = ims.getIssuesToCalculate(leid)
        if len(issue_id_list) > 0:
            dummy.setPrivateVotingClosed(issue_id_list, leid)

    def calculateResults(self):
        """In DummyDB calculation is actually provided by a series of views, so there is nothing to do for now."""
        return True

    def returnResults(self):
        """Return results from battle_view to liquid_feedback battle table."""
        dummy = self.dummy
        ims = self.ims
        (battle_list, voter_count_map) = dummy.getPrivateVotingResults()
        if len(battle_list) > 0:
            if ims.returnResults(battle_list, voter_count_map) == True:
                # If results were successfully returned, set state on these issues to closed
                dummy.setClosed(battle_list)
Example #2
0
class Cron(MyBaseRequestHandler):
  """Execute periodic tasks, such as poll LQFB event table."""
  dummy = None
  ims = None

  def get(self):
    self.dummy = dummyFactory()
    self.ims = ImsConnectorFactory(LqfbDB)
    self.ims.connect(host=conf['lqfb.host'], password=conf['lqfb.password'])
    self.getIssuesForVoting()
    self.getPublicVotes()
    self.getIssuesToCalculate()
    self.calculateResults()
    self.returnResults()
    self.write("Execution of periodic tasks completed.")

  def getIssuesForVoting(self) :
    dummy = self.dummy
    ims = self.ims
    leid = dummy.getLastEventId('voting')
    issues = ims.getIssuesForVoting(leid)
    if issues.isEmpty() :
      return
    else :
      dummy.insertIssuesForVoting(issues)

  def getPublicVotes(self) :
    dummy = self.dummy
    ims = self.ims
    leid = dummy.getLastEventId('public_voting_closed')
    (public_votes, leid) = ims.getPublicVotes(leid)
    if len( public_votes ) > 0 :
      dummy.insertPublicVotes(public_votes, leid)
      
  def getIssuesToCalculate(self) :
    dummy = self.dummy
    ims = self.ims
    leid = dummy.getLastEventId('private_voting_closed')
    (issue_id_list, leid) = ims.getIssuesToCalculate(leid)
    if len( issue_id_list ) > 0 :
      dummy.setPrivateVotingClosed(issue_id_list, leid)

  def calculateResults(self) :
    """In DummyDB calculation is actually provided by a series of views, so there is nothing to do for now."""
    return True

      
  def returnResults(self) :
    """Return results from battle_view to liquid_feedback battle table."""
    dummy = self.dummy
    ims = self.ims
    (battle_list, voter_count_map) = dummy.getPrivateVotingResults()
    if len( battle_list ) > 0 :
      if ims.returnResults(battle_list, voter_count_map) == True :
        # If results were successfully returned, set state on these issues to closed
        dummy.setClosed(battle_list)
    def post(self):
        """Process the submitted votes and save them in our DummyDB"""
        # First we need to check user credentials. This is done against the source
        # database (e.g. Liquid Feedback).
        username = self.get_argument('username')
        password = self.get_argument('password')
        ims = ImsConnectorFactory(LqfbDB)
        ims.connect(host=conf['lqfb.host'], password=conf['lqfb.password'])
        user_id = ims.userAuthentication(username, password)
        if not user_id:
            raise tornado.web.HTTPError(
                401,
                "To vote, please provide your Liquid Feedback username and password."
            )

        # Fetch issue that is voted on, we need it already
        dummy = dummyFactory()
        issue = dummy.getIssue(self.get_argument('issue_id'))
        # remove wrapper object
        issue = issue.getIssue()

        # Check that issue is in voting state
        if not issue['state'] == 'voting':
            raise tornado.web.HTTPError(
                400,
                'Issue %s is not in "voting" state.' % issue['issue']['id'])

        # Check authorization
        if not ims.userAuthorization(user_id, issue['unit']['id']):
            raise tornado.web.HTTPError(
                403,
                "User '%s' is not authorized to vote in unit <em>%s</em>" %
                (username, issue['unit']['name']))

        if self.get_argument('vote_type') == 'direct':
            # Get user score for each initiative in issue
            scores = {}
            for ini in issue['initiatives']:
                arg = "i" + str(ini['id'])
                value = int(self.get_argument(arg))
                scores[int(ini['id'])] = value

            # Check that values are within allowed range.
            # Rules:
            """You can give the same score to more than one alternative.
        But the scores cannot contain gaps. For example... <br />
        This is allowed: (+1, 0, -1) <br />
        This is also allowed: (+1, +1, 0) <br />
        but this is not allowed: (+2, 0, -1) <br />
        ...since in the latter there is no score +1.<br />
        Note that 0 exists always due to 
        Status Quo, so all your scores have to be around 0: ...+2, +1, 0, -1, -2...
        """
            #Speaking of which, need to add the Status Quo
            scores[None] = 0
            # Now we can check for a consecutive range
            v_list = [v for (k, v) in scores.items()]
            v_list.sort()
            previous = v_list[0]
            for v in v_list:
                if v != previous and v != previous + 1:
                    raise tornado.web.HTTPError(
                        400,
                        'Illegal scores in your vote (there is a gap in the values): '
                        + ", ".join(str(x) for x in v_list))
                previous = v
            # With my logic, the above is also a sufficient check that values are between
            # -nr_ini ... nr_ini

            # We don't actually save the Status Quo vote to database:
            del (scores[None])
            # Now save the vote
            dummy.saveVote(user_id, self.get_argument('issue_id'), scores,
                           'direct')
            self.write(
                "Your vote was saved successfully. Thank you for voting!")
        elif self.get_argument('vote_type') == 'delegated':
            trustee_id = ims.getUserId(
                self.get_argument('trustee_identification'), 'identification')
            if trustee_id:
                dummy.saveVote(user_id, self.get_argument('issue_id'),
                               trustee_id, 'delegated')
                self.write(
                    "Your vote was saved successfully. Thank you for voting!")
            else:
                raise tornado.web.HTTPError(
                    400,
                    'Cannot delegate vote. No such member in this voting system: %s'
                    % self.get_argument('trustee_identification'))
        else:
            raise tornado.web.HTTPError(
                400, 'Invalid vote_type: %s' % self.get_argument('vote_type'))
Example #4
0
  def post(self):
    """Process the submitted votes and save them in our DummyDB"""
    # First we need to check user credentials. This is done against the source
    # database (e.g. Liquid Feedback).
    username=self.get_argument('username')
    password=self.get_argument('password')
    ims = ImsConnectorFactory(LqfbDB)
    ims.connect(host=conf['lqfb.host'], password=conf['lqfb.password'])
    user_id = ims.userAuthentication(username, password)
    if not user_id :
      raise tornado.web.HTTPError(401, "To vote, please provide your Liquid Feedback username and password.")

    # Fetch issue that is voted on, we need it already
    dummy = dummyFactory()
    issue = dummy.getIssue(self.get_argument('issue_id'))
    # remove wrapper object
    issue = issue.getIssue()
    
    # Check that issue is in voting state
    if not issue['state'] == 'voting' :
      raise tornado.web.HTTPError(400, 'Issue %s is not in "voting" state.' % issue['issue']['id'] )

    # Check authorization
    if not ims.userAuthorization(user_id, issue['unit']['id']) :
      raise tornado.web.HTTPError(403, "User '%s' is not authorized to vote in unit <em>%s</em>" % (username, issue['unit']['name']) )
    
    if self.get_argument('vote_type') == 'direct' :
      # Get user score for each initiative in issue
      scores = {}
      for ini in issue['initiatives'] :
        arg = "i" + str( ini['id'] )
        value = int( self.get_argument(arg) )
        scores[ int( ini['id'] ) ] = value

      # Check that values are within allowed range.
      # Rules:
      """You can give the same score to more than one alternative.
        But the scores cannot contain gaps. For example... <br />
        This is allowed: (+1, 0, -1) <br />
        This is also allowed: (+1, +1, 0) <br />
        but this is not allowed: (+2, 0, -1) <br />
        ...since in the latter there is no score +1.<br />
        Note that 0 exists always due to 
        Status Quo, so all your scores have to be around 0: ...+2, +1, 0, -1, -2...
        """
      #Speaking of which, need to add the Status Quo
      scores[None] = 0
      # Now we can check for a consecutive range
      v_list = [v for (k,v) in scores.items()]
      v_list.sort()
      previous = v_list[0]
      for v in v_list :
        if v != previous and v != previous + 1 :
          raise tornado.web.HTTPError(400, 'Illegal scores in your vote (there is a gap in the values): ' + ", ".join(str(x) for x in v_list) )
        previous = v
      # With my logic, the above is also a sufficient check that values are between
      # -nr_ini ... nr_ini

      # We don't actually save the Status Quo vote to database:
      del( scores[None] )
      # Now save the vote
      dummy.saveVote(user_id, self.get_argument('issue_id'), scores, 'direct' )
      self.write("Your vote was saved successfully. Thank you for voting!")
    elif self.get_argument('vote_type') == 'delegated' :
      trustee_id = ims.getUserId(self.get_argument('trustee_identification'), 'identification')
      if trustee_id :
        dummy.saveVote(user_id, self.get_argument('issue_id'), trustee_id, 'delegated' )
        self.write("Your vote was saved successfully. Thank you for voting!")
      else :
        raise tornado.web.HTTPError(400, 'Cannot delegate vote. No such member in this voting system: %s' % self.get_argument('trustee_identification') )
    else :
      raise tornado.web.HTTPError(400, 'Invalid vote_type: %s' % self.get_argument('vote_type') )