<commit_before>extern crate regex;
extern crate chrono;
extern crate libc;
extern crate clap;
extern crate clipboard;

use regex::{Regex};
use std::collections::HashMap;

use chrono::*;

use libc::system;
use std::ffi::{CString, CStr};
use std::os::raw::c_char;

use clap::{Arg};
use clap::App;

use clipboard::ClipboardContext;

use std::io;
use std::io::prelude::*;
use std::fs::File;
use std::io::BufReader;
use std::io::SeekFrom;

use std::fmt;

use std::{thread, time};

mod structs;

fn speak(data: &CStr) {
    extern { fn system(data: *const c_char); }

    unsafe { system(data.as_ptr()) }
}

fn main()
{
    let matches = App::new("ACT_linux")
        .version("0.0.1")
        .author("Bergman. <Morindhal@gmail.com>")
        .about("Parses EQ2 logs")
            .arg(Arg::with_name("FILE")
                .help("Sets the log-file to use")
                .required(true)
                .index(1))
            .arg(Arg::with_name("player")
                .required(true)
                .help("Sets the character name to parse, this only catches the YOU and YOUR lines"))
        .get_matches();
    let from_file = matches.value_of("FILE").unwrap();
    let player = matches.value_of("player").unwrap();
    let f = File::open(from_file).unwrap();
    let mut ctx = ClipboardContext::new().unwrap();
    /*{
        Ok(file) => file,
        Err(e) =>
        {
            println!("{}", e);
        }
    };*/
    //Start a encounter, this code will be moved into the main loop when it works
    let mut encounters: Vec<structs::Encounter> = Vec::new();

    let re = Regex::new(r"\((?P<time>\d+)\)\[(?P<datetime>(\D|\d)+)\] (?P<attacker>\D*?)(' |'s |YOUR |YOU )(?P<attack>\D*)(((multi attack)|hits|hit|flurry)|(( multi attacks)| hits| hit)) (?P<target>\D+) (?P<crittype>\D+) (?P<damage>\d+) (?P<damagetype>[A-Za-z]+) damage").unwrap();
    let timeparser = Regex::new(r"(?P<day_week>[A-Za-z]+) (?P<month>[A-Za-z]+)  (?P<day_month>\d+) (?P<hour>\d+):(?P<minute>\d+):(?P<second>\d+) (?P<year>\d+)").unwrap();

    let mut file = BufReader::new(&f);
    file.seek(SeekFrom::End(-10));

    let mut buffer = String::new();
    let mut battle_timer = time::Instant::now();
    let mut fightdone = true;
    'main: loop
    {
        buffer.clear();
        if file.read_line(&mut buffer).unwrap() > 0
        {
            let triggerbuffer = buffer.clone();
            thread::spawn( move ||
            {
                let mut triggers: HashMap<&str, Regex> = HashMap::new();
                    triggers.insert("Ruling I am", Regex::new(r".*I rule.*").unwrap());
                    triggers.insert("Verily", Regex::new(r".*i also rule.*").unwrap());
                for (trigger, trigged) in triggers.iter()
                {
                    match trigged.captures(triggerbuffer.as_str()) {None => {}, Some(cap) =>
                    {
                        speak(&CString::new(format!("espeak \"{}\"", trigger)).unwrap());
                    }};
                }
            });
            match re.captures(buffer.as_str()) {None => {}, Some(cap) =>
            {
                match timeparser.captures(cap.name("datetime").unwrap()) {None => {}, Some(time_cap) =>
                {
                    //println!("{}",cap.name("attack").unwrap());
                    let parsed_time = UTC
                                            .ymd(
                                                time_cap.name("year").unwrap().parse::<i32>().unwrap(),
                                                match time_cap.name("month").unwrap() {"Jan"=>0, "Feb"=>1, "Mar"=>2, "Apr"=>3,  "May"=>4, "Jun"=>5, "Jul"=>6, "Aug"=>7, "Sep"=>8, "Oct"=>9, "Nov"=>10, "Dec"=>11, _=>0},
                                                time_cap.name("day_month").unwrap().parse::<u32>().unwrap())
                                            .and_hms(
                                                time_cap.name("hour").unwrap().parse::<u32>().unwrap(),
                                                time_cap.name("minute").unwrap().parse::<u32>().unwrap(),
                                                time_cap.name("second").unwrap().parse::<u32>().unwrap()
                                                );
                if fightdone
                {
                    println!("\n\n\n\n\n");
                    encounters.push(structs::Encounter{ attackers: Vec::new(), encounter_start: parsed_time, encounter_end: parsed_time, encounter_duration : 0, player : String::from(player.clone()) });
                    fightdone = false;
                }
                encounters.last_mut().unwrap().attack(cap);
                encounters.last_mut().unwrap().encounter_duration = 0;// encounters.last_mut().unwrap().encounter_start.elapsed();
                encounters.last_mut().unwrap().encounter_end = parsed_time; //assume every line ends things
                battle_timer = time::Instant::now();
                }};
                }
            };
        }
        else
        {
            thread::sleep(time::Duration::from_millis(100));
        }
        if battle_timer.elapsed() >= time::Duration::from_millis(3000)
        {
            if !fightdone
            {
                encounters.last_mut().unwrap().attackers.sort();
                println!("{}", encounters.last().unwrap());;
                match ctx.set_contents(format!("{}", encounters.last().unwrap()))
                {
                    Ok(_)=>{},
                    Err(e)=>println!("Clipboard error: {}", e)
                }
                fightdone = true;
            }
        }
    }
}

/*
(1477272172)[Mon Oct 24 03:22:52 2016] YOUR Raging Whirlwind multi attacks Bonesnapper for a critical of 38996 cold damage.\r\n
(1477272172)[Mon Oct 24 03:22:52 2016] Kabernet\'s Asylum multi attacks Bonesnapper for a critical of 36622 mental damage.\r\n
(1478123041)[Wed Nov  2 22:44:01 2016] YOU hit training dummy for a critical of 377262 heat damage.
(1478123041)[Wed Nov  2 22:44:01 2016] YOU multi attack training dummy for a critical of 148320 heat damage.
(1478132824)[Thu Nov  3 01:27:04 2016] Devorstator's Impatience heals Devorstator for 43947 hit points.

println!("{}",buffer

DATASTRUCTURE:
I should probably parse attacks into vectors as well, as there are a limited number of attacks viable and I am likely to want to be able to output all of a specific attack or the total damage of one particular attack
    This is advanced though so I won't do it for the first iteration of the program.

what I should be able to do:

* printout a full encounter as player dps, sorted by dps.
** This should be calculated by final damage divided by encounter_time in seconds

* printout a full encounter as player hps, sorted by hps
** This should be calculated by final healed divided by encounter_time in seconds

*/
<commit_msg>Removed old comments.<commit_after>extern crate regex;
extern crate chrono;
extern crate libc;
extern crate clap;
extern crate clipboard;

use regex::{Regex};
use std::collections::HashMap;

use chrono::*;

use libc::system;
use std::ffi::{CString, CStr};
use std::os::raw::c_char;

use clap::{Arg};
use clap::App;

use clipboard::ClipboardContext;

use std::io;
use std::io::prelude::*;
use std::fs::File;
use std::io::BufReader;
use std::io::SeekFrom;

use std::fmt;

use std::{thread, time};

mod structs;

fn speak(data: &CStr) {
    extern { fn system(data: *const c_char); }

    unsafe { system(data.as_ptr()) }
}

fn main()
{
    let matches = App::new("ACT_linux")
        .version("0.0.1")
        .author("Bergman. <Morindhal@gmail.com>")
        .about("Parses EQ2 logs")
            .arg(Arg::with_name("FILE")
                .help("Sets the log-file to use")
                .required(true)
                .index(1))
            .arg(Arg::with_name("player")
                .required(true)
                .help("Sets the character name to parse, this only catches the YOU and YOUR lines"))
        .get_matches();
    let from_file = matches.value_of("FILE").unwrap();
    let player = matches.value_of("player").unwrap();
    let f = File::open(from_file).unwrap();
    let mut ctx = ClipboardContext::new().unwrap();
    /*{
        Ok(file) => file,
        Err(e) =>
        {
            println!("{}", e);
        }
    };*/
    let mut encounters: Vec<structs::Encounter> = Vec::new();

    let re = Regex::new(r"\((?P<time>\d+)\)\[(?P<datetime>(\D|\d)+)\] (?P<attacker>\D*?)(' |'s |YOUR |YOU )(?P<attack>\D*)(((multi attack)|hits|hit|flurry)|(( multi attacks)| hits| hit)) (?P<target>\D+) (?P<crittype>\D+) (?P<damage>\d+) (?P<damagetype>[A-Za-z]+) damage").unwrap();
    let timeparser = Regex::new(r"(?P<day_week>[A-Za-z]+) (?P<month>[A-Za-z]+)  (?P<day_month>\d+) (?P<hour>\d+):(?P<minute>\d+):(?P<second>\d+) (?P<year>\d+)").unwrap();

    let mut file = BufReader::new(&f);
    file.seek(SeekFrom::End(0));

    let mut buffer = String::new();
    let mut battle_timer = time::Instant::now();
    let mut fightdone = true;
    'main: loop
    {
        buffer.clear();
        if file.read_line(&mut buffer).unwrap() > 0
        {
            let triggerbuffer = buffer.clone();
            thread::spawn( move ||
            {
                let mut triggers: HashMap<&str, Regex> = HashMap::new();
                    triggers.insert("Ruling I am", Regex::new(r".*I rule.*").unwrap());
                    triggers.insert("Verily", Regex::new(r".*i also rule.*").unwrap());
                for (trigger, trigged) in triggers.iter()
                {
                    match trigged.captures(triggerbuffer.as_str()) {None => {}, Some(cap) =>
                    {
                        speak(&CString::new(format!("espeak \"{}\"", trigger)).unwrap());
                    }};
                }
            });
            match re.captures(buffer.as_str()) {None => {}, Some(cap) =>
            {
                match timeparser.captures(cap.name("datetime").unwrap()) {None => {}, Some(time_cap) =>
                {
                    //println!("{}",cap.name("attack").unwrap());
                    let parsed_time = UTC
                                            .ymd(
                                                time_cap.name("year").unwrap().parse::<i32>().unwrap(),
                                                match time_cap.name("month").unwrap() {"Jan"=>0, "Feb"=>1, "Mar"=>2, "Apr"=>3,  "May"=>4, "Jun"=>5, "Jul"=>6, "Aug"=>7, "Sep"=>8, "Oct"=>9, "Nov"=>10, "Dec"=>11, _=>0},
                                                time_cap.name("day_month").unwrap().parse::<u32>().unwrap())
                                            .and_hms(
                                                time_cap.name("hour").unwrap().parse::<u32>().unwrap(),
                                                time_cap.name("minute").unwrap().parse::<u32>().unwrap(),
                                                time_cap.name("second").unwrap().parse::<u32>().unwrap()
                                                );
                if fightdone
                {
                    println!("\n\n\n\n\n");
                    encounters.push(structs::Encounter{ attackers: Vec::new(), encounter_start: parsed_time, encounter_end: parsed_time, encounter_duration : 0, player : String::from(player.clone()) });
                    fightdone = false;
                }
                encounters.last_mut().unwrap().attack(cap);
                encounters.last_mut().unwrap().encounter_duration = 0;// encounters.last_mut().unwrap().encounter_start.elapsed();
                encounters.last_mut().unwrap().encounter_end = parsed_time; //assume every line ends things
                battle_timer = time::Instant::now();
                }};
                }
            };
        }
        else
        {
            thread::sleep(time::Duration::from_millis(100));
        }
        if battle_timer.elapsed() >= time::Duration::from_millis(3000)
        {
            if !fightdone
            {
                encounters.last_mut().unwrap().attackers.sort();
                println!("{}", encounters.last().unwrap());;
                match ctx.set_contents(format!("{}", encounters.last().unwrap()))
                {
                    Ok(_)=>{},
                    Err(e)=>println!("Clipboard error: {}", e)
                }
                fightdone = true;
            }
        }
    }
}

/*
(1477272172)[Mon Oct 24 03:22:52 2016] YOUR Raging Whirlwind multi attacks Bonesnapper for a critical of 38996 cold damage.\r\n
(1477272172)[Mon Oct 24 03:22:52 2016] Kabernet\'s Asylum multi attacks Bonesnapper for a critical of 36622 mental damage.\r\n
(1478123041)[Wed Nov  2 22:44:01 2016] YOU hit training dummy for a critical of 377262 heat damage.
(1478123041)[Wed Nov  2 22:44:01 2016] YOU multi attack training dummy for a critical of 148320 heat damage.
(1478132824)[Thu Nov  3 01:27:04 2016] Devorstator's Impatience heals Devorstator for 43947 hit points.

println!("{}",buffer

*/
<|endoftext|>


<commit_before>trait Normalize {
  fn normalize(&self) -> Self;
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum Const {
  Data,
  Codata,
}

impl Normalize for Const {
  fn normalize(&self) -> Const {
    *self
  }
}

impl ToString for Const {
  fn to_string(&self) -> String {
    match *self {
      Const::Data => "data".to_string(),
      Const::Codata => "codata".to_string(),
    }
  }
}

#[derive(Clone, Debug, Eq, PartialEq)]
struct Var {
  name: String,
  idx: i32,
}

impl Var {
  pub fn new(name: &str, idx: i32) -> Var {
    Var {
      name: name.to_string(),
      idx: idx,
    }
  }
}

fn vn(name: &str, idx: i32) -> Var {
  Var::new(name, idx)
}

fn v(name: &str) -> Var {
  vn(name, 0)
}

impl Normalize for Var {
  fn normalize(&self) -> Var {
    self.clone()
  }
}

impl ToString for Var {
  fn to_string(&self) -> String {
    if self.idx == 0 {
      self.name.clone()
    } else {
      self.name.clone() + "@" + &self.idx.to_string()
    }
  }
}

#[derive(Clone, Debug, Eq, PartialEq)]
enum Expr {
  // Type system constants
  Const(Const),
  // Bound variables
  Var(Var),
  // Lambda
  Lam(Var, Box<Expr>, Box<Expr>),
  // "forall"
  Pi(Var, Box<Expr>, Box<Expr>),
  // Function application
  App(Box<Expr>, Box<Expr>),
}

impl Expr {
  pub fn constant(constant: Const) -> Expr {
    Expr::Const(constant)
  }
  pub fn var(v: &Var) -> Expr {
    Expr::Var(v.clone())
  }
  pub fn lam(var: Var, ty: Expr, body: Expr) -> Expr {
    Expr::Lam(var, Box::new(ty), Box::new(body))
  }
  pub fn pi(var: Var, ty: Expr, body: Expr) -> Expr {
    Expr::Pi(var, Box::new(ty), Box::new(body))
  }
  pub fn app(f: Expr, arg: Expr) -> Expr {
    Expr::App(Box::new(f), Box::new(arg))
  }

  pub fn is_constant(&self) -> bool {
    match *self {
      Expr::Const(_) => true,
      _ => false,
    }
  }
  pub fn is_var(&self) -> bool {
    use Expr::*;
    match *self {
      Var(_) => true,
      _ => false,
    }
  }
  pub fn is_lam(&self) -> bool {
    match *self {
      Expr::Lam(_, _, _) => true,
      _ => false,
    }
  }
  pub fn is_pi(&self) -> bool {
    match *self {
      Expr::Pi(_, _, _) => true,
      _ => false,
    }
  }
  pub fn is_app(&self) -> bool {
    match *self {
      Expr::App(_, _) => true,
      _ => false,
    }
  }
}

fn constant(c: Const) -> Expr {
  Expr::constant(c)
}
fn var(v: &Var) -> Expr {
  Expr::var(v)
}
fn lam(var: Var, ty: Expr, body: Expr) -> Expr {
  Expr::lam(var, ty, body)
}
fn pi(var: Var, ty: Expr, body: Expr) -> Expr {
  Expr::pi(var, ty, body)
}
fn app(f: Expr, arg: Expr) -> Expr {
  Expr::app(f, arg)
}

fn replace(val: &Var, with: &Expr, body: &Box<Expr>) -> Expr {
  use Expr::*;
  println!("replacing {} with {} in {}",
           val.to_string(),
           with.to_string(),
           body.to_string());
  // *body.clone()
  match **body {
    Const(ref constant) => *body.clone(), //Const(constant),
    Var(ref var) => {
      println!("replacing var");
      if var.to_string() == val.to_string() {
        println!("  eq -> replacing");
        with.clone()
      } else {
        println!("  no change");
        Var(var.clone())
      }
    }
    Lam(ref var, ref ty, ref body) => {
      // println!("  lam");
      let ty = Box::new(replace(val, &with.clone(), &ty));
      // let body = Box::new(replace(val, with, &body));
      Lam(var.clone(), ty.clone(), body.clone())
      // panic!("Lam")
      // Lam(var.clone(),
      //     Box::new(replace(val.clone(), with.clone(), ty.clone())),
      //     Box::new(replace(val.clone(), with.clone(), body.clone())))
    }
    Pi(ref var, ref ty, ref body) => panic!("Pi"),
    App(ref f, ref arg) => panic!("App"), //replace(val, with, f.clone()),
  }
}

impl Normalize for Expr {
  fn normalize(&self) -> Expr {
    use Expr::*;
    println!("normalize {}", self.to_string());
    match *self {
      Const(ref constant) => Const(constant.normalize()),
      Var(ref var) => Var(var.normalize()),
      Lam(ref var, ref ty, ref body) => {
        let l = &Lam(var.normalize(),
                     Box::new(ty.normalize()),
                     Box::new(body.normalize()));
        l.clone()
      }
      Pi(ref var, ref ty, ref body) => {
        let p = &Pi(var.normalize(),
                    Box::new(ty.normalize()),
                    Box::new(body.normalize()));
        p.clone()
      }
      App(ref f, ref arg) => {
        let f = f.normalize();
        let arg = arg.normalize();
        if let Lam(var, ty, body) = f {
          replace(&var, &arg, &body)
          // Lam(var, ty, body)
        } else if let Pi(var, ty, body) = f {
          replace(&var, &arg, &body)
        } else {
          panic!("f isn't a function {}", f.to_string())
        }
      }
    }
  }
}

impl ToString for Expr {
  fn to_string(&self) -> String {
    use Expr::*;
    match *self {
      Const(ref constant) => constant.to_string(),
      Var(ref var) => var.to_string(),
      Lam(ref var, ref ty, ref body) => {
        "(".to_string() + &var.to_string() + " : " + &ty.to_string() + ") -> " +
        &body.to_string()
      }
      Pi(ref var, ref ty, ref body) => {
        "forall (".to_string() + &var.to_string() + " : " + &ty.to_string() +
        ") -> " + &body.to_string()
      }
      App(ref f, ref arg) => {
        if f.is_lam() || f.is_pi() {
          "(".to_string() + &f.to_string() + ") " + &arg.to_string()
        } else {
          f.to_string() + " " + &arg.to_string()
        }
      }
    }
  }
}

// trait Ctor {}

// impl Ctor for Expr

fn main() {
  println!("{}", Const::Data.to_string());
  let a = v("a");
  let x = v("x");
  let expra = var(&a);
  let exprx = var(&x);
  println!("{}", x.to_string());
  let id = pi(a.clone(), constant(Const::Data), lam(x, expra, exprx));
  println!("{}", id.to_string());
  let apply_int = app(id.clone(), var(&v("int")));
  println!("{}", apply_int.normalize().to_string());
  let apply_id = app(app(id, var(&v("int"))), var(&v("1")));
  println!("{}", apply_id.to_string());
  println!("{}", apply_id.normalize().to_string());
}

#[test]
fn test_to_string() {
  let codata = Const::Codata;
  println!("{}", codata.to_string());
  assert_eq!("codata", codata.to_string());
  let a = v("a");
  let x = v("x");
  let expra = var(&a);
  let exprx = var(&x);
  println!("{}", x.to_string());
  assert_eq!("x", x.to_string());
  let id = pi(a.clone(), constant(Const::Data), lam(x, expra, exprx));
  println!("{}", id.to_string());
  assert_eq!("forall (a : data) -> (x : a) -> x", id.to_string());
  let apply_id = app(app(id, var(&v("int"))), var(&v("1")));
  println!("{}", apply_id.to_string());
  assert_eq!("(forall (a : data) -> (x : a) -> x) int 1",
             apply_id.to_string());
}
<commit_msg>Clean up?<commit_after>trait Normalize {
  fn normalize(&self) -> Self;
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum Const {
  Data,
  Codata,
}

impl Normalize for Const {
  fn normalize(&self) -> Const {
    *self
  }
}

impl ToString for Const {
  fn to_string(&self) -> String {
    match *self {
      Const::Data => "data".to_string(),
      Const::Codata => "codata".to_string(),
    }
  }
}

#[derive(Clone, Debug, Eq, PartialEq)]
struct Var {
  name: String,
  idx: i32,
}

impl Var {
  pub fn new(name: &str, idx: i32) -> Var {
    Var {
      name: name.to_string(),
      idx: idx,
    }
  }
}

impl Normalize for Var {
  fn normalize(&self) -> Var {
    self.clone()
  }
}

impl ToString for Var {
  fn to_string(&self) -> String {
    if self.idx == 0 {
      self.name.clone()
    } else {
      self.name.clone() + "@" + &self.idx.to_string()
    }
  }
}

#[derive(Clone, Debug, Eq, PartialEq)]
enum Expr {
  // Type system constants
  Const(Const),
  // Bound variables
  Var(Var),
  // Lambda
  Lam(Var, Box<Expr>, Box<Expr>),
  // "forall"
  Pi(Var, Box<Expr>, Box<Expr>),
  // Function application
  App(Box<Expr>, Box<Expr>),
}

impl Expr {
  pub fn constant(constant: Const) -> Expr {
    Expr::Const(constant)
  }
  pub fn var(v: &Var) -> Expr {
    Expr::Var(v.clone())
  }
  pub fn lam(var: Var, ty: Expr, body: Expr) -> Expr {
    Expr::Lam(var, Box::new(ty), Box::new(body))
  }
  pub fn pi(var: Var, ty: Expr, body: Expr) -> Expr {
    Expr::Pi(var, Box::new(ty), Box::new(body))
  }
  pub fn app(f: Expr, arg: Expr) -> Expr {
    Expr::App(Box::new(f), Box::new(arg))
  }

  pub fn is_constant(&self) -> bool {
    match *self {
      Expr::Const(_) => true,
      _ => false,
    }
  }
  pub fn is_var(&self) -> bool {
    match *self {
      Expr::Var(_) => true,
      _ => false,
    }
  }
  pub fn is_lam(&self) -> bool {
    match *self {
      Expr::Lam(_, _, _) => true,
      _ => false,
    }
  }
  pub fn is_pi(&self) -> bool {
    match *self {
      Expr::Pi(_, _, _) => true,
      _ => false,
    }
  }
  pub fn is_app(&self) -> bool {
    match *self {
      Expr::App(_, _) => true,
      _ => false,
    }
  }
}

fn constant(c: Const) -> Expr {
  Expr::constant(c)
}
fn var(v: &Var) -> Expr {
  Expr::var(v)
}
fn lam(var: Var, ty: Expr, body: Expr) -> Expr {
  Expr::lam(var, ty, body)
}
fn pi(var: Var, ty: Expr, body: Expr) -> Expr {
  Expr::pi(var, ty, body)
}
fn app(f: Expr, arg: Expr) -> Expr {
  Expr::app(f, arg)
}

fn replace(val: &Var, with: &Expr, body: &Box<Expr>) -> Expr {
  use Expr::*;
  println!("replacing {} with {} in {}",
           val.to_string(),
           with.to_string(),
           body.to_string());
  // *body.clone()
  match **body {
    Const(ref constant) => *body.clone(), //Const(constant),
    Var(ref var) => {
      println!("replacing var");
      if var.to_string() == val.to_string() {
        println!("  eq -> replacing");
        with.clone()
      } else {
        println!("  no change");
        Var(var.clone())
      }
    }
    Lam(ref var, ref ty, ref body) => {
      // println!("  lam");
      let ty = Box::new(replace(val, &with.clone(), &ty));
      // let body = Box::new(replace(val, with, &body));
      Lam(var.clone(), ty.clone(), body.clone())
      // panic!("Lam")
      // Lam(var.clone(),
      //     Box::new(replace(val.clone(), with.clone(), ty.clone())),
      //     Box::new(replace(val.clone(), with.clone(), body.clone())))
    }
    Pi(ref var, ref ty, ref body) => panic!("Pi"),
    App(ref f, ref arg) => panic!("App"), //replace(val, with, f.clone()),
  }
}

impl Normalize for Expr {
  fn normalize(&self) -> Expr {
    use Expr::*;
    println!("normalize {}", self.to_string());
    match *self {
      Const(ref constant) => Const(constant.normalize()),
      Var(ref var) => Var(var.normalize()),
      Lam(ref var, ref ty, ref body) => {
        let l = &Lam(var.normalize(),
                     Box::new(ty.normalize()),
                     Box::new(body.normalize()));
        l.clone()
      }
      Pi(ref var, ref ty, ref body) => {
        let p = &Pi(var.normalize(),
                    Box::new(ty.normalize()),
                    Box::new(body.normalize()));
        p.clone()
      }
      App(ref f, ref arg) => {
        let f = f.normalize();
        let arg = arg.normalize();
        if let Lam(var, ty, body) = f {
          replace(&var, &arg, &body)
          // Lam(var, ty, body)
        } else if let Pi(var, ty, body) = f {
          replace(&var, &arg, &body)
        } else {
          panic!("f isn't a function {}", f.to_string())
        }
      }
    }
  }
}

impl ToString for Expr {
  fn to_string(&self) -> String {
    use Expr::*;
    match *self {
      Const(ref constant) => constant.to_string(),
      Var(ref var) => var.to_string(),
      Lam(ref var, ref ty, ref body) => {
        "(".to_string() + &var.to_string() + " : " + &ty.to_string() + ") -> " +
        &body.to_string()
      }
      Pi(ref var, ref ty, ref body) => {
        "forall (".to_string() + &var.to_string() + " : " + &ty.to_string() +
        ") -> " + &body.to_string()
      }
      App(ref f, ref arg) => {
        if f.is_lam() || f.is_pi() {
          "(".to_string() + &f.to_string() + ") " + &arg.to_string()
        } else {
          f.to_string() + " " + &arg.to_string()
        }
      }
    }
  }
}

fn main() {
  println!("{}", Const::Data.to_string());
  let a = Var::new("a", 0);
  let x = Var::new("x", 0);
  let expra = var(&a);
  let exprx = var(&x);
  println!("{}", x.to_string());
  let id = pi(a.clone(), constant(Const::Data), lam(x, expra, exprx));
  println!("{}", id.to_string());
  let apply_int = app(id.clone(), var(&Var::new("int", 0)));
  println!("{}", apply_int.normalize().to_string());
  let apply_id = app(app(id, var(&Var::new("int", 0))), var(&Var::new("1", 0)));
  println!("{}", apply_id.to_string());
  println!("{}", apply_id.normalize().to_string());
}

#[test]
fn test_to_string() {
  let codata = Const::Codata;
  println!("{}", codata.to_string());
  assert_eq!("codata", codata.to_string());
  let a = v("a");
  let x = v("x");
  let expra = var(&a);
  let exprx = var(&x);
  println!("{}", x.to_string());
  assert_eq!("x", x.to_string());
  let id = pi(a.clone(), constant(Const::Data), lam(x, expra, exprx));
  println!("{}", id.to_string());
  assert_eq!("forall (a : data) -> (x : a) -> x", id.to_string());
  let apply_id = app(app(id, var(&v("int"))), var(&v("1")));
  println!("{}", apply_id.to_string());
  assert_eq!("(forall (a : data) -> (x : a) -> x) int 1",
             apply_id.to_string());
}
<|endoftext|>


<commit_before>use std::io::{self, BufReader, Write};
use std::io::BufRead;
use std::net::TcpStream;
use std::fs::File;

extern crate chrono;
use chrono::*;

extern crate stats;
use stats::median;

extern crate clap;
use clap::{Arg, App, ArgMatches};

mod percentile;
use percentile::percentile;

mod http_status;

mod request_response;
use request_response::*;

pub fn open_logfile(path: &str, time_filter: Option<Duration>) -> Result<(Vec<Request>,Vec<Response>), io::Error> {
    let f = try!(File::open(path));

    let f = BufReader::new(f);

    let mut requests: Vec<Request> = Vec::new();
    let mut responses: Vec<Response> = Vec::new();

    for line in f.lines() {
        let line_value = &line.unwrap();

        if line_value.contains("->") {
            let r = try!(Request::new_from_log_line(&line_value));

            if time_filter.is_none() ||
              (time_filter.is_some() && r.is_between_times(UTC::now().with_timezone(&r.time.timezone()) - time_filter.unwrap(), UTC::now().with_timezone(&r.time.timezone()))) {
                requests.push(r);
            }
        }

        if line_value.contains("<-") {
            let r = try!(Response::new_from_log_line(&line_value));
            responses.push(r);
        }

    }

    responses.sort_by_key(|r| r.id);

    Ok((requests, responses))
}

#[derive(Eq, PartialEq)]
#[derive(Debug)]
pub struct RequestLogAnalyzerResult {
    count: usize,
    max: usize,
    min: usize,
    avg: usize,
    median: usize,
    percentile90: usize,
}

pub fn analyze(request_response_pairs: &Vec<RequestResponsePair>) -> Option<RequestLogAnalyzerResult> {
    if request_response_pairs.len() == 0 {
        return None;
    }

    let times: Vec<i64> = request_response_pairs.iter()
        .map(|rr: &RequestResponsePair| -> i64 {rr.response.response_time.num_milliseconds() })
        .collect();

    let sum: usize = times.iter().sum::<i64>() as usize;
    let avg: usize = sum / times.len();

    let max: usize = *times.iter().max().unwrap() as usize;
    let min: usize = *times.iter().min().unwrap() as usize;

    let percentile90: usize = percentile(&times, 0.9) as usize;

    let median = median(times.into_iter()).unwrap() as usize;

    Some(RequestLogAnalyzerResult {
        count: request_response_pairs.len().into(),
        max: max,
        min: min,
        avg: avg,
        median: median,
        percentile90: percentile90,
    })
}

fn render_terminal(result: RequestLogAnalyzerResult) {
    println!("count:\t{}", result.count);
    println!("time.avg:\t{}", result.avg);
    println!("time.min:\t{}", result.min);
    println!("time.median:\t{}", result.median);
    println!("time.90percent:\t{}", result.percentile90);
    println!("time.max:\t{}", result.max);
}

pub fn render_graphite<T: Write>(result: RequestLogAnalyzerResult, time: DateTime<FixedOffset>, mut stream: T) {
    let mut write = |text: String| {
        stream.write(
            format!("{} {}\n", text, time.timestamp() )
            .as_bytes()
        );
    };

    write(format!("requests.count {}", result.count));
    write(format!("requests.time.max {}", result.max));
    write(format!("requests.time.min {}", result.min));
    write(format!("requests.time.avg {}", result.avg));
    write(format!("requests.time.median {}", result.median));
    write(format!("requests.time.90percent {}", result.percentile90));
}

fn parse_args<'a>() -> ArgMatches<'a> {
    App::new("Request.log Analyzer")
        .arg(Arg::with_name("filename")
            .index(1)
            .value_name("FILE")
            .required(true)
            .help("Log file to analyze")
            .takes_value(true))
        .arg(Arg::with_name("time_filter_minutes")
            .value_name("MINUTES")
            .short("t")
            .help("Limit to the last n minutes")
            .takes_value(true))
        .arg(Arg::with_name("include_term")
            .value_name("TERM")
            .long("include")
            .help("Only includes lines that contain this term")
            .takes_value(true))
        .arg(Arg::with_name("exclude_term")
            .value_name("TERM")
            .long("exclude")
            .help("Excludes lines that contain this term")
            .takes_value(true))
        .arg(Arg::with_name("graphite-server")
            .value_name("GRAPHITE_SERVER")
            .long("graphite-server")
            .help("Send values to this Graphite server instead of stdout")
            .takes_value(true))
        .arg(Arg::with_name("graphite-port")
            .value_name("GRAPHITE_PORT")
            .long("graphite-port")
            .takes_value(true)
            .default_value("2003"))
        .arg(Arg::with_name("graphite-prefix")
            .value_name("GRAPHITE_PREFIX")
            .long("graphite-prefix")
            .help("Prefix for Graphite key, e.g. 'servers.prod.publisher1'")
            .takes_value(true))
        .get_matches()
}

fn main() {
    let args = parse_args();

    let filename = args.value_of("filename").unwrap();

    let time_filter = match args.value_of("time_filter_minutes") {
        Some(minutes) => Some(Duration::minutes(minutes.parse().unwrap())),
        None => None
    };

    let lines = open_logfile(filename, time_filter);
    let (requests, responses) = lines.unwrap();

    let time_zone = &requests[0].time.timezone();

    let pairs: Vec<RequestResponsePair> = pair_requests_responses(requests, responses)
        .into_iter()
        .filter(|rr| rr.matches_include_exclude_filter(
            args.value_of("include_term"),
            args.value_of("exclude_term")
        ))
        .collect();

    let stream = TcpStream::connect("127.0.0.1:2003").unwrap();

    match analyze(&pairs) {
        // Some(result) => render_terminal(result),
        Some(result) => render_graphite(result, UTC::now().with_timezone(time_zone), stream),
        None => println!("No matching log lines in file.")
    }
}

#[cfg(test)]
mod tests {
	use super::*;
    use request_response::*;
    extern crate chrono;
    use chrono::*;

    #[test]
    fn test_open_logfile() {
        let lines = open_logfile("src/test/simple-1.log", None);
        let (requests, responses) = lines.unwrap();

        assert_eq!(requests.len(), 2);
        assert_eq!(responses.len(), 2);
    }

    #[test]
    fn test_open_logfile_time_filter() {
        let time_filter: Duration = Duration::minutes(1);
        let lines = open_logfile("src/test/simple-1.log", Some(time_filter));
        let (requests, responses) = lines.unwrap();

        assert_eq!(requests.len(), 0);

        let time_filter: Duration = Duration::minutes(52560000); // 100 years
        let lines = open_logfile("src/test/simple-1.log", Some(time_filter));
        let (requests, responses) = lines.unwrap();

        assert_eq!(requests.len(), 2);
    }

    #[test]
    fn test_pair_requests_resonses() {
        let lines = open_logfile("src/test/simple-1.log", None);
        let (requests, responses) = lines.unwrap();

        let result = pair_requests_responses(requests, responses);

        assert_eq!(result.len(), 2);

        assert_eq!(result[0].request.id, result[0].response.id);
        assert_eq!(result[1].request.id, result[1].response.id);
    }

    #[test]
    fn test_request_log_analyzer_result() {
        let lines = open_logfile("src/test/response-time-calculations.log", None);
        let (requests, responses) = lines.unwrap();

        let request_response_pairs = pair_requests_responses(requests, responses);

        let result = analyze(&request_response_pairs);

        let expected = Some(RequestLogAnalyzerResult {
            count: 3,
            max: 100,
            min: 1,
            avg: 37,
            median: 10,
            percentile90: 100,
        });

        assert_eq!(result, expected);
    }

    #[test]
    fn test_request_log_analyze_none_matching() {
        let lines = open_logfile("src/test/simple-1.log", Some(Duration::minutes(0)));
        let (requests, responses) = lines.unwrap();

        let request_response_pairs = pair_requests_responses(requests, responses);

        let result = analyze(&request_response_pairs);

        let expected = None;

        assert_eq!(result, expected);
    }

    #[test]
    fn test_90_percentile_calculation() {
        let lines = open_logfile("src/test/percentile.log", None);
        let (requests, responses) = lines.unwrap();

        let request_response_pairs = pair_requests_responses(requests, responses);

        let result: RequestLogAnalyzerResult = analyze(&request_response_pairs).unwrap();

        assert_eq!(result.percentile90, 9);
    }

    #[test]
    fn test_render_graphite() {
        use std::io::{self, BufReader};
        use std::io::prelude::Write;
        use std::str;

        struct MockTcpStream {
            write_calls: Vec<String>,
        };

        impl Write for MockTcpStream {
            fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
                self.write_calls.push(str::from_utf8(buf).unwrap().to_string());
                Ok(1)
            }

            fn flush(&mut self) -> io::Result<()> { Ok(()) }
        }

        let mut mock_tcp_stream = MockTcpStream {
            write_calls: vec![]
        };

        render_graphite(RequestLogAnalyzerResult {
                count: 3,
                max: 100,
                min: 1,
                avg: 37,
                median: 10,
                percentile90: 100,
            },
            DateTime::parse_from_str("22/Sep/2016:22:41:59 +0200", "%d/%b/%Y:%H:%M:%S %z").unwrap(),
            &mut mock_tcp_stream
        );

        assert_eq!(&mock_tcp_stream.write_calls[0], "requests.count 3 1474576919\n");
        assert_eq!(&mock_tcp_stream.write_calls[1], "requests.time.max 100 1474576919\n");
        assert_eq!(&mock_tcp_stream.write_calls[2], "requests.time.min 1 1474576919\n");
        assert_eq!(&mock_tcp_stream.write_calls[3], "requests.time.avg 37 1474576919\n");
        assert_eq!(&mock_tcp_stream.write_calls[4], "requests.time.median 10 1474576919\n");
        assert_eq!(&mock_tcp_stream.write_calls[5], "requests.time.90percent 100 1474576919\n");
    }
}
<commit_msg>Enable optional Graphite usage from CLI<commit_after>use std::io::{self, BufReader, Write};
use std::io::BufRead;
use std::net::TcpStream;
use std::fs::File;

extern crate chrono;
use chrono::*;

extern crate stats;
use stats::median;

extern crate clap;
use clap::{Arg, App, ArgMatches};

mod percentile;
use percentile::percentile;

mod http_status;

mod request_response;
use request_response::*;

pub fn open_logfile(path: &str, time_filter: Option<Duration>) -> Result<(Vec<Request>,Vec<Response>), io::Error> {
    let f = try!(File::open(path));

    let f = BufReader::new(f);

    let mut requests: Vec<Request> = Vec::new();
    let mut responses: Vec<Response> = Vec::new();

    for line in f.lines() {
        let line_value = &line.unwrap();

        if line_value.contains("->") {
            let r = try!(Request::new_from_log_line(&line_value));

            if time_filter.is_none() ||
              (time_filter.is_some() && r.is_between_times(UTC::now().with_timezone(&r.time.timezone()) - time_filter.unwrap(), UTC::now().with_timezone(&r.time.timezone()))) {
                requests.push(r);
            }
        }

        if line_value.contains("<-") {
            let r = try!(Response::new_from_log_line(&line_value));
            responses.push(r);
        }

    }

    responses.sort_by_key(|r| r.id);

    Ok((requests, responses))
}

#[derive(Eq, PartialEq)]
#[derive(Debug)]
pub struct RequestLogAnalyzerResult {
    count: usize,
    max: usize,
    min: usize,
    avg: usize,
    median: usize,
    percentile90: usize,
}

pub fn analyze(request_response_pairs: &Vec<RequestResponsePair>) -> Option<RequestLogAnalyzerResult> {
    if request_response_pairs.len() == 0 {
        return None;
    }

    let times: Vec<i64> = request_response_pairs.iter()
        .map(|rr: &RequestResponsePair| -> i64 {rr.response.response_time.num_milliseconds() })
        .collect();

    let sum: usize = times.iter().sum::<i64>() as usize;
    let avg: usize = sum / times.len();

    let max: usize = *times.iter().max().unwrap() as usize;
    let min: usize = *times.iter().min().unwrap() as usize;

    let percentile90: usize = percentile(&times, 0.9) as usize;

    let median = median(times.into_iter()).unwrap() as usize;

    Some(RequestLogAnalyzerResult {
        count: request_response_pairs.len().into(),
        max: max,
        min: min,
        avg: avg,
        median: median,
        percentile90: percentile90,
    })
}

fn render_terminal(result: RequestLogAnalyzerResult) {
    println!("count:\t{}", result.count);
    println!("time.avg:\t{}", result.avg);
    println!("time.min:\t{}", result.min);
    println!("time.median:\t{}", result.median);
    println!("time.90percent:\t{}", result.percentile90);
    println!("time.max:\t{}", result.max);
}

pub fn render_graphite<T: Write>(result: RequestLogAnalyzerResult, time: DateTime<FixedOffset>, mut stream: T) {
    let mut write = |text: String| {
        stream.write(
            format!("{} {}\n", text, time.timestamp() )
            .as_bytes()
        );
    };

    write(format!("requests.count {}", result.count));
    write(format!("requests.time.max {}", result.max));
    write(format!("requests.time.min {}", result.min));
    write(format!("requests.time.avg {}", result.avg));
    write(format!("requests.time.median {}", result.median));
    write(format!("requests.time.90percent {}", result.percentile90));
}

fn parse_args<'a>() -> ArgMatches<'a> {
    App::new("Request.log Analyzer")
        .arg(Arg::with_name("filename")
            .index(1)
            .value_name("FILE")
            .required(true)
            .help("Log file to analyze")
            .takes_value(true))
        .arg(Arg::with_name("time_filter_minutes")
            .value_name("MINUTES")
            .short("t")
            .help("Limit to the last n minutes")
            .takes_value(true))
        .arg(Arg::with_name("include_term")
            .value_name("TERM")
            .long("include")
            .help("Only includes lines that contain this term")
            .takes_value(true))
        .arg(Arg::with_name("exclude_term")
            .value_name("TERM")
            .long("exclude")
            .help("Excludes lines that contain this term")
            .takes_value(true))
        .arg(Arg::with_name("graphite-server")
            .value_name("GRAPHITE_SERVER")
            .long("graphite-server")
            .help("Send values to this Graphite server instead of stdout")
            .takes_value(true))
        .arg(Arg::with_name("graphite-port")
            .value_name("GRAPHITE_PORT")
            .long("graphite-port")
            .takes_value(true)
            .default_value("2003"))
        .arg(Arg::with_name("graphite-prefix")
            .value_name("GRAPHITE_PREFIX")
            .long("graphite-prefix")
            .help("Prefix for Graphite key, e.g. 'servers.prod.publisher1'")
            .takes_value(true))
        .get_matches()
}

fn main() {
    let args = parse_args();

    let filename = args.value_of("filename").unwrap();

    let time_filter = match args.value_of("time_filter_minutes") {
        Some(minutes) => Some(Duration::minutes(minutes.parse().unwrap())),
        None => None
    };

    let lines = open_logfile(filename, time_filter);
    let (requests, responses) = lines.unwrap();

    let time_zone = &requests[0].time.timezone();

    let pairs: Vec<RequestResponsePair> = pair_requests_responses(requests, responses)
        .into_iter()
        .filter(|rr| rr.matches_include_exclude_filter(
            args.value_of("include_term"),
            args.value_of("exclude_term")
        ))
        .collect();

    if args.is_present("graphite-server") {
        let stream = TcpStream::connect(
            (
                args.value_of("graphite-server").unwrap(),
                args.value_of("graphite-port").unwrap().parse().unwrap()
            )
        ).unwrap();

        match analyze(&pairs) {
            Some(result) => render_graphite(result, UTC::now().with_timezone(time_zone), stream),
            None => println!("No matching log lines in file.")
        }
    } else {
        match analyze(&pairs) {
            Some(result) => render_terminal(result),
            None => println!("No matching log lines in file.")
        }
    }
}

#[cfg(test)]
mod tests {
	use super::*;
    use request_response::*;
    extern crate chrono;
    use chrono::*;

    #[test]
    fn test_open_logfile() {
        let lines = open_logfile("src/test/simple-1.log", None);
        let (requests, responses) = lines.unwrap();

        assert_eq!(requests.len(), 2);
        assert_eq!(responses.len(), 2);
    }

    #[test]
    fn test_open_logfile_time_filter() {
        let time_filter: Duration = Duration::minutes(1);
        let lines = open_logfile("src/test/simple-1.log", Some(time_filter));
        let (requests, responses) = lines.unwrap();

        assert_eq!(requests.len(), 0);

        let time_filter: Duration = Duration::minutes(52560000); // 100 years
        let lines = open_logfile("src/test/simple-1.log", Some(time_filter));
        let (requests, responses) = lines.unwrap();

        assert_eq!(requests.len(), 2);
    }

    #[test]
    fn test_pair_requests_resonses() {
        let lines = open_logfile("src/test/simple-1.log", None);
        let (requests, responses) = lines.unwrap();

        let result = pair_requests_responses(requests, responses);

        assert_eq!(result.len(), 2);

        assert_eq!(result[0].request.id, result[0].response.id);
        assert_eq!(result[1].request.id, result[1].response.id);
    }

    #[test]
    fn test_request_log_analyzer_result() {
        let lines = open_logfile("src/test/response-time-calculations.log", None);
        let (requests, responses) = lines.unwrap();

        let request_response_pairs = pair_requests_responses(requests, responses);

        let result = analyze(&request_response_pairs);

        let expected = Some(RequestLogAnalyzerResult {
            count: 3,
            max: 100,
            min: 1,
            avg: 37,
            median: 10,
            percentile90: 100,
        });

        assert_eq!(result, expected);
    }

    #[test]
    fn test_request_log_analyze_none_matching() {
        let lines = open_logfile("src/test/simple-1.log", Some(Duration::minutes(0)));
        let (requests, responses) = lines.unwrap();

        let request_response_pairs = pair_requests_responses(requests, responses);

        let result = analyze(&request_response_pairs);

        let expected = None;

        assert_eq!(result, expected);
    }

    #[test]
    fn test_90_percentile_calculation() {
        let lines = open_logfile("src/test/percentile.log", None);
        let (requests, responses) = lines.unwrap();

        let request_response_pairs = pair_requests_responses(requests, responses);

        let result: RequestLogAnalyzerResult = analyze(&request_response_pairs).unwrap();

        assert_eq!(result.percentile90, 9);
    }

    #[test]
    fn test_render_graphite() {
        use std::io::{self, BufReader};
        use std::io::prelude::Write;
        use std::str;

        struct MockTcpStream {
            write_calls: Vec<String>,
        };

        impl Write for MockTcpStream {
            fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
                self.write_calls.push(str::from_utf8(buf).unwrap().to_string());
                Ok(1)
            }

            fn flush(&mut self) -> io::Result<()> { Ok(()) }
        }

        let mut mock_tcp_stream = MockTcpStream {
            write_calls: vec![]
        };

        render_graphite(RequestLogAnalyzerResult {
                count: 3,
                max: 100,
                min: 1,
                avg: 37,
                median: 10,
                percentile90: 100,
            },
            DateTime::parse_from_str("22/Sep/2016:22:41:59 +0200", "%d/%b/%Y:%H:%M:%S %z").unwrap(),
            &mut mock_tcp_stream
        );

        assert_eq!(&mock_tcp_stream.write_calls[0], "requests.count 3 1474576919\n");
        assert_eq!(&mock_tcp_stream.write_calls[1], "requests.time.max 100 1474576919\n");
        assert_eq!(&mock_tcp_stream.write_calls[2], "requests.time.min 1 1474576919\n");
        assert_eq!(&mock_tcp_stream.write_calls[3], "requests.time.avg 37 1474576919\n");
        assert_eq!(&mock_tcp_stream.write_calls[4], "requests.time.median 10 1474576919\n");
        assert_eq!(&mock_tcp_stream.write_calls[5], "requests.time.90percent 100 1474576919\n");
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 The Noise-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use num::Float;

use {math, Seed};
use {GenFn2, GenFn3, GenFn4};
use {Point2, Point3, Point4};

/// A callable struct for applying 2-dimensional [fractional Brownian motion]
/// (http://en.wikipedia.org/wiki/Fractional_Brownian_motion).
///
/// Fractional Brownian motion is a way of combining multiple octaves of a noise
/// function to create a richer and more varied output. It can theoretically be
/// used with any noise function, but it tends to only produce good results with
/// gradient noise functions.
///
/// The struct contains many parameters, which can either be set using the
/// builder methods provided, or by constructing the type manually.
///
/// # Example
///
/// ```rust
/// extern crate noise;
/// extern crate rand;
///
/// use noise::{Brownian2, perlin2};
///
/// # fn main() {
/// let seed = rand::random();
/// let noise = Brownian2::new(perlin2, 4).wavelength(32.0);
/// let val = noise.apply(&seed, &[42.0, 37.0]);
/// # }
/// ```
#[derive(Copy, Clone)]
pub struct Brownian2<T, F: GenFn2<T>> {
    /// The underlying noise function to call.
    pub function: F,
    /// The number of times to call the noise function.
    pub octaves: usize,
    /// The base frequency of the noise
    pub frequency: T,
    /// The rate at which the amplitude of the noise is reduced for each octave.
    pub persistence: T,
    /// The rate at which the frequency of the noise increases for each octave.
    pub lacunarity: T,
}

/// A callable struct for applying 3-dimensional [fractional Brownian motion]
/// (http://en.wikipedia.org/wiki/Fractional_Brownian_motion).
///
/// Fractional Brownian motion is a way of combining multiple octaves of a noise
/// function to create a richer and more varied output. It can theoretically be
/// used with any noise function, but it tends to only produce good results with
/// gradient noise functions.
///
/// The struct contains many parameters, which can either be set using the
/// builder methods provided, or by constructing the type manually.
///
/// # Example
///
/// ```rust
/// extern crate noise;
/// extern crate rand;
///
/// use noise::{Brownian3, perlin3};
///
/// # fn main() {
/// let seed = rand::random();
/// let noise = Brownian3::new(perlin3, 4).wavelength(32.0);
/// let val = noise.apply(&seed, &[42.0, 37.0, 2.0]);
/// # }
/// ```
#[derive(Copy, Clone)]
pub struct Brownian3<T, F: GenFn3<T>> {
    /// The underlying noise function to call.
    pub function: F,
    /// The number of times to call the noise function.
    pub octaves: usize,
    /// The base frequency of the noise
    pub frequency: T,
    /// The rate at which the amplitude of the noise is reduced for each octave.
    pub persistence: T,
    /// The rate at which the frequency of the noise increases for each octave.
    pub lacunarity: T,
}

/// A callable struct for applying 4-dimensional [fractional Brownian motion]
/// (http://en.wikipedia.org/wiki/Fractional_Brownian_motion).
///
/// Fractional Brownian motion is a way of combining multiple octaves of a noise
/// function to create a richer and more varied output. It can theoretically be
/// used with any noise function, but it tends to only produce good results with
/// gradient noise functions.
///
/// The struct contains many parameters, which can either be set using the
/// builder methods provided, or by constructing the type manually.
///
/// # Example
///
/// ```rust
/// extern crate noise;
/// extern crate rand;
///
/// use noise::{Brownian4, perlin4};
///
/// # fn main() {
/// let seed = rand::random();
/// let noise = Brownian4::new(perlin4, 4).wavelength(32.0);
/// let val = noise.apply(&seed, &[42.0, 37.0, 2.0, 3.0]);
/// # }
/// ```
#[derive(Copy, Clone)]
pub struct Brownian4<T, F: GenFn4<T>> {
    /// The underlying noise function to call on each octave.
    pub function: F,
    /// The number of times to call the noise function.
    pub octaves: usize,
    /// The base frequency of the noise
    pub frequency: T,
    /// The rate at which the amplitude of the noise is reduced on each octave.
    pub persistence: T,
    /// The rate at which the frequency of the noise increases on each octave.
    pub lacunarity: T,
}

macro_rules! impl_brownian {
    { $Brownian:ident, $GenFn:ident, $Point:ident, $mapn:path } => {
        impl<T: Float, F: $GenFn<T>> $Brownian<T, F> {
            /// Constructs a new brownian noise function, defaulting to:
            ///
            /// - frequency: `1.0`
            /// - lacunarity: `2.0`
            /// - persistence: `0.5`
            #[inline]
            pub fn new(function: F, octaves: usize) -> $Brownian<T, F> {
                $Brownian {
                    function: function,
                    octaves: octaves,
                    frequency: math::cast(1.0f32),
                    lacunarity: math::cast(2.0f32),
                    persistence: math::cast(0.5f32),
                }
            }

            /// A builder method that sets underlying noise function to call on
            /// each octave.
            #[inline]
            pub fn function<Q: $GenFn<T>>(self, function: Q) -> $Brownian<T, Q> {
                let $Brownian { octaves, frequency, lacunarity, persistence, .. } = self;
                $Brownian {
                    function: function,
                    octaves: octaves,
                    frequency: frequency,
                    persistence: persistence,
                    lacunarity: lacunarity,
                }
            }

            /// A builder method that sets the number of times to call the noise
            /// function.
            #[inline]
            pub fn octaves(self, octaves: usize) -> $Brownian<T, F> {
                $Brownian { octaves: octaves, ..self }
            }

            /// A builder method that sets the wavelength of the brownian noise.
            /// This is equivalent to `self.frequency(wavelength.recip())`.
            #[inline]
            pub fn wavelength(self, wavelength: T) -> $Brownian<T, F> {
                self.frequency(wavelength.recip())
            }

            /// A builder method that sets the base frequency of the noise.
            #[inline]
            pub fn frequency(self, frequency: T) -> $Brownian<T, F> {
                $Brownian { frequency: frequency, ..self }
            }

            /// A builder method that sets the rate at which the amplitude of
            /// the noise is reduced on each octave.
            #[inline]
            pub fn persistence(self, persistence: T) -> $Brownian<T, F> {
                $Brownian { persistence: persistence, ..self }
            }

            /// A builder method that sets the rate at which the frequency of
            /// the noise increases on each octave.
            #[inline]
            pub fn lacunarity(self, lacunarity: T) -> $Brownian<T, F> {
                $Brownian { lacunarity: lacunarity, ..self }
            }

            /// Apply the Brownian noise function for the supplied seed and point.
            #[inline]
            pub fn apply(&self, seed: &Seed, point: &$Point<T>) -> T {
                let mut frequency: T = self.frequency;
                let mut amplitude: T = math::cast(1);
                let mut total_amplitude = T::zero();
                let mut result: T = math::cast(0);
                let point = *point;
                for _ in 0..self.octaves {
                    let scaled_point = $mapn(point, |v| v * frequency);
                    result = result + ((self.function)(seed, &scaled_point) * amplitude);
                    total_amplitude = total_amplitude + amplitude;
                    amplitude = amplitude * self.persistence;
                    frequency = frequency * self.lacunarity;
                }
                result / total_amplitude
            }
        }
    }
}

impl_brownian! { Brownian2, GenFn2, Point2, math::map2 }
impl_brownian! { Brownian3, GenFn3, Point3, math::map3 }
impl_brownian! { Brownian4, GenFn4, Point4, math::map4 }

#[cfg(rust_unstable)]
impl<'a, 'b, T, F> Fn(&'a Seed, &'b Point2<T>) for Brownian2<T, F> where
    T: Float,
    F: GenFn2<T>,
{
    /// Applies the brownian noise function for the supplied seed and point.
    extern "rust-call" fn call(&self, (seed, point): (&'a Seed, &'b Point2<T>)) -> T {
        self.apply(seed, point)
    }
}

#[cfg(rust_unstable)]
impl<'a, 'b, T, F> FnMut(&'a Seed, &'b Point2<T>) for Brownian2<T, F> where
    T: Float,
    F: GenFn2<T>,
{
    extern "rust-call" fn call_mut(&mut self, (seed, point): (&'a Seed, &'b Point2<T>)) -> T {
        self.call((seed, point))
    }
}

#[cfg(rust_unstable)]
impl<'a, 'b, T, F> FnOnce(&'a Seed, &'b Point2<T>) for Brownian2<T, F> where
    T: Float,
    F: GenFn2<T>,
{
    type Output = T;
    extern "rust-call" fn call_once(self, (seed, point): (&'a Seed, &'b Point2<T>)) -> T {
        self.call((seed, point))
    }
}

#[cfg(rust_unstable)]
impl<'a, 'b, T, F> Fn(&'a Seed, &'b Point3<T>) for Brownian3<T, F> where
    T: Float,
    F: GenFn3<T>,
{
    /// Applies the brownian noise function for the supplied seed and point.
    extern "rust-call" fn call(&self, (seed, point): (&'a Seed, &'b Point3<T>)) -> T {
        self.apply(seed, point)
    }
}

#[cfg(rust_unstable)]
impl<'a, 'b, T, F> FnMut(&'a Seed, &'b Point3<T>) for Brownian3<T, F> where
    T: Float,
    F: GenFn3<T>,
{
    extern "rust-call" fn call_mut(&mut self, (seed, point): (&'a Seed, &'b Point3<T>)) -> T {
        self.call((seed, point))
    }
}

#[cfg(rust_unstable)]
impl<'a, 'b, T, F> FnOnce(&'a Seed, &'b Point3<T>) for Brownian3<T, F> where
    T: Float,
    F: GenFn3<T>,
{
    type Output = T;
    extern "rust-call" fn call_once(self, (seed, point): (&'a Seed, &'b Point3<T>)) -> T {
        self.call((seed, point))
    }
}

#[cfg(rust_unstable)]
impl<'a, 'b, T, F> Fn(&'a Seed, &'b ::Point4<T>) for Brownian4<T, F> where
    T: Float,
    F: GenFn4<T>,
{
    /// Applies the brownian noise function for the supplied seed and point.
    extern "rust-call" fn call(&self, (seed, point): (&'a Seed, &'b Point4<T>)) -> T {
        self.apply(seed, point)
    }
}

#[cfg(rust_unstable)]
impl<'a, 'b, T, F> FnMut(&'a Seed, &'b Point4<T>) for Brownian4<T, F> where
    T: Float,
    F: GenFn4<T>,
{
    extern "rust-call" fn call_mut(&mut self, (seed, point): (&'a Seed, &'b Point4<T>)) -> T {
        self.call((seed, point))
    }
}

#[cfg(rust_unstable)]
impl<'a, 'b, T, F> FnOnce(&'a Seed, &'b Point4<T>) for Brownian4<T, F> where
    T: Float,
    F: GenFn4<T>,
{
    type Output = T;
    extern "rust-call" fn call_once(self, (seed, point): (&'a Seed, &'b Point4<T>)) -> T {
        self.call((seed, point))
    }
}
<commit_msg>Fix brownian noise values accumulating at origin.<commit_after>// Copyright 2015 The Noise-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use num::Float;

use {math, Seed};
use {GenFn2, GenFn3, GenFn4};
use {Point2, Point3, Point4};

/// A callable struct for applying 2-dimensional [fractional Brownian motion]
/// (http://en.wikipedia.org/wiki/Fractional_Brownian_motion).
///
/// Fractional Brownian motion is a way of combining multiple octaves of a noise
/// function to create a richer and more varied output. It can theoretically be
/// used with any noise function, but it tends to only produce good results with
/// gradient noise functions.
///
/// The struct contains many parameters, which can either be set using the
/// builder methods provided, or by constructing the type manually.
///
/// # Example
///
/// ```rust
/// extern crate noise;
/// extern crate rand;
///
/// use noise::{Brownian2, perlin2};
///
/// # fn main() {
/// let seed = rand::random();
/// let noise = Brownian2::new(perlin2, 4).wavelength(32.0);
/// let val = noise.apply(&seed, &[42.0, 37.0]);
/// # }
/// ```
#[derive(Copy, Clone)]
pub struct Brownian2<T, F: GenFn2<T>> {
    /// The underlying noise function to call.
    pub function: F,
    /// The number of times to call the noise function.
    pub octaves: usize,
    /// The base frequency of the noise
    pub frequency: T,
    /// The rate at which the amplitude of the noise is reduced for each octave.
    pub persistence: T,
    /// The rate at which the frequency of the noise increases for each octave.
    pub lacunarity: T,
}

/// A callable struct for applying 3-dimensional [fractional Brownian motion]
/// (http://en.wikipedia.org/wiki/Fractional_Brownian_motion).
///
/// Fractional Brownian motion is a way of combining multiple octaves of a noise
/// function to create a richer and more varied output. It can theoretically be
/// used with any noise function, but it tends to only produce good results with
/// gradient noise functions.
///
/// The struct contains many parameters, which can either be set using the
/// builder methods provided, or by constructing the type manually.
///
/// # Example
///
/// ```rust
/// extern crate noise;
/// extern crate rand;
///
/// use noise::{Brownian3, perlin3};
///
/// # fn main() {
/// let seed = rand::random();
/// let noise = Brownian3::new(perlin3, 4).wavelength(32.0);
/// let val = noise.apply(&seed, &[42.0, 37.0, 2.0]);
/// # }
/// ```
#[derive(Copy, Clone)]
pub struct Brownian3<T, F: GenFn3<T>> {
    /// The underlying noise function to call.
    pub function: F,
    /// The number of times to call the noise function.
    pub octaves: usize,
    /// The base frequency of the noise
    pub frequency: T,
    /// The rate at which the amplitude of the noise is reduced for each octave.
    pub persistence: T,
    /// The rate at which the frequency of the noise increases for each octave.
    pub lacunarity: T,
}

/// A callable struct for applying 4-dimensional [fractional Brownian motion]
/// (http://en.wikipedia.org/wiki/Fractional_Brownian_motion).
///
/// Fractional Brownian motion is a way of combining multiple octaves of a noise
/// function to create a richer and more varied output. It can theoretically be
/// used with any noise function, but it tends to only produce good results with
/// gradient noise functions.
///
/// The struct contains many parameters, which can either be set using the
/// builder methods provided, or by constructing the type manually.
///
/// # Example
///
/// ```rust
/// extern crate noise;
/// extern crate rand;
///
/// use noise::{Brownian4, perlin4};
///
/// # fn main() {
/// let seed = rand::random();
/// let noise = Brownian4::new(perlin4, 4).wavelength(32.0);
/// let val = noise.apply(&seed, &[42.0, 37.0, 2.0, 3.0]);
/// # }
/// ```
#[derive(Copy, Clone)]
pub struct Brownian4<T, F: GenFn4<T>> {
    /// The underlying noise function to call on each octave.
    pub function: F,
    /// The number of times to call the noise function.
    pub octaves: usize,
    /// The base frequency of the noise
    pub frequency: T,
    /// The rate at which the amplitude of the noise is reduced on each octave.
    pub persistence: T,
    /// The rate at which the frequency of the noise increases on each octave.
    pub lacunarity: T,
}

macro_rules! impl_brownian {
    { $Brownian:ident, $GenFn:ident, $Point:ident, $mapn:path } => {
        impl<T: Float, F: $GenFn<T>> $Brownian<T, F> {
            /// Constructs a new brownian noise function, defaulting to:
            ///
            /// - frequency: `1.0`
            /// - lacunarity: `2.0`
            /// - persistence: `0.5`
            #[inline]
            pub fn new(function: F, octaves: usize) -> $Brownian<T, F> {
                $Brownian {
                    function: function,
                    octaves: octaves,
                    frequency: math::cast(1.0f32),
                    lacunarity: math::cast(2.0f32),
                    persistence: math::cast(0.5f32),
                }
            }

            /// A builder method that sets underlying noise function to call on
            /// each octave.
            #[inline]
            pub fn function<Q: $GenFn<T>>(self, function: Q) -> $Brownian<T, Q> {
                let $Brownian { octaves, frequency, lacunarity, persistence, .. } = self;
                $Brownian {
                    function: function,
                    octaves: octaves,
                    frequency: frequency,
                    persistence: persistence,
                    lacunarity: lacunarity,
                }
            }

            /// A builder method that sets the number of times to call the noise
            /// function.
            #[inline]
            pub fn octaves(self, octaves: usize) -> $Brownian<T, F> {
                $Brownian { octaves: octaves, ..self }
            }

            /// A builder method that sets the wavelength of the brownian noise.
            /// This is equivalent to `self.frequency(wavelength.recip())`.
            #[inline]
            pub fn wavelength(self, wavelength: T) -> $Brownian<T, F> {
                self.frequency(wavelength.recip())
            }

            /// A builder method that sets the base frequency of the noise.
            #[inline]
            pub fn frequency(self, frequency: T) -> $Brownian<T, F> {
                $Brownian { frequency: frequency, ..self }
            }

            /// A builder method that sets the rate at which the amplitude of
            /// the noise is reduced on each octave.
            #[inline]
            pub fn persistence(self, persistence: T) -> $Brownian<T, F> {
                $Brownian { persistence: persistence, ..self }
            }

            /// A builder method that sets the rate at which the frequency of
            /// the noise increases on each octave.
            #[inline]
            pub fn lacunarity(self, lacunarity: T) -> $Brownian<T, F> {
                $Brownian { lacunarity: lacunarity, ..self }
            }

            /// Apply the Brownian noise function for the supplied seed and point.
            #[inline]
            pub fn apply(&self, seed: &Seed, point: &$Point<T>) -> T {
                let mut frequency: T = self.frequency;
                let mut amplitude: T = math::cast(1);
                let mut total_amplitude = T::zero();
                let mut result: T = math::cast(0);
                let mut offset: T = math::cast(1.73205080756887);
                let point = *point;
                for _ in 0..self.octaves {
                    let scaled_point = $mapn(point, |v| v * frequency + offset);
                    result = result + ((self.function)(seed, &scaled_point) * amplitude);
                    total_amplitude = total_amplitude + amplitude;
                    amplitude = amplitude * self.persistence;
                    frequency = frequency * self.lacunarity;
                    offset = offset + math::cast(1.73205080756887);
                }
                result / total_amplitude
            }
        }
    }
}

impl_brownian! { Brownian2, GenFn2, Point2, math::map2 }
impl_brownian! { Brownian3, GenFn3, Point3, math::map3 }
impl_brownian! { Brownian4, GenFn4, Point4, math::map4 }

#[cfg(rust_unstable)]
impl<'a, 'b, T, F> Fn(&'a Seed, &'b Point2<T>) for Brownian2<T, F> where
    T: Float,
    F: GenFn2<T>,
{
    /// Applies the brownian noise function for the supplied seed and point.
    extern "rust-call" fn call(&self, (seed, point): (&'a Seed, &'b Point2<T>)) -> T {
        self.apply(seed, point)
    }
}

#[cfg(rust_unstable)]
impl<'a, 'b, T, F> FnMut(&'a Seed, &'b Point2<T>) for Brownian2<T, F> where
    T: Float,
    F: GenFn2<T>,
{
    extern "rust-call" fn call_mut(&mut self, (seed, point): (&'a Seed, &'b Point2<T>)) -> T {
        self.call((seed, point))
    }
}

#[cfg(rust_unstable)]
impl<'a, 'b, T, F> FnOnce(&'a Seed, &'b Point2<T>) for Brownian2<T, F> where
    T: Float,
    F: GenFn2<T>,
{
    type Output = T;
    extern "rust-call" fn call_once(self, (seed, point): (&'a Seed, &'b Point2<T>)) -> T {
        self.call((seed, point))
    }
}

#[cfg(rust_unstable)]
impl<'a, 'b, T, F> Fn(&'a Seed, &'b Point3<T>) for Brownian3<T, F> where
    T: Float,
    F: GenFn3<T>,
{
    /// Applies the brownian noise function for the supplied seed and point.
    extern "rust-call" fn call(&self, (seed, point): (&'a Seed, &'b Point3<T>)) -> T {
        self.apply(seed, point)
    }
}

#[cfg(rust_unstable)]
impl<'a, 'b, T, F> FnMut(&'a Seed, &'b Point3<T>) for Brownian3<T, F> where
    T: Float,
    F: GenFn3<T>,
{
    extern "rust-call" fn call_mut(&mut self, (seed, point): (&'a Seed, &'b Point3<T>)) -> T {
        self.call((seed, point))
    }
}

#[cfg(rust_unstable)]
impl<'a, 'b, T, F> FnOnce(&'a Seed, &'b Point3<T>) for Brownian3<T, F> where
    T: Float,
    F: GenFn3<T>,
{
    type Output = T;
    extern "rust-call" fn call_once(self, (seed, point): (&'a Seed, &'b Point3<T>)) -> T {
        self.call((seed, point))
    }
}

#[cfg(rust_unstable)]
impl<'a, 'b, T, F> Fn(&'a Seed, &'b ::Point4<T>) for Brownian4<T, F> where
    T: Float,
    F: GenFn4<T>,
{
    /// Applies the brownian noise function for the supplied seed and point.
    extern "rust-call" fn call(&self, (seed, point): (&'a Seed, &'b Point4<T>)) -> T {
        self.apply(seed, point)
    }
}

#[cfg(rust_unstable)]
impl<'a, 'b, T, F> FnMut(&'a Seed, &'b Point4<T>) for Brownian4<T, F> where
    T: Float,
    F: GenFn4<T>,
{
    extern "rust-call" fn call_mut(&mut self, (seed, point): (&'a Seed, &'b Point4<T>)) -> T {
        self.call((seed, point))
    }
}

#[cfg(rust_unstable)]
impl<'a, 'b, T, F> FnOnce(&'a Seed, &'b Point4<T>) for Brownian4<T, F> where
    T: Float,
    F: GenFn4<T>,
{
    type Output = T;
    extern "rust-call" fn call_once(self, (seed, point): (&'a Seed, &'b Point4<T>)) -> T {
        self.call((seed, point))
    }
}
<|endoftext|>


<commit_before>extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate exonum;
extern crate router;
extern crate bodyparser;
extern crate iron;

use exonum::blockchain::{Blockchain, Service, ServiceContext, Schema, GenesisConfig,
                         ValidatorKeys, Transaction, ApiContext};
use exonum::node::{Node, NodeConfig, NodeApiConfig, ApiSender};
use exonum::messages::{RawTransaction, FromRaw, Message};
use exonum::encoding::serialize::json::reexport::Value;
use exonum::storage::{Fork, Snapshot, MemoryDB, MapIndex, Entry};
use exonum::crypto::{PublicKey, Hash};
use exonum::encoding;
use exonum::api::Api;
use iron::prelude::*;
use iron::Handler;
use router::Router;
use std::time::SystemTime;

const SERVICE_ID: u16 = 1;
const TX_TIME_ID: u16 = 1;

// SCHEMA

encoding_struct! {
    struct Time {
        const SIZE = 12;

        field time:     SystemTime  [00 => 12]
    }
}

pub struct TimeSchema<T> {
    view: T,
}

impl<T: AsRef<Snapshot>> TimeSchema<T> {
    pub fn new(view: T) -> Self {
        TimeSchema { view }
    }

    pub fn validators_time(&self) -> MapIndex<&Snapshot, PublicKey, Time> {
        MapIndex::new("time.validators_time", self.view.as_ref())
    }

    pub fn time(&self) -> Entry<&Snapshot, Time> {
        Entry::new("time.time", self.view.as_ref())
    }
}

impl<'a> TimeSchema<&'a mut Fork> {
    pub fn validators_time_mut(&mut self) -> MapIndex<&mut Fork, PublicKey, Time> {
        MapIndex::new("time.validators_time", self.view)
    }

    pub fn time_mut(&mut self) -> Entry<&mut Fork, Time> {
        Entry::new("time.time", self.view)
    }
}

// TRANSACTION

message! {
    struct TxTime {
        const TYPE = SERVICE_ID;
        const ID = TX_TIME_ID;
        const SIZE = 44;

        field time:     SystemTime  [00 => 12]
        field pub_key:  &PublicKey  [12 => 44]
    }
}

impl Transaction for TxTime {
    fn verify(&self) -> bool {
        self.verify_signature(self.pub_key())
    }

    fn execute(&self, view: &mut Fork) {
        let validator_keys = Schema::new(&view).actual_configuration().validator_keys;

        if validator_keys.iter().any(|&validator| {
            validator.service_key == *self.pub_key()
        })
        {
            let mut schema = TimeSchema::new(view);
            if let Some(storage_time) = schema.validators_time().get(self.pub_key()) {
                if storage_time.time() < self.time() {
                    schema.validators_time_mut().put(
                        self.pub_key(),
                        Time::new(self.time()),
                    );

                    let mut validators_time = Vec::new();
                    {
                        let idx = schema.validators_time();

                        for pair in idx.iter() {
                            let (pub_key, time) = (pair.0, pair.1.time());
                            if validator_keys.iter().any(|validator| {
                                validator.service_key == pub_key
                            })
                            {
                                validators_time.push(time);
                            }
                        }
                    }

                    let f = validator_keys.len() / 3;
                    if validators_time.len() > f {
                        validators_time.sort();
                        validators_time.reverse();
                        if let Some(current_time) = schema.time().get() {
                            if current_time.time() < validators_time[f] {
                                schema.time_mut().set(Time::new(validators_time[f]));
                            }
                        }
                    }
                }
            }
        }
    }
}

// API

#[derive(Serialize, Deserialize)]
pub struct TxResponse {
    pub tx_hash: Hash,
}

#[derive(Clone)]
struct TimeApi {
    channel: ApiSender,
    blockchain: Blockchain,
}

impl TimeApi {
    fn get_current_time(&self, _: &mut Request) -> IronResult<Response> {
        let view = self.blockchain.snapshot();
        let schema = TimeSchema::new(&view);
        let current_time = schema.time().get();
        self.ok_response(&serde_json::to_value(current_time).unwrap())
    }

    fn get_validators_time(&self, _: &mut Request) -> IronResult<Response> {
        let view = self.blockchain.snapshot();
        let schema = TimeSchema::new(&view);
        let idx = schema.validators_time();
        let validators_time: Vec<Time> = idx.values().collect();
        if validators_time.is_empty() {
            self.not_found_response(&serde_json::to_value("Validators time database if empty")
                .unwrap())
        } else {
            self.ok_response(&serde_json::to_value(validators_time).unwrap())
        }
    }

    fn wire_private(&self, router: &mut Router) {
        let self_ = self.clone();
        let get_validators_time = move |req: &mut Request| self_.get_validators_time(req);
        router.get(
            "/validators_time",
            get_validators_time,
            "get_validators_time",
        );
    }
}

impl Api for TimeApi {
    fn wire(&self, router: &mut Router) {
        let self_ = self.clone();
        let get_current_time = move |req: &mut Request| self_.get_current_time(req);
        router.get("/current_time", get_current_time, "get_current_time");
    }
}

// SERVICE DECLARATION

struct TimeService;

impl Service for TimeService {
    fn service_name(&self) -> &'static str {
        "time"
    }

    fn service_id(&self) -> u16 {
        SERVICE_ID
    }

    fn tx_from_raw(&self, raw: RawTransaction) -> Result<Box<Transaction>, encoding::Error> {
        match raw.message_type() {
            TX_TIME_ID => Ok(Box::new(TxTime::from_raw(raw)?)),
            _ => {
                let error =
                    encoding::Error::IncorrectMessageType { message_type: raw.message_type() };
                Err(error)
            }
        }
    }

    fn initialize(&self, _fork: &mut Fork) -> Value {
        Value::Null
    }

    fn handle_commit(&self, context: &mut ServiceContext) {
        let (pub_key, sec_key) = (*context.public_key(), context.secret_key().clone());
        context.add_transaction(Box::new(TxTime::new(SystemTime::now(), &pub_key, &sec_key)));
    }

    fn private_api_handler(&self, ctx: &ApiContext) -> Option<Box<Handler>> {
        let mut router = Router::new();
        let api = TimeApi {
            channel: ctx.node_channel().clone(),
            blockchain: ctx.blockchain().clone(),
        };
        api.wire(&mut router);
        Some(Box::new(router))
    }

    fn public_api_handler(&self, ctx: &ApiContext) -> Option<Box<Handler>> {
        let mut router = Router::new();
        let api = TimeApi {
            channel: ctx.node_channel().clone(),
            blockchain: ctx.blockchain().clone(),
        };
        api.wire_private(&mut router);
        Some(Box::new(router))
    }
}

fn main() {
    exonum::helpers::init_logger().unwrap();

    println!("Creating in-memory database...");
    let db = MemoryDB::new();
    let services: Vec<Box<Service>> = vec![Box::new(TimeService)];
    let blockchain = Blockchain::new(Box::new(db), services);

    let (consensus_public_key, consensus_secret_key) = exonum::crypto::gen_keypair();
    let (service_public_key, service_secret_key) = exonum::crypto::gen_keypair();

    let validator_keys = ValidatorKeys {
        consensus_key: consensus_public_key,
        service_key: service_public_key,
    };
    let genesis = GenesisConfig::new(vec![validator_keys].into_iter());

    let api_address = "0.0.0.0:8000".parse().unwrap();
    let api_cfg = NodeApiConfig {
        public_api_address: Some(api_address),
        ..Default::default()
    };

    let peer_address = "0.0.0.0:2000".parse().unwrap();

    let node_cfg = NodeConfig {
        listen_address: peer_address,
        peers: vec![],
        service_public_key,
        service_secret_key,
        consensus_public_key,
        consensus_secret_key,
        genesis,
        external_address: None,
        network: Default::default(),
        whitelist: Default::default(),
        api: api_cfg,
        mempool: Default::default(),
        services_configs: Default::default(),
    };

    println!("Starting a single node...");
    let node = Node::new(blockchain, node_cfg);

    println!("Blockchain is ready for transactions!");
    node.run().unwrap();
}
<commit_msg>Rewrite_execute<commit_after>extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate exonum;
extern crate router;
extern crate bodyparser;
extern crate iron;

use exonum::blockchain::{Blockchain, Service, ServiceContext, Schema, GenesisConfig,
                         ValidatorKeys, Transaction, ApiContext};
use exonum::node::{Node, NodeConfig, NodeApiConfig, ApiSender};
use exonum::messages::{RawTransaction, FromRaw, Message};
use exonum::encoding::serialize::json::reexport::Value;
use exonum::storage::{Fork, Snapshot, MemoryDB, MapIndex, Entry};
use exonum::crypto::{PublicKey, Hash};
use exonum::encoding;
use exonum::api::Api;
use iron::prelude::*;
use iron::Handler;
use router::Router;
use std::time::SystemTime;

const SERVICE_ID: u16 = 1;
const TX_TIME_ID: u16 = 1;

// SCHEMA

encoding_struct! {
    struct Time {
        const SIZE = 12;

        field time:     SystemTime  [00 => 12]
    }
}

pub struct TimeSchema<T> {
    view: T,
}

impl<T: AsRef<Snapshot>> TimeSchema<T> {
    pub fn new(view: T) -> Self {
        TimeSchema { view }
    }

    pub fn validators_time(&self) -> MapIndex<&Snapshot, PublicKey, Time> {
        MapIndex::new("time.validators_time", self.view.as_ref())
    }

    pub fn time(&self) -> Entry<&Snapshot, Time> {
        Entry::new("time.time", self.view.as_ref())
    }
}

impl<'a> TimeSchema<&'a mut Fork> {
    pub fn validators_time_mut(&mut self) -> MapIndex<&mut Fork, PublicKey, Time> {
        MapIndex::new("time.validators_time", self.view)
    }

    pub fn time_mut(&mut self) -> Entry<&mut Fork, Time> {
        Entry::new("time.time", self.view)
    }
}

// TRANSACTION

message! {
    struct TxTime {
        const TYPE = SERVICE_ID;
        const ID = TX_TIME_ID;
        const SIZE = 44;

        field time:     SystemTime  [00 => 12]
        field pub_key:  &PublicKey  [12 => 44]
    }
}

impl Transaction for TxTime {
    fn verify(&self) -> bool {
        self.verify_signature(self.pub_key())
    }

    fn execute(&self, view: &mut Fork) {
        let validator_keys = Schema::new(&view).actual_configuration().validator_keys;

        if validator_keys.iter().any(|&validator| {
            validator.service_key == *self.pub_key()
        })
        {
            let mut schema = TimeSchema::new(view);
            if let Some(storage_time) = schema.validators_time().get(self.pub_key()) {
                if storage_time.time() < self.time() {
                    schema.validators_time_mut().put(
                        self.pub_key(),
                        Time::new(self.time()),
                    );
                }
                else {
                    return;
                }
            }
            else {
                schema.validators_time_mut().put(
                    self.pub_key(),
                    Time::new(self.time()),
                );
            }

            let mut validators_time = Vec::new();
            {
                let idx = schema.validators_time();

                for pair in idx.iter() {
                    let (pub_key, time) = (pair.0, pair.1.time());
                    if validator_keys.iter().any(|validator| {
                        validator.service_key == pub_key
                    })
                        {
                            validators_time.push(time);
                        }
                }
            }

            let f = validator_keys.len() / 3;
            if validators_time.len() > f {
                validators_time.sort();
                validators_time.reverse();
                if let Some(current_time) = schema.time().get() {
                    if current_time.time() < validators_time[f] {
                        schema.time_mut().set(Time::new(validators_time[f]));
                    }
                }
                else {
                    schema.time_mut().set(Time::new(validators_time[f]));
                }
            }
        }
    }
}

// API

#[derive(Serialize, Deserialize)]
pub struct TxResponse {
    pub tx_hash: Hash,
}

#[derive(Clone)]
struct TimeApi {
    channel: ApiSender,
    blockchain: Blockchain,
}

impl TimeApi {
    fn get_current_time(&self, _: &mut Request) -> IronResult<Response> {
        let view = self.blockchain.snapshot();
        let schema = TimeSchema::new(&view);
        let current_time = schema.time().get();
        self.ok_response(&serde_json::to_value(current_time).unwrap())
    }

    fn get_validators_time(&self, _: &mut Request) -> IronResult<Response> {
        let view = self.blockchain.snapshot();
        let schema = TimeSchema::new(&view);
        let idx = schema.validators_time();
        let validators_time: Vec<Time> = idx.values().collect();
        if validators_time.is_empty() {
            self.not_found_response(&serde_json::to_value("Validators time database if empty")
                .unwrap())
        } else {
            self.ok_response(&serde_json::to_value(validators_time).unwrap())
        }
    }

    fn wire_private(&self, router: &mut Router) {
        let self_ = self.clone();
        let get_validators_time = move |req: &mut Request| self_.get_validators_time(req);
        router.get(
            "/validators_time",
            get_validators_time,
            "get_validators_time",
        );
    }
}

impl Api for TimeApi {
    fn wire(&self, router: &mut Router) {
        let self_ = self.clone();
        let get_current_time = move |req: &mut Request| self_.get_current_time(req);
        router.get("/current_time", get_current_time, "get_current_time");
    }
}

// SERVICE DECLARATION

struct TimeService;

impl Service for TimeService {
    fn service_name(&self) -> &'static str {
        "time"
    }

    fn service_id(&self) -> u16 {
        SERVICE_ID
    }

    fn tx_from_raw(&self, raw: RawTransaction) -> Result<Box<Transaction>, encoding::Error> {
        match raw.message_type() {
            TX_TIME_ID => Ok(Box::new(TxTime::from_raw(raw)?)),
            _ => {
                let error =
                    encoding::Error::IncorrectMessageType { message_type: raw.message_type() };
                Err(error)
            }
        }
    }

    fn initialize(&self, _fork: &mut Fork) -> Value {
        Value::Null
    }

    fn handle_commit(&self, context: &mut ServiceContext) {
        let (pub_key, sec_key) = (*context.public_key(), context.secret_key().clone());
        context.add_transaction(Box::new(TxTime::new(SystemTime::now(), &pub_key, &sec_key)));
    }

    fn private_api_handler(&self, ctx: &ApiContext) -> Option<Box<Handler>> {
        let mut router = Router::new();
        let api = TimeApi {
            channel: ctx.node_channel().clone(),
            blockchain: ctx.blockchain().clone(),
        };
        api.wire(&mut router);
        Some(Box::new(router))
    }

    fn public_api_handler(&self, ctx: &ApiContext) -> Option<Box<Handler>> {
        let mut router = Router::new();
        let api = TimeApi {
            channel: ctx.node_channel().clone(),
            blockchain: ctx.blockchain().clone(),
        };
        api.wire_private(&mut router);
        Some(Box::new(router))
    }
}

fn main() {
    exonum::helpers::init_logger().unwrap();

    println!("Creating in-memory database...");
    let db = MemoryDB::new();
    let services: Vec<Box<Service>> = vec![Box::new(TimeService)];
    let blockchain = Blockchain::new(Box::new(db), services);

    let (consensus_public_key, consensus_secret_key) = exonum::crypto::gen_keypair();
    let (service_public_key, service_secret_key) = exonum::crypto::gen_keypair();

    let validator_keys = ValidatorKeys {
        consensus_key: consensus_public_key,
        service_key: service_public_key,
    };
    let genesis = GenesisConfig::new(vec![validator_keys].into_iter());

    let api_address = "0.0.0.0:8000".parse().unwrap();
    let api_cfg = NodeApiConfig {
        public_api_address: Some(api_address),
        ..Default::default()
    };

    let peer_address = "0.0.0.0:2000".parse().unwrap();

    let node_cfg = NodeConfig {
        listen_address: peer_address,
        peers: vec![],
        service_public_key,
        service_secret_key,
        consensus_public_key,
        consensus_secret_key,
        genesis,
        external_address: None,
        network: Default::default(),
        whitelist: Default::default(),
        api: api_cfg,
        mempool: Default::default(),
        services_configs: Default::default(),
    };

    println!("Starting a single node...");
    let node = Node::new(blockchain, node_cfg);

    println!("Blockchain is ready for transactions!");
    node.run().unwrap();
}
<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (eliza@elizas.website)
//
//  Copyright (c) 2015-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! # SOS kernel
//! This crate contains the kernel for SOS, the Stupid Operating System.
//!
//! # SOS: the Stupid Operating System
//! SOS is a simple, tiny toy OS implemented in Rust. It targets the `x86`,
//! `x86_64`, and ARM v7 CPU architectures.
//!
//! I'm writing this mostly for fun, to learn more about OS design and kernel
//! hacking, so don't expect anything new or exciting out of this project.
//!
//! SOS is copyright 2015-2017 Eliza Weisman, and is released under the terms
//! of the MIT license.

#![crate_name = "sos_kernel"]

#![doc(html_root_url = "https://hawkw.github.io/sos-kernel/")]

#![feature( lang_items, asm, naked_functions )]
#![feature( linkage )]
#![feature( const_fn
          , slice_patterns
          , associated_consts
          , type_ascription
          , custom_derive )]
#![feature(collections)]

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
#![cfg_attr( any(target_arch = "x86_64", target_arch="x86")
           , feature(abi_x86_interrupt))]

#![no_std]
#![cfg_attr(not(test), no_main)]

// -- non-SOS dependencies --------------------------------------------------
#[macro_use] extern crate lazy_static;
#[macro_use] extern crate bitflags;
#[macro_use] extern crate log;

extern crate collections;
extern crate rlibc;
extern crate spin;

// -- SOS dependencies ------------------------------------------------------
#[macro_use] extern crate vga;

extern crate alloc;
extern crate cpu;
extern crate elf;
extern crate paging;
extern crate params;
extern crate memory;
extern crate util;

#[macro_use] pub mod io;

pub mod heap;
pub mod arch;
pub mod logger;

use params::InitParams;

/// SOS version number
pub const VERSION_STRING: &'static str
    = concat!("Stupid Operating System v", env!("CARGO_PKG_VERSION"));

/// Kernel main loop
pub fn kernel_main() -> ! {
    // let mut a_vec = collections::vec::Vec::<usize>::new();
    // info!(target: "test", "Created a vector in kernel space! {:?}", a_vec);
    // a_vec.push(1);
    // info!(target: "test", "pushed to vec: {:?}", a_vec);
    // a_vec.push(2);
    // info!(target: "test", "pushed to vec: {:?}", a_vec);

    // let mut frame_allocator = frame_alloc::FrameAllocator::new();
    // paging::test_paging(&mut frame_allocator);

    loop { }
}

/// Kernel initialization function called into by architecture-specific init
///
/// Our initialization process essentially looks like this:
///
/// ```text
/// +-------------+
/// | bootloader  |
/// | (multiboot) |
/// +------|------+
/// +------V------+
/// | start.asm   |
/// +------|------+
/// +------|--------------------------------------------------------+
/// |      |           RUST-LAND KERNEL FUNCTIONS                   |
/// |      V                                                        |
/// | arch_init() ----------> kernel_init() --------> kernel_main() |
/// | + collects boot info   + initializes interrupts               |
/// |   from arch-specific   + initializes the heap                 |
/// |   sources              + remaps the kernel into the higher    |
/// | + some CPU-specific      half of the address space            |
/// |   configuration                                               |
/// +---------------------------------------------------------------+
/// ```
pub fn kernel_init(params: &InitParams) {
    use alloc::frame::mem_map::MemMapAllocator;
    use ::paging::kernel_remap;

    kinfoln!("Hello from the kernel!");
    // kinfoln!("Got init params: {:#?}", params );

    // -- remap the kernel ----------------------------------------------------
    let mut frame_allocator = MemMapAllocator::from(params);
    kinfoln!(dots: " . ", "Remapping the kernel...");
    let page_table = match kernel_remap(&params, &mut frame_allocator) {
        Ok(p) => {
            kinfoln!(dots: " . ", target: "Remapping the kernel", "[ OKAY ]");
            p
        }
      , Err(why) => {
            kinfoln!(dots: " . ", target: "Remapping the kernel", "[ FAIL ]");
            panic!( "Could not remap kernel: {:?}", why)
        }
    };

    paging::test_paging(&mut frame_allocator);

    // -- initialize the heap ------------------------------------------------
    attempt!( unsafe { heap::initialize(params) } =>
             dots: " . ", "Intializing heap...");
    kinfoln!( dots: " . . "
            , "Heap begins at {:#x} and ends at {:#x}"
            , params.heap_base, params.heap_top);

    // -- initialize interrupts ----------------------------------------------
    // attempt!( unsafe { arch::interrupts::initialize() } =>
    //           "Initializing interrupts...", dots: " . " );

    println!("\n{} {}-bit\n", VERSION_STRING, arch::ARCH_BITS);

    // -- call into kernel main loop ------------------------------------------
    // (currently, this does nothing)
    kernel_main()
}

/// This fake `main` function exists only to placate `cargo test`.
#[cfg(test)]
fn main() {

}
<commit_msg>refac(kernel_init): expect that the paging test was successful<commit_after>//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (eliza@elizas.website)
//
//  Copyright (c) 2015-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! # SOS kernel
//! This crate contains the kernel for SOS, the Stupid Operating System.
//!
//! # SOS: the Stupid Operating System
//! SOS is a simple, tiny toy OS implemented in Rust. It targets the `x86`,
//! `x86_64`, and ARM v7 CPU architectures.
//!
//! I'm writing this mostly for fun, to learn more about OS design and kernel
//! hacking, so don't expect anything new or exciting out of this project.
//!
//! SOS is copyright 2015-2017 Eliza Weisman, and is released under the terms
//! of the MIT license.

#![crate_name = "sos_kernel"]

#![doc(html_root_url = "https://hawkw.github.io/sos-kernel/")]

#![feature( lang_items, asm, naked_functions )]
#![feature( linkage )]
#![feature( const_fn
          , slice_patterns
          , associated_consts
          , type_ascription
          , custom_derive )]
#![feature(collections)]

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
#![cfg_attr( any(target_arch = "x86_64", target_arch="x86")
           , feature(abi_x86_interrupt))]

#![no_std]
#![cfg_attr(not(test), no_main)]

// -- non-SOS dependencies --------------------------------------------------
#[macro_use] extern crate lazy_static;
#[macro_use] extern crate bitflags;
#[macro_use] extern crate log;

extern crate collections;
extern crate rlibc;
extern crate spin;

// -- SOS dependencies ------------------------------------------------------
#[macro_use] extern crate vga;

extern crate alloc;
extern crate cpu;
extern crate elf;
extern crate paging;
extern crate params;
extern crate memory;
extern crate util;

#[macro_use] pub mod io;

pub mod heap;
pub mod arch;
pub mod logger;

use params::InitParams;

/// SOS version number
pub const VERSION_STRING: &'static str
    = concat!("Stupid Operating System v", env!("CARGO_PKG_VERSION"));

/// Kernel main loop
pub fn kernel_main() -> ! {
    // let mut a_vec = collections::vec::Vec::<usize>::new();
    // info!(target: "test", "Created a vector in kernel space! {:?}", a_vec);
    // a_vec.push(1);
    // info!(target: "test", "pushed to vec: {:?}", a_vec);
    // a_vec.push(2);
    // info!(target: "test", "pushed to vec: {:?}", a_vec);

    // let mut frame_allocator = frame_alloc::FrameAllocator::new();
    // paging::test_paging(&mut frame_allocator);

    loop { }
}

/// Kernel initialization function called into by architecture-specific init
///
/// Our initialization process essentially looks like this:
///
/// ```text
/// +-------------+
/// | bootloader  |
/// | (multiboot) |
/// +------|------+
/// +------V------+
/// | start.asm   |
/// +------|------+
/// +------|--------------------------------------------------------+
/// |      |           RUST-LAND KERNEL FUNCTIONS                   |
/// |      V                                                        |
/// | arch_init() ----------> kernel_init() --------> kernel_main() |
/// | + collects boot info   + initializes interrupts               |
/// |   from arch-specific   + initializes the heap                 |
/// |   sources              + remaps the kernel into the higher    |
/// | + some CPU-specific      half of the address space            |
/// |   configuration                                               |
/// +---------------------------------------------------------------+
/// ```
pub fn kernel_init(params: &InitParams) {
    use alloc::frame::mem_map::MemMapAllocator;
    use ::paging::kernel_remap;

    kinfoln!("Hello from the kernel!");
    // kinfoln!("Got init params: {:#?}", params );

    // -- remap the kernel ----------------------------------------------------
    let mut frame_allocator = MemMapAllocator::from(params);
    kinfoln!(dots: " . ", "Remapping the kernel...");
    let page_table = match kernel_remap(&params, &mut frame_allocator) {
        Ok(p) => {
            kinfoln!(dots: " . ", target: "Remapping the kernel", "[ OKAY ]");
            p
        }
      , Err(why) => {
            kinfoln!(dots: " . ", target: "Remapping the kernel", "[ FAIL ]");
            panic!( "Could not remap kernel: {:?}", why)
        }
    };

    attempt!(paging::test_paging(&mut frame_allocator) =>
             dots: " . . ", "Testing paging...");

    // -- initialize the heap ------------------------------------------------
    attempt!( unsafe { heap::initialize(params) } =>
             dots: " . ", "Intializing heap...");
    kinfoln!( dots: " . . "
            , "Heap begins at {:#x} and ends at {:#x}"
            , params.heap_base, params.heap_top);

    // -- initialize interrupts ----------------------------------------------
    // attempt!( unsafe { arch::interrupts::initialize() } =>
    //           "Initializing interrupts...", dots: " . " );

    println!("\n{} {}-bit\n", VERSION_STRING, arch::ARCH_BITS);

    // -- call into kernel main loop ------------------------------------------
    // (currently, this does nothing)
    kernel_main()
}

/// This fake `main` function exists only to placate `cargo test`.
#[cfg(test)]
fn main() {

}
<|endoftext|>


<commit_before>use structopt::StructOpt;

/// The CaSILE command line interface, publishing automation level wizard.
#[derive(StructOpt)]
struct Cli {
    // #[structopt(short, long)]
    // version: [ version = env!("VERGEN_SEMVER") ],

    /// Activate debug mode
    #[structopt(short, long, env = "DEBUG")]
    debug: bool,

    /// Outputs verbose feedback where possible
    #[structopt(short, long)]
    verbose: bool,

    #[structopt(subcommand)]
    command: Command,
}

#[derive(StructOpt)]
enum Command {
    /// Executes a make target
    Make {
        target: String
    },

    /// Pass through other commands to shell
    #[structopt(external_subcommand)]
    Other(Vec<String>),
}

fn main() {
    let args = Cli::from_args();
    println!("Insert magic potion!");
    println!("Build SHA: {}", env!("VERGEN_SHA_SHORT"));
}
<commit_msg>chore(cli): Pass through correct version string<commit_after>use structopt::StructOpt;

/// The CaSILE command line interface, publishing automation level wizard.
#[derive(StructOpt)]
#[structopt(version = env!("VERGEN_SEMVER"))]
struct Cli {
    /// Activate debug mode
    #[structopt(short, long, env = "DEBUG")]
    debug: bool,

    /// Outputs verbose feedback where possible
    #[structopt(short, long)]
    verbose: bool,

    #[structopt(subcommand)]
    command: Command,
}

#[derive(StructOpt)]
enum Command {
    /// Executes a make target
    Make {
        target: String
    },

    /// Pass through other commands to shell
    #[structopt(external_subcommand)]
    Other(Vec<String>),
}

fn main() {
    let args = Cli::from_args();
    println!("Insert magic potion!");
}
<|endoftext|>