fix: resolve I1 date parsing regression and implement strict volume cross-checking gate
This commit is contained in:
@@ -106,9 +106,12 @@ export default function PublicationCategoryPage({ params }: PageProps) {
|
|||||||
<h3 className="font-serif text-xl font-normal text-ink leading-snug">
|
<h3 className="font-serif text-xl font-normal text-ink leading-snug">
|
||||||
{rec.title}
|
{rec.title}
|
||||||
</h3>
|
</h3>
|
||||||
<span className="font-mono text-xs text-vermillion bg-ivory border border-line px-2.5 py-1 rounded shrink-0 font-bold">
|
<time
|
||||||
|
dateTime={rec.publishedAt}
|
||||||
|
className="font-mono text-xs text-vermillion bg-ivory border border-line px-2.5 py-1 rounded shrink-0 font-bold"
|
||||||
|
>
|
||||||
{rec.publishedAt}
|
{rec.publishedAt}
|
||||||
</span>
|
</time>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{rec.isPatent ? (
|
{rec.isPatent ? (
|
||||||
|
|||||||
@@ -117,9 +117,12 @@ export default function PublicationsIndexPage() {
|
|||||||
<h3 className="font-serif text-lg font-normal text-ink leading-snug">
|
<h3 className="font-serif text-lg font-normal text-ink leading-snug">
|
||||||
{rec.title}
|
{rec.title}
|
||||||
</h3>
|
</h3>
|
||||||
<span className="font-mono text-xs text-vermillion bg-ivory border border-line px-2 py-0.5 rounded shrink-0">
|
<time
|
||||||
|
dateTime={rec.publishedAt}
|
||||||
|
className="font-mono text-xs text-vermillion bg-ivory border border-line px-2 py-0.5 rounded shrink-0"
|
||||||
|
>
|
||||||
{rec.publishedAt}
|
{rec.publishedAt}
|
||||||
</span>
|
</time>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-xs text-ink-mute font-mono">
|
<div className="text-xs text-ink-mute font-mono">
|
||||||
{rec.venue}
|
{rec.venue}
|
||||||
|
|||||||
@@ -7,14 +7,14 @@ export const publications: Publication[] = [
|
|||||||
"title": "Globally Integrated Trust Authority (GITA) for Resource-Constrained Edge Devices in IoT and 6G",
|
"title": "Globally Integrated Trust Authority (GITA) for Resource-Constrained Edge Devices in IoT and 6G",
|
||||||
"venue": "IEEE Transactions on Network and Service Management",
|
"venue": "IEEE Transactions on Network and Service Management",
|
||||||
"volume": "Vol. 23, pp. 4490~4505, April 2026",
|
"volume": "Vol. 23, pp. 4490~4505, April 2026",
|
||||||
"publishedAt": "4490"
|
"publishedAt": "2026-04"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"category": "intl-journal-conf",
|
"category": "intl-journal-conf",
|
||||||
"title": "Application Level Trust Authority (APPLETA) for Resource-Constrained Edge Devices in IoT and 6G",
|
"title": "Application Level Trust Authority (APPLETA) for Resource-Constrained Edge Devices in IoT and 6G",
|
||||||
"venue": "IEEE Transactions on Consumer Electronics",
|
"venue": "IEEE Transactions on Consumer Electronics",
|
||||||
"volume": "Vol. 71, No. 2, pp. 4934~4948, May 2025",
|
"volume": "Vol. 71, No. 2, pp. 4934~4948, May 2025",
|
||||||
"publishedAt": "4934"
|
"publishedAt": "2025-05"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"category": "intl-journal-conf",
|
"category": "intl-journal-conf",
|
||||||
@@ -35,21 +35,21 @@ export const publications: Publication[] = [
|
|||||||
"title": "Use of QUIC for Mobile-Oriented Future Internet (Q-MOFI)",
|
"title": "Use of QUIC for Mobile-Oriented Future Internet (Q-MOFI)",
|
||||||
"venue": "Electronics",
|
"venue": "Electronics",
|
||||||
"volume": "Vol. 13, Article No. 13020431, pp. 1~20, January 2024",
|
"volume": "Vol. 13, Article No. 13020431, pp. 1~20, January 2024",
|
||||||
"publishedAt": "1302-04-31"
|
"publishedAt": "2024-01"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"category": "intl-journal-conf",
|
"category": "intl-journal-conf",
|
||||||
"title": "Use of QUIC for CoAP Transport in IoT Networks",
|
"title": "Use of QUIC for CoAP Transport in IoT Networks",
|
||||||
"venue": "Internet of Things (ISSN: 2543-1536)",
|
"venue": "Internet of Things (ISSN: 2543-1536)",
|
||||||
"volume": "Vol. 24, pp. 1~16, Article No. 100905, December 2023",
|
"volume": "Vol. 24, pp. 1~16, Article No. 100905, December 2023",
|
||||||
"publishedAt": "1009-00-05"
|
"publishedAt": "2023-12"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"category": "intl-journal-conf",
|
"category": "intl-journal-conf",
|
||||||
"title": "Adaptive Control of Congestion Window in QUIC",
|
"title": "Adaptive Control of Congestion Window in QUIC",
|
||||||
"venue": "International Conference on ICTC",
|
"venue": "International Conference on ICTC",
|
||||||
"volume": "pp. 1394~1396, October 2023",
|
"volume": "pp. 1394~1396, October 2023",
|
||||||
"publishedAt": "1394"
|
"publishedAt": "2023-10"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"category": "intl-journal-conf",
|
"category": "intl-journal-conf",
|
||||||
@@ -63,91 +63,91 @@ export const publications: Publication[] = [
|
|||||||
"title": "Use of QUIC for AMQP in IoT networks",
|
"title": "Use of QUIC for AMQP in IoT networks",
|
||||||
"venue": "Computer Networks",
|
"venue": "Computer Networks",
|
||||||
"volume": "Vol. 225, Article No. 109640, pp. 1~10, April 2023",
|
"volume": "Vol. 225, Article No. 109640, pp. 1~10, April 2023",
|
||||||
"publishedAt": "1096-04-00"
|
"publishedAt": "2023-04"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"category": "intl-journal-conf",
|
"category": "intl-journal-conf",
|
||||||
"title": "Zero Energy IoT Devices in Smart Cities Using RF Energy Harvesting",
|
"title": "Zero Energy IoT Devices in Smart Cities Using RF Energy Harvesting",
|
||||||
"venue": "Electronics",
|
"venue": "Electronics",
|
||||||
"volume": "Vol. 12, Article No. 12010148, pp. 1~24, January 2023",
|
"volume": "Vol. 12, Article No. 12010148, pp. 1~24, January 2023",
|
||||||
"publishedAt": "1201-01"
|
"publishedAt": "2023-01"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"category": "intl-journal-conf",
|
"category": "intl-journal-conf",
|
||||||
"title": "Image Forensics Using Non-Reducing Convolutional Neural Network for Consecutive Dual Operators",
|
"title": "Image Forensics Using Non-Reducing Convolutional Neural Network for Consecutive Dual Operators",
|
||||||
"venue": "Applied Sciences",
|
"venue": "Applied Sciences",
|
||||||
"volume": "Vol. 12, Article No. 12147152, pp. 1~18, July 2022",
|
"volume": "Vol. 12, Article No. 12147152, pp. 1~18, July 2022",
|
||||||
"publishedAt": "1214"
|
"publishedAt": "2022-07"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"category": "intl-journal-conf",
|
"category": "intl-journal-conf",
|
||||||
"title": "6LoWPAN over Optical Wireless Communications for IPv6 Transport in Internet of Things Networks",
|
"title": "6LoWPAN over Optical Wireless Communications for IPv6 Transport in Internet of Things Networks",
|
||||||
"venue": "IEEE Wireless Communications Letters",
|
"venue": "IEEE Wireless Communications Letters",
|
||||||
"volume": "Vol. 11, No. 6, pp. 1142~1145, June 2022",
|
"volume": "Vol. 11, No. 6, pp. 1142~1145, June 2022",
|
||||||
"publishedAt": "1142"
|
"publishedAt": "2022-06"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"category": "intl-journal-conf",
|
"category": "intl-journal-conf",
|
||||||
"title": "AEDCN-Net: Accurate and Efficient Deep Convolutional Neural Network Model for Medical Image Segmentation",
|
"title": "AEDCN-Net: Accurate and Efficient Deep Convolutional Neural Network Model for Medical Image Segmentation",
|
||||||
"venue": "IEEE Access",
|
"venue": "IEEE Access",
|
||||||
"volume": "Vol. 9, pp. 154194~154203, November 2021",
|
"volume": "Vol. 9, pp. 154194~154203, November 2021",
|
||||||
"publishedAt": "1541-09-04"
|
"publishedAt": "2021-11"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"category": "intl-journal-conf",
|
"category": "intl-journal-conf",
|
||||||
"title": "Proxy-based Adaptive Transmission of MP-QUIC in Internet-of-Things Environment",
|
"title": "Proxy-based Adaptive Transmission of MP-QUIC in Internet-of-Things Environment",
|
||||||
"venue": "Electronics",
|
"venue": "Electronics",
|
||||||
"volume": "Vol. 10, Article No. 10172175, pp. 1~14, September 2021",
|
"volume": "Vol. 10, Article No. 10172175, pp. 1~14, September 2021",
|
||||||
"publishedAt": "1017"
|
"publishedAt": "2021-09"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"category": "intl-journal-conf",
|
"category": "intl-journal-conf",
|
||||||
"title": "Digital Certificate Verification Scheme for Smart Grid Using Fog Computing (FONICA)",
|
"title": "Digital Certificate Verification Scheme for Smart Grid Using Fog Computing (FONICA)",
|
||||||
"venue": "Sustainability",
|
"venue": "Sustainability",
|
||||||
"volume": "Vol. 13, Article No. 13052549, pp. 1~19, February 2021",
|
"volume": "Vol. 13, Article No. 13052549, pp. 1~19, February 2021",
|
||||||
"publishedAt": "1305"
|
"publishedAt": "2021-02"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"category": "intl-journal-conf",
|
"category": "intl-journal-conf",
|
||||||
"title": "Framework of IoT Services over Unidirectional Visible Lights Communication Networks",
|
"title": "Framework of IoT Services over Unidirectional Visible Lights Communication Networks",
|
||||||
"venue": "Electronics",
|
"venue": "Electronics",
|
||||||
"volume": "Vol. 9, Article No. 9091349, pp. 1~22, September 2020",
|
"volume": "Vol. 9, Article No. 9091349, pp. 1~22, September 2020",
|
||||||
"publishedAt": "9091"
|
"publishedAt": "2020-09"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"category": "intl-journal-conf",
|
"category": "intl-journal-conf",
|
||||||
"title": "CoAP-based Streaming Control for IoT Applications",
|
"title": "CoAP-based Streaming Control for IoT Applications",
|
||||||
"venue": "Electronics",
|
"venue": "Electronics",
|
||||||
"volume": "Vol. 9, Article No. 9081320, pp. 1~19, August 2020",
|
"volume": "Vol. 9, Article No. 9081320, pp. 1~19, August 2020",
|
||||||
"publishedAt": "9081"
|
"publishedAt": "2020-08"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"category": "intl-journal-conf",
|
"category": "intl-journal-conf",
|
||||||
"title": "Agent-based In-Vehicle Infotainment Services in Internet-of-Things Environments",
|
"title": "Agent-based In-Vehicle Infotainment Services in Internet-of-Things Environments",
|
||||||
"venue": "Electronics",
|
"venue": "Electronics",
|
||||||
"volume": "Vol. 9, Article No. 9081288, pp. 1~22, August 2020",
|
"volume": "Vol. 9, Article No. 9081288, pp. 1~22, August 2020",
|
||||||
"publishedAt": "9081"
|
"publishedAt": "2020-08"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"category": "intl-journal-conf",
|
"category": "intl-journal-conf",
|
||||||
"title": "Partial Bicasting with Buffering for Proxy Mobile IPv6 Mobility Management in CoAP-Based IoT Networks",
|
"title": "Partial Bicasting with Buffering for Proxy Mobile IPv6 Mobility Management in CoAP-Based IoT Networks",
|
||||||
"venue": "Electronics",
|
"venue": "Electronics",
|
||||||
"volume": "Vol. 9, Article No. 9040598, pp. 1~13, April 2020",
|
"volume": "Vol. 9, Article No. 9040598, pp. 1~13, April 2020",
|
||||||
"publishedAt": "9040"
|
"publishedAt": "2020-04"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"category": "intl-journal-conf",
|
"category": "intl-journal-conf",
|
||||||
"title": "Distributed Identifier-Locator Mapping Management in Mobile ILNP Networks",
|
"title": "Distributed Identifier-Locator Mapping Management in Mobile ILNP Networks",
|
||||||
"venue": "Electronics",
|
"venue": "Electronics",
|
||||||
"volume": "Vol. 9, Article No. 9010058, pp. 1~26, January 2020",
|
"volume": "Vol. 9, Article No. 9010058, pp. 1~26, January 2020",
|
||||||
"publishedAt": "9010-05-08"
|
"publishedAt": "2020-01"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"category": "intl-journal-conf",
|
"category": "intl-journal-conf",
|
||||||
"title": "Mobile-Oriented Future Internet: Implementation and Experimentations over EU-Korea Testbed",
|
"title": "Mobile-Oriented Future Internet: Implementation and Experimentations over EU-Korea Testbed",
|
||||||
"venue": "Electronics",
|
"venue": "Electronics",
|
||||||
"volume": "Vol. 8, Article No. 8030338, pp. 1~24, March 2019",
|
"volume": "Vol. 8, Article No. 8030338, pp. 1~24, March 2019",
|
||||||
"publishedAt": "8030"
|
"publishedAt": "2019-03"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"category": "intl-journal-conf",
|
"category": "intl-journal-conf",
|
||||||
@@ -182,7 +182,7 @@ export const publications: Publication[] = [
|
|||||||
"title": "Device Management and Data Transport in IoT Networks Based on Visible Light Communication",
|
"title": "Device Management and Data Transport in IoT Networks Based on Visible Light Communication",
|
||||||
"venue": "Sensors",
|
"venue": "Sensors",
|
||||||
"volume": "Vol. 18, Article No. s18082741, August 2018",
|
"volume": "Vol. 18, Article No. s18082741, August 2018",
|
||||||
"publishedAt": "1808"
|
"publishedAt": "2018-08"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"category": "intl-journal-conf",
|
"category": "intl-journal-conf",
|
||||||
@@ -217,7 +217,7 @@ export const publications: Publication[] = [
|
|||||||
"title": "Use of Proxy Mobile IPv6 for Mobility Management in CoAP-based IoT Networks",
|
"title": "Use of Proxy Mobile IPv6 for Mobility Management in CoAP-based IoT Networks",
|
||||||
"venue": "IEEE Communications Letters",
|
"venue": "IEEE Communications Letters",
|
||||||
"volume": "Vol. 20, No. 11, pp. 2284~2287, November 2016",
|
"volume": "Vol. 20, No. 11, pp. 2284~2287, November 2016",
|
||||||
"publishedAt": "2284"
|
"publishedAt": "2016-11"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"category": "intl-journal-conf",
|
"category": "intl-journal-conf",
|
||||||
@@ -252,7 +252,7 @@ export const publications: Publication[] = [
|
|||||||
"title": "An ID/Locator Separation Based Group Mobility Management in Wireless Body Area Network",
|
"title": "An ID/Locator Separation Based Group Mobility Management in Wireless Body Area Network",
|
||||||
"venue": "Journal of Sensors",
|
"venue": "Journal of Sensors",
|
||||||
"volume": "Vol. 2015, Open Access Article (Article ID 537205), 12 pages, July 2015",
|
"volume": "Vol. 2015, Open Access Article (Article ID 537205), 12 pages, July 2015",
|
||||||
"publishedAt": "5372-00-05"
|
"publishedAt": "2015"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"category": "intl-journal-conf",
|
"category": "intl-journal-conf",
|
||||||
@@ -322,7 +322,7 @@ export const publications: Publication[] = [
|
|||||||
"title": "Distributed Mobility Control in Proxy Mobile IPv6 Networks",
|
"title": "Distributed Mobility Control in Proxy Mobile IPv6 Networks",
|
||||||
"venue": "IEICE Transactions on Communications",
|
"venue": "IEICE Transactions on Communications",
|
||||||
"volume": "Vol. E94-B, No. 8, pp. 2216~2224, August 2011",
|
"volume": "Vol. E94-B, No. 8, pp. 2216~2224, August 2011",
|
||||||
"publishedAt": "2216"
|
"publishedAt": "2011-08"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"category": "intl-journal-conf",
|
"category": "intl-journal-conf",
|
||||||
@@ -350,7 +350,7 @@ export const publications: Publication[] = [
|
|||||||
"title": "Performance Enhancement of mSCTP for Vertical Handover across Heterogeneous Wireless Networks",
|
"title": "Performance Enhancement of mSCTP for Vertical Handover across Heterogeneous Wireless Networks",
|
||||||
"venue": "International Journal of Communication Systems",
|
"venue": "International Journal of Communication Systems",
|
||||||
"volume": "Vol. 22, No. 12, pp. 1573~1591, December 2009",
|
"volume": "Vol. 22, No. 12, pp. 1573~1591, December 2009",
|
||||||
"publishedAt": "1573"
|
"publishedAt": "2009-12"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"category": "intl-journal-conf",
|
"category": "intl-journal-conf",
|
||||||
@@ -399,14 +399,14 @@ export const publications: Publication[] = [
|
|||||||
"title": "",
|
"title": "",
|
||||||
"venue": "IEICE Transactions on Communications",
|
"venue": "IEICE Transactions on Communications",
|
||||||
"volume": "Vol. E87-B, No. 9, pp. 2548~2556, September 2004",
|
"volume": "Vol. E87-B, No. 9, pp. 2548~2556, September 2004",
|
||||||
"publishedAt": "2548"
|
"publishedAt": "2004-09"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"category": "intl-journal-conf",
|
"category": "intl-journal-conf",
|
||||||
"title": "",
|
"title": "",
|
||||||
"venue": "IEICE Transactions on Fundamentals of Electronics Communications and Computer Sciences",
|
"venue": "IEICE Transactions on Fundamentals of Electronics Communications and Computer Sciences",
|
||||||
"volume": "Vol. E87-A, No. 6, pp. 1527~1530, June 2004",
|
"volume": "Vol. E87-A, No. 6, pp. 1527~1530, June 2004",
|
||||||
"publishedAt": "1527"
|
"publishedAt": "2004-06"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"category": "intl-journal-conf",
|
"category": "intl-journal-conf",
|
||||||
@@ -1083,7 +1083,7 @@ export const publications: Publication[] = [
|
|||||||
"title": "인터넷 멀티캐스트 라우팅 프로토콜 분석",
|
"title": "인터넷 멀티캐스트 라우팅 프로토콜 분석",
|
||||||
"venue": "ETRI 전자통신동향분석",
|
"venue": "ETRI 전자통신동향분석",
|
||||||
"volume": "99년 10월호, pp. 99 - 110, 1999.",
|
"volume": "99년 10월호, pp. 99 - 110, 1999.",
|
||||||
"publishedAt": "1999-10",
|
"publishedAt": "1999",
|
||||||
"kci": false
|
"kci": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1099,7 +1099,7 @@ export const publications: Publication[] = [
|
|||||||
"title": "",
|
"title": "",
|
||||||
"venue": "ETRI 전자통신동향분석",
|
"venue": "ETRI 전자통신동향분석",
|
||||||
"volume": "99년 6월호, pp. 76 - 84, 1999.",
|
"volume": "99년 6월호, pp. 76 - 84, 1999.",
|
||||||
"publishedAt": "1999-06",
|
"publishedAt": "1999",
|
||||||
"kci": false
|
"kci": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1107,7 +1107,7 @@ export const publications: Publication[] = [
|
|||||||
"title": "Design of Survivable Communication Networks with High Connectivity Constraints",
|
"title": "Design of Survivable Communication Networks with High Connectivity Constraints",
|
||||||
"venue": "한국경영과학회논문지",
|
"venue": "한국경영과학회논문지",
|
||||||
"volume": "Vol. 22, No. 3, pp. 59-80, September, 1997. (KCI)",
|
"volume": "Vol. 22, No. 3, pp. 59-80, September, 1997. (KCI)",
|
||||||
"publishedAt": "1997",
|
"publishedAt": "1997-09",
|
||||||
"kci": true
|
"kci": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -27,44 +27,50 @@ def to_iso(raw):
|
|||||||
return None
|
return None
|
||||||
raw = raw.strip()
|
raw = raw.strip()
|
||||||
|
|
||||||
# 1) YYYY-MM-DD or YYYY.MM.DD
|
# 1) English month + 19XX/20XX year: "April 2026", "Feb. 2008", "August, 2018"
|
||||||
m = re.search(r'(\d{4})[. /\\-]?(\d{1,2})[. /\\-]?(\d{1,2})', raw)
|
m_txt = re.search(r'([A-Za-z]+)\.?\s*,?\s*((?:19|20)\d{2})', raw)
|
||||||
if m:
|
|
||||||
yr = int(m.group(1))
|
|
||||||
mo = int(m.group(2))
|
|
||||||
day = int(m.group(3))
|
|
||||||
if mo <= 12 and day <= 31:
|
|
||||||
return f"{yr:04d}-{mo:02d}-{day:02d}"
|
|
||||||
|
|
||||||
# 2) "May 2026", "Feb. 2008", "August 2018"
|
|
||||||
m_txt = re.search(r'([A-Za-z]+)\.?\s*(\d{4})', raw)
|
|
||||||
if m_txt:
|
if m_txt:
|
||||||
mo_str = m_txt.group(1).lower().rstrip('.')
|
mo_str = m_txt.group(1).lower().rstrip('.')
|
||||||
yr_str = m_txt.group(2)
|
yr_str = m_txt.group(2)
|
||||||
if mo_str in MONTH_MAP:
|
if mo_str in MONTH_MAP:
|
||||||
return f"{yr_str}-{MONTH_MAP[mo_str]}"
|
return f"{yr_str}-{MONTH_MAP[mo_str]}"
|
||||||
|
|
||||||
# 3) "2019년 12월", "9월, 1999"
|
# 2) Korean "2026년 6월", "9월, 1999"
|
||||||
m_kor = re.search(r'(\d{4})년\s*(\d{1,2})월', raw)
|
m_kor = re.search(r'((?:19|20)\d{2})년\s*(\d{1,2})월', raw)
|
||||||
if m_kor:
|
if m_kor:
|
||||||
return f"{int(m_kor.group(1)):04d}-{int(m_kor.group(2)):02d}"
|
yr = int(m_kor.group(1))
|
||||||
|
mo = int(m_kor.group(2))
|
||||||
|
if 1 <= mo <= 12:
|
||||||
|
return f"{yr:04d}-{mo:02d}"
|
||||||
|
|
||||||
m_kor2 = re.search(r'(\d{1,2})월.*?,?\s*(\d{4})', raw)
|
m_kor2 = re.search(r'(\d{1,2})월\s*,?\s*((?:19|20)\d{2})', raw)
|
||||||
if m_kor2:
|
if m_kor2:
|
||||||
return f"{int(m_kor2.group(2)):04d}-{int(m_kor2.group(1)):02d}"
|
mo = int(m_kor2.group(1))
|
||||||
|
yr = int(m_kor2.group(2))
|
||||||
|
if 1 <= mo <= 12:
|
||||||
|
return f"{yr:04d}-{mo:02d}"
|
||||||
|
|
||||||
# 4) YYYY-MM or YYYY.MM
|
# 3) ISO date: YYYY-MM-DD, YYYY.MM.DD (where YYYY is 19XX or 20XX)
|
||||||
m_ym = re.search(r'(\d{4})[. /\\-]?(\d{1,2})', raw)
|
m = re.search(r'((?:19|20)\d{2})[. /\\-]?(\d{1,2})[. /\\-]?(\d{1,2})', raw)
|
||||||
|
if m:
|
||||||
|
yr = int(m.group(1))
|
||||||
|
mo = int(m.group(2))
|
||||||
|
day = int(m.group(3))
|
||||||
|
if 1 <= mo <= 12 and 1 <= day <= 31:
|
||||||
|
return f"{yr:04d}-{mo:02d}-{day:02d}"
|
||||||
|
|
||||||
|
# 4) ISO month: YYYY-MM or YYYY.MM
|
||||||
|
m_ym = re.search(r'((?:19|20)\d{2})[. /\\-]?(\d{1,2})', raw)
|
||||||
if m_ym:
|
if m_ym:
|
||||||
yr = int(m_ym.group(1))
|
yr = int(m_ym.group(1))
|
||||||
mo = int(m_ym.group(2))
|
mo = int(m_ym.group(2))
|
||||||
if mo <= 12:
|
if 1 <= mo <= 12:
|
||||||
return f"{yr:04d}-{mo:02d}"
|
return f"{yr:04d}-{mo:02d}"
|
||||||
|
|
||||||
# 5) YYYY only
|
# 5) 19XX or 20XX year only
|
||||||
m_y = re.search(r'(\d{4})', raw)
|
m_y = re.search(r'((?:19|20)\d{2})', raw)
|
||||||
if m_y:
|
if m_y:
|
||||||
return f"{int(m_y.group(1)):04d}"
|
return f"{m_y.group(1)}"
|
||||||
|
|
||||||
return raw
|
return raw
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,13 @@ import re
|
|||||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
sys.path.insert(0, os.path.join(BASE_DIR, "refer_landing_page", "scripts", "extract"))
|
sys.path.insert(0, os.path.join(BASE_DIR, "refer_landing_page", "scripts", "extract"))
|
||||||
|
|
||||||
|
MONTH_MAP = {
|
||||||
|
"january": "01", "jan": "01", "february": "02", "feb": "02", "march": "03", "mar": "03",
|
||||||
|
"april": "04", "apr": "04", "may": "05", "june": "06", "jun": "06", "july": "07", "jul": "07",
|
||||||
|
"august": "08", "aug": "08", "september": "09", "sep": "09", "sept": "09", "october": "10",
|
||||||
|
"oct": "10", "november": "11", "nov": "11", "december": "12", "dec": "12"
|
||||||
|
}
|
||||||
|
|
||||||
def verify():
|
def verify():
|
||||||
from generate_all import parse_members, parse_publications, parse_lectures, parse_standards
|
from generate_all import parse_members, parse_publications, parse_lectures, parse_standards
|
||||||
|
|
||||||
@@ -17,7 +24,7 @@ def verify():
|
|||||||
total_pubs = len(intl_p) + len(dom_p) + len(pat_p)
|
total_pubs = len(intl_p) + len(dom_p) + len(pat_p)
|
||||||
std_docs_count = sum(len(p["documents"]) for b in bodies for p in b["projects"])
|
std_docs_count = sum(len(p["documents"]) for b in bodies for p in b["projects"])
|
||||||
|
|
||||||
print("=== DATA VERIFICATION GATE (AC-07 / AC-08 / AC-10 / AC-11) ===")
|
print("=== DATA VERIFICATION GATE (AC-07 / AC-08 / AC-10 / AC-11 / VOLUME CROSS-CHECK) ===")
|
||||||
print(f"Active Members: {len(active_m)} (Expected: 16)")
|
print(f"Active Members: {len(active_m)} (Expected: 16)")
|
||||||
print(f"Alumni: {len(alumni_m)} (Expected: 60)")
|
print(f"Alumni: {len(alumni_m)} (Expected: 60)")
|
||||||
print(f"International Papers: {len(intl_p)} (Expected: 68)")
|
print(f"International Papers: {len(intl_p)} (Expected: 68)")
|
||||||
@@ -29,6 +36,8 @@ def verify():
|
|||||||
print(f"Standard Documents: {std_docs_count} (Expected: 44)")
|
print(f"Standard Documents: {std_docs_count} (Expected: 44)")
|
||||||
|
|
||||||
errors = []
|
errors = []
|
||||||
|
|
||||||
|
# 1. Count checks
|
||||||
if len(active_m) != 16:
|
if len(active_m) != 16:
|
||||||
errors.append(f"Active Members count mismatch: got {len(active_m)}, expected 16")
|
errors.append(f"Active Members count mismatch: got {len(active_m)}, expected 16")
|
||||||
if len(alumni_m) != 60:
|
if len(alumni_m) != 60:
|
||||||
@@ -48,8 +57,10 @@ def verify():
|
|||||||
if std_docs_count != 44:
|
if std_docs_count != 44:
|
||||||
errors.append(f"Standard Documents count mismatch: got {std_docs_count}, expected 44")
|
errors.append(f"Standard Documents count mismatch: got {std_docs_count}, expected 44")
|
||||||
|
|
||||||
# Date ISO 8601 validation (AC-11)
|
# 2. File checks (BOM, Strict ISO 8601, and Semantic Date Ranges)
|
||||||
content_dir = os.path.join(BASE_DIR, "content")
|
content_dir = os.path.join(BASE_DIR, "content")
|
||||||
|
date_regex = re.compile(r'^(19|20)\d{2}(-(0[1-9]|1[0-2]))?(-(0[1-9]|[12]\d|3[01]))?$')
|
||||||
|
|
||||||
for fname in ["members.ts", "publications.ts", "lectures.ts", "standards.ts"]:
|
for fname in ["members.ts", "publications.ts", "lectures.ts", "standards.ts"]:
|
||||||
fpath = os.path.join(content_dir, fname)
|
fpath = os.path.join(content_dir, fname)
|
||||||
if not os.path.exists(fpath):
|
if not os.path.exists(fpath):
|
||||||
@@ -58,18 +69,42 @@ def verify():
|
|||||||
with open(fpath, "r", encoding="utf-8") as f:
|
with open(fpath, "r", encoding="utf-8") as f:
|
||||||
text = f.read()
|
text = f.read()
|
||||||
|
|
||||||
# Check BOM (AC-10)
|
|
||||||
if text.startswith('\ufeff'):
|
if text.startswith('\ufeff'):
|
||||||
errors.append(f"BOM found in {fname}")
|
errors.append(f"BOM (U+FEFF) found in {fname}")
|
||||||
|
|
||||||
# Check dates
|
|
||||||
dates = re.findall(r'"(publishedAt|applicationAt|registrationAt|graduatedAt)": "([^"]+)"', text)
|
dates = re.findall(r'"(publishedAt|applicationAt|registrationAt|graduatedAt)": "([^"]+)"', text)
|
||||||
for k, d in dates:
|
for k, d in dates:
|
||||||
if not re.match(r'^\d{4}(-\d{2})?(-\d{2})?$', d):
|
if not date_regex.match(d):
|
||||||
errors.append(f"Non-ISO 8601 date in {fname}: {k}='{d}'")
|
errors.append(f"Invalid ISO 8601 or out-of-bounds date in {fname}: {k}='{d}'")
|
||||||
|
|
||||||
|
# 3. Volume Cross-Check for Publications (Ensures volume year matches publishedAt year)
|
||||||
|
for pub in intl_p + dom_p:
|
||||||
|
vol = pub.get("volume", "")
|
||||||
|
pub_date = pub.get("publishedAt", "")
|
||||||
|
if not pub_date:
|
||||||
|
errors.append(f"Missing publishedAt for paper: {pub.get('title')}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Look for English month + 19XX/20XX year or Korean YYYY년 MM월
|
||||||
|
m_txt = re.search(r'([A-Za-z]+)\.?\s*,?\s*((?:19|20)\d{2})', vol)
|
||||||
|
m_kor = re.search(r'((?:19|20)\d{2})년\s*(\d{1,2})월', vol)
|
||||||
|
m_kor2 = re.search(r'(\d{1,2})월\s*,?\s*((?:19|20)\d{2})', vol)
|
||||||
|
|
||||||
|
expected_yr = None
|
||||||
|
if m_txt:
|
||||||
|
mo_str = m_txt.group(1).lower().rstrip('.')
|
||||||
|
if mo_str in MONTH_MAP:
|
||||||
|
expected_yr = m_txt.group(2)
|
||||||
|
elif m_kor:
|
||||||
|
expected_yr = m_kor.group(1)
|
||||||
|
elif m_kor2:
|
||||||
|
expected_yr = m_kor2.group(2)
|
||||||
|
|
||||||
|
if expected_yr and not pub_date.startswith(expected_yr):
|
||||||
|
errors.append(f"Volume date mismatch for '{pub.get('title')}': volume has {expected_yr}, publishedAt is {pub_date}")
|
||||||
|
|
||||||
if errors:
|
if errors:
|
||||||
print("\n❌ DATA VERIFICATION FAILED:")
|
print(f"\n❌ DATA VERIFICATION FAILED ({len(errors)} errors):")
|
||||||
for err in errors:
|
for err in errors:
|
||||||
print(f" - {err}")
|
print(f" - {err}")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|||||||
Reference in New Issue
Block a user