#![doc = include_str!("../docs/team.md")]
pub mod coach;
pub mod defense;
pub mod offense;
#[cfg(feature = "rocket_okapi")]
use rocket_okapi::okapi::schemars;
#[cfg(feature = "rocket_okapi")]
use rocket_okapi::okapi::schemars::JsonSchema;
use serde::{Deserialize, Deserializer, Serialize};
#[cfg(feature = "wasm")]
use tsify_next::Tsify;
use crate::game::play::PlaySimulatable;
use crate::game::score::ScoreSimulatable;
use crate::team::coach::FootballTeamCoach;
use crate::team::defense::FootballTeamDefense;
use crate::team::offense::FootballTeamOffense;
pub const DEFAULT_TEAM_NAME: &str = "Null Island Defaults";
pub const DEFAULT_TEAM_SHORT_NAME: &str = "NULL";
#[cfg_attr(feature = "rocket_okapi", derive(JsonSchema))]
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Default, Serialize, Deserialize)]
pub struct FootballTeamRaw {
name: String,
short_name: String,
coach: FootballTeamCoach,
defense: FootballTeamDefense,
offense: FootballTeamOffense
}
impl FootballTeamRaw {
pub fn validate(&self) -> Result<(), String> {
if self.name.len() > 64 {
return Err(
format!(
"Team name is longer than 64 characters: {}",
self.name
)
)
}
if self.short_name.len() > 4 {
return Err(
format!(
"Team short name is longer than 4 characters: {}",
self.short_name
)
)
}
Ok(())
}
}
#[cfg_attr(feature = "rocket_okapi", derive(JsonSchema))]
#[cfg_attr(feature = "wasm", derive(Tsify))]
#[cfg_attr(feature = "wasm", tsify(into_wasm_abi, from_wasm_abi))]
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Default, Serialize)]
pub struct FootballTeam {
name: String,
short_name: String,
coach: FootballTeamCoach,
defense: FootballTeamDefense,
offense: FootballTeamOffense
}
impl TryFrom<FootballTeamRaw> for FootballTeam {
type Error = String;
fn try_from(item: FootballTeamRaw) -> Result<Self, Self::Error> {
match item.validate() {
Ok(()) => (),
Err(error) => return Err(error),
};
Ok(
FootballTeam{
name: item.name,
short_name: item.short_name,
coach: item.coach,
offense: item.offense,
defense: item.defense
}
)
}
}
impl<'de> Deserialize<'de> for FootballTeam {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let raw = FootballTeamRaw::deserialize(deserializer)?;
FootballTeam::try_from(raw).map_err(serde::de::Error::custom)
}
}
impl PlaySimulatable for FootballTeam {
fn coach(&self) -> &FootballTeamCoach {
&self.coach
}
fn offense(&self) -> &FootballTeamOffense {
&self.offense
}
fn defense(&self) -> &FootballTeamDefense {
&self.defense
}
}
impl ScoreSimulatable for FootballTeam {
fn name(&self) -> &str {
&self.name
}
fn defense_overall(&self) -> u32 {
self.defense.overall()
}
fn offense_overall(&self) -> u32 {
self.offense.overall()
}
}
impl FootballTeam {
pub fn new() -> FootballTeam {
FootballTeam{
name: String::from(DEFAULT_TEAM_NAME),
short_name: String::from(DEFAULT_TEAM_SHORT_NAME),
coach: FootballTeamCoach::new(),
offense: FootballTeamOffense::new(),
defense: FootballTeamDefense::new()
}
}
pub fn from_overalls(name: &str, short_name: &str, offense_overall: u32, defense_overall: u32) -> Result<FootballTeam, String> {
let offense = FootballTeamOffense::from_overall(offense_overall)?;
let defense = FootballTeamDefense::from_overall(defense_overall)?;
Ok(
FootballTeam{
name: String::from(name),
short_name: String::from(short_name),
coach: FootballTeamCoach::new(),
offense,
defense
}
)
}
pub fn from_properties(name: &str, short_name: &str, coach: FootballTeamCoach, offense: FootballTeamOffense, defense: FootballTeamDefense) -> FootballTeam {
FootballTeam{
name: String::from(name),
short_name: String::from(short_name),
coach,
offense,
defense
}
}
pub fn name(&self) -> &str {
&self.name
}
pub fn name_mut(&mut self) -> &mut String {
&mut self.name
}
pub fn short_name(&self) -> &str {
&self.short_name
}
pub fn short_name_mut(&mut self) -> &mut String {
&mut self.short_name
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_football_team_from_properties() {
let result_a = FootballTeam::from_overalls("Test Team", "TEST", 200, 50);
let expected_a: Result<FootballTeam, String> = Err(
String::from("Passing attribute is out of range [0, 100]: 200")
);
assert_eq!(
result_a,
expected_a
);
let result_b = FootballTeam::from_overalls("Test Team", "TEST", 50, 150);
let expected_b: Result<FootballTeam, String> = Err(
String::from("Blitzing attribute is out of range [0, 100]: 150")
);
assert_eq!(
result_b,
expected_b
);
}
}