summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/candidates.adb271
-rw-r--r--src/candidates.ads136
-rw-r--r--src/stv.adb1
3 files changed, 368 insertions, 40 deletions
diff --git a/src/candidates.adb b/src/candidates.adb
index 3701ffc..bb09a40 100644
--- a/src/candidates.adb
+++ b/src/candidates.adb
@@ -1,42 +1,291 @@
with Ada.Text_IO;
-use Ada.Text_IO;
with CSV;
package body Candidates is
+ function To_String
+ (Input_Candidate : in Candidate;
+ Delimiter : in Character := ',')
+ return String
+ is
+ package My_CSV is new CSV (Delimiter => Delimiter);
+ use type My_CSV.String_Vectors.Vector;
+
+ My_Record : My_CSV.CSV_Record;
+ begin
+ My_Record :=
+ My_CSV.String_Vectors.Empty_Vector &
+ Input_Candidate.Group &
+ Input_Candidate.Group_Rank &
+ Input_Candidate.First_Name &
+ Input_Candidate.Last_Name &
+ Input_Candidate.Party;
+ return My_CSV.Unparse_Record (My_Record);
+ end To_String;
+
+
+
+
procedure Read_Candidates
- (Data_File, State : in String;
- Above_Ballot : out Above_Line_Ballot;
- Below_Ballot : out Below_Line_Ballot;
- Candidate_List : out Candidate_Vectors.Vector)
+ (Filename, State : in String;
+ Candidate_List : out Candidate_Vector)
is
+ package My_CSV is new CSV;
+ use Ada.Text_IO;
+ use type Ada.Containers.Count_Type;
+ use type SU.Unbounded_String;
+
+ Input_File : File_Type;
+ Current_Record : My_CSV.CSV_Record;
+ Current_Candidate : Candidate;
+ begin
+ Open (Input_File, In_File, Filename);
+ Candidate_List := (Vec => Candidate_Vectors.Empty_Vector);
+
+ while not End_Of_File (Input_File) loop
+ Current_Record := My_CSV.Parse_Line (Get_Line (Input_File));
+
+ -- all the field numbers here correspond to how
+ -- AEC Senate candidate data is arranged in csv format
+ if Current_Record.Length = 25 and then
+ Current_Record.Element (2) = "S" and then
+ Current_Record.Element (3) = State
+ then
+ Current_Candidate :=
+ (First_Name => Current_Record.Element (8),
+ Last_Name => Current_Record.Element (7),
+ Group => Current_Record.Element (5),
+ Group_Rank => Current_Record.Element (6),
+ Party => Current_Record.Element (9));
+ Candidate_List.Vec.Append (Current_Candidate);
+ end if;
+ end loop;
+
+ Close (Input_File);
+ end Read_Candidates;
+
+
+
+
+ function First
+ (Candidate_List : in Candidate_Vector)
+ return CandidateID is
+ begin
+ return Candidate_List.Vec.First_Index;
+ end First;
+
+
+
+
+ function Last
+ (Candidate_List : in Candidate_Vector)
+ return CandidateID is
+ begin
+ return Candidate_List.Vec.Last_Index;
+ end Last;
+
+
+
+
+ function Lookup
+ (Candidate_List : in Candidate_Vector;
+ Index : in CandidateID)
+ return Candidate is
begin
- end Read_Candidate;
+ return Candidate_List.Vec.Element (Index);
+ end Lookup;
+
+
+
+
+ function First
+ (CandidateID_List : in CandidateID_Vector)
+ return Positive is
+ begin
+ return CandidateID_List.Vec.First_Index;
+ end First;
+
+
+
+
+ function Last
+ (CandidateID_List : in CandidateID_Vector)
+ return Positive is
+ begin
+ return CandidateID_List.Vec.Last_Index;
+ end Last;
+
+
+
+
+ function Lookup
+ (CandidateID_List : in CandidateID_Vector;
+ Index : in Positive)
+ return CandidateID is
+ begin
+ return CandidateID_List.Vec.Element (Index);
+ end Lookup;
+
+
+
+
+ function "<"
+ (Left, Right : Candidate)
+ return Boolean
+ is
+ use type SU.Unbounded_String;
+ begin
+ if SU.Length (Left.Group) = SU.Length (Right.Group) then
+ if Left.Group = Right.Group then
+ return Left.Group_Rank < Right.Group_Rank;
+ else
+ return Left.Group < Right.Group;
+ end if;
+ else
+ return SU.Length (Left.Group) < SU.Length (Right.Group);
+ end if;
+ end "<";
+
+
+
+
+ function Generate_Above
+ (Candidate_List : in Candidate_Vector)
+ return Above_Line_Ballot
+ is
+ use type Ada.Containers.Count_Type;
+ use type SU.Unbounded_String;
+
+ Result : Above_Line_Ballot;
+ Working_Vector : CandidateID_Vector;
+ Current_Group : SU.Unbounded_String;
+ Current_Index : CandidateID;
+ begin
+ Result := (Vec => Above_Line_Ballots.Empty_Vector);
+
+ if Candidate_List.Vec.Length = 0 then
+ return Result;
+ end if;
+
+ Current_Index := Candidate_List.Vec.First_Index;
+ while Current_Index <= Candidate_List.Vec.Last_Index loop
+ Current_Group := Candidate_List.Vec.Element (Current_Index).Group;
+
+ -- the assumption is that the "UG" group is always last
+ -- a fairly safe assumption given alphabetical group order
+ exit when Current_Group = "UG";
+
+ Working_Vector := (Vec => CandidateID_Vectors.Empty_Vector);
+ loop
+ Working_Vector.Vec.Append (Current_Index);
+ Current_Index := Current_Index + 1;
+ exit when Current_Index > Candidate_List.Vec.Last_Index or else
+ Current_Group /= Candidate_List.Vec.Element (Current_Index).Group;
+ end loop;
+ Result.Vec.Append (Working_Vector);
+ end loop;
+
+ return Result;
+ end Generate_Above;
+
+
+
+
+ function Generate_Below
+ (Candidate_List : in Candidate_Vector)
+ return Below_Line_Ballot
+ is
+ Result : Below_Line_Ballot;
+ begin
+ Result := (Vec => CandidateID_Vectors.Empty_Vector);
+ for ID in CandidateID range Candidate_List.Vec.First_Index .. Candidate_List.Vec.Last_Index loop
+ Result.Vec.Append (ID);
+ end loop;
+ return Result;
+ end Generate_Below;
+
+
+
+
+ procedure Generate_Ballots
+ (Candidate_List : in Candidate_Vector;
+ Above_Ballot : out Above_Line_Ballot;
+ Below_Ballot : out Below_Line_Ballot)
+ is
+ package Sorting is new Candidate_Vectors.Generic_Sorting;
+
+ My_Candidate_List : Candidate_Vector;
+ begin
+ My_Candidate_List := Candidate_List;
+ Sorting.Sort (My_Candidate_List.Vec);
+ Above_Ballot := Generate_Above (My_Candidate_List);
+ Below_Ballot := Generate_Below (My_Candidate_List);
+ end Generate_Ballots;
+
+
+
+
+ function First
+ (Above_Ballot : in Above_Line_Ballot)
+ return Positive is
+ begin
+ return Above_Ballot.Vec.First_Index;
+ end First;
+
+
+
+
+ function Last
+ (Above_Ballot : in Above_Line_Ballot)
+ return Positive is
+ begin
+ return Above_Ballot.Vec.Last_Index;
+ end Last;
function Lookup
(Above_Ballot : in Above_Line_Ballot;
- Index : in Natural)
- return CandidateID_Vectors.Vector is
+ Index : in Positive)
+ return CandidateID_Vector is
begin
- return Above_Ballot.Element (Index);
+ return Above_Ballot.Vec.Element (Index);
end Lookup;
+ function First
+ (Below_Ballot : in Below_Line_Ballot)
+ return Positive is
+ begin
+ return Below_Ballot.Vec.First_Index;
+ end First;
+
+
+
+
+ function Last
+ (Below_Ballot : in Below_Line_Ballot)
+ return Positive is
+ begin
+ return Below_Ballot.Vec.Last_Index;
+ end Last;
+
+
+
+
function Lookup
(Below_Ballot : in Below_Line_Ballot;
- Index : in Natural)
+ Index : in Positive)
return CandidateID is
begin
- return Below_Ballot.Element (Index);
+ return Below_Ballot.Vec.Element (Index);
end Lookup;
diff --git a/src/candidates.ads b/src/candidates.ads
index 90b2425..fb04a4e 100644
--- a/src/candidates.ads
+++ b/src/candidates.ads
@@ -1,73 +1,151 @@
-with Ada.Containers.Vectors;
+private with Ada.Strings.Unbounded;
+private with Ada.Containers.Vectors;
package Candidates is
type Candidate is private;
- type CandidateID is Natural;
+ type CandidateID is new Positive;
+
+
+ function To_String
+ (Input_Candidate : in Candidate;
+ Delimiter : in Character := ',')
+ return String;
+
+
+
+
+ type Candidate_Vector is private;
+ type CandidateID_Vector is private;
+
+
+ procedure Read_Candidates
+ (Filename, State : in String;
+ Candidate_List : out Candidate_Vector);
+
+
+ function First
+ (Candidate_List : in Candidate_Vector)
+ return CandidateID;
+
+
+ function Last
+ (Candidate_List : in Candidate_Vector)
+ return CandidateID;
+
+
+ function Lookup
+ (Candidate_List : in Candidate_Vector;
+ Index : in CandidateID)
+ return Candidate;
+
+
+ function First
+ (CandidateID_List : in CandidateID_Vector)
+ return Positive;
+
+
+ function Last
+ (CandidateID_List : in CandidateID_Vector)
+ return Positive;
+
+
+ function Lookup
+ (CandidateID_List : in CandidateID_Vector;
+ Index : in Positive)
+ return CandidateID;
+
+
type Above_Line_Ballot is private;
type Below_Line_Ballot is private;
- package Candidate_Vectors is new Ada.Containers.Vectors
- (Index_Type => CandidateID,
- Element_Type => Candidate);
+ procedure Generate_Ballots
+ (Candidate_List : in Candidate_Vector;
+ Above_Ballot : out Above_Line_Ballot;
+ Below_Ballot : out Below_Line_Ballot);
- package CandidateID_Vectors is new Ada.Containers.Vectors
- (Index_Type => Natural,
- Element_Type => CandidateID);
+ function First
+ (Above_Ballot : in Above_Line_Ballot)
+ return Positive;
- procedure Read_Candidates
- (Data_File, State : in String;
- Above_Ballot : out Above_Line_Ballot;
- Below_Ballot : out Below_Line_Ballot;
- Candidate_List : out Candidate_Vectors.Vector);
+ function Last
+ (Above_Ballot : in Above_Line_Ballot)
+ return Positive;
function Lookup
(Above_Ballot : in Above_Line_Ballot;
- Index : in Natural)
- return CandidateID_Vectors.Vector;
+ Index : in Positive)
+ return CandidateID_Vector;
+
+
+ function First
+ (Below_Ballot : in Below_Line_Ballot)
+ return Positive;
+
+
+ function Last
+ (Below_Ballot : in Below_Line_Ballot)
+ return Positive;
function Lookup
(Below_Ballot : in Below_Line_Ballot;
- Index : in Natural)
+ Index : in Positive)
return CandidateID;
private
+ package SU renames Ada.Strings.Unbounded;
+
+
type Candidate is record
- ID : CandidateID;
- First_Name : String;
- Last_Name : String;
- Group : String;
- Group_Rank : Natural;
- Party : String;
+ First_Name : SU.Unbounded_String;
+ Last_Name : SU.Unbounded_String;
+ Group : SU.Unbounded_String;
+ Group_Rank : SU.Unbounded_String;
+ Party : SU.Unbounded_String;
end record;
- package Above_Line_Ballots is new Ada.Containers.Vectors
- (Index_Type => Natural,
- Element_Type => CandidateID_Vectors.Vector);
+ package Candidate_Vectors is new Ada.Containers.Vectors
+ (Index_Type => CandidateID,
+ Element_Type => Candidate);
+ type Candidate_Vector is record
+ Vec : Candidate_Vectors.Vector;
+ end record;
- package Below_Line_Ballots is new Ada.Containers.Vectors
- (Index_Type => Natural,
+ package CandidateID_Vectors is new Ada.Containers.Vectors
+ (Index_Type => Positive,
Element_Type => CandidateID);
+ type CandidateID_Vector is record
+ Vec : CandidateID_Vectors.Vector;
+ end record;
+
+
+ package Above_Line_Ballots is new Ada.Containers.Vectors
+ (Index_Type => Positive,
+ Element_Type => CandidateID_Vector);
+ type Above_Line_Ballot is record
+ Vec : Above_Line_Ballots.Vector;
+ end record;
- type Above_Line_Ballot is Above_Line_Ballots.Vector;
- type Below_Line_Ballot is Below_Line_Ballots.Vector;
+ type Below_Line_Ballot is record
+ Vec : CandidateID_Vectors.Vector;
+ end record;
end Candidates;
diff --git a/src/stv.adb b/src/stv.adb
index 3297da2..a7d6c6d 100644
--- a/src/stv.adb
+++ b/src/stv.adb
@@ -3,6 +3,7 @@
with Ada.Text_IO;
with Ada.Strings.Unbounded;
with CSV;
+with Candidates;
procedure STV is