use crate::core::Chart;
use crate::features::{
domains::{Domain, domain_for_palace},
extractor::{ChartFeatures, FeatureExtractionError, FeatureExtractor},
mutagen_flows::MutagenFlow,
palace_features::PalaceFeature,
relations::{PalaceRelation, all_palace_relations},
star_features::StarFeature,
};
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Hash)]
pub struct BasicFeatureExtractor;
impl FeatureExtractor for BasicFeatureExtractor {
fn extract(&self, chart: &Chart) -> Result<ChartFeatures, FeatureExtractionError> {
let mut palace_features = Vec::new();
let mut star_features = Vec::new();
let mut mutagen_flows = Vec::new();
for palace in chart.palaces() {
let domain = domain_for_palace(palace.name());
if let Some(domain) = domain {
palace_features.push(PalaceFeature::new(palace.name(), domain));
}
for placement in palace.stars() {
star_features.push(StarFeature::new(
palace.name(),
placement.name(),
placement.kind(),
placement.brightness(),
placement.mutagen(),
placement.scope(),
domain,
));
if let Some(mutagen) = placement.mutagen() {
mutagen_flows.push(MutagenFlow::new(
palace.name(),
placement.name(),
mutagen,
placement.scope(),
));
}
}
}
let domains = distinct_domains(&palace_features);
let relations = all_relations();
Ok(ChartFeatures::new(
chart.method_profile().id(),
domains,
palace_features,
star_features,
mutagen_flows,
relations,
))
}
}
fn distinct_domains(palace_features: &[PalaceFeature]) -> Vec<Domain> {
let mut domains = Vec::new();
for feature in palace_features {
if !domains.contains(&feature.domain()) {
domains.push(feature.domain());
}
}
domains
}
fn all_relations() -> Vec<PalaceRelation> {
all_palace_relations()
.iter()
.flat_map(|relations| relations.to_relations())
.collect()
}