1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.tv.recommendation; 18 19 import java.util.concurrent.TimeUnit; 20 21 public class RecentChannelEvaluator extends Recommender.Evaluator { 22 private static final long WATCH_DURATION_MS_LOWER_BOUND = TimeUnit.MINUTES.toMillis(3); 23 private static final long WATCH_DURATION_MS_UPPER_BOUND = TimeUnit.MINUTES.toMillis(7); 24 25 private static final double MAX_SCORE_FOR_LOWER_BOUND = 0.1; 26 27 private long mLastWatchLogUpdateTimeMs; 28 29 public RecentChannelEvaluator() { 30 mLastWatchLogUpdateTimeMs = System.currentTimeMillis(); 31 } 32 33 @Override 34 public void onNewWatchLog(ChannelRecord channelRecord) { 35 mLastWatchLogUpdateTimeMs = System.currentTimeMillis(); 36 } 37 38 @Override 39 public double evaluateChannel(long channelId) { 40 ChannelRecord cr = getRecommender().getChannelRecord(channelId); 41 if (cr == null) { 42 return NOT_RECOMMENDED; 43 } 44 WatchedProgram[] watchHistory = cr.getWatchHistory(); 45 double maxScore = 0.0; 46 for (int i = watchHistory.length - 1; i >= 0; --i) { 47 double recentWatchScore = 48 (double) watchHistory[i].getWatchEndTimeMs() / mLastWatchLogUpdateTimeMs; 49 double watchDurationScore; 50 double watchDuration = watchHistory[i].getWatchedDurationMs(); 51 if (watchDuration < WATCH_DURATION_MS_LOWER_BOUND) { 52 watchDurationScore = MAX_SCORE_FOR_LOWER_BOUND; 53 } else if (watchDuration < WATCH_DURATION_MS_UPPER_BOUND) { 54 watchDurationScore = (watchDuration - WATCH_DURATION_MS_LOWER_BOUND) 55 / (WATCH_DURATION_MS_UPPER_BOUND - WATCH_DURATION_MS_LOWER_BOUND) 56 * (1 - MAX_SCORE_FOR_LOWER_BOUND) + MAX_SCORE_FOR_LOWER_BOUND; 57 } else { 58 watchDurationScore = 1.0; 59 } 60 maxScore = Math.max(maxScore, watchDurationScore * recentWatchScore); 61 } 62 return (maxScore > 0.0) ? maxScore : NOT_RECOMMENDED; 63 } 64 }