diff --git a/VotersBallot.png b/VotersBallot.png index 00ef817..a63d0c3 100644 Binary files a/VotersBallot.png and b/VotersBallot.png differ diff --git a/meerkat-common/src/main/proto/meerkat/BallotQuestionUIElement.proto b/meerkat-common/src/main/proto/meerkat/BallotQuestionUIElement.proto index 53a18e9..2ec0b9d 100644 --- a/meerkat-common/src/main/proto/meerkat/BallotQuestionUIElement.proto +++ b/meerkat-common/src/main/proto/meerkat/BallotQuestionUIElement.proto @@ -4,11 +4,18 @@ package meerkat; option java_package = "meerkat.protobuf"; +// Message that represent single answer for given question +message UIAnswer{ + bytes answer=1; + string description=2; +} + // Message object which is number of bytes message ListOfAnswers{ - repeated bytes answers = 1; + repeated UIAnswer answers = 1; } + // Message object which contains the type of the answers and their data in bytes message UIAnswers { int32 AnswersType = 1; diff --git a/voting-booth-gui/src/main/java/meerkat/voting/gui/Main.java b/voting-booth-gui/src/main/java/meerkat/voting/gui/Main.java index b75dfc9..bdd27cb 100644 --- a/voting-booth-gui/src/main/java/meerkat/voting/gui/Main.java +++ b/voting-booth-gui/src/main/java/meerkat/voting/gui/Main.java @@ -29,7 +29,7 @@ public class Main extends Application { */ private VotingBoothConfiguration GetConfig() throws IOException, JSONException { VotingBoothConfigurationCreator creator = new VotingBoothConfigurationCreator(); - return creator.CreateConfiguration("/F:/vova/meerkat/meerkat-java/voting-booth-gui/src/main/resources/configuration/VotingBoothConfiguration.json"); + return creator.CreateConfiguration("/configuration/VotingBoothConfiguration.json"); } @Override diff --git a/voting-booth-gui/src/main/java/meerkat/voting/gui/configuration/VotingBoothConfiguration.java b/voting-booth-gui/src/main/java/meerkat/voting/gui/configuration/VotingBoothConfiguration.java index fde3d63..8eda170 100644 --- a/voting-booth-gui/src/main/java/meerkat/voting/gui/configuration/VotingBoothConfiguration.java +++ b/voting-booth-gui/src/main/java/meerkat/voting/gui/configuration/VotingBoothConfiguration.java @@ -1,6 +1,5 @@ package meerkat.voting.gui.configuration; -import com.google.protobuf.ByteString; import javafx.embed.swing.SwingFXUtils; import meerkat.protobuf.BallotQuestionUIElementOuterClass; @@ -35,18 +34,24 @@ public class VotingBoothConfiguration { return false; } // Check that all the given answers are valid bte strings that can be converted into strings - for (ByteString answer: NameSelectionQuestion.getAnswers().getAnswers().getAnswersList()){ + for (BallotQuestionUIElementOuterClass.UIAnswer answer: NameSelectionQuestion.getAnswers().getAnswers().getAnswersList()){ try { - String strAnswer = answer.toStringUtf8(); + answer.getAnswer().toStringUtf8(); + if (answer.getDescription() == null) { + return false; + } } catch (Exception e){ return false; } } // Check that all given byteStrings that are pictures can be converted into pictures - for (ByteString answer :NameSelectionByPictureQuestion.getAnswers().getAnswers().getAnswersList()){ + for (BallotQuestionUIElementOuterClass.UIAnswer answer :NameSelectionByPictureQuestion.getAnswers().getAnswers().getAnswersList()){ try { - BufferedImage bufferedImage = ImageIO.read(answer.newInput()); + BufferedImage bufferedImage = ImageIO.read(answer.getAnswer().newInput()); SwingFXUtils.toFXImage(bufferedImage, null); + if (answer.getDescription() == null){ + return false; + } } catch (Exception e) { return false; } diff --git a/voting-booth-gui/src/main/java/meerkat/voting/gui/configuration/VotingBoothConfigurationCreator.java b/voting-booth-gui/src/main/java/meerkat/voting/gui/configuration/VotingBoothConfigurationCreator.java index 44733f5..e2bf68b 100644 --- a/voting-booth-gui/src/main/java/meerkat/voting/gui/configuration/VotingBoothConfigurationCreator.java +++ b/voting-booth-gui/src/main/java/meerkat/voting/gui/configuration/VotingBoothConfigurationCreator.java @@ -2,6 +2,7 @@ package meerkat.voting.gui.configuration; import com.google.protobuf.ByteString; import meerkat.protobuf.BallotQuestionUIElementOuterClass; +import org.factcenter.qilin.util.Pair; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -69,7 +70,7 @@ public class VotingBoothConfigurationCreator { * @throws JSONException will be thrown if the parsing will fail */ private JSONArray getJsonFromPath(String path) throws FileNotFoundException, JSONException { - String content = new Scanner(new File(path)).useDelimiter("\\Z").next(); + String content = new Scanner(new File(getClass().getResource(path).getPath())).useDelimiter("\\Z").next(); JSONObject jsonObject = new JSONObject(content); this.logger.debug("Created json object from from configuration path."); return (JSONArray)jsonObject.get("questions"); @@ -86,30 +87,32 @@ public class VotingBoothConfigurationCreator { // Question part JSONObject question = object.getJSONObject("question"); int questionType = question.getInt("type"); - ByteString questionValue = this.convertToByteStringBasedOnType(questionType, question.getString("questionValue")); + ByteString questionValue = ByteString.copyFromUtf8(question.getString("questionValue")); - // Answers Part + // Convert and add json objects which have field answer and description into list of UIAnswers JSONObject answers = object.getJSONObject("answers"); int answersType = answers.getInt("type"); JSONArray answersValues = answers.getJSONArray("answersValue"); - List byteStrings = new ArrayList<>(); + List> answersPairs= new ArrayList<>(); for (int i = 0 ; i < answersValues.length(); i ++){ - byteStrings.add(this.convertToByteStringBasedOnType(answersType, answersValues.getString(i))); + ByteString answer = this.convertToByteStringBasedOnType(answersType, answersValues.getJSONObject(i)); + String description = answersValues.getJSONObject(i).getString("description"); + answersPairs.add(new Pair<>(answer, description)); } // Create the UIQuestion and set the values parsed from jason BallotQuestionUIElementOuterClass.UIQuestion uiQuestion = BallotQuestionUIElementOuterClass.UIQuestion.newBuilder() .setQuestionType(questionType) .setQuestion(BallotQuestionUIElementOuterClass.Question.newBuilder() - .setQuestion(questionValue)) + .setQuestion(questionValue)) .build(); // Create UIAnswers and set the values parsed from jason BallotQuestionUIElementOuterClass.UIAnswers.Builder uiAnswersBuilder = BallotQuestionUIElementOuterClass.UIAnswers.newBuilder() .setAnswersType(answersType); BallotQuestionUIElementOuterClass.ListOfAnswers.Builder listOfAnswers = BallotQuestionUIElementOuterClass.ListOfAnswers.newBuilder(); - for(ByteString byteString : byteStrings){ - listOfAnswers.addAnswers(byteString); + for(Pair pair: answersPairs){ + listOfAnswers.addAnswers(ConvertPairIntoUIAnswer(pair)); } uiAnswersBuilder.setAnswers(listOfAnswers); @@ -121,19 +124,31 @@ public class VotingBoothConfigurationCreator { .build(); } + /** + * Converts given pair into UIAnswer + * @param pair A pair of byteString which is the answer and string which is the description of the answer + * @return UIAnswer + */ + private BallotQuestionUIElementOuterClass.UIAnswer ConvertPairIntoUIAnswer(Pair pair) { + return BallotQuestionUIElementOuterClass.UIAnswer.newBuilder() + .setAnswer(pair.a) + .setDescription(pair.b) + .build(); + } + /** * Tries to get convert the given question to ByteString else throws excetion * @param questionType the type of the question (can be 0 - text, 1 - audio, 2 - image) - * @param questionValue the values itseld (in case the type is 1 or 2 the question value will be a path to the file) + * @param value jsonObject which contains the value and its description * @return ByteString which is or the value or the file in given path * @throws IOException will be thrown if the given type is unsupported */ - private ByteString convertToByteStringBasedOnType(int questionType, String questionValue) throws IOException { + private ByteString convertToByteStringBasedOnType(int questionType, JSONObject value) throws IOException, JSONException { if (questionType == BallotQuestionUIElementOuterClass.ValueType.TEXT_TYPE.getNumber()) { - return ByteString.copyFromUtf8(questionValue); + return ByteString.copyFromUtf8(value.getString("answer")); } if (questionType == BallotQuestionUIElementOuterClass.ValueType.IMAGE_TYPE.getNumber()) { - return ByteString.copyFrom(getFileBytes(questionValue)); + return ByteString.copyFrom(getFileBytes(value.getString("answer"))); } else { throw new IOException(UNSUPPORTED_VALUE_TYPE_ERROR_MESSAGE); diff --git a/voting-booth-gui/src/main/java/meerkat/voting/gui/managment/VotersBallot.java b/voting-booth-gui/src/main/java/meerkat/voting/gui/managment/VotersBallot.java index ecc8d44..d4b35d3 100644 --- a/voting-booth-gui/src/main/java/meerkat/voting/gui/managment/VotersBallot.java +++ b/voting-booth-gui/src/main/java/meerkat/voting/gui/managment/VotersBallot.java @@ -1,6 +1,6 @@ package meerkat.voting.gui.managment; -import com.google.protobuf.ByteString; +import meerkat.protobuf.BallotQuestionUIElementOuterClass; import java.util.List; @@ -15,7 +15,7 @@ import java.util.List; public class VotersBallot { public List VoterChannel; public String VotersNameSelection; - public ByteString VotersImageSelection; + public BallotQuestionUIElementOuterClass.UIAnswer VotersImageSelection; public String toString(){ return this.VotersNameSelection +"---"+ this.VoterChannel.get(0) + "" + this.VoterChannel.get(1) + diff --git a/voting-booth-gui/src/main/java/meerkat/voting/gui/panels/ballot_summary/VotersChoicesAdder.java b/voting-booth-gui/src/main/java/meerkat/voting/gui/panels/ballot_summary/VotersChoicesAdder.java index 6532d71..399f259 100644 --- a/voting-booth-gui/src/main/java/meerkat/voting/gui/panels/ballot_summary/VotersChoicesAdder.java +++ b/voting-booth-gui/src/main/java/meerkat/voting/gui/panels/ballot_summary/VotersChoicesAdder.java @@ -46,7 +46,7 @@ class VotersChoicesAdder { this.RemoveAllAnswers(); this.addAnswer(this.getChannelChoice(this.votersBallot.VoterChannel)); this.addAnswer(this.getNameChoice(this.votersBallot.VotersNameSelection)); - this.addAnswer(this.getImageChoice(this.votersBallot.VotersImageSelection)); + this.addAnswer(this.getImageChoice(this.votersBallot.VotersImageSelection.getAnswer())); Label error = new Label(); error.setPrefSize(250,30); this.addAnswer(error); diff --git a/voting-booth-gui/src/main/java/meerkat/voting/gui/panels/select_candidate_by_picture/PicturesAnswersUpdater.java b/voting-booth-gui/src/main/java/meerkat/voting/gui/panels/select_candidate_by_picture/PicturesAnswersUpdater.java index 511c758..dfdcd47 100644 --- a/voting-booth-gui/src/main/java/meerkat/voting/gui/panels/select_candidate_by_picture/PicturesAnswersUpdater.java +++ b/voting-booth-gui/src/main/java/meerkat/voting/gui/panels/select_candidate_by_picture/PicturesAnswersUpdater.java @@ -1,13 +1,13 @@ package meerkat.voting.gui.panels.select_candidate_by_picture; import com.google.common.util.concurrent.FutureCallback; -import com.google.protobuf.ByteString; import javafx.embed.swing.SwingFXUtils; import javafx.event.Event; import javafx.event.EventHandler; import javafx.geometry.Insets; import javafx.scene.Node; import javafx.scene.control.CheckBox; +import javafx.scene.control.Label; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.BorderPane; @@ -36,8 +36,8 @@ class PicturesAnswersUpdater implements EventHandler{ private Stage currentStage; private int columIndex; - private List allAvailableAnswers; - private FutureCallback imageUpdate; + private List allAvailableAnswers; + private FutureCallback imageUpdate; PicturesAnswersUpdater(Stage primaryStage) { this.currentStage = primaryStage; @@ -52,7 +52,7 @@ class PicturesAnswersUpdater implements EventHandler{ * Sets the call back object which will be called every time the voter choose different candidate picture * @param imageUpdate the callback object itself */ - public void SetImageUpdate(FutureCallback imageUpdate){ + public void SetImageUpdate(FutureCallback imageUpdate){ this.imageUpdate = imageUpdate; } @@ -63,15 +63,15 @@ class PicturesAnswersUpdater implements EventHandler{ */ void UpdateAnswers(BallotQuestionUIElementOuterClass.BallotQuestionUIElement question) { this.RemoveAllAnswers(); - List answers = new ArrayList<>(question.getAnswers().getAnswers().getAnswersList()); + List answers = new ArrayList<>(question.getAnswers().getAnswers().getAnswersList()); if (question.getRandomizeListOrder()) { Collections.shuffle(answers); } - for (ByteString bytesAnswer : answers){ + for (BallotQuestionUIElementOuterClass.UIAnswer answer: answers){ try { - this.allAvailableAnswers.add(bytesAnswer); - this.AddAnswer(bytesAnswer); + this.allAvailableAnswers.add(answer); + this.AddAnswer(answer); } catch (IOException e) { e.printStackTrace(); } @@ -100,19 +100,23 @@ class PicturesAnswersUpdater implements EventHandler{ /** * Creates binaryData element which is grid pane with the binaryData and check box * - * @param binaryData string binaryData to show to the voter + * @param answer object which have the answer and its description * @param location the location of the picture * @return GridPane which contains string and check box */ - private GridPane GetAnswerElement(ByteString binaryData, int location) throws IOException { + private GridPane GetAnswerElement(BallotQuestionUIElementOuterClass.UIAnswer answer, int location) throws IOException { GridPane gridPane = new GridPane(); - BufferedImage bufferedImage = ImageIO.read(binaryData.newInput()); + BufferedImage bufferedImage = ImageIO.read(answer.getAnswer().newInput()); Image image = SwingFXUtils.toFXImage(bufferedImage, null); ImageView imageView = new ImageView(); imageView.setImage(image); + Label description = new Label(answer.getDescription()); + BorderPane descriptionBorderPane = new BorderPane(); + descriptionBorderPane.setCenter(description); + BorderPane borderPane = new BorderPane(); CheckBox checkBox = new CheckBox(); checkBox.setId(location+"-checkbox"); @@ -120,7 +124,8 @@ class PicturesAnswersUpdater implements EventHandler{ borderPane.setCenter(checkBox); gridPane.add(imageView, 2 , 1); - gridPane.add(borderPane, 2, 2); + gridPane.add(descriptionBorderPane, 2, 2); + gridPane.add(borderPane, 2, 3); gridPane.setPrefSize(100, 100); gridPane.setPadding(new Insets(10)); @@ -132,13 +137,13 @@ class PicturesAnswersUpdater implements EventHandler{ /** * Adds the GridPane binaryData to the panel * - * @param binaryData the binaryData string to represent to the user + * @param answer the binaryData string to represent to the user */ - private void AddAnswer(ByteString binaryData) throws IOException { + private void AddAnswer(BallotQuestionUIElementOuterClass.UIAnswer answer) throws IOException { GridPane container = this.GetAnswersContainer(); this.columIndex++; - GridPane newAnswer = this.GetAnswerElement(binaryData, this.columIndex); + GridPane newAnswer = this.GetAnswerElement(answer, this.columIndex); container.addColumn(1); container.add(newAnswer, this.columIndex, 0); @@ -154,7 +159,7 @@ class PicturesAnswersUpdater implements EventHandler{ GridPane answersContainer = this.GetAnswersContainer(); for (Node child : answersContainer.getChildren()){ GridPane answer = (GridPane)child; - BorderPane borderPane = (BorderPane) answer.getChildren().get(1); + BorderPane borderPane = (BorderPane) answer.getChildren().get(2); CheckBox checkBox = (CheckBox)borderPane.getCenter(); if (!Objects.equals(checkBox.getId(), target.getId()) && checkBox.isSelected()){ checkBox.fire(); @@ -173,6 +178,7 @@ class PicturesAnswersUpdater implements EventHandler{ if (target.isSelected()) { String answerIndex = target.getId().split("-")[0]; + System.out.println(answerIndex); this.imageUpdate.onSuccess(this.allAvailableAnswers.get(Integer.parseInt(answerIndex) - 1)); this.uncheckBoxes(target); } diff --git a/voting-booth-gui/src/main/java/meerkat/voting/gui/panels/select_candidate_by_picture/SelectCandidateByPictureController.java b/voting-booth-gui/src/main/java/meerkat/voting/gui/panels/select_candidate_by_picture/SelectCandidateByPictureController.java index b007868..b7041ac 100644 --- a/voting-booth-gui/src/main/java/meerkat/voting/gui/panels/select_candidate_by_picture/SelectCandidateByPictureController.java +++ b/voting-booth-gui/src/main/java/meerkat/voting/gui/panels/select_candidate_by_picture/SelectCandidateByPictureController.java @@ -1,9 +1,9 @@ package meerkat.voting.gui.panels.select_candidate_by_picture; import com.google.common.util.concurrent.FutureCallback; -import com.google.protobuf.ByteString; import javafx.fxml.FXML; import javafx.scene.input.MouseEvent; +import meerkat.protobuf.BallotQuestionUIElementOuterClass; import meerkat.voting.gui.managment.TwoWayNode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -12,7 +12,7 @@ import org.slf4j.LoggerFactory; * Created by Vladimir Eliezer Tokarev on 8/27/2016. * SelectCandidateNameController handle the behavior of select by picture screen */ -public class SelectCandidateByPictureController extends TwoWayNode implements FutureCallback { +public class SelectCandidateByPictureController extends TwoWayNode implements FutureCallback { private final Logger logger = LoggerFactory.getLogger(SelectCandidateByPictureController.class); @@ -50,7 +50,7 @@ public class SelectCandidateByPictureController extends TwoWayNode implements Fu } @Override - public void onSuccess(ByteString result) { + public void onSuccess(BallotQuestionUIElementOuterClass.UIAnswer result) { this.votersBallot.VotersImageSelection = result; } diff --git a/voting-booth-gui/src/main/java/meerkat/voting/gui/panels/select_candidate_name/StringsAnswersUpdater.java b/voting-booth-gui/src/main/java/meerkat/voting/gui/panels/select_candidate_name/StringsAnswersUpdater.java index 29f8f8e..6246a62 100644 --- a/voting-booth-gui/src/main/java/meerkat/voting/gui/panels/select_candidate_name/StringsAnswersUpdater.java +++ b/voting-booth-gui/src/main/java/meerkat/voting/gui/panels/select_candidate_name/StringsAnswersUpdater.java @@ -1,7 +1,6 @@ package meerkat.voting.gui.panels.select_candidate_name; import com.google.common.util.concurrent.FutureCallback; -import com.google.protobuf.ByteString; import javafx.event.Event; import javafx.scene.Node; import javafx.scene.control.CheckBox; @@ -108,13 +107,14 @@ class StringsAnswersUpdater implements javafx.event.EventHandler{ void UpdateAnswers(BallotQuestionUIElementOuterClass.BallotQuestionUIElement question) { this.RemoveAllAnswers(); - List answers = new ArrayList<>(question.getAnswers().getAnswers().getAnswersList()); + List answers = + new ArrayList<>(question.getAnswers().getAnswers().getAnswersList()); if (question.getRandomizeListOrder()){ Collections.shuffle(answers); } - for (ByteString bytesAnswer : answers){ - this.AddAnswer(bytesAnswer.toStringUtf8()); + for (BallotQuestionUIElementOuterClass.UIAnswer answer: answers){ + this.AddAnswer(answer.getAnswer().toStringUtf8()); } this.currentStage.show(); this.logger.debug("Removed all the old answers and add all the news ones."); diff --git a/voting-booth-gui/src/main/resources/configuration/VotingBoothConfiguration.json b/voting-booth-gui/src/main/resources/configuration/VotingBoothConfiguration.json index c378bdd..fe1c33c 100644 --- a/voting-booth-gui/src/main/resources/configuration/VotingBoothConfiguration.json +++ b/voting-booth-gui/src/main/resources/configuration/VotingBoothConfiguration.json @@ -9,9 +9,18 @@ "answers": { "type": 0, "answersValue": [ - "George Boosh", - "Antonio Banderass", - "Michael Jakson" + { + "answer": "George Boosh", + "description": "The dude with the crazy stare" + }, + { + "answer": "Antonio Banderass", + "description": "the Espanic actor" + }, + { + "answer": "Michael Jakson", + "description": "the first black white singer" + } ] } }, @@ -24,9 +33,18 @@ "answers": { "type": 2, "answersValue": [ - "/F:/vova/meerkat/meerkat-java/voting-booth-gui/src/main/resources/images/GeorgeBush.png", - "/F:/vova/meerkat/meerkat-java/voting-booth-gui/src/main/resources/images/MichaelJackson.png", - "/F:/vova/meerkat/meerkat-java/voting-booth-gui/src/main/resources/images/AntonioBanderass.png" + { + "answer": "/F:/vova/meerkat/meerkat-java/voting-booth-gui/src/main/resources/images/GeorgeBush.png", + "description": "George Boosh image." + }, + { + "answer": "/F:/vova/meerkat/meerkat-java/voting-booth-gui/src/main/resources/images/MichaelJackson.png", + "description": "Michael Jakson image." + }, + { + "answer": "/F:/vova/meerkat/meerkat-java/voting-booth-gui/src/main/resources/images/AntonioBanderass.png", + "description": "Antonio Banderass image." + } ] } }