summaryrefslogtreecommitdiff
path: root/src/main/java/com/p4square/grow/backend/resources
diff options
context:
space:
mode:
authorJesse Morgan <jesse@jesterpm.net>2016-04-09 14:22:20 -0700
committerJesse Morgan <jesse@jesterpm.net>2016-04-09 15:48:01 -0700
commit3102d8bce3426d9cf41aeaf201c360d342677770 (patch)
tree38c4f1e8828f9af9c4b77a173bee0d312b321698 /src/main/java/com/p4square/grow/backend/resources
parentbbf907e51dfcf157bdee24dead1d531122aa25db (diff)
Switching from Ivy+Ant to Maven.
Diffstat (limited to 'src/main/java/com/p4square/grow/backend/resources')
-rw-r--r--src/main/java/com/p4square/grow/backend/resources/AccountResource.java87
-rw-r--r--src/main/java/com/p4square/grow/backend/resources/BannerResource.java85
-rw-r--r--src/main/java/com/p4square/grow/backend/resources/SurveyResource.java115
-rw-r--r--src/main/java/com/p4square/grow/backend/resources/SurveyResultsResource.java253
-rw-r--r--src/main/java/com/p4square/grow/backend/resources/TrainingRecordResource.java235
-rw-r--r--src/main/java/com/p4square/grow/backend/resources/TrainingResource.java97
6 files changed, 872 insertions, 0 deletions
diff --git a/src/main/java/com/p4square/grow/backend/resources/AccountResource.java b/src/main/java/com/p4square/grow/backend/resources/AccountResource.java
new file mode 100644
index 0000000..2ac7061
--- /dev/null
+++ b/src/main/java/com/p4square/grow/backend/resources/AccountResource.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2013 Jesse Morgan
+ */
+
+package com.p4square.grow.backend.resources;
+
+import java.io.IOException;
+
+import org.restlet.data.Status;
+import org.restlet.resource.ServerResource;
+import org.restlet.representation.Representation;
+
+import org.restlet.ext.jackson.JacksonRepresentation;
+
+import org.apache.log4j.Logger;
+
+import com.p4square.grow.model.UserRecord;
+import com.p4square.grow.provider.Provider;
+import com.p4square.grow.provider.ProvidesUserRecords;
+import com.p4square.grow.provider.JsonEncodedProvider;
+
+/**
+ * Stores a document about a user.
+ *
+ * @author Jesse Morgan <jesse@jesterpm.net>
+ */
+public class AccountResource extends ServerResource {
+ private static final Logger LOG = Logger.getLogger(AccountResource.class);
+
+ private Provider<String, UserRecord> mUserRecordProvider;
+
+ private String mUserId;
+
+ @Override
+ public void doInit() {
+ super.doInit();
+
+ final ProvidesUserRecords backend = (ProvidesUserRecords) getApplication();
+ mUserRecordProvider = backend.getUserRecordProvider();
+
+ mUserId = getAttribute("userId");
+ }
+
+ /**
+ * Handle GET Requests.
+ */
+ @Override
+ protected Representation get() {
+ try {
+ UserRecord result = mUserRecordProvider.get(mUserId);
+
+ if (result == null) {
+ setStatus(Status.CLIENT_ERROR_NOT_FOUND);
+ return null;
+ }
+
+ JacksonRepresentation<UserRecord> rep = new JacksonRepresentation<UserRecord>(result);
+ rep.setObjectMapper(JsonEncodedProvider.MAPPER);
+ return rep;
+
+ } catch (IOException e) {
+ setStatus(Status.SERVER_ERROR_INTERNAL);
+ return null;
+ }
+ }
+
+ /**
+ * Handle PUT requests
+ */
+ @Override
+ protected Representation put(Representation entity) {
+ try {
+ JacksonRepresentation<UserRecord> representation =
+ new JacksonRepresentation<>(entity, UserRecord.class);
+ representation.setObjectMapper(JsonEncodedProvider.MAPPER);
+ UserRecord record = representation.getObject();
+
+ mUserRecordProvider.put(mUserId, record);
+ setStatus(Status.SUCCESS_NO_CONTENT);
+
+ } catch (IOException e) {
+ setStatus(Status.SERVER_ERROR_INTERNAL);
+ }
+
+ return null;
+ }
+}
diff --git a/src/main/java/com/p4square/grow/backend/resources/BannerResource.java b/src/main/java/com/p4square/grow/backend/resources/BannerResource.java
new file mode 100644
index 0000000..2b9c8e6
--- /dev/null
+++ b/src/main/java/com/p4square/grow/backend/resources/BannerResource.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2013 Jesse Morgan
+ */
+
+package com.p4square.grow.backend.resources;
+
+import java.io.IOException;
+
+import org.restlet.data.Status;
+import org.restlet.ext.jackson.JacksonRepresentation;
+import org.restlet.representation.Representation;
+import org.restlet.representation.StringRepresentation;
+import org.restlet.resource.ServerResource;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import org.apache.log4j.Logger;
+
+import com.p4square.grow.backend.GrowBackend;
+import com.p4square.grow.model.Banner;
+import com.p4square.grow.provider.JsonEncodedProvider;
+import com.p4square.grow.provider.Provider;
+
+/**
+ * Fetches or sets the banner string.
+ *
+ * @author Jesse Morgan <jesse@jesterpm.net>
+ */
+public class BannerResource extends ServerResource {
+ private static final Logger LOG = Logger.getLogger(BannerResource.class);
+
+ public static final ObjectMapper MAPPER = JsonEncodedProvider.MAPPER;
+
+ private Provider<String, String> mStringProvider;
+
+ @Override
+ public void doInit() {
+ super.doInit();
+
+ final GrowBackend backend = (GrowBackend) getApplication();
+ mStringProvider = backend.getStringProvider();
+ }
+
+ /**
+ * Handle GET Requests.
+ */
+ @Override
+ protected Representation get() {
+ String result = null;
+ try {
+ result = mStringProvider.get("banner");
+
+ } catch (IOException e) {
+ LOG.warn("Exception loading banner: " + e);
+ }
+
+ if (result == null || result.length() == 0) {
+ result = "{\"html\":null}";
+ }
+
+ return new StringRepresentation(result);
+ }
+
+ /**
+ * Handle PUT requests
+ */
+ @Override
+ protected Representation put(Representation entity) {
+ try {
+ JacksonRepresentation<Banner> representation =
+ new JacksonRepresentation<>(entity, Banner.class);
+ representation.setObjectMapper(MAPPER);
+
+ Banner banner = representation.getObject();
+
+ mStringProvider.put("banner", MAPPER.writeValueAsString(banner));
+ setStatus(Status.SUCCESS_NO_CONTENT);
+
+ } catch (IOException e) {
+ setStatus(Status.SERVER_ERROR_INTERNAL);
+ }
+
+ return null;
+ }
+}
diff --git a/src/main/java/com/p4square/grow/backend/resources/SurveyResource.java b/src/main/java/com/p4square/grow/backend/resources/SurveyResource.java
new file mode 100644
index 0000000..8723ee2
--- /dev/null
+++ b/src/main/java/com/p4square/grow/backend/resources/SurveyResource.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2013 Jesse Morgan
+ */
+
+package com.p4square.grow.backend.resources;
+
+import java.io.IOException;
+
+import java.util.Map;
+import java.util.HashMap;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import org.restlet.data.MediaType;
+import org.restlet.data.Status;
+import org.restlet.ext.jackson.JacksonRepresentation;
+import org.restlet.representation.Representation;
+import org.restlet.representation.StringRepresentation;
+import org.restlet.resource.ServerResource;
+
+import org.apache.log4j.Logger;
+
+import com.p4square.grow.backend.GrowBackend;
+import com.p4square.grow.model.Question;
+import com.p4square.grow.provider.JsonEncodedProvider;
+import com.p4square.grow.provider.Provider;
+
+/**
+ * This resource manages assessment questions.
+ *
+ * @author Jesse Morgan <jesse@jesterpm.net>
+ */
+public class SurveyResource extends ServerResource {
+ private static final Logger LOG = Logger.getLogger(SurveyResource.class);
+
+ private static final ObjectMapper MAPPER = JsonEncodedProvider.MAPPER;
+
+ private Provider<String, Question> mQuestionProvider;
+ private Provider<String, String> mStringProvider;
+
+ private String mQuestionId;
+
+ @Override
+ public void doInit() {
+ super.doInit();
+
+ final GrowBackend backend = (GrowBackend) getApplication();
+ mQuestionProvider = backend.getQuestionProvider();
+ mStringProvider = backend.getStringProvider();
+
+ mQuestionId = getAttribute("questionId");
+ }
+
+ /**
+ * Handle GET Requests.
+ */
+ @Override
+ protected Representation get() {
+ String result = "{}";
+
+ if (mQuestionId == null) {
+ // TODO: List all question ids
+
+ } else if (mQuestionId.equals("first")) {
+ // Get the first question id from db?
+ Map<?, ?> questionSummary = getQuestionsSummary();
+ mQuestionId = (String) questionSummary.get("first");
+
+ } else if (mQuestionId.equals("count")) {
+ // Get the first question id from db?
+ Map<?, ?> questionSummary = getQuestionsSummary();
+
+ return new StringRepresentation("{\"count\":" +
+ String.valueOf((Integer) questionSummary.get("count")) + "}");
+ }
+
+ if (mQuestionId != null) {
+ // Get a question by id
+ Question question = null;
+ try {
+ question = mQuestionProvider.get(mQuestionId);
+ } catch (IOException e) {
+ LOG.error("IOException loading question: " + e);
+ }
+
+ if (question == null) {
+ // 404
+ setStatus(Status.CLIENT_ERROR_NOT_FOUND);
+ return null;
+ }
+
+ JacksonRepresentation<Question> rep = new JacksonRepresentation<>(question);
+ rep.setObjectMapper(MAPPER);
+ return rep;
+ }
+
+ return new StringRepresentation(result);
+ }
+
+ private Map<?, ?> getQuestionsSummary() {
+ try {
+ // TODO: This could be better. Quick fix for provider support.
+ String json = mStringProvider.get("/questions");
+
+ if (json != null) {
+ return MAPPER.readValue(json, Map.class);
+ }
+
+ } catch (IOException e) {
+ LOG.info("Exception reading questions summary.", e);
+ }
+
+ return null;
+ }
+}
diff --git a/src/main/java/com/p4square/grow/backend/resources/SurveyResultsResource.java b/src/main/java/com/p4square/grow/backend/resources/SurveyResultsResource.java
new file mode 100644
index 0000000..7c15cfd
--- /dev/null
+++ b/src/main/java/com/p4square/grow/backend/resources/SurveyResultsResource.java
@@ -0,0 +1,253 @@
+/*
+ * Copyright 2013 Jesse Morgan
+ */
+
+package com.p4square.grow.backend.resources;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.HashMap;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import org.restlet.data.MediaType;
+import org.restlet.data.Status;
+import org.restlet.representation.Representation;
+import org.restlet.representation.StringRepresentation;
+import org.restlet.resource.ServerResource;
+
+import org.apache.log4j.Logger;
+
+import com.p4square.grow.backend.GrowBackend;
+import com.p4square.grow.model.Answer;
+import com.p4square.grow.model.Question;
+import com.p4square.grow.model.RecordedAnswer;
+import com.p4square.grow.model.Score;
+import com.p4square.grow.model.UserRecord;
+import com.p4square.grow.provider.CollectionProvider;
+import com.p4square.grow.provider.Provider;
+
+
+/**
+ * Store the user's answers to the assessment and generate their score.
+ *
+ * @author Jesse Morgan <jesse@jesterpm.net>
+ */
+public class SurveyResultsResource extends ServerResource {
+ private static final Logger LOG = Logger.getLogger(SurveyResultsResource.class);
+
+ private static final ObjectMapper MAPPER = new ObjectMapper();
+
+ static enum RequestType {
+ ASSESSMENT, ANSWER
+ }
+
+ private CollectionProvider<String, String, String> mAnswerProvider;
+ private Provider<String, Question> mQuestionProvider;
+ private Provider<String, UserRecord> mUserRecordProvider;
+
+ private RequestType mRequestType;
+ private String mUserId;
+ private String mQuestionId;
+
+ @Override
+ public void doInit() {
+ super.doInit();
+
+ final GrowBackend backend = (GrowBackend) getApplication();
+ mAnswerProvider = backend.getAnswerProvider();
+ mQuestionProvider = backend.getQuestionProvider();
+ mUserRecordProvider = backend.getUserRecordProvider();
+
+ mUserId = getAttribute("userId");
+ mQuestionId = getAttribute("questionId");
+
+ mRequestType = RequestType.ASSESSMENT;
+ if (mQuestionId != null) {
+ mRequestType = RequestType.ANSWER;
+ }
+ }
+
+ /**
+ * Handle GET Requests.
+ */
+ @Override
+ protected Representation get() {
+ try {
+ String result = null;
+
+ switch (mRequestType) {
+ case ANSWER:
+ result = mAnswerProvider.get(mUserId, mQuestionId);
+ break;
+
+ case ASSESSMENT:
+ result = mAnswerProvider.get(mUserId, "summary");
+ if (result == null || result.length() == 0) {
+ result = buildAssessment();
+ }
+ break;
+ }
+
+ if (result == null) {
+ setStatus(Status.CLIENT_ERROR_NOT_FOUND);
+ return null;
+ }
+
+ return new StringRepresentation(result);
+ } catch (IOException e) {
+ LOG.error("IOException getting answer: ", e);
+ setStatus(Status.SERVER_ERROR_INTERNAL);
+ return null;
+ }
+ }
+
+ /**
+ * Handle PUT requests
+ */
+ @Override
+ protected Representation put(Representation entity) {
+ boolean success = false;
+
+ switch (mRequestType) {
+ case ANSWER:
+ try {
+ mAnswerProvider.put(mUserId, mQuestionId, entity.getText());
+ mAnswerProvider.put(mUserId, "lastAnswered", mQuestionId);
+ mAnswerProvider.put(mUserId, "summary", null);
+ success = true;
+
+ } catch (Exception e) {
+ LOG.warn("Caught exception putting answer: " + e.getMessage(), e);
+ }
+ break;
+
+ default:
+ setStatus(Status.CLIENT_ERROR_METHOD_NOT_ALLOWED);
+ return null;
+ }
+
+ if (success) {
+ setStatus(Status.SUCCESS_NO_CONTENT);
+
+ } else {
+ setStatus(Status.SERVER_ERROR_INTERNAL);
+ }
+
+ return null;
+ }
+
+ /**
+ * Clear assessment results.
+ */
+ @Override
+ protected Representation delete() {
+ boolean success = false;
+
+ switch (mRequestType) {
+ case ANSWER:
+ try {
+ mAnswerProvider.put(mUserId, mQuestionId, null);
+ mAnswerProvider.put(mUserId, "summary", null);
+ success = true;
+
+ } catch (Exception e) {
+ LOG.warn("Caught exception putting answer: " + e.getMessage(), e);
+ }
+ break;
+
+ case ASSESSMENT:
+ try {
+ mAnswerProvider.put(mUserId, "summary", null);
+ mAnswerProvider.put(mUserId, "lastAnswered", null);
+ // TODO Delete answers
+
+ UserRecord record = mUserRecordProvider.get(mUserId);
+ if (record != null) {
+ record.setLanding("assessment");
+ mUserRecordProvider.put(mUserId, record);
+ }
+
+ success = true;
+
+ } catch (Exception e) {
+ LOG.warn("Caught exception putting answer: " + e.getMessage(), e);
+ }
+ break;
+
+ default:
+ setStatus(Status.CLIENT_ERROR_METHOD_NOT_ALLOWED);
+ return null;
+ }
+
+ if (success) {
+ setStatus(Status.SUCCESS_NO_CONTENT);
+
+ } else {
+ setStatus(Status.SERVER_ERROR_INTERNAL);
+ }
+
+ return null;
+
+ }
+
+ /**
+ * This method compiles assessment results.
+ */
+ private String buildAssessment() throws IOException {
+ StringBuilder sb = new StringBuilder("{ ");
+
+ // Last question answered
+ final String lastAnswered = mAnswerProvider.get(mUserId, "lastAnswered");
+ if (lastAnswered != null && lastAnswered.length() > 0) {
+ sb.append("\"lastAnswered\": \"" + lastAnswered + "\", ");
+ }
+
+ // Compute score
+ Map<String, String> row = mAnswerProvider.query(mUserId);
+ if (row.size() > 0) {
+ Score score = new Score();
+ boolean scoringDone = false;
+ int totalAnswers = 0;
+ for (Map.Entry<String, String> c : row.entrySet()) {
+ if (c.getKey().equals("lastAnswered") || c.getKey().equals("summary")) {
+ continue;
+ }
+
+ try {
+ Question question = mQuestionProvider.get(c.getKey());
+ RecordedAnswer userAnswer = MAPPER.readValue(c.getValue(), RecordedAnswer.class);
+
+ if (question == null) {
+ LOG.warn("Answer for unknown question: " + c.getKey());
+ continue;
+ }
+
+ LOG.debug("Scoring questionId: " + c.getKey());
+ scoringDone = !question.scoreAnswer(score, userAnswer);
+
+ } catch (Exception e) {
+ LOG.error("Failed to score question: {userid: \"" + mUserId +
+ "\", questionid:\"" + c.getKey() +
+ "\", userAnswer:\"" + c.getValue() + "\"}", e);
+ }
+
+ totalAnswers++;
+ }
+
+ sb.append("\"score\":" + score.getScore());
+ sb.append(", \"sum\":" + score.getSum());
+ sb.append(", \"count\":" + score.getCount());
+ sb.append(", \"totalAnswers\":" + totalAnswers);
+ sb.append(", \"result\":\"" + score.toString() + "\"");
+ }
+
+ sb.append(" }");
+ String summary = sb.toString();
+
+ // Persist summary
+ mAnswerProvider.put(mUserId, "summary", summary);
+
+ return summary;
+ }
+}
diff --git a/src/main/java/com/p4square/grow/backend/resources/TrainingRecordResource.java b/src/main/java/com/p4square/grow/backend/resources/TrainingRecordResource.java
new file mode 100644
index 0000000..51ba56a
--- /dev/null
+++ b/src/main/java/com/p4square/grow/backend/resources/TrainingRecordResource.java
@@ -0,0 +1,235 @@
+/*
+ * Copyright 2013 Jesse Morgan
+ */
+
+package com.p4square.grow.backend.resources;
+
+import java.io.IOException;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import org.restlet.data.MediaType;
+import org.restlet.data.Status;
+import org.restlet.resource.ServerResource;
+import org.restlet.representation.Representation;
+import org.restlet.representation.StringRepresentation;
+
+import org.restlet.ext.jackson.JacksonRepresentation;
+
+import org.apache.log4j.Logger;
+
+import com.p4square.grow.backend.GrowBackend;
+
+import com.p4square.grow.model.Chapter;
+import com.p4square.grow.model.Playlist;
+import com.p4square.grow.model.VideoRecord;
+import com.p4square.grow.model.TrainingRecord;
+
+import com.p4square.grow.provider.CollectionProvider;
+import com.p4square.grow.provider.JsonEncodedProvider;
+import com.p4square.grow.provider.Provider;
+import com.p4square.grow.provider.ProvidesAssessments;
+import com.p4square.grow.provider.ProvidesTrainingRecords;
+
+import com.p4square.grow.model.Score;
+
+/**
+ *
+ * @author Jesse Morgan <jesse@jesterpm.net>
+ */
+public class TrainingRecordResource extends ServerResource {
+ private static final Logger LOG = Logger.getLogger(TrainingRecordResource.class);
+ private static final ObjectMapper MAPPER = JsonEncodedProvider.MAPPER;
+
+ static enum RequestType {
+ SUMMARY, VIDEO
+ }
+
+ private Provider<String, TrainingRecord> mTrainingRecordProvider;
+ private CollectionProvider<String, String, String> mAnswerProvider;
+
+ private RequestType mRequestType;
+ private String mUserId;
+ private String mVideoId;
+ private TrainingRecord mRecord;
+
+ @Override
+ public void doInit() {
+ super.doInit();
+
+ mTrainingRecordProvider = ((ProvidesTrainingRecords) getApplication()).getTrainingRecordProvider();
+ mAnswerProvider = ((ProvidesAssessments) getApplication()).getAnswerProvider();
+
+ mUserId = getAttribute("userId");
+ mVideoId = getAttribute("videoId");
+
+ try {
+ Playlist defaultPlaylist = ((ProvidesTrainingRecords) getApplication()).getDefaultPlaylist();
+
+ mRecord = mTrainingRecordProvider.get(mUserId);
+ if (mRecord == null) {
+ mRecord = new TrainingRecord();
+ mRecord.setPlaylist(defaultPlaylist);
+ skipAssessedChapters(mUserId, mRecord);
+ } else {
+ // Merge the playlist with the most recent version.
+ mRecord.getPlaylist().merge(defaultPlaylist);
+ }
+
+ } catch (IOException e) {
+ LOG.error("IOException loading TrainingRecord: " + e.getMessage(), e);
+ mRecord = null;
+ }
+
+ mRequestType = RequestType.SUMMARY;
+ if (mVideoId != null) {
+ mRequestType = RequestType.VIDEO;
+ }
+ }
+
+ /**
+ * Handle GET Requests.
+ */
+ @Override
+ protected Representation get() {
+ JacksonRepresentation<?> rep = null;
+
+ if (mRecord == null) {
+ setStatus(Status.SERVER_ERROR_INTERNAL);
+ return null;
+ }
+
+ switch (mRequestType) {
+ case VIDEO:
+ VideoRecord video = mRecord.getPlaylist().find(mVideoId);
+ if (video == null) {
+ break; // Fall through and return 404
+ }
+ rep = new JacksonRepresentation<VideoRecord>(video);
+ break;
+
+ case SUMMARY:
+ rep = new JacksonRepresentation<TrainingRecord>(mRecord);
+ break;
+ }
+
+ if (rep == null) {
+ setStatus(Status.CLIENT_ERROR_NOT_FOUND);
+ return null;
+
+ } else {
+ rep.setObjectMapper(JsonEncodedProvider.MAPPER);
+ return rep;
+ }
+ }
+
+ /**
+ * Handle PUT requests
+ */
+ @Override
+ protected Representation put(Representation entity) {
+ if (mRecord == null) {
+ setStatus(Status.SERVER_ERROR_INTERNAL);
+ return null;
+ }
+
+ switch (mRequestType) {
+ case VIDEO:
+ try {
+ JacksonRepresentation<VideoRecord> representation =
+ new JacksonRepresentation<>(entity, VideoRecord.class);
+ representation.setObjectMapper(JsonEncodedProvider.MAPPER);
+ VideoRecord update = representation.getObject();
+ VideoRecord video = mRecord.getPlaylist().find(mVideoId);
+
+ if (video == null) {
+ // TODO: Video isn't on their playlist...
+ LOG.warn("Skipping video completion for video missing from playlist.");
+
+ } else if (update.getComplete() && !video.getComplete()) {
+ // Video was newly completed
+ video.complete();
+ mRecord.setLastVideo(mVideoId);
+
+ mTrainingRecordProvider.put(mUserId, mRecord);
+ }
+
+ setStatus(Status.SUCCESS_NO_CONTENT);
+
+ } catch (Exception e) {
+ LOG.warn("Caught exception updating training record: " + e.getMessage(), e);
+ setStatus(Status.SERVER_ERROR_INTERNAL);
+ }
+ break;
+
+ default:
+ setStatus(Status.CLIENT_ERROR_METHOD_NOT_ALLOWED);
+ }
+
+ return null;
+ }
+
+ private Score getAssessedScore(String userId) throws IOException {
+ // Get the user's score.
+ Score assessedScore = new Score(0, 0);
+
+ String summaryString = mAnswerProvider.get(userId, "summary");
+ if (summaryString == null) {
+ throw new IOException("Asked to create training record for unassessed user " + userId);
+ }
+
+ Map<?,?> summary = MAPPER.readValue(summaryString, Map.class);
+
+ if (summary.containsKey("sum") && summary.containsKey("count")) {
+ double sum = (Double) summary.get("sum");
+ int count = (Integer) summary.get("count");
+ assessedScore = new Score(sum, count);
+ }
+
+ return assessedScore;
+ }
+
+ /**
+ * Mark the chapters which the user assessed through as not required.
+ */
+ private void skipAssessedChapters(String userId, TrainingRecord record) {
+ // Get the user's score.
+ Score assessedScore = new Score(0, 0);
+
+ try {
+ assessedScore = getAssessedScore(userId);
+ } catch (IOException e) {
+ LOG.error("IOException fetching assessment record for " + userId, e);
+ return;
+ }
+
+ // Mark the correct videos as not required.
+ Playlist playlist = record.getPlaylist();
+
+ for (Map.Entry<String, Chapter> entry : playlist.getChaptersMap().entrySet()) {
+ String chapterId = entry.getKey();
+ Chapter chapter = entry.getValue();
+ boolean required;
+
+ if ("introduction".equals(chapter)) {
+ // Introduction chapter is always required
+ required = true;
+
+ } else {
+ // Chapter required if the floor of the score is <= the chapter's numeric value.
+ required = assessedScore.floor() <= Score.numericScore(chapterId);
+ }
+
+ if (!required) {
+ for (VideoRecord video : chapter.getVideos().values()) {
+ video.setRequired(required);
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/p4square/grow/backend/resources/TrainingResource.java b/src/main/java/com/p4square/grow/backend/resources/TrainingResource.java
new file mode 100644
index 0000000..6efdfab
--- /dev/null
+++ b/src/main/java/com/p4square/grow/backend/resources/TrainingResource.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2013 Jesse Morgan
+ */
+
+package com.p4square.grow.backend.resources;
+
+import java.io.IOException;
+import java.util.Map;
+
+import org.restlet.data.Status;
+import org.restlet.resource.ServerResource;
+import org.restlet.representation.Representation;
+import org.restlet.representation.StringRepresentation;
+
+import org.apache.log4j.Logger;
+
+import com.p4square.grow.backend.GrowBackend;
+import com.p4square.grow.backend.db.CassandraDatabase;
+
+import com.p4square.grow.provider.CollectionProvider;
+/**
+ * This resource returns a listing of training items for a particular level.
+ *
+ * @author Jesse Morgan <jesse@jesterpm.net>
+ */
+public class TrainingResource extends ServerResource {
+ private final static Logger LOG = Logger.getLogger(TrainingResource.class);
+
+ private CollectionProvider<String, String, String> mVideoProvider;
+
+ private String mLevel;
+ private String mVideoId;
+
+ @Override
+ public void doInit() {
+ super.doInit();
+
+ GrowBackend backend = (GrowBackend) getApplication();
+ mVideoProvider = backend.getVideoProvider();
+
+ mLevel = getAttribute("level");
+ mVideoId = getAttribute("videoId");
+ }
+
+ /**
+ * Handle GET Requests.
+ */
+ @Override
+ protected Representation get() {
+ String result = null;
+
+ if (mLevel == null) {
+ setStatus(Status.CLIENT_ERROR_NOT_FOUND);
+ return null;
+ }
+
+ try {
+ if (mVideoId == null) {
+ // Get all videos
+ // TODO: This could be improved, but this is the quickest way to get
+ // providers working.
+ Map<String, String> videos = mVideoProvider.query(mLevel);
+ if (videos.size() > 0) {
+ StringBuilder sb = new StringBuilder("{ \"level\": \"" + mLevel + "\"");
+ sb.append(", \"videos\": [");
+ boolean first = true;
+ for (String value : videos.values()) {
+ if (!first) {
+ sb.append(", ");
+ }
+ sb.append(value);
+ first = false;
+ }
+ sb.append("] }");
+ result = sb.toString();
+ }
+
+ } else {
+ // Get single video
+ result = mVideoProvider.get(mLevel, mVideoId);
+ }
+
+ if (result == null) {
+ // 404
+ setStatus(Status.CLIENT_ERROR_NOT_FOUND);
+ return null;
+ }
+
+ return new StringRepresentation(result);
+
+ } catch (IOException e) {
+ LOG.error("IOException fetch video: " + e.getMessage(), e);
+ setStatus(Status.SERVER_ERROR_INTERNAL);
+ return null;
+ }
+ }
+}