Results
Overview
The ballots system provides flexible data visualization and aggregation capabilities for voting results. It supports sorting by multiple criteria, filtering by voters or candidates, and provides various rendering endpoints for displaying ballot data.
Sorting Logic
Primary Sorting Modes
The system supports sorting by different metrics:
- By Date (Default) - Sorts by when votes were cast (
voted_oncolumn) - By Sum - Sorts by total sum of points
- By Mean - Sorts by average score per candidate
- By Weight - Sorts by weighted scores
- By Category - Sorts by a specific category/option name
Sorting Implementation
// From src/ballots.rs#L789-879
pub async fn ballots_sorted(
voting_id: &str,
mode: Option<&str>,
sort: Option<&str>,
voters: Vec<&str>,
candidates: Vec<&str>,
filter: Option<&str>,
) -> Table<Criterion, TableRow>
The sorting logic works as follows:
- Collects all ballots for the specified voting session
- Applies string filtering (if provided)
- Applies candidate/voter filtering (if provided)
- Applies ESC mode (if
mode="esc"):- Groups rows by candidate
- Aggregates votes across all voters
- Calculates mean scores
- Sorts in descending order by sum
- Applies the specified sort criterion to the table rows
ESC Mode (Enhanced Sorting Criteria)
When mode="esc", the system uses the sort_merge_esc function which:
- Groups ballots by candidate
- Merges votes from multiple voters
- Calculates
meanfor each candidate - Sorts results by total sum in descending order
Filtering Logic
String Filtering
The filter_table_by_str function allows filtering by comma-separated tokens:
// From src/ballots.rs#L755-787
fn filter_table_by_str(
table: Table<Criterion, TableRow>,
filter: &str,
) -> Table<Criterion, TableRow>
Behavior:
- Accepts a comma-separated string of terms
- Matches rows where the candidate name or any vote name contains the term (case-insensitive)
- Example:
filter="candidate1,candidate2"will match rows with either candidate
Candidate/Voter Filtering
The filter_row_on_candidates function provides precise filtering:
// From src/ballots.rs#L594-685
fn filter_row_on_candidates(
rows: Table<Criterion, TableRow>,
voters: Vec<&str>,
candidates: Vec<&str>,
) -> Table<Criterion, TableRow>
Behavior:
- Takes vectors of voter names and candidate names as filter criteria
- Uses case-insensitive substring matching
- If
votersvector is empty, all voters are included - If
candidatesvector is empty, all candidates are included - Rows must match BOTH voter AND candidate criteria (if both are specified)
- Aggregates results by candidate
Filter Order of Operations
// From src/ballots.rs#L789-879
table = filter_table_by_str(table, extracted_filter); // First: String filter
table = filter_row_on_candidates(table, voters, candidates); // Second: Candidate/voter filterAvailable Render Endpoints
1. Ballots by Voted On
Endpoint: GET /ballots/<voting_id>
// From src/templates/ballots.rs#L17-27
#[get("/<voting_id>")]
pub async fn render_ballots_by_voted_on(voting_id: &str)
Description: Lists all ballots in chronological order by when they were cast.
Template: cast-ballots
2. Ballots with Advanced Filtering & Sorting
Endpoint: GET /ballots/<voting_id>/results?sort=...&mode=...&voter=...&candidate=...&filter=...
// From src/templates/ballots.rs#L29-51
#[get("/<voting_id>/results?<sort>&<mode>&<voter>&<candidate>&<filter>")]
pub async fn render_ballots_sorted(
voting_id: &str,
sort: Option<&str>,
mode: Option<&str>,
voter: Vec<&str>,
candidate: Vec<&str>,
filter: Option<&str>,
)
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
voting_id | path | The voting session identifier |
sort | query | Sort criterion: date, sum, mean, weight, or category:<name> |
mode | query | Rendering mode: esc for ESC mode, or no-esc (default) |
voter | query | Vector of voter names to filter by |
candidate | query | Vector of candidate names to filter by |
filter | query | Comma-separated string filter for candidates/vote names |
Sort Options:
date- Sort by voting date (default)sum- Sort by total sum (descending)mean- Sort by average score (descending)weight- Sort by weighted score (descending)category:<name>- Sort by a specific category (descending)
Mode Options:
esc- Use ESC mode (grouped by candidate, aggregated votes, sorted by sum)no-esc- Individual rows, not aggregated
Templates: esc or cast-ballots (depending on mode)
3. Ballots by Specific Voter
Endpoint: GET /ballots/<voting_id>/voters/<voter>
// From src/templates/ballots.rs#L53-63
#[get("/<voting_id>/voters/<voter>")]
pub async fn render_ballots_by_voter(
voting_id: &str,
voter: &str,
)
Description: Shows all ballots cast by a specific voter for the voting session.
Template: cast-user-ballots
Response: If no ballots found, renders missing-data template.
4. Ballots by Specific Candidate
Endpoint: GET /ballots/<voting_id>/candidates/<candidate>
// From src/templates/ballots.rs#L65-75
#[get("/<voting_id>/candidates/<candidate>")]
pub async fn render_ballots_by_candidate(
voting_id: &str,
candidate: &str,
)
Description: Shows all ballots received by a specific candidate.
Template: cast-user-ballots
Response: If no ballots found, renders missing-data template.
Data Structure
TableRow
pub struct TableRow {
pub voting: String, // Voting session identifier
pub voter: String, // Voter identifier
pub candidate: String, // Candidate identifier
pub sum: i8, // Total sum of points
pub weighted: f64, // Weighted score
pub mean: f64, // Average score
notes: String, // Additional notes
votes: Vec<Vote>, // Array of individual votes
pub voted_on: String, // Timestamp of vote
}Usage Examples
Example 1: Show All Ballots Chronologically
GET /ballots/12345Example 2: Sort by Sum (ESC Mode)
GET /ballots/12345/results?sort=sum&mode=escExample 3: Filter by Specific Voter and Candidate
GET /ballots/12345/results?sort=mean&voter=john_doe&candidate=alice_smithExample 4: Filter by Category
GET /ballots/12345/results?sort=category:technical&mode=escExample 5: String Filter
GET /ballots/12345/results?filter=candidate1,candidate2Example 6: View Ballots by Specific Voter
GET /ballots/12345/voters/john_doeExample 7: View Ballots by Specific Candidate
GET /ballots/12345/candidates/alice_smithSummary
The ballots system provides a flexible and powerful way to:
- Sort by multiple criteria (date, sum, mean, weight, or category)
- Filter using precise criteria (voter/candidate names) or loose string matching
- Aggregate votes across multiple voters when using ESC mode
- Display different views for administrative and end-user purposes
The system automatically handles edge cases like missing data and provides appropriate templates for different scenarios.