<commit_before>//
// Sysinfo
//
// Copyright (c) 2019 Guillaume Gomez
//

use std::fs::File;
use std::io::Read;
use std::path::Path;

use std::collections::HashMap;
use NetworkExt;
use NetworksExt;
use NetworksIter;

/// Network interfaces.
///
/// ```no_run
/// use sysinfo::{NetworksExt, System, SystemExt};
///
/// let s = System::new_all();
/// let networks = s.get_networks();
/// ```
#[derive(Debug)]
pub struct Networks {
    interfaces: HashMap<String, NetworkData>,
}

macro_rules! old_and_new {
    ($ty_:expr, $name:ident, $old:ident) => {{
        $ty_.$old = $ty_.$name;
        $ty_.$name = $name;
    }};
    ($ty_:expr, $name:ident, $old:ident, $path:expr) => {{
        let _tmp = $path;
        $ty_.$old = $ty_.$name;
        $ty_.$name = _tmp;
    }};
}

fn read<P: AsRef<Path>>(parent: P, path: &str, data: &mut Vec<u8>) -> usize {
    if let Ok(mut f) = File::open(parent.as_ref().join(path)) {
        if let Ok(size) = f.read(data) {
            let mut i = 0;
            let mut ret = 0;

            while i < size && i < data.len() && data[i] >= b'0' && data[i] <= b'9' {
                ret *= 10;
                ret += (data[i] - b'0') as usize;
                i += 1;
            }
            return ret;
        }
    }
    0
}

impl Networks {
    pub(crate) fn new() -> Self {
        Networks {
            interfaces: HashMap::new(),
        }
    }
}

impl NetworksExt for Networks {
    fn iter<'a>(&'a self) -> NetworksIter<'a> {
        NetworksIter::new(self.interfaces.iter())
    }

    fn refresh(&mut self) {
        let mut v = vec![0; 30];

        for (interface_name, data) in self.interfaces.iter_mut() {
            data.update(interface_name, &mut v);
        }
    }

    fn refresh_networks_list(&mut self) {
        if let Ok(dir) = std::fs::read_dir("/sys/class/net/") {
            let mut data = vec![0; 30];
            for entry in dir {
                if let Ok(entry) = entry {
                    let parent = &entry.path().join("statistics");
                    let entry = match entry.file_name().into_string() {
                        Ok(entry) => entry,
                        Err(_) => continue,
                    };
                    let rx_bytes = read(parent, "rx_bytes", &mut data);
                    let tx_bytes = read(parent, "tx_bytes", &mut data);
                    let rx_packets = read(parent, "rx_packets", &mut data);
                    let tx_packets = read(parent, "tx_packets", &mut data);
                    let rx_errors = read(parent, "rx_errors", &mut data);
                    let tx_errors = read(parent, "tx_errors", &mut data);
                    let rx_compressed = read(parent, "rx_compressed", &mut data);
                    let tx_compressed = read(parent, "tx_compressed", &mut data);
                    let interface = self.interfaces.entry(entry).or_insert_with(|| NetworkData {
                        rx_bytes,
                        old_rx_bytes: rx_bytes,
                        tx_bytes,
                        old_tx_bytes: tx_bytes,
                        rx_packets,
                        old_rx_packets: rx_packets,
                        tx_packets,
                        old_tx_packets: tx_packets,
                        rx_errors,
                        old_rx_errors: rx_errors,
                        tx_errors,
                        old_tx_errors: tx_errors,
                        rx_compressed,
                        old_rx_compressed: rx_compressed,
                        tx_compressed,
                        old_tx_compressed: tx_compressed,
                    });
                    old_and_new!(interface, rx_bytes, old_rx_bytes);
                    old_and_new!(interface, tx_bytes, old_tx_bytes);
                    old_and_new!(interface, rx_packets, old_rx_packets);
                    old_and_new!(interface, tx_packets, old_tx_packets);
                    old_and_new!(interface, rx_errors, old_rx_errors);
                    old_and_new!(interface, tx_errors, old_tx_errors);
                    old_and_new!(interface, rx_compressed, old_rx_compressed);
                    old_and_new!(interface, tx_compressed, old_tx_compressed);
                }
            }
        }
    }
}

/// Contains network information.
#[derive(Debug)]
pub struct NetworkData {
    /// Total number of bytes received over interface.
    rx_bytes: usize,
    old_rx_bytes: usize,
    /// Total number of bytes transmitted over interface.
    tx_bytes: usize,
    old_tx_bytes: usize,
    /// Total number of packets received.
    rx_packets: usize,
    old_rx_packets: usize,
    /// Total number of packets transmitted.
    tx_packets: usize,
    old_tx_packets: usize,
    /// Shows the total number of packets received with error. This includes
    /// too-long-frames errors, ring-buffer overflow errors, CRC errors,
    /// frame alignment errors, fifo overruns, and missed packets.
    rx_errors: usize,
    old_rx_errors: usize,
    /// similar to `rx_errors`
    tx_errors: usize,
    old_tx_errors: usize,
    /// Indicates the number of compressed packets received by this
    /// network device. This value might only be relevant for interfaces
    /// that support packet compression (e.g: PPP).
    rx_compressed: usize,
    old_rx_compressed: usize,
    /// Indicates the number of transmitted compressed packets. Note
    /// this might only be relevant for devices that support
    /// compression (e.g: PPP).
    tx_compressed: usize,
    old_tx_compressed: usize,
}

impl NetworkData {
    fn update(&mut self, path: &str, data: &mut Vec<u8>) {
        let path = &Path::new("/sys/class/net/").join(path).join("statistics");
        old_and_new!(self, rx_bytes, old_rx_bytes, read(path, "rx_bytes", data));
        old_and_new!(self, tx_bytes, old_tx_bytes, read(path, "tx_bytes", data));
        old_and_new!(
            self,
            rx_packets,
            old_rx_packets,
            read(path, "rx_packets", data)
        );
        old_and_new!(
            self,
            tx_packets,
            old_tx_packets,
            read(path, "tx_packets", data)
        );
        old_and_new!(
            self,
            rx_errors,
            old_rx_errors,
            read(path, "rx_errors", data)
        );
        old_and_new!(
            self,
            tx_errors,
            old_tx_errors,
            read(path, "tx_errors", data)
        );
        old_and_new!(
            self,
            rx_compressed,
            old_rx_compressed,
            read(path, "rx_compressed", data)
        );
        old_and_new!(
            self,
            tx_compressed,
            old_tx_compressed,
            read(path, "tx_compressed", data)
        );
    }
}

impl NetworkExt for NetworkData {
    fn get_income(&self) -> u64 {
        self.rx_bytes as u64 - self.old_rx_bytes as u64
    }

    fn get_outcome(&self) -> u64 {
        self.tx_bytes as u64 - self.old_tx_bytes as u64
    }

    fn get_total_income(&self) -> u64 {
        self.rx_bytes as u64
    }

    fn get_total_outcome(&self) -> u64 {
        self.rx_bytes as u64
    }
}
<commit_msg>Don't read network compressed packets on linux for the moment<commit_after>//
// Sysinfo
//
// Copyright (c) 2019 Guillaume Gomez
//

use std::fs::File;
use std::io::Read;
use std::path::Path;

use std::collections::HashMap;
use NetworkExt;
use NetworksExt;
use NetworksIter;

/// Network interfaces.
///
/// ```no_run
/// use sysinfo::{NetworksExt, System, SystemExt};
///
/// let s = System::new_all();
/// let networks = s.get_networks();
/// ```
#[derive(Debug)]
pub struct Networks {
    interfaces: HashMap<String, NetworkData>,
}

macro_rules! old_and_new {
    ($ty_:expr, $name:ident, $old:ident) => {{
        $ty_.$old = $ty_.$name;
        $ty_.$name = $name;
    }};
    ($ty_:expr, $name:ident, $old:ident, $path:expr) => {{
        let _tmp = $path;
        $ty_.$old = $ty_.$name;
        $ty_.$name = _tmp;
    }};
}

fn read<P: AsRef<Path>>(parent: P, path: &str, data: &mut Vec<u8>) -> usize {
    if let Ok(mut f) = File::open(parent.as_ref().join(path)) {
        if let Ok(size) = f.read(data) {
            let mut i = 0;
            let mut ret = 0;

            while i < size && i < data.len() && data[i] >= b'0' && data[i] <= b'9' {
                ret *= 10;
                ret += (data[i] - b'0') as usize;
                i += 1;
            }
            return ret;
        }
    }
    0
}

impl Networks {
    pub(crate) fn new() -> Self {
        Networks {
            interfaces: HashMap::new(),
        }
    }
}

impl NetworksExt for Networks {
    fn iter<'a>(&'a self) -> NetworksIter<'a> {
        NetworksIter::new(self.interfaces.iter())
    }

    fn refresh(&mut self) {
        let mut v = vec![0; 30];

        for (interface_name, data) in self.interfaces.iter_mut() {
            data.update(interface_name, &mut v);
        }
    }

    fn refresh_networks_list(&mut self) {
        if let Ok(dir) = std::fs::read_dir("/sys/class/net/") {
            let mut data = vec![0; 30];
            for entry in dir {
                if let Ok(entry) = entry {
                    let parent = &entry.path().join("statistics");
                    let entry = match entry.file_name().into_string() {
                        Ok(entry) => entry,
                        Err(_) => continue,
                    };
                    let rx_bytes = read(parent, "rx_bytes", &mut data);
                    let tx_bytes = read(parent, "tx_bytes", &mut data);
                    let rx_packets = read(parent, "rx_packets", &mut data);
                    let tx_packets = read(parent, "tx_packets", &mut data);
                    let rx_errors = read(parent, "rx_errors", &mut data);
                    let tx_errors = read(parent, "tx_errors", &mut data);
                    // let rx_compressed = read(parent, "rx_compressed", &mut data);
                    // let tx_compressed = read(parent, "tx_compressed", &mut data);
                    let interface = self.interfaces.entry(entry).or_insert_with(|| NetworkData {
                        rx_bytes,
                        old_rx_bytes: rx_bytes,
                        tx_bytes,
                        old_tx_bytes: tx_bytes,
                        rx_packets,
                        old_rx_packets: rx_packets,
                        tx_packets,
                        old_tx_packets: tx_packets,
                        rx_errors,
                        old_rx_errors: rx_errors,
                        tx_errors,
                        old_tx_errors: tx_errors,
                        // rx_compressed,
                        // old_rx_compressed: rx_compressed,
                        // tx_compressed,
                        // old_tx_compressed: tx_compressed,
                    });
                    old_and_new!(interface, rx_bytes, old_rx_bytes);
                    old_and_new!(interface, tx_bytes, old_tx_bytes);
                    old_and_new!(interface, rx_packets, old_rx_packets);
                    old_and_new!(interface, tx_packets, old_tx_packets);
                    old_and_new!(interface, rx_errors, old_rx_errors);
                    old_and_new!(interface, tx_errors, old_tx_errors);
                    // old_and_new!(interface, rx_compressed, old_rx_compressed);
                    // old_and_new!(interface, tx_compressed, old_tx_compressed);
                }
            }
        }
    }
}

/// Contains network information.
#[derive(Debug)]
pub struct NetworkData {
    /// Total number of bytes received over interface.
    rx_bytes: usize,
    old_rx_bytes: usize,
    /// Total number of bytes transmitted over interface.
    tx_bytes: usize,
    old_tx_bytes: usize,
    /// Total number of packets received.
    rx_packets: usize,
    old_rx_packets: usize,
    /// Total number of packets transmitted.
    tx_packets: usize,
    old_tx_packets: usize,
    /// Shows the total number of packets received with error. This includes
    /// too-long-frames errors, ring-buffer overflow errors, CRC errors,
    /// frame alignment errors, fifo overruns, and missed packets.
    rx_errors: usize,
    old_rx_errors: usize,
    /// similar to `rx_errors`
    tx_errors: usize,
    old_tx_errors: usize,
    // /// Indicates the number of compressed packets received by this
    // /// network device. This value might only be relevant for interfaces
    // /// that support packet compression (e.g: PPP).
    // rx_compressed: usize,
    // old_rx_compressed: usize,
    // /// Indicates the number of transmitted compressed packets. Note
    // /// this might only be relevant for devices that support
    // /// compression (e.g: PPP).
    // tx_compressed: usize,
    // old_tx_compressed: usize,
}

impl NetworkData {
    fn update(&mut self, path: &str, data: &mut Vec<u8>) {
        let path = &Path::new("/sys/class/net/").join(path).join("statistics");
        old_and_new!(self, rx_bytes, old_rx_bytes, read(path, "rx_bytes", data));
        old_and_new!(self, tx_bytes, old_tx_bytes, read(path, "tx_bytes", data));
        old_and_new!(
            self,
            rx_packets,
            old_rx_packets,
            read(path, "rx_packets", data)
        );
        old_and_new!(
            self,
            tx_packets,
            old_tx_packets,
            read(path, "tx_packets", data)
        );
        old_and_new!(
            self,
            rx_errors,
            old_rx_errors,
            read(path, "rx_errors", data)
        );
        old_and_new!(
            self,
            tx_errors,
            old_tx_errors,
            read(path, "tx_errors", data)
        );
        // old_and_new!(
        //     self,
        //     rx_compressed,
        //     old_rx_compressed,
        //     read(path, "rx_compressed", data)
        // );
        // old_and_new!(
        //     self,
        //     tx_compressed,
        //     old_tx_compressed,
        //     read(path, "tx_compressed", data)
        // );
    }
}

impl NetworkExt for NetworkData {
    fn get_income(&self) -> u64 {
        self.rx_bytes as u64 - self.old_rx_bytes as u64
    }

    fn get_outcome(&self) -> u64 {
        self.tx_bytes as u64 - self.old_tx_bytes as u64
    }

    fn get_total_income(&self) -> u64 {
        self.rx_bytes as u64
    }

    fn get_total_outcome(&self) -> u64 {
        self.rx_bytes as u64
    }
}
<|endoftext|>


<commit_before>use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::collections::{BinaryHeap, HashMap};

use std::hash::Hash;

use super::visit::{EdgeRef, GraphBase, IntoEdges, VisitMap, Visitable};
use crate::scored::MinScored;

use crate::algo::Measure;

/// \[Generic\] A* shortest path algorithm.
///
/// Computes the shortest path from `start` to `finish`, including the total path cost.
///
/// `finish` is implicitly given via the `is_goal` callback, which should return `true` if the
/// given node is the finish node.
///
/// The function `edge_cost` should return the cost for a particular edge. Edge costs must be
/// non-negative.
///
/// The function `estimate_cost` should return the estimated cost to the finish for a particular
/// node. For the algorithm to find the actual shortest path, it should be admissible, meaning that
/// it should never overestimate the actual cost to get to the nearest goal node. Estimate costs
/// must also be non-negative.
///
/// The graph should be `Visitable` and implement `IntoEdges`.
///
/// # Example
/// ```
/// use petgraph::Graph;
/// use petgraph::algo::astar;
///
/// let mut g = Graph::new();
/// let a = g.add_node((0., 0.));
/// let b = g.add_node((2., 0.));
/// let c = g.add_node((1., 1.));
/// let d = g.add_node((0., 2.));
/// let e = g.add_node((3., 3.));
/// let f = g.add_node((4., 2.));
/// g.extend_with_edges(&[
///     (a, b, 2),
///     (a, d, 4),
///     (b, c, 1),
///     (b, f, 7),
///     (c, e, 5),
///     (e, f, 1),
///     (d, e, 1),
/// ]);
///
/// // Graph represented with the weight of each edge
/// // Edges with '*' are part of the optimal path.
/// //
/// //     2       1
/// // a ----- b ----- c
/// // | 4*    | 7     |
/// // d       f       | 5
/// // | 1*    | 1*    |
/// // \------ e ------/
///
/// let path = astar(&g, a, |finish| finish == f, |e| *e.weight(), |_| 0);
/// assert_eq!(path, Some((6, vec![a, d, e, f])));
/// ```
///
/// Returns the total cost + the path of subsequent `NodeId` from start to finish, if one was
/// found.
pub fn astar<G, F, H, K, IsGoal>(
    graph: G,
    start: G::NodeId,
    mut is_goal: IsGoal,
    mut edge_cost: F,
    mut estimate_cost: H,
) -> Option<(K, Vec<G::NodeId>)>
where
    G: IntoEdges + Visitable,
    IsGoal: FnMut(G::NodeId) -> bool,
    G::NodeId: Eq + Hash,
    F: FnMut(G::EdgeRef) -> K,
    H: FnMut(G::NodeId) -> K,
    K: Measure + Copy,
{
    let mut visited = graph.visit_map();
    let mut visit_next = BinaryHeap::new();
    let mut scores = HashMap::new();
    let mut path_tracker = PathTracker::<G>::new();

    let zero_score = K::default();
    scores.insert(start, zero_score);
    visit_next.push(MinScored(estimate_cost(start), start));

    while let Some(MinScored(_, node)) = visit_next.pop() {
        if is_goal(node) {
            let path = path_tracker.reconstruct_path_to(node);
            let cost = scores[&node];
            return Some((cost, path));
        }

        // Don't visit the same node several times, as the first time it was visited it was using
        // the shortest available path.
        if !visited.visit(node) {
            continue;
        }

        // This lookup can be unwrapped without fear of panic since the node was necessarily scored
        // before adding him to `visit_next`.
        let node_score = scores[&node];

        for edge in graph.edges(node) {
            let next = edge.target();
            if visited.is_visited(&next) {
                continue;
            }

            let mut next_score = node_score + edge_cost(edge);

            match scores.entry(next) {
                Occupied(ent) => {
                    let old_score = *ent.get();
                    if next_score < old_score {
                        *ent.into_mut() = next_score;
                        path_tracker.set_predecessor(next, node);
                    } else {
                        next_score = old_score;
                    }
                }
                Vacant(ent) => {
                    ent.insert(next_score);
                    path_tracker.set_predecessor(next, node);
                }
            }

            let next_estimate_score = next_score + estimate_cost(next);
            visit_next.push(MinScored(next_estimate_score, next));
        }
    }

    None
}

struct PathTracker<G>
where
    G: GraphBase,
    G::NodeId: Eq + Hash,
{
    came_from: HashMap<G::NodeId, G::NodeId>,
}

impl<G> PathTracker<G>
where
    G: GraphBase,
    G::NodeId: Eq + Hash,
{
    fn new() -> PathTracker<G> {
        PathTracker {
            came_from: HashMap::new(),
        }
    }

    fn set_predecessor(&mut self, node: G::NodeId, previous: G::NodeId) {
        self.came_from.insert(node, previous);
    }

    fn reconstruct_path_to(&self, last: G::NodeId) -> Vec<G::NodeId> {
        let mut path = vec![last];

        let mut current = last;
        while let Some(&previous) = self.came_from.get(&current) {
            path.push(previous);
            current = previous;
        }

        path.reverse();

        path
    }
}
<commit_msg>Ensure A* algorithm re-visits nodes when needed<commit_after>use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::collections::{BinaryHeap, HashMap};

use std::hash::Hash;

use super::visit::{EdgeRef, GraphBase, IntoEdges};
use crate::scored::MinScored;

use crate::algo::Measure;

/// \[Generic\] A* shortest path algorithm.
///
/// Computes the shortest path from `start` to `finish`, including the total path cost.
///
/// `finish` is implicitly given via the `is_goal` callback, which should return `true` if the
/// given node is the finish node.
///
/// The function `edge_cost` should return the cost for a particular edge. Edge costs must be
/// non-negative.
///
/// The function `estimate_cost` should return the estimated cost to the finish for a particular
/// node. For the algorithm to find the actual shortest path, it should be admissible, meaning that
/// it should never overestimate the actual cost to get to the nearest goal node. Estimate costs
/// must also be non-negative.
///
/// The graph should be `Visitable` and implement `IntoEdges`.
///
/// # Example
/// ```
/// use petgraph::Graph;
/// use petgraph::algo::astar;
///
/// let mut g = Graph::new();
/// let a = g.add_node((0., 0.));
/// let b = g.add_node((2., 0.));
/// let c = g.add_node((1., 1.));
/// let d = g.add_node((0., 2.));
/// let e = g.add_node((3., 3.));
/// let f = g.add_node((4., 2.));
/// g.extend_with_edges(&[
///     (a, b, 2),
///     (a, d, 4),
///     (b, c, 1),
///     (b, f, 7),
///     (c, e, 5),
///     (e, f, 1),
///     (d, e, 1),
/// ]);
///
/// // Graph represented with the weight of each edge
/// // Edges with '*' are part of the optimal path.
/// //
/// //     2       1
/// // a ----- b ----- c
/// // | 4*    | 7     |
/// // d       f       | 5
/// // | 1*    | 1*    |
/// // \------ e ------/
///
/// let path = astar(&g, a, |finish| finish == f, |e| *e.weight(), |_| 0);
/// assert_eq!(path, Some((6, vec![a, d, e, f])));
/// ```
///
/// Returns the total cost + the path of subsequent `NodeId` from start to finish, if one was
/// found.
pub fn astar<G, F, H, K, IsGoal>(
    graph: G,
    start: G::NodeId,
    mut is_goal: IsGoal,
    mut edge_cost: F,
    mut estimate_cost: H,
) -> Option<(K, Vec<G::NodeId>)>
where
    G: IntoEdges,
    IsGoal: FnMut(G::NodeId) -> bool,
    G::NodeId: Eq + Hash,
    F: FnMut(G::EdgeRef) -> K,
    H: FnMut(G::NodeId) -> K,
    K: Measure + Copy,
{
    let mut visit_next = BinaryHeap::new();
    let mut scores = HashMap::new();
    let mut path_tracker = PathTracker::<G>::new();

    let zero_score = K::default();
    scores.insert(start, zero_score);
    visit_next.push(MinScored(estimate_cost(start), start));

    while let Some(MinScored(_, node)) = visit_next.pop() {
        if is_goal(node) {
            let path = path_tracker.reconstruct_path_to(node);
            let cost = scores[&node];
            return Some((cost, path));
        }

        // This lookup can be unwrapped without fear of panic since the node was necessarily scored
        // before adding it to `visit_next`.
        let node_score = scores[&node];

        for edge in graph.edges(node) {
            let next = edge.target();
            let next_score = node_score + edge_cost(edge);

            match scores.entry(next) {
                Occupied(mut entry) => {
                    // No need to add neighbors that we have already reached, unless the new path
                    // is shorter.
                    if &next_score < entry.get() {
                        entry.insert(next_score);
                    } else {
                        continue;
                    }
                }
                Vacant(entry) => {
                    entry.insert(next_score);
                }
            }

            path_tracker.set_predecessor(next, node);
            let next_estimate_score = next_score + estimate_cost(next);
            visit_next.push(MinScored(next_estimate_score, next));
        }
    }

    None
}

struct PathTracker<G>
where
    G: GraphBase,
    G::NodeId: Eq + Hash,
{
    came_from: HashMap<G::NodeId, G::NodeId>,
}

impl<G> PathTracker<G>
where
    G: GraphBase,
    G::NodeId: Eq + Hash,
{
    fn new() -> PathTracker<G> {
        PathTracker {
            came_from: HashMap::new(),
        }
    }

    fn set_predecessor(&mut self, node: G::NodeId, previous: G::NodeId) {
        self.came_from.insert(node, previous);
    }

    fn reconstruct_path_to(&self, last: G::NodeId) -> Vec<G::NodeId> {
        let mut path = vec![last];

        let mut current = last;
        while let Some(&previous) = self.came_from.get(&current) {
            path.push(previous);
            current = previous;
        }

        path.reverse();

        path
    }
}
<|endoftext|>


<commit_before>use ::*;

#[derive(Debug, Serialize)]
struct Ballstats {
    name: String,
    games: i32,
    goals: i32,
    img: String,
}

#[get("/balls")]
fn balls<'a>() -> ContRes<'a> {
    let conn = lock_database();
    let mut stmt =
        conn.prepare("select ball_id, sum(home_score+away_score) as goals, count(ball_id) as balls, (select name from balls where ball_id = balls.id), (select img from balls where ball_id = balls.id) FROM games WHERE dato > date('now','start of month') GROUP BY ball_id order by balls desc , goals desc")
            .unwrap();

    let ballstats: Vec<_> = stmt.query_map(&[], |row| {
        Ballstats {
            name: row.get(3),
            img: row.get(4),
            games: row.get(2),
            goals: row.get(1),
        }
    })
    .unwrap()
    .map(Result::unwrap)
    .collect();
    let mut context = create_context("balls");
    context.add("ballstats", &ballstats);

    respond_page("balls", context)
}

#[get("/ball/<ball>")]
fn ball<'a>(ball:String) -> ContRes<'a> {
    let conn = lock_database();
    let mut stmt =
        conn.prepare("SELECT \
            (SELECT name FROM players p WHERE p.id = g.home_id) AS home, \
            (SELECT name FROM players p WHERE p.id = g.away_id) AS away, home_score, away_score, ball_id,  \
            (SELECT img FROM balls b WHERE ball_id = b.id), \
            (SELECT name FROM balls b WHERE ball_id = b.id) AS ballname, \
            dato \
            FROM games g  \
            WHERE ballname = ?1 AND dato > date('now','start of month') \
            ORDER BY ID DESC")
            .unwrap();
    let games: Vec<_> = stmt.query_map(&[&ball], |row| {
            PlayedGame {
                home: row.get(0),
                away: row.get(1),
                home_score: row.get(2),
                away_score: row.get(3),
                ball: row.get(5),
                ball_name: row.get(6),
                dato: row.get(7),
            }
        })
        .unwrap()
        .map(Result::unwrap)
        .collect();

    let mut context = create_context("balls");
    if games.len() != 0 {
        println!("Ukendt bold: {}",ball);
    }

    context.add("games", &games);
    context.add("ball", &ball);
    respond_page("ball", context)
}

#[get("/newball")]
fn newball<'a>() -> ContRes<'a> {
    let conn = lock_database();
    let mut stmt = conn.prepare("SELECT id, name, img from balls ORDER BY name ASC").unwrap();

    let mut balls = Vec::new();

    for ball in stmt.query_map(&[], |row| (row.get::<_, i32>(0), row.get::<_, String>(1), row.get::<_, String>(2))).unwrap() {
        let (id, name, img) = ball.unwrap();
        balls.push(Ball{id: id, name: name, img: img});
    }

    let mut context = create_context("balls");
    context.add("balls", &balls);

    respond_page("newball", context)
}

#[derive(FromForm)]
struct NewBallQuery {
    name: String,
    img: String,
    secret: String,
    #[allow(dead_code)]
    submit: IgnoreField
}

#[post("/newball/submit", data = "<f>")]
fn submit_newball<'r>(f: Form<NewBallQuery>) -> Resp<'r> {
    let NewBallQuery{name, img, secret, ..} = f.into_inner();

    let mut context = create_context("balls");
    if secret != CONFIG.secret {
        context.add("fejl", &"Det indtastede kodeord er forkert 💩");
    } else if name.is_empty() {
        context.add("fejl", &"Den indtastede bold er ikke lovlig 😜");
    } else {
        let n = lock_database().execute("INSERT INTO balls (name, img) VALUES (?, ?)", &[&img, &name]).unwrap();

        if n == 0 {
            context.add("fejl", &"Den indtastede bold eksisterer allerede 💩");
        } else {
            reset_ratings();
            return Resp::red(Redirect::to("/"));
        }
    }
    Resp::cont(respond_page("newball_fejl", context))
}
<commit_msg>Removed debug text on  /ball/<ball><commit_after>use ::*;

#[derive(Debug, Serialize)]
struct Ballstats {
    name: String,
    games: i32,
    goals: i32,
    img: String,
}

#[get("/balls")]
fn balls<'a>() -> ContRes<'a> {
    let conn = lock_database();
    let mut stmt =
        conn.prepare("select ball_id, sum(home_score+away_score) as goals, count(ball_id) as balls, (select name from balls where ball_id = balls.id), (select img from balls where ball_id = balls.id) FROM games WHERE dato > date('now','start of month') GROUP BY ball_id order by balls desc , goals desc")
            .unwrap();

    let ballstats: Vec<_> = stmt.query_map(&[], |row| {
        Ballstats {
            name: row.get(3),
            img: row.get(4),
            games: row.get(2),
            goals: row.get(1),
        }
    })
    .unwrap()
    .map(Result::unwrap)
    .collect();
    let mut context = create_context("balls");
    context.add("ballstats", &ballstats);

    respond_page("balls", context)
}

#[get("/ball/<ball>")]
fn ball<'a>(ball:String) -> ContRes<'a> {
    let conn = lock_database();
    let mut stmt =
        conn.prepare("SELECT \
            (SELECT name FROM players p WHERE p.id = g.home_id) AS home, \
            (SELECT name FROM players p WHERE p.id = g.away_id) AS away, home_score, away_score, ball_id,  \
            (SELECT img FROM balls b WHERE ball_id = b.id), \
            (SELECT name FROM balls b WHERE ball_id = b.id) AS ballname, \
            dato \
            FROM games g  \
            WHERE ballname = ?1 AND dato > date('now','start of month') \
            ORDER BY ID DESC")
            .unwrap();
    let games: Vec<_> = stmt.query_map(&[&ball], |row| {
            PlayedGame {
                home: row.get(0),
                away: row.get(1),
                home_score: row.get(2),
                away_score: row.get(3),
                ball: row.get(5),
                ball_name: row.get(6),
                dato: row.get(7),
            }
        })
        .unwrap()
        .map(Result::unwrap)
        .collect();

    let mut context = create_context("balls");

    context.add("games", &games);
    context.add("ball", &ball);
    respond_page("ball", context)
}

#[get("/newball")]
fn newball<'a>() -> ContRes<'a> {
    let conn = lock_database();
    let mut stmt = conn.prepare("SELECT id, name, img from balls ORDER BY name ASC").unwrap();

    let mut balls = Vec::new();

    for ball in stmt.query_map(&[], |row| (row.get::<_, i32>(0), row.get::<_, String>(1), row.get::<_, String>(2))).unwrap() {
        let (id, name, img) = ball.unwrap();
        balls.push(Ball{id: id, name: name, img: img});
    }

    let mut context = create_context("balls");
    context.add("balls", &balls);

    respond_page("newball", context)
}

#[derive(FromForm)]
struct NewBallQuery {
    name: String,
    img: String,
    secret: String,
    #[allow(dead_code)]
    submit: IgnoreField
}

#[post("/newball/submit", data = "<f>")]
fn submit_newball<'r>(f: Form<NewBallQuery>) -> Resp<'r> {
    let NewBallQuery{name, img, secret, ..} = f.into_inner();

    let mut context = create_context("balls");
    if secret != CONFIG.secret {
        context.add("fejl", &"Det indtastede kodeord er forkert 💩");
    } else if name.is_empty() {
        context.add("fejl", &"Den indtastede bold er ikke lovlig 😜");
    } else {
        let n = lock_database().execute("INSERT INTO balls (name, img) VALUES (?, ?)", &[&img, &name]).unwrap();

        if n == 0 {
            context.add("fejl", &"Den indtastede bold eksisterer allerede 💩");
        } else {
            reset_ratings();
            return Resp::red(Redirect::to("/"));
        }
    }
    Resp::cont(respond_page("newball_fejl", context))
}
<|endoftext|>


<commit_before>
use std::ops::Add;
use std::ops::Sub;
use std::ops::Mul;
use std::cmp;

#[derive(Debug, Eq)]
pub struct BaseN/*<T>*/{
    base: usize, // TODO: Why isn't base u8?  Want to limit to 255 right?
    vec: Vec</*T*/u8>
}

impl BaseN {

    pub fn new(base: usize) -> BaseN/*<T>*/ {
        BaseN { base: base, vec: Vec::new() }
    }
    pub fn with_capacity(base: usize, capacity: usize) -> BaseN {
        BaseN { base: base, vec: Vec::with_capacity(capacity) }
    }
    pub fn with_existing(base: usize, vec: Vec<u8>) -> BaseN {
        BaseN { base: base, vec: vec }
    }
    pub fn from_usize(base: usize, val: usize) -> Result<BaseN, &'static str> {

        let mut new_vec:Vec<u8> = Vec::new();
        let mut val10: usize = val;
        loop {
            let _val = val10 / base;
            match _val {
                0 => {
                    new_vec.push(val10 as u8);
                    break;
                }
                _ => {
                    let remainder = val10 % base;
                    println!("{}", remainder);
                    new_vec.push(remainder as u8);
                    val10 = _val;
                }
            }
        }
        let new_basen: BaseN = BaseN { base: base, vec: new_vec };

        Ok(new_basen)
    }

    pub fn to_base(self, new_base: usize) -> Result<BaseN, &'static str> {

        //TODO: If base is same, just return existing??
        if self.base == new_base {
            return Ok(self);
        }

        // TODO: Create copy, convert mutable, or both?
        //let new_basen = BaseN::new(new_base);

        println!("converting base {} to base {}", self.base, new_base);
        let mut val10: usize = self.to_usize().unwrap();
        println!("{}", val10);

        BaseN::from_usize(new_base, val10)

    }
    pub fn to_usize(&self) -> Result<usize, &'static str> {
        let mut _val10: usize = 0;
        for (i, x) in self.vec.iter().enumerate() {
            _val10 = _val10 + (*x as usize) * self.base.pow(i as u32);
        }
        Ok(_val10)
    }

}

//impl Copy for BaseN { }

impl PartialEq for BaseN {
    fn eq(&self, other: &BaseN) -> bool {
        (self.vec == other.vec)
            && (self.base == other.base)
    }
}

impl Clone for BaseN {
    fn clone(&self) -> Self {
        BaseN { base: self.base, vec: self.vec.clone() }
    }

    fn clone_from(&mut self, source: &Self) {
        self.vec.clone_from(&source.vec);
        self.base = source.base;
    }
}

impl Add for BaseN {
    type Output = Result<BaseN, &'static str>;

    // Option<> because might overflow, bases incorrect, etc.
    // I suppose you could add a base16 to base10 with an internal convert
    fn add(self, _rhs: BaseN) -> Result<BaseN, &'static str> {

        let add_basen = match _rhs.base==self.base {
            true => _rhs,//.clone(),
            false => _rhs.to_base(self.base).unwrap()
                // TODO: Throw error?  Don't actually know
                // what base user wanted to end with
        };

        // TODO: Use zip() w/ carry array instead?
        let max = cmp::max(self.vec.len(), add_basen.vec.len());
        let mut new_vec: Vec<u8> = Vec::with_capacity(max);

        let mut carry: u8 = 0;

        for i in 0..max {
            match (self.vec.get(i), add_basen.vec.get(i)) {
                (Some(x), Some(y)) => {
                    let sum: u8 = *x + *y + carry;
                    carry = sum / (add_basen.base as u8);
                    new_vec.push(sum % (add_basen.base as u8));
                },
                (Some(x), None) => {
                    // no carry, but need to resize
                    let sum: u8 = *x + carry;
                    carry = sum / (add_basen.base as u8);
                    new_vec.push(sum % (add_basen.base as u8));
                },
                (_, _) => break // no ops needed

            }
        }

        let new_basen: BaseN = BaseN { base: add_basen.base, vec: new_vec };

        Ok(new_basen)
    }
}

<commit_msg>Make struct fields public<commit_after>
use std::ops::Add;
use std::ops::Sub;
use std::ops::Mul;
use std::cmp;

#[derive(Debug, Eq)]
pub struct BaseN/*<T>*/{
    pub base: usize, // TODO: Why isn't base u8?  Want to limit to 255 right?
    pub vec: Vec</*T*/u8>
    // TODO: Make proper accessor functions for struct fields
}

impl BaseN {

    pub fn new(base: usize) -> BaseN/*<T>*/ {
        BaseN { base: base, vec: Vec::new() }
    }
    pub fn with_capacity(base: usize, capacity: usize) -> BaseN {
        BaseN { base: base, vec: Vec::with_capacity(capacity) }
    }
    pub fn with_existing(base: usize, vec: Vec<u8>) -> BaseN {
        BaseN { base: base, vec: vec }
    }
    pub fn from_usize(base: usize, val: usize) -> Result<BaseN, &'static str> {

        let mut new_vec:Vec<u8> = Vec::new();
        let mut val10: usize = val;
        loop {
            let _val = val10 / base;
            match _val {
                0 => {
                    new_vec.push(val10 as u8);
                    break;
                }
                _ => {
                    let remainder = val10 % base;
                    println!("{}", remainder);
                    new_vec.push(remainder as u8);
                    val10 = _val;
                }
            }
        }
        let new_basen: BaseN = BaseN { base: base, vec: new_vec };

        Ok(new_basen)
    }

    pub fn to_base(self, new_base: usize) -> Result<BaseN, &'static str> {

        //TODO: If base is same, just return existing??
        if self.base == new_base {
            return Ok(self);
        }

        // TODO: Create copy, convert mutable, or both?
        //let new_basen = BaseN::new(new_base);

        println!("converting base {} to base {}", self.base, new_base);
        let mut val10: usize = self.to_usize().unwrap();
        println!("{}", val10);

        BaseN::from_usize(new_base, val10)

    }
    pub fn to_usize(&self) -> Result<usize, &'static str> {
        let mut _val10: usize = 0;
        for (i, x) in self.vec.iter().enumerate() {
            _val10 = _val10 + (*x as usize) * self.base.pow(i as u32);
        }
        Ok(_val10)
    }

}

//impl Copy for BaseN { }

impl PartialEq for BaseN {
    fn eq(&self, other: &BaseN) -> bool {
        (self.vec == other.vec)
            && (self.base == other.base)
    }
}

impl Clone for BaseN {
    fn clone(&self) -> Self {
        BaseN { base: self.base, vec: self.vec.clone() }
    }

    fn clone_from(&mut self, source: &Self) {
        self.vec.clone_from(&source.vec);
        self.base = source.base;
    }
}

impl Add for BaseN {
    type Output = Result<BaseN, &'static str>;

    // Option<> because might overflow, bases incorrect, etc.
    // I suppose you could add a base16 to base10 with an internal convert
    fn add(self, _rhs: BaseN) -> Result<BaseN, &'static str> {

        let add_basen = match _rhs.base==self.base {
            true => _rhs,//.clone(),
            false => _rhs.to_base(self.base).unwrap()
                // TODO: Throw error?  Don't actually know
                // what base user wanted to end with
        };

        // TODO: Use zip() w/ carry array instead?
        let max = cmp::max(self.vec.len(), add_basen.vec.len());
        let mut new_vec: Vec<u8> = Vec::with_capacity(max);

        let mut carry: u8 = 0;

        for i in 0..max {
            match (self.vec.get(i), add_basen.vec.get(i)) {
                (Some(x), Some(y)) => {
                    let sum: u8 = *x + *y + carry;
                    carry = sum / (add_basen.base as u8);
                    new_vec.push(sum % (add_basen.base as u8));
                },
                (Some(x), None) => {
                    // no carry, but need to resize
                    let sum: u8 = *x + carry;
                    carry = sum / (add_basen.base as u8);
                    new_vec.push(sum % (add_basen.base as u8));
                },
                (_, _) => break // no ops needed

            }
        }

        let new_basen: BaseN = BaseN { base: add_basen.base, vec: new_vec };

        Ok(new_basen)
    }
}

<|endoftext|>


<commit_before>use rustc_serialize::base64::{self, ToBase64};

use crypto::{HashDigest, SecretKey, hash_message,
             sign_message, slice_to_signature};
use simples_pb::{HashedBlock, SignedBlock, Block};
use store::{ProtoStore, KeyValueStore};
use error::{SimplesError, SimplesResult};

pub trait HashedBlockExt {
    fn get_block<'a>(&'a self) -> &'a Block;
    fn compute_hash(&mut self) -> HashDigest;
    fn verify_hash(&self) -> SimplesResult<()>;
}

impl HashedBlockExt for HashedBlock {
    fn get_block<'a>(&'a self) -> &'a Block {
        self.get_signed_block().get_block()
    }

    fn compute_hash(&mut self) -> HashDigest {
        let hash_digest = hash_message(self.get_signed_block());
        self.set_hash(hash_digest.0.to_vec());
        hash_digest
    }

    fn verify_hash(&self) -> SimplesResult<()> {
        let computed_hash = hash_message(self.get_signed_block());
        let block_hash = try!(HashDigest::from_bytes(&self.get_hash()[]));
        if computed_hash == block_hash { Ok(()) }
        else { Err(SimplesError::new(&format!(
            "Block has invalid hash: {} != {} (actual)",
            block_hash, computed_hash)[]))
        }
    }
}

pub trait SignedBlockExt {
    fn sign(&mut self, secret_key: &SecretKey);
    fn verify_signature(&self) -> SimplesResult<()>;
}

impl SignedBlockExt for SignedBlock {
    fn sign(&mut self, secret_key: &SecretKey) {
        let signature = sign_message(secret_key, self.get_block());
        self.set_signature(signature.0.to_vec());
    }

    fn verify_signature(&self) -> SimplesResult<()> {
        Ok(())
    }
}

const GENESIS_FIELD: &'static str = "genesis";
const CHAIN_HEAD_FIELD: &'static str = "blockchain-head";

fn verify_block(block: &HashedBlock) -> SimplesResult<()> {
    try!(block.verify_hash());
    block.get_signed_block().verify_signature()
}

pub struct BlockStore<Store: KeyValueStore> {
    proto_store: ProtoStore<Store>,
    head_block: HashedBlock,
    genesis_block: HashedBlock
}

impl<Store: KeyValueStore> BlockStore<Store> {
    pub fn new_with_genesis(kv_store: Store, genesis: &HashedBlock)
                            -> SimplesResult<Self>
    {
        let mut proto_store = ProtoStore::new(kv_store);
        let new_genesis_hash =
            try!(HashDigest::from_bytes(genesis.get_hash()));
        let maybe_genesis_block  =
            try!(proto_store.get(GENESIS_FIELD.as_bytes()));
        if maybe_genesis_block.is_none()  {
            try!(proto_store.set(GENESIS_FIELD.as_bytes(), genesis));
            try!(proto_store.set(CHAIN_HEAD_FIELD.as_bytes(), genesis));
        } else {
            let genesis_block: HashedBlock = maybe_genesis_block.unwrap();
            let maybe_genesis_hash =
                HashDigest::from_bytes(genesis_block.get_hash());
            if maybe_genesis_hash.is_err() ||
                maybe_genesis_hash.unwrap() != new_genesis_hash {
                    try!(proto_store.set(GENESIS_FIELD.as_bytes(), genesis));
                    try!(proto_store.set(CHAIN_HEAD_FIELD.as_bytes(), genesis));
            }
        }
        Ok(BlockStore {
            proto_store: proto_store,
            head_block: genesis.clone(),
            genesis_block: genesis.clone()
        })
    }

    pub fn new_from_existing(kv_store: Store) -> SimplesResult<Self> {
        let proto_store = ProtoStore::new(kv_store);
        let maybe_genesis_block =
            try!(proto_store.get(GENESIS_FIELD.as_bytes()));
        if maybe_genesis_block.is_none() {
            return Err(SimplesError::new(&format!(
                "No genesis block in DB at key={}", GENESIS_FIELD)));
        }
        let genesis_block = maybe_genesis_block.unwrap();
        println!("Got genesis block");

        let maybe_head_block =
            try!(proto_store.get(CHAIN_HEAD_FIELD.as_bytes()));
        if maybe_head_block.is_none() {
            return Err(SimplesError::new(&format!(
                "No head block in DB at key={}", CHAIN_HEAD_FIELD)));
        }
        let head_block = maybe_head_block.unwrap();
        println!("Got head block");
        Ok(BlockStore {
            proto_store: proto_store,
            head_block: head_block,
            genesis_block: genesis_block
        })
    }

    pub fn get_head(&self) -> &HashedBlock { &self.head_block }

    pub fn get_head_hash(&self) -> HashDigest {
        let maybe_digest = HashDigest::from_bytes(self.head_block.get_hash());
        assert!(maybe_digest.is_ok(),
                "FATAL: Corrupted DB, head block has invalid hash.");
        maybe_digest.unwrap()
    }

    pub fn set_head(&mut self, new_head: HashedBlock) -> SimplesResult<()> {
        try!(verify_block(&new_head));
        try!(self.set_block(&new_head));
        try!(self.proto_store.set(CHAIN_HEAD_FIELD.as_bytes(), &new_head));
        self.head_block = new_head;
        Ok(())
    }

    pub fn get_genesis(&self) -> &HashedBlock { &self.genesis_block }

    pub fn get_genesis_hash(&self) -> HashDigest {
        let maybe_digest = HashDigest::from_bytes(
            self.genesis_block.get_hash());
        assert!(maybe_digest.is_ok(),
                "FATAL: Corrupted DB, head block has invalid hash.");
        maybe_digest.unwrap()
    }

    pub fn get_block(&self, hash: &HashDigest)
                     -> SimplesResult<Option<HashedBlock>> {
        let maybe_block = self.proto_store.get(&hash.0[]);
        match maybe_block {
            Ok(Some(ref block)) => { try!(verify_block(block)); },
            _ => ()
        };
        maybe_block
    }

    pub fn set_block(&mut self, block: &HashedBlock) -> SimplesResult<()> {
        try!(verify_block(block));
        Ok(try!(self.proto_store.set(&block.get_hash()[], block)))
    }
}

#[test]
fn test_hashed_block_ext() {
    let mut hashed_block = HashedBlock::new();
    assert!(hashed_block.verify_hash().is_err());
    hashed_block.compute_hash();
    assert!(hashed_block.verify_hash().is_ok());
    println!("Block hash: {}",
            &hashed_block.get_hash()[].to_base64(base64::STANDARD));
}

#[test]
fn test_signed_block_ext() {
}
<commit_msg>Improved naming.<commit_after>use rustc_serialize::base64::{self, ToBase64};

use crypto::{HashDigest, SecretKey, hash_message,
             sign_message, slice_to_signature};
use simples_pb::{HashedBlock, SignedBlock, Block};
use store::{ProtoStore, KeyValueStore};
use error::{SimplesError, SimplesResult};

pub trait HashedBlockExt {
    fn get_block<'a>(&'a self) -> &'a Block;
    fn compute_hash(&mut self) -> HashDigest;
    fn verify_hash(&self) -> SimplesResult<()>;
}

impl HashedBlockExt for HashedBlock {
    fn get_block<'a>(&'a self) -> &'a Block {
        self.get_signed_block().get_block()
    }

    fn compute_hash(&mut self) -> HashDigest {
        let hash_digest = hash_message(self.get_signed_block());
        self.set_hash(hash_digest.0.to_vec());
        hash_digest
    }

    fn verify_hash(&self) -> SimplesResult<()> {
        let computed_hash = hash_message(self.get_signed_block());
        let block_hash = try!(HashDigest::from_bytes(&self.get_hash()[]));
        if computed_hash == block_hash { Ok(()) }
        else { Err(SimplesError::new(&format!(
            "Block has invalid hash: {} != {} (actual)",
            block_hash, computed_hash)[]))
        }
    }
}

pub trait SignedBlockExt {
    fn sign(&mut self, secret_key: &SecretKey);
    fn verify_signature(&self) -> SimplesResult<()>;
}

impl SignedBlockExt for SignedBlock {
    fn sign(&mut self, secret_key: &SecretKey) {
        let signature = sign_message(secret_key, self.get_block());
        self.set_signature(signature.0.to_vec());
    }

    fn verify_signature(&self) -> SimplesResult<()> {
        Ok(())
    }
}

const GENESIS_FIELD: &'static str = "genesis";
const CHAIN_HEAD_FIELD: &'static str = "blockchain-head";

fn verify_block(block: &HashedBlock) -> SimplesResult<()> {
    try!(block.verify_hash());
    block.get_signed_block().verify_signature()
}

pub struct BlockStore<Store: KeyValueStore> {
    proto_store: ProtoStore<Store>,
    head_block: HashedBlock,
    genesis_block: HashedBlock
}

impl<Store: KeyValueStore> BlockStore<Store> {
    pub fn new_with_genesis(kv_store: Store, genesis: &HashedBlock)
                            -> SimplesResult<Self>
    {
        let mut proto_store = ProtoStore::new(kv_store);
        let new_genesis_hash =
            try!(HashDigest::from_bytes(genesis.get_hash()));
        let maybe_genesis_block  =
            try!(proto_store.get(GENESIS_FIELD.as_bytes()));
        if maybe_genesis_block.is_none()  {
            try!(proto_store.set(GENESIS_FIELD.as_bytes(), genesis));
            try!(proto_store.set(CHAIN_HEAD_FIELD.as_bytes(), genesis));
        } else {
            let genesis_block: HashedBlock = maybe_genesis_block.unwrap();
            let maybe_genesis_hash =
                HashDigest::from_bytes(genesis_block.get_hash());
            if maybe_genesis_hash.is_err() ||
                maybe_genesis_hash.unwrap() != new_genesis_hash {
                    try!(proto_store.set(GENESIS_FIELD.as_bytes(), genesis));
                    try!(proto_store.set(CHAIN_HEAD_FIELD.as_bytes(), genesis));
            }
        }
        Ok(BlockStore {
            proto_store: proto_store,
            head_block: genesis.clone(),
            genesis_block: genesis.clone()
        })
    }

    pub fn new_from_existing(kv_store: Store) -> SimplesResult<Self> {
        let proto_store = ProtoStore::new(kv_store);
        let maybe_genesis_block =
            try!(proto_store.get(GENESIS_FIELD.as_bytes()));
        if maybe_genesis_block.is_none() {
            return Err(SimplesError::new(&format!(
                "No genesis block in DB at key={}", GENESIS_FIELD)));
        }
        let genesis_block = maybe_genesis_block.unwrap();
        println!("Got genesis block");

        let maybe_head_block =
            try!(proto_store.get(CHAIN_HEAD_FIELD.as_bytes()));
        if maybe_head_block.is_none() {
            return Err(SimplesError::new(&format!(
                "No head block in DB at key={}", CHAIN_HEAD_FIELD)));
        }
        let head_block = maybe_head_block.unwrap();
        println!("Got head block");
        Ok(BlockStore {
            proto_store: proto_store,
            head_block: head_block,
            genesis_block: genesis_block
        })
    }

    pub fn get_head(&self) -> &HashedBlock { &self.head_block }

    pub fn get_head_hash(&self) -> HashDigest {
        let maybe_hash = HashDigest::from_bytes(self.head_block.get_hash());
        assert!(maybe_hash.is_ok(),
                "FATAL: Corrupted DB, head block has invalid hash.");
        maybe_hash.unwrap()
    }

    pub fn set_head(&mut self, new_head: HashedBlock) -> SimplesResult<()> {
        try!(verify_block(&new_head));
        try!(self.set_block(&new_head));
        try!(self.proto_store.set(CHAIN_HEAD_FIELD.as_bytes(), &new_head));
        self.head_block = new_head;
        Ok(())
    }

    pub fn get_genesis(&self) -> &HashedBlock { &self.genesis_block }

    pub fn get_genesis_hash(&self) -> HashDigest {
        let maybe_hash = HashDigest::from_bytes(self.genesis_block.get_hash());
        assert!(maybe_hash.is_ok(),
                "FATAL: Corrupted DB, genesis block has invalid hash.");
        maybe_hash.unwrap()
    }

    pub fn get_block(&self, hash: &HashDigest)
                     -> SimplesResult<Option<HashedBlock>> {
        let maybe_block = self.proto_store.get(&hash.0[]);
        match maybe_block {
            Ok(Some(ref block)) => { try!(verify_block(block)); },
            _ => ()
        };
        maybe_block
    }

    pub fn set_block(&mut self, block: &HashedBlock) -> SimplesResult<()> {
        try!(verify_block(block));
        Ok(try!(self.proto_store.set(&block.get_hash()[], block)))
    }
}

#[test]
fn test_hashed_block_ext() {
    let mut hashed_block = HashedBlock::new();
    assert!(hashed_block.verify_hash().is_err());
    hashed_block.compute_hash();
    assert!(hashed_block.verify_hash().is_ok());
    println!("Block hash: {}",
            &hashed_block.get_hash()[].to_base64(base64::STANDARD));
}

#[test]
fn test_signed_block_ext() {
}
<|endoftext|>


<commit_before>/*
 * Copyright 2015-2016 Torrie Fischer <tdfischer@hackerbots.net>
 *
 * 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 rustc_serialize::json::Json;
use rustc_serialize::json;
use matrix::json as mjson;
use matrix::model;

#[derive(Debug)]
pub enum MembershipAction {
    Join,
    Leave,
    Ban,
    Invite,
}

impl MembershipAction {
    pub fn from_str(s: &str) -> Self {
        match s {
            "join" => MembershipAction::Join,
            "leave" => MembershipAction::Leave,
            "ban" => MembershipAction::Ban,
            "invite" => MembershipAction::Invite,
            _ => panic!("unknown membership action {:?}", s)
        }
    }
}

#[derive(Debug)]
pub enum RoomEvent {
    CanonicalAlias(String),
    JoinRules(String),
    Membership(model::UserID, MembershipAction),
    HistoryVisibility(String),
    Create,
    Aliases(Vec<String>),
    Message(model::UserID, String),
    PowerLevels,
    Name(model::UserID, String),
    Avatar(model::UserID, String),
    Topic(model::UserID, String),
    Unknown(String, Json)
}

#[derive(Debug)]
pub struct TypingEvent {
    pub users: Vec<model::UserID>,
    pub room: model::RoomID,
}

#[derive(Debug)]
pub enum EventData {
    Room(model::RoomID, RoomEvent),
    Typing(TypingEvent),
    Presence(PresenceEvent),
    Unknown(String, Json),
    EndOfSync(String)
}

impl EventData {
    pub fn type_str(&self) -> String {
        match self {
            &EventData::Room(_, RoomEvent::Message(_, _)) =>
                "m.room.message".to_string(),
            &EventData::Room(_, RoomEvent::CanonicalAlias(_)) =>
                "m.room.canonical_alias".to_string(),
            &EventData::Room(_, RoomEvent::JoinRules(_)) =>
                "m.room.join_rules".to_string(),
            &EventData::Room(_, RoomEvent::Membership(_, _)) =>
                "m.room.member".to_string(),
            &EventData::Room(_, RoomEvent::HistoryVisibility(_)) =>
                "m.room.history_visibility".to_string(),
            &EventData::Room(_, RoomEvent::Create )=>
                "m.room.create".to_string(),
            &EventData::Room(_, RoomEvent::Aliases(_)) =>
                "m.room.aliases".to_string(),
            &EventData::Room(_, RoomEvent::PowerLevels) =>
                "m.room.power_levels".to_string(),
            &EventData::Room(_, RoomEvent::Name(_, _)) =>
                "m.room.name".to_string(),
            &EventData::Room(_, RoomEvent::Avatar(_, _)) =>
                "m.room.avatar".to_string(),
            &EventData::Room(_, RoomEvent::Topic(_, _)) =>
                "m.room.topic".to_string(),
            &EventData::Room(_, RoomEvent::Unknown(ref unknown_type, _)) =>
                format!("m.room.{}", unknown_type),
            &EventData::Typing(_) =>
                "m.typing".to_string(),
            &EventData::Presence(_) =>
                "m.presence".to_string(),
            &EventData::Unknown(ref unknown_type, _) => unknown_type.clone(),
            &EventData::EndOfSync(_) => panic!("EndOfSync is a special value")
        }
    }

    pub fn to_json(&self) -> json::Json {
        let mut ret = json::Object::new();
        match self {
            &EventData::Room(ref _id, ref evt) => {
                match evt {
                    &RoomEvent::Message(_, ref text) => {
                        ret.insert("msgtype".to_string(), json::Json::String("m.text".to_string()));
                        ret.insert("body".to_string(), json::Json::String(text.clone()));
                    },
                    _ => panic!("Can only serialize m.room.message events :(")
                }
            },
            _ => panic!("Can only serialize m.room.message events :(")
        }
        json::Json::Object(ret)
    }
}

#[derive(Debug)]
pub struct Event {
    pub id: Option<model::EventID>,
    pub data: EventData
}

#[derive(Debug)]
pub struct PresenceEvent {
    pub presence: String,
    pub user: model::UserID
}

impl Event {
    pub fn from_json(json: &Json) -> Self {
        let tokens: Vec<&str> = mjson::string(json, "type").split(".").collect();
        let id = match json.as_object().unwrap().get("event_id") {
            Some(i) => Some(model::EventID::from_str(i.as_string().unwrap())),
            None => None
        };
        if tokens[0] != "m" {
            Event {
                id: id,
                data: EventData::Unknown(json.as_object().unwrap().get("type").unwrap().as_string().unwrap().to_string(), json.clone()),
            }
        } else {
            Event {
                id: id,
                data: match tokens[1] {
                    "room" =>
                        Self::from_room_json(tokens[2], json),
                    "typing" =>
                        EventData::Typing(TypingEvent {
                            users: vec![],
                            room: model::RoomID::from_str(mjson::string(json, "room_id"))
                        }),
                    "presence" =>
                        EventData::Presence(PresenceEvent{
                            presence: mjson::string(json, "content.presence").to_string(),
                            user: model::UserID::from_str(mjson::string(json, "sender"))
                        }),
                    e =>
                        EventData::Unknown(e.to_string(), json.clone())
                }
            }
        }
    }

    fn from_room_json(event_type: &str, json: &Json) -> EventData {
        EventData::Room(
            model::RoomID::from_str(mjson::string(json, "room_id")),
            match event_type {
                "canonical_alias" =>
                    RoomEvent::CanonicalAlias(mjson::string(json, "content.alias").to_string()),
                "join_rules" => {
                        if json.find_path(&["content", "join_rules"]) == None {
                            RoomEvent::JoinRules(mjson::string(json, "content.join_rule").to_string())
                        } else {
                            RoomEvent::JoinRules(mjson::string(json, "content.join_rules").to_string())
                        }
                    },
                "member" =>
                    RoomEvent::Membership(model::UserID::from_str(mjson::string(json, "sender")), MembershipAction::from_str(mjson::string(json, "content.membership"))),
                "history_visibility" =>
                    RoomEvent::HistoryVisibility(mjson::string(json, "content.history_visibility").to_string()),
                "create" =>
                    RoomEvent::Create,
                "aliases" => {
                    let aliases = mjson::array(json, "content.aliases");
                    let mut alias_list: Vec<String> = vec![];
                    for alias in aliases {
                        alias_list.push(alias.as_string().unwrap().to_string());
                    }
                    RoomEvent::Aliases(alias_list)
                },
                "power_levels" =>
                    RoomEvent::PowerLevels,
                "message" =>
                    RoomEvent::Message(model::UserID::from_str(mjson::string(json, "sender")), mjson::string(json, "content.body").to_string()),
                "name" =>
                    RoomEvent::Name(model::UserID::from_str(mjson::string(json, "sender")), mjson::string(json, "content.name").to_string()),
                "topic" =>
                    RoomEvent::Topic(model::UserID::from_str(mjson::string(json, "sender")), mjson::string(json, "content.topic").to_string()),
                "avatar" =>
                    RoomEvent::Avatar(model::UserID::from_str(mjson::string(json, "sender")), mjson::string(json, "content.url").to_string()),
                unknown_type => RoomEvent::Unknown(unknown_type.to_string(), json.clone())
            }
        )
    }
}
<commit_msg>if content is blank, return an unknown event rather than panicing on trying to find missing content fields.  fixes https://github.com/tdfischer/pto/issues/48<commit_after>/*
 * Copyright 2015-2016 Torrie Fischer <tdfischer@hackerbots.net>
 *
 * 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 rustc_serialize::json::Json;
use rustc_serialize::json;
use matrix::json as mjson;
use matrix::model;

#[derive(Debug)]
pub enum MembershipAction {
    Join,
    Leave,
    Ban,
    Invite,
}

impl MembershipAction {
    pub fn from_str(s: &str) -> Self {
        match s {
            "join" => MembershipAction::Join,
            "leave" => MembershipAction::Leave,
            "ban" => MembershipAction::Ban,
            "invite" => MembershipAction::Invite,
            _ => panic!("unknown membership action {:?}", s)
        }
    }
}

#[derive(Debug)]
pub enum RoomEvent {
    CanonicalAlias(String),
    JoinRules(String),
    Membership(model::UserID, MembershipAction),
    HistoryVisibility(String),
    Create,
    Aliases(Vec<String>),
    Message(model::UserID, String),
    PowerLevels,
    Name(model::UserID, String),
    Avatar(model::UserID, String),
    Topic(model::UserID, String),
    Unknown(String, Json)
}

#[derive(Debug)]
pub struct TypingEvent {
    pub users: Vec<model::UserID>,
    pub room: model::RoomID,
}

#[derive(Debug)]
pub enum EventData {
    Room(model::RoomID, RoomEvent),
    Typing(TypingEvent),
    Presence(PresenceEvent),
    Unknown(String, Json),
    EndOfSync(String)
}

impl EventData {
    pub fn type_str(&self) -> String {
        match self {
            &EventData::Room(_, RoomEvent::Message(_, _)) =>
                "m.room.message".to_string(),
            &EventData::Room(_, RoomEvent::CanonicalAlias(_)) =>
                "m.room.canonical_alias".to_string(),
            &EventData::Room(_, RoomEvent::JoinRules(_)) =>
                "m.room.join_rules".to_string(),
            &EventData::Room(_, RoomEvent::Membership(_, _)) =>
                "m.room.member".to_string(),
            &EventData::Room(_, RoomEvent::HistoryVisibility(_)) =>
                "m.room.history_visibility".to_string(),
            &EventData::Room(_, RoomEvent::Create )=>
                "m.room.create".to_string(),
            &EventData::Room(_, RoomEvent::Aliases(_)) =>
                "m.room.aliases".to_string(),
            &EventData::Room(_, RoomEvent::PowerLevels) =>
                "m.room.power_levels".to_string(),
            &EventData::Room(_, RoomEvent::Name(_, _)) =>
                "m.room.name".to_string(),
            &EventData::Room(_, RoomEvent::Avatar(_, _)) =>
                "m.room.avatar".to_string(),
            &EventData::Room(_, RoomEvent::Topic(_, _)) =>
                "m.room.topic".to_string(),
            &EventData::Room(_, RoomEvent::Unknown(ref unknown_type, _)) =>
                format!("m.room.{}", unknown_type),
            &EventData::Typing(_) =>
                "m.typing".to_string(),
            &EventData::Presence(_) =>
                "m.presence".to_string(),
            &EventData::Unknown(ref unknown_type, _) => unknown_type.clone(),
            &EventData::EndOfSync(_) => panic!("EndOfSync is a special value")
        }
    }

    pub fn to_json(&self) -> json::Json {
        let mut ret = json::Object::new();
        match self {
            &EventData::Room(ref _id, ref evt) => {
                match evt {
                    &RoomEvent::Message(_, ref text) => {
                        ret.insert("msgtype".to_string(), json::Json::String("m.text".to_string()));
                        ret.insert("body".to_string(), json::Json::String(text.clone()));
                    },
                    _ => panic!("Can only serialize m.room.message events :(")
                }
            },
            _ => panic!("Can only serialize m.room.message events :(")
        }
        json::Json::Object(ret)
    }
}

#[derive(Debug)]
pub struct Event {
    pub id: Option<model::EventID>,
    pub data: EventData
}

#[derive(Debug)]
pub struct PresenceEvent {
    pub presence: String,
    pub user: model::UserID
}

impl Event {
    pub fn from_json(json: &Json) -> Self {
        let tokens: Vec<&str> = mjson::string(json, "type").split(".").collect();
        let id = match json.as_object().unwrap().get("event_id") {
            Some(i) => Some(model::EventID::from_str(i.as_string().unwrap())),
            None => None
        };
        if tokens[0] != "m" {
            Event {
                id: id,
                data: EventData::Unknown(json.as_object().unwrap().get("type").unwrap().as_string().unwrap().to_string(), json.clone()),
            }
        } else {
            Event {
                id: id,
                data: match tokens[1] {
                    "room" =>
                        Self::from_room_json(tokens[2], json),
                    "typing" =>
                        EventData::Typing(TypingEvent {
                            users: vec![],
                            room: model::RoomID::from_str(mjson::string(json, "room_id"))
                        }),
                    "presence" =>
                        EventData::Presence(PresenceEvent{
                            presence: mjson::string(json, "content.presence").to_string(),
                            user: model::UserID::from_str(mjson::string(json, "sender"))
                        }),
                    e =>
                        EventData::Unknown(e.to_string(), json.clone())
                }
            }
        }
    }

    fn from_room_json(event_type: &str, json: &Json) -> EventData {

        if mjson::path(json, "content").as_object().unwrap().len() == 0 {
            // probably a redaction.
            return EventData::Room(
                model::RoomID::from_str(mjson::string(json, "room_id")),
                RoomEvent::Unknown(event_type.to_string(), json.clone())
            )
        }

        EventData::Room(
            model::RoomID::from_str(mjson::string(json, "room_id")),
            match event_type {
                "canonical_alias" =>
                    RoomEvent::CanonicalAlias(mjson::string(json, "content.alias").to_string()),
                "join_rules" => {
                        if json.find_path(&["content", "join_rules"]) == None {
                            RoomEvent::JoinRules(mjson::string(json, "content.join_rule").to_string())
                        } else {
                            RoomEvent::JoinRules(mjson::string(json, "content.join_rules").to_string())
                        }
                    },
                "member" =>
                    RoomEvent::Membership(model::UserID::from_str(mjson::string(json, "sender")), MembershipAction::from_str(mjson::string(json, "content.membership"))),
                "history_visibility" =>
                    RoomEvent::HistoryVisibility(mjson::string(json, "content.history_visibility").to_string()),
                "create" =>
                    RoomEvent::Create,
                "aliases" => {
                    let aliases = mjson::array(json, "content.aliases");
                    let mut alias_list: Vec<String> = vec![];
                    for alias in aliases {
                        alias_list.push(alias.as_string().unwrap().to_string());
                    }
                    RoomEvent::Aliases(alias_list)
                },
                "power_levels" =>
                    RoomEvent::PowerLevels,
                "message" =>
                    RoomEvent::Message(model::UserID::from_str(mjson::string(json, "sender")), mjson::string(json, "content.body").to_string()),
                "name" =>
                    RoomEvent::Name(model::UserID::from_str(mjson::string(json, "sender")), mjson::string(json, "content.name").to_string()),
                "topic" =>
                    RoomEvent::Topic(model::UserID::from_str(mjson::string(json, "sender")), mjson::string(json, "content.topic").to_string()),
                "avatar" =>
                    RoomEvent::Avatar(model::UserID::from_str(mjson::string(json, "sender")), mjson::string(json, "content.url").to_string()),
                unknown_type => RoomEvent::Unknown(unknown_type.to_string(), json.clone())
            }
        )
    }
}
<|endoftext|>


<commit_before>//! Types for counting and recording time in a simulation.
//!
//! `clock` is the primary module for time tracking in `game_time`. It
//! provides two primary types: `GameClock`, a "clock" for tracking frames
//! and time progression within the simulation and `GameTime`, a specific
//! point in time within the simulation.
use std::thread;
use std::time;

use chrono;
use float_duration::{FloatDuration, TimePoint};
use step::TimeStep;

use framerate::FrameCount;

/// A specific point of time in a simulation.
///
/// `GameTime` knows both the wall time and game time of the simulation at a
/// fixed time. A `GameTime` object is usually created by calling
/// [`tick`](./struct.GameClock.html#method.tick) on a [`GameClock`](./struct.GameClock.html)
/// object.
#[derive(Debug, Clone)]
pub struct GameTime {
    frame_wall_time: chrono::DateTime<chrono::Local>,
    frame_game_time: time::Duration,
    elapsed_game_time: FloatDuration,
    elapsed_wall_time: FloatDuration,
    frame_number: u64,
}

/// Time-tracking for use in real-time simulations.
///
/// `GameClock` provides time tracking for simulations. It
/// tracks total time the simulation has run for as well as
/// the elapsed time between individual frames.
///
/// In addition to tracking wall time, it tracks "game time"
/// which is the time used by the simulation itself. This game time is updated
/// each frame and
/// can be coupled directly to wall time [`VariableStep`](../step/struct.VariableStep.html)
/// or can be updated by a fixed amount (see the [`step`](../step/index.html) module for more
/// options).
///
/// `GameClock` uses [`GameTime`](./struct.GameTime.html) objects
/// to report the time at each frame to the program. The [`tick`](./fn.tick.html)
/// tells `GameClock` when a new frame is started, and returns
/// the `GameTime` object for that frame. This object can then be passed
/// to the rest of the simulation independently of `GameClock`.
#[derive(Debug, Clone)]
pub struct GameClock {
    last_frame_time: GameTime,
    start_wall_time: chrono::DateTime<chrono::Local>,
    total_game_time: time::Duration,
    current_frame: u64,
    clock_multiplier: f64,
}

impl GameClock {
    /// Construct a new `GameClock` object, initialized to start at
    /// zero game time and a wall time of `chrono::Local::now()`.
    pub fn new() -> GameClock {
        let now = chrono::Local::now();
        let start_game_time = GameTime {
            frame_wall_time: now,
            frame_game_time: time::Duration::new(0, 0),
            elapsed_game_time: FloatDuration::zero(),
            elapsed_wall_time: FloatDuration::zero(),
            frame_number: 0,
        };

        GameClock {
            last_frame_time: start_game_time,
            start_wall_time: now,
            total_game_time: time::Duration::new(0, 0),
            current_frame: 0,
            clock_multiplier: 1.0,
        }
    }

    /// Return the current frame number.
    ///
    /// The frame number starts at `0` for "before the first frame"
    /// and increases by 1 every time `tick` is called.
    pub fn current_frame_number(&self) -> u64 {
        self.current_frame
    }
    /// Return the wall time when the `GameClock` was created.
    pub fn start_wall_time(&self) -> chrono::DateTime<chrono::Local> {
        self.start_wall_time
    }
    /// Return the wall time at the start of the current frame.
    ///
    /// This is equivalent to the value returned by
    /// `last_frame_time().frame_wall_time()`
    pub fn frame_wall_time(&self) -> chrono::DateTime<chrono::Local> {
        self.last_frame_time.frame_wall_time
    }

    /// Return the amount of wall time elapsed since the start of the current frame.
    pub fn frame_elapsed_time(&self) -> FloatDuration {
        chrono::Local::now()
            .float_duration_since(self.frame_wall_time())
            .unwrap()
    }
    /// Return the [`GameTime`](./struct.GameTime.html) for the current frame.
    pub fn last_frame_time(&self) -> &GameTime {
        &self.last_frame_time
    }
    /// Return the rate at which game time is increasing.
    pub fn clock_multiplier(&self) -> f64 {
        self.clock_multiplier
    }
    /// Set the rate at which game time is increasing.
    pub fn set_clock_multiplier(&mut self, val: f64) -> &mut GameClock {
        self.clock_multiplier = val;
        self
    }

    /// Mark the start of a new frame, updating time statistics.
    ///
    /// The `GameTime` for the new frame is returned. This gives the time
    /// statistics for the entirety of the current frame. It is cached and
    /// can be later obtained by calling `last_frame_time`.
    ///
    /// `time_progress` is a [`TimeStep`](../step/trait.TimeStep.html) reference used to
    /// compute the elapsed game time for the frame..
    pub fn tick<T>(&mut self, time_progress: &mut T) -> GameTime
    where
        T: TimeStep + ?Sized,
    {
        let frame_start = chrono::Local::now();

        self.current_frame += 1;

        let elapsed_wall_time = frame_start
            .float_duration_since(self.frame_wall_time())
            .unwrap();

        let elapsed_game_time = time_progress.time_step(&elapsed_wall_time) * self.clock_multiplier;
        let total_game_time = self.total_game_time + elapsed_game_time.to_std().unwrap();

        self.total_game_time = total_game_time;

        let time = GameTime {
            frame_wall_time: frame_start,
            frame_game_time: total_game_time,
            elapsed_game_time,
            elapsed_wall_time,
            frame_number: self.current_frame,
        };

        self.last_frame_time = time.clone();

        time
    }

    /// Put the current thread to sleep if necessary in order to maintain the target frame rate.
    ///
    /// If the current frame has taken more time than the target frame rate allows, then the
    /// thread will not sleep. Otherwise it will sleep for
    /// `counter.target_time_per_frame() - self.frame_elapsed_time()`
    ///
    /// This method relies on the passed function `f` to actually perform the sleep.
    /// `f` receives the amount of sleep time requested and it is up to itself to
    /// sleep for that amount of time. If you don't care how the sleep is performed,
    /// use the [`sleep_remaining`](./struct.GameClock.html#method.sleep_remaining)
    /// method instead.
    pub fn sleep_remaining_via<C, F>(&mut self, counter: &C, f: F)
    where
        C: FrameCount + ?Sized,
        F: FnOnce(FloatDuration),
    {
        let remaining_time = counter.target_time_per_frame() -
            self.last_frame_time.elapsed_time_since_frame_start();
        if !remaining_time.is_negative() {
            f(remaining_time)
        }
    }

    /// Put the current thread to sleep if necessary in order to maintain the target frame rate.
    ///
    /// If the current frame has taken more time than the target frame rate allows, then the
    /// thread will not sleep. Otherwise it will sleep for
    /// `counter.target_time_per_frame() - self.frame_elapsed_time()`
    ///
    /// This method uses [`std::thread::sleep`](https://doc.rust-lang.org/std/thread/fn.sleep.html)
    /// to put the thread to sleep. If a different sleep function is desired, use
    /// the [`sleep_remaining_via`](./struct.GameClock.html#method.sleep_remaining_via)
    /// method instead.
    pub fn sleep_remaining<C>(&mut self, counter: &C)
    where
        C: FrameCount + ?Sized,
    {
        self.sleep_remaining_via(counter, |rem| thread::sleep(rem.to_std().unwrap()))
    }
}

impl Default for GameClock {
    fn default() -> GameClock {
        GameClock::new()
    }
}

impl GameTime {
    /// Construct a `GameTime` object directly.
    ///
    /// This is useful primarily for writing tests or for constructing a
    /// `GameTime` without using a `GameClock`.
    pub fn new(
        frame_wall_time: chrono::DateTime<chrono::Local>,
        frame_game_time: time::Duration,
        elapsed_game_time: FloatDuration,
        elapsed_wall_time: FloatDuration,
        frame_number: u64,
    ) -> GameTime {
        GameTime {
            frame_wall_time,
            frame_game_time,
            elapsed_game_time,
            elapsed_wall_time,
            frame_number,
        }
    }

    /// The game time at the time of creation of this `GameTime` object.
    pub fn frame_game_time(&self) -> time::Duration {
        self.frame_game_time
    }
    /// The wall time at the time of creation of this `GameTime` object.
    pub fn frame_wall_time(&self) -> chrono::DateTime<chrono::Local> {
        self.frame_wall_time
    }
    /// The amount of game time that passed since the previous frame.
    pub fn elapsed_game_time(&self) -> FloatDuration {
        self.elapsed_game_time
    }
    /// The amount of wall time that passed since the previous frame.
    pub fn elapsed_wall_time(&self) -> FloatDuration {
        self.elapsed_wall_time
    }
    /// The amount of elapsed wall time since the start of the current frame.
    ///
    /// This value is computed from the current instant when called, based
    /// on the frame start time. This can be used for intra-frame profiling.
    pub fn elapsed_time_since_frame_start(&self) -> FloatDuration {
        chrono::Local::now()
            .float_duration_since(self.frame_wall_time)
            .unwrap()
    }
    /// The index of the current frame.
    ///
    /// This value increases by 1 for each frame created, and represents the total
    /// number of frames executed in the simulation.
    pub fn frame_number(&self) -> u64 {
        self.frame_number
    }
    /// Return the instantaneous frame rate between the last and current frames.
    ///
    /// The "instantaneous" frame rate is computed from the last frame's elapsed
    /// time, and takes no previous frames into account.
    ///
    /// For a more stable frame rate, use a [`FrameCount`](../framerate/counter/trait.FrameCount.html)
    /// object.
    pub fn instantaneous_frame_rate(&self) -> f64 {
        1.0 / self.elapsed_game_time.as_seconds()
    }
}
<commit_msg>Added `GameClockBuilder`<commit_after>//! Types for counting and recording time in a simulation.
//!
//! `clock` is the primary module for time tracking in `game_time`. It
//! provides two primary types: `GameClock`, a "clock" for tracking frames
//! and time progression within the simulation and `GameTime`, a specific
//! point in time within the simulation.
use std::thread;
use std::time;

use chrono;
use float_duration::{FloatDuration, TimePoint};
use step::TimeStep;

use framerate::FrameCount;

/// A specific point of time in a simulation.
///
/// `GameTime` knows both the wall time and game time of the simulation at a
/// fixed time. A `GameTime` object is usually created by calling
/// [`tick`](./struct.GameClock.html#method.tick) on a [`GameClock`](./struct.GameClock.html)
/// object.
#[derive(Debug, Clone)]
pub struct GameTime {
    frame_wall_time: chrono::DateTime<chrono::Local>,
    frame_game_time: time::Duration,
    elapsed_game_time: FloatDuration,
    elapsed_wall_time: FloatDuration,
    frame_number: u64,
}

/// Time-tracking for use in real-time simulations.
///
/// `GameClock` provides time tracking for simulations. It
/// tracks total time the simulation has run for as well as
/// the elapsed time between individual frames.
///
/// In addition to tracking wall time, it tracks "game time"
/// which is the time used by the simulation itself. This game time is updated
/// each frame and
/// can be coupled directly to wall time [`VariableStep`](../step/struct.VariableStep.html)
/// or can be updated by a fixed amount (see the [`step`](../step/index.html) module for more
/// options).
///
/// `GameClock` uses [`GameTime`](./struct.GameTime.html) objects
/// to report the time at each frame to the program. The [`tick`](./fn.tick.html)
/// tells `GameClock` when a new frame is started, and returns
/// the `GameTime` object for that frame. This object can then be passed
/// to the rest of the simulation independently of `GameClock`.
#[derive(Debug, Clone)]
pub struct GameClock {
    last_frame_time: GameTime,
    start_wall_time: chrono::DateTime<chrono::Local>,
    total_game_time: time::Duration,
    current_frame: u64,
    clock_multiplier: f64,
}

/// A [`GameClock`](./struct.GameClock.html) builder,
/// allowing for customization of the initial time and parameters.
///
/// `GameClockBuilder` offers fine control over the initial state of a `GameClock`. For
/// most cases, using [`GameClock::new()`](./struct.GameClock.html#method.new) is good enough.
/// However, it can be useful to have more control in some situations, especially testing.
#[derive(Debug, Clone)]
pub struct GameClockBuilder {
    start_game_time: time::Duration,
    start_wall_time: chrono::DateTime<chrono::Local>,
    start_frame: u64,
    clock_multiplier: f64,
}

impl GameClock {
    /// Construct a new `GameClock` object, initialized to start at
    /// zero game time and a wall time of `chrono::Local::now()`.
    pub fn new() -> GameClock {
        let now = chrono::Local::now();
        let start_game_time = GameTime {
            frame_wall_time: now,
            frame_game_time: time::Duration::new(0, 0),
            elapsed_game_time: FloatDuration::zero(),
            elapsed_wall_time: FloatDuration::zero(),
            frame_number: 0,
        };

        GameClock {
            last_frame_time: start_game_time,
            start_wall_time: now,
            total_game_time: time::Duration::new(0, 0),
            current_frame: 0,
            clock_multiplier: 1.0,
        }
    }

    /// Return the current frame number.
    ///
    /// The frame number starts at `0` for "before the first frame"
    /// and increases by 1 every time `tick` is called.
    pub fn current_frame_number(&self) -> u64 {
        self.current_frame
    }
    /// Return the wall time when the `GameClock` was created.
    pub fn start_wall_time(&self) -> chrono::DateTime<chrono::Local> {
        self.start_wall_time
    }
    /// Return the wall time at the start of the current frame.
    ///
    /// This is equivalent to the value returned by
    /// `last_frame_time().frame_wall_time()`
    pub fn frame_wall_time(&self) -> chrono::DateTime<chrono::Local> {
        self.last_frame_time.frame_wall_time
    }

    /// Return the amount of wall time elapsed since the start of the current frame.
    pub fn frame_elapsed_time(&self) -> FloatDuration {
        chrono::Local::now()
            .float_duration_since(self.frame_wall_time())
            .unwrap()
    }
    /// Return the [`GameTime`](./struct.GameTime.html) for the current frame.
    pub fn last_frame_time(&self) -> &GameTime {
        &self.last_frame_time
    }
    /// Return the rate at which game time is increasing.
    pub fn clock_multiplier(&self) -> f64 {
        self.clock_multiplier
    }
    /// Set the rate at which game time is increasing.
    pub fn set_clock_multiplier(&mut self, val: f64) -> &mut GameClock {
        self.clock_multiplier = val;
        self
    }

    /// Mark the start of a new frame, updating time statistics.
    ///
    /// The `GameTime` for the new frame is returned. This gives the time
    /// statistics for the entirety of the current frame. It is cached and
    /// can be later obtained by calling `last_frame_time`.
    ///
    /// `time_progress` is a [`TimeStep`](../step/trait.TimeStep.html) reference used to
    /// compute the elapsed game time for the frame..
    pub fn tick<T>(&mut self, time_progress: &mut T) -> GameTime
    where
        T: TimeStep + ?Sized,
    {
        let frame_start = chrono::Local::now();

        self.current_frame += 1;

        let elapsed_wall_time = frame_start
            .float_duration_since(self.frame_wall_time())
            .unwrap();

        let elapsed_game_time = time_progress.time_step(&elapsed_wall_time) * self.clock_multiplier;
        let total_game_time = self.total_game_time + elapsed_game_time.to_std().unwrap();

        self.total_game_time = total_game_time;

        let time = GameTime {
            frame_wall_time: frame_start,
            frame_game_time: total_game_time,
            elapsed_game_time,
            elapsed_wall_time,
            frame_number: self.current_frame,
        };

        self.last_frame_time = time.clone();

        time
    }

    /// Put the current thread to sleep if necessary in order to maintain the target frame rate.
    ///
    /// If the current frame has taken more time than the target frame rate allows, then the
    /// thread will not sleep. Otherwise it will sleep for
    /// `counter.target_time_per_frame() - self.frame_elapsed_time()`
    ///
    /// This method relies on the passed function `f` to actually perform the sleep.
    /// `f` receives the amount of sleep time requested and it is up to itself to
    /// sleep for that amount of time. If you don't care how the sleep is performed,
    /// use the [`sleep_remaining`](./struct.GameClock.html#method.sleep_remaining)
    /// method instead.
    pub fn sleep_remaining_via<C, F>(&mut self, counter: &C, f: F)
    where
        C: FrameCount + ?Sized,
        F: FnOnce(FloatDuration),
    {
        let remaining_time = counter.target_time_per_frame() -
            self.last_frame_time.elapsed_time_since_frame_start();
        if !remaining_time.is_negative() {
            f(remaining_time)
        }
    }

    /// Put the current thread to sleep if necessary in order to maintain the target frame rate.
    ///
    /// If the current frame has taken more time than the target frame rate allows, then the
    /// thread will not sleep. Otherwise it will sleep for
    /// `counter.target_time_per_frame() - self.frame_elapsed_time()`
    ///
    /// This method uses [`std::thread::sleep`](https://doc.rust-lang.org/std/thread/fn.sleep.html)
    /// to put the thread to sleep. If a different sleep function is desired, use
    /// the [`sleep_remaining_via`](./struct.GameClock.html#method.sleep_remaining_via)
    /// method instead.
    pub fn sleep_remaining<C>(&mut self, counter: &C)
    where
        C: FrameCount + ?Sized,
    {
        self.sleep_remaining_via(counter, |rem| thread::sleep(rem.to_std().unwrap()))
    }
}

impl Default for GameClock {
    fn default() -> GameClock {
        GameClock::new()
    }
}

impl GameTime {
    /// Construct a `GameTime` object directly.
    ///
    /// This is useful primarily for writing tests or for constructing a
    /// `GameTime` without using a `GameClock`.
    pub fn new(
        frame_wall_time: chrono::DateTime<chrono::Local>,
        frame_game_time: time::Duration,
        elapsed_game_time: FloatDuration,
        elapsed_wall_time: FloatDuration,
        frame_number: u64,
    ) -> GameTime {
        GameTime {
            frame_wall_time,
            frame_game_time,
            elapsed_game_time,
            elapsed_wall_time,
            frame_number,
        }
    }

    /// The game time at the time of creation of this `GameTime` object.
    pub fn frame_game_time(&self) -> time::Duration {
        self.frame_game_time
    }
    /// The wall time at the time of creation of this `GameTime` object.
    pub fn frame_wall_time(&self) -> chrono::DateTime<chrono::Local> {
        self.frame_wall_time
    }
    /// The amount of game time that passed since the previous frame.
    pub fn elapsed_game_time(&self) -> FloatDuration {
        self.elapsed_game_time
    }
    /// The amount of wall time that passed since the previous frame.
    pub fn elapsed_wall_time(&self) -> FloatDuration {
        self.elapsed_wall_time
    }
    /// The amount of elapsed wall time since the start of the current frame.
    ///
    /// This value is computed from the current instant when called, based
    /// on the frame start time. This can be used for intra-frame profiling.
    pub fn elapsed_time_since_frame_start(&self) -> FloatDuration {
        chrono::Local::now()
            .float_duration_since(self.frame_wall_time)
            .unwrap()
    }
    /// The index of the current frame.
    ///
    /// This value increases by 1 for each frame created, and represents the total
    /// number of frames executed in the simulation.
    pub fn frame_number(&self) -> u64 {
        self.frame_number
    }
    /// Return the instantaneous frame rate between the last and current frames.
    ///
    /// The "instantaneous" frame rate is computed from the last frame's elapsed
    /// time, and takes no previous frames into account.
    ///
    /// For a more stable frame rate, use a
    /// [`FrameCount`](../framerate/counter/trait.FrameCount.html) object.
    pub fn instantaneous_frame_rate(&self) -> f64 {
        1.0 / self.elapsed_game_time.as_seconds()
    }
}

impl GameClockBuilder {
    /// Construct a new `GameClockBuilder` with default values.
    ///
    /// Calling `build` on the returned object returns immediately gives the same
    /// result as `GameClock::new()`.
    pub fn new() -> GameClockBuilder {
        GameClockBuilder {
            start_game_time: time::Duration::new(0, 0),
            start_wall_time: chrono::Local::now(),
            start_frame: 0,
            clock_multiplier: 1.0,
        }
    }

    /// Set the initial game time when the game is started.
    ///
    /// Defaults to zero.
    pub fn start_game_time(&mut self, time: time::Duration) -> &mut GameClockBuilder {
        self.start_game_time = time;
        self
    }
    /// Set the initial wall time when the game is started.
    ///
    /// Defaults to `chrono::Local::now()`.
    pub fn start_wall_time(
        &mut self,
        time: chrono::DateTime<chrono::Local>,
    ) -> &mut GameClockBuilder {
        self.start_wall_time = time;
        self
    }
    /// Set the initial frame number.
    ///
    /// Defaults to `0`.
    pub fn start_frame(&mut self, frame_num: u64) -> &mut GameClockBuilder {
        self.start_frame = frame_num;
        self
    }
    /// Set the initial clock multiplier.
    ///
    /// Defaults to `1.0`.
    pub fn clock_multiplier(&mut self, multiplier: f64) -> &mut GameClockBuilder {
        self.clock_multiplier = multiplier;
        self
    }
    /// Construct a `GameClock` object with the set parameters.
    pub fn build(&self) -> GameClock {
        let start_game_time = GameTime {
            frame_wall_time: self.start_wall_time,
            frame_game_time: self.start_game_time,
            elapsed_game_time: FloatDuration::zero(),
            elapsed_wall_time: FloatDuration::zero(),
            frame_number: self.start_frame,
        };

        GameClock {
            last_frame_time: start_game_time,
            start_wall_time: self.start_wall_time,
            total_game_time: time::Duration::new(0, 0),
            current_frame: self.start_frame,
            clock_multiplier: self.clock_multiplier,
        }
    }
}

impl Default for GameClockBuilder {
    fn default() -> GameClockBuilder {
        GameClockBuilder::new()
    }
}
<|endoftext|>