start javaFX window from voting booth ToyRun

android-scanner
Laura Radaelli 2016-12-13 10:23:51 +02:00
parent 971db5d89c
commit 0b1d334d3c
9 changed files with 1061 additions and 19 deletions

2
.gitignore vendored
View File

@ -16,3 +16,5 @@ out
*.db
*.sql
.arcconfig
/meerkat_election_params_tempfile.dat
/meerkat_booth_system_messages.dat

View File

@ -0,0 +1,32 @@
package meerkat.voting.gui.managment;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.ImageIcon;
import java.awt.image.BufferedImage;
import java.awt.Dimension;
import java.awt.Toolkit;
import javax.imageio.ImageIO;
import java.io.File;
import java.io.IOException;
public class Printer {
public static void printBallot(String filename) throws IOException {
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// bi = ImageIO.read(ImageResourceDemo.class.getResource("../resource/avatar6.jpeg"));
BufferedImage bi = ImageIO.read(new File(filename));
frame.add(new JLabel(new ImageIcon(bi)));
frame.pack();
frame.setAlwaysOnTop(true);
frame.setLocationRelativeTo(null);
Dimension screenSize = new Dimension(Toolkit.getDefaultToolkit().getScreenSize());
int wdwLeft = 500 + screenSize.width / 2;
int wdwTop = screenSize.height / 2;
frame.setLocation(wdwLeft, wdwTop);
frame.setVisible(true);
}
}

View File

@ -3,6 +3,7 @@ package meerkat.voting.gui.panels.vote_have_been_cast;
import javafx.fxml.FXML;
import javafx.scene.input.MouseEvent;
import meerkat.voting.gui.managment.TwoWayNode;
import meerkat.voting.gui.managment.Printer;
import net.sourceforge.barbecue.Barcode;
import net.sourceforge.barbecue.BarcodeException;
import net.sourceforge.barbecue.BarcodeFactory;
@ -15,10 +16,7 @@ import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.ImageIcon;
import java.awt.image.BufferedImage;
/**
* Created by Vladimir Eliezer Tokarev on 8/27/2016.
@ -37,7 +35,7 @@ public class VoteHaveBeenCastController extends TwoWayNode {
BufferedImage image = BarcodeImageHandler.getImage(barcode);
File outputfile = new File("VotersBallot.png");
ImageIO.write(image, "png", outputfile);
showBallot("VotersBallot.png");
Printer.printBallot("VotersBallot.png");
this.logger.debug("Created the bar code with voters choises at VotersBallot.png.");
}
@ -56,15 +54,5 @@ public class VoteHaveBeenCastController extends TwoWayNode {
// This panel doesn't have any questions representations that why there is nothing ti show here
}
private void showBallot(String filename) throws IOException {
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// bi = ImageIO.read(ImageResourceDemo.class.getResource("../resource/avatar6.jpeg"));
BufferedImage bi = ImageIO.read(new File(filename));
frame.add(new JLabel(new ImageIcon(bi)));
frame.pack();
frame.setAlwaysOnTop(true);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}

View File

@ -0,0 +1,301 @@
package meerkat.voting;
import com.google.protobuf.ByteString;
import com.sun.corba.se.impl.orbutil.graph.Graph;
import meerkat.crypto.DigitalSignature;
import meerkat.crypto.Encryption;
import meerkat.protobuf.Voting;
import meerkat.voting.controller.VotingBoothImpl;
import meerkat.voting.encryptor.VBCryptoManager;
import meerkat.voting.encryptor.VBCryptoManagerImpl;
import meerkat.voting.gui.ui.GraphicalFX;
import javafx.application.Application;
import meerkat.voting.gui.ui.GraphicalUI;
import meerkat.voting.gui.ui.SystemConsoleUI;
import meerkat.voting.output.SystemConsoleOutputDevice;
import meerkat.voting.storage.StorageManager;
import meerkat.voting.storage.StorageManagerMockup;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;
/**
* Created by Laura on 12/12/2016.
*/
public class VotingBoothToyGraphicalRun {
// public static void main(String[] args) {
// Application.launch(GraphicalFX.class, args);
// }
public static void main(String[] args) {
try {
generateSystemMessages();
generateDemoQuestions();
}
catch (Exception e) {
return;
}
Random rand = new Random();
Encryption enc = new ToyEncryption();
DigitalSignature sig = new ToySignature("MY_SIGNER_ID");
StorageManager storageManager = new StorageManagerMockup();
SystemConsoleOutputDevice outputDevice = new SystemConsoleOutputDevice();
VBCryptoManager cryptoManager = new VBCryptoManagerImpl(rand, enc, sig);
// SystemConsoleUI ui = new SystemConsoleUI ();
GraphicalUI ui = new GraphicalUI();
VotingBoothImpl controller = new VotingBoothImpl();
try {
controller.init(outputDevice, cryptoManager, ui, storageManager);
}
catch (Exception e) {
System.err.println("init failed");
return;
}
// create threads
Thread controllerThread = new Thread(controller);
controllerThread.setName("Meerkat VB-Controller Thread");
Thread uiThread = new Thread(ui);
uiThread.setName("Meerkat VB-UI Thread");
Thread outputThread = new Thread(outputDevice);
outputThread.setName("Meerkat VB-Output Thread");
uiThread.start();
controllerThread.start();
outputThread.start();
}
private static void generateDemoQuestions() throws IOException {
Voting.ElectionParams electionParams = Voting.ElectionParams.newBuilder()
.addAllRaceQuestions(generateBallotQuestions())
.addAllChannelChoiceQuestions(generateChannelChoiceQuestions())
.setSelectionData(generateSelectionData())
.build();
try {
FileOutputStream output = new FileOutputStream(StorageManagerMockup.electionParamFullFilename);
electionParams.writeTo(output);
output.close();
System.out.println("Successfully wrote election parameter protobuf to a file");
}
catch (IOException e) {
System.err.println("Could not write to the election parameter file: '" + StorageManagerMockup.electionParamFullFilename + "'.");
throw e;
}
}
private static List<Voting.BallotQuestion> generateChannelChoiceQuestions() {
ArrayList<Voting.BallotQuestion> channelChoiceQuestions = new ArrayList();
String[] ans1 = {"Red", "Blue", "Green"};
Voting.BallotQuestion ccquestion1 = generateBallotQuestion("What is your favorite color?", "Pick one answer", ans1);
channelChoiceQuestions.add(ccquestion1);
String[] ans2 = {"Yes", "No"};
Voting.BallotQuestion ccquestion2 = generateBallotQuestion("Are you a republican?", "Pick one answer", ans2);
channelChoiceQuestions.add(ccquestion2);
return channelChoiceQuestions;
}
private static List<Voting.BallotQuestion> generateBallotQuestions() {
ArrayList<Voting.BallotQuestion> allBallotQuestions = new ArrayList();
String[] answers1 = {"answer 1", "answer 2", "answer 3", "answer 4"};
allBallotQuestions.add(generateBallotQuestion("question 1. Asking something...", "Pick one answer", answers1));
String[] answers2 = {"Miranda Kerr", "Doutzen Kroes", "Moran Atias", "Roslana Rodina", "Adriana Lima"};
allBallotQuestions.add(generateBallotQuestion("question 2: Which model do you like", "Mark as many as you want", answers2));
allBallotQuestions.add(generateBallotQuestion("question 3. Asking something...", "Pick one answer", answers1));
allBallotQuestions.add(generateBallotQuestion("question 4. Asking something...", "Pick one answer", answers1));
String[] answers5 = {"Clint Eastwood", "Ninja", "Sonic", "Tai-chi", "Diablo", "Keanu"};
allBallotQuestions.add(generateBallotQuestion("question 5: Good name for a cat", "Pick the best one", answers5));
allBallotQuestions.add(generateBallotQuestion("question 6. Asking something...", "Pick one answer", answers1));
allBallotQuestions.add(generateBallotQuestion("question 7. Asking something...", "Pick one answer", answers1));
allBallotQuestions.add(generateBallotQuestion("question 8. Asking something...", "Pick one answer", answers1));
allBallotQuestions.add(generateBallotQuestion("question 9. Asking something...", "Pick one answer", answers1));
allBallotQuestions.add(generateBallotQuestion("question 10. Asking something...", "Pick one answer", answers1));
allBallotQuestions.add(generateBallotQuestion("question 11. Asking something...", "Pick one answer", answers1));
allBallotQuestions.add(generateBallotQuestion("question 12. Asking something...", "Pick one answer", answers1));
allBallotQuestions.add(generateBallotQuestion("question 13. Asking something...", "Pick one answer", answers1));
allBallotQuestions.add(generateBallotQuestion("question 14. Asking something...", "Pick one answer", answers1));
return allBallotQuestions;
}
private static Voting.BallotQuestion generateBallotQuestion(String questionStr, String descriptionStr, String[] answers) {
Voting.UIElement question = Voting.UIElement.newBuilder()
.setType(Voting.UIElementDataType.TEXT)
.setData(stringToBytes(questionStr))
.build();
Voting.UIElement description = Voting.UIElement.newBuilder()
.setType(Voting.UIElementDataType.TEXT)
.setData(stringToBytes(descriptionStr))
.build();
Voting.BallotQuestion.Builder bqb = Voting.BallotQuestion.newBuilder();
bqb.setIsMandatory(false);
bqb.setQuestion(question);
bqb.setDescription(description);
for (String answerStr : answers) {
Voting.UIElement answer = Voting.UIElement.newBuilder()
.setType(Voting.UIElementDataType.TEXT)
.setData(stringToBytes(answerStr))
.build();
bqb.addAnswer(answer);
}
return bqb.build();
}
private static Voting.SimpleCategoriesSelectionData generateSelectionData() {
Voting.Category sharedDefaults = Voting.Category.newBuilder()
.addQuestionIndex(0)
.addQuestionIndex(5)
.addQuestionIndex(9)
.build();
Voting.Category cat00 = Voting.Category.newBuilder()
.addQuestionIndex(1)
.addQuestionIndex(4)
.addQuestionIndex(6)
.addQuestionIndex(7)
.build();
Voting.Category cat01 = Voting.Category.newBuilder()
.addQuestionIndex(2)
.addQuestionIndex(4)
.addQuestionIndex(8)
.build();
Voting.Category cat02 = Voting.Category.newBuilder()
.addQuestionIndex(3)
.addQuestionIndex(8)
.build();
Voting.Category cat10 = Voting.Category.newBuilder()
.addQuestionIndex(10)
.addQuestionIndex(11)
.build();
Voting.Category cat11 = Voting.Category.newBuilder()
.addQuestionIndex(12)
.addQuestionIndex(13)
.build();
Voting.CategoryChooser catChooser0 = Voting.CategoryChooser.newBuilder()
.addCategory(cat00)
.addCategory(cat01)
.addCategory(cat02)
.build();
Voting.CategoryChooser catChooser1 = Voting.CategoryChooser.newBuilder()
.addCategory(cat10)
.addCategory(cat11)
.build();
return Voting.SimpleCategoriesSelectionData.newBuilder()
.setSharedDefaults(sharedDefaults)
.addCategoryChooser(catChooser0)
.addCategoryChooser(catChooser1)
.build();
}
private static ByteString stringToBytes (String s) {
return ByteString.copyFromUtf8(s);
}
private static void generateSystemMessages() throws IOException{
Map<String, Voting.UIElement> systemMessageMap = new HashMap();
systemMessageMap.put(StorageManager.WAIT_FOR_COMMIT_MESSAGE, Voting.UIElement.newBuilder()
.setType(Voting.UIElementDataType.TEXT)
.setData(ByteString.copyFromUtf8("Please wait while committing to ballot"))
.build());
systemMessageMap.put(StorageManager.WAIT_FOR_AUDIT_MESSAGE, Voting.UIElement.newBuilder()
.setType(Voting.UIElementDataType.TEXT)
.setData(ByteString.copyFromUtf8("Please wait while auditing your ballot"))
.build());
systemMessageMap.put(StorageManager.WAIT_FOR_CAST_MESSAGE, Voting.UIElement.newBuilder()
.setType(Voting.UIElementDataType.TEXT)
.setData(ByteString.copyFromUtf8("Please wait while finalizing your ballot for voting"))
.build());
systemMessageMap.put(StorageManager.RESTART_VOTING_BUTTON, Voting.UIElement.newBuilder()
.setType(Voting.UIElementDataType.TEXT)
.setData(ByteString.copyFromUtf8("Restart voting"))
.build());
systemMessageMap.put(StorageManager.UNRECOGNIZED_FINALIZE_RESPONSE_MESSAGE, Voting.UIElement.newBuilder()
.setType(Voting.UIElementDataType.TEXT)
.setData(ByteString.copyFromUtf8("Could not understand response for Cast or Audit. Force restarting."))
.build());
systemMessageMap.put(StorageManager.UNSUCCESSFUL_CHANNEL_CHOICE_MESSAGE, Voting.UIElement.newBuilder()
.setType(Voting.UIElementDataType.TEXT)
.setData(ByteString.copyFromUtf8("Choice of channel was unsuccessful. Force restarting."))
.build());
systemMessageMap.put(StorageManager.OUTPUT_DEVICE_FAILURE_MESSAGE, Voting.UIElement.newBuilder()
.setType(Voting.UIElementDataType.TEXT)
.setData(ByteString.copyFromUtf8("Ballot output device failure. Force restarting."))
.build());
systemMessageMap.put(StorageManager.UNSUCCESSFUL_VOTING_MESSAGE, Voting.UIElement.newBuilder()
.setType(Voting.UIElementDataType.TEXT)
.setData(ByteString.copyFromUtf8("Voting was unsuccessful. Force restarting."))
.build());
systemMessageMap.put(StorageManager.SOMETHING_WRONG_MESSAGE, Voting.UIElement.newBuilder()
.setType(Voting.UIElementDataType.TEXT)
.setData(ByteString.copyFromUtf8("Something was terribly wrong. Force restarting."))
.build());
systemMessageMap.put(StorageManager.ENCRYPTION_FAILED_MESSAGE, Voting.UIElement.newBuilder()
.setType(Voting.UIElementDataType.TEXT)
.setData(ByteString.copyFromUtf8("Encryption failed for some unknown reason."))
.build());
systemMessageMap.put(StorageManager.RETRY_BUTTON, Voting.UIElement.newBuilder()
.setType(Voting.UIElementDataType.TEXT)
.setData(ByteString.copyFromUtf8("Retry"))
.build());
systemMessageMap.put(StorageManager.CANCEL_VOTE_BUTTON, Voting.UIElement.newBuilder()
.setType(Voting.UIElementDataType.TEXT)
.setData(ByteString.copyFromUtf8("Cancel Vote"))
.build());
Voting.BoothSystemMessages systemMessages = Voting.BoothSystemMessages.newBuilder().putAllSystemMessage(systemMessageMap).build();
try {
FileOutputStream output = new FileOutputStream(StorageManagerMockup.systemMessagesFilename);
systemMessages.writeTo(output);
output.close();
System.out.println("Successfully wrote system messages protobuf to a file");
}
catch (IOException e) {
System.err.println("Could not write to the system messages file: '" + StorageManagerMockup.systemMessagesFilename + "'.");
throw e;
}
}
}

View File

@ -0,0 +1,80 @@
package meerkat.voting.gui.ui;
/**
* Created by Laura on 12/12/2016.
*/
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javafx.scene.Parent;
import javafx.fxml.FXMLLoader;
import java.io.IOException;
import java.io.File;
public class GraphicalFX extends Application {
private static final Logger logger = LoggerFactory.getLogger(GraphicalUI.class);
private static GraphicalUI parent;
public static void setParent(GraphicalUI ui) {
if (GraphicalFX.parent==null) {
GraphicalFX.parent = ui;
}
logger.warn("Trying to assign again the parent of GraphicalFX.");
}
@Override
public void init() throws Exception {
// System.out.println("init() of Hello World FX");
parent.setGraphicalFx(this);
}
// public static void main(String[] args) {
// launch(args);
// }
@Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Hello World!");
Button btn = new Button();
btn.setText("Say 'Hello World'");
btn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
System.out.println("Hello World!");
System.out.println(parent.testPrint());
}
});
StackPane root = new StackPane();
root.getChildren().add(btn);
Scene scene = new Scene(root, 300, 250);
// System.out.println("Working Directory = " +
// System.getProperty("user.dir"));
// Parent root = null;
// try {
// File dir1 = new File (".");
// System.out.println ("Current dir : " + dir1.getCanonicalPath());
// root = FXMLLoader.load(getClass().getClassLoader().getResource("/graphical_fxml/welcome_splash_screen.fxml"));
// } catch (IOException e) {
// e.printStackTrace();
// System.out.println("Working Directory = " +
// System.getProperty("user.dir"));
// }
//
// Scene scene = new Scene(root, 300, 275);
primaryStage.setScene(scene);
primaryStage.show();
}
}

View File

@ -0,0 +1,494 @@
package meerkat.voting.gui.ui;
import com.google.common.util.concurrent.FutureCallback;
import javafx.application.Application;
import javafx.stage.Stage;
import meerkat.protobuf.Voting.BallotAnswer;
import meerkat.protobuf.Voting.BallotQuestion;
import meerkat.protobuf.Voting.UIElement;
import meerkat.protobuf.Voting.UIElementDataType;
import meerkat.voting.controller.callbacks.*;
import meerkat.voting.gui.ui.uicommands.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Timer;
import static java.lang.System.in;
/**
* an asynchronous thread implementation of the VotingBoothUI interface
* This is a mock-up implementation using just the console as our UI device
*/
public class GraphicalUI implements VotingBoothUI, Runnable {
private static final Logger logger = LoggerFactory.getLogger(GraphicalUI.class);
private BufferedReader bufferedReader;
private CommandPend<UICommand> cmdPend;
private Date startWaitingTime;
private volatile boolean shutDownHasBeenCalled;
private GraphicalFX ui;
public GraphicalUI() {
final int tickDurationInMillisec = 10; // period between view update calls
logger.info("A graphical UI console is constructed");
cmdPend = new CommandPend<>();
// bufferedReader = new BufferedReader(new InputStreamReader(in));
GraphicalFX.setParent(this);
startWaitingTime = null;
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TickerTimerTask(cmdPend), new Date(), tickDurationInMillisec);
shutDownHasBeenCalled = false;
}
/**
* the run() method. Simply loops and takes the UI's pending command and handles it accordingly
*/
@Override
public void run () {
logger.info("UI starts running");
while (! wasShutDownCalled()) {
Application.launch(GraphicalFX.class);
// try {
// UICommand command = cmdPend.take();
// handleSingleCommand(command);
// }
// catch (InterruptedException e) {
// logger.warn ("Interrupted while reading the pending command " + e);
// }
}
}
@Override
public void callShutDown() {
logger.info("callShutDown command has been called");
shutDownHasBeenCalled = true;
stopWaiting();
cmdPend.clear();
try {
ui.stop();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* chooses the next method to run according to the type of the given UICommand.
* Special case for the TickCommand.
* As this command is registered in the queue constantly, we simply ignore this command if the UI is not in
* a waiting state
* @param command any valid UICommand
*/
private void handleSingleCommand(UICommand command) {
if (!(command instanceof TickCommand)) {
if (startWaitingTime != null) {
stopWaiting();
}
}
if (command instanceof StartSessionUICommand) {
doShowWelcomeScreen((StartSessionUICommand)command);
}
else if (command instanceof ChannelChoiceUICommand) {
doAskChannelChoiceQuestions((ChannelChoiceUICommand)command);
}
else if (command instanceof RaceVotingUICommand) {
doAskVotingQuestions((RaceVotingUICommand)command);
}
else if (command instanceof CastOrAuditUICommand) {
doCastOrAudit ((CastOrAuditUICommand)command);
}
else if (command instanceof FatalErrorUICommand) {
doFatalError((FatalErrorUICommand)command);
}
else if (command instanceof WaitForFinishUICommand) {
doWaitForFinish((WaitForFinishUICommand)command);
}
else if (command instanceof TickCommand) {
doTick ();
}
else {
String errorMessage = "handleSingleCommand: unknown type of UICommand received: " +
command.getClass().getName();
logger.error(errorMessage);
throw new RuntimeException(errorMessage);
}
}
/**
* start a new session by registering a StartSessionUICommand
* @param callback - a boolean future callback to return when done
*/
@Override
public void startNewVoterSession(FutureCallback<Void> callback) {
logger.debug("UI interface call to startNewVoterSession");
cmdPend.trample(new StartSessionUICommand((NewVoterCallback)callback));
}
/**
* welcomes the new voter at the beginning of the session
* @param command a StartSessionUICommand with a acallback
*/
private void doShowWelcomeScreen(StartSessionUICommand command) {
logger.debug("UI entered doShowWelcomeScreen");
System.out.println("Welcome, new voter!");
waitForEnter(null);
ControllerCallback<Void> callback = command.getCallback();
callback.onSuccess(null);
}
/**
* marks that the waiting, for something else to have happened, is finished
*/
private void stopWaiting () {
System.out.println ();
startWaitingTime = null;
}
/**
* waits until the ENTER key is pressed in the console
* @param message a message to show the user in the console
*/
private void waitForEnter(String message) {
if (message != null) {
System.out.println(message);
}
System.out.println("\nPress ENTER to proceed.\n");
String t = null;
while (t == null) {
try {
t = readInputLine();
}
catch (IOException e) {
String errorMessage = "waitForEnter: threw an IOException: " + e;
logger.error(errorMessage);
System.err.println(errorMessage);
}
}
}
/**
* call for the channel choice phase by registering a ChannelChoiceUICommand in the queue
* @param questions questions to determine the right voting channel for this voter
* @param callback that's where we store the answers to decide channel upon for the current voter
*/
@Override
public void chooseChannel(List<BallotQuestion> questions, FutureCallback<List<BallotAnswer>> callback) {
logger.debug("UI interface call to chooseChannel");
cmdPend.trample(new ChannelChoiceUICommand(questions, (ChannelChoiceCallback)callback));
}
/**
* lists the channel choice questions to the voter and gathers the voter's answers
* @param command a ChannelChoiceUICommand with the data and a callback
*/
private void doAskChannelChoiceQuestions (ChannelChoiceUICommand command) {
logger.debug("UI: doAskChannelChoiceQuestions");
System.out.println("Showing questions for choosing channel:\n");
try {
List<BallotAnswer> answers = askVoterForAnswers(command.getQuestions());
command.getCallback().onSuccess(answers);
}
catch (VoterCancelThrowable e) {
command.getCallback().onFailure(e);
}
catch (IOException e) {
String errorMessage = "Channel choice failed due to IOException: " + e;
logger.error (errorMessage);
System.err.println(errorMessage);
command.getCallback().onFailure(e);
}
}
/**
* call for the race voting question phase by registering a RaceVotingUICommand in the queue
* @param questions all ballot questions to present to the voter
* @param callback the responses to the questions collected by the UI, to send back to the controller. Responses are null if voter chose to cancel session
*/
@Override
public void askVoterQuestions(List<BallotQuestion> questions, FutureCallback<List<BallotAnswer>> callback) {
logger.debug("UI interface call to chooseChannel");
cmdPend.trample(new RaceVotingUICommand(questions, (VotingCallback)callback));
}
/**
* lists the race voting questions to the voter and gathers the voter's answers
* @param command a RaceVotingUICommand with a callback
*/
private void doAskVotingQuestions (RaceVotingUICommand command) {
logger.debug("UI: doAskVotingQuestions");
System.out.println("Showing questions for race voting:\n");
try {
List<BallotAnswer> answers = askVoterForAnswers(command.getQuestions());
command.getCallback().onSuccess(answers);
}
catch (VoterCancelThrowable e) {
command.getCallback().onFailure(e);
}
catch (IOException e) {
String errorMessage = "Asking voting questions failed due to IOException: " + e;
logger.error (errorMessage);
System.err.println(errorMessage);
command.getCallback().onFailure(e);
}
}
/**
* call for the cast-or-audit phase by registering a CastOrAuditUICommand in the queue
* @param callback the returned choice of how to finalize the ballot
*/
@Override
public void castOrAudit(FutureCallback<FinalizeBallotChoice> callback) {
logger.debug("UI interface call to castOrAudit");
cmdPend.trample(new CastOrAuditUICommand((CastOrAuditCallback)callback));
}
/**
* asks the voter whether to cast or audit the ballot
* @param command a simple CastOrAuditUICommand with the callback
*/
private void doCastOrAudit(CastOrAuditUICommand command) {
logger.debug("UI entered doCastOrAudit");
System.out.println ("Finalizing your vote. Do you wish to (C)ast or (A)udit?");
FinalizeBallotChoice fChoice;
try {
String s = readInputLine();
if (s.equals("cast") || s.equals("c")) {
fChoice = FinalizeBallotChoice.CAST;
}
else if (s.equals("audit") || s.equals("a")) {
fChoice = FinalizeBallotChoice.AUDIT;
}
else {
throw new IllegalArgumentException("UI could not understand the answer for cast/audit question '" + s + "'");
}
ControllerCallback callback = command.getCallback();
assert (callback instanceof CastOrAuditCallback);
((CastOrAuditCallback)callback).onSuccess(fChoice);
}
catch (IllegalArgumentException|IOException e) {
String errorMessage = "doCastOrAudit: some error with reading input from console. details: " + e;
logger.error(errorMessage);
command.getCallback().onFailure(e);
}
}
/**
* makes the UI (and voter) wait for something else to happen, by registering a WaitForFinishUICommand in the queue
* @param message a message to show the user on the UI device while waiting
* @param callback a success return value of the wait (cancelling returns false)
*/
@Override
public void notifyVoterToWaitForFinish(UIElement message, FutureCallback<Void> callback) {
logger.debug("UI interface call to notifyVoterToWaitForFinish");
cmdPend.trample(new WaitForFinishUICommand(message, (WaitForFinishCallback)callback));
}
/**
* Tells the voter (in the console) to wait until some other process is finished
* @param command a simple WaitForFinishUICommand with the callback
*/
public void doWaitForFinish (WaitForFinishUICommand command) {
logger.debug("UI entered doWaitForFinish");
startWaitingTime = new Date();
UIElement message = command.getMessage();
String messageString;
if (message.getType() != UIElementDataType.TEXT) {
messageString = "Default message: encountered an error. System halting";
} else {
messageString = UIUtils.bytesToString(message.getData());
}
System.out.println(messageString);
System.out.print ("Waiting : .");
}
/**
* show an error to the voter. Halts the system until a technician handles it
* @param errorMessage message to show in UI device
* @param callback returns interrupt
*/
@Override
public void showErrorMessageAndHalt(UIElement errorMessage, FutureCallback<Boolean> callback) {
logger.debug("UI interface call to showErrorMessageAndHalt");
throw new UnsupportedOperationException("Not implemented becuase currently not sure if we ever use it.");
}
/**
* show an error to the voter. let him press a (chosen) button for handling the error.
* @param errorMessage message to show in UI device
* @param buttonLabels labels for buttons to present to voter
* @param callback the number of the selected button
*/
@Override
public void showErrorMessageWithButtons(UIElement errorMessage, UIElement[] buttonLabels, FutureCallback<Integer> callback) {
logger.debug("UI interface call to showErrorMessageWithButtons");
cmdPend.trample(new FatalErrorUICommand(errorMessage, buttonLabels, (ControllerCallback<Integer>)callback));
}
/**
* show an error to the voter. let him press a (chosen) button for handling the error.
* @param command a FatalErrorUICommand with the callback
*/
private void doFatalError (FatalErrorUICommand command) {
logger.debug("UI entered doFatalError");
UIElement errorMessage = command.getErrorMessage();
String errorMessageString;
if (errorMessage.getType() != UIElementDataType.TEXT) {
errorMessageString = "Default message: encountered an error. System halting";
} else {
errorMessageString = UIUtils.bytesToString(errorMessage.getData());
}
UIElement[] buttonLabels = command.getButtonLabels();
String[] buttonLabelStrings = new String[buttonLabels.length];
for (int i = 0; i < buttonLabels.length; ++i) {
if (buttonLabels[i].getType() != UIElementDataType.TEXT) {
buttonLabelStrings[i] = "<NON_TEXT>";
} else {
buttonLabelStrings[i] = UIUtils.bytesToString(errorMessage.getData());
}
}
System.out.println(errorMessageString);
for (int i = 0; i < buttonLabelStrings.length; ++i) {
System.out.println("" + i + " - " + buttonLabelStrings[i]);
}
try {
String s = readInputLine();
Integer chosenButton = new Integer(s);
command.getCallback().onSuccess(chosenButton);
}
catch (IOException e) {
String err = "doFatalError: some error with reading input from console. details: " + e;
logger.error(err);
command.getCallback().onFailure(e);
}
}
/**
* this method is run when a TickCommand was received while in waiting state
*/
private void doTick () {
if (startWaitingTime != null) {
System.out.print ("."); // still waiting
}
}
/**
* get an input line from the console
* @return a line from the voter
* @throws IOException
*/
private String readInputLine() throws IOException{
String s;
try {
s = this.bufferedReader.readLine();
if (null == s) {
throw new IOException();
}
} catch (IOException e) {
String errorMessage = "readInputLine: some error with reading input from console. details: " + e;
logger.error(errorMessage);
throw new IOException(e);
}
return s;
}
/**
* present the questions to the voter console sequentially.
* Voter may choose at any time to skip a question, go back or even cancel the whole session
* @param questions list of questions to present
* @return list of answers to the questions (at the same order)
* @throws VoterCancelThrowable this is thrown if a voter chose to cancel in the middle of the process
* @throws IOException
*/
private List<BallotAnswer> askVoterForAnswers(List<BallotQuestion> questions) throws VoterCancelThrowable, IOException {
UIUtils.assertQuestionsAreValid (questions, logger);
List<BallotAnswer> answers = new ArrayList<>();
int index = 0;
while (index < questions.size()) {
BallotQuestion question = questions.get(index);
System.out.println("Question number " + index);
showQuestionInConsole(question);
System.out.println("UI screen: Enter your answer. You can also type '(b)ack' or '(c)ancel' or '(s)kip");
String s = readInputLine();
if ((s.equals("cancel") || s.equals("c")) || (index == 0 && (s.equals("back") || s.equals("b")))) {
throw new VoterCancelThrowable();
}
else if (s.equals("back") || s.equals("b")) {
--index;
answers.remove(index);
}
else if (s.equals("skip") || s.equals("s")) {
answers.add(UIUtils.translateStringAnswerToProtoBufMessageAnswer(""));
++index;
}
else {
answers.add(UIUtils.translateStringAnswerToProtoBufMessageAnswer(s));
++index;
}
}
return answers;
}
/**
* present a question in the console to the voter
* @param question a text ballot question
*/
private void showQuestionInConsole(BallotQuestion question) {
if (!UIUtils.isQuestionOnlyText(question)) {
System.err.println("debug: an element in question is not of TEXT type");
throw new UnsupportedOperationException();
}
System.out.println("Question text: " + UIUtils.bytesToString(question.getQuestion().getData()));
System.out.println("Description: " + UIUtils.bytesToString(question.getDescription().getData()));
int answerIndex = 0;
for (UIElement answer : question.getAnswerList()) {
++answerIndex;
System.out.println("Answer " + answerIndex + ": " + UIUtils.bytesToString(answer.getData()));
}
}
private boolean wasShutDownCalled () {
return shutDownHasBeenCalled;
}
public String testPrint() {
return "testPrint called";
}
public void setGraphicalFx(GraphicalFX graphicalFX) {
this.ui = graphicalFX;
}
}

View File

@ -0,0 +1,39 @@
package meerkat.voting.gui.ui.controllerFX;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.input.MouseEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Created by Vladimir Eliezer Tokarev on 8/27/2016.
* WelcomeSplashController handle the behavior of welcome splash class
*/
public class WelcomeSplashController {
private final Logger logger = LoggerFactory.getLogger(WelcomeSplashController.class);
private final String INVALID_CONFIGURATION_ERROR_TEXT = "The given configuration is invalid please run this voting booth with different configuraiton.";
@FXML
private Label ErrorPanel;
@FXML
private void StartVotingProcess(MouseEvent mousePressed) {
// this.currentStage.close();
// this.currentStage.setScene(this.next.GetCurrentScene());
// this.next.UpdateNode();
// this.currentStage.show();
// this.logger.debug("Jumping to the select channel object.");
}
/**
* Represents the given string to user in ErrorLabel
* @param message is the error string to represent to the user
*/
private void RepresentErrorToVoter(String message) {
// ErrorPanel.setText(message);
// this.currentStage.show();
}
}

View File

@ -17,8 +17,10 @@ public class StorageManagerMockup implements StorageManager {
private static final Logger logger = LoggerFactory.getLogger(StorageManagerMockup.class);
public static final String electionParamFullFilename = "/home/hai/meerkat-java/meerkat_election_params_tempfile.dat";
public static final String systemMessagesFilename = "/home/hai/meerkat-java/meerkat_booth_system_messages.dat";
// public static final String electionParamFullFilename = "/home/hai/meerkat-java/meerkat_election_params_tempfile.dat";
// public static final String systemMessagesFilename = "/home/hai/meerkat-java/meerkat_booth_system_messages.dat";
public static final String electionParamFullFilename = "./meerkat_election_params_tempfile.dat";
public static final String systemMessagesFilename = "./meerkat_booth_system_messages.dat";
private boolean adminHardwareKeyInserted;
@ -31,7 +33,7 @@ public class StorageManagerMockup implements StorageManager {
@Override
public boolean isAdminHardwareKeyInserted() {
logger.info("Entered method isAdminHardwareKeyInserted");
logger.warn("isAdminHardwareKeyInserted is not yet fully implemented. It does not check the file system. "
logger.warn("isAdminHardwareKe01d is not yet fully implemented. It does not check the file system. "
+ "Rather it just returns a private boolean member");
return adminHardwareKeyInserted;
}

View File

@ -0,0 +1,104 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<GridPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="meerkat.voting.gui.panels.welcome_splash.WelcomeSplashController">
<columnConstraints>
<ColumnConstraints />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints />
<RowConstraints maxHeight="129.0" minHeight="10.0" prefHeight="47.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="222.0" minHeight="10.0" prefHeight="201.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="170.0" minHeight="10.0" prefHeight="129.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<GridPane GridPane.columnIndex="1" GridPane.rowIndex="1">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="185.0" minWidth="10.0" prefWidth="185.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="334.0" minWidth="10.0" prefWidth="258.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="194.0" minWidth="10.0" prefWidth="124.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<BorderPane prefHeight="200.0" prefWidth="200.0">
<center>
<Label text="Organization Logo" BorderPane.alignment="CENTER" />
</center>
</BorderPane>
<BorderPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2">
<center>
<Label text="Date" BorderPane.alignment="CENTER" />
</center>
</BorderPane>
</children>
</GridPane>
<GridPane GridPane.columnIndex="1" GridPane.rowIndex="1">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="74.0" minHeight="10.0" prefHeight="74.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="123.0" minHeight="10.0" prefHeight="93.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="59.0" minHeight="10.0" prefHeight="29.0" vgrow="SOMETIMES" />
</rowConstraints>
</GridPane>
<GridPane GridPane.columnIndex="1" GridPane.rowIndex="2">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="75.0" minHeight="10.0" prefHeight="75.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="107.0" minHeight="10.0" prefHeight="107.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="56.0" minHeight="10.0" prefHeight="27.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<BorderPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="1">
<center>
<Button mnemonicParsing="false" onMousePressed="#StartVotingProcess" prefHeight="50.0" prefWidth="170.0" text="Start Here" BorderPane.alignment="CENTER">
<font>
<Font size="24.0" />
</font>
</Button>
</center>
</BorderPane>
<GridPane>
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<BorderPane prefHeight="200.0" prefWidth="200.0">
<center>
<Label text="This is the name of the Election" BorderPane.alignment="CENTER">
<font>
<Font size="18.0" />
</font>
</Label>
</center>
</BorderPane>
<BorderPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="1">
<top>
<Label text="Location | Precinct" BorderPane.alignment="CENTER" />
</top>
</BorderPane>
</children>
</GridPane>
</children>
</GridPane>
<BorderPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="3">
<center>
<Label fx:id="ErrorPanel" maxHeight="30.0" maxWidth="500.0" minHeight="30.0" minWidth="500.0" prefHeight="30.0" prefWidth="500.0" BorderPane.alignment="CENTER" />
</center>
</BorderPane>
</children>
</GridPane>