forked from cdos-rla/colorado-rla
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #139 from DemocracyDevelopers/73-generate-assertio…
…ns-endpoint 73 generate assertions endpoint
- Loading branch information
Showing
19 changed files
with
1,014 additions
and
175 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
50 changes: 50 additions & 0 deletions
50
...opers/corla/communication/responseToColoradoRla/GenerateAssertionsResponseWithErrors.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
/* | ||
Democracy Developers IRV extensions to colorado-rla. | ||
@copyright 2024 Colorado Department of State | ||
These IRV extensions are designed to connect to a running instance of the raire | ||
service (https://github.com/DemocracyDevelopers/raire-service), in order to | ||
generate assertions that can be audited using colorado-rla. | ||
The colorado-rla IRV extensions are free software: you can redistribute it and/or modify it under the terms | ||
of the GNU Affero General Public License as published by the Free Software Foundation, either | ||
version 3 of the License, or (at your option) any later version. | ||
The colorado-rla IRV extensions are distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; | ||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
See the GNU Affero General Public License for more details. | ||
You should have received a copy of the GNU Affero General Public License along with | ||
raire-service. If not, see <https://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
package au.org.democracydevelopers.corla.communication.responseToColoradoRla; | ||
|
||
import java.beans.ConstructorProperties; | ||
|
||
/** | ||
* The response to be sent to colorado-rla after a GenerateAssertionsRequest. | ||
* These are identified by contest name. | ||
* The success response is simply a winner and an empty error string. | ||
* Error responses have some non-empty error and usually a winner set to "UNKNOWN". | ||
* Note that errors may sometimes have a real winner, though they usually don't. For example, if trimming assertions | ||
* times out, there will be both a statement of that error and a real winner. | ||
*/ | ||
public final class GenerateAssertionsResponseWithErrors { | ||
public final String contestName; | ||
public final String winner; | ||
public final String raireError; | ||
|
||
/** | ||
* @param contestName The name of the contest. | ||
* @param winner The winner of the contest, as calculated by raire. | ||
* @param raireError The error message returned from raire. Empty if there was no error. | ||
*/ | ||
@ConstructorProperties({"contestName", "winner", "raireError"}) | ||
public GenerateAssertionsResponseWithErrors(String contestName, String winner, String raireError) { | ||
this.contestName = contestName; | ||
this.winner = winner; | ||
this.raireError = raireError; | ||
} | ||
} |
116 changes: 116 additions & 0 deletions
116
...oject/src/main/java/au/org/democracydevelopers/corla/endpoint/AbstractAllIrvEndpoint.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
/* | ||
Democracy Developers IRV extensions to colorado-rla. | ||
@copyright 2024 Colorado Department of State | ||
These IRV extensions are designed to connect to a running instance of the raire | ||
service (https://github.com/DemocracyDevelopers/raire-service), in order to | ||
generate assertions that can be audited using colorado-rla. | ||
The colorado-rla IRV extensions are free software: you can redistribute it and/or modify it under the terms | ||
of the GNU Affero General Public License as published by the Free Software Foundation, either | ||
version 3 of the License, or (at your option) any later version. | ||
The colorado-rla IRV extensions are distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; | ||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
See the GNU Affero General Public License for more details. | ||
You should have received a copy of the GNU Affero General Public License along with | ||
raire-service. If not, see <https://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
package au.org.democracydevelopers.corla.endpoint; | ||
|
||
import au.org.democracydevelopers.corla.model.ContestType; | ||
import com.google.gson.Gson; | ||
import org.apache.http.impl.client.CloseableHttpClient; | ||
import org.apache.http.impl.client.HttpClients; | ||
import org.apache.log4j.LogManager; | ||
import org.apache.log4j.Logger; | ||
import us.freeandfair.corla.asm.ASMEvent; | ||
import us.freeandfair.corla.controller.ContestCounter; | ||
import us.freeandfair.corla.endpoint.AbstractDoSDashboardEndpoint; | ||
import us.freeandfair.corla.model.*; | ||
import java.util.List; | ||
|
||
/** | ||
* An abstract endpoint for communicating with raire. Includes all the information for collecting IRV contests | ||
* and making a request to raire, including the location of the raire service. | ||
* Used by GetAssertions and GenerateAssertions. | ||
*/ | ||
public abstract class AbstractAllIrvEndpoint extends AbstractDoSDashboardEndpoint { | ||
|
||
/** | ||
* Class-wide logger | ||
*/ | ||
private static final Logger LOGGER = LogManager.getLogger(AbstractAllIrvEndpoint.class); | ||
|
||
/** | ||
* GSON, for serialising requests. | ||
*/ | ||
protected final Gson gson = new Gson(); | ||
|
||
/** | ||
* Identify RAIRE service URL from config. | ||
*/ | ||
protected static final String RAIRE_URL = "raire_url"; | ||
|
||
/** | ||
* The httpClient used for making requests to the raire-service. | ||
*/ | ||
protected final CloseableHttpClient httpClient = HttpClients.createDefault(); | ||
|
||
|
||
/** | ||
* The event to return for this endpoint. | ||
*/ | ||
protected final ThreadLocal<ASMEvent> my_event = new ThreadLocal<>(); | ||
|
||
/** | ||
* @return State admin authorization is necessary for this endpoint. | ||
*/ | ||
public AuthorizationType requiredAuthorization() { return AuthorizationType.STATE; } | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
@Override | ||
protected ASMEvent endpointEvent() { | ||
return my_event.get(); | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
@Override | ||
protected void reset() { | ||
my_event.set(null); | ||
} | ||
|
||
/** | ||
* Get all the ContestResults whose contests are consistently IRV. | ||
* @return A list of all ContestResults for IRV contests. | ||
* @throws RuntimeException if it encounters contests with a mix of IRV and any other contest type. | ||
*/ | ||
public static List<ContestResult> getIRVContestResults() { | ||
final String prefix = "[getIRVContestResults]"; | ||
final String msg = "Inconsistent contest types:"; | ||
|
||
// Find all the ContestResults with any that match IRV. | ||
List<ContestResult> results = ContestCounter.countAllContests().stream() | ||
.filter(cr -> cr.getContests().stream().map(Contest::description) | ||
.anyMatch(d -> d.equalsIgnoreCase(ContestType.IRV.toString()))).toList(); | ||
|
||
// The above should be sufficient, but just in case, check that each contest we found _all_ matches IRV, and | ||
// throw a RuntimeException if not. | ||
for (final ContestResult cr : results) { | ||
if (cr.getContests().stream().map(Contest::description) | ||
.anyMatch(d -> !d.equalsIgnoreCase(ContestType.IRV.toString()))) { | ||
LOGGER.error(String.format("%s %s %s", prefix, msg, cr.getContestName())); | ||
throw new RuntimeException(msg + cr.getContestName()); | ||
} | ||
} | ||
|
||
return results; | ||
} | ||
} |
Oops, something went wrong.