214 lines
5.5 KiB
JavaScript
214 lines
5.5 KiB
JavaScript
/**
|
|
* 공통 헬퍼 함수
|
|
*/
|
|
|
|
import {
|
|
ABNORMAL_TYPE_LABELS,
|
|
ABNORMAL_TYPE_DESCRIPTIONS,
|
|
ABNORMAL_TYPE_COLORS
|
|
} from './constants.js';
|
|
|
|
/**
|
|
* 날짜 범위 설정
|
|
* @param {number} days - 일 수
|
|
* @returns {Object} 시작일과 종료일
|
|
*/
|
|
export function getDateRange(days) {
|
|
const endDate = new Date();
|
|
const startDate = new Date();
|
|
startDate.setDate(endDate.getDate() - days);
|
|
|
|
return {
|
|
startDate: startDate.toISOString().split('T')[0],
|
|
endDate: endDate.toISOString().split('T')[0]
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 날짜를 시간 차이로 변환
|
|
* @param {string} startDate - 시작 날짜
|
|
* @returns {number} 현재로부터의 시간 차이
|
|
*/
|
|
export function getHoursFromNow(startDate) {
|
|
const start = new Date(startDate);
|
|
const now = new Date();
|
|
return Math.ceil((now - start) / (1000 * 60 * 60));
|
|
}
|
|
|
|
/**
|
|
* 비정상 유형 라벨 가져오기
|
|
* @param {string} type - 비정상 유형
|
|
* @returns {string} 라벨
|
|
*/
|
|
export function getTypeLabel(type) {
|
|
return ABNORMAL_TYPE_LABELS[type] || type;
|
|
}
|
|
|
|
/**
|
|
* 비정상 유형 설명 가져오기
|
|
* @param {string} type - 비정상 유형
|
|
* @returns {string} 설명
|
|
*/
|
|
export function getTypeDescription(type) {
|
|
return ABNORMAL_TYPE_DESCRIPTIONS[type] || '비정상 궤적';
|
|
}
|
|
|
|
/**
|
|
* 비정상 유형별 색상 가져오기
|
|
* @param {string} type - 비정상 유형
|
|
* @returns {Array} RGB 색상 배열
|
|
*/
|
|
export function getColorByType(type) {
|
|
return [...(ABNORMAL_TYPE_COLORS[type] || [128, 128, 128]), 200];
|
|
}
|
|
|
|
/**
|
|
* CSS 선택자용 ID 이스케이프
|
|
* @param {string} id - 이스케이프할 ID
|
|
* @returns {string} 이스케이프된 ID
|
|
*/
|
|
export function escapeSelector(id) {
|
|
return id.replace(/:/g, '-');
|
|
}
|
|
|
|
/**
|
|
* 조회 기간 레이블 생성
|
|
* @param {string} startDate - 시작 날짜
|
|
* @param {string} endDate - 종료 날짜
|
|
* @returns {string} 기간 레이블
|
|
*/
|
|
export function getPeriodLabel(startDate, endDate) {
|
|
if (!startDate || !endDate) return '전체';
|
|
|
|
const start = new Date(startDate);
|
|
const end = new Date(endDate);
|
|
const diffDays = Math.ceil((end - start) / (1000 * 60 * 60 * 24)) + 1;
|
|
|
|
if (startDate === endDate) {
|
|
return start.toLocaleDateString('ko-KR');
|
|
} else {
|
|
return `${start.toLocaleDateString('ko-KR')} ~ ${end.toLocaleDateString('ko-KR')} (${diffDays}일간)`;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 숫자 포맷팅
|
|
* @param {number} number - 포맷할 숫자
|
|
* @param {number} decimals - 소수점 자리수
|
|
* @returns {string} 포맷된 숫자
|
|
*/
|
|
export function formatNumber(number, decimals = 0) {
|
|
if (number === null || number === undefined) return '-';
|
|
return Number(number).toFixed(decimals);
|
|
}
|
|
|
|
/**
|
|
* 거리 포맷팅
|
|
* @param {number} distance - 거리 (nm)
|
|
* @returns {string} 포맷된 거리
|
|
*/
|
|
export function formatDistance(distance) {
|
|
if (!distance) return '-';
|
|
return `${formatNumber(distance, 2)}nm`;
|
|
}
|
|
|
|
/**
|
|
* 속도 포맷팅
|
|
* @param {number} speed - 속도 (knots)
|
|
* @returns {string} 포맷된 속도
|
|
*/
|
|
export function formatSpeed(speed) {
|
|
if (!speed) return '-';
|
|
return `${formatNumber(speed, 1)}kts`;
|
|
}
|
|
|
|
/**
|
|
* 날짜/시간 포맷팅
|
|
* @param {string|Date} date - 날짜
|
|
* @returns {string} 포맷된 날짜/시간
|
|
*/
|
|
export function formatDateTime(date) {
|
|
if (!date) return '-';
|
|
return new Date(date).toLocaleString('ko-KR');
|
|
}
|
|
|
|
/**
|
|
* 디바운스 함수
|
|
* @param {Function} func - 실행할 함수
|
|
* @param {number} wait - 대기 시간 (ms)
|
|
* @returns {Function} 디바운스된 함수
|
|
*/
|
|
export function debounce(func, wait) {
|
|
let timeout;
|
|
return function executedFunction(...args) {
|
|
const later = () => {
|
|
clearTimeout(timeout);
|
|
func(...args);
|
|
};
|
|
clearTimeout(timeout);
|
|
timeout = setTimeout(later, wait);
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 쓰로틀 함수
|
|
* @param {Function} func - 실행할 함수
|
|
* @param {number} limit - 제한 시간 (ms)
|
|
* @returns {Function} 쓰로틀된 함수
|
|
*/
|
|
export function throttle(func, limit) {
|
|
let inThrottle;
|
|
return function(...args) {
|
|
if (!inThrottle) {
|
|
func.apply(this, args);
|
|
inThrottle = true;
|
|
setTimeout(() => inThrottle = false, limit);
|
|
}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 깊은 복사
|
|
* @param {*} obj - 복사할 객체
|
|
* @returns {*} 복사된 객체
|
|
*/
|
|
export function deepClone(obj) {
|
|
if (obj === null || typeof obj !== 'object') return obj;
|
|
if (obj instanceof Date) return new Date(obj.getTime());
|
|
if (obj instanceof Array) return obj.map(item => deepClone(item));
|
|
if (obj instanceof Object) {
|
|
const cloned = {};
|
|
for (const key in obj) {
|
|
if (obj.hasOwnProperty(key)) {
|
|
cloned[key] = deepClone(obj[key]);
|
|
}
|
|
}
|
|
return cloned;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* URL 쿼리 파라미터 파싱
|
|
* @param {string} url - URL
|
|
* @returns {Object} 파라미터 객체
|
|
*/
|
|
export function parseQueryParams(url = window.location.search) {
|
|
const params = new URLSearchParams(url);
|
|
const result = {};
|
|
for (const [key, value] of params) {
|
|
result[key] = value;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* 객체를 쿼리 스트링으로 변환
|
|
* @param {Object} params - 파라미터 객체
|
|
* @returns {string} 쿼리 스트링
|
|
*/
|
|
export function objectToQueryString(params) {
|
|
return Object.keys(params)
|
|
.filter(key => params[key] !== null && params[key] !== undefined)
|
|
.map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
|
|
.join('&');
|
|
} |