Skip to main content

amlich_api/
lib.rs

1mod convert;
2mod dto;
3
4use std::collections::HashMap;
5
6use amlich_core::holiday_data::{lunar_festivals, solar_holidays};
7use amlich_core::holidays::get_vietnamese_holidays;
8use amlich_core::insight_data::{
9    all_elements, find_can, find_chi, find_tiet_khi_insight, get_day_guidance,
10};
11
12pub use dto::*;
13
14pub fn get_day_info(query: &DateQuery) -> Result<DayInfoDto, String> {
15    if !(1..=12).contains(&query.month) {
16        return Err("month must be 1-12".to_string());
17    }
18    if !(1..=31).contains(&query.day) {
19        return Err("day must be 1-31".to_string());
20    }
21
22    let tz = query.timezone.unwrap_or(amlich_core::VIETNAM_TIMEZONE);
23    let info = amlich_core::get_day_info_with_timezone(query.day, query.month, query.year, tz);
24    Ok(DayInfoDto::from(&info))
25}
26
27pub fn get_day_info_for_date(day: i32, month: i32, year: i32) -> Result<DayInfoDto, String> {
28    get_day_info(&DateQuery {
29        day,
30        month,
31        year,
32        timezone: None,
33    })
34}
35
36pub fn get_holidays(year: i32, major_only: bool) -> Vec<HolidayDto> {
37    get_vietnamese_holidays(year)
38        .iter()
39        .filter(|h| !major_only || h.is_major)
40        .map(HolidayDto::from)
41        .collect()
42}
43
44pub fn get_day_insight(query: &DateQuery) -> Result<DayInsightDto, String> {
45    let day_info = get_day_info(query)?;
46
47    let festival = lunar_festivals()
48        .iter()
49        .find(|item| {
50            if item.is_solar {
51                item.solar_day == Some(day_info.solar.day)
52                    && item.solar_month == Some(day_info.solar.month)
53            } else {
54                item.lunar_day == day_info.lunar.day && item.lunar_month == day_info.lunar.month
55            }
56        })
57        .map(FestivalInsightDto::from);
58
59    let holiday = solar_holidays()
60        .iter()
61        .find(|item| {
62            item.solar_day == day_info.solar.day && item.solar_month == day_info.solar.month
63        })
64        .map(HolidayInsightDto::from);
65
66    let can_info = find_can(&day_info.canchi.day.can);
67    let chi_info = find_chi(&day_info.canchi.day.chi);
68    let element_index: &HashMap<String, amlich_core::insight_data::ElementInfo> = all_elements();
69
70    let canchi = match (can_info, chi_info) {
71        (Some(can), Some(chi)) => {
72            let element = element_index
73                .get(&can.element)
74                .map(|el| ElementInsightDto::from((&can.element, el)));
75            Some(CanChiInsightDto {
76                can: CanInsightDto::from(can),
77                chi: ChiInsightDto::from(chi),
78                element,
79            })
80        }
81        _ => None,
82    };
83
84    let day_guidance = get_day_guidance(&day_info.canchi.day.chi).map(DayGuidanceDto::from);
85    let tiet_khi = find_tiet_khi_insight(&day_info.tiet_khi.name).map(TietKhiInsightDto::from);
86
87    Ok(DayInsightDto {
88        solar: day_info.solar,
89        lunar: day_info.lunar,
90        festival,
91        holiday,
92        canchi,
93        day_guidance,
94        tiet_khi,
95    })
96}
97
98pub fn get_day_insight_for_date(day: i32, month: i32, year: i32) -> Result<DayInsightDto, String> {
99    get_day_insight(&DateQuery {
100        day,
101        month,
102        year,
103        timezone: None,
104    })
105}