| Index: chrome/browser/history/visit_filter.cc
|
| diff --git a/chrome/browser/history/visit_filter.cc b/chrome/browser/history/visit_filter.cc
|
| index 4acebac6619a75732c7f1ecaca0ca76efefaef66..32ca4266d6455885f3ef73646adac1cac41d0288 100644
|
| --- a/chrome/browser/history/visit_filter.cc
|
| +++ b/chrome/browser/history/visit_filter.cc
|
| @@ -4,13 +4,18 @@
|
|
|
| #include "chrome/browser/history/visit_filter.h"
|
|
|
| +#include <math.h>
|
| +
|
| #include <algorithm>
|
|
|
| #include "base/logging.h"
|
| #include "base/time.h"
|
| +#include "chrome/browser/history/history_types.h"
|
|
|
| namespace history {
|
|
|
| +const double kLn2 = 0.6931471805599453;
|
| +
|
| VisitFilter::VisitFilter()
|
| : day_(DAY_UNDEFINED),
|
| max_results_(0),
|
| @@ -20,54 +25,58 @@ VisitFilter::VisitFilter()
|
| VisitFilter::~VisitFilter() {
|
| }
|
|
|
| -void VisitFilter::SetTimeInRangeFilter(base::Time begin_time_of_the_day,
|
| - base::Time end_time_of_the_day) {
|
| - DCHECK(!begin_time_of_the_day.is_null());
|
| - DCHECK(!end_time_of_the_day.is_null());
|
| - if ((end_time_of_the_day < begin_time_of_the_day) ||
|
| - ((end_time_of_the_day - begin_time_of_the_day) >
|
| - base::TimeDelta::FromDays(1))) {
|
| - begin_time_of_the_day_ = base::Time();
|
| - end_time_of_the_day_ = base::Time();
|
| - } else {
|
| - begin_time_of_the_day_ = begin_time_of_the_day;
|
| - end_time_of_the_day_ = end_time_of_the_day;
|
| - }
|
| +void VisitFilter::SetFilterTime(const base::Time& filter_time) {
|
| + filter_time_ = filter_time;
|
| UpdateTimeVector();
|
| }
|
|
|
| -void VisitFilter::SetDayOfTheWeekFilter(int day, base::Time week) {
|
| +void VisitFilter::SetFilterWidth(const base::TimeDelta& filter_width) {
|
| + filter_width_ = filter_width;
|
| + UpdateTimeVector();
|
| +}
|
| +
|
| +void VisitFilter::SetDayOfTheWeekFilter(int day) {
|
| day_ = day;
|
| - week_ = week;
|
| UpdateTimeVector();
|
| }
|
|
|
| -void VisitFilter::SetDayTypeFilter(bool workday, base::Time week) {
|
| +void VisitFilter::SetDayTypeFilter(bool workday) {
|
| day_ = workday ? WORKDAY : HOLIDAY;
|
| - week_ = week;
|
| UpdateTimeVector();
|
| }
|
|
|
| void VisitFilter::ClearFilters() {
|
| - begin_time_of_the_day_ = base::Time();
|
| - end_time_of_the_day_ = base::Time();
|
| + filter_time_ = base::Time();
|
| + filter_width_ = base::TimeDelta::FromHours(0);
|
| day_ = DAY_UNDEFINED;
|
| UpdateTimeVector();
|
| }
|
|
|
| bool VisitFilter::UpdateTimeVector() {
|
| - TimeVector times_of_the_day;
|
| - if (!begin_time_of_the_day_.is_null()) {
|
| - GetTimesInRange(begin_time_of_the_day_, end_time_of_the_day_,
|
| - max_results_, ×_of_the_day);
|
| - }
|
| +
|
| TimeVector days_of_the_week;
|
| if (day_ >= 0 && day_ <= 6) {
|
| - GetTimesOnTheDayOfTheWeek(day_, week_, max_results_, &days_of_the_week);
|
| + GetTimesOnTheDayOfTheWeek(day_, filter_time_, max_results_,
|
| + &days_of_the_week);
|
| } else if (day_ == WORKDAY || day_ == HOLIDAY) {
|
| GetTimesOnTheSameDayType(
|
| - (day_ == WORKDAY), week_, max_results_, &days_of_the_week);
|
| + (day_ == WORKDAY), filter_time_, max_results_, &days_of_the_week);
|
| + }
|
| +
|
| + TimeVector times_of_the_day;
|
| + if (filter_width_ != base::TimeDelta::FromSeconds(0)) {
|
| + if (sorting_order_ == ORDER_BY_TIME_GAUSSIAN) {
|
| + // Limit queries to 5 standard deviations.
|
| + GetTimesInRange(filter_time_ - 5 * filter_width_,
|
| + filter_time_ + 5 * filter_width_,
|
| + max_results_, ×_of_the_day);
|
| + } else {
|
| + GetTimesInRange(filter_time_ - filter_width_,
|
| + filter_time_ + filter_width_,
|
| + max_results_, ×_of_the_day);
|
| + }
|
| }
|
| +
|
| if (times_of_the_day.empty()) {
|
| if (days_of_the_week.empty())
|
| times_.clear();
|
| @@ -79,6 +88,7 @@ bool VisitFilter::UpdateTimeVector() {
|
| else
|
| IntersectTimeVectors(times_of_the_day, days_of_the_week, ×_);
|
| }
|
| +
|
| return !times_.empty();
|
| }
|
|
|
| @@ -95,6 +105,16 @@ void VisitFilter::GetTimesInRange(base::Time begin_time_of_the_day,
|
| if (!max_results)
|
| max_results = kMaxReturnedResults;
|
|
|
| + // If range is more than 24 hours, return a contiguous interval covering
|
| + // |max_results| days.
|
| + base::TimeDelta one_day = base::TimeDelta::FromDays(1);
|
| + if (end_time_of_the_day - begin_time_of_the_day >= one_day) {
|
| + times->push_back(
|
| + std::make_pair(begin_time_of_the_day - one_day * (max_results - 1),
|
| + end_time_of_the_day));
|
| + return;
|
| + }
|
| +
|
| for (size_t i = 0; i < max_results; ++i) {
|
| times->push_back(
|
| std::make_pair(begin_time_of_the_day - base::TimeDelta::FromDays(i),
|
| @@ -102,6 +122,70 @@ void VisitFilter::GetTimesInRange(base::Time begin_time_of_the_day,
|
| }
|
| }
|
|
|
| +double VisitFilter::GetVisitScore(const VisitRow& visit) const {
|
| + // Decay score by half each week.
|
| + base::TimeDelta time_passed = filter_time_ - visit.visit_time;
|
| + // Clamp to 0 in case time jumps backwards (e.g. due to DST).
|
| + double decay_exponent = std::max(0.0, kLn2 * static_cast<double>(
|
| + time_passed.InMicroseconds()) / base::Time::kMicrosecondsPerWeek);
|
| + double staleness = 1.0 / exp(decay_exponent);
|
| +
|
| + double score = 0;
|
| + switch (sorting_order()) {
|
| + case ORDER_BY_RECENCY:
|
| + score = 1.0; // Let the staleness factor take care of it.
|
| + break;
|
| + case ORDER_BY_VISIT_COUNT:
|
| + score = 1.0; // Every visit counts the same.
|
| + staleness = 1.0; // No decay on this one.
|
| + break;
|
| + case ORDER_BY_TIME_GAUSSIAN: {
|
| + double offset =
|
| + GetTimeOfDayDifference(filter_time_,
|
| + visit.visit_time).InMicroseconds();
|
| + double sd = filter_width_.InMicroseconds();
|
| +
|
| + // Calculate score using the normal distribution density function.
|
| + score = exp(-(offset * offset) / (2 * sd * sd));
|
| + break;
|
| + }
|
| + case ORDER_BY_TIME_LINEAR: {
|
| + base::TimeDelta offset = GetTimeOfDayDifference(filter_time_,
|
| + visit.visit_time);
|
| + if (offset > filter_width_) {
|
| + score = 0;
|
| + } else {
|
| + score = 1 - offset.InMicroseconds() / static_cast<double>(
|
| + filter_width_.InMicroseconds());
|
| + }
|
| + break;
|
| + }
|
| + case ORDER_BY_DURATION_SPENT:
|
| + default:
|
| + NOTREACHED() << "Not implemented!";
|
| + }
|
| + return staleness * score;
|
| +}
|
| +
|
| +base::TimeDelta
|
| +VisitFilter::GetTimeOfDayDifference(base::Time t1, base::Time t2) {
|
| + base::TimeDelta time_of_day1 = t1 - t1.LocalMidnight();
|
| + base::TimeDelta time_of_day2 = t2 - t2.LocalMidnight();
|
| +
|
| + base::TimeDelta difference;
|
| + if (time_of_day1 < time_of_day2)
|
| + difference = time_of_day2 - time_of_day1;
|
| + else
|
| + difference = time_of_day1 - time_of_day2;
|
| +
|
| + // If the difference is more than 12 hours, we'll get closer by 'wrapping'
|
| + // around the day barrier.
|
| + if (difference > base::TimeDelta::FromHours(12))
|
| + difference = base::TimeDelta::FromHours(24) - difference;
|
| +
|
| + return difference;
|
| +}
|
| +
|
| // static
|
| void VisitFilter::GetTimesOnTheDayOfTheWeek(int day,
|
| base::Time week,
|
|
|