Skip to content

Instantly share code, notes, and snippets.

@Cranc
Last active July 26, 2016 09:10
Show Gist options
  • Save Cranc/69be8f2d806b7abed7aa29f2b7a49b4b to your computer and use it in GitHub Desktop.
Save Cranc/69be8f2d806b7abed7aa29f2b7a49b4b to your computer and use it in GitHub Desktop.
achievment system for creating, maintaining and updating of achievments in rust
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