/* * Copyright 2013-2014 Richard M. Hightower * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * __________ _____ __ .__ * \______ \ ____ ____ ____ /\ / \ _____ | | _|__| ____ ____ * | | _// _ \ / _ \ / \ \/ / \ / \\__ \ | |/ / |/ \ / ___\ * | | ( <_> | <_> ) | \ /\ / Y \/ __ \| <| | | \/ /_/ > * |______ /\____/ \____/|___| / \/ \____|__ (____ /__|_ \__|___| /\___ / * \/ \/ \/ \/ \/ \//_____/ * ____. ___________ _____ ______________.___. * | |____ ___ _______ \_ _____/ / _ \ / _____/\__ | | * | \__ \\ \/ /\__ \ | __)_ / /_\ \ \_____ \ / | | * /\__| |/ __ \\ / / __ \_ | \/ | \/ \ \____ | * \________(____ /\_/ (____ / /_______ /\____|__ /_______ / / ______| * \/ \/ \/ \/ \/ \/ */ package com.examples.model.test.movies.wathcer; import com.examples.model.test.movies.entitlement.Rights; import com.examples.model.test.movies.likeable.Like; import com.examples.model.test.movies.likeable.LikeFactor; import com.examples.model.test.movies.likeable.VendorCategory; import com.examples.model.test.movies.likeable.LikeabilityUpdate; import com.examples.model.test.movies.media.Movie; import com.examples.model.test.time.TimeZoneHolder; import org.boon.Lists; import java.util.*; /** * Stores users preferences. * Her likes and dislikes. * Also stores the last media watched. * The recent movies watched, and deice information. * */ public class Watcher { /** Watcher name. */ private final String username; /** Version number of this object. */ private long version; /** VendorCategory scores. */ private final Map<VendorCategory, LikeFactor> tags; /** Actors scores. */ private final Map<String, LikeFactor> actors; /** People scores. */ private final Map<String, LikeFactor> people; /** Last device used. */ private ScreenDevice lastScreenDeviceUsed = ScreenDevice.UNKNOWN; /** Last connection speed used. */ private DeviceConnectionSpeed lastConnectionSpeed = DeviceConnectionSpeed.UNKNOWN; /** Last media watched position. */ private int lastVideoPosition; /** Last media watched. */ private String lastVideo; /** Set of entitlements. */ private Rights rights; /** Set of movies that the user watched. */ private Set<String> watchedVideos = new LinkedHashSet<>(); /** * Timezone. */ private TimeZoneHolder timeZone = TimeZoneHolder.PST; /** * Last media watched. * @return */ public String lastVideo() { return lastVideo; } /** * last media watched. * @param lastVideo * @return */ public Watcher lastVideo(String lastVideo) { this.lastVideo = lastVideo; return this; } /** * Last media position. * @return */ public int lastVideoPosition() { return lastVideoPosition; } /** * Last media position. * @param lastVideoPosition * @return */ public Watcher lastVideoPosition(int lastVideoPosition) { this.lastVideoPosition = lastVideoPosition; return this; } /** * New Watcher * @param username */ public Watcher(final String username) { this.username = username; tags = new HashMap<>( ); actors = new HashMap<>( ); people = new HashMap<>( ); watchedVideos = new HashSet<>(); } /** * New Watcher. * @param username * @return */ public static Watcher user ( final String username ) { return new Watcher( username ); } /** New users with a given version number. * * @param username username * @param version version * @return */ public static Watcher user ( final String username, long version ) { Watcher watcher = user(username); watcher.version = version; return watcher; } /** For from List. * Converts a user into a list. * @param username username * @param version version * @param lastVideo lastVideo watched * @param lastVideoPosition last position of last media watched * @param watchedVideos list of last watched movies * @param tags category tags for movies * @param actors actors we have scored * @param people people we have scored */ private Watcher(final String username, long version, String lastVideo, int lastVideoPosition, Set<String> watchedVideos, Map<VendorCategory, LikeFactor> tags, Map<String, LikeFactor> actors, Map<String, LikeFactor> people) { this.username = username; this.version = version; this.watchedVideos = watchedVideos; this.tags = tags; this.actors = actors; this.people = people; this.lastVideo = lastVideo; this.lastVideoPosition = lastVideoPosition; } /* For JSON output. */ List<Object> serializeAs() { return Lists.list(username, version, lastVideo, lastVideoPosition, watchedVideos, tags, actors, people); } public LikeFactor playerScore( String id ) { LikeFactor likeFactor = actors.get( id ); if ( likeFactor == null ) { likeFactor = new LikeFactor(); actors.put(id, likeFactor); } return likeFactor; } public LikeFactor personScore( String personId ) { LikeFactor likeFactor = people.get( personId ); if ( likeFactor == null ) { likeFactor = new LikeFactor(); people.put(personId, likeFactor); } return likeFactor; } /** Add a person score. * A person is someone (announcer, TV personality) who was in the media who we want to score. * @param personId person id * @param value value * @return */ public boolean addPersonScore(final String personId, final int value) { LikeFactor likeFactor = people.get( personId ); /*LikeFactor already exists. */ if ( likeFactor != null ) { return false; } personScore(personId).setScore(value); return true; } /** * LikeFactor a category. * * @param category category to score * @return new score */ public LikeFactor categoryScore( VendorCategory category ) { LikeFactor likeFactor = tags.get( category ); if ( likeFactor == null ) { likeFactor = new LikeFactor(); tags.put(category, likeFactor); } return likeFactor; } /** Update user's preferences. * * @param scoreUpdate scoreUpdate * @param movie movie * @return Watcher self */ public Watcher updateScore(LikeabilityUpdate scoreUpdate, Movie movie) { /* Remove the first movie added if the movie watch count is above the amount we can hold in memory. */ if ( watchedVideos.size() > 10 ) { Iterator<String> iterator = watchedVideos.iterator(); iterator.next(); iterator.remove(); } watchedVideos.add ( scoreUpdate.video() ); this.lastVideo = scoreUpdate.video(); this.lastVideoPosition = scoreUpdate.lastVideoPosition(); Like like = scoreUpdate.getLike(); categoryScore( movie.category() ).changeBy( 5 ); for ( String player : movie.players () ) { changePlayerScoreBy(like, player ); } for ( String person : movie.people () ) { changePersonScoreBy(like, person ); } for ( VendorCategory category : movie.tags() ) { changeCategoryScore (like, category ); } version ++; return this; } /** * Change a person score. * @param like like * @param person person * @return self */ private Watcher changePersonScoreBy( Like like, String person ) { LikeFactor likeFactor = personScore( person ); likeFactor.changeBy ( 10 ); if (likeFactor.getScore () == 0) { people.remove(person); } version ++; return this; } /** * Change a category score * @param like like * @param category category to score * @return self */ private Watcher changeCategoryScore( Like like, VendorCategory category ) { LikeFactor likeFactor = categoryScore ( category ); likeFactor.changeBy ( 10 ); if (likeFactor.getScore () == 0) { tags.remove(category); } version ++; return this; } /** * Change a player score * @param like like * @param player player * @return self */ private Watcher changePlayerScoreBy( Like like, String player ) { LikeFactor likeFactor = playerScore ( player ); likeFactor.changeBy ( 10 ); if (likeFactor.getScore () == 0) { actors.remove(player); } version ++; return this; } /** * lookup likeFactor. * @param likeFactor * @return */ private int score( LikeFactor likeFactor) { if ( likeFactor == null ) { return 0; } return likeFactor.getScore(); } /** Get a person score. */ public int getPersonScore(String person) { LikeFactor likeFactor = people.get( person ); return score(likeFactor); } /** Get a category score. * * @param category category to score * @return score */ public int getCategoryScore( VendorCategory category ) { LikeFactor likeFactor = tags.get( category ); return score (likeFactor); } /** * Player score * @param id of player * @return score */ public int getPlayerScore( String id ) { LikeFactor likeFactor = actors.get( id ); return score (likeFactor); } /** * Version to track updates of object. * @return version */ public long version() { return version; } @Override public String toString() { return "Watcher{" + "username='" + username + '\'' + ", tags=" + tags + ", actors=" + actors + ", people=" + people + ", watchedVideos=" + watchedVideos + '}'; } @Override public int hashCode() { int result = username != null ? username.hashCode() : 0; result = 31 * result + ( int ) ( version ^ ( version >>> 32 ) ); result = 31 * result + ( tags != null ? tags.hashCode() : 0 ); result = 31 * result + ( actors != null ? actors.hashCode() : 0 ); result = 31 * result + ( people != null ? people.hashCode() : 0 ); result = 31 * result + ( watchedVideos != null ? watchedVideos.hashCode() : 0 ); return result; } @Override public boolean equals( Object o ) { if ( this == o ) return true; if ( o == null || getClass() != o.getClass() ) return false; Watcher watcher = (Watcher) o; if ( version != watcher.version ) return false; if ( tags != null ? !tags.equals( watcher.tags) : watcher.tags != null ) return false; if ( people != null ? !people.equals( watcher.people) : watcher.people != null ) return false; if ( actors != null ? !actors.equals( watcher.actors) : watcher.actors != null ) return false; if ( username != null ? !username.equals( watcher.username ) : watcher.username != null ) return false; if ( watchedVideos != null ? !watchedVideos.equals( watcher.watchedVideos ) : watcher.watchedVideos != null ) return false; return true; } /** * Bump the version. * @return */ public long bumpVersion() { version++; return version; } /** * Add a new player score. * @param id id of player * @param value new value * @return true if able to */ public boolean addPlayerScore(String id, int value) { LikeFactor likeFactor = actors.get( id ); /*LikeFactor already exists. */ if ( likeFactor != null ) { return false; } playerScore(id).setScore(value); return true; } /** * * @param category * @param value * @return */ public boolean addCategoryScore(VendorCategory category, int value) { LikeFactor likeFactor = tags.get( category ); /*LikeFactor already exists. */ if ( likeFactor != null ) { return false; } categoryScore(category).setScore(value); return true; } /** * * @param id * @return */ public boolean removePersonScore(String id) { this.people.remove(id); return true; } /** * * @param id * @return */ public boolean removePlayerScore(String id) { this.actors.remove(id); return true; } /** * * @param category * @return */ public boolean removeCategoryScore(VendorCategory category) { this.tags.remove(category); return true; } /** * * @param id * @param current * @param value * @return */ public boolean incrementPersonScore(String id, int current, int value) { if (current== Short.MIN_VALUE) { personScore(id).changeBy(value); return true; } else { return personScore(id).changeBy(current, value); } } /** * * @param id * @param current * @param value * @return */ public boolean incrementPlayerScore(String id, int current, int value) { if (current== Short.MIN_VALUE) { playerScore(id).changeBy(value); return true; } else { return playerScore(id).changeBy(current, value); } } /** * * @param category * @param current * @param value * @return */ public boolean incrementCategoryScore(VendorCategory category, int current, int value) { if (current== Short.MIN_VALUE) { categoryScore(category).changeBy(value); return true; } else { return categoryScore(category).changeBy(current, value); } } /** * * @param personId * @return */ public boolean addDefaultPersonScore(String personId) { LikeFactor likeFactor = people.get( personId ); /*LikeFactor already exists. */ if ( likeFactor != null ) { return false; } personScore(personId).setScore(20); return true; } /** * * @param id * @return */ public boolean addDefaultPlayerScore(String id) { LikeFactor likeFactor = actors.get( id ); /*LikeFactor already exists. */ if ( likeFactor != null ) { return false; } playerScore(id).setScore( 20 ); return true; } /** * * @param category * @return */ public boolean addDefaultCategoryScore(VendorCategory category) { LikeFactor likeFactor = tags.get( category ); /*LikeFactor already exists. */ if ( likeFactor != null ) { return false; } categoryScore(category).setScore(20); return true; } /** * * @return */ public DeviceConnectionSpeed connectionSpeed() { return lastConnectionSpeed; } /** * * @return */ public ScreenDevice device() { return lastScreenDeviceUsed; } /** * * @param lastConnectionSpeed * @return */ public Watcher setLastConnectionSpeed(DeviceConnectionSpeed lastConnectionSpeed) { if (lastConnectionSpeed == DeviceConnectionSpeed.UNKNOWN) { return this; } this.lastConnectionSpeed = lastConnectionSpeed; return this; } /** * * @param lastScreenDeviceUsed * @return */ public Watcher setLastScreenDeviceUsed(ScreenDevice lastScreenDeviceUsed) { if (lastScreenDeviceUsed == ScreenDevice.UNKNOWN) { return this; } this.lastScreenDeviceUsed = lastScreenDeviceUsed; return this; } public Rights getRights() { return rights; } public void setRights(Rights rights) { this.rights = rights; } public Watcher setTimeZone(TimeZoneHolder holder) { this.timeZone = holder; return this; } public Set<String> watchedVideos() { return watchedVideos; } public String name() { return username; } public TimeZoneHolder getTimeZone() { return timeZone; } }