forked from organicmaps/organicmaps-tmp
[assessment-tool] Implemented radio-buttons for relevances.
This commit is contained in:
parent
37b38c9217
commit
d3c949065a
14 changed files with 287 additions and 59 deletions
|
@ -19,6 +19,10 @@ set(
|
|||
main_view.cpp
|
||||
main_view.hpp
|
||||
model.hpp
|
||||
result_view.cpp
|
||||
result_view.hpp
|
||||
results_view.cpp
|
||||
results_view.hpp
|
||||
sample_view.cpp
|
||||
sample_view.hpp
|
||||
samples_view.cpp
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "search/search_quality/assessment_tool/main_model.hpp"
|
||||
|
||||
#include "search/search_quality/assessment_tool/view.hpp"
|
||||
#include "search/search_quality/matcher.hpp"
|
||||
|
||||
#include "map/framework.hpp"
|
||||
|
||||
|
@ -19,7 +20,10 @@
|
|||
#include <fstream>
|
||||
#include <iterator>
|
||||
|
||||
MainModel::MainModel(Framework & framework) : m_framework(framework) {}
|
||||
MainModel::MainModel(Framework & framework)
|
||||
: m_framework(framework), m_index(m_framework.GetIndex())
|
||||
{
|
||||
}
|
||||
|
||||
void MainModel::Open(std::string const & path)
|
||||
{
|
||||
|
@ -41,6 +45,8 @@ void MainModel::Open(std::string const & path)
|
|||
return;
|
||||
}
|
||||
|
||||
InvalidateSearch();
|
||||
|
||||
m_samples.swap(samples);
|
||||
m_view->SetSamples(m_samples);
|
||||
}
|
||||
|
@ -54,6 +60,8 @@ void MainModel::OnSampleSelected(int index)
|
|||
auto const & sample = m_samples[index];
|
||||
m_view->ShowSample(m_samples[index]);
|
||||
|
||||
InvalidateSearch();
|
||||
|
||||
auto & engine = m_framework.GetSearchEngine();
|
||||
{
|
||||
auto latLon = MercatorBounds::ToLatLon(sample.m_pos);
|
||||
|
@ -64,24 +72,53 @@ void MainModel::OnSampleSelected(int index)
|
|||
params.m_suggestsEnabled = false;
|
||||
params.SetPosition(latLon.lat, latLon.lon);
|
||||
|
||||
auto const timestamp = ++m_queryTimestamp;
|
||||
auto const timestamp = m_queryTimestamp;
|
||||
m_numShownResults = 0;
|
||||
|
||||
params.m_onResults = [this, timestamp](search::Results const & results) {
|
||||
GetPlatform().RunOnGuiThread([this, timestamp, results]() { OnResults(timestamp, results); });
|
||||
params.m_onResults = [this, sample, timestamp](search::Results const & results) {
|
||||
vector<search::Sample::Result::Relevance> relevances;
|
||||
if (results.IsEndedNormal())
|
||||
{
|
||||
search::Matcher matcher(m_index);
|
||||
|
||||
vector<search::Result> const actual(results.begin(), results.end());
|
||||
std::vector<size_t> goldenMatching;
|
||||
{
|
||||
std::vector<size_t> actualMatching;
|
||||
matcher.Match(sample.m_results, actual, goldenMatching, actualMatching);
|
||||
}
|
||||
|
||||
relevances.assign(actual.size(), search::Sample::Result::RELEVANCE_IRRELEVANT);
|
||||
for (size_t i = 0; i < goldenMatching.size(); ++i) {
|
||||
if (goldenMatching[i] != search::Matcher::kInvalidId)
|
||||
relevances[goldenMatching[i]] = sample.m_results[i].m_relevance;
|
||||
}
|
||||
}
|
||||
|
||||
GetPlatform().RunOnGuiThread(
|
||||
[this, timestamp, results, relevances]() { OnResults(timestamp, results, relevances); });
|
||||
};
|
||||
|
||||
if (auto handle = m_queryHandle.lock())
|
||||
handle->Cancel();
|
||||
m_queryHandle = engine.Search(params, sample.m_viewport);
|
||||
}
|
||||
}
|
||||
|
||||
void MainModel::OnResults(uint64_t timestamp, search::Results const & results)
|
||||
void MainModel::OnResults(uint64_t timestamp, search::Results const & results,
|
||||
vector<search::Sample::Result::Relevance> const & relevances)
|
||||
{
|
||||
if (timestamp != m_queryTimestamp)
|
||||
return;
|
||||
CHECK_LESS_OR_EQUAL(m_numShownResults, results.GetCount(), ());
|
||||
m_view->ShowResults(results.begin() + m_numShownResults, results.end());
|
||||
m_numShownResults = results.GetCount();
|
||||
|
||||
if (results.IsEndedNormal())
|
||||
m_view->SetResultRelevances(relevances);
|
||||
}
|
||||
|
||||
void MainModel::InvalidateSearch()
|
||||
{
|
||||
++m_queryTimestamp;
|
||||
if (auto handle = m_queryHandle.lock())
|
||||
handle->Cancel();
|
||||
}
|
||||
|
|
|
@ -25,9 +25,13 @@ public:
|
|||
void OnSampleSelected(int index) override;
|
||||
|
||||
private:
|
||||
void OnResults(uint64_t timestamp, search::Results const & results);
|
||||
void OnResults(uint64_t timestamp, search::Results const & results,
|
||||
std::vector<search::Sample::Result::Relevance> const & relevances);
|
||||
|
||||
void InvalidateSearch();
|
||||
|
||||
Framework & m_framework;
|
||||
Index const & m_index;
|
||||
std::vector<search::Sample> m_samples;
|
||||
|
||||
std::weak_ptr<search::ProcessorHandle> m_queryHandle;
|
||||
|
|
|
@ -56,6 +56,12 @@ void MainView::ShowResults(search::Results::Iter begin, search::Results::Iter en
|
|||
m_sampleView->ShowResults(begin, end);
|
||||
}
|
||||
|
||||
void MainView::SetResultRelevances(
|
||||
std::vector<search::Sample::Result::Relevance> const & relevances)
|
||||
{
|
||||
m_sampleView->SetResultRelevances(relevances);
|
||||
}
|
||||
|
||||
void MainView::ShowError(std::string const & msg)
|
||||
{
|
||||
QMessageBox box(QMessageBox::Critical /* icon */, tr("Error") /* title */,
|
||||
|
|
|
@ -30,6 +30,8 @@ public:
|
|||
void SetSamples(std::vector<search::Sample> const & samples) override;
|
||||
void ShowSample(search::Sample const & sample) override;
|
||||
void ShowResults(search::Results::Iter begin, search::Results::Iter end) override;
|
||||
void SetResultRelevances(
|
||||
std::vector<search::Sample::Result::Relevance> const & relevances) override;
|
||||
void ShowError(std::string const & msg) override;
|
||||
|
||||
private Q_SLOTS:
|
||||
|
|
97
search/search_quality/assessment_tool/result_view.cpp
Normal file
97
search/search_quality/assessment_tool/result_view.cpp
Normal file
|
@ -0,0 +1,97 @@
|
|||
#include "search/search_quality/assessment_tool/result_view.hpp"
|
||||
|
||||
#include "search/result.hpp"
|
||||
#include "search/search_quality/assessment_tool/helpers.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <QtWidgets/QHBoxLayout>
|
||||
#include <QtWidgets/QLabel>
|
||||
#include <QtWidgets/QRadioButton>
|
||||
#include <QtWidgets/QVBoxLayout>
|
||||
|
||||
namespace
|
||||
{
|
||||
QLabel * CreateLabel(QWidget & parent)
|
||||
{
|
||||
QLabel * label = new QLabel(&parent);
|
||||
label->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum);
|
||||
label->setWordWrap(true);
|
||||
return label;
|
||||
}
|
||||
|
||||
void SetText(QLabel & label, std::string const & text) {
|
||||
if (text.empty())
|
||||
{
|
||||
label.hide();
|
||||
return;
|
||||
}
|
||||
|
||||
label.setText(ToQString(text));
|
||||
label.show();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
ResultView::ResultView(search::Result const & result, QWidget & parent) : QWidget(&parent)
|
||||
{
|
||||
Init();
|
||||
SetContents(result);
|
||||
}
|
||||
|
||||
void ResultView::SetRelevance(search::Sample::Result::Relevance relevance)
|
||||
{
|
||||
m_irrelevant->setChecked(false);
|
||||
m_relevant->setChecked(false);
|
||||
m_vital->setChecked(false);
|
||||
switch (relevance)
|
||||
{
|
||||
case search::Sample::Result::RELEVANCE_IRRELEVANT: m_irrelevant->setChecked(true); break;
|
||||
case search::Sample::Result::RELEVANCE_RELEVANT: m_relevant->setChecked(true); break;
|
||||
case search::Sample::Result::RELEVANCE_VITAL: m_vital->setChecked(true); break;
|
||||
}
|
||||
}
|
||||
|
||||
void ResultView::Init()
|
||||
{
|
||||
auto * layout = new QVBoxLayout(this /* parent */);
|
||||
layout->setSizeConstraint(QLayout::SetMinimumSize);
|
||||
setLayout(layout);
|
||||
|
||||
m_string = CreateLabel(*this /* parent */);
|
||||
layout->addWidget(m_string);
|
||||
|
||||
m_type = CreateLabel(*this /* parent */);
|
||||
m_type->setStyleSheet("QLabel { font-size : 8pt }");
|
||||
layout->addWidget(m_type);
|
||||
|
||||
m_address = CreateLabel(*this /* parent */);
|
||||
m_address->setStyleSheet("QLabel { color : green ; font-size : 8pt }");
|
||||
layout->addWidget(m_address);
|
||||
|
||||
{
|
||||
auto * group = new QWidget(this /* parent */);
|
||||
auto * groupLayout = new QHBoxLayout(group /* parent */);
|
||||
group->setLayout(groupLayout);
|
||||
|
||||
m_irrelevant = new QRadioButton("0", this /* parent */);
|
||||
m_relevant = new QRadioButton("+1", this /* parent */);
|
||||
m_vital = new QRadioButton("+2", this /* parent */);
|
||||
|
||||
groupLayout->addWidget(m_irrelevant);
|
||||
groupLayout->addWidget(m_relevant);
|
||||
groupLayout->addWidget(m_vital);
|
||||
|
||||
layout->addWidget(group);
|
||||
}
|
||||
}
|
||||
|
||||
void ResultView::SetContents(search::Result const & result)
|
||||
{
|
||||
SetText(*m_string, result.GetString());
|
||||
SetText(*m_type, result.GetFeatureType());
|
||||
SetText(*m_address, result.GetAddress());
|
||||
|
||||
m_irrelevant->setChecked(false);
|
||||
m_relevant->setChecked(false);
|
||||
m_vital->setChecked(false);
|
||||
}
|
33
search/search_quality/assessment_tool/result_view.hpp
Normal file
33
search/search_quality/assessment_tool/result_view.hpp
Normal file
|
@ -0,0 +1,33 @@
|
|||
#pragma once
|
||||
|
||||
#include "search/search_quality/sample.hpp"
|
||||
|
||||
#include <QtWidgets/QWidget>
|
||||
|
||||
class QLabel;
|
||||
class QRadioButton;
|
||||
|
||||
namespace search
|
||||
{
|
||||
class Result;
|
||||
}
|
||||
|
||||
class ResultView : public QWidget
|
||||
{
|
||||
public:
|
||||
ResultView(search::Result const & result, QWidget & parent);
|
||||
|
||||
void SetRelevance(search::Sample::Result::Relevance relevance);
|
||||
|
||||
private:
|
||||
void Init();
|
||||
void SetContents(search::Result const & result);
|
||||
|
||||
QLabel * m_string = nullptr;
|
||||
QLabel * m_type = nullptr;
|
||||
QLabel * m_address = nullptr;
|
||||
|
||||
QRadioButton * m_irrelevant = nullptr;
|
||||
QRadioButton * m_relevant = nullptr;
|
||||
QRadioButton * m_vital = nullptr;
|
||||
};
|
39
search/search_quality/assessment_tool/results_view.cpp
Normal file
39
search/search_quality/assessment_tool/results_view.cpp
Normal file
|
@ -0,0 +1,39 @@
|
|||
#include "search/search_quality/assessment_tool/results_view.hpp"
|
||||
|
||||
#include "search/search_quality/assessment_tool/result_view.hpp"
|
||||
|
||||
#include "base/assert.hpp"
|
||||
|
||||
#include <QtWidgets/QListWidgetItem>
|
||||
|
||||
ResultsView::ResultsView(QWidget & parent) : QListWidget(&parent) { setAlternatingRowColors(true); }
|
||||
|
||||
void ResultsView::Add(search::Result const & result)
|
||||
{
|
||||
auto * item = new QListWidgetItem(this /* parent */);
|
||||
addItem(item);
|
||||
|
||||
auto * view = new ResultView(result, *this /* parent */);
|
||||
item->setSizeHint(view->minimumSizeHint());
|
||||
setItemWidget(item, view);
|
||||
|
||||
m_results.push_back(view);
|
||||
}
|
||||
|
||||
ResultView & ResultsView::Get(size_t i)
|
||||
{
|
||||
CHECK_LESS(i, Size(), ());
|
||||
return *m_results[i];
|
||||
}
|
||||
|
||||
ResultView const & ResultsView::Get(size_t i) const
|
||||
{
|
||||
CHECK_LESS(i, Size(), ());
|
||||
return *m_results[i];
|
||||
}
|
||||
|
||||
void ResultsView::Clear()
|
||||
{
|
||||
m_results.clear();
|
||||
clear();
|
||||
}
|
34
search/search_quality/assessment_tool/results_view.hpp
Normal file
34
search/search_quality/assessment_tool/results_view.hpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
#include <QtWidgets/QListWidget>
|
||||
|
||||
class QWidget;
|
||||
class ResultView;
|
||||
|
||||
namespace search
|
||||
{
|
||||
class Result;
|
||||
}
|
||||
|
||||
class ResultsView : private QListWidget
|
||||
{
|
||||
public:
|
||||
explicit ResultsView(QWidget & parent);
|
||||
|
||||
void Add(search::Result const & result);
|
||||
|
||||
ResultView & Get(size_t i);
|
||||
ResultView const & Get(size_t i) const;
|
||||
|
||||
size_t Size() const { return m_results.size(); }
|
||||
|
||||
void Clear();
|
||||
|
||||
QWidget * GetWidget() { return this; }
|
||||
|
||||
private:
|
||||
std::vector<ResultView *> m_results;
|
||||
};
|
|
@ -3,6 +3,8 @@
|
|||
#include "search/result.hpp"
|
||||
#include "search/search_quality/assessment_tool/helpers.hpp"
|
||||
#include "search/search_quality/assessment_tool/languages_list.hpp"
|
||||
#include "search/search_quality/assessment_tool/result_view.hpp"
|
||||
#include "search/search_quality/assessment_tool/results_view.hpp"
|
||||
#include "search/search_quality/sample.hpp"
|
||||
|
||||
#include <QtGui/QStandardItem>
|
||||
|
@ -13,37 +15,8 @@
|
|||
#include <QtWidgets/QHeaderView>
|
||||
#include <QtWidgets/QLabel>
|
||||
#include <QtWidgets/QLineEdit>
|
||||
#include <QtWidgets/QListWidget>
|
||||
#include <QtWidgets/QVBoxLayout>
|
||||
|
||||
namespace
|
||||
{
|
||||
QWidget * CreateSampleWidget(QWidget & parent, search::Result const & result)
|
||||
{
|
||||
auto * widget = new QWidget(&parent);
|
||||
auto * layout = new QVBoxLayout(widget);
|
||||
widget->setLayout(layout);
|
||||
|
||||
layout->addWidget(new QLabel(ToQString(result.GetString())));
|
||||
|
||||
if (result.GetResultType() == search::Result::RESULT_FEATURE && !result.GetFeatureType().empty())
|
||||
{
|
||||
auto * type = new QLabel(ToQString(result.GetFeatureType()), widget);
|
||||
type->setStyleSheet("QLabel { font-size : 8pt }");
|
||||
layout->addWidget(type);
|
||||
}
|
||||
|
||||
if (!result.GetAddress().empty())
|
||||
{
|
||||
auto * address = new QLabel(ToQString(result.GetAddress()), widget);
|
||||
address->setStyleSheet("QLabel { color : green ; font-size : 8pt }");
|
||||
layout->addWidget(address);
|
||||
}
|
||||
|
||||
return widget;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
SampleView::SampleView(QWidget * parent) : QWidget(parent)
|
||||
{
|
||||
auto * mainLayout = BuildLayoutWithoutMargins<QVBoxLayout>(this /* parent */);
|
||||
|
@ -71,8 +44,8 @@ SampleView::SampleView(QWidget * parent) : QWidget(parent)
|
|||
|
||||
layout->addWidget(new QLabel(tr("Found results")));
|
||||
|
||||
m_results = new QListWidget(box /* parent */);
|
||||
layout->addWidget(m_results);
|
||||
m_results = new ResultsView(*box /* parent */);
|
||||
layout->addWidget(m_results->GetWidget());
|
||||
|
||||
mainLayout->addWidget(box);
|
||||
}
|
||||
|
@ -88,19 +61,19 @@ void SampleView::SetContents(search::Sample const & sample)
|
|||
|
||||
m_langs->Select(sample.m_locale);
|
||||
|
||||
m_results->clear();
|
||||
m_results->Clear();
|
||||
}
|
||||
|
||||
void SampleView::ShowResults(search::Results::Iter begin, search::Results::Iter end)
|
||||
{
|
||||
for (auto it = begin; it != end; ++it)
|
||||
{
|
||||
auto * item = new QListWidgetItem(m_results);
|
||||
m_results->addItem(item);
|
||||
|
||||
auto * widget = CreateSampleWidget(*m_results /* parent */, *it /* sample */);
|
||||
item->setSizeHint(widget->minimumSizeHint());
|
||||
|
||||
m_results->setItemWidget(item, widget);
|
||||
}
|
||||
m_results->Add(*it /* result */);
|
||||
}
|
||||
|
||||
void SampleView::SetResultRelevances(
|
||||
std::vector<search::Sample::Result::Relevance> const & relevances)
|
||||
{
|
||||
CHECK_EQUAL(relevances.size(), m_results->Size(), ());
|
||||
for (size_t i = 0; i < relevances.size(); ++i)
|
||||
m_results->Get(i).SetRelevance(relevances[i]);
|
||||
}
|
||||
|
|
|
@ -1,17 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include "search/result.hpp"
|
||||
#include "search/search_quality/sample.hpp"
|
||||
|
||||
#include <QtWidgets/QWidget>
|
||||
|
||||
class LanguagesList;
|
||||
class QLineEdit;
|
||||
class QListWidget;
|
||||
|
||||
namespace search
|
||||
{
|
||||
struct Sample;
|
||||
}
|
||||
class ResultsView;
|
||||
|
||||
class SampleView : public QWidget
|
||||
{
|
||||
|
@ -20,9 +16,10 @@ public:
|
|||
|
||||
void SetContents(search::Sample const & sample);
|
||||
void ShowResults(search::Results::Iter begin, search::Results::Iter end);
|
||||
void SetResultRelevances(std::vector<search::Sample::Result::Relevance> const & relevances);
|
||||
|
||||
private:
|
||||
QLineEdit * m_query = nullptr;
|
||||
LanguagesList * m_langs = nullptr;
|
||||
QListWidget * m_results = nullptr;
|
||||
ResultsView * m_results = nullptr;
|
||||
};
|
||||
|
|
|
@ -18,6 +18,8 @@ public:
|
|||
virtual void SetSamples(std::vector<search::Sample> const & samples) = 0;
|
||||
virtual void ShowSample(search::Sample const & sample) = 0;
|
||||
virtual void ShowResults(search::Results::Iter begin, search::Results::Iter end) = 0;
|
||||
virtual void SetResultRelevances(
|
||||
std::vector<search::Sample::Result::Relevance> const & relevances) = 0;
|
||||
virtual void ShowError(std::string const & msg) = 0;
|
||||
|
||||
protected:
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace search
|
|||
// static
|
||||
size_t constexpr Matcher::kInvalidId;
|
||||
|
||||
Matcher::Matcher(Index & index) : m_index(index) {}
|
||||
Matcher::Matcher(Index const & index) : m_index(index) {}
|
||||
|
||||
void Matcher::Match(std::vector<Sample::Result> const & golden, std::vector<Result> const & actual,
|
||||
std::vector<size_t> & goldenMatching, std::vector<size_t> & actualMatching)
|
||||
|
|
|
@ -22,7 +22,7 @@ class Matcher
|
|||
public:
|
||||
static size_t constexpr kInvalidId = std::numeric_limits<size_t>::max();
|
||||
|
||||
Matcher(Index & index);
|
||||
Matcher(Index const & index);
|
||||
|
||||
void Match(std::vector<Sample::Result> const & golden, std::vector<Result> const & actual,
|
||||
std::vector<size_t> & goldenMatching, std::vector<size_t> & actualMatching);
|
||||
|
@ -32,7 +32,7 @@ private:
|
|||
|
||||
bool Matches(Sample::Result const & golden, Result const & actual);
|
||||
|
||||
Index & m_index;
|
||||
Index const & m_index;
|
||||
std::unique_ptr<Index::FeaturesLoaderGuard> m_guard;
|
||||
};
|
||||
} // namespace search
|
||||
|
|
Loading…
Add table
Reference in a new issue