1816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko/*
2816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Copyright (C) 2015 The Android Open Source Project
3816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko *
4816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Licensed under the Apache License, Version 2.0 (the "License");
5816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * you may not use this file except in compliance with the License.
6816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * You may obtain a copy of the License at
7816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko *
8816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko *      http://www.apache.org/licenses/LICENSE-2.0
9816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko *
10816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Unless required by applicable law or agreed to in writing, software
11816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * distributed under the License is distributed on an "AS IS" BASIS,
12816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * See the License for the specific language governing permissions and
14816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * limitations under the License.
15816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */
16816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
17816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkopackage com.android.tv.recommendation;
18816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
196ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport static org.junit.Assert.assertEquals;
206ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko
2165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.support.test.filters.SmallTest;
22816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.test.MoreAsserts;
23816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
24816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport com.android.tv.data.Program;
25816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport com.android.tv.recommendation.RoutineWatchEvaluator.ProgramTime;
26816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
276ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport org.junit.Test;
286ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko
292e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalkoimport java.util.Arrays;
30816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport java.util.Calendar;
31816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport java.util.List;
322e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalkoimport java.util.TreeSet;
33816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport java.util.concurrent.TimeUnit;
34816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
3507b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko@SmallTest
36816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkopublic class RoutineWatchEvaluatorTest extends EvaluatorTestCase<RoutineWatchEvaluator> {
372e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko    private static class ScoredItem implements Comparable<ScoredItem> {
382e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko        private final String mBase;
392e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko        private final String mText;
402e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko        private final double mScore;
412e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko
422e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko        private ScoredItem(String base, String text) {
432e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko            this.mBase = base;
442e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko            this.mText = text;
452e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko            this.mScore = RoutineWatchEvaluator.calculateTitleMatchScore(base, text);
462e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko        }
472e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko
482e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko        @Override
492e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko        public int compareTo(ScoredItem scoredItem) {
502e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko            return Double.compare(mScore, scoredItem.mScore);
512e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko        }
522e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko
532e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko        @Override
542e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko        public String toString() {
552e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko            return mBase + " scored with " + mText + " is " + mScore;
562e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko        }
572e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko    }
582e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko
592e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko    private static ScoredItem score(String t1, String t2) {
602e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko        return new ScoredItem(t1, t2);
612e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko    }
62816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
6307b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko    @Override
64816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public RoutineWatchEvaluator createEvaluator() {
65816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        return new RoutineWatchEvaluator();
66816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
67816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
686ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    @Test
69816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void testSplitTextToWords() {
70816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertSplitTextToWords("");
71816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertSplitTextToWords("Google", "Google");
72816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertSplitTextToWords("The Big Bang Theory", "The", "Big", "Bang", "Theory");
73816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertSplitTextToWords("Hello, world!", "Hello", "world");
74816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertSplitTextToWords("Adam's Rib", "Adam's", "Rib");
75816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertSplitTextToWords("G.I. Joe", "G.I", "Joe");
76816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertSplitTextToWords("A.I.", "A.I");
77816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
78816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
796ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    @Test
80816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void testCalculateMaximumMatchedWordSequenceLength() {
81816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertMaximumMatchedWordSequenceLength(0, "", "Google");
82816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertMaximumMatchedWordSequenceLength(2, "The Big Bang Theory", "Big Bang");
83816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertMaximumMatchedWordSequenceLength(2, "The Big Bang Theory", "Theory Of Big Bang");
84816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertMaximumMatchedWordSequenceLength(4, "The Big Bang Theory", "The Big Bang Theory");
85816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertMaximumMatchedWordSequenceLength(1, "Modern Family", "Family Guy");
86816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertMaximumMatchedWordSequenceLength(1, "The Simpsons", "The Walking Dead");
87816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertMaximumMatchedWordSequenceLength(3, "Game Of Thrones 1", "Game Of Thrones 6");
88816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertMaximumMatchedWordSequenceLength(0, "Dexter", "Friends");
89816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
90816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
916ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    @Test
922e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko    public void testCalculateTitleMatchScore_empty() {
936ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        assertEqualScores(0.0, RoutineWatchEvaluator.calculateTitleMatchScore("", ""));
946ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        assertEqualScores(0.0, RoutineWatchEvaluator.calculateTitleMatchScore("foo", ""));
956ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        assertEqualScores(0.0, RoutineWatchEvaluator.calculateTitleMatchScore("", "foo"));
962e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko    }
972e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko
986ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    @Test
992e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko    public void testCalculateTitleMatchScore_spaces() {
1006ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        assertEqualScores(0.0, RoutineWatchEvaluator.calculateTitleMatchScore(" ", " "));
1016ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        assertEqualScores(0.0, RoutineWatchEvaluator.calculateTitleMatchScore("foo", " "));
1026ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        assertEqualScores(0.0, RoutineWatchEvaluator.calculateTitleMatchScore(" ", "foo"));
1032e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko    }
1042e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko
1052e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko
1066ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    @Test
1072e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko    public void testCalculateTitleMatchScore_null() {
1086ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        assertEqualScores(0.0, RoutineWatchEvaluator.calculateTitleMatchScore(null, null));
1096ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        assertEqualScores(0.0, RoutineWatchEvaluator.calculateTitleMatchScore("foo", null));
1106ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        assertEqualScores(0.0, RoutineWatchEvaluator.calculateTitleMatchScore(null, "foo"));
1112e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko    }
1122e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko
1136ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    @Test
1142e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko    public void testCalculateTitleMatchScore_longerMatchIsBetter() {
1152e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko        String base = "foo bar baz";
1162e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko        assertInOrder(
1172e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko                score(base, ""),
1182e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko                score(base, "bar"),
1192e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko                score(base, "foo bar"),
1202e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko                score(base, "foo bar baz"));
1212e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko    }
1222e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko
1236ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    @Test
124816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void testProgramTime_createFromProgram() {
125816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        Calendar time = Calendar.getInstance();
126816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        int todayDayOfWeek = time.get(Calendar.DAY_OF_WEEK);
127816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // Value of DayOfWeek is between 1 and 7 (inclusive).
128816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        int tomorrowDayOfWeek = (todayDayOfWeek % 7) + 1;
129816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
130816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // Today 00:00 - 01:00.
131816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        ProgramTime programTimeToday0000_0100 = ProgramTime.createFromProgram(
132816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                createDummyProgram(todayAtHourMin(0, 0), TimeUnit.HOURS.toMillis(1)));
133816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertProgramTime(todayDayOfWeek, hourMinuteToSec(0, 0), hourMinuteToSec(1, 0),
134816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                programTimeToday0000_0100);
135816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
136816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // Today 23:30 - 24:30.
137816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        ProgramTime programTimeToday2330_2430 = ProgramTime.createFromProgram(
138816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                createDummyProgram(todayAtHourMin(23, 30), TimeUnit.HOURS.toMillis(1)));
139816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertProgramTime(todayDayOfWeek, hourMinuteToSec(23, 30), hourMinuteToSec(24, 30),
140816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                programTimeToday2330_2430);
141816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
142816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // Tomorrow 00:00 - 01:00.
143816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        ProgramTime programTimeTomorrow0000_0100 = ProgramTime.createFromProgram(
144816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                createDummyProgram(tomorrowAtHourMin(0, 0), TimeUnit.HOURS.toMillis(1)));
145816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertProgramTime(tomorrowDayOfWeek, hourMinuteToSec(0, 0), hourMinuteToSec(1, 0),
146816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                programTimeTomorrow0000_0100);
147816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
148816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // Tomorrow 23:30 - 24:30.
149816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        ProgramTime programTimeTomorrow2330_2430 = ProgramTime.createFromProgram(
150816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                createDummyProgram(tomorrowAtHourMin(23, 30), TimeUnit.HOURS.toMillis(1)));
151816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertProgramTime(tomorrowDayOfWeek, hourMinuteToSec(23, 30), hourMinuteToSec(24, 30),
152816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                programTimeTomorrow2330_2430);
153816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
154816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // Today 18:00 - Tomorrow 12:00.
155816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        ProgramTime programTimeToday1800_3600 = ProgramTime.createFromProgram(
156816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                createDummyProgram(todayAtHourMin(18, 0), TimeUnit.HOURS.toMillis(18)));
157816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // Maximum duration of ProgramTime is 12 hours.
158816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // So, this program looks like it ends at Tomorrow 06:00 (30:00).
159816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertProgramTime(todayDayOfWeek, hourMinuteToSec(18, 0), hourMinuteToSec(30, 0),
160816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                programTimeToday1800_3600);
161816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
162816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
1636ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    @Test
164816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void testCalculateOverlappedIntervalScore() {
165816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // Today 21:00 - 24:00.
166816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        ProgramTime programTimeToday2100_2400 = ProgramTime.createFromProgram(
167816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                createDummyProgram(todayAtHourMin(21, 0), TimeUnit.HOURS.toMillis(3)));
168816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // Today 22:00 - 01:00.
169816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        ProgramTime programTimeToday2200_0100 = ProgramTime.createFromProgram(
170816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                createDummyProgram(todayAtHourMin(22, 0), TimeUnit.HOURS.toMillis(3)));
171816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // Tomorrow 00:00 - 03:00.
172816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        ProgramTime programTimeTomorrow0000_0300 = ProgramTime.createFromProgram(
173816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                createDummyProgram(tomorrowAtHourMin(0, 0), TimeUnit.HOURS.toMillis(3)));
174816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // Tomorrow 20:00 - Tomorrow 23:00.
175816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        ProgramTime programTimeTomorrow2000_2300 = ProgramTime.createFromProgram(
176816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                createDummyProgram(tomorrowAtHourMin(20, 0), TimeUnit.HOURS.toMillis(3)));
177816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
178816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // Check intersection time and commutative law in all cases.
179816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        int oneHourInSec = hourMinuteToSec(1, 0);
1802e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko        assertOverlappedIntervalScore(2 * oneHourInSec, true, programTimeToday2100_2400,
1812e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko                programTimeToday2200_0100);
1822e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko        assertOverlappedIntervalScore(0, false, programTimeToday2100_2400,
1832e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko                programTimeTomorrow0000_0300);
1842e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko        assertOverlappedIntervalScore(2 * oneHourInSec, false, programTimeToday2100_2400,
1852e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko                programTimeTomorrow2000_2300);
1862e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko        assertOverlappedIntervalScore(oneHourInSec, true, programTimeToday2200_0100,
1872e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko                programTimeTomorrow0000_0300);
1882e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko        assertOverlappedIntervalScore(oneHourInSec, false, programTimeToday2200_0100,
1892e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko                programTimeTomorrow2000_2300);
1902e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko        assertOverlappedIntervalScore(0, false, programTimeTomorrow0000_0300,
1912e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko                programTimeTomorrow2000_2300);
192816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
193816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
1946ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    @Test
195816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void testGetTimeOfDayInSec() {
196816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // Time was set as 00:00:00. So, getTimeOfDay must returns 0 (= 0 * 60 * 60 + 0 * 60 + 0).
197816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertEquals("TimeOfDayInSec", hourMinuteToSec(0, 0),
198816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                RoutineWatchEvaluator.getTimeOfDayInSec(todayAtHourMin(0, 0)));
199816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
200816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // Time was set as 23:59:59. So, getTimeOfDay must returns 23 * 60 + 60 + 59 * 60 + 59.
201816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertEquals("TimeOfDayInSec", hourMinuteSecondToSec(23, 59, 59),
202816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                RoutineWatchEvaluator.getTimeOfDayInSec(todayAtHourMinSec(23, 59, 59)));
203816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
204816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
205816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private void assertSplitTextToWords(String text, String... words) {
206816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        List<String> wordList = RoutineWatchEvaluator.splitTextToWords(text);
207816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        MoreAsserts.assertContentsInOrder(wordList, words);
208816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
209816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
2102e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko    private void assertMaximumMatchedWordSequenceLength(int expectedLength, String text1,
2112e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko            String text2) {
212816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        List<String> wordList1 = RoutineWatchEvaluator.splitTextToWords(text1);
213816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        List<String> wordList2 = RoutineWatchEvaluator.splitTextToWords(text2);
214816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertEquals("MaximumMatchedWordSequenceLength", expectedLength,
21565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                RoutineWatchEvaluator.calculateMaximumMatchedWordSequenceLength(
21665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                        wordList1, wordList2));
217816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertEquals("MaximumMatchedWordSequenceLength", expectedLength,
21865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                RoutineWatchEvaluator.calculateMaximumMatchedWordSequenceLength(
21965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                        wordList2, wordList1));
220816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
221816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
222816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private void assertProgramTime(int expectedWeekDay, int expectedStartTimeOfDayInSec,
223816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            int expectedEndTimeOfDayInSec, ProgramTime actualProgramTime) {
224816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertEquals("Weekday", expectedWeekDay, actualProgramTime.weekDay);
2252e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko        assertEquals("StartTimeOfDayInSec", expectedStartTimeOfDayInSec,
2262e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko                actualProgramTime.startTimeOfDayInSec);
2272e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko        assertEquals("EndTimeOfDayInSec", expectedEndTimeOfDayInSec,
2282e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko                actualProgramTime.endTimeOfDayInSec);
229816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
230816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
231816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private void assertOverlappedIntervalScore(int expectedSeconds, boolean overlappedOnSameDay,
232816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            ProgramTime t1, ProgramTime t2) {
23307b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko        double score = expectedSeconds;
234816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (!overlappedOnSameDay) {
235816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            score *= RoutineWatchEvaluator.MULTIPLIER_FOR_UNMATCHED_DAY_OF_WEEK;
236816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
237816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // Two tests for testing commutative law.
2386ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        assertEqualScores("OverlappedIntervalScore", score,
23965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                RoutineWatchEvaluator.calculateOverlappedIntervalScore(t1, t2));
2406ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        assertEqualScores("OverlappedIntervalScore", score,
24165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                RoutineWatchEvaluator.calculateOverlappedIntervalScore(t2, t1));
242816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
243816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
244816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private int hourMinuteToSec(int hour, int minute) {
245816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        return hourMinuteSecondToSec(hour, minute, 0);
246816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
247816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
248816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private int hourMinuteSecondToSec(int hour, int minute, int second) {
249816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        return hour * 60 * 60 + minute * 60 + second;
250816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
251816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
252816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private Calendar todayAtHourMin(int hour, int minute) {
253816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        return todayAtHourMinSec(hour, minute, 0);
254816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
255816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
256816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private Calendar todayAtHourMinSec(int hour, int minute, int second) {
257816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        Calendar time = Calendar.getInstance();
258816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        time.set(Calendar.HOUR_OF_DAY, hour);
259816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        time.set(Calendar.MINUTE, minute);
260816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        time.set(Calendar.SECOND, second);
261816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        return time;
262816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
263816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
264816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private Calendar tomorrowAtHourMin(int hour, int minute) {
265816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        Calendar time = todayAtHourMin(hour, minute);
266816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        time.add(Calendar.DATE, 1);
267816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        return time;
268816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
269816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
270816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private Program createDummyProgram(Calendar startTime, long programDurationMs) {
271816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        long startTimeMs = startTime.getTimeInMillis();
272816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
2732e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko        return new Program.Builder().setStartTimeUtcMillis(startTimeMs)
2742e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko                .setEndTimeUtcMillis(startTimeMs + programDurationMs).build();
2752e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko    }
2762e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko
2772e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko    private static <T> void assertInOrder(T... items) {
2782e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko        TreeSet<T> copy = new TreeSet<>(Arrays.asList(items));
2792e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko        MoreAsserts.assertContentsInOrder(copy, items);
280816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
281816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko}
282