#![doc = include_str!("../../docs/team/defense.md")]
#[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;
const DEFENSE_ADVANTAGE: u32 = 3_u32;
#[cfg_attr(feature = "rocket_okapi", derive(JsonSchema))]
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Default, Serialize, Deserialize)]
pub struct FootballTeamDefenseRaw {
blitzing: u32,
rush_defense: u32,
pass_defense: u32,
coverage: u32,
turnovers: u32,
kick_returning: u32
}
impl FootballTeamDefenseRaw {
pub fn validate(&self) -> Result<(), String> {
if self.blitzing > 100 {
return Err(
format!(
"Blitzing attribute is out of range [0, 100]: {}",
self.blitzing
)
)
}
if self.rush_defense > 100 {
return Err(
format!(
"Rush defense attribute is out of range [0, 100]: {}",
self.rush_defense
)
)
}
if self.pass_defense > 100 {
return Err(
format!(
"Pass defense attribute is out of range [0, 100]: {}",
self.pass_defense
)
)
}
if self.coverage > 100 {
return Err(
format!(
"Coverage attribute is out of range [0, 100]: {}",
self.coverage
)
)
}
if self.turnovers > 100 {
return Err(
format!(
"Turnovers attribute is out of range [0, 100]: {}",
self.turnovers
)
)
}
if self.kick_returning > 100 {
return Err(
format!(
"Kick returning attribute is out of range [0, 100]: {}",
self.kick_returning
)
)
}
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, Serialize)]
pub struct FootballTeamDefense {
blitzing: u32,
rush_defense: u32,
pass_defense: u32,
coverage: u32,
turnovers: u32,
kick_returning: u32
}
impl TryFrom<FootballTeamDefenseRaw> for FootballTeamDefense {
type Error = String;
fn try_from(item: FootballTeamDefenseRaw) -> Result<Self, Self::Error> {
match item.validate() {
Ok(()) => (),
Err(error) => return Err(error),
};
Ok(
FootballTeamDefense{
blitzing: item.blitzing,
rush_defense: item.rush_defense,
pass_defense: item.pass_defense,
coverage: item.coverage,
turnovers: item.turnovers,
kick_returning: item.kick_returning
}
)
}
}
impl<'de> Deserialize<'de> for FootballTeamDefense {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let raw = FootballTeamDefenseRaw::deserialize(deserializer)?;
FootballTeamDefense::try_from(raw).map_err(serde::de::Error::custom)
}
}
impl Default for FootballTeamDefense {
fn default() -> Self {
FootballTeamDefense{
blitzing: 50_u32,
rush_defense: 50_u32,
pass_defense: 50_u32,
coverage: 50_u32,
turnovers: 50_u32,
kick_returning: 50_u32
}
}
}
impl FootballTeamDefense {
pub fn new() -> FootballTeamDefense {
FootballTeamDefense::default()
}
pub fn from_overall(overall: u32) -> Result<FootballTeamDefense, String> {
let raw = FootballTeamDefenseRaw{
blitzing: overall,
rush_defense: overall,
pass_defense: overall,
coverage: overall,
turnovers: overall,
kick_returning: overall
};
FootballTeamDefense::try_from(raw)
}
pub fn overall(&self) -> u32 {
(
(
self.blitzing + self.rush_defense + self.pass_defense +
self.coverage + self.turnovers + self.kick_returning
) as f32 / 6_f32
) as u32
}
pub fn rush_defense(&self) -> u32 {
self.rush_defense
}
pub fn rush_defense_advantage(&self, defense_advantage: bool) -> u32 {
if defense_advantage {
100_u32.min(self.rush_defense + DEFENSE_ADVANTAGE)
} else {
self.rush_defense
}
}
pub fn pass_defense(&self) -> u32 {
self.pass_defense
}
pub fn pass_defense_advantage(&self, defense_advantage: bool) -> u32 {
if defense_advantage {
100_u32.min(self.pass_defense + DEFENSE_ADVANTAGE)
} else {
self.pass_defense
}
}
pub fn coverage(&self) -> u32 {
self.coverage
}
pub fn coverage_advantage(&self, defense_advantage: bool) -> u32 {
if defense_advantage {
100_u32.min(self.coverage + DEFENSE_ADVANTAGE)
} else {
self.coverage
}
}
pub fn blitzing(&self) -> u32 {
self.blitzing
}
pub fn blitzing_advantage(&self, defense_advantage: bool) -> u32 {
if defense_advantage {
100_u32.min(self.blitzing + DEFENSE_ADVANTAGE)
} else {
self.blitzing
}
}
pub fn turnovers(&self) -> u32 {
self.turnovers
}
pub fn turnovers_advantage(&self, defense_advantage: bool) -> u32 {
if defense_advantage {
100_u32.min(self.turnovers + DEFENSE_ADVANTAGE)
} else {
self.turnovers
}
}
pub fn kick_returning(&self) -> u32 {
self.kick_returning
}
pub fn kick_returning_advantage(&self, defense_advantage: bool) -> u32 {
if defense_advantage {
100_u32.min(self.kick_returning + DEFENSE_ADVANTAGE)
} else {
self.kick_returning
}
}
}
#[cfg_attr(feature = "rocket_okapi", derive(JsonSchema))]
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Serialize)]
pub struct FootballTeamDefenseBuilder {
blitzing: u32,
rush_defense: u32,
pass_defense: u32,
coverage: u32,
turnovers: u32,
kick_returning: u32
}
impl Default for FootballTeamDefenseBuilder {
fn default() -> Self {
FootballTeamDefenseBuilder{
blitzing: 50_u32,
rush_defense: 50_u32,
pass_defense: 50_u32,
coverage: 50_u32,
turnovers: 50_u32,
kick_returning: 50_u32
}
}
}
impl FootballTeamDefenseBuilder {
pub fn new() -> FootballTeamDefenseBuilder {
FootballTeamDefenseBuilder::default()
}
pub fn blitzing(mut self, blitzing: u32) -> Self {
self.blitzing = blitzing;
self
}
pub fn rush_defense(mut self, rush_defense: u32) -> Self {
self.rush_defense = rush_defense;
self
}
pub fn pass_defense(mut self, pass_defense: u32) -> Self {
self.pass_defense = pass_defense;
self
}
pub fn coverage(mut self, coverage: u32) -> Self {
self.coverage = coverage;
self
}
pub fn turnovers(mut self, turnovers: u32) -> Self {
self.turnovers = turnovers;
self
}
pub fn kick_returning(mut self, kick_returning: u32) -> Self {
self.kick_returning = kick_returning;
self
}
pub fn build(self) -> Result<FootballTeamDefense, String> {
let raw = FootballTeamDefenseRaw{
blitzing: self.blitzing,
rush_defense: self.rush_defense,
pass_defense: self.pass_defense,
coverage: self.coverage,
turnovers: self.turnovers,
kick_returning: self.kick_returning
};
FootballTeamDefense::try_from(raw)
}
}