From e5b246a4f0f513c65a177a07a8c0f5c8741d004f Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Tue, 31 May 2016 11:50:12 +0200 Subject: [PATCH] Character search ranking and display is more sophisticated now --- ZRCola/zrcolachrslct.cpp | 34 +++++++++++++++--------- ZRCola/zrcolachrslct.h | 3 ++- lib/libZRCola/include/zrcola/character.h | 7 ++++- lib/libZRCola/src/character.cpp | 18 ++++++------- 4 files changed, 39 insertions(+), 23 deletions(-) diff --git a/ZRCola/zrcolachrslct.cpp b/ZRCola/zrcolachrslct.cpp index c2815eb..f78ba50 100644 --- a/ZRCola/zrcolachrslct.cpp +++ b/ZRCola/zrcolachrslct.cpp @@ -221,7 +221,7 @@ void wxZRColaCharSelect::OnSearchComplete(wxThreadEvent& event) // Display results. wxString chars; chars.reserve(m_searchThread->m_hits.size()); - for (std::vector< std::pair >::const_iterator i = m_searchThread->m_hits.cbegin(), i_end = m_searchThread->m_hits.cend(); i != i_end; ++i) + for (std::vector >::const_iterator i = m_searchThread->m_hits.cbegin(), i_end = m_searchThread->m_hits.cend(); i != i_end; ++i) chars += i->second; m_gridResults->SetCharacters(chars); @@ -483,17 +483,17 @@ wxZRColaCharSelect::SearchThread::SearchThread(wxZRColaCharSelect *parent) : wxThread::ExitCode wxZRColaCharSelect::SearchThread::Entry() { ZRColaApp *app = (ZRColaApp*)wxTheApp; - std::map hits; + std::map hits; if (TestDestroy()) return (wxThread::ExitCode)1; { // Search by indexes and merge results. - std::map hits_sub; + std::map hits_sub; if (!app->m_chr_db.Search(m_search.c_str(), m_cats, hits, hits_sub, TestDestroyS, this)) return (wxThread::ExitCode)1; - for (std::map::const_iterator i = hits_sub.cbegin(), i_end = hits_sub.cend(); i != i_end; ++i) { + for (std::map::const_iterator i = hits_sub.cbegin(), i_end = hits_sub.cend(); i != i_end; ++i) { if (TestDestroy()) return (wxThread::ExitCode)1; - std::map::iterator idx = hits.find(i->first); + std::map::iterator idx = hits.find(i->first); if (idx == hits.end()) hits.insert(std::make_pair(i->first, i->second / 4)); else @@ -501,13 +501,23 @@ wxThread::ExitCode wxZRColaCharSelect::SearchThread::Entry() } } - // Now sort the characters by rank. - m_hits.reserve(hits.size()); - for (std::map::const_iterator i = hits.cbegin(), i_end = hits.cend(); i != i_end; ++i) { + // Get best rank. + ZRCola::charrank_t rank_ref = 0; + for (std::map::const_iterator i = hits.cbegin(), i_end = hits.cend(); i != i_end; ++i) { if (TestDestroy()) return (wxThread::ExitCode)1; - m_hits.push_back(std::make_pair(i->second, i->first)); + if (i->second > rank_ref) + rank_ref = i->second; } - std::qsort(m_hits.data(), m_hits.size(), sizeof(std::pair), CompareHits); + + // Now sort the characters by rank (taking only top 3/4 by rank). + ZRCola::charrank_t rank_threshold = rank_ref*3/4; + m_hits.reserve(hits.size()); + for (std::map::const_iterator i = hits.cbegin(), i_end = hits.cend(); i != i_end; ++i) { + if (TestDestroy()) return (wxThread::ExitCode)1; + if (i->second > rank_threshold) + m_hits.push_back(std::make_pair(i->second, i->first)); + } + std::qsort(m_hits.data(), m_hits.size(), sizeof(std::pair), CompareHits); // Signal the event handler that this thread is going to be destroyed. // NOTE: here we assume that using the m_parent pointer is safe, @@ -520,8 +530,8 @@ wxThread::ExitCode wxZRColaCharSelect::SearchThread::Entry() int __cdecl wxZRColaCharSelect::SearchThread::CompareHits(const void *a, const void *b) { - const std::pair *_a = (const std::pair*)a; - const std::pair *_b = (const std::pair*)b; + const std::pair *_a = (const std::pair*)a; + const std::pair *_b = (const std::pair*)b; if (_a->first > _b->first) return -1; else if (_a->first < _b->first) return 1; diff --git a/ZRCola/zrcolachrslct.h b/ZRCola/zrcolachrslct.h index ffeae72..8e49b12 100644 --- a/ZRCola/zrcolachrslct.h +++ b/ZRCola/zrcolachrslct.h @@ -34,6 +34,7 @@ class wxPersistentZRColaCharSelect; #include #include #include +#include wxDECLARE_EVENT(wxEVT_SEARCH_COMPLETE, wxThreadEvent); @@ -101,7 +102,7 @@ protected: public: std::wstring m_search; ///< Search phrase std::set m_cats; ///< Search categories - std::vector< std::pair > m_hits; ///< Search results + std::vector > m_hits; ///< Search results protected: wxZRColaCharSelect *m_parent; ///< Thread owner diff --git a/lib/libZRCola/include/zrcola/character.h b/lib/libZRCola/include/zrcola/character.h index 3ed03c3..b9b0d7c 100644 --- a/lib/libZRCola/include/zrcola/character.h +++ b/lib/libZRCola/include/zrcola/character.h @@ -36,6 +36,11 @@ namespace ZRCola { + /// + /// Character rank type + /// + typedef double charrank_t; + /// /// Character category ID type /// Two letter abbreviation, non-terminated @@ -237,7 +242,7 @@ namespace ZRCola { /// \param[in] fn_abort Pointer to function to periodically test for search cancellation /// \param[in] cookie Cookie for \p fn_abort call /// - bool Search(_In_z_ const wchar_t *str, _In_ const std::set &cats, _Inout_ std::map &hits, _Inout_ std::map &hits_sub, _In_opt_ bool (__cdecl *fn_abort)(void *cookie) = NULL, _In_opt_ void *cookie = NULL) const; + bool Search(_In_z_ const wchar_t *str, _In_ const std::set &cats, _Inout_ std::map &hits, _Inout_ std::map &hits_sub, _In_opt_ bool (__cdecl *fn_abort)(void *cookie) = NULL, _In_opt_ void *cookie = NULL) const; /// /// Get character category diff --git a/lib/libZRCola/src/character.cpp b/lib/libZRCola/src/character.cpp index 078b834..a3ca121 100644 --- a/lib/libZRCola/src/character.cpp +++ b/lib/libZRCola/src/character.cpp @@ -20,7 +20,7 @@ #include "stdafx.h" -bool ZRCola::character_db::Search(_In_z_ const wchar_t *str, _In_ const std::set &cats, _Inout_ std::map &hits, _Inout_ std::map &hits_sub, _In_opt_ bool (__cdecl *fn_abort)(void *cookie), _In_opt_ void *cookie) const +bool ZRCola::character_db::Search(_In_z_ const wchar_t *str, _In_ const std::set &cats, _Inout_ std::map &hits, _Inout_ std::map &hits_sub, _In_opt_ bool (__cdecl *fn_abort)(void *cookie), _In_opt_ void *cookie) const { assert(str); @@ -77,13 +77,13 @@ bool ZRCola::character_db::Search(_In_z_ const wchar_t *str, _In_ const std::set if (fn_abort && fn_abort(cookie)) return false; wchar_t c = data[i]; if (cats.find(GetCharCat(c)) != cats.end()) { - std::map::iterator idx = hits.find(c); + std::map::iterator idx = hits.find(c); if (idx == hits.end()) { // New character. - hits.insert(std::make_pair(data[i], 1)); + hits.insert(std::make_pair(data[i], 1.0/len)); } else { - // Increment existing character. - idx->second++; + // Increase rating of existing character. + idx->second += 1.0/len; } } } @@ -95,13 +95,13 @@ bool ZRCola::character_db::Search(_In_z_ const wchar_t *str, _In_ const std::set if (fn_abort && fn_abort(cookie)) return false; wchar_t c = data[i]; if (cats.find(GetCharCat(c)) != cats.end()) { - std::map::iterator idx = hits_sub.find(c); + std::map::iterator idx = hits_sub.find(c); if (idx == hits_sub.end()) { // New character. - hits_sub.insert(std::make_pair(data[i], 1)); + hits_sub.insert(std::make_pair(data[i], 1.0/len)); } else { - // Increment existing character. - idx->second++; + // Increase rating of existing character. + idx->second += 1.0/len; } } }