Codebase list mozc / upstream/1.3.975.102 prediction / predictor.cc
upstream/1.3.975.102

Tree @upstream/1.3.975.102 (Download .tar.gz)

predictor.cc @upstream/1.3.975.102raw · history · blame

// Copyright 2010-2012, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <string>
#include <vector>
#include "base/base.h"
#include "base/singleton.h"
#include "config/config_handler.h"
#include "config/config.pb.h"
#include "converter/segments.h"
#include "session/commands.pb.h"
#include "prediction/dictionary_predictor.h"
#include "prediction/predictor.h"
#include "prediction/user_history_predictor.h"

namespace mozc {
namespace {
const int kPredictionSize = 100;


size_t GetCandidatesSize(const Segments &segments) {
  if (segments.conversion_segments_size() <= 0) {
    LOG(ERROR) << "No conversion segments found";
    return 0;
  }
  return segments.conversion_segment(0).candidates_size();
}

PredictorInterface *g_predictor = NULL;
PredictorInterface *g_user_history_predictor = NULL;
PredictorInterface *g_dictionary_predictor = NULL;


}  // namespace

BasePredictor::BasePredictor() {}

BasePredictor::~BasePredictor() {}

void BasePredictor::Finish(Segments *segments) {
  PredictorFactory::GetUserHistoryPredictor()->Finish(segments);
  PredictorFactory::GetDictionaryPredictor()->Finish(segments);

  if (segments->conversion_segments_size() < 1 ||
      segments->request_type() == Segments::CONVERSION) {
    return;
  }
  Segment *segment = segments->mutable_conversion_segment(0);
  if (segment->candidates_size() < 1) {
    return;
  }
  // update the key as the original key only contains
  // the 'prefix'.
  // note that candidate key may be different from request key (=segment key)
  // due to suggestion/prediction.
  segment->set_key(segment->candidate(0).key);
}

// Since DictionaryPredictor is immutable, no need
// to call DictionaryPredictor::Revert/Clear*/Finish methods.
void BasePredictor::Revert(Segments *segments) {
  PredictorInterface *user_history_predictor =
      PredictorFactory::GetUserHistoryPredictor();
  DCHECK(user_history_predictor != NULL);
  user_history_predictor->Revert(segments);
}

bool BasePredictor::ClearAllHistory() {
  PredictorInterface *user_history_predictor =
      PredictorFactory::GetUserHistoryPredictor();
  DCHECK(user_history_predictor != NULL);
  return user_history_predictor->ClearAllHistory();
}

bool BasePredictor::ClearUnusedHistory() {
  PredictorInterface *user_history_predictor =
      PredictorFactory::GetUserHistoryPredictor();
  DCHECK(user_history_predictor);
  return user_history_predictor->ClearUnusedHistory();
}

bool BasePredictor::Sync() {
  PredictorInterface *user_history_predictor =
      PredictorFactory::GetUserHistoryPredictor();
  DCHECK(user_history_predictor);
  return user_history_predictor->Sync();
}

bool BasePredictor::Reload() {
  PredictorInterface *user_history_predictor =
      PredictorFactory::GetUserHistoryPredictor();
  DCHECK(user_history_predictor);
  return user_history_predictor->Reload();
}

bool DefaultPredictor::Predict(Segments *segments) const {
  DCHECK(segments->request_type() == Segments::PREDICTION ||
         segments->request_type() == Segments::SUGGESTION ||
         segments->request_type() == Segments::PARTIAL_PREDICTION ||
         segments->request_type() == Segments::PARTIAL_SUGGESTION);

  if (GET_CONFIG(presentation_mode)) {
    return false;
  }

  int size = kPredictionSize;
  if (segments->request_type() == Segments::SUGGESTION) {
    size = min(9, max(1, static_cast<int>(GET_CONFIG(suggestions_size))));
  }

  bool result = false;

  PredictorInterface *user_history_predictor =
      PredictorFactory::GetUserHistoryPredictor();
  PredictorInterface *dictionary_predictor =
      PredictorFactory::GetDictionaryPredictor();
  DCHECK(user_history_predictor);
  DCHECK(dictionary_predictor);

  int remained_size = size;
  segments->set_max_prediction_candidates_size(static_cast<size_t>(size));
  result |= user_history_predictor->Predict(segments);
  remained_size = size - static_cast<size_t>(GetCandidatesSize(*segments));

  // Do not call dictionary_predictor if the size of candidates get
  // >= suggestions_size.
  if (remained_size <= 0) {
    return result;
  }

  segments->set_max_prediction_candidates_size(remained_size);
  result |= dictionary_predictor->Predict(segments);
  remained_size = size - static_cast<size_t>(GetCandidatesSize(*segments));


  return result;
}


#define GET_PREDICTOR(PredictorClass, predictor_instance) do { \
  if (predictor_instance == NULL) { \
    return Singleton<PredictorClass>::get(); \
  } else { \
    return predictor_instance; \
  } \
} while (0)

PredictorInterface *PredictorFactory::GetPredictor() {
    GET_PREDICTOR(DefaultPredictor, g_predictor);
}

void PredictorFactory::SetPredictor(PredictorInterface *predictor) {
  g_predictor = predictor;
}

PredictorInterface *PredictorFactory::GetUserHistoryPredictor() {
  GET_PREDICTOR(UserHistoryPredictor, g_user_history_predictor);
}

void PredictorFactory::SetUserHistoryPredictor(PredictorInterface *predictor) {
  g_user_history_predictor = predictor;
}

PredictorInterface *PredictorFactory::GetDictionaryPredictor() {
  GET_PREDICTOR(DictionaryPredictor, g_dictionary_predictor);
}

void PredictorFactory::SetDictionaryPredictor(PredictorInterface *predictor) {
  g_dictionary_predictor = predictor;
}


#undef GET_PREDICTOR
}  // namespace mozc