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}