/** * πŸ“„ Excel to JSON Utility * μ—‘μ…€ 데이터 JSON λ³€ν™˜ μœ ν‹Έλ¦¬ν‹° * * - μ—‘μ…€ 파일 데이터 νŒŒμ‹± 및 JSON λ³€ν™˜ κΈ°λŠ₯ * - λ‚ μ§œ 및 μ‹œκ°„ ν¬λ§·νŒ… 및 μœ νš¨μ„± 검사 * - Zod μŠ€ν‚€λ§ˆλ₯Ό ν†΅ν•œ 데이터 νƒ€μž… 검증 및 μ•ˆμ „μ„± 보μž₯ * - μˆ˜μš©κ°€-맨홀 λ§€μΉ­κ²°κ³Ό, μ‹œκ°„νŒ¨ν„΄, μœ λŸ‰μžλ£Œ λ“± 데이터 λ³€ν™˜ * - κ°•μš°μžλ£Œ 및 μˆ˜μš©κ°€ λ¬Όμ‚¬μš©λŸ‰ 데이터 처리 * - λ‹€μ–‘ν•œ λ‚ μ§œ ν˜•μ‹(M/D/YYYY, YYYY-MM-DD λ“±) 지원 */ export const TEST_UUID = '2d4b151d-1828-41e0-91d9-4cd28ea1cc7e' import { z } from "zod"; // "YYYY-MM-DDTHH:MM:SS" ν˜•μ‹μœΌλ‘œ ν¬λ§·νŒ… ν•˜λŠ” ν•¨μˆ˜ function parseAndFormatDateTimeToISOCompatibleString( dateInput: string, timeInputForMDY: string | null, inputType: 'YYYY-MM-DD_H:MM' | 'M/D/YYYY_H:MM' | 'M/D/YY_H:MM' ): string | null { let year: number, month: number, day: number, hours: number, minutes: number; let datePartStr: string; let timePartStr: string; if (inputType === 'YYYY-MM-DD_H:MM') { const parts = String(dateInput).split(' '); if (parts.length !== 2) { console.warn(`Invalid dateTime format for ${inputType} (split space):`, dateInput); return null; } datePartStr = parts[0] ?? ""; // "YYYY-MM-DD" timePartStr = parts[1] ?? ""; // "H:MM" const dateParts = datePartStr.split('-'); if (dateParts.length !== 3) { console.warn(`Invalid date format for ${inputType} (datePart):`, datePartStr); return null; } year = parseInt(dateParts[0] ?? '', 10); month = parseInt(dateParts[1] ?? '', 10); day = parseInt(dateParts[2] ?? '', 10); } else if (inputType === 'M/D/YYYY_H:MM') { datePartStr = String(dateInput); // "M/D/YYYY" if (!timeInputForMDY) { console.warn(`Time input is missing for ${inputType}:`, dateInput); return null; } timePartStr = String(timeInputForMDY); // "H:MM" const dateParts = datePartStr.split('/'); if (dateParts.length !== 3) { console.warn(`Invalid date format for ${inputType} (datePart):`, datePartStr); return null; } month = parseInt(dateParts[0] ?? '', 10); day = parseInt(dateParts[1] ?? '', 10); year = parseInt(dateParts[2] ?? '', 10); } else if (inputType === 'M/D/YY_H:MM') { // "M/D/YY H:MM" ν˜•μ‹ 처리 const parts = String(dateInput).split(' '); if (parts.length !== 2) { console.warn(`Invalid dateTime format for ${inputType} (split space):`, dateInput); return null; } datePartStr = parts[0] ?? ""; // "M/D/YY" timePartStr = parts[1] ?? ""; // "H:MM" const dateParts = datePartStr.split('/'); if (dateParts.length !== 3) { console.warn(`Invalid date format for ${inputType} (datePart):`, datePartStr); return null; } month = parseInt(dateParts[0] ?? '', 10); day = parseInt(dateParts[1] ?? '', 10); year = parseInt(dateParts[2] ?? '', 10); // YY to YYYY conversion (assuming 2000s) if (year < 100) { year += 2000; } } else { console.warn("Invalid inputType for date parsing."); return null; } // μ‹œκ°„ νŒŒμ‹± (H:MM) - 곡톡 둜직 const timeParts = timePartStr.split(':'); if (timeParts.length !== 2) { console.warn(`Invalid time format (timePart):`, timePartStr); return null; } hours = parseInt(timeParts[0] ?? '', 10); minutes = parseInt(timeParts[1] ?? '', 10); if (isNaN(year) || isNaN(month) || isNaN(day) || isNaN(hours) || isNaN(minutes)) { console.warn("Invalid parsed date or time numeric values:", { year, month, day, hours, minutes }); return null; } // "YYYY-MM-DD HH:MM:SS" ν˜•μ‹μœΌλ‘œ ν¬λ§·νŒ… - 곡톡 둜직 const formattedYear = String(year).padStart(4, '0'); // μ—°λ„λŠ” 4자리둜 보μž₯ (M/D/YYYY의 경우) const formattedMonth = String(month).padStart(2, '0'); const formattedDay = String(day).padStart(2, '0'); const formattedHours = String(hours).padStart(2, '0'); const formattedMinutes = String(minutes).padStart(2, '0'); return `${formattedYear}-${formattedMonth}-${formattedDay} ${formattedHours}:${formattedMinutes}:00`; } // μˆ˜μš©κ°€-맨홀 λ§€μΉ­κ²°κ³Ό (μˆ˜μ • ν•„μš”) export const MatchingResultZod = z.object({ anlsSn: z.number(), // 뢄석 일련번호 mhlMngNo: z.string(), // 맨홀 번호 (μž„μ‹œκ°’μ΄λΌ μΆ”ν›„ μˆ˜μ • ν•„μš”) rcptrNo: z.string(), // μˆ˜μš©κ°€ 번호 }); export type MatchingResultZodType = z.infer; export const excelToMatchingResultData = (excelData: any) => { const MatchingResultData: MatchingResultZodType[] = excelData.map((item: any) => { return { anlsSn: Number(item["NO"]), mhlMngNo: String(item["FTR_IDN"]), // (μž„μ‹œκ°’μ΄λΌ μΆ”ν›„ μˆ˜μ • ν•„μš”) rcptrNo: String(item["μˆ˜μš©κ°€"]), }; }).filter((el: any) => el !== undefined); return MatchingResultData; }; // μ‹œκ°„νŒ¨ν„΄ export const timePatternZod = z.object({ hrId: z.number(), // μ‹œκ°„ rt: z.number().nullish(), // λΉ„μœ¨ }); export type timePatternZodType = z.infer; export const excelToTimePatternData = (excelData: any) => { const timePatternData: timePatternZodType[] = excelData.map((item: any) => { return { hrId: Number(item["μ‹œκ°„"]), rt: Number(item["λΉ„μœ¨"]), }; }).filter((el: any) => el !== undefined); return timePatternData; }; // μœ λŸ‰μžλ£Œ export const flowRateZod = z.object({ pplMngNo: z.string(), // κ΄€λ‘œλ²ˆν˜Έ mtrngDt: z.string(), // μ‹œκ°„ oilq: z.number().nullish(), // μœ λŸ‰(γŽ₯/h) }); export type flowRateZodType = z.infer; export const excelToFlowRateData = (excelData: any) => { const flowRateData: flowRateZodType[] = excelData.map((item: any) => { const dateTimeStr = String(item["μ‹œκ°„"]); // "M/D/YY H:MM" ν˜•μ‹ (예: "2/23/25 0:10") const formattedDateTime = parseAndFormatDateTimeToISOCompatibleString(dateTimeStr, null, 'M/D/YY_H:MM'); if (!formattedDateTime) return undefined; return { pplMngNo: String(item["κ΄€λ‘œλ²ˆν˜Έ"]), mtrngDt: formattedDateTime, oilq: Number(item["μœ λŸ‰(γŽ₯/h)"]), }; }).filter((el: any) => el !== undefined); return flowRateData; }; // μˆ˜μš©κ°€ λ¬Όμ‚¬μš©λŸ‰ export const rcptrInfoZod = z.object({ rcptrNo: z.string(), // μˆ˜μš©κ°€λ²ˆν˜Έ useYm: z.string(), // μ‚¬μš©μ—°μ›” usqty: z.number().nullish(), // μ‚¬μš©λŸ‰(γŽ₯) }); export type rcptrInfoZodType = z.infer; export const excelToRcptrInfoData = (excelData: any) => { const flowRateData: rcptrInfoZodType[] = excelData.map((item: any) => { return { rcptrNo: String(item["μˆ˜μš©κ°€λ²ˆν˜Έ"]), useYm: String(item["μ‚¬μš©μ—°μ›”"]), usqty: Number(item["μ‚¬μš©λŸ‰(γŽ₯)"]), }; }).filter((el: any) => el !== undefined); return flowRateData; }; // κ°•μš°μžλ£Œ (μˆ˜μ • ν•„μš”) export const rainZod = z.object({ mtrngDt: z.string(), // λ‚ μ§œ + μ‹œκ°„ amrf: z.number().nullish(), // κ°•μš°λŸ‰(mm) }); export type rainZodType = z.infer; export const excelToRainData = (excelData: any) => { const rainData: rainZodType[] = excelData.map((item: any) => { const datePartStr = String(item["λ‚ μ§œ"]); // "M/D/YYYY" ν˜•μ‹ (예: "5/9/2021") const timePartStr = String(item["μ‹œκ°„"]); // "H:MM" ν˜•μ‹ (예: "8:00") const formattedForRainZod = parseAndFormatDateTimeToISOCompatibleString(datePartStr, timePartStr, 'M/D/YYYY_H:MM'); if (!formattedForRainZod) return undefined; return { mtrngDt: formattedForRainZod, amrf: Number(item["κ°•μš°λŸ‰(mm)"]), }; }).filter((el: any) => el !== undefined); return rainData; };