1use derive_more::{Deref, DerefMut, Display, From, Into};
5use nil_core::city::{City, PublicCity};
6use nil_core::continent::coord::Coord;
7use nil_core::error::Error as CoreError;
8use nil_core::ranking::score::Score;
9use nil_core::world::World;
10use serde::{Deserialize, Serialize};
11
12#[cfg(feature = "axum")]
13use nil_payload_macros::IntoJsonResponse;
14
15#[cfg(feature = "typescript")]
16use ts_rs::TS;
17
18#[derive(Clone, Debug, Deref, DerefMut, From, Into, Deserialize, Serialize)]
19#[cfg_attr(feature = "axum", derive(IntoJsonResponse))]
20#[cfg_attr(feature = "typescript", derive(TS))]
21#[cfg_attr(feature = "typescript", ts(export))]
22pub struct GetCitiesResponse(pub Vec<GetCityResponse>);
23
24#[derive(Clone, Debug, Deserialize, Serialize)]
25#[cfg_attr(feature = "axum", derive(IntoJsonResponse))]
26#[cfg_attr(feature = "typescript", derive(TS))]
27#[cfg_attr(feature = "typescript", ts(export))]
28pub struct GetCityResponse {
29 pub city: City,
30 pub score: Option<Score>,
31}
32
33#[bon::bon]
34impl GetCityResponse {
35 #[builder]
36 pub fn new(
37 #[builder(start_fn)] world: &World,
38 #[builder(start_fn)] coord: Coord,
39 #[builder(default)] score: bool,
40 ) -> Result<Self, CoreError> {
41 let city = world.city(coord)?;
42 let score = score
43 .then(|| city.score(&world.stats().infrastructure()))
44 .transpose()?;
45
46 Ok(Self { city: city.clone(), score })
47 }
48}
49
50#[derive(Clone, Copy, Debug, Deref, DerefMut, Display, From, Into, Deserialize, Serialize)]
51#[cfg_attr(feature = "axum", derive(IntoJsonResponse))]
52#[cfg_attr(feature = "typescript", derive(TS))]
53#[cfg_attr(feature = "typescript", ts(export))]
54pub struct GetCityScoreResponse(pub Score);
55
56#[derive(Clone, Debug, Deref, DerefMut, From, Into, Deserialize, Serialize)]
57#[cfg_attr(feature = "axum", derive(IntoJsonResponse))]
58#[cfg_attr(feature = "typescript", derive(TS))]
59#[cfg_attr(feature = "typescript", ts(export))]
60pub struct GetPublicCitiesResponse(pub Vec<GetPublicCityResponse>);
61
62#[derive(Clone, Debug, Deserialize, Serialize)]
63#[serde(rename_all = "camelCase")]
64#[cfg_attr(feature = "axum", derive(IntoJsonResponse))]
65#[cfg_attr(feature = "typescript", derive(TS))]
66#[cfg_attr(feature = "typescript", ts(export))]
67pub struct GetPublicCityResponse {
68 pub city: PublicCity,
69 pub score: Option<Score>,
70}
71
72#[bon::bon]
73impl GetPublicCityResponse {
74 #[builder]
75 pub fn new(
76 #[builder(start_fn)] world: &World,
77 #[builder(start_fn)] coord: Coord,
78 #[builder(default)] score: bool,
79 ) -> Result<Self, CoreError> {
80 GetCityResponse::builder(world, coord)
81 .score(score)
82 .build()
83 .map(Into::into)
84 }
85}
86
87impl From<GetCityResponse> for GetPublicCityResponse {
88 fn from(value: GetCityResponse) -> Self {
89 Self {
90 city: PublicCity::from(&value.city),
91 score: value.score,
92 }
93 }
94}
95
96#[derive(Clone, Debug, Deref, DerefMut, From, Into, Deserialize, Serialize)]
97#[cfg_attr(feature = "axum", derive(IntoJsonResponse))]
98#[cfg_attr(feature = "typescript", derive(TS))]
99#[cfg_attr(feature = "typescript", ts(export))]
100pub struct SearchCityResponse(pub Vec<City>);
101
102#[derive(Clone, Debug, Deref, DerefMut, From, Into, Deserialize, Serialize)]
103#[cfg_attr(feature = "axum", derive(IntoJsonResponse))]
104#[cfg_attr(feature = "typescript", derive(TS))]
105#[cfg_attr(feature = "typescript", ts(export))]
106pub struct SearchPublicCityResponse(pub Vec<PublicCity>);