태그 선택 — 타입별로 자주 쓰는 것을 그 자리에 깐다
태그를 하나 걸려면 매번 모달을 열어 500여 개(액션 160여 개) 목록에서 찾아야 했다. 한 서식이 쓰는 서로 다른 태그는 중앙값 6개, 최대 27개다(--db-tags) — 서식 하나 만들 때마다 그 짓을 예닐곱 번 한다. ■ 실측이 설계를 정했다 --db-tags 진단을 신설해 운영 디자인 1,271건의 태그 사용 8,032건을 컨트롤 타입별로 집계했다. 후보가 타입마다 거의 완전히 갈린다: 이미지 · 데이터 태그 343건 / 7종 — 상위 16종이 100% (서명·직인·로고가 전부) 라디오 · 액션 태그 736건 / 7종 — 100% (RadCheckControl 이 580건) 체크박스 · 액션 태그 357건 / 7종 — 100% 텍스트박스 · 액션 태그 200건 / 6종 — 100% 마스크입력 · 데이터 태그 57건 / 13종 — 100% 버튼 · 액션 태그 393건 / 46종 — 상위 16종이 83% 텍스트박스 · 데이터 태그 5,927건 / 144종 — 상위 16종이 65% (여기만 꼬리가 길다) 즉 일곱 조합 중 다섯은 **짧은 목록이 운영 전체를 덮는다**. 이미지 하나 고르려고 500개를 뒤지고 있었다는 뜻이다. ■ 바꾼 것 · 인스펙터 행 아래에 그 타입에서 자주 쓰는 태그를 빈도순 칩으로 깐다(최대 8개). 누르면 바로 값이 된다. 칩은 **값이 비어 있을 때만** 뜬다 — 이미 정해진 행 아래에도 깔면 좁은 패널이 금방 길어진다. · 피커를 열면 자주 쓰는 것이 맨 위로 올라온다(그 안에서는 빈도순, 나머지는 원래 가나다순 유지). 건수 표시에 '자주 쓰는 것 N건이 위에' 를 덧붙였다. · 전체 카탈로그와 자유 입력은 그대로다. 제안은 제안이지 제한이 아니다 — 타입별 자료가 없는 조합의 액션 태그는 아예 비워 둔다. 추측으로 권하면 그 칸은 배포된 뒤에야 빈칸으로 드러난다. 순서를 가나다순이 아니라 빈도순으로 둔 것이 핵심이다. 가나다순은 운영의 절반을 차지하는 RadCheckControl 과 한 번도 안 쓰인 태그를 같은 무게로 보여 준다. ■ 곁다리로 확인한 것 카탈로그에 없는 값이 데이터 태그 1종(PAT_전체주소 ×11), 액션 태그 1종(OprEmrList ×5) 나왔다. 둘 다 레거시 bzDataInterface / EN_DataActionTyp 에 존재하지 않는다 — 우리 카탈로그가 맞고, 저 값들은 운영 서식에 이미 박힌 죽은 태그다(런타임이 해석하지 못한다). 우리가 만든 것이 아니라 손대지 않았다. 편집 스모크 17건 추가(타입별 좁힘 / 빈도 순서 / 자료 없는 타입은 빈 목록 / 제안이 전부 카탈로그에 있는지 12조합 검사 / 값이 정해지면 칩 감춤). 회귀: 테스트 142/142, 편집 스모크 210건 실패 0, DB 왕복 1,271건 diff 0/예외 0, 종이 렌더 P062 바이트 동일. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
ddf2bdaee8
commit
de01012b7e
@@ -0,0 +1,113 @@
|
||||
namespace SheetMe.Core.Catalog;
|
||||
|
||||
/// <summary>
|
||||
/// 태그 실사용 순위 — 컨트롤 타입별로 '실제로 쓰이는 태그'를 많이 쓰는 순서로 준다.
|
||||
///
|
||||
/// <b>왜 타입별인가.</b> 카탈로그는 데이터 태그 500여 종 · 액션 태그 160여 종인데,
|
||||
/// 어느 타입에서든 똑같은 전체 목록을 보여 주면 원하는 것을 찾는 데 시간이 걸린다.
|
||||
/// 실측(진단 <c>--db-tags</c>, 디자인 1,271건 / 태그 사용 8,032건)은 후보가 타입마다
|
||||
/// 거의 완전히 갈린다는 것을 보여 준다:
|
||||
/// <list type="bullet">
|
||||
/// <item>이미지(PictureBox)의 데이터 태그는 운영 전체에서 <b>7종이 전부</b>다 — 서명과 직인·로고.</item>
|
||||
/// <item>라디오·체크박스의 액션 태그도 각각 7종으로 100% 를 덮는다.</item>
|
||||
/// <item>텍스트박스만 꼬리가 길다(144종). 그래도 상위 16종이 65% 다.</item>
|
||||
/// </list>
|
||||
///
|
||||
/// <b>이 목록은 제안이지 제한이 아니다.</b> 전체 카탈로그는 피커에 그대로 남아 있고
|
||||
/// 자유 입력도 열려 있다. 여기 없는 태그를 쓰는 것은 언제나 가능하다.
|
||||
///
|
||||
/// 순서는 알파벳순이 아니라 <b>사용 빈도순</b>이다. 가나다순으로 늘어놓으면
|
||||
/// 가장 흔한 PAT_이름 과 거의 안 쓰는 태그가 같은 무게로 보인다.
|
||||
/// </summary>
|
||||
public static class LegacyTagUsageCatalog
|
||||
{
|
||||
#region Member Fields
|
||||
// 키: "{속성키}|{중립 타입명}". 값: 사용 빈도 내림차순.
|
||||
private static readonly Dictionary<string, string[]> byKeyAndType = new(StringComparer.Ordinal)
|
||||
{
|
||||
// ── 데이터 태그(자동 채움 원천) ──
|
||||
["DataInterfaceTag|TextBox"] = new[]
|
||||
{
|
||||
"PAT_이름", "PAT_차트번호", "ETC_요양기관명칭_병원명", "PAT_성별", "ETC_현재일자",
|
||||
"OCM_진단서의사명", "PAT_생년월일", "PAT_나이", "OCM_진료과", "PAT_주민번호_Dash",
|
||||
"ETC_로그인_사용자명", "PAT_휴대전화번호", "OCM_진단서의사면허번호", "ETC_요양기관기호",
|
||||
"OCM_담당의사", "PAT_도로명주소",
|
||||
},
|
||||
// 운영 343건이 이 7종뿐이다 — 서명란·직인·로고
|
||||
["DataInterfaceTag|PictureBox"] = new[]
|
||||
{
|
||||
"OCM_진단서의사싸인", "ETC_요양기관명칭_병원직인", "OCM_진단서의사싸인_Refer",
|
||||
"ETC_요양기관명칭_병원로고", "OCM_담당의사싸인", "OCM_로그인_사용자싸인",
|
||||
},
|
||||
// 마스크 입력은 날짜·시각이 사실상 전부다
|
||||
["DataInterfaceTag|MaskedTextBox"] = new[]
|
||||
{
|
||||
"ETC_현재일자", "ETC_현재일시_MaskBox", "OCM_입원내원일자", "OCM_퇴원일시",
|
||||
"OCM_외래내원일자", "PAT_주민번호", "ETC_현재일시", "OCM_입원일시",
|
||||
},
|
||||
|
||||
// ── 액션 태그(더블클릭/버튼 동작) ──
|
||||
// 라디오·체크박스는 각각 7종으로 운영 100% 를 덮는다
|
||||
["DataActionTag|RadioButton"] = new[]
|
||||
{
|
||||
"RadCheckControl", "ChoiceData", "PanelVisible", "UnAllCheck",
|
||||
"PanelUnVisible", "ButtonData", "SetVisibleStatus",
|
||||
},
|
||||
["DataActionTag|CheckBox"] = new[]
|
||||
{
|
||||
"RadCheckControl", "VisibleYon", "DataCopy_Chk", "MinusToPlus",
|
||||
"AllCheck", "ChoiceData", "DateVisibleYon",
|
||||
},
|
||||
["DataActionTag|TextBox"] = new[]
|
||||
{
|
||||
"DtrLicList", "UmlsMst", "ReturnUidNam", "YondoList", "OkdInfList",
|
||||
},
|
||||
// 버튼은 검색 계열이라 꼬리가 있다(46종) — 상위 16종이 83%
|
||||
["DataActionTag|Button"] = new[]
|
||||
{
|
||||
"ComOkdList", "ImgeList", "CodeFInd", "OkdInfList", "OprInfList",
|
||||
"OkdInfData", "EmrSelectData", "YondoList", "TPRList", "ComPidList",
|
||||
"TPR", "AllCheck", "ReturnLabData", "EmgTotalEmr", "DataCopy_MtM", "DtrLicList",
|
||||
},
|
||||
};
|
||||
|
||||
// 타입 구분 없이 흔한 데이터 태그 — 위 표에 타입이 없을 때의 폴백(예: 콤보·날짜선택)
|
||||
private static readonly string[] CommonDataTags =
|
||||
{
|
||||
"PAT_이름", "PAT_차트번호", "PAT_성별", "PAT_생년월일", "PAT_나이",
|
||||
"ETC_현재일자", "OCM_진료과", "OCM_담당의사",
|
||||
};
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
/// <summary>
|
||||
/// 이 컨트롤 타입에서 자주 쓰이는 태그 — 빈도 내림차순.
|
||||
/// 타입별 자료가 없으면 데이터 태그는 공통 목록, 액션 태그는 빈 목록(추측하지 않는다).
|
||||
/// </summary>
|
||||
public static IReadOnlyList<string> SuggestFor(string propertyKey, string controlType)
|
||||
{
|
||||
if (byKeyAndType.TryGetValue(propertyKey + "|" + controlType, out var ranked))
|
||||
{
|
||||
return ranked;
|
||||
}
|
||||
return propertyKey == "DataInterfaceTag" ? CommonDataTags : Array.Empty<string>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 피커 목록 정렬용 순위 — 낮을수록 위. 실사용 자료에 없으면 int.MaxValue.
|
||||
/// 가나다순으로만 늘어놓으면 가장 흔한 태그와 거의 안 쓰는 태그가 같은 무게로 보인다.
|
||||
/// </summary>
|
||||
public static int RankOf(string propertyKey, string controlType, string tag)
|
||||
{
|
||||
var ranked = SuggestFor(propertyKey, controlType);
|
||||
for (var i = 0; i < ranked.Count; i++)
|
||||
{
|
||||
if (string.Equals(ranked[i], tag, StringComparison.Ordinal))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return int.MaxValue;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
Reference in New Issue
Block a user