diff options
4 files changed, 73 insertions, 20 deletions
diff --git a/src/main/java/com/p4square/grow/ccb/CCBProgressReporter.java b/src/main/java/com/p4square/grow/ccb/CCBProgressReporter.java index 6eb9c15..c352fc7 100644 --- a/src/main/java/com/p4square/grow/ccb/CCBProgressReporter.java +++ b/src/main/java/com/p4square/grow/ccb/CCBProgressReporter.java @@ -57,7 +57,7 @@ public class CCBProgressReporter implements ProgressReporter { if (currentLevel != null) { if (Score.numericScore(chapter) <= Score.numericScore(currentLevel.getSelection().getLabel())) { - LOG.info("Not updating level for " + user.getIdentifier() + LOG.debug("Not updating level for " + user.getIdentifier() + " because current level (" + currentLevel.getSelection().getLabel() + ") is greater than new level (" + chapter + ")"); return; diff --git a/src/main/java/com/p4square/grow/frontend/GrowFrontend.java b/src/main/java/com/p4square/grow/frontend/GrowFrontend.java index b5f62fb..ebaa8df 100644 --- a/src/main/java/com/p4square/grow/frontend/GrowFrontend.java +++ b/src/main/java/com/p4square/grow/frontend/GrowFrontend.java @@ -7,6 +7,8 @@ package com.p4square.grow.frontend; import java.io.File; import java.io.IOException; import java.lang.reflect.Constructor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import freemarker.template.Template; @@ -51,6 +53,8 @@ public class GrowFrontend extends FMFacade { private IntegrationDriver mIntegrationFactory; + private final ExecutorService mThreadPool; + public GrowFrontend() { this(new Config(), new MetricRegistry()); } @@ -58,6 +62,7 @@ public class GrowFrontend extends FMFacade { public GrowFrontend(Config config, MetricRegistry metricRegistry) { mConfig = config; mMetricRegistry = metricRegistry; + mThreadPool = Executors.newFixedThreadPool(mConfig.getInt("threadPoolSize", 10)); } public Config getConfig() { @@ -68,6 +73,10 @@ public class GrowFrontend extends FMFacade { return mMetricRegistry; } + public ExecutorService getThreadPool() { + return mThreadPool; + } + @Override public synchronized void start() throws Exception { Template errorTemplate = getTemplate("templates/error.ftl"); diff --git a/src/main/java/com/p4square/grow/frontend/TrainingPageResource.java b/src/main/java/com/p4square/grow/frontend/TrainingPageResource.java index a1e7789..108c7a7 100644 --- a/src/main/java/com/p4square/grow/frontend/TrainingPageResource.java +++ b/src/main/java/com/p4square/grow/frontend/TrainingPageResource.java @@ -4,24 +4,22 @@ package com.p4square.grow.frontend; -import java.util.ArrayList; +import java.io.IOException; import java.util.Collections; import java.util.Comparator; -import java.util.HashMap; +import java.util.Date; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.ExecutorService; import freemarker.template.Template; -import org.restlet.data.CookieSetting; -import org.restlet.data.Form; import org.restlet.data.MediaType; import org.restlet.data.Status; import org.restlet.ext.freemarker.TemplateRepresentation; import org.restlet.representation.Representation; import org.restlet.representation.StringRepresentation; -import org.restlet.resource.ServerResource; import org.apache.log4j.Logger; @@ -36,6 +34,7 @@ import com.p4square.grow.model.VideoRecord; import com.p4square.grow.model.Playlist; import com.p4square.grow.provider.TrainingRecordProvider; import com.p4square.grow.provider.Provider; +import org.restlet.security.User; /** * TrainingPageResource handles rendering the training page. @@ -49,26 +48,25 @@ public class TrainingPageResource extends FreeMarkerPageResource { private static final Logger LOG = Logger.getLogger(TrainingPageResource.class); private static final String[] CHAPTERS = { "introduction", "seeker", "believer", "disciple", "teacher", "leader" }; - private static final Comparator<Map<String, Object>> VIDEO_COMPARATOR = new Comparator<Map<String, Object>>() { - @Override - public int compare(Map<String, Object> left, Map<String, Object> right) { - String leftNumberStr = (String) left.get("number"); - String rightNumberStr = (String) right.get("number"); - - if (leftNumberStr == null || rightNumberStr == null) { - return -1; - } - - double leftNumber = Double.valueOf(leftNumberStr); - double rightNumber = Double.valueOf(rightNumberStr); + private static final Comparator<Map<String, Object>> VIDEO_COMPARATOR = (left, right) -> { + String leftNumberStr = (String) left.get("number"); + String rightNumberStr = (String) right.get("number"); - return Double.compare(leftNumber, rightNumber); + if (leftNumberStr == null || rightNumberStr == null) { + return -1; } + + double leftNumber = Double.valueOf(leftNumberStr); + double rightNumber = Double.valueOf(rightNumberStr); + + return Double.compare(leftNumber, rightNumber); }; private Config mConfig; private Template mTrainingTemplate; private JsonRequestClient mJsonClient; + private ExecutorService mThreadPool; + private ProgressReporter mProgressReporter; private Provider<String, TrainingRecord> mTrainingRecordProvider; private FeedData mFeedData; @@ -90,12 +88,14 @@ public class TrainingPageResource extends FreeMarkerPageResource { } mJsonClient = new JsonRequestClient(getContext().getClientDispatcher()); - mTrainingRecordProvider = new TrainingRecordProvider<String>(new JsonRequestProvider<TrainingRecord>(getContext().getClientDispatcher(), TrainingRecord.class)) { + mTrainingRecordProvider = new TrainingRecordProvider<String>(new JsonRequestProvider<>(getContext().getClientDispatcher(), TrainingRecord.class)) { @Override public String makeKey(String userid) { return getBackendEndpoint() + "/accounts/" + userid + "/training"; } }; + mThreadPool = growFrontend.getThreadPool(); + mProgressReporter = growFrontend.getThirdPartyIntegrationFactory().getProgressReporter(); mFeedData = new FeedData(getContext(), mConfig); @@ -125,6 +125,7 @@ public class TrainingPageResource extends FreeMarkerPageResource { // to skip ahead. boolean allowUserToSkip = mConfig.getBoolean("allowUserToSkip", false) || getQueryValue("magicskip") != null; String defaultChapter = null; + String highestCompletedChapter = null; boolean userTriedToSkip = false; int overallProgress = 0; @@ -152,6 +153,7 @@ public class TrainingPageResource extends FreeMarkerPageResource { allowedChapters.put(chapterId, allowed); if (completed) { + highestCompletedChapter = chapterId; overallProgress++; } } @@ -227,6 +229,27 @@ public class TrainingPageResource extends FreeMarkerPageResource { root.put("feeddata", mFeedData); } + // Updated the integration database with the last completed chapter, + // just in case this failed previously. + if (highestCompletedChapter != null) { + try { + final User user = getRequest().getClientInfo().getUser(); + // Get the date of the highest completed chapter. + final Date completionDate = playlist.getChaptersMap().get(highestCompletedChapter).getCompletionDate(); + final String completedChapter = highestCompletedChapter; + mThreadPool.execute(() -> { + try { + mProgressReporter.reportChapterComplete(user, completedChapter, completionDate); + } catch (IOException e) { + LOG.error("Failed to sync progress", e); + } + }); + } catch (Throwable e) { + // Don't let any failures here fail the page load. + LOG.error("Unexpected throwable", e); + } + } + return new TemplateRepresentation(mTrainingTemplate, root, MediaType.TEXT_HTML); } catch (Exception e) { diff --git a/src/main/java/com/p4square/grow/model/Chapter.java b/src/main/java/com/p4square/grow/model/Chapter.java index 3a08e4c..ac27de6 100644 --- a/src/main/java/com/p4square/grow/model/Chapter.java +++ b/src/main/java/com/p4square/grow/model/Chapter.java @@ -4,6 +4,7 @@ package com.p4square.grow.model; +import java.util.Date; import java.util.HashMap; import java.util.Map; @@ -98,6 +99,26 @@ public class Chapter implements Cloneable { } /** + * @return the completion date for the chapter, or null if it has not been completed. + */ + @JsonIgnore + public Date getCompletionDate() { + Date latest = new Date(0); + for (VideoRecord video : mVideos.values()) { + if (video.getRequired() && !video.getComplete()) { + // Hey, this chapter isn't complete! + return null; + } + + Date completionDate = video.getCompletionDate(); + if (completionDate.after(latest)) { + latest = completionDate; + } + } + return latest; + } + + /** * Deeply clone a chapter. * * @return a new Chapter object identical but independent of this one. |