131 lines
3 KiB
C++
131 lines
3 KiB
C++
#pragma once
|
|
|
|
#include "../std/string.hpp"
|
|
#include "../std/algorithm.hpp"
|
|
#include "../std/stdint.hpp"
|
|
|
|
namespace wr { class Writer; }
|
|
namespace rd { class Reader; }
|
|
|
|
const int EMPTY_COORD = 1000;
|
|
|
|
|
|
class ArticleInfo
|
|
{
|
|
void GenerateKey();
|
|
static string Title2Key(string const & s);
|
|
|
|
protected:
|
|
string m_key;
|
|
string m_title;
|
|
string m_url;
|
|
uint32_t m_length;
|
|
int32_t m_parentIndex; // NO_PARENT is the root article
|
|
bool m_redirect;
|
|
double m_lat, m_lon;
|
|
|
|
static const int32_t NO_PARENT = -1;
|
|
|
|
/// Need access for protected fields in Build and Storage classes.
|
|
friend class Storage;
|
|
friend class StorageBuilder;
|
|
|
|
public:
|
|
ArticleInfo()
|
|
: m_length(0), m_parentIndex(NO_PARENT),
|
|
m_redirect(false), m_lat(EMPTY_COORD), m_lon(EMPTY_COORD)
|
|
{
|
|
}
|
|
|
|
ArticleInfo(string const & title)
|
|
: m_title(title), m_length(0), m_parentIndex(NO_PARENT),
|
|
m_redirect(false), m_lat(EMPTY_COORD), m_lon(EMPTY_COORD)
|
|
{
|
|
GenerateKey();
|
|
}
|
|
|
|
ArticleInfo(string const & title, ArticleInfo const & src, bool redirect)
|
|
: m_title(title), m_url(src.m_url),
|
|
m_length(src.m_length), m_parentIndex(NO_PARENT),
|
|
m_redirect(redirect), m_lat(src.m_lat), m_lon(src.m_lon)
|
|
{
|
|
GenerateKey();
|
|
}
|
|
|
|
static string Prefix2Key(string const & s);
|
|
|
|
string const & GetTitle() const { return m_title; }
|
|
string GetUrl() const { return m_url + ".html"; }
|
|
string GetThumbnailUrl() const { return m_url + ".jpg"; }
|
|
|
|
bool IsRedirect() const { return m_redirect; }
|
|
bool IsValidCoordinates() const;
|
|
|
|
void Write(wr::Writer & w) const;
|
|
void Read(rd::Reader & r);
|
|
|
|
bool GetLatLon(double & lat, double & lon) const
|
|
{
|
|
if (IsValidCoordinates())
|
|
{
|
|
lat = m_lat;
|
|
lon = m_lon;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// Calculate score for info. Less is better.
|
|
double Score(double currLat, double currLon) const;
|
|
|
|
void Swap(ArticleInfo & i);
|
|
|
|
bool operator == (ArticleInfo const & r) const;
|
|
|
|
/// @param[in] query should be simplified, lower case, utf8 string (matching by m_key).
|
|
bool PrefixMatchExcept1stToken(string const & query) const;
|
|
|
|
struct LessStorage
|
|
{
|
|
bool operator() (ArticleInfo const & i1, ArticleInfo const & i2) const
|
|
{
|
|
return (i1.m_key < i2.m_key);
|
|
}
|
|
};
|
|
|
|
class LessPrefix
|
|
{
|
|
int Compare(ArticleInfo const & info, string const & prefix) const
|
|
{
|
|
size_t const count = min(info.m_key.size(), prefix.size());
|
|
for (size_t i = 0; i < count; ++i)
|
|
{
|
|
if (info.m_key[i] < prefix[i])
|
|
return -1;
|
|
else if (info.m_key[i] > prefix[i])
|
|
return 1;
|
|
}
|
|
return (info.m_key.size() < prefix.size() ? -1 : 0);
|
|
}
|
|
|
|
public:
|
|
bool operator() (ArticleInfo const & info, string const & prefix) const
|
|
{
|
|
return (Compare(info, prefix) == -1);
|
|
}
|
|
bool operator() (string const & prefix, ArticleInfo const & info) const
|
|
{
|
|
return (Compare(info, prefix) == 1);
|
|
}
|
|
};
|
|
};
|
|
|
|
inline void swap(ArticleInfo & a1, ArticleInfo & a2)
|
|
{
|
|
a1.Swap(a2);
|
|
}
|
|
|
|
inline string ToString(ArticleInfo const & i)
|
|
{
|
|
return i.GetTitle();
|
|
}
|