-
-
Notifications
You must be signed in to change notification settings - Fork 5
/
Dictionary.hpp
221 lines (188 loc) · 6.35 KB
/
Dictionary.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
//////////////////////////////////////////////////////////////////////////////
// Dictionary.hpp --- XWord Giver (Japanese Crossword Generator)
// Copyright (C) 2012-2020 Katayama Hirofumi MZ. All Rights Reserved.
// (Japanese, UTF-8)
#pragma once
// 辞書の最大数。
#define XG_MAX_DICTS 64
//////////////////////////////////////////////////////////////////////////////
// 単語データ。
struct XG_WordData
{
// 単語。
XGStringW m_word;
// ヒント。
XGStringW m_hint;
// コンストラクタ。
XG_WordData() noexcept { }
// コンストラクタ。
XG_WordData(const XGStringW& word_) : m_word(word_)
{
}
// コンストラクタ。
XG_WordData(const XGStringW& word_, const XGStringW& hint_) :
m_word(word_), m_hint(hint_)
{
}
// コンストラクタ。
XG_WordData(XGStringW&& word_, XGStringW&& hint_) noexcept :
m_word(std::move(word_)), m_hint(std::move(hint_))
{
}
// コピーコンストラクタ。
XG_WordData(const XG_WordData& wd) = default;
// コピーコンストラクタ。
XG_WordData(XG_WordData&& wd) noexcept :
m_word(std::move(wd.m_word)), m_hint(std::move(wd.m_hint))
{
}
// 代入。
void __fastcall operator=(const XG_WordData& wd) {
m_word = wd.m_word;
m_hint = wd.m_hint;
}
// 代入。
void __fastcall operator=(XG_WordData&& wd) noexcept {
m_word = std::move(wd.m_word);
m_hint = std::move(wd.m_hint);
}
void clear() noexcept {
m_word.clear();
m_hint.clear();
}
};
namespace std
{
template <>
inline void swap(XG_WordData& data1, XG_WordData& data2) noexcept {
std::swap(data1.m_word, data2.m_word);
std::swap(data1.m_hint, data2.m_hint);
}
}
// 辞書データ。優先タグか否かで分ける。
extern std::vector<XG_WordData> xg_dict_1, xg_dict_2;
// タグ付けデータ。
extern std::unordered_map<XGStringW, std::unordered_set<XGStringW> > xg_word_to_tags_map;
// タグのヒストグラム。
extern std::unordered_map<XGStringW, size_t> xg_tag_histgram;
// 単語の長さのヒストグラム。
extern std::unordered_map<size_t, size_t> xg_word_length_histgram;
// 優先タグ。
extern std::unordered_set<XGStringW> xg_priority_tags;
// 除外タグ。
extern std::unordered_set<XGStringW> xg_forbidden_tags;
// テーマ文字列。
extern XGStringW xg_strTheme;
// 既定のテーマ文字列。
extern XGStringW xg_strDefaultTheme;
// テーマが変更されたか?
extern bool xg_bThemeModified;
// 配置できる最大単語長。
extern int xg_nDictMaxWordLen;
// 配置できる最小単語長。
extern int xg_nDictMinWordLen;
// 辞書ファイルを読み込む。
bool __fastcall XgLoadDictFile(LPCWSTR pszFile);
// テーマをリセットする。
void __fastcall XgResetTheme(HWND hwnd);
// テーマを設定する。
void XgSetThemeString(const XGStringW& strTheme);
// テーマ文字列をパースする。
void XgParseTheme(std::unordered_set<XGStringW>& priority,
std::unordered_set<XGStringW>& forbidden,
const XGStringW& strTheme);
// ミニ辞書を作成する。
std::vector<XG_WordData> XgCreateMiniDict(void);
//////////////////////////////////////////////////////////////////////////////
// XG_WordData構造体を比較するファンクタ。
class xg_word_less
{
public:
bool __fastcall operator()(const XG_WordData& wd1, const XG_WordData& wd2) noexcept
{
return wd1.m_word < wd2.m_word;
}
};
// 単語データが存在するか?
inline bool XgWordDataExists(const std::vector<XG_WordData>& data, const XG_WordData& wd)
{
return binary_search(data.begin(), data.end(), wd, xg_word_less());
}
struct XG_WordData_Equal
{
bool operator()(const XG_WordData wd1, const XG_WordData wd2) noexcept
{
return wd1.m_word == wd2.m_word;
}
};
// 辞書データをソートし、一意的にする。
void __fastcall XgSortAndUniqueDictData(std::vector<XG_WordData>& data);
//////////////////////////////////////////////////////////////////////////////
// 単語が長すぎるかどうかを確認するファンクタ。
class xg_word_toolong
{
public:
xg_word_toolong(int n) noexcept
{
m_n = n;
}
bool __fastcall operator()(const XG_WordData& wd) const noexcept
{
return static_cast<int>(wd.m_word.size()) > m_n;
}
protected:
int m_n; // 最大長。
};
//////////////////////////////////////////////////////////////////////////////
// 2文字未満の単語を削除する。
template <typename t_string>
inline bool XgTrimDict(std::unordered_set<t_string>& words)
{
for (auto& word : words) {
if (word.size() <= 1) {
words.erase(word);
}
}
return !words.empty();
}
template <typename t_string>
inline bool XgTrimDict(std::vector<t_string>& words)
{
auto it = std::remove_if(words.begin(), words.end(), [](const t_string& word) noexcept {
return (word.size() <= 1);
});
words.erase(it, words.end());
return !words.empty();
}
//////////////////////////////////////////////////////////////////////////////
// 辞書のエントリ。
struct XG_DICT
{
XGStringW m_filename; // ファイル名。
XGStringW m_friendly_name; // 親切な名前。
XG_DICT() noexcept
{
}
XG_DICT(const XGStringW& filename, const XGStringW& friendly_name)
: m_filename(filename)
, m_friendly_name(friendly_name)
{
}
};
// 現在の辞書名。
extern XGStringW xg_dict_name;
// すべての辞書ファイル。
typedef std::deque<XG_DICT> dicts_t;
extern dicts_t xg_dicts;
// 辞書名をセットする。
void XgSetDict(const XGStringW& strFile);
// フォルダから辞書群を読み込む。
BOOL XgLoadDictsFromDir(LPCWSTR pszDir);
// 辞書ファイルをすべて読み込む。
BOOL XgLoadDictsAll(void);
// 辞書を切り替える。
void XgSelectDict(HWND hwnd, size_t iDict);
// 辞書からタイトルを取得。
XGStringW XgLoadTitleFromDict(LPCWSTR pszPath);
// カギを使って辞書を更新する。
BOOL XgUpdateDictionaryUsingClues(HWND hwnd, const XGStringW& dict_name);