Skip to content

Commit

Permalink
Create new quarantine triggers and update create quarantine checks fu…
Browse files Browse the repository at this point in the history
…nction
  • Loading branch information
JohnMwashuma committed Oct 24, 2024
1 parent b457035 commit e61ec8e
Show file tree
Hide file tree
Showing 2 changed files with 164 additions and 111 deletions.
135 changes: 125 additions & 10 deletions tally_ho/libs/verify/quarantine_checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,10 @@

def create_quarantine_checks():
for quarantine_check in getattr(settings, 'QUARANTINE_DATA'):
QuarantineCheck.objects.update_or_create(
name=quarantine_check['name'],
method=quarantine_check['method'],
defaults={'active': quarantine_check['active'],
'value': quarantine_check['value'],
'description': quarantine_check['description'],
'percentage': quarantine_check['percentage']},
)
try:
QuarantineCheck.objects.get(method=quarantine_check['method'])
except QuarantineCheck.DoesNotExist:
QuarantineCheck.objects.create(**quarantine_check)


def get_total_candidates_votes(result_form):
Expand All @@ -41,7 +37,18 @@ def get_total_candidates_votes(result_form):

def quarantine_checks():
"""Return tuples of (QuarantineCheck, validation_function)."""
all_methods = {'pass_overvote':
all_methods = {
'pass_registrants_trigger':
pass_registrants_trigger,
'pass_voter_cards_trigger':
pass_voter_cards_trigger,
'pass_ballot_papers_trigger':
pass_ballot_papers_trigger,
'pass_ballot_inside_box_trigger':
pass_ballot_inside_box_trigger,
'pass_candidates_votes_trigger':
pass_candidates_votes_trigger,
'pass_overvote':
pass_overvote,
'pass_tampering':
pass_tampering,
Expand All @@ -58,7 +65,8 @@ def quarantine_checks():
'pass_turnout_percentage_validation':
pass_turnout_percentage_validation,
'pass_percentage_of_votes_per_candidate_validation':
pass_percentage_of_votes_per_candidate_validation}
pass_percentage_of_votes_per_candidate_validation
}
methods = []

quarantine_checks_methods =\
Expand Down Expand Up @@ -106,6 +114,113 @@ def pass_overvote(result_form):

return recon_form.number_ballots_used <= max_number_ballots

def pass_registrants_trigger(result_form):
"""Summation of recon fields number_cancelled_ballots and
number_ballots_inside_box must be less than or equal to the number of
registered voters at the station.
If the `result_form` does not have a `reconciliation_form` this will
always return True.
If the `station` for this `result_form` has an empty `registrants` field
this will always return True.
:param result_form: The result form to check.
:returns: A boolean of true if passed, otherwise false.
"""
recon_form = result_form.reconciliationform

if not recon_form:
return True

registrants = result_form.station.registrants if result_form.station\
else None

if registrants is None:
return True

return recon_form.total_of_cancelled_ballots_and_ballots_inside_box <=\
registrants

def pass_voter_cards_trigger(result_form):
"""Summation of recon fields number_cancelled_ballots and
number_ballots_inside_box must be equal to
number_of_voter_cards_in_the_ballot_box
If the `result_form` does not have a `reconciliation_form` this will
always return True.
:param result_form: The result form to check.
:returns: A boolean of true if passed, otherwise false.
"""
recon_form = result_form.reconciliationform

if not recon_form:
return True

return recon_form.total_of_cancelled_ballots_and_ballots_inside_box ==\
recon_form.number_of_voter_cards_in_the_ballot_box

def pass_ballot_papers_trigger(result_form):
"""The total number of ballots received by the polling station must be
equal to the total number of ballots found inside and outside the
ballot box.
If the `result_form` does not have a `reconciliation_form` this will
always return True.
:param result_form: The result form to check.
:returns: A boolean of true if passed, otherwise false.
"""
recon_form = result_form.reconciliationform

if not recon_form:
return True

return recon_form.number_ballots_received ==\
recon_form.number_ballots_inside_and_outside_box

def pass_ballot_inside_box_trigger(result_form):
"""The total number of ballots found inside the ballot box must be
equal to the summation of the number of unstamped ballots and the
number of invalid votes (including the blanks) and
the number of valid votes
If the `result_form` does not have a `reconciliation_form` this will
always return True.
:param result_form: The result form to check.
:returns: A boolean of true if passed, otherwise false.
"""
recon_form = result_form.reconciliationform

if not recon_form:
return True

return (
recon_form.number_unstamped_ballots +
recon_form.number_invalid_votes +
recon_form.number_valid_votes
) ==\
recon_form.number_ballots_inside_box

def pass_candidates_votes_trigger(result_form):
"""The total number of the sorted and counted ballots must be
equal to the total votes distributed among the candidates.
If the `result_form` does not have a `reconciliation_form` this will
always return True.
:param result_form: The result form to check.
:returns: A boolean of true if passed, otherwise false.
"""
recon_form = result_form.reconciliationform

if not recon_form:
return True

return recon_form.num_votes == recon_form.number_sorted_and_counted


def pass_tampering(result_form):
"""Guard against errors and tampering with the form.
Expand Down
140 changes: 39 additions & 101 deletions tally_ho/settings/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,118 +196,56 @@

# Quaritine trigger data
QUARANTINE_DATA = [
{'name': 'Trigger 1 - Guard against overvoting',
{'name': 'Registrants trigger',
'description':
str('Check to guard against overvoting. '
'If the result form does not have a reconciliation form this trigger '
' will always pass. '
'If the station for this result_form has an empty registrants field '
'this trigger will always pass. '
'Fails if the number of ballots reported to be used in a '
'station exceeds the number of potential voters minus the number '
'of registrants plus N persons to accomodate staff and security.'),
'method': 'pass_overvote',
str('Summation of the number of cancelled ballots and '
'the number of ballots inside the box must be less than or equal to '
'the number of registered voters at the station.'),
'method': 'pass_registrants_trigger',
'active': True,
'value': 10,
'percentage': 90},
{'name': 'Trigger 2 - Guard against errors and tampering with the form',
'value': 0,
'percentage': 0
},
{'name': 'Voter cards trigger',
'description':
str('Guard against errors and tampering with the form. '
'If the result form does not have a reconciliation form this trigger '
'will always pass. '
'Fails if the sum of the results section of the form does not equal '
'the number of ballots expected based on the calculation of the '
'key fields from the reconciliation form with a N% tolerance.'),
'method': 'pass_tampering',
str('Summation of the number of cancelled ballots and '
'the number of ballots inside the box must be equal to '
'the number of voter cards in the ballot box.'),
'method': 'pass_voter_cards_trigger',
'active': True,
'value': 3,
'percentage': 0},
{'name': 'Trigger 3 - Validate total number of ballots used',
'description':
str('Validate that the total number of received ballots equals the '
'total of the ballots inside the box plus ballots outside the box.'
' If the result form does not have a reconciliation form this trigger'
' will always pass.'),
'method': 'pass_ballots_number_validation',
'active': False,
'value': 2,
'percentage': 0},
{'name': 'Trigger 4 - Validate number of signatures on the voter list',
'description':
str('Validate that the total number of received ballots equals the '
'total of the ballots inside the box plus ballots outside the box. '
'If the result form does not have a reconciliation form this trigger '
'will always pass.'),
'method': 'pass_signatures_validation',
'active': False,
'value': 2,
'percentage': 0},
{'name': 'Trigger 5 - Validate the total number of ballots inside the box',
'description':
str('The total number of ballot papers inside the ballot box will be '
'compared against the total of valid, invalid, and unstamped ballots.'
' If the result form does not have a reconciliation form this trigger'
' will always pass. '
'Fails if the value of the number of ballots inside box from the '
'recon form does not equal the value of the recon property '
'number of ballots inside the box with an N% tolerance.'),
'method': 'pass_ballots_inside_box_validation',
'active': False,
'value': 2,
'percentage': 0},
{'name': 'Trigger 6 - Validate sum of votes distributed to all candidates',
'description':
str('The total votes for candidates should equal the valid ballots: '
'after sorting the ballots inside the ballot box as valid and '
'invalid, and unstamped. The above sum should equal the'
' sum of all candidates votes. '
'If the result form does not have a reconciliation form this trigger '
'will always pass. '
'Fails if the value of the number of valid votes from the recon form '
'does not equal the sum of all candidates votes from the result form '
'with an N% tolerance.'),
'method': 'pass_sum_of_candidates_votes_validation',
'active': False,
'value': 0,
'percentage': 0},
{'name': 'Trigger 7 - Validate percentage of invalid ballots',
'percentage': 0
},
{'name': 'Ballot papers trigger',
'description':
str('Validate the percentage of invalid ballots. '
'If the result form does not have a reconciliation form this trigger '
'will always pass. '
'Fails if the percentage of invalid ballots is greater than the this '
'trigger percentage value.'),
'method': 'pass_invalid_ballots_percentage_validation',
'active': False,
str('The total number of ballots received by the polling station must be'
' equal to total number of ballots found inside and outside the '
'ballot box.'),
'method': 'pass_ballot_papers_trigger',
'active': True,
'value': 0,
'percentage': 20},
{'name': 'Trigger 8 - Validate turnout percentage',
'percentage': 0
},
{'name': 'Ballot inside the box trigger',
'description':
str('Validate the turnout percentage. '
'If the result form does not have a reconciliation form this trigger '
'will always pass. '
'If the station for this result form has an empty registrants field '
'this trigger will always pass. '
'Fails if the turnout percentage is greater than the this '
'trigger percentage value.'),
'method': 'pass_turnout_percentage_validation',
'active': False,
str('The total number of ballots found inside the ballot box must be '
'equal to the summation of the number of unstamped ballots and the '
'number of invalid votes (including the blanks) and '
'the number of valid votes.'),
'method': 'pass_ballot_inside_box_trigger',
'active': True,
'value': 0,
'percentage': 100},
{'name':
'Trigger 9 - Validate percentage of votes per candidate of total votes',
'percentage': 0
},
{'name': 'Candidates votes trigger',
'description':
str('Validate that the percentage of votes per candidate of the total '
'valid votes does not exceed a certain threshold. '
'If the result form does not have a reconciliation form this trigger '
'will always pass. '
'Fails if the percentage of votes for a particular candidate '
'of the total valid votes is greater than the this trigger '
'percentage value.'),
'method': 'pass_percentage_of_votes_per_candidate_validation',
'active': False,
str('The total number of the sorted and counted ballots must be '
'equal to the total votes distributed among the candidates.'),
'method': 'pass_candidates_votes_trigger',
'active': True,
'value': 0,
'percentage': 50},
'percentage': 0
},
]

ELECTROL_RACES = [
Expand Down

0 comments on commit e61ec8e

Please sign in to comment.