summaryrefslogtreecommitdiff
path: root/src/com/p4square/grow/model
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/p4square/grow/model')
-rw-r--r--src/com/p4square/grow/model/Chapter.java79
-rw-r--r--src/com/p4square/grow/model/Playlist.java171
-rw-r--r--src/com/p4square/grow/model/Question.java6
-rw-r--r--src/com/p4square/grow/model/TrainingRecord.java49
-rw-r--r--src/com/p4square/grow/model/VideoRecord.java85
5 files changed, 387 insertions, 3 deletions
diff --git a/src/com/p4square/grow/model/Chapter.java b/src/com/p4square/grow/model/Chapter.java
new file mode 100644
index 0000000..4d59983
--- /dev/null
+++ b/src/com/p4square/grow/model/Chapter.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2013 Jesse Morgan
+ */
+
+package com.p4square.grow.model;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+/**
+ * Chapter is a list of VideoRecords in a Playlist.
+ *
+ * @author Jesse Morgan <jesse@jesterpm.net>
+ */
+public class Chapter implements Cloneable {
+ private Map<String, VideoRecord> mVideos;
+
+ public Chapter() {
+ mVideos = new HashMap<String, VideoRecord>();
+ }
+
+ /**
+ * @return The VideoRecord for videoid or null if videoid is not in the chapter.
+ */
+ public VideoRecord getVideoRecord(String videoid) {
+ return mVideos.get(videoid);
+ }
+
+ /**
+ * @return A map of video ids to VideoRecords.
+ */
+ @JsonAnyGetter
+ public Map<String, VideoRecord> getVideos() {
+ return mVideos;
+ }
+
+ /**
+ * Set the VideoRecord for a video id.
+ * @param videoId the video id.
+ * @param video the VideoRecord.
+ */
+ @JsonAnySetter
+ public void setVideoRecord(String videoId, VideoRecord video) {
+ mVideos.put(videoId, video);
+ }
+
+ /**
+ * @return true if every required video has been completed.
+ */
+ @JsonIgnore
+ public boolean isComplete() {
+ boolean complete = true;
+
+ for (VideoRecord r : mVideos.values()) {
+ if (r.getRequired() && !r.getComplete()) {
+ return false;
+ }
+ }
+
+ return complete;
+ }
+
+ /**
+ * Deeply clone a chapter.
+ *
+ * @return a new Chapter object identical but independent of this one.
+ */
+ public Chapter clone() throws CloneNotSupportedException {
+ Chapter c = new Chapter();
+ for (Map.Entry<String, VideoRecord> videoEntry : mVideos.entrySet()) {
+ c.setVideoRecord(videoEntry.getKey(), videoEntry.getValue().clone());
+ }
+ return c;
+ }
+}
diff --git a/src/com/p4square/grow/model/Playlist.java b/src/com/p4square/grow/model/Playlist.java
new file mode 100644
index 0000000..79ce68e
--- /dev/null
+++ b/src/com/p4square/grow/model/Playlist.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2013 Jesse Morgan
+ */
+
+package com.p4square.grow.model;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+/**
+ * Representation of a user's playlist.
+ *
+ * @author Jesse Morgan <jesse@jesterpm.net>
+ */
+public class Playlist {
+ /**
+ * Map of Chapter ID to map of Video ID to VideoRecord.
+ */
+ private Map<String, Chapter> mPlaylist;
+
+ private Date mLastUpdated;
+
+ /**
+ * Construct an empty playlist.
+ */
+ public Playlist() {
+ mPlaylist = new HashMap<String, Chapter>();
+ mLastUpdated = new Date(0); // Default to a prehistoric date if we don't have one.
+ }
+
+ /**
+ * Find the VideoRecord for a video id.
+ */
+ public VideoRecord find(String videoId) {
+ for (Chapter chapter : mPlaylist.values()) {
+ VideoRecord r = chapter.getVideoRecord(videoId);
+
+ if (r != null) {
+ return r;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * @return The last modified date of the source playlist.
+ */
+ public Date getLastUpdated() {
+ return mLastUpdated;
+ }
+
+ /**
+ * Set the last updated date.
+ * @param date the new last updated date.
+ */
+ public void setLastUpdated(Date date) {
+ mLastUpdated = date;
+ }
+
+ /**
+ * Add a video to the playlist.
+ */
+ public VideoRecord add(String chapterId, String videoId) {
+ Chapter chapter = mPlaylist.get(chapterId);
+
+ if (chapter == null) {
+ chapter = new Chapter();
+ mPlaylist.put(chapterId, chapter);
+ }
+
+ VideoRecord r = new VideoRecord();
+ chapter.setVideoRecord(videoId, r);
+ return r;
+ }
+
+ /**
+ * Add a Chapter to the Playlist.
+ * @param chapterId The name of the chapter.
+ * @param chapter The Chapter object to add.
+ */
+ @JsonAnySetter
+ public void addChapter(String chapterId, Chapter chapter) {
+ mPlaylist.put(chapterId, chapter);
+ }
+
+ /**
+ * @return a map of chapter id to chapter.
+ */
+ @JsonAnyGetter
+ public Map<String, Chapter> getChaptersMap() {
+ return mPlaylist;
+ }
+
+ /**
+ * @return The last chapter to be completed.
+ */
+ @JsonIgnore
+ public Map<String, Boolean> getChapterStatuses() {
+ Map<String, Boolean> completed = new HashMap<String, Boolean>();
+
+ for (Map.Entry<String, Chapter> entry : mPlaylist.entrySet()) {
+ completed.put(entry.getKey(), entry.getValue().isComplete());
+ }
+
+ return completed;
+ }
+
+ /**
+ * @return true if all required videos in the chapter have been watched.
+ */
+ public boolean isChapterComplete(String chapterId) {
+ Chapter chapter = mPlaylist.get(chapterId);
+ if (chapter != null) {
+ return chapter.isComplete();
+ }
+
+ return false;
+ }
+
+ /**
+ * Merge a playlist into this playlist.
+ *
+ * Merge is accomplished by adding all missing Chapters and VideoRecords to
+ * this playlist.
+ */
+ public void merge(Playlist source) {
+ if (source.getLastUpdated().before(mLastUpdated)) {
+ // Already up to date.
+ return;
+ }
+
+ for (Map.Entry<String, Chapter> entry : source.getChaptersMap().entrySet()) {
+ String chapterName = entry.getKey();
+ Chapter theirChapter = entry.getValue();
+ Chapter myChapter = mPlaylist.get(entry.getKey());
+
+ if (myChapter == null) {
+ // Add entire chapter
+ try {
+ mPlaylist.put(chapterName, theirChapter.clone());
+ } catch (CloneNotSupportedException e) {
+ throw new RuntimeException(e); // Unexpected...
+ }
+
+ } else {
+ // Check chapter for missing videos
+ for (Map.Entry<String, VideoRecord> videoEntry : theirChapter.getVideos().entrySet()) {
+ String videoId = videoEntry.getKey();
+ VideoRecord myVideo = myChapter.getVideoRecord(videoId);
+
+ if (myVideo == null) {
+ try {
+ myVideo = videoEntry.getValue().clone();
+ myChapter.setVideoRecord(videoId, myVideo);
+ } catch (CloneNotSupportedException e) {
+ throw new RuntimeException(e); // Unexpected...
+ }
+ }
+ }
+ }
+ }
+
+ mLastUpdated = source.getLastUpdated();
+ }
+}
diff --git a/src/com/p4square/grow/model/Question.java b/src/com/p4square/grow/model/Question.java
index 37deffa..f4b9458 100644
--- a/src/com/p4square/grow/model/Question.java
+++ b/src/com/p4square/grow/model/Question.java
@@ -7,9 +7,9 @@ package com.p4square.grow.model;
import java.util.HashMap;
import java.util.Map;
-import org.codehaus.jackson.annotate.JsonSubTypes;
-import org.codehaus.jackson.annotate.JsonSubTypes.Type;
-import org.codehaus.jackson.annotate.JsonTypeInfo;
+import com.fasterxml.jackson.annotation.JsonSubTypes;
+import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
/**
* Model of an assessment question.
diff --git a/src/com/p4square/grow/model/TrainingRecord.java b/src/com/p4square/grow/model/TrainingRecord.java
new file mode 100644
index 0000000..bc3ffa9
--- /dev/null
+++ b/src/com/p4square/grow/model/TrainingRecord.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2013 Jesse Morgan
+ */
+
+package com.p4square.grow.model;
+
+/**
+ * Representation of a user's training record.
+ *
+ * @author Jesse Morgan <jesse@jesterpm.net>
+ */
+public class TrainingRecord {
+ private String mLastVideo;
+ private Playlist mPlaylist;
+
+ public TrainingRecord() {
+ mPlaylist = new Playlist();
+ }
+
+ /**
+ * @return Video id of the last video watched.
+ */
+ public String getLastVideo() {
+ return mLastVideo;
+ }
+
+ /**
+ * Set the video id for the last video watched.
+ * @param video The new video id.
+ */
+ public void setLastVideo(String video) {
+ mLastVideo = video;
+ }
+
+ /**
+ * @return the user's Playlist.
+ */
+ public Playlist getPlaylist() {
+ return mPlaylist;
+ }
+
+ /**
+ * Set the user's playlist.
+ * @param playlist The new playlist.
+ */
+ public void setPlaylist(Playlist playlist) {
+ mPlaylist = playlist;
+ }
+}
diff --git a/src/com/p4square/grow/model/VideoRecord.java b/src/com/p4square/grow/model/VideoRecord.java
new file mode 100644
index 0000000..ec99d0d
--- /dev/null
+++ b/src/com/p4square/grow/model/VideoRecord.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2013 Jesse Morgan
+ */
+
+package com.p4square.grow.model;
+
+import java.util.Date;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+/**
+ * Simple bean containing video completion data.
+ *
+ * @author Jesse Morgan <jesse@jesterpm.net>
+ */
+public class VideoRecord implements Cloneable {
+ private Boolean mComplete;
+ private Boolean mRequired;
+ private Date mCompletionDate;
+
+ public VideoRecord() {
+ mComplete = null;
+ mRequired = null;
+ mCompletionDate = null;
+ }
+
+ public boolean getComplete() {
+ if (mComplete == null) {
+ return false;
+ }
+ return mComplete;
+ }
+
+ public void setComplete(boolean complete) {
+ mComplete = complete;
+ }
+
+ @JsonIgnore
+ public boolean isCompleteSet() {
+ return mComplete != null;
+ }
+
+ public boolean getRequired() {
+ if (mRequired == null) {
+ return true;
+ }
+ return mRequired;
+ }
+
+ public void setRequired(boolean complete) {
+ mRequired = complete;
+ }
+
+ @JsonIgnore
+ public boolean isRequiredSet() {
+ return mRequired != null;
+ }
+
+ public Date getCompletionDate() {
+ return mCompletionDate;
+ }
+
+ public void setCompletionDate(Date date) {
+ mCompletionDate = date;
+ }
+
+ /**
+ * Convenience method to mark a video complete.
+ */
+ public void complete() {
+ mComplete = true;
+ mCompletionDate = new Date();
+ }
+
+ /**
+ * @return an identical clone of this record.
+ */
+ public VideoRecord clone() throws CloneNotSupportedException {
+ VideoRecord r = (VideoRecord) super.clone();
+ r.mComplete = mComplete;
+ r.mRequired = mRequired;
+ r.mCompletionDate = mCompletionDate;
+ return r;
+ }
+}