diff options
Diffstat (limited to 'src/com/p4square/grow/model')
-rw-r--r-- | src/com/p4square/grow/model/Chapter.java | 79 | ||||
-rw-r--r-- | src/com/p4square/grow/model/Playlist.java | 171 | ||||
-rw-r--r-- | src/com/p4square/grow/model/Question.java | 6 | ||||
-rw-r--r-- | src/com/p4square/grow/model/TrainingRecord.java | 49 | ||||
-rw-r--r-- | src/com/p4square/grow/model/VideoRecord.java | 85 |
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; + } +} |