extern crate sha2;
extern crate hmac;
extern crate hex;
extern crate byteorder;
use std::io::Cursor;
use byteorder::{ReadBytesExt, BigEndian};
use sha2::{Sha256, Digest};
use hmac::{Hmac, Mac};
type HmacSha256 = Hmac<Sha256>;
use std::fmt;
pub struct Game {
pub hash: Vec<u8>
}
impl Game {
pub fn new(s: &String) -> Option<Game> {
if s.len() != 64 {
return None
}
match hex::decode(s) {
Ok(val) => {
Some(Game {
hash: val
})
}
Err(_err) => {
None
}
}
}
pub fn outcome(&self) -> f64 {
const U64_SIZE:u32 = 64;
const SEED:&'static [u8; 64] = b"0000000000000000004d6ec16dafe9d8370958664c1dc422f452892264c59526";
const NUM_BITS:u32 = 52;
const POW2:f64 = 1.0 / 4503599627370496.0;
const MASK:u64 = 0b11111111_11111111_11111111_11111111_11111111_11111111_11110000_00000000;
let mut mac = HmacSha256::new_varkey(SEED).expect("HMAC should accept Seed as key");
mac.input(&self.hash);
let result = mac.result();
let code_bytes = result.code();
let mut rdr = Cursor::new(code_bytes);
let r:u64 = (rdr.read_u64::<BigEndian>().unwrap() & MASK) >> (U64_SIZE - NUM_BITS);
let x1 = r as f64 * POW2;
let x:f64 = 99.0 / (1.0 - x1);
let result:f64 = x.floor() / 100.0;
result.max(1.0)
}
}
impl PartialEq for Game {
fn eq(self: &Self, another: &Game) -> bool {
self.hash == another.hash
}
}
impl IntoIterator for Game {
type Item = Game;
type IntoIter = GameIntoIterator;
fn into_iter(self) -> Self::IntoIter {
GameIntoIterator {
hash: self.hash.clone(),
game: self,
index: 0,
}
}
}
pub struct GameIntoIterator {
game: Game,
hash: Vec<u8>,
index: usize
}
impl Iterator for GameIntoIterator {
type Item = Game;
fn next(&mut self) -> Option<Game> {
let mut hasher = Sha256::new();
hasher.input(&hex::encode(self.hash.clone())); let result = hasher.result().to_vec();
self.hash = result.clone();
self.index = self.index + 1;
self.game = Game {
hash: result
};
Some(self.game.clone())
}
}
impl Clone for Game {
fn clone(&self) -> Game {
Game {
hash: self.hash.clone()
}
}
}
impl fmt::Display for Game {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Game’s hash: {} Bust: {}", hex::encode(&self.hash), self.outcome())
}
}
impl fmt::Debug for Game {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Game’s hash: {} Bust: {}", hex::encode(&self.hash), self.outcome())
}
}