# Path: dividebatur/aecdata/candidatelist.py
# class CandidateList:
#     """CandidateList provides a list of senate candidates and groups.
# 
#     The following members are publicly accessible:
# 
#       - candidates: a list of all candidates, in the order they appear
#         on the ballot.
#       - candidate_by_id: a dictionary mapping candidate IDs to the candidate.
#       - groups: a list of groups, in the order they appear on the
#         ballot.  Does not include the ungrouped candidates.
#       - group_by_id: a dictionary mapping group IDs (e.g. A, B, ...)
#         to the group.
#     """
# 
#     def __init__(self, state, all_candidates_csv, senate_candidates_csv):
#         self.state = state
#         self._load(all_candidates_csv, senate_candidates_csv)
# 
#     def _load(self, all_candidates_csv, senate_candidates_csv):
#         self.candidates = []
#         self.candidate_by_id = {}
#         self.groups = []
#         self.group_by_id = {}
# 
#         candidate_by_name_party, party_ab = self._load_senate_candidates(
#             senate_candidates_csv)
#         current_group = None
#         current_party = None
#         current_candidates = []
#         for c in self._load_all_candidates(all_candidates_csv):
#             if c.ticket != current_group:
#                 if current_group is not None and current_group != "UG":
#                     group = Group(current_group,
#                                   current_party,
#                                   party_ab[current_party],
#                                   tuple(current_candidates))
#                     self.groups.append(group)
#                     self.group_by_id[group.group_id] = group
#                 current_group = c.ticket
#                 current_party = c.party_ballot_nm
#                 current_candidates = []
# 
#             candidate_id = candidate_by_name_party[
#                 c.surname, c.ballot_given_nm, c.party_ballot_nm]
#             candidate = Candidate(candidate_id,
#                                   c.surname,
#                                   c.ballot_given_nm,
#                                   len(self.candidates),
#                                   current_group,
#                                   c.ballot_position,
#                                   c.party_ballot_nm,
#                                   party_ab[c.party_ballot_nm])
#             self.candidates.append(candidate)
#             self.candidate_by_id[candidate.candidate_id] = candidate
#             current_candidates.append(candidate)
# 
#         # Add the final group, assuming it isn't the ungrouped candidates
#         if current_group is not None and current_group != "UG":
#             group = Group(current_group,
#                           current_party,
#                           party_ab[current_party],
#                           tuple(current_candidates))
#             self.groups.append(group)
#             self.group_by_id[group.group_id] = group
# 
#     def _load_all_candidates(self, all_candidates_csv):
#         candidates = []
#         with open(all_candidates_csv, 'rt') as fd:
#             reader = csv.reader(fd)
#             header = next(reader)
#             for candidate in sorted(named_tuple_iter('AllCandidate', reader, header, ballot_position=int), key=lambda row: (ticket_sort_key(row.ticket), row.ballot_position)):
#                 if candidate.state_ab != self.state:
#                     continue
#                 if candidate.nom_ty != 'S':
#                     continue
#                 candidates.append(candidate)
#         return candidates
# 
#     def _load_senate_candidates(self, senate_candidates_csv):
#         by_name_party = {}
#         party_ab = {}
#         seen_ids = set()
#         with open(senate_candidates_csv, 'rt') as fd:
#             reader = csv.reader(fd)
#             next(reader)  # skip the version
#             header = next(reader)
#             for candidate in named_tuple_iter(
#                     'Candidate', reader, header, CandidateID=int):
#                 if candidate.StateAb != self.state:
#                     continue
#                 k = (candidate.Surname, candidate.GivenNm, candidate.PartyNm)
#                 assert candidate.CandidateID not in seen_ids
#                 assert k not in by_name_party
#                 by_name_party[k] = candidate.CandidateID
#                 seen_ids.add(candidate.CandidateID)
#                 party_ab[candidate.PartyNm] = candidate.PartyAb
#         return by_name_party, party_ab
# 
#     def get_candidate_id(self, surname, given_name):
#         for candidate in self.candidates:
#             if candidate.surname == surname and candidate.given_name == given_name:
#                 return candidate.candidate_id
#         raise KeyError((surname, given_name))


import os
import unittest
import dividebatur
from dividebatur.aecdata import CandidateList
        self.assertEqual(4, last_candidate.ballot_position)
        self.assertEqual("Independent", last_candidate.party_name)
        self.assertEqual("IND", last_candidate.party_abbreviation)

        first_group = cl.groups[0]
        self.assertEqual("A", first_group.group_id)
        self.assertEqual("Liberal Democrats", first_group.party_name)
        self.assertEqual("LDP", first_group.party_abbreviation)
        self.assertEqual(2, len(first_group.candidates))
        self.assertIs(first_candidate, first_group.candidates[0])

        # Even though the "UG" candidates appear last on the ballot,
        # they do not count as a group.
        last_group = cl.groups[-1]
        self.assertEqual("AR", last_group.group_id)
        self.assertEqual("One Nation", last_group.party_name)
        self.assertEqual("ON", last_group.party_abbreviation)

        # Lookup by ID
        self.assertIs(first_candidate, cl.candidate_by_id[24801])
        self.assertIs(last_group, cl.group_by_id["AR"])

    def test_fed2016(self):
        all_candidates_csv = os.path.join(
            datadir, "fed2016", "common",
            "2016federalelection-all-candidates-nat-30-06-924.csv")
        senate_candidates_csv = os.path.join(
            datadir, "fed2016", "common",
            "SenateCandidatesDownload-20499.csv")


# Path: dividebatur/aecdata/candidatelist.py
# class CandidateList:
#     """CandidateList provides a list of senate candidates and groups.
# 
#     The following members are publicly accessible:
# 
#       - candidates: a list of all candidates, in the order they appear
#         on the ballot.
#       - candidate_by_id: a dictionary mapping candidate IDs to the candidate.
#       - groups: a list of groups, in the order they appear on the
#         ballot.  Does not include the ungrouped candidates.
#       - group_by_id: a dictionary mapping group IDs (e.g. A, B, ...)
#         to the group.
#     """
# 
#     def __init__(self, state, all_candidates_csv, senate_candidates_csv):
#         self.state = state
#         self._load(all_candidates_csv, senate_candidates_csv)
# 
#     def _load(self, all_candidates_csv, senate_candidates_csv):
#         self.candidates = []
#         self.candidate_by_id = {}
#         self.groups = []
#         self.group_by_id = {}
# 
#         candidate_by_name_party, party_ab = self._load_senate_candidates(
#             senate_candidates_csv)
#         current_group = None
#         current_party = None
#         current_candidates = []
#         for c in self._load_all_candidates(all_candidates_csv):
#             if c.ticket != current_group:
#                 if current_group is not None and current_group != "UG":
#                     group = Group(current_group,
#                                   current_party,
#                                   party_ab[current_party],
#                                   tuple(current_candidates))
#                     self.groups.append(group)
#                     self.group_by_id[group.group_id] = group
#                 current_group = c.ticket
#                 current_party = c.party_ballot_nm
#                 current_candidates = []
# 
#             candidate_id = candidate_by_name_party[
#                 c.surname, c.ballot_given_nm, c.party_ballot_nm]
#             candidate = Candidate(candidate_id,
#                                   c.surname,
#                                   c.ballot_given_nm,
#                                   len(self.candidates),
#                                   current_group,
#                                   c.ballot_position,
#                                   c.party_ballot_nm,
#                                   party_ab[c.party_ballot_nm])
#             self.candidates.append(candidate)
#             self.candidate_by_id[candidate.candidate_id] = candidate
#             current_candidates.append(candidate)
# 
#         # Add the final group, assuming it isn't the ungrouped candidates
#         if current_group is not None and current_group != "UG":
#             group = Group(current_group,
#                           current_party,
#                           party_ab[current_party],
#                           tuple(current_candidates))
#             self.groups.append(group)
#             self.group_by_id[group.group_id] = group
# 
#     def _load_all_candidates(self, all_candidates_csv):
#         candidates = []
#         with open(all_candidates_csv, 'rt') as fd:
#             reader = csv.reader(fd)
#             header = next(reader)
#             for candidate in sorted(named_tuple_iter('AllCandidate', reader, header, ballot_position=int), key=lambda row: (ticket_sort_key(row.ticket), row.ballot_position)):
#                 if candidate.state_ab != self.state:
#                     continue
#                 if candidate.nom_ty != 'S':
#                     continue
#                 candidates.append(candidate)
#         return candidates
# 
#     def _load_senate_candidates(self, senate_candidates_csv):
#         by_name_party = {}
#         party_ab = {}
#         seen_ids = set()
#         with open(senate_candidates_csv, 'rt') as fd:
#             reader = csv.reader(fd)
#             next(reader)  # skip the version
#             header = next(reader)
#             for candidate in named_tuple_iter(
#                     'Candidate', reader, header, CandidateID=int):
#                 if candidate.StateAb != self.state:
#                     continue
#                 k = (candidate.Surname, candidate.GivenNm, candidate.PartyNm)
#                 assert candidate.CandidateID not in seen_ids
#                 assert k not in by_name_party
#                 by_name_party[k] = candidate.CandidateID
#                 seen_ids.add(candidate.CandidateID)
#                 party_ab[candidate.PartyNm] = candidate.PartyAb
#         return by_name_party, party_ab
# 
#     def get_candidate_id(self, surname, given_name):
#         for candidate in self.candidates:
#             if candidate.surname == surname and candidate.given_name == given_name:
#                 return candidate.candidate_id
#         raise KeyError((surname, given_name))


# Path: dividebatur/tests/test_candidatelist.py
import os
import unittest
import dividebatur
from dividebatur.aecdata import CandidateList

        self.assertEqual(4, last_candidate.ballot_position)
        self.assertEqual("Independent", last_candidate.party_name)
        self.assertEqual("IND", last_candidate.party_abbreviation)

        first_group = cl.groups[0]
        self.assertEqual("A", first_group.group_id)
        self.assertEqual("Liberal Democrats", first_group.party_name)
        self.assertEqual("LDP", first_group.party_abbreviation)
        self.assertEqual(2, len(first_group.candidates))
        self.assertIs(first_candidate, first_group.candidates[0])

        # Even though the "UG" candidates appear last on the ballot,
        # they do not count as a group.
        last_group = cl.groups[-1]
        self.assertEqual("AR", last_group.group_id)
        self.assertEqual("One Nation", last_group.party_name)
        self.assertEqual("ON", last_group.party_abbreviation)

        # Lookup by ID
        self.assertIs(first_candidate, cl.candidate_by_id[24801])
        self.assertIs(last_group, cl.group_by_id["AR"])

    def test_fed2016(self):
        all_candidates_csv = os.path.join(
            datadir, "fed2016", "common",
            "2016federalelection-all-candidates-nat-30-06-924.csv")
        senate_candidates_csv = os.path.join(
            datadir, "fed2016", "common",
            "SenateCandidatesDownload-20499.csv")


        cl = CandidateList("WA", all_candidates_csv, senate_candidates_csv)