component factories + formatting

feature/battle
brnrs 5 years ago
parent 1a52695945
commit 28d5069b02
  1. 15
      src/battle/mod.rs
  2. 12
      src/contexts/component.rs
  3. 97
      src/contexts/component_factory.rs
  4. 8
      src/contexts/component_map.rs
  5. 4
      src/contexts/mod.rs
  6. 6
      src/contexts/model_i.rs
  7. 1
      src/main.rs

@ -161,16 +161,17 @@ fn check_result(context: &Context) -> Option<BattleResult> {
let team_db = context.get::<TeamDb>().unwrap(); let team_db = context.get::<TeamDb>().unwrap();
let actor_state_db = context.get::<ActorStateDb>().unwrap(); let actor_state_db = context.get::<ActorStateDb>().unwrap();
let is_alive = |actor_id: &u32| {
if let ActorState::Dead = actor_state_db.get(*actor_id).unwrap() {
false
} else {
true
}
};
let alive: Vec<TeamId> = team_db let alive: Vec<TeamId> = team_db
.iter() .iter()
.filter_map(|(team_id, team)| { .filter_map(|(team_id, team)| {
if team.actors.iter().any(|actor_id| { if team.actors.iter().any(is_alive) {
if let ActorState::Dead = actor_state_db.get(*actor_id).unwrap() {
false
} else {
true
}
}) {
Some(*team_id) Some(*team_id)
} else { } else {
None None

@ -1,13 +1,13 @@
use std::any::{Any, TypeId, type_name}; use std::any::{type_name, Any, TypeId};
use std::convert::TryFrom;
use std::cell::RefCell; use std::cell::RefCell;
use std::convert::TryFrom;
use std::ops::Deref; use std::ops::Deref;
use std::rc::Rc; use std::rc::Rc;
#[derive(Clone)] #[derive(Clone)]
pub struct Component<T: Any + ?Sized + 'static>(Rc<RefCell<T>>); pub struct Component<T: Any + ?Sized + 'static>(Rc<RefCell<T>>);
impl <T> Deref for Component<T> { impl<T> Deref for Component<T> {
type Target = RefCell<T>; type Target = RefCell<T>;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
@ -16,7 +16,7 @@ impl <T> Deref for Component<T> {
} }
#[allow(dead_code)] #[allow(dead_code)]
impl <T: Any + Sized + 'static> Component<T> { impl<T: Any + Sized + 'static> Component<T> {
pub fn from(t: T) -> Component<T> { pub fn from(t: T) -> Component<T> {
Component(Rc::new(RefCell::new(t))) Component(Rc::new(RefCell::new(t)))
} }
@ -30,9 +30,9 @@ impl <T: Any + Sized + 'static> Component<T> {
} }
} }
impl <T: Any + Sized + 'static> TryFrom<Rc<dyn Any + 'static>> for Component<T> { impl<T: Any + Sized + 'static> TryFrom<Rc<dyn Any + 'static>> for Component<T> {
type Error = Rc<dyn Any + 'static>; type Error = Rc<dyn Any + 'static>;
fn try_from(rc: Rc<dyn Any + 'static>) -> Result<Component<T>, Self::Error> { fn try_from(rc: Rc<dyn Any + 'static>) -> Result<Component<T>, Self::Error> {
Ok(Component(rc.downcast::<RefCell<T>>()?)) Ok(Component(rc.downcast::<RefCell<T>>()?))
} }
} }

@ -1,7 +1,7 @@
use super::component::Component; use super::component::Component;
use super::model_i::{Context, FromContext}; use super::model_i::{Context, FromContext};
use std::any::{Any, type_name}; use std::any::{type_name, Any};
trait ComponentFactory { trait ComponentFactory {
type Input; type Input;
@ -14,11 +14,102 @@ trait ContextComponentFactory: ComponentFactory {
fn build_from_context(&self, context: &Context) -> Result<Self::Output, String>; fn build_from_context(&self, context: &Context) -> Result<Self::Output, String>;
} }
impl <T:Any + Sized + 'static, O, CF: ComponentFactory<Input=Component<T>, Output=O>> ContextComponentFactory for CF { impl<T: Any + Sized + 'static, O, CF: ComponentFactory<Input = Component<T>, Output = O>>
ContextComponentFactory for CF
{
fn build_from_context(&self, context: &Context) -> Result<Self::Output, String> { fn build_from_context(&self, context: &Context) -> Result<Self::Output, String> {
let input = FromContext::from(context).ok_or_else(|| format!("Could not find retrieve component of type {} from context", type_name::<T>()))?; let input = FromContext::from(context).ok_or_else(|| {
format!(
"Could not find retrieve component of type {} from context",
type_name::<T>()
)
})?;
self.build(input) self.build(input)
} }
} }
#[macro_export]
macro_rules! derive_ccf {
($CF:ty; $( $T:ty ),* ) => {
impl ContextComponentFactory for $CF {
fn build_from_context(&self, context: &Context) -> Result<Self::Output, String> {
let input = from_context!(context; $($T),*);
self.build(input)
}
}
}
}
#[macro_export]
macro_rules! from_context {
($context:expr; $( $T:ty ),* ) => {
(
$(
FromContext::from($context).ok_or_else(|| {
format!(
"Could not find retrieve component of type {} from context",
type_name::<$T>()
)
})?,
)*
)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[derive(Debug, Eq, PartialEq)]
struct A(&'static str);
#[derive(Debug, Eq, PartialEq)]
struct B(u32);
#[test]
fn test_from_context_macro() {
// Given
fn get_input(context: &Context) -> Result<(Component<A>, Component<B>), String> {
Ok(from_context!(context; A, B))
}
let mut context = Context::new();
context.set(A("Test"));
context.set(B(67));
// When
let (comp_a, comp_b) = get_input(&context).unwrap();
// Then
assert_eq!(*comp_a.borrow(), A("Test"));
assert_eq!(*comp_b.borrow(), B(67));
}
#[derive(Debug, Eq, PartialEq)]
struct C(&'static str, u32);
struct CFactory;
impl ComponentFactory for CFactory {
type Input = (Component<A>, Component<B>);
type Output = C;
fn build(&self, (comp_a, comp_b): Self::Input) -> Result<Self::Output, String> {
Ok(C(comp_a.borrow().0, comp_b.borrow().0))
}
}
#[test]
fn test_derive_ccf_macro() {
// Given
derive_ccf!(CFactory; A, B);
let c_factory = CFactory;
let mut context = Context::new();
context.set(A("test"));
context.set(B(67));
// When
let c = c_factory.build_from_context(&context).unwrap();
assert_eq!(c, C("test", 67));
}
}

@ -19,10 +19,14 @@ impl ComponentMap {
} }
pub fn get<T: Any + Sized + 'static>(&self) -> Option<Component<T>> { pub fn get<T: Any + Sized + 'static>(&self) -> Option<Component<T>> {
self.0.get(&TypeId::of::<T>()).cloned().map(|c| c.try_into().unwrap()) self.0
.get(&TypeId::of::<T>())
.cloned()
.map(|c| c.try_into().unwrap())
} }
pub fn set<T: Any + Sized + 'static>(&mut self, component: T) { pub fn set<T: Any + Sized + 'static>(&mut self, component: T) {
self.0.insert(TypeId::of::<T>(), Rc::new(RefCell::new(component))); self.0
.insert(TypeId::of::<T>(), Rc::new(RefCell::new(component)));
} }
} }

@ -1,4 +1,4 @@
mod model_i;
mod component; mod component;
mod component_map;
mod component_factory; mod component_factory;
mod component_map;
mod model_i;

@ -43,7 +43,7 @@ pub trait FromContext: Sized {
fn from(context: &Context) -> Option<Self>; fn from(context: &Context) -> Option<Self>;
} }
impl <T: Any + Sized + 'static> FromContext for Component<T> { impl<T: Any + Sized + 'static> FromContext for Component<T> {
fn from(context: &Context) -> Option<Self> { fn from(context: &Context) -> Option<Self> {
context.get() context.get()
} }
@ -96,8 +96,8 @@ mod tests {
#[derive(Debug, Eq, PartialEq)] #[derive(Debug, Eq, PartialEq)]
struct TestStruct(&'static str); struct TestStruct(&'static str);
let context = Context::new(); let context = Context::new();
let subcontext = { let subcontext = {
let mut tmp = context.subcontext(); let mut tmp = context.subcontext();
tmp.set(TestStruct("hello")); tmp.set(TestStruct("hello"));
tmp tmp
}; };

@ -9,7 +9,6 @@ use battle::skill::*;
use battle::uic::Uic; use battle::uic::Uic;
use context::Context; use context::Context;
fn main() { fn main() {
println!("Hello, world!"); println!("Hello, world!");

Loading…
Cancel
Save