예제 #1
0
 def test_irv_01(self):
     candidates = ' A B C'
     ballots = (
         (15, ' A B C'),
         (10, ' B C A'),
         (8, ' C B A'),
     )
     tie_breaker = ' A B C'
     options = {}
     exp_elected = ('B', )
     exp_status = _test_aids.build_expected_status((
         ('A', 'defeated', 2, 15),
         ('B', 'elected', 2, 18),
         ('C', 'defeated', 1, 8),
     ))
     exp_tally = {
         'A': [15, 15],
         'B': [10, 18],
         'C': [8],
         ':Overvotes': [0, 0],
         ':Abstentions': [0, 0],
         ':Other exhausted': [0, 0],
     }
     elected, status, tally = rcv.Tabulation(1, candidates, ballots, 3,
                                             tie_breaker,
                                             options).tabulate()
     status_dict = {
         candidate: status.as_dict()
         for candidate, status in status.items()
     }
     self.assertEqual(set(elected), set(exp_elected))
     self.assertEqual(status_dict, exp_status)
     self.assertEqual(tally, exp_tally)
예제 #2
0
def run_test_spec(test_case, input_json):
    """
  Run a test case using test specs from a JSON text file
  """
    tabulate_args, test_spec = with_json.build_tabulate_args(
        input_json, 'all-tests-spec.json')
    if 'maxDiff' in test_spec:
        maxDiff = test_spec['maxDiff']
        if maxDiff is None:
            test_case.maxDiff = None
        if type(maxDiff) == int and maxDiff >= 0:
            test_case.maxDiff = maxDiff

    try:
        print_description = test_spec['print_description']
    except KeyError:
        print_description = False
    if print_description:
        print('\n  """' + test_spec['description'] + '"""')

    if 'exception' in test_spec:
        exception_type, exception_message = test_spec['exception']
        _test_aids.assertRaises_with_message(test_case, u2s(exception_type),
                                             u2s(exception_message),
                                             rcv.tabulate, tabulate_args)
    else:
        expected_elected = validate.str_tuple(test_spec['elected'])
        expected_status = _test_aids.build_expected_status(
            test_spec['status_codes'])
        expected_tally = {
            _test_aids.u2s(candidate): [
                K.Decimal(vote_total)
                if test_spec['nbr_seats_to_fill'] > 1 else vote_total
                for vote_total in votes
            ]
            for candidate, votes in test_spec['tally'].items()
        }
        elected, status, tally = rcv.Tabulation(*tabulate_args).tabulate()
        if 'print_results' in test_spec and test_spec['print_results']:
            print_elected(elected)
            print_status(status)
            print_tally(tally)
            try:
                description = test_spec['description']
            except KeyError:
                description = None
            jason_str = with_json.results_to_json(elected, status, tally,
                                                  description)
            print(jason_str)
        status_dict = {
            candidate: status.as_dict()
            for candidate, status in status.items()
        }
        test_case.assertEqual(tally, expected_tally)
        test_case.assertEqual(status_dict, expected_status)
        test_case.assertEqual(set(elected), set(expected_elected))
예제 #3
0
 def make_irv_01(self):
     candidates = ' A B C'
     ballots = (
         (15, ' A B C'),
         (10, ' B C A'),
         (8, ' C B A'),
     )
     tie_breaker = ' A B C'
     options = {}
     return rcv.Tabulation(1, candidates, ballots, 3, tie_breaker, options)
예제 #4
0
 def make_stv_01(self):
     candidates = ' A B C D'
     ballots = (
         (15, ' A B C'),
         (8, ' B C D'),
         (1, ' B'),
         (1, ' B #'),
         (8, ' C B A'),
         (5, ' D C B'),
     )
     tie_breaker = ' A B C D'
     options = {}
     return rcv.Tabulation(3, candidates, ballots, 3, tie_breaker, options)
예제 #5
0
 def test_stv_01(self):
     candidates = ' A B C D E'
     ballots = (
         (15, ' A B C D E'),
         (6, ' B C A E D'),
         (3, ' C B A D E'),
         (7, ' D E A B C'),
         (9, ' E D C B A'),
     )
     tie_breaker = ' A B C D E'
     options = {}
     exp_elected = ('A', 'B', 'D')
     exp_status = _test_aids.build_expected_status(
         (('A', 'elected', 1, 15.0), ('B', 'elected', 2, 10.99995),
          ('C', 'defeated', 3, 3.99975), ('D', 'elected', 4, 10.45435),
          ('E', 'defeated', 4, 9.54540)))
     exp_tally = _test_aids.build_stv_tally({
         'A': [15.0, 10.0, 10.0, 10.0],
         'B': [6.0, 10.99995, 10.0, 10.0],
         'C': [3.0, 3.0, 3.99975],
         'D': [7.0, 7.0, 7.0, 10.45435],
         'E': [9.0, 9.0, 9.0, 9.54540],
         ':Overvotes': [0.0, 0.0, 0.0, 0.0],
         ':Abstentions': [0.0, 0.0, 0.0, 0.0],
         ':Other exhausted': [0.0, 0.0, 0.0, 0.0],
         ':Residual surplus': [0.0, 0.00005, 0.00025, 0.00025],
     })
     elected, status, tally = rcv.Tabulation(3, candidates, ballots, 5,
                                             tie_breaker,
                                             options).tabulate()
     status_dict = {
         candidate: status.as_dict()
         for candidate, status in status.items()
     }
     self.assertEqual(set(elected), set(exp_elected))
     self.assertEqual(status_dict, exp_status)
     self.assertEqual(tally, exp_tally)
예제 #6
0
def tabulate(input_json='', output_json='', default_json=None):
    """
  Tabulate an RCV contest using JSON files for input and output

  Arguments
  ---------
  input_json
    A str name of a file or an opened file that is read to get a JSON
    specification of the tabulation to be performed.  If the value is an
    empty str, standard input is read.  If the value is None, nothing is
    read. The JSON specification should be a JSON object with names
    that correspond to the parameters of rcv.Tabulation() initialization.

    Additional names may be specified.  Some that are recognized
    include:

    description
      A description of the contest being tabulated.

    include
      An array of additional input JSON file names that are read.  The
      name / value pairs in included files are subject to being
      overridden by subsequent file names in the array of included file
      names and also, ultimately, contents of the input_json file.  Any
      include value from an included file is ignored.

  output_json
    A str name of a file or an opened file that is written to with a
    JSON specification of the tabulation results.  If the value is an
    empty str, results are written to standard output.  If the value is
    None, nothing is written.  The JSON specification of the tabulation
    result is a JSON object with the following names:

    elected
      An array of winners, corresponding to the first value returned by
      rcv.Tabulation().tabulate().

    status
      An array of status values, each expressed as an array,
      corresponding to the values of the second value returned by
      rcv.Tabulation().tabulate().  The status values are listed in the
      following order:  candidate, status, nbr_round, votes.  For STV,
      votes are expressed as a real number.

    tally
      An object of tally values, corresponding to the third value
      returned by rcv.Tabulation().tabulate().

    description
      A string value of the input description value, if a non-empty
      description value string was provided.  Otherwise, this name is
      not included in the JSON output.

  default_json
    A str name of a file or an opened file that is read to provide
    default values for input_json specification before that file is
    read.  If the value is an empty string, standard input is read.  If
    the value is None, no attempt to read defaults is made.  If both
    this value and the input_json value are empty strings, this value is
    treated as if it were None.  The include name is recognized from
    this file, but its value may be overridden by an include value
    specified in the input_json file.


  Returns
  -------
  A four-tuple consisting of the three values returned by the
  rcv.Tabulation().tabulate() function, and a dict of the input values
  built from input_json and default_json.


  Raises
  ------
  The same as the rcv.Tabulation().tabulate() method, plus other
  exceptions that might be related to accessing files to build the
  tabulation specification or to store its results.

  """
    tabulate_args, tabulation_spec = build_tabulate_args(
        input_json, default_json)
    try:
        description = tabulation_spec['description']
    except KeyError:
        description = None
    elected, status, tally = rcv.Tabulation(*tabulate_args).tabulate()
    json_str = results_to_json(elected, status, tally, description)
    write_file(output_json, s2u(json_str))
    return elected, status, tally, tabulation_spec