From e931adb3c50e55e5b6af89d411bf9a7be950f69a Mon Sep 17 00:00:00 2001 From: Jesse Morgan Date: Tue, 17 Sep 2013 22:28:51 -0700 Subject: Fixing question 4 to skip 4a in some cases. For this fix I am moving Question and Answer from the backend into a new model package. Question is now used in SurveyPageResource instead of the Map. Eventually I should encode/decode the model from the json directly. I am adding support to the Question model to find the next question based on the answer to the current question. If the answer has a specific nextQuestion field, that is used. Otherwise the question's nextQuestion field is used. This is to facilitate skipping irrelevant questions. --- .../p4square/grow/backend/resources/Answer.java | 57 ------------ .../p4square/grow/backend/resources/Question.java | 72 --------------- .../backend/resources/SurveyResultsResource.java | 2 + .../p4square/grow/frontend/SurveyPageResource.java | 79 +++++++++------- src/com/p4square/grow/model/Answer.java | 63 +++++++++++++ src/com/p4square/grow/model/Question.java | 101 +++++++++++++++++++++ 6 files changed, 212 insertions(+), 162 deletions(-) delete mode 100644 src/com/p4square/grow/backend/resources/Answer.java delete mode 100644 src/com/p4square/grow/backend/resources/Question.java create mode 100644 src/com/p4square/grow/model/Answer.java create mode 100644 src/com/p4square/grow/model/Question.java (limited to 'src') diff --git a/src/com/p4square/grow/backend/resources/Answer.java b/src/com/p4square/grow/backend/resources/Answer.java deleted file mode 100644 index 5ba1bce..0000000 --- a/src/com/p4square/grow/backend/resources/Answer.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2013 Jesse Morgan - */ - -package com.p4square.grow.backend.resources; - -import java.util.Map; - -/** - * This is the model of an assessment question's answer. - * - * @author Jesse Morgan - */ -class Answer { - public static enum ScoreType { - NONE, AVERAGE, TRUMP; - } - - private final String mAnswerId; - private final String mAnswerText; - private final ScoreType mType; - private final float mScoreFactor; - - public Answer(final String id, final Map answer) { - mAnswerId = id; - mAnswerText = (String) answer.get("text"); - final String typeStr = (String) answer.get("type"); - if (typeStr == null) { - mType = ScoreType.AVERAGE; - } else { - mType = ScoreType.valueOf(typeStr.toUpperCase()); - } - - if (mType != ScoreType.NONE) { - mScoreFactor = Float.valueOf((String) answer.get("score")); - } else { - mScoreFactor = 0; - } - - } - - public String getId() { - return mAnswerId; - } - - public String getText() { - return mAnswerText; - } - - public ScoreType getType() { - return mType; - } - - public float getScoreFactor() { - return mScoreFactor; - } -} diff --git a/src/com/p4square/grow/backend/resources/Question.java b/src/com/p4square/grow/backend/resources/Question.java deleted file mode 100644 index e90ca77..0000000 --- a/src/com/p4square/grow/backend/resources/Question.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2013 Jesse Morgan - */ - -package com.p4square.grow.backend.resources; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -/** - * Model of an assessment question. - * - * @author Jesse Morgan - */ -class Question { - public static enum QuestionType { - TEXT, IMAGE, SLIDER, QUAD, CIRCLE; - } - - private final String mQuestionId; - private final QuestionType mType; - private final String mQuestionText; - private Map mAnswers; - - private final String mPreviousQuestionId; - private final String mNextQuestionId; - - public Question(final Map map) { - mQuestionId = (String) map.get("id"); - mType = QuestionType.valueOf(((String) map.get("type")).toUpperCase()); - - mQuestionText = (String) map.get("text"); - - mPreviousQuestionId = (String) map.get("previousQuestion"); - mNextQuestionId = (String) map.get("nextQuestion"); - - mAnswers = new HashMap(); - for (Map.Entry answer : - ((Map) map.get("answers")).entrySet()) { - - final String id = answer.getKey(); - final Map answerMap = (Map) answer.getValue(); - final Answer answerObj = new Answer(id, answerMap); - mAnswers.put(id, answerObj); - } - } - - public String getId() { - return mQuestionId; - } - - public QuestionType getType() { - return mType; - } - - public String getText() { - return mQuestionText; - } - - public String getPrevious() { - return mPreviousQuestionId; - } - - public String getNext() { - return mNextQuestionId; - } - - public Map getAnswers() { - return Collections.unmodifiableMap(mAnswers); - } -} diff --git a/src/com/p4square/grow/backend/resources/SurveyResultsResource.java b/src/com/p4square/grow/backend/resources/SurveyResultsResource.java index e93e253..208fa2e 100644 --- a/src/com/p4square/grow/backend/resources/SurveyResultsResource.java +++ b/src/com/p4square/grow/backend/resources/SurveyResultsResource.java @@ -20,6 +20,8 @@ import org.restlet.representation.StringRepresentation; import org.apache.log4j.Logger; +import com.p4square.grow.model.Answer; +import com.p4square.grow.model.Question; import com.p4square.grow.backend.GrowBackend; import com.p4square.grow.backend.db.CassandraDatabase; diff --git a/src/com/p4square/grow/frontend/SurveyPageResource.java b/src/com/p4square/grow/frontend/SurveyPageResource.java index 4d87027..8fc38ba 100644 --- a/src/com/p4square/grow/frontend/SurveyPageResource.java +++ b/src/com/p4square/grow/frontend/SurveyPageResource.java @@ -26,6 +26,7 @@ import com.p4square.fmfacade.json.ClientException; import com.p4square.fmfacade.FreeMarkerPageResource; import com.p4square.grow.config.Config; +import com.p4square.grow.model.Question; /** * SurveyPageResource handles rendering the survey and processing user's answers. @@ -78,8 +79,8 @@ public class SurveyPageResource extends FreeMarkerPageResource { mQuestionId = getCurrentQuestionId(); if (mQuestionId != null) { - Map lastQuestion = getQuestion(mQuestionId); - return redirectToNextQuestion(lastQuestion); + Question lastQuestion = getQuestion(mQuestionId); + return redirectToNextQuestion(lastQuestion, getAnswer(mQuestionId)); } } @@ -88,43 +89,41 @@ public class SurveyPageResource extends FreeMarkerPageResource { mQuestionId = "first"; } - Map questionData = getQuestion(mQuestionId); - if (questionData == null) { + Question question = getQuestion(mQuestionId); + if (question == null) { setStatus(Status.CLIENT_ERROR_NOT_FOUND); return new ErrorPage("Could not find the question."); } // Set the real question id if a meta-id was used (i.e. first) - mQuestionId = (String) questionData.get("id"); + mQuestionId = question.getId(); // Get any previous answer to the question - String selectedAnswer = null; - { - JsonResponse response = backendGet("/accounts/" + mUserId + "/assessment/answers/" + mQuestionId); - if (response.getStatus().isSuccess()) { - selectedAnswer = (String) response.getMap().get("answerId"); - } - } + String selectedAnswer = getAnswer(mQuestionId); Map root = getRootObject(); - root.put("question", questionData); + root.put("question", question.getMap()); root.put("selectedAnswerId", selectedAnswer); // Get the question count and compute progress - Map countData = getQuestion("count"); - if (countData != null) { - JsonResponse response = backendGet("/accounts/" + mUserId + "/assessment"); + { + JsonResponse response = backendGet("/assessment/question/count"); if (response.getStatus().isSuccess()) { - Integer completed = (Integer) response.getMap().get("count"); - Integer total = (Integer) countData.get("count"); - - if (completed != null && total != null && total != 0) { - root.put("percentComplete", String.valueOf((int) (100.0 * completed) / total)); + Map countData = response.getMap(); + if (countData != null) { + response = backendGet("/accounts/" + mUserId + "/assessment"); + if (response.getStatus().isSuccess()) { + Integer completed = (Integer) response.getMap().get("count"); + Integer total = (Integer) countData.get("count"); + + if (completed != null && total != null && total != 0) { + root.put("percentComplete", String.valueOf((int) (100.0 * completed) / total)); + } + } } } } - return new TemplateRepresentation(mSurveyTemplate, root, MediaType.TEXT_HTML); } catch (Exception e) { @@ -158,8 +157,8 @@ public class SurveyPageResource extends FreeMarkerPageResource { try { // Find the question - Map questionData = getQuestion(mQuestionId); - if (questionData == null) { + Question question = getQuestion(mQuestionId); + if (question == null) { // User is answering a question which doesn't exist setStatus(Status.CLIENT_ERROR_NOT_FOUND); return new ErrorPage("Question not found."); @@ -182,10 +181,10 @@ public class SurveyPageResource extends FreeMarkerPageResource { // Find the next question or finish the assessment. if ("previous".equals(direction)) { - return redirectToPreviousQuestion(questionData); + return redirectToPreviousQuestion(question); } else { - return redirectToNextQuestion(questionData); + return redirectToNextQuestion(question, answerId); } } catch (Exception e) { @@ -213,7 +212,7 @@ public class SurveyPageResource extends FreeMarkerPageResource { } } - private Map getQuestion(String id) { + private Question getQuestion(String id) { try { Map questionData = null; @@ -223,7 +222,7 @@ public class SurveyPageResource extends FreeMarkerPageResource { } questionData = response.getMap(); - return questionData; + return new Question((Map) questionData); } catch (ClientException e) { LOG.warn("Error fetching question.", e); @@ -231,8 +230,22 @@ public class SurveyPageResource extends FreeMarkerPageResource { } } - private Representation redirectToNextQuestion(Map questionData) { - String nextQuestionId = (String) questionData.get("nextQuestion"); + private String getAnswer(String questionId) { + try { + JsonResponse response = backendGet("/accounts/" + mUserId + "/assessment/answers/" + questionId); + if (response.getStatus().isSuccess()) { + return (String) response.getMap().get("answerId"); + } + + } catch (ClientException e) { + LOG.warn("Error fetching answer to question " + questionId, e); + } + + return null; + } + + private Representation redirectToNextQuestion(Question question, String answerid) { + String nextQuestionId = question.getNextQuestion(answerid); if (nextQuestionId == null) { // Just finished the last question. Update the user's account @@ -252,11 +265,11 @@ public class SurveyPageResource extends FreeMarkerPageResource { return redirectToQuestion(nextQuestionId); } - private Representation redirectToPreviousQuestion(Map questionData) { - String nextQuestionId = (String) questionData.get("previousQuestion"); + private Representation redirectToPreviousQuestion(Question question) { + String nextQuestionId = question.getPreviousQuestion(); if (nextQuestionId == null) { - nextQuestionId = (String) questionData.get("id"); + nextQuestionId = (String) question.getId(); } return redirectToQuestion(nextQuestionId); diff --git a/src/com/p4square/grow/model/Answer.java b/src/com/p4square/grow/model/Answer.java new file mode 100644 index 0000000..4c84060 --- /dev/null +++ b/src/com/p4square/grow/model/Answer.java @@ -0,0 +1,63 @@ +/* + * Copyright 2013 Jesse Morgan + */ + +package com.p4square.grow.model; + +import java.util.Map; + +/** + * This is the model of an assessment question's answer. + * + * @author Jesse Morgan + */ +public class Answer { + public static enum ScoreType { + NONE, AVERAGE, TRUMP; + } + + private final String mAnswerId; + private final String mAnswerText; + private final ScoreType mType; + private final float mScoreFactor; + private final String mNextQuestionId; + + public Answer(final String id, final Map answer) { + mAnswerId = id; + mAnswerText = (String) answer.get("text"); + final String typeStr = (String) answer.get("type"); + if (typeStr == null) { + mType = ScoreType.AVERAGE; + } else { + mType = ScoreType.valueOf(typeStr.toUpperCase()); + } + + if (mType != ScoreType.NONE) { + mScoreFactor = Float.valueOf((String) answer.get("score")); + } else { + mScoreFactor = 0; + } + + mNextQuestionId = (String) answer.get("nextQuestion"); + } + + public String getId() { + return mAnswerId; + } + + public String getText() { + return mAnswerText; + } + + public ScoreType getType() { + return mType; + } + + public float getScoreFactor() { + return mScoreFactor; + } + + public String getNextQuestion() { + return mNextQuestionId; + } +} diff --git a/src/com/p4square/grow/model/Question.java b/src/com/p4square/grow/model/Question.java new file mode 100644 index 0000000..387d723 --- /dev/null +++ b/src/com/p4square/grow/model/Question.java @@ -0,0 +1,101 @@ +/* + * Copyright 2013 Jesse Morgan + */ + +package com.p4square.grow.model; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * Model of an assessment question. + * + * @author Jesse Morgan + */ +public class Question { + public static enum QuestionType { + TEXT, IMAGE, SLIDER, QUAD, CIRCLE; + } + + private final Map mMap; + private final String mQuestionId; + private final QuestionType mType; + private final String mQuestionText; + private Map mAnswers; + + private final String mPreviousQuestionId; + private final String mNextQuestionId; + + public Question(final Map map) { + mMap = map; + mQuestionId = (String) map.get("id"); + mType = QuestionType.valueOf(((String) map.get("type")).toUpperCase()); + + mQuestionText = (String) map.get("text"); + + mPreviousQuestionId = (String) map.get("previousQuestion"); + mNextQuestionId = (String) map.get("nextQuestion"); + + mAnswers = new HashMap(); + for (Map.Entry answer : + ((Map) map.get("answers")).entrySet()) { + + final String id = answer.getKey(); + final Map answerMap = (Map) answer.getValue(); + final Answer answerObj = new Answer(id, answerMap); + mAnswers.put(id, answerObj); + } + } + + public String getId() { + return mQuestionId; + } + + public QuestionType getType() { + return mType; + } + + public String getText() { + return mQuestionText; + } + + public String getPreviousQuestion() { + return mPreviousQuestionId; + } + + public String getNextQuestion() { + return mNextQuestionId; + } + + public Map getAnswers() { + return Collections.unmodifiableMap(mAnswers); + } + + public Map getMap() { + return Collections.unmodifiableMap(mMap); + } + + /** + * Determine the id of the next question based on the answer to this + * question. + * + * @param answerid + * The id of the selected answer. + * @return a question id or null if this is the last question. + */ + public String getNextQuestion(String answerid) { + String nextQuestion = null; + + Answer a = mAnswers.get(answerid); + if (a != null) { + nextQuestion = a.getNextQuestion(); + } + + if (nextQuestion == null) { + nextQuestion = mNextQuestionId; + } + + return nextQuestion; + } +} -- cgit v1.2.3