Last active
July 26, 2016 09:10
-
-
Save Cranc/69be8f2d806b7abed7aa29f2b7a49b4b to your computer and use it in GitHub Desktop.
achievment system for creating, maintaining and updating of achievments in rust
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::collections::{HashMap, HashSet}; | |
/// <summary> | |
/// | |
/// </summary> | |
/// <param name=""></param> | |
fn main() { | |
let mut ach_dic = Achiev::new(); | |
println!("add property kill cats with kill > 10"); | |
ach_dic.define_property("kill cats",0,ACTIVE_IF_GREATER_THAN,10); | |
let mut hset = HashSet::new(); | |
hset.insert("kill cats"); | |
println!("add property kill cats to achievment you killed 10 cats"); | |
ach_dic.define_achievment("you killed 10 cats",hset); | |
println!("check for solved achievments"); | |
for i in ach_dic.check_achievments() { | |
println!("solved: {:?}", i); | |
} | |
println!("kill 11 cats"); | |
println!("check for solved achievments"); | |
match ach_dic.set_value("kill cats",11) { | |
Ok(_) => println!("Success"), | |
Err(_) => println!("Failure"), | |
} | |
println!("dictionary value {}",ach_dic.property_dictionary["kill cats"].value); | |
for i in ach_dic.check_achievments() { | |
println!("solved: {:?}", i); | |
} | |
} | |
/// <summary> | |
/// enum Error contains a number of erros that can occure in achievment calls. | |
/// </summary> | |
#[allow(dead_code)] | |
enum Error { | |
NoKeyFound, | |
NoKeyFoundAt(String), | |
NotAValidRule(String), | |
NoTagsFound, | |
} | |
/// <summary> | |
/// enum Success contains success messages send by some functions. | |
/// </summary> | |
#[allow(dead_code)] | |
enum Success { | |
SetSuccessfull, | |
ResetSuccessfull, | |
} | |
#[derive(Copy, Clone)] | |
enum PropertyTags {CollectPlants, MineBlocks, PlaceBlocks, } | |
/// activation rules | |
#[allow(dead_code)] | |
const ACTIVE_IF_GREATER_THAN: &'static str = ">"; | |
#[allow(dead_code)] | |
const ACTIVE_IF_LESS_THAN: &'static str = "<"; | |
#[allow(dead_code)] | |
const ACTIVE_IF_EQUALS_TO: &'static str = "=="; | |
/// <summary> | |
/// Contains information of prerequisits for Achievments | |
/// </summary> | |
/// <param name="name">contains name of property</param> | |
/// <param name="value">contains current value of property</param> | |
/// <param name="activation">contains the rule for the activation (see activation rules)</param> | |
/// <param name="activationvalue">contains value needed for activation</param> | |
/// <param name="initialvalue">contains the initial value</param> | |
// #[allow(dead_code)] | |
#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)] | |
struct Property<'a> { | |
name: &'a str, | |
value: i32, | |
activation: &'a str, | |
activationvalue: i32, | |
initialvalue: i32, | |
} | |
#[allow(dead_code)] | |
impl<'a> Property<'a> { | |
fn new(name: &'a str, | |
initialvalue: i32, | |
activationvalue: i32, | |
activationrule: &'a str, | |
) | |
-> Property<'a> { | |
Property { | |
name: name, | |
value: initialvalue, | |
initialvalue: initialvalue, | |
activationvalue: activationvalue, | |
activation: activationrule, | |
} | |
} | |
/// <summary> | |
/// set_value sets the value of the property | |
/// </summary> | |
/// <param name="val">contains value to change to.</param> | |
fn set_value(&mut self, val: i32) { | |
self.value = val; | |
} | |
/// <summary> | |
/// is_active checks if property is already unlocked. | |
/// </summary> | |
fn is_active(&self) -> Result<bool, Error> { | |
match self.activation { | |
ACTIVE_IF_GREATER_THAN => Ok(&self.value > &self.activationvalue), | |
ACTIVE_IF_LESS_THAN => Ok(&self.value < &self.activationvalue), | |
ACTIVE_IF_EQUALS_TO => Ok(&self.value == &self.activationvalue), | |
_ => Err(Error::NotAValidRule(self.activation.to_string())), | |
} | |
} | |
fn reset(&mut self) { | |
self.value = self.activationvalue; | |
} | |
} | |
/// <summary> | |
/// Contains information of prerequisits for Achievments | |
/// </summary> | |
/// <param name="name">contains name of achievment</param> | |
/// <param name="props">contains vector with all propertys</param> | |
/// <param name="unlocked">contains information about status of achievment</param> | |
#[allow(dead_code)] | |
struct Achievment<'a> { | |
name: &'a str, | |
props: HashSet<&'a str>, | |
unlocked: bool, | |
} | |
#[allow(dead_code)] | |
impl<'a> Achievment<'a> { | |
fn new(name: &'a str, props: HashSet<&'a str>) -> Achievment<'a> { | |
Achievment { | |
name: name, | |
props: props, | |
unlocked: false, | |
} | |
} | |
/// <summary> | |
/// set_unlocked sets the achievment to the given value | |
/// </summary> | |
/// <param name="val">contains value to define status of achievment.</param> | |
fn set_unlocked(&mut self, val: bool) { | |
self.unlocked = val; | |
} | |
//TODO: implement contains method that checks if achievment contains property | |
} | |
/// <summary> | |
/// Contains dictionarys of all achievments and prerequisits | |
/// </summary> | |
/// <param name="property_dictionary">contains all propertys</param> | |
/// <param name="achievment_dictionary">contains all achievments</param> | |
#[allow(dead_code)] | |
struct Achiev<'a> { | |
property_dictionary: HashMap<&'a str, Property<'a>>, | |
achievment_dictionary: HashMap<&'a str, Achievment<'a>>, | |
} | |
#[allow(dead_code)] | |
impl<'a> Achiev<'a> { | |
fn new() -> Achiev<'a> { | |
Achiev { | |
property_dictionary: HashMap::new(), | |
achievment_dictionary: HashMap::new(), | |
} | |
} | |
/// <summary> | |
/// define_property adds a new property to its dictionary. | |
/// </summary> | |
/// <param name"name">name to identify the property with.</param> | |
/// <param name"initialvalue">value that defines the startpoint of property.</param> | |
/// <param name"activationrule">rule that defines the logic prerequisits fo activation.</param> | |
/// <param name"value">value that defines the activationvalue of the property.</param> | |
fn define_property(&mut self, | |
name: &'a str, | |
initialvalue: i32, | |
activationrule: &'a str, | |
value: i32) { | |
self.property_dictionary.insert(name, | |
Property::new(name, initialvalue, value, activationrule)); | |
} | |
/// <summary> | |
/// define_property adds a new property to its dictionary. | |
/// </summary> | |
/// <param name"name">name to identify the achievment with.</param> | |
/// <param name"related_props"> | |
/// contains a Hashset of propertys associated with achievment. | |
/// </param> | |
fn define_achievment(&mut self, name: &'a str, related_props: HashSet<&'a str>) { | |
self.achievment_dictionary.insert(name, Achievment::new(name, related_props)); | |
} | |
/// <summary> | |
/// get_value returns current value of given property. | |
/// </summary> | |
/// <param name="property_name">contains the name of the property.</param> | |
fn get_value(&self, property_name: &str) -> Result<i32, Error> { | |
match self.property_dictionary.get(property_name) { | |
Some(review) => Ok(review.value), | |
None => Err(Error::NoKeyFound), | |
} | |
} | |
/// <summary> | |
/// set_value sets current value of given property. | |
/// </summary> | |
/// <param name="property_name">contains the name of the property.</param> | |
/// <param name="value">contains the value the property is set to.</param> | |
fn set_value(&mut self, property_name: &str, value: i32) -> Result<Success, Error> { | |
match self.property_dictionary.get_mut(property_name) { | |
Some(review) => { | |
let greater = |x, y| { | |
if x > y { | |
x | |
} else { | |
y | |
} | |
}; | |
let lesser = |x, y| { | |
if x < y { | |
x | |
} else { | |
y | |
} | |
}; | |
let equal = |x, y| { | |
if x == y { | |
x | |
} else { | |
y | |
} | |
}; | |
let val = match review.activation { | |
ACTIVE_IF_GREATER_THAN => greater(value, review.value), | |
ACTIVE_IF_LESS_THAN => lesser(value, review.value), | |
ACTIVE_IF_EQUALS_TO => equal(value, review.value), | |
_ => return Err(Error::NotAValidRule(review.activation.to_string())), | |
}; | |
review.set_value(val); | |
Ok(Success::SetSuccessfull) | |
} | |
None => Err(Error::NoKeyFound), | |
} | |
} | |
/// <summary> | |
/// add_value adds current value to all given property. | |
/// </summary> | |
/// <param name="property_names">contains the names of the propertys.</param> | |
/// <param name="value">contains the value the property is set to.</param> | |
fn add_value(&mut self, property_names: Vec<&str>, value: i32) -> Result<Success, Error> { | |
for i in property_names { | |
match self.property_dictionary.get_mut(i) { | |
Some(review) => review.set_value(value), | |
None => return Err(Error::NoKeyFoundAt(i.to_string())), | |
} | |
} | |
Ok(Success::SetSuccessfull) | |
} | |
/// <summary> | |
/// check_achievments checks if new achievments are completed and | |
/// returns the new completed ones. | |
/// </summary> | |
fn check_achievments(&mut self) -> Result<Vec<&str>, Error> { | |
let mut vec = Vec::new(); | |
for (k, mut v) in &mut self.achievment_dictionary { | |
if v.unlocked == true { | |
continue; | |
} | |
let mut active_probs = 0; | |
for p in &mut v.props.iter() { | |
let pro = match self.property_dictionary.get(p) { | |
Some(v) => v, | |
None => return Err(Error::NoKeyFoundAt(p.to_string())), | |
}; | |
match pro.is_active() { | |
Ok(v) => { | |
if v == true { | |
active_probs += 1 | |
} | |
} | |
Err(e) => return Err(e), | |
} | |
} | |
if active_probs == v.props.len() { | |
v.set_unlocked(true); | |
vec.push(k.clone()); | |
} | |
} | |
Ok(vec) | |
} | |
fn reset_property(&mut self, property_name: &str) -> Result<Success, Error> { | |
match self.property_dictionary.get_mut(property_name) { | |
Some(v) => v.reset(), | |
None => return Err(Error::NoKeyFoundAt(property_name.to_string())), | |
} | |
// TODO: implement call to achievment::contains and set unlocked of all achievments that have | |
// the reseted property | |
Ok(Success::ResetSuccessfull) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment