blob: c862e5add0b9ebb181caece6ebc26438522f0205 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "peridot/bin/suggestion_engine/ranking_features/mod_pair_ranking_feature.h"
#include <lib/context/cpp/context_helper.h>
#include <lib/fxl/logging.h>
#include "rapidjson/document.h"
#include "rapidjson/schema.h"
namespace modular {
namespace {
// Sample map using data collected between Feb 6-20, 2018
constexpr char kDataFilePath[] = "/pkg/data/ranking_data/mod_pairs.json";
} // namespace
ModPairRankingFeature::ModPairRankingFeature(const bool init_data) {
if (init_data) {
LoadDataFromFile(kDataFilePath);
}
}
ModPairRankingFeature::~ModPairRankingFeature() = default;
void ModPairRankingFeature::LoadDataFromFile(const std::string& filepath) {
auto maybe_result = FetchJsonObject(filepath);
if (!maybe_result.has_value()) {
FXL_LOG(WARNING) << "Failed to fetch mod pairs ranking feature data.";
return;
}
auto& result = maybe_result.value();
module_pairs_.clear();
for (rapidjson::Value::ConstMemberIterator iter = result.MemberBegin();
iter != result.MemberEnd(); ++iter) {
const std::string existing_mod_url = iter->name.GetString();
rapidjson::Value& other_mods = result[existing_mod_url.c_str()];
for (rapidjson::Value::ConstMemberIterator iter2 = other_mods.MemberBegin();
iter2 != other_mods.MemberEnd(); ++iter2) {
const std::string added_mod_url = iter2->name.GetString();
module_pairs_[existing_mod_url][added_mod_url] = iter2->value.GetDouble();
}
}
}
double ModPairRankingFeature::ComputeFeatureInternal(
const fuchsia::modular::UserInput& query,
const RankedSuggestion& suggestion) {
double prob = 0.0;
for (auto& command : *suggestion.prototype->proposal.on_selected) {
fidl::StringPtr module_url;
switch (command.Which()) {
case fuchsia::modular::StoryCommand::Tag::kAddMod: {
module_url = command.add_mod().intent.handler;
break;
}
case fuchsia::modular::StoryCommand::Tag::kSetKindOfProtoStoryOption:
case fuchsia::modular::StoryCommand::Tag::kSetFocusState:
case fuchsia::modular::StoryCommand::Tag::kFocusMod:
case fuchsia::modular::StoryCommand::Tag::kSetLinkValue:
case fuchsia::modular::StoryCommand::Tag::kRemoveMod:
case fuchsia::modular::StoryCommand::Tag::Invalid:
continue;
}
if (module_url.is_null() || module_url->empty()) {
continue;
}
// Currently computing: max{P(m|mi) for mi in modules_in_source_story}
// TODO(miguelfrde): compute P(module_url | modules in source story)
for (auto& context_value : *ContextValues()) {
const std::string existing_mod_url = context_value.meta.mod->url;
if (module_pairs_.count(existing_mod_url) &&
module_pairs_[existing_mod_url].count(module_url)) {
prob = std::max(prob, module_pairs_[existing_mod_url][module_url]);
}
}
}
return prob;
}
fuchsia::modular::ContextSelectorPtr
ModPairRankingFeature::CreateContextSelectorInternal() {
// Get modules in the currently focused story.
auto selector = fuchsia::modular::ContextSelector::New();
selector->type = fuchsia::modular::ContextValueType::MODULE;
selector->meta = fuchsia::modular::ContextMetadata::New();
selector->meta->story = fuchsia::modular::StoryMetadata::New();
selector->meta->story->focused = fuchsia::modular::FocusedState::New();
selector->meta->story->focused->state =
fuchsia::modular::FocusedStateState::FOCUSED;
return selector;
}
} // namespace modular