Skip to content

Commit 2196db3

Browse files
committed
improve hidden features
1 parent d09b580 commit 2196db3

9 files changed

+212
-21
lines changed

GUI.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -7078,7 +7078,10 @@ void __fastcall MainWnd_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT /*codeNo
70787078
if (dialog.DoModal(hwnd) != IDOK)
70797079
break;
70807080

7081-
if (XgPatEdit(hwnd, dialog.s_bAdd)) {
7081+
if (dialog.s_nType == XG_PatEditDialog::TYPE_SHOWINFO)
7082+
break;
7083+
7084+
if (XgPatEdit(hwnd, dialog.s_nType == XG_PatEditDialog::TYPE_ADD)) {
70827085
// 成功メッセージ。
70837086
XgCenterMessageBoxW(hwnd, XgLoadStringDx1(IDS_WROTEPAT),
70847087
XgLoadStringDx2(IDS_APPNAME), MB_ICONINFORMATION);

HISTORY.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@
267267
- Supported TIFF images.
268268
- Improved Input Palette.
269269
- 2024-XX-YY ver.5.1.7
270-
- Added trick "Ctrl+Alt+Shift+Q".
270+
- Added hidden features "Ctrl+Alt+Shift+Q".
271271
- Added UTF-8 BOM to PAT.txt.
272272
- Added "Choose a pattern from &PAT.txt automatically" feature to "Generate Crossword".
273273

@@ -852,6 +852,6 @@
852852
- TIFF画像のサポート。
853853
- 入力パレットの改良。
854854
- 2024年XX月YY日 ver.5.1.7
855-
- 裏技「Ctrl+Alt+Shift+Q」を追加。
855+
- 隠し機能「Ctrl+Alt+Shift+Q」を追加。
856856
- PAT.txtにUTF-8 BOMを付けるようにした。
857857
- 「問題の作成」に「PAT.txtから黒マスパターンを自動的に選ぶ」機能を追加。

XG_PatEditDialog.hpp

+37-9
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,18 @@
22

33
#include "XG_Window.hpp"
44

5+
void XgShowPatInfo(HWND hwndInfo);
6+
57
// 「パターン編集」ダイアログ。
68
class XG_PatEditDialog : public XG_Dialog
79
{
810
public:
9-
static inline BOOL s_bAdd = TRUE;
11+
enum TYPE {
12+
TYPE_ADD,
13+
TYPE_DELETE,
14+
TYPE_SHOWINFO
15+
};
16+
static inline TYPE s_nType = TYPE_ADD;
1017
static inline HBITMAP s_hbm = NULL;
1118

1219
XG_PatEditDialog() noexcept
@@ -21,11 +28,19 @@ class XG_PatEditDialog : public XG_Dialog
2128
HWND hCmb1 = ::GetDlgItem(hwnd, cmb1);
2229
ComboBox_AddString(hCmb1, XgLoadStringDx1(IDS_ADD));
2330
ComboBox_AddString(hCmb1, XgLoadStringDx1(IDS_DELETE));
31+
ComboBox_AddString(hCmb1, XgLoadStringDx1(IDS_SHOWINFO));
2432

25-
if (s_bAdd)
33+
switch (s_nType) {
34+
case TYPE_ADD:
2635
ComboBox_SetCurSel(hCmb1, 0);
27-
else
36+
break;
37+
case TYPE_DELETE:
2838
ComboBox_SetCurSel(hCmb1, 1);
39+
break;
40+
case TYPE_SHOWINFO:
41+
ComboBox_SetCurSel(hCmb1, 2);
42+
break;
43+
}
2944

3045
OnCmb1(hwnd);
3146

@@ -41,18 +56,30 @@ class XG_PatEditDialog : public XG_Dialog
4156
switch (iItem)
4257
{
4358
case 0:
59+
::ShowWindow(::GetDlgItem(m_hWnd, edt1), SW_HIDE);
60+
::ShowWindow(::GetDlgItem(m_hWnd, stc1), SW_SHOWNOACTIVATE);
4461
hbm = ::LoadBitmapW(xg_hInstance, MAKEINTRESOURCEW(IDB_ADDPAT));
62+
::DeleteObject(s_hbm);
63+
s_hbm = hbm;
64+
SendDlgItemMessageW(m_hWnd, stc1, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)s_hbm);
4565
break;
4666
case 1:
67+
::ShowWindow(::GetDlgItem(m_hWnd, edt1), SW_HIDE);
68+
::ShowWindow(::GetDlgItem(m_hWnd, stc1), SW_SHOWNOACTIVATE);
4769
hbm = ::LoadBitmapW(xg_hInstance, MAKEINTRESOURCEW(IDB_DELETEPAT));
70+
::DeleteObject(s_hbm);
71+
s_hbm = hbm;
72+
SendDlgItemMessageW(m_hWnd, stc1, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)s_hbm);
73+
break;
74+
case 2:
75+
::ShowWindow(::GetDlgItem(m_hWnd, edt1), SW_SHOWNOACTIVATE);
76+
::ShowWindow(::GetDlgItem(m_hWnd, stc1), SW_HIDE);
77+
XgShowPatInfo(::GetDlgItem(m_hWnd, edt1));
4878
break;
4979
default:
5080
break;
5181
}
5282

53-
::DeleteObject(s_hbm);
54-
s_hbm = hbm;
55-
SendDlgItemMessageW(m_hWnd, stc1, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)s_hbm);
5683
}
5784

5885
void OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
@@ -63,15 +90,16 @@ class XG_PatEditDialog : public XG_Dialog
6390
case IDCANCEL:
6491
{
6592
HWND hCmb1 = ::GetDlgItem(hwnd, cmb1);
66-
INT iItem = ComboBox_GetCurSel(hCmb1);
67-
s_bAdd = (iItem == 0);
93+
s_nType = (TYPE)ComboBox_GetCurSel(hCmb1);
6894
::DeleteObject(s_hbm);
6995
s_hbm = NULL;
7096
::EndDialog(hwnd, id);
7197
}
7298
break;
7399
case cmb1:
74-
OnCmb1(hwnd);
100+
if (codeNotify == CBN_SELCHANGE) {
101+
OnCmb1(hwnd);
102+
}
75103
break;
76104
}
77105
}

XG_PatternDialog.hpp

-3
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,6 @@ bool __fastcall XgOnSolve_NoAddBlack(HWND hwnd, bool bShowAnswer = true);
1111
// 解を求める(黒マス追加なし)。結果を表示しない。
1212
bool __fastcall XgOnSolve_NoAddBlackNoResults(HWND hwnd, bool bShowAnswer = true);
1313

14-
// パターンデータを読み込む。
15-
BOOL XgLoadPatterns(LPCWSTR pszFileName, patterns_t& patterns, std::wstring *pComments = nullptr);
16-
1714
#define XG_MAX_PAT_SIZE1 20
1815
#define XG_MAX_PAT_SIZE2 30
1916
#define XG_MAX_PAT_SIZE3 45

XWordGiver.cpp

+138
Original file line numberDiff line numberDiff line change
@@ -7956,3 +7956,141 @@ bool __fastcall XgIsAnyThreadTerminated(void) noexcept
79567956
}
79577957
return false;
79587958
}
7959+
7960+
// パターンの統計情報を表示。
7961+
void XgShowPatInfo(HWND hwndInfo)
7962+
{
7963+
std::wstring text;
7964+
7965+
// 使用文字の頻度分布。
7966+
{
7967+
std::map<WCHAR, DWORD> ch2num;
7968+
{
7969+
const XG_Board *xw = (xg_bSolved ? &xg_solution : &xg_xword);
7970+
for (int i = 0; i < xg_nRows; i++) {
7971+
for (int j = 0; j < xg_nCols; j++) {
7972+
auto ch = xw->GetAt(i, j);
7973+
ch2num[ch] += 1;
7974+
}
7975+
}
7976+
}
7977+
std::vector<std::pair<DWORD, DWORD>> pairs;
7978+
for (auto& pair : ch2num) {
7979+
pairs.push_back(pair);
7980+
}
7981+
std::sort(pairs.begin(), pairs.end(), [](auto& a, auto& b){
7982+
return a.second > b.second;
7983+
});
7984+
text += L"\r\n";
7985+
text += L"[[ ";
7986+
text += XgLoadStringDx1(IDS_CHARUSAGEDIST);
7987+
text += L" ]]";
7988+
text += L"\r\n";
7989+
for (auto& pair : pairs) {
7990+
text += (WCHAR)0x3010; //
7991+
text += pair.first;
7992+
text += (WCHAR)0x3011; //
7993+
text += L" : ";
7994+
text += std::to_wstring(pair.second);
7995+
text += L"\r\n";
7996+
}
7997+
}
7998+
7999+
// 単語の長さの頻度分布。
8000+
if (xg_bSolved) {
8001+
std::map<WCHAR, DWORD> len2num;
8002+
std::vector<XG_WordData> dict = XgCreateMiniDict();
8003+
for (auto& data : dict) {
8004+
len2num[(DWORD)data.m_word.size()] += 1;
8005+
}
8006+
std::vector<std::pair<WCHAR, DWORD>> pairs;
8007+
for (auto& pair : len2num) {
8008+
pairs.push_back(pair);
8009+
}
8010+
std::sort(pairs.begin(), pairs.end(), [](auto& a, auto& b){
8011+
return a.second > b.second;
8012+
});
8013+
text += L"\r\n";
8014+
text += L"[[ ";
8015+
text += XgLoadStringDx1(IDS_WORDLENDIST);
8016+
text += L" ]]";
8017+
text += L"\r\n";
8018+
for (auto& pair : pairs) {
8019+
text += std::to_wstring(pair.first);
8020+
text += L" : ";
8021+
text += std::to_wstring(pair.second);
8022+
text += L"\r\n";
8023+
}
8024+
}
8025+
8026+
// ヒントの長さ。
8027+
if (xg_bSolved) {
8028+
std::vector<XG_WordData> dict = XgCreateMiniDict();
8029+
size_t count = dict.size();
8030+
size_t sum = 0, min = 999999, max = 0;
8031+
for (auto& data : dict) {
8032+
auto len = data.m_hint.size();
8033+
if (min > len)
8034+
min = len;
8035+
if (max < len)
8036+
max = len;
8037+
sum += data.m_hint.size();
8038+
}
8039+
text += L"\r\n";
8040+
text += L"[[ ";
8041+
text += XgLoadStringDx1(IDS_HINTLENAVG); // 平均値。
8042+
text += L" ]]";
8043+
text += L": ";
8044+
text += std::to_wstring(sum / (double)count);
8045+
text += L"\r\n";
8046+
text += L"[[ ";
8047+
text += XgLoadStringDx1(IDS_HINTLENMIN); // 最小値。
8048+
text += L" ]]";
8049+
text += L": ";
8050+
text += std::to_wstring(min);
8051+
text += L"\r\n";
8052+
text += L"[[ ";
8053+
text += XgLoadStringDx1(IDS_HINTLENMAX); // 最大値。
8054+
text += L" ]]";
8055+
text += L": ";
8056+
text += std::to_wstring(max);
8057+
text += L"\r\n";
8058+
}
8059+
8060+
// パターンの頻度分布。
8061+
{
8062+
// パターンを読み込む。
8063+
patterns_t patterns;
8064+
WCHAR szPath[MAX_PATH];
8065+
XgFindLocalFile(szPath, _countof(szPath), L"PAT.txt");
8066+
if (!XgLoadPatterns(szPath, patterns)) {
8067+
::SetWindowTextW(hwndInfo, NULL);
8068+
return;
8069+
}
8070+
8071+
// ソートして一意化する。
8072+
XgSortAndUniquePatterns(patterns, TRUE);
8073+
8074+
std::map<DWORD, DWORD> size2num;
8075+
for (const auto& pat : patterns) {
8076+
size2num[MAKELONG(pat.num_rows, pat.num_columns)] += 1;
8077+
}
8078+
text += L"\r\n";
8079+
text += L"[[ ";
8080+
text += XgLoadStringDx1(IDS_PATSIZEDIST);
8081+
text += L" ]]";
8082+
text += L"\r\n";
8083+
for (auto& pair : size2num) {
8084+
size_t num_columns = HIWORD(pair.first);
8085+
size_t num_rows = LOWORD(pair.first);
8086+
text += std::to_wstring(num_columns);
8087+
text += L" x ";
8088+
text += std::to_wstring(num_rows);
8089+
text += L" : ";
8090+
text += std::to_wstring(pair.second);
8091+
text += L"\r\n";
8092+
}
8093+
}
8094+
8095+
::SetWindowTextW(hwndInfo, text.c_str());
8096+
}

XWordGiver.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -1505,6 +1505,8 @@ BOOL XgSavePatterns(LPCWSTR pszFileName, const patterns_t& patterns,
15051505
const std::wstring *pComments = nullptr);
15061506
// パターン編集。
15071507
BOOL XgPatEdit(HWND hwnd, BOOL bAdd);
1508+
// パターンデータを読み込む。
1509+
BOOL XgLoadPatterns(LPCWSTR pszFileName, patterns_t& patterns, std::wstring *pComments = nullptr);
15081510

15091511
//////////////////////////////////////////////////////////////////////////////
15101512
// ボックス。

lang/en_US.rc

+11-3
Original file line numberDiff line numberDiff line change
@@ -1515,13 +1515,14 @@ FONT 9, "Tahoma"
15151515
}
15161516

15171517
IDD_ADDDELETEPAT DIALOG 0, 0, 325, 240
1518-
CAPTION "Pattern Edit"
1518+
CAPTION "Hidden features of XWordGiver"
15191519
STYLE DS_CENTER | DS_MODALFRAME | WS_POPUPWINDOW | WS_CAPTION
15201520
FONT 9, "Tahoma"
15211521
{
15221522
RTEXT "&Operation:", -1, 10, 10, 55, 10, SS_CENTERIMAGE | NOT WS_GROUP
15231523
COMBOBOX cmb1, 75, 10, 75, 300, CBS_HASSTRINGS | CBS_AUTOHSCROLL | CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
15241524
CONTROL "", stc1, "STATIC", SS_CENTERIMAGE | SS_BITMAP | WS_GROUP, 10, 30, 305, 185
1525+
EDITTEXT edt1, 20, 40, 280, 165, ES_READONLY | ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE | WS_VSCROLL | WS_HSCROLL | NOT WS_VISIBLE
15251526
DEFPUSHBUTTON "OK", IDOK, 190, 220, 60, 15
15261527
PUSHBUTTON "Cancel", IDCANCEL, 255, 220, 60, 15
15271528
}
@@ -1742,11 +1743,18 @@ STRINGTABLE
17421743
IDS_POLICYPRESET_JPN_LOOSE_3, "0x011B: Japanese publisher policy (Loose): Horizontal symmetry"
17431744
IDS_MARKINGTYPE, "Error: There is a missing character '%c' on the board."
17441745
IDS_MARKINGEMPTY, "Enter a word or choose from the suggestions below:"
1745-
IDS_ADD, "Add"
1746-
IDS_DELETE, "Delete"
1746+
IDS_ADD, "Add Pattern"
1747+
IDS_DELETE, "Delete Pattern"
17471748
IDS_CANTWRITEPAT, "Failed to write PAT.txt. Sorry."
17481749
IDS_WROTEPAT, "Success! PAT.txt has been written."
17491750
IDS_NOMATCHPAT, "No matching pattern in ""PAT.txt""."
1751+
IDS_SHOWINFO, "Show Info"
1752+
IDS_PATSIZEDIST, "The distribution of PAT.txt pattern sizes"
1753+
IDS_CHARUSAGEDIST, "The distribution of board character usage"
1754+
IDS_WORDLENDIST, "The distribution of board word length"
1755+
IDS_HINTLENAVG, "Clue length average"
1756+
IDS_HINTLENMIN, "Clue length min."
1757+
IDS_HINTLENMAX, "Clue length max."
17501758
IDS_TT_NEW, "New crossword"
17511759
IDS_TT_GENERATE, "Generate crossword"
17521760
IDS_TT_OPEN, "Open crossword"

lang/ja_JP.rc

+11-3
Original file line numberDiff line numberDiff line change
@@ -1518,13 +1518,14 @@ FONT 9, "MS UI Gothic"
15181518
}
15191519

15201520
IDD_ADDDELETEPAT DIALOG 0, 0, 325, 240
1521-
CAPTION "パターン編集"
1521+
CAPTION "クロスワード ギバーの隠し機能"
15221522
STYLE DS_CENTER | DS_MODALFRAME | WS_POPUPWINDOW | WS_CAPTION
15231523
FONT 9, "MS UI Gothic"
15241524
{
15251525
RTEXT "処理(&O):", -1, 10, 10, 55, 10, SS_CENTERIMAGE | NOT WS_GROUP
15261526
COMBOBOX cmb1, 75, 10, 75, 300, CBS_HASSTRINGS | CBS_AUTOHSCROLL | CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
15271527
CONTROL "", stc1, "STATIC", SS_CENTERIMAGE | SS_BITMAP | WS_GROUP, 10, 30, 305, 185
1528+
EDITTEXT edt1, 20, 40, 280, 165, ES_READONLY | ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE | WS_VSCROLL | WS_HSCROLL | NOT WS_VISIBLE
15281529
DEFPUSHBUTTON "OK", IDOK, 190, 220, 60, 15
15291530
PUSHBUTTON "キャンセル", IDCANCEL, 255, 220, 60, 15
15301531
}
@@ -1745,11 +1746,18 @@ STRINGTABLE
17451746
IDS_POLICYPRESET_JPN_LOOSE_3, "0x011B: 日本の出版社ルール (ゆるい): 左右対称"
17461747
IDS_MARKINGTYPE, "エラー: 盤面に足りない文字「%c」があります。"
17471748
IDS_MARKINGEMPTY, "単語を入力、または下の候補から選択して下さい:"
1748-
IDS_ADD, "追加"
1749-
IDS_DELETE, "削除"
1749+
IDS_ADD, "パターンの追加"
1750+
IDS_DELETE, "パターンの削除"
17501751
IDS_CANTWRITEPAT, "失敗。PAT.txtの書き込みに失敗しました。書き込めないフォルダの可能性があります。"
17511752
IDS_WROTEPAT, "PAT.txt の書き込みに成功しました。"
17521753
IDS_NOMATCHPAT, "対応するパターンがPAT.txtにありません。"
1754+
IDS_SHOWINFO, "情報の表示"
1755+
IDS_PATSIZEDIST, "PAT.txtのパターンサイズの頻度分布"
1756+
IDS_CHARUSAGEDIST, "盤面の使用文字の頻度分布"
1757+
IDS_WORDLENDIST, "盤面の単語の長さの頻度分布"
1758+
IDS_HINTLENAVG, "ヒントの長さの平均値"
1759+
IDS_HINTLENMIN, "ヒントの長さの最小値"
1760+
IDS_HINTLENMAX, "ヒントの長さの最大値"
17531761
IDS_TT_NEW, "新規作成"
17541762
IDS_TT_GENERATE, "問題を自動生成する"
17551763
IDS_TT_OPEN, "問題を開く"

resource.h

+7
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,13 @@
227227
#define IDS_CANTWRITEPAT 307
228228
#define IDS_WROTEPAT 308
229229
#define IDS_NOMATCHPAT 309
230+
#define IDS_SHOWINFO 310
231+
#define IDS_PATSIZEDIST 311
232+
#define IDS_CHARUSAGEDIST 312
233+
#define IDS_WORDLENDIST 313
234+
#define IDS_HINTLENAVG 314
235+
#define IDS_HINTLENMIN 315
236+
#define IDS_HINTLENMAX 316
230237
#define IDS_TT_NEW 10100
231238
#define IDS_TT_GENERATE 10101
232239
#define IDS_TT_OPEN 10102

0 commit comments

Comments
 (0)