<commit_before>extern crate osmpbfreader;
extern crate time;

use time::PreciseTime;
use std::fs::File;
use std::path::Path;
use std::ffi::OsString;
use std::collections::HashMap;
use std::collections::HashSet;

use osmpbfreader::OsmObj;
use osmpbfreader::OsmPbfReader;

#[derive(Debug, Clone, Copy)]
struct Position {
    lat: f64,
    lon: f64,
}

#[derive(Debug, Clone, Copy)]
struct ParsedEdge {
    id_from: i64,
    id_to: i64,
    length: f64,
}

struct ParseData {
    // used node-ids
    nodes_used: HashSet<i64>,
    // "useful" ways
    filtered_ways: HashSet<i64>,
    // relevant nodes and their position
    nodes: HashMap<i64, Position>,
    // edges
    edges: Vec<ParsedEdge>
}

struct RoutingEdge {
    target: usize,
    length: f64,
    constraints: u8,
}

struct OsmNode {
    position: Position,
    internal_id: usize
}

struct RoutingData {
    // relevant nodes and their position
    osm_nodes: HashMap<i64, OsmNode>,
    //[n_id] -> osm_n_id
    internal_nodes: Vec<i64>,
    // [e_id] -> n_id target|length|constraints
    internal_edges: Vec<RoutingEdge>,
    // [n_id] -> e_id
    internal_offset: Vec<usize>,
}

fn main() {
    let default_file = OsString::from("/home/zsdn/baden-wuerttemberg-latest.osm.pbf".to_string());
    //let default_file = OsString::from("/home/zsdn/germany-latest.osm.pbf".to_string());
    let args: Vec<OsString> = std::env::args_os().collect();
    match args.len() {
        1 => {
            read_file(&default_file);
        }
        2 => {
            read_file(&args[1]);
        }
        _ => {},
    };
}

fn read_file(filename: &OsString) -> RoutingData {
    let mut parse_result = ParseData { nodes_used: HashSet::new(), filtered_ways: HashSet::new(), nodes: HashMap::new(), edges: Vec::new() };

    let start_p1 = PreciseTime::now();
    first_parse(&filename, &mut parse_result);
    let end_p1 = PreciseTime::now();

    println!("P1 | ways:  {}", parse_result.filtered_ways.len());
    println!("P1 | nodes_used: {}", parse_result.nodes_used.len());
    println!("P1 | edges: {}", parse_result.edges.len());
    println!("P1 | nodes: {}", parse_result.nodes.len());
    println!("P1 | duration: {}", start_p1.to(end_p1));

    let start_p2 = PreciseTime::now();
    second_parse(&filename, &mut parse_result);
    let end_p2 = PreciseTime::now();

    println!("P2 | ways:  {}", parse_result.filtered_ways.len());
    println!("P2 | nodes_used: {}", parse_result.nodes_used.len());
    println!("P2 | edges: {}", parse_result.edges.len());
    println!("P2 | nodes: {}", parse_result.nodes.len());
    println!("P2 | duration: {}", start_p2.to(end_p2));

    let start_p3 = PreciseTime::now();
    third_parse(&filename, &mut parse_result);
    let end_p3 = PreciseTime::now();

    println!("P3 | ways:  {}", parse_result.filtered_ways.len());
    println!("P3 | nodes_used: {}", parse_result.nodes_used.len());
    println!("P3 | edges: {}", parse_result.edges.len());
    println!("P3 | nodes: {}", parse_result.nodes.len());
    println!("P3 | duration: {}", start_p3.to(end_p3));

    let start_b = PreciseTime::now();
    let routing_data = build_routing_data(&mut parse_result);
    let end_b = PreciseTime::now();

    println!("B  | edges:  {}", routing_data.internal_edges.len());
    println!("B  | nodes:  {}", routing_data.internal_nodes.len());
    println!("B  | offset:  {}", routing_data.internal_offset.len());
    println!("B  | osm_nodes:  {}", routing_data.osm_nodes.len());
    println!("B  | duration: {}", start_b.to(end_b));

    return routing_data;
}

fn first_parse(filename: &OsString, parse_result: &mut ParseData) {
    let pbf_file = File::open(&Path::new(filename)).unwrap();

    let mut invalid_values = HashSet::new();
    init_filter_list(&mut invalid_values);

    let mut pbf = OsmPbfReader::new(pbf_file);

    for obj in pbf.iter() {
        match obj {
            OsmObj::Way(way) => {
                if filter_way(&way, &invalid_values) {
                    for node in way.nodes {
                        parse_result.nodes_used.insert(node);
                    }
                    parse_result.filtered_ways.insert(way.id);
                }
            }
            _ => {}
        }
    }
}

fn second_parse(filename: &OsString, parse_result: &mut ParseData) {
    let pbf_file = File::open(&Path::new(filename)).unwrap();
    let mut pbf = OsmPbfReader::new(pbf_file);

    for obj in pbf.iter() {
        match obj {
            OsmObj::Node(node) => {
                if parse_result.nodes_used.remove(&node.id) {
                    parse_result.nodes.insert(node.id, Position { lat: node.lat, lon: node.lon });
                }
            }
            _ => {}
        }
    }
}

fn third_parse(filename: &OsString, parse_result: &mut ParseData) {
    let pbf_file = File::open(&Path::new(filename)).unwrap();
    let mut pbf = OsmPbfReader::new(pbf_file);

    for obj in pbf.iter() {
        match obj {
            OsmObj::Way(way) => {
                if parse_result.filtered_ways.remove(&way.id) {
                    for node_pair in way.nodes.windows(2) {
                        if let (Some(from), Some(to)) = (node_pair.first(), node_pair.last()) {
                            if let (Some(from_node), Some(to_node)) = (parse_result.nodes.get(from), parse_result.nodes.get(to)) {
                                let edge_length = calculate_distance(from_node, to_node);
                                let edge = ParsedEdge { id_from: from.clone(), id_to: to.clone(), length: edge_length.clone() };
                                parse_result.edges.push(edge);

                                if let Some(val) = way.tags.get("oneway") {
                                    if val == "yes" {
                                        let edge_reverse = ParsedEdge { id_from: to.clone(), id_to: from.clone(), length: edge_length.clone() };
                                        parse_result.edges.push(edge_reverse);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            _ => {}
        }
    }
}

fn build_routing_data(parse_result: &mut ParseData) -> RoutingData {
    let mut routing_data = RoutingData { osm_nodes: HashMap::new(), internal_nodes: Vec::new(), internal_edges: Vec::new(), internal_offset: vec![usize::max_value(); parse_result.nodes.len()] };

    parse_result.edges.sort_by(|a, b| b.id_from.cmp(&a.id_from));

    for node in parse_result.nodes.keys() {
        routing_data.internal_nodes.push(node.clone());
    }

    routing_data.internal_nodes.sort();

    for (i, node) in routing_data.internal_nodes.iter().enumerate() {
        if let Some(pos) = parse_result.nodes.remove(node) {
            routing_data.osm_nodes.insert(node.clone(), OsmNode { position: pos, internal_id: i });

            if let Some(edge) = parse_result.edges.last() {
                if edge.id_from == *node {
                    routing_data.internal_offset[i] = routing_data.internal_edges.len();
                }
            }

            loop {
                if let Some(edge) = parse_result.edges.last() {
                    if edge.id_from != *node {
                        break;
                    }
                } else {
                    break;
                }
                if let Some(edge) = parse_result.edges.pop() {
                    routing_data.internal_edges.push(RoutingEdge { target: edge.id_to as usize, length: edge.length, constraints: 0b00000001 });
                } else {
                    break;
                }
            }
        }
    }

    return routing_data;
}

fn calculate_distance(node1: &Position, node2: &Position) -> f64 {
    let lat1 = node1.lat;
    let lat2 = node2.lat;
    let lng1 = node1.lon;
    let lng2 = node2.lon;

    let earth_radius: f64 = 6371000.0; //meters
    let d_lat = (lat2 - lat1).to_radians();
    let d_lng = (lng2 - lng1).to_radians();
    let a = (d_lat / 2.0).sin() * (d_lat / 2.0).sin() + lat1.to_radians().cos() * lat2.to_radians().cos() * (d_lng / 2.0).sin() * (d_lng / 2.0).sin();
    let c = 2.0 * a.sqrt().atan2((1.0 - a).sqrt());
    let dist = earth_radius * c;

    return dist;
}

fn init_filter_list(invalid_values: &mut HashSet<&str>) {
    invalid_values.insert("services");
    invalid_values.insert("pedestrian");
    invalid_values.insert("raceway");
    invalid_values.insert("footway");
    invalid_values.insert("path");
    invalid_values.insert("steps");
    invalid_values.insert("bridleway");
    invalid_values.insert("construction");
}

fn filter_way(way: &osmpbfreader::Way, invalid_values: &HashSet<&str>) -> bool {
    if let Some(value) = way.tags.get("highway") {
        return !invalid_values.contains(&value.as_str());
    } else {
        return false;
    }
}<commit_msg>add missing step to offset array construction add test for routing data generation method consume parse data in routing data generation method<commit_after>extern crate osmpbfreader;
extern crate time;

use time::PreciseTime;
use std::fs::File;
use std::path::Path;
use std::ffi::OsString;
use std::collections::HashMap;
use std::collections::HashSet;

use osmpbfreader::OsmObj;
use osmpbfreader::OsmPbfReader;

#[derive(Debug, Clone, Copy)]
struct Position {
    lat: f64,
    lon: f64,
}

#[derive(Debug, Clone, Copy)]
struct ParsedEdge {
    id_from: i64,
    id_to: i64,
    length: f64,
}

struct ParseData {
    // used node-ids
    nodes_used: HashSet<i64>,
    // "useful" ways
    filtered_ways: HashSet<i64>,
    // relevant nodes and their position
    nodes: HashMap<i64, Position>,
    // edges
    edges: Vec<ParsedEdge>
}

#[derive(Debug)]
struct RoutingEdge {
    target: usize,
    length: f64,
    constraints: u8,
}

struct OsmNode {
    position: Position,
    internal_id: usize
}

struct RoutingData {
    // relevant nodes and their position
    osm_nodes: HashMap<i64, OsmNode>,
    //[n_id] -> osm_n_id
    internal_nodes: Vec<i64>,
    // [e_id] -> n_id target|length|constraints
    internal_edges: Vec<RoutingEdge>,
    // [n_id] -> e_id
    internal_offset: Vec<usize>,
}

fn main() {
    let default_file = OsString::from("/home/zsdn/baden-wuerttemberg-latest.osm.pbf".to_string());
    //let default_file = OsString::from("/home/zsdn/germany-latest.osm.pbf".to_string());
    let args: Vec<OsString> = std::env::args_os().collect();
    match args.len() {
        1 => {
            read_file(&default_file);
        }
        2 => {
            read_file(&args[1]);
        }
        _ => {},
    };
}

fn read_file(filename: &OsString) -> RoutingData {
    let mut parse_result = ParseData { nodes_used: HashSet::new(), filtered_ways: HashSet::new(), nodes: HashMap::new(), edges: Vec::new() };

    let start_p1 = PreciseTime::now();
    first_parse(&filename, &mut parse_result);
    let end_p1 = PreciseTime::now();

    println!("P1 | ways:  {}", parse_result.filtered_ways.len());
    println!("P1 | nodes_used: {}", parse_result.nodes_used.len());
    println!("P1 | edges: {}", parse_result.edges.len());
    println!("P1 | nodes: {}", parse_result.nodes.len());
    println!("P1 | duration: {}", start_p1.to(end_p1));

    let start_p2 = PreciseTime::now();
    second_parse(&filename, &mut parse_result);
    let end_p2 = PreciseTime::now();

    println!("P2 | ways:  {}", parse_result.filtered_ways.len());
    println!("P2 | nodes_used: {}", parse_result.nodes_used.len());
    println!("P2 | edges: {}", parse_result.edges.len());
    println!("P2 | nodes: {}", parse_result.nodes.len());
    println!("P2 | duration: {}", start_p2.to(end_p2));

    let start_p3 = PreciseTime::now();
    third_parse(&filename, &mut parse_result);
    let end_p3 = PreciseTime::now();

    println!("P3 | ways:  {}", parse_result.filtered_ways.len());
    println!("P3 | nodes_used: {}", parse_result.nodes_used.len());
    println!("P3 | edges: {}", parse_result.edges.len());
    println!("P3 | nodes: {}", parse_result.nodes.len());
    println!("P3 | duration: {}", start_p3.to(end_p3));

    let start_b = PreciseTime::now();
    let routing_data = build_routing_data(parse_result);
    let end_b = PreciseTime::now();

    println!("B  | edges:  {}", routing_data.internal_edges.len());
    println!("B  | nodes:  {}", routing_data.internal_nodes.len());
    println!("B  | offset:  {}", routing_data.internal_offset.len());
    println!("B  | osm_nodes:  {}", routing_data.osm_nodes.len());
    println!("B  | duration: {}", start_b.to(end_b));

    return routing_data;
}

#[test]
fn test() {
    let edge_vec = vec![ParsedEdge{id_from : 0, id_to : 1, length : 1.0},
                        ParsedEdge{id_from : 0, id_to : 2, length : 1.0},
                        ParsedEdge{id_from : 2, id_to : 1, length : 1.0},
                        ParsedEdge{id_from : 2, id_to : 3, length : 1.0},
                        ParsedEdge{id_from : 3, id_to : 1, length : 1.0},
                        ParsedEdge{id_from : 3, id_to : 4, length : 1.0},
    ];

    let mut nodes_map = HashMap::new();

    nodes_map.insert(0, Position { lat: 0.0, lon: 0.0 });
    nodes_map.insert(1, Position { lat: 0.0, lon: 0.0 });
    nodes_map.insert(2, Position { lat: 0.0, lon: 0.0 });
    nodes_map.insert(3, Position { lat: 0.0, lon: 0.0 });
    nodes_map.insert(4, Position { lat: 0.0, lon: 0.0 });

    let parse_result = ParseData { nodes: nodes_map, edges: edge_vec, filtered_ways: HashSet::new(), nodes_used: HashSet::new() };

    let routing_data = build_routing_data(parse_result);

    println!("NODES: {:?}", routing_data.internal_nodes);
    println!("EDGES: {:?}", routing_data.internal_edges);
    println!("OFFSET: {:?}", routing_data.internal_offset);

    assert_eq!(routing_data.internal_offset, vec![0, 2, 2, 4, 5]);
}

fn first_parse(filename: &OsString, parse_result: &mut ParseData) {
    let pbf_file = File::open(&Path::new(filename)).unwrap();

    let mut invalid_values = HashSet::new();
    init_filter_list(&mut invalid_values);

    let mut pbf = OsmPbfReader::new(pbf_file);

    for obj in pbf.iter() {
        match obj {
            OsmObj::Way(way) => {
                if filter_way(&way, &invalid_values) {
                    for node in way.nodes {
                        parse_result.nodes_used.insert(node);
                    }
                    parse_result.filtered_ways.insert(way.id);
                }
            }
            _ => {}
        }
    }
}

fn second_parse(filename: &OsString, parse_result: &mut ParseData) {
    let pbf_file = File::open(&Path::new(filename)).unwrap();
    let mut pbf = OsmPbfReader::new(pbf_file);

    for obj in pbf.iter() {
        match obj {
            OsmObj::Node(node) => {
                if parse_result.nodes_used.remove(&node.id) {
                    parse_result.nodes.insert(node.id, Position { lat: node.lat, lon: node.lon });
                }
            }
            _ => {}
        }
    }
}

fn third_parse(filename: &OsString, parse_result: &mut ParseData) {
    let pbf_file = File::open(&Path::new(filename)).unwrap();
    let mut pbf = OsmPbfReader::new(pbf_file);

    for obj in pbf.iter() {
        match obj {
            OsmObj::Way(way) => {
                if parse_result.filtered_ways.remove(&way.id) {
                    for node_pair in way.nodes.windows(2) {
                        if let (Some(from), Some(to)) = (node_pair.first(), node_pair.last()) {
                            if let (Some(from_node), Some(to_node)) = (parse_result.nodes.get(from), parse_result.nodes.get(to)) {
                                let edge_length = calculate_distance(from_node, to_node);
                                let edge = ParsedEdge { id_from: from.clone(), id_to: to.clone(), length: edge_length.clone() };
                                parse_result.edges.push(edge);

                                if let Some(val) = way.tags.get("oneway") {
                                    if val == "yes" {
                                        let edge_reverse = ParsedEdge { id_from: to.clone(), id_to: from.clone(), length: edge_length.clone() };
                                        parse_result.edges.push(edge_reverse);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            _ => {}
        }
    }
}

fn build_routing_data(mut parse_result: ParseData) -> RoutingData {
    let mut routing_data = RoutingData { osm_nodes: HashMap::new(), internal_nodes: Vec::new(), internal_edges: Vec::new(), internal_offset: vec![usize::max_value(); parse_result.nodes.len()] };

    parse_result.edges.sort_by(|a, b| b.id_from.cmp(&a.id_from));

    for node in parse_result.nodes.keys() {
        routing_data.internal_nodes.push(node.clone());
    }

    routing_data.internal_nodes.sort();

    for (i, node) in routing_data.internal_nodes.iter().enumerate() {
        if let Some(pos) = parse_result.nodes.remove(node) {
            routing_data.osm_nodes.insert(node.clone(), OsmNode { position: pos, internal_id: i });

            if let Some(edge) = parse_result.edges.last() {
                if edge.id_from == *node {
                    routing_data.internal_offset[i] = routing_data.internal_edges.len();
                }
            }

            loop {
                if let Some(edge) = parse_result.edges.last() {
                    if edge.id_from != *node {
                        break;
                    }
                } else {
                    break;
                }
                if let Some(edge) = parse_result.edges.pop() {
                    routing_data.internal_edges.push(RoutingEdge { target: edge.id_to as usize, length: edge.length, constraints: 0b00000001 });
                } else {
                    break;
                }
            }
        }
    }

    let mut current_offset = routing_data.internal_edges.len() - 1;

    for offset in &mut routing_data.internal_offset.iter_mut().rev() {
        if *offset == usize::max_value() {
            *offset = current_offset;
        } else {
            current_offset = *offset;
        }
    }

    return routing_data;
}

fn calculate_distance(node1: &Position, node2: &Position) -> f64 {
    let lat1 = node1.lat;
    let lat2 = node2.lat;
    let lng1 = node1.lon;
    let lng2 = node2.lon;

    let earth_radius: f64 = 6371000.0; //meters
    let d_lat = (lat2 - lat1).to_radians();
    let d_lng = (lng2 - lng1).to_radians();
    let a = (d_lat / 2.0).sin() * (d_lat / 2.0).sin() + lat1.to_radians().cos() * lat2.to_radians().cos() * (d_lng / 2.0).sin() * (d_lng / 2.0).sin();
    let c = 2.0 * a.sqrt().atan2((1.0 - a).sqrt());
    let dist = earth_radius * c;

    return dist;
}

fn init_filter_list(invalid_values: &mut HashSet<&str>) {
    invalid_values.insert("services");
    invalid_values.insert("pedestrian");
    invalid_values.insert("raceway");
    invalid_values.insert("footway");
    invalid_values.insert("path");
    invalid_values.insert("steps");
    invalid_values.insert("bridleway");
    invalid_values.insert("construction");
}

fn filter_way(way: &osmpbfreader::Way, invalid_values: &HashSet<&str>) -> bool {
    if let Some(value) = way.tags.get("highway") {
        return !invalid_values.contains(&value.as_str());
    } else {
        return false;
    }
}<|endoftext|>


<commit_before>//
// main.rs
// Copyright (C) 2017 Szymon Urbaś <szymon.urbas@aol.com>
// Distributed under terms of the BSD (2-clause) license.
//
// Created on: 13 Mar 2017 21:03:41 +0100 (CET)
//

extern crate rand;
extern crate cursive;

use std::thread;
use std::time;

mod process;
mod scheduler;
mod fcfs;
mod round_robin;
mod tui;

use scheduler::*;
use tui::*;

/// Length of a single system clock tick (frequency of actual, real time)
const CLOCK_HZ: u64 = 50;
/// Switch context every <value> clock ticks
const SYSTEM_HZ: usize = 8;

fn main() {
  let mut tui = tui::new();

  let scenarios = {
    (0..2).map(|_| (0..10).map(|_| 16).collect::<Vec<usize>>()).collect::<Vec<Vec<usize>>>()
  };

  macro_rules! run_simulation_suite {
    ($scheduler:ident) => ({
      let mut average_waiting_time = 0f64;

      for (run, scenario) in scenarios.iter().enumerate() {
        let scheduler = $scheduler::new();
        let avg = run_simulation(&mut tui, scheduler, scenario.clone());
        tui.add_result(format!("{}: #{:02}: Average waiting time: {:02.2}", stringify!($scheduler), run, avg));

        average_waiting_time -= average_waiting_time / (run + 1) as f64;
        average_waiting_time += avg / (run + 1) as f64;
      }

      tui.add_result(format!("{}: Overall average: {:02.2}", stringify!($scheduler), average_waiting_time));
    })
  }

  run_simulation_suite!(fcfs);
  run_simulation_suite!(round_robin);

  tui.update();

  loop {}
}

fn run_simulation<S>(mut tui: &mut Tui, mut scheduler: S, mut process_list: Vec<usize>) -> f64
where S: Scheduler {
  let mut clock_tick = 0;
  let mut process_spawner = process::new_spawner();
  let mut average_waiting_time = 0f64;
  let mut num_of_spawned_procs = 1;

  tui.set_header(format!("Using algorithm: {}", scheduler.name()));
  tui.debug(format!("{:05}: Starting simulation using {}", clock_tick, scheduler.name()));

  // vectors only support the pop (from the back) operation so
  // reverse it (so we pop from the front)
  process_list.reverse();

  // Add the equivalent of the 'init' process
  scheduler.add_process(process_spawner.spawn(process_list.pop().unwrap()));

  loop {
    // update the process view
    scheduler.list_processes(&mut tui);
    // update all the views
    tui.update();

    if !scheduler.has_processes() {
      // if there's no more processes - end the simulation
      // if a process can only be created by another process - there's
      // nothing else to do
      break;
    }

    // simulate executing the current process
    tui.debug(format!("{:05}: Executing {}", clock_tick, scheduler.current_proc().unwrap().name));
    scheduler.current_proc_mut().unwrap().record_execution();

    // Simulate other processes creating new processes
    // Assume that you can't create new processes, if there's none already
    if clock_tick % SYSTEM_HZ == 0 {
      if let Some(burst_time) = process_list.pop() {
        let new_proc = process_spawner.spawn(burst_time);
        tui.debug(format!("{:05}: Spawning {}", clock_tick, new_proc.name));
        scheduler.add_process(new_proc);
        num_of_spawned_procs += 1;
      }
    }

    if scheduler.current_proc().unwrap().done_executing() {
      tui.debug(format!("{:05}: Killing process {}", clock_tick, scheduler.current_proc().unwrap().name));
      scheduler.kill_current_proc();
    }

    if scheduler.has_processes() {
      if clock_tick % SYSTEM_HZ == SYSTEM_HZ - 1 {
        let prev_proc_name = scheduler.current_proc().unwrap().name.clone();
        scheduler.schedule();
        tui.debug(format!("{:05}: Switching context: {} -> {}", clock_tick, prev_proc_name, scheduler.current_proc().unwrap().name));
        tui.debug(format!("{:05}: {} was waiting {} clock ticks", clock_tick, scheduler.current_proc().unwrap().name, scheduler.current_proc().unwrap().waiting_time));

        average_waiting_time -= average_waiting_time / num_of_spawned_procs as f64;
        average_waiting_time += scheduler.current_proc().unwrap().waiting_time as f64 / num_of_spawned_procs as f64;
      }

      // increase the waiting time for every process
      scheduler.increase_waiting_times();
    }

    thread::sleep(time::Duration::from_millis(1000 / CLOCK_HZ));

    clock_tick += 1;
  }

  average_waiting_time
}

/*
 * vi: ts=2 sw=2 expandtab
 */

<commit_msg>Make each process' expected execution time random<commit_after>//
// main.rs
// Copyright (C) 2017 Szymon Urbaś <szymon.urbas@aol.com>
// Distributed under terms of the BSD (2-clause) license.
//
// Created on: 13 Mar 2017 21:03:41 +0100 (CET)
//

extern crate rand;
extern crate cursive;

use std::thread;
use std::time;

mod process;
mod scheduler;
mod fcfs;
mod round_robin;
mod tui;

use scheduler::*;
use tui::*;

/// Length of a single system clock tick (frequency of actual, real time)
const CLOCK_HZ: u64 = 50;
/// Switch context every <value> clock ticks
const SYSTEM_HZ: usize = 8;

fn main() {
  let mut tui = tui::new();

  let scenarios = {
    (0..2).map(|_| (0..10).map(|_| rand::random::<usize>() % (SYSTEM_HZ * 4) + 1).collect::<Vec<usize>>()).collect::<Vec<Vec<usize>>>()
  };

  macro_rules! run_simulation_suite {
    ($scheduler:ident) => ({
      let mut average_waiting_time = 0f64;

      for (run, scenario) in scenarios.iter().enumerate() {
        let scheduler = $scheduler::new();
        let avg = run_simulation(&mut tui, scheduler, scenario.clone());
        tui.add_result(format!("{}: #{:02}: Average waiting time: {:02.2}", stringify!($scheduler), run, avg));

        average_waiting_time -= average_waiting_time / (run + 1) as f64;
        average_waiting_time += avg / (run + 1) as f64;
      }

      tui.add_result(format!("{}: Overall average: {:02.2}", stringify!($scheduler), average_waiting_time));
    })
  }

  run_simulation_suite!(fcfs);
  run_simulation_suite!(round_robin);

  tui.update();

  loop {}
}

fn run_simulation<S>(mut tui: &mut Tui, mut scheduler: S, mut process_list: Vec<usize>) -> f64
where S: Scheduler {
  let mut clock_tick = 0;
  let mut process_spawner = process::new_spawner();
  let mut average_waiting_time = 0f64;
  let mut num_of_spawned_procs = 1;

  tui.set_header(format!("Using algorithm: {}", scheduler.name()));
  tui.debug(format!("{:05}: Starting simulation using {}", clock_tick, scheduler.name()));

  // vectors only support the pop (from the back) operation so
  // reverse it (so we pop from the front)
  process_list.reverse();

  // Add the equivalent of the 'init' process
  scheduler.add_process(process_spawner.spawn(process_list.pop().unwrap()));

  loop {
    // update the process view
    scheduler.list_processes(&mut tui);
    // update all the views
    tui.update();

    if !scheduler.has_processes() {
      // if there's no more processes - end the simulation
      // if a process can only be created by another process - there's
      // nothing else to do
      break;
    }

    // simulate executing the current process
    tui.debug(format!("{:05}: Executing {}", clock_tick, scheduler.current_proc().unwrap().name));
    scheduler.current_proc_mut().unwrap().record_execution();

    // Simulate other processes creating new processes
    // Assume that you can't create new processes, if there's none already
    if clock_tick % SYSTEM_HZ == 0 {
      if let Some(burst_time) = process_list.pop() {
        let new_proc = process_spawner.spawn(burst_time);
        tui.debug(format!("{:05}: Spawning {}", clock_tick, new_proc.name));
        scheduler.add_process(new_proc);
        num_of_spawned_procs += 1;
      }
    }

    if scheduler.current_proc().unwrap().done_executing() {
      tui.debug(format!("{:05}: Killing process {}", clock_tick, scheduler.current_proc().unwrap().name));
      scheduler.kill_current_proc();
    }

    if scheduler.has_processes() {
      if clock_tick % SYSTEM_HZ == SYSTEM_HZ - 1 {
        let prev_proc_name = scheduler.current_proc().unwrap().name.clone();
        scheduler.schedule();
        tui.debug(format!("{:05}: Switching context: {} -> {}", clock_tick, prev_proc_name, scheduler.current_proc().unwrap().name));
        tui.debug(format!("{:05}: {} was waiting {} clock ticks", clock_tick, scheduler.current_proc().unwrap().name, scheduler.current_proc().unwrap().waiting_time));

        average_waiting_time -= average_waiting_time / num_of_spawned_procs as f64;
        average_waiting_time += scheduler.current_proc().unwrap().waiting_time as f64 / num_of_spawned_procs as f64;
      }

      // increase the waiting time for every process
      scheduler.increase_waiting_times();
    }

    thread::sleep(time::Duration::from_millis(1000 / CLOCK_HZ));

    clock_tick += 1;
  }

  average_waiting_time
}

/*
 * vi: ts=2 sw=2 expandtab
 */

<|endoftext|>


<commit_before>#![feature(libc)]
#![feature(io)]
#![cfg(not(test))]

extern crate libc;
extern crate "rustc-serialize" as rustc_serialize;
extern crate rustbox;
extern crate docopt;
extern crate iota;

use std::io::stdin;
use docopt::Docopt;
use iota::{
    Editor, Input,
    StandardMode, NormalMode,
    RustboxFrontend, Mode
};
use rustbox::{InitOptions, RustBox, InputMode};
static USAGE: &'static str = "
Usage: iota [<filename>] [options]
       iota --help

Options:
    --vi           Start Iota with vi-like modes
    -h, --help     Show this message.
";

#[derive(RustcDecodable, Debug)]
struct Args {
    arg_filename: Option<String>,
    flag_vi: bool,
    flag_help: bool,
}

fn is_raw(fileno: libc::c_int) -> bool {
    // FIXME: find a way to do this without unsafe
    //        std::io doesn't allow for this, currently
    unsafe { libc::isatty(fileno) == 1 }
}

fn main() {
    let args: Args = Docopt::new(USAGE)
                            .and_then(|d| d.decode())
                            .unwrap_or_else(|e| e.exit());

    let stdin_is_raw = is_raw(libc::STDIN_FILENO);
    let stderr_is_raw = is_raw(libc::STDERR_FILENO);

    // editor source - either a filename or stdin
    let source = if stdin_is_raw {
        Input::Filename(args.arg_filename)
    } else {
        Input::Stdin(stdin())
    };

    // initialise rustbox
    let rb = match RustBox::init(InitOptions{
        // FIXME: find a way to do this without unsafe
        //        std::io doesn't allow for this, currently
        buffer_stderr: stderr_is_raw,
        input_mode: InputMode::Esc,
    }) {
        Result::Ok(v) => v,
        Result::Err(e) => panic!("{}", e),
    };

    // initialise the frontend
    let frontend = RustboxFrontend::new(&rb);

    // initialise the editor mode
    let mode: Box<Mode> = if args.flag_vi {
        Box::new(NormalMode::new())
    } else {
         Box::new(StandardMode::new())
    };

    // start the editor
    let mut editor = Editor::new(source, mode, frontend);
    editor.start();
}
<commit_msg>Remove comment<commit_after>#![feature(libc)]
#![feature(io)]
#![cfg(not(test))]

extern crate libc;
extern crate "rustc-serialize" as rustc_serialize;
extern crate rustbox;
extern crate docopt;
extern crate iota;

use std::io::stdin;
use docopt::Docopt;
use iota::{
    Editor, Input,
    StandardMode, NormalMode,
    RustboxFrontend, Mode
};
use rustbox::{InitOptions, RustBox, InputMode};
static USAGE: &'static str = "
Usage: iota [<filename>] [options]
       iota --help

Options:
    --vi           Start Iota with vi-like modes
    -h, --help     Show this message.
";

#[derive(RustcDecodable, Debug)]
struct Args {
    arg_filename: Option<String>,
    flag_vi: bool,
    flag_help: bool,
}

fn is_raw(fileno: libc::c_int) -> bool {
    // FIXME: find a way to do this without unsafe
    //        std::io doesn't allow for this, currently
    unsafe { libc::isatty(fileno) == 1 }
}

fn main() {
    let args: Args = Docopt::new(USAGE)
                            .and_then(|d| d.decode())
                            .unwrap_or_else(|e| e.exit());

    let stdin_is_raw = is_raw(libc::STDIN_FILENO);
    let stderr_is_raw = is_raw(libc::STDERR_FILENO);

    // editor source - either a filename or stdin
    let source = if stdin_is_raw {
        Input::Filename(args.arg_filename)
    } else {
        Input::Stdin(stdin())
    };

    // initialise rustbox
    let rb = match RustBox::init(InitOptions{
        buffer_stderr: stderr_is_raw,
        input_mode: InputMode::Esc,
    }) {
        Result::Ok(v) => v,
        Result::Err(e) => panic!("{}", e),
    };

    // initialise the frontend
    let frontend = RustboxFrontend::new(&rb);

    // initialise the editor mode
    let mode: Box<Mode> = if args.flag_vi {
        Box::new(NormalMode::new())
    } else {
         Box::new(StandardMode::new())
    };

    // start the editor
    let mut editor = Editor::new(source, mode, frontend);
    editor.start();
}
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#![feature(iter_arith, zero_one, custom_derive,
           custom_attribute, plugin, const_fn)]
#![plugin(serde_macros)]
#![plugin(clippy)]

extern crate devicemapper;
#[macro_use]
extern crate clap;
extern crate nix;
extern crate crc;
extern crate byteorder;
extern crate uuid;
extern crate time;
extern crate serde;
extern crate serde_json;
extern crate bytesize;
extern crate dbus;

#[macro_use] extern crate custom_derive;
#[macro_use] extern crate newtype_derive;

pub static mut debug: bool = false;

macro_rules! dbgp {
    ($($arg:tt)*) => (
        unsafe {
            if ::debug {
                println!($($arg)*)
            }
        })
}

mod types;
mod consts;
mod froyo;
mod blockdev;
mod raid;
mod thin;
mod util;
mod dbus_api;

use std::io::Write;
use std::error::Error;
use std::process::exit;
use std::path::{Path, PathBuf};
use std::rc::Rc;
use std::cell::RefCell;

use clap::{App, Arg, SubCommand, ArgMatches};
use bytesize::ByteSize;
use dbus::{Connection, BusType};

use types::{DataBlocks, FroyoResult};
use froyo::{Froyo, FroyoStatus};

// We are given BlockDevs to start.
// We allocate LinearDevs from each for the meta and data devices.
// We use all these to make RaidDevs.
// We create two RaidLinearDevs from these for meta and data devices.
// We use these to make a ThinPoolDev.
// From that, we allocate a ThinDev.

fn list(_args: &ArgMatches) -> FroyoResult<()> {
    let froyos = try!(Froyo::find_all());
    for f in &froyos {
        println!("{}", f.name);
    }

    Ok(())
}

fn status(args: &ArgMatches) -> FroyoResult<()> {
    let name = args.value_of("froyodevname").unwrap();
    match try!(Froyo::find(&name)) {
        Some(f) => {
            let status = match try!(f.status()) {
                FroyoStatus::Good(_) => "good",
                FroyoStatus::RaidFailed => "RAID failed",
                FroyoStatus::ThinPoolFailed => "Thin pool failed",
                FroyoStatus::ThinFailed => "Thin device failed",
            };

            let space = try!(f.avail_redundant_space());
            let total = f.total_redundant_space();

            let percent = (*(total-space) * 100) / *total;

            println!("Status: {}, {}% used ({} of {} {} blocks free)",
                     status, percent,
                     *space, *total,
                     ByteSize::b(f.data_block_size() as usize).to_string(true));
        },
        None => println!("Froyodev \"{}\" not found", name),
    }
    Ok(())
}

fn add(_args: &ArgMatches) -> FroyoResult<()> {
    println!("hello from add()");
    Ok(())
}

fn remove(_args: &ArgMatches) -> FroyoResult<()> {
    println!("hello from remove()");
    Ok(())
}

fn create(args: &ArgMatches) -> FroyoResult<()> {
    let name = args.value_of("froyodevname").unwrap();
    let dev_paths: Vec<_> = args.values_of("devices").unwrap().into_iter()
        .map(|dev| {
            if !Path::new(dev).is_absolute() {
                PathBuf::from(format!("/dev/{}", dev))
            } else {
                PathBuf::from(dev)
            }})
        .collect();
    let force = args.is_present("force");

    let froyo = try!(Froyo::new(name, &dev_paths, force));

    try!(froyo.save_state());

    dbgp!("Froyodev {} created", froyo.name);

    Ok(())
}

fn dump_meta(args: &ArgMatches) -> FroyoResult<()> {
    let name = args.value_of("froyodevname").unwrap();
    match try!(Froyo::find(&name)) {
        Some(f) =>
            println!("{}", try!(f.to_metadata_pretty())),
        None => println!("Froyodev \"{}\" not found", name),
    }

    Ok(())
}

fn dbus_server(_args: &ArgMatches) -> FroyoResult<()> {
    let c = Connection::get_private(BusType::Session).unwrap();
    let froyos = try!(Froyo::find_all());
    let froyos = froyos.into_iter()
        .map(|f| Rc::new(RefCell::new(f)))
        .collect::<Vec<_>>();
    let mut froyos = Rc::new(RefCell::new(froyos));
    let tree = try!(dbus_api::get_tree(&c, &mut froyos));

    // TODO: event loop needs to handle dbus and also dm events (or polling)
    // so we can extend/reshape/delay/whatever in a timely fashion
    for _ in tree.run(&c, c.iter(1000)) {

    }

    Ok(())
}

fn main() {

    let matches = App::new("froyo")
        .version(&crate_version!())
        .author("Andy Grover <andy@groveronline.com>")
        .about("Drobo + Free + YOLO")
        .arg(Arg::with_name("debug")
             .short("d")
             .long("debug")
             .help("Print additional output for debugging")
             )
        .subcommand(SubCommand::with_name("list")
                    .about("List all froyodevs")
                    .arg(Arg::with_name("long")
                         .short("l")
                         .long("long")
                         .help("Use a long listing format")
                         )
                    )
        .subcommand(SubCommand::with_name("status")
                    .about("Get the status of a single froyodev")
                    .arg(Arg::with_name("froyodevname")
                         .required(true)
                         .help("Froyodev to get info on")
                         .index(1)
                         )
                    )
        .subcommand(SubCommand::with_name("add")
                    .about("Add one or more additional block devices to a froyodev")
                    .arg(Arg::with_name("froyodevname")
                         .help("Froyodev to add the device to")
                         .required(true)
                         .index(1)
                         )
                    .arg(Arg::with_name("devices")
                         .help("device(s) to add")
                         .multiple(true)
                         .required(true)
                         .index(2)
                         )
                    )
        .subcommand(SubCommand::with_name("remove")
                    .about("Remove a block device from a froyodev")
                    .arg(Arg::with_name("froyodevname")
                         .help("Froyodev to remove the device from")
                         .required(true)
                         .index(1)
                         )
                    .arg(Arg::with_name("devices")
                         .help("Block device(s) to remove")
                         .multiple(true)
                         .required(true)
                         .index(2)
                         )
                    )
        .subcommand(SubCommand::with_name("create")
                    .about("Create a new froyodev")
                    .arg(Arg::with_name("force")
                         .short("f")
                         .long("force")
                         .help("Force")
                         )
                    .arg(Arg::with_name("froyodevname")
                         .help("Name of the new froyodev")
                         .required(true)
                         .index(1)
                         )
                    .arg(Arg::with_name("devices")
                         .help("Initial block device(s) to use")
                         .multiple(true)
                         .required(true)
                         .index(2)
                         )
                    )
        .subcommand(SubCommand::with_name("dev")
                    .about("Developer/debug commands")
                    .subcommand(SubCommand::with_name("dump_meta")
                                .about("Output the JSON metadata for a froyodev")
                                .arg(Arg::with_name("froyodevname")
                                     .help("Name of the froyodev")
                                     .required(true)
                                     .index(1)
                                     )
                                )
                    .subcommand(SubCommand::with_name("dbus_server")
                                .about("Serve the Froyo DBus API")
                                )
                    )
        .get_matches();

    if matches.is_present("debug") {
        // must use unsafe to change a mut static, sigh
        unsafe { debug = true };
    }

    let r = match matches.subcommand() {
        ("list", Some(matches)) => list(matches),
        ("status", Some(matches)) => status(matches),
        ("add", Some(matches)) => add(matches),
        ("remove", Some(matches)) => remove(matches),
        ("create", Some(matches)) => create(matches),
        ("dev", Some(matches)) => match matches.subcommand() {
            ("dump_meta", Some(matches)) => dump_meta(matches),
            ("dbus_server", Some(matches)) => dbus_server(matches),
            ("", None) => {
                println!("No command given, try \"help\"");
                Ok(())
            }
            _ => unreachable!(),
        },
        ("", None) => {
            println!("No command given, try \"help\"");
            Ok(())
        }
        _ => unreachable!(),
    };

    if let Err(r) = r {
        if let Err(e) = writeln!(&mut ::std::io::stderr(), "{}", r.description()) {
            panic!("Unable to write to stderr: {}", e)
        }
        exit(1);
    }
}
<commit_msg>Fix status cmd's size calculations<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#![feature(iter_arith, zero_one, custom_derive,
           custom_attribute, plugin, const_fn)]
#![plugin(serde_macros)]
#![plugin(clippy)]

extern crate devicemapper;
#[macro_use]
extern crate clap;
extern crate nix;
extern crate crc;
extern crate byteorder;
extern crate uuid;
extern crate time;
extern crate serde;
extern crate serde_json;
extern crate bytesize;
extern crate dbus;

#[macro_use] extern crate custom_derive;
#[macro_use] extern crate newtype_derive;

pub static mut debug: bool = false;

macro_rules! dbgp {
    ($($arg:tt)*) => (
        unsafe {
            if ::debug {
                println!($($arg)*)
            }
        })
}

mod types;
mod consts;
mod froyo;
mod blockdev;
mod raid;
mod thin;
mod util;
mod dbus_api;

use std::io::Write;
use std::error::Error;
use std::process::exit;
use std::path::{Path, PathBuf};
use std::rc::Rc;
use std::cell::RefCell;

use clap::{App, Arg, SubCommand, ArgMatches};
use bytesize::ByteSize;
use dbus::{Connection, BusType};

use types::{DataBlocks, FroyoResult};
use consts::SECTOR_SIZE;
use froyo::{Froyo, FroyoStatus};

// We are given BlockDevs to start.
// We allocate LinearDevs from each for the meta and data devices.
// We use all these to make RaidDevs.
// We create two RaidLinearDevs from these for meta and data devices.
// We use these to make a ThinPoolDev.
// From that, we allocate a ThinDev.

fn list(_args: &ArgMatches) -> FroyoResult<()> {
    let froyos = try!(Froyo::find_all());
    for f in &froyos {
        println!("{}", f.name);
    }

    Ok(())
}

fn status(args: &ArgMatches) -> FroyoResult<()> {
    let name = args.value_of("froyodevname").unwrap();
    match try!(Froyo::find(&name)) {
        Some(f) => {
            let status = match try!(f.status()) {
                FroyoStatus::Good(_) => "good",
                FroyoStatus::RaidFailed => "RAID failed",
                FroyoStatus::ThinPoolFailed => "Thin pool failed",
                FroyoStatus::ThinFailed => "Thin device failed",
            };

            let space = *try!(f.avail_redundant_space()) * SECTOR_SIZE;
            let total = *f.total_redundant_space() * SECTOR_SIZE;

            let percent = ((total-space) * 100) / total;

            println!("Status: {}, {}% used ({} of {} free)",
                     status, percent,
                     ByteSize::b(space as usize).to_string(true),
                     ByteSize::b(total as usize).to_string(true));
        },
        None => println!("Froyodev \"{}\" not found", name),
    }
    Ok(())
}

fn add(_args: &ArgMatches) -> FroyoResult<()> {
    println!("hello from add()");
    Ok(())
}

fn remove(_args: &ArgMatches) -> FroyoResult<()> {
    println!("hello from remove()");
    Ok(())
}

fn create(args: &ArgMatches) -> FroyoResult<()> {
    let name = args.value_of("froyodevname").unwrap();
    let dev_paths: Vec<_> = args.values_of("devices").unwrap().into_iter()
        .map(|dev| {
            if !Path::new(dev).is_absolute() {
                PathBuf::from(format!("/dev/{}", dev))
            } else {
                PathBuf::from(dev)
            }})
        .collect();
    let force = args.is_present("force");

    let froyo = try!(Froyo::new(name, &dev_paths, force));

    try!(froyo.save_state());

    dbgp!("Froyodev {} created", froyo.name);

    Ok(())
}

fn dump_meta(args: &ArgMatches) -> FroyoResult<()> {
    let name = args.value_of("froyodevname").unwrap();
    match try!(Froyo::find(&name)) {
        Some(f) =>
            println!("{}", try!(f.to_metadata_pretty())),
        None => println!("Froyodev \"{}\" not found", name),
    }

    Ok(())
}

fn dbus_server(_args: &ArgMatches) -> FroyoResult<()> {
    let c = Connection::get_private(BusType::Session).unwrap();
    let froyos = try!(Froyo::find_all());
    let froyos = froyos.into_iter()
        .map(|f| Rc::new(RefCell::new(f)))
        .collect::<Vec<_>>();
    let mut froyos = Rc::new(RefCell::new(froyos));
    let tree = try!(dbus_api::get_tree(&c, &mut froyos));

    // TODO: event loop needs to handle dbus and also dm events (or polling)
    // so we can extend/reshape/delay/whatever in a timely fashion
    for _ in tree.run(&c, c.iter(1000)) {

    }

    Ok(())
}

fn main() {

    let matches = App::new("froyo")
        .version(&crate_version!())
        .author("Andy Grover <andy@groveronline.com>")
        .about("Drobo + Free + YOLO")
        .arg(Arg::with_name("debug")
             .short("d")
             .long("debug")
             .help("Print additional output for debugging")
             )
        .subcommand(SubCommand::with_name("list")
                    .about("List all froyodevs")
                    .arg(Arg::with_name("long")
                         .short("l")
                         .long("long")
                         .help("Use a long listing format")
                         )
                    )
        .subcommand(SubCommand::with_name("status")
                    .about("Get the status of a single froyodev")
                    .arg(Arg::with_name("froyodevname")
                         .required(true)
                         .help("Froyodev to get info on")
                         .index(1)
                         )
                    )
        .subcommand(SubCommand::with_name("add")
                    .about("Add one or more additional block devices to a froyodev")
                    .arg(Arg::with_name("froyodevname")
                         .help("Froyodev to add the device to")
                         .required(true)
                         .index(1)
                         )
                    .arg(Arg::with_name("devices")
                         .help("device(s) to add")
                         .multiple(true)
                         .required(true)
                         .index(2)
                         )
                    )
        .subcommand(SubCommand::with_name("remove")
                    .about("Remove a block device from a froyodev")
                    .arg(Arg::with_name("froyodevname")
                         .help("Froyodev to remove the device from")
                         .required(true)
                         .index(1)
                         )
                    .arg(Arg::with_name("devices")
                         .help("Block device(s) to remove")
                         .multiple(true)
                         .required(true)
                         .index(2)
                         )
                    )
        .subcommand(SubCommand::with_name("create")
                    .about("Create a new froyodev")
                    .arg(Arg::with_name("force")
                         .short("f")
                         .long("force")
                         .help("Force")
                         )
                    .arg(Arg::with_name("froyodevname")
                         .help("Name of the new froyodev")
                         .required(true)
                         .index(1)
                         )
                    .arg(Arg::with_name("devices")
                         .help("Initial block device(s) to use")
                         .multiple(true)
                         .required(true)
                         .index(2)
                         )
                    )
        .subcommand(SubCommand::with_name("dev")
                    .about("Developer/debug commands")
                    .subcommand(SubCommand::with_name("dump_meta")
                                .about("Output the JSON metadata for a froyodev")
                                .arg(Arg::with_name("froyodevname")
                                     .help("Name of the froyodev")
                                     .required(true)
                                     .index(1)
                                     )
                                )
                    .subcommand(SubCommand::with_name("dbus_server")
                                .about("Serve the Froyo DBus API")
                                )
                    )
        .get_matches();

    if matches.is_present("debug") {
        // must use unsafe to change a mut static, sigh
        unsafe { debug = true };
    }

    let r = match matches.subcommand() {
        ("list", Some(matches)) => list(matches),
        ("status", Some(matches)) => status(matches),
        ("add", Some(matches)) => add(matches),
        ("remove", Some(matches)) => remove(matches),
        ("create", Some(matches)) => create(matches),
        ("dev", Some(matches)) => match matches.subcommand() {
            ("dump_meta", Some(matches)) => dump_meta(matches),
            ("dbus_server", Some(matches)) => dbus_server(matches),
            ("", None) => {
                println!("No command given, try \"help\"");
                Ok(())
            }
            _ => unreachable!(),
        },
        ("", None) => {
            println!("No command given, try \"help\"");
            Ok(())
        }
        _ => unreachable!(),
    };

    if let Err(r) = r {
        if let Err(e) = writeln!(&mut ::std::io::stderr(), "{}", r.description()) {
            panic!("Unable to write to stderr: {}", e)
        }
        exit(1);
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate serenity;
extern crate rand;
extern crate typemap;
extern crate stalch;
extern crate seximal;
extern crate hyper;
extern crate base64;

use std::io;
use stalch::{run_with_state, InOuter, State, Result as StalchResult};

use std::env;
use std::io::Read;
use std::result::Result as StdResult;
use typemap::Key;

use rand::Rng;
use rand::thread_rng;

use serenity::prelude::*;
use serenity::model::*;
use serenity::Result;
use serenity::utils;
use serenity::CACHE;

use serenity::framework::StandardFramework;

const PREFIX: &str = "f]";
const WESTMANN: UserId = UserId(229154015626264577);
const FALCH: UserId = UserId(165877785544491008);
const MEMES: ChannelId = ChannelId(306454829738491904);
const FALCHATS: GuildId = GuildId(189120762659995648);

command!(info(_ctx, msg, _args) {
    msg.channel_id.send_message(|cm| {
        cm.embed(|e| {
            e.title("falchbot")
             .colour(utils::Colour::blue())
             .description("(c) LFalch.com 2018")
             .footer(|f| f.text(serenity::constants::USER_AGENT))
        })
    }).unwrap();
});

command!(setgame(ctx, msg, args) {
    if msg.author.id == FALCH {
        ctx.set_game(Game::playing(&args.join(" ")));
    } else {
        msg.reply("Unauthorised")?;
    }
});

command!(seticon(_ctx, msg, args) {
    let s = args.join("/");

    if msg.author.id == FALCH {
        let img = {
            let client = hyper::Client::new();
            let mut resp = client.get(&format!("http://dev.lfalch.com/{}.png", s)).send()?;
            if !resp.status.is_success() {
                msg.reply("No success")?;
                return Ok(());
            }

            let mut v = Vec::new();

            resp.read_to_end(&mut v)?;

            let b64 = base64::encode(&v);
            let ext = "png";

            format!("data:image/{};base64,{}", ext, b64)
        };

        FALCHATS.edit(|e| e.icon(Some(&img)))?;
    } else {
        msg.reply("Unauthorised")?;
    }
});

command!(rpn(_ctx, msg, args) {
    match calculate(&*args) {
        Ok(r) => msg.reply(&format!("Result: {}", r)),
        Err(e) => msg.reply(&format!("Error: {:?}", e))
    }?;
});

command!(stalch(_ctx, msg, args) {
    match stalch_run(args.join(" ") + "\n") {
        Ok((r, s)) => {
            if r.is_empty() {
                msg.reply(&format!("Stack:\n```\n{}\n```", s))
            } else {
                msg.reply(&format!("Output:\n```\n{}\n```", r))
            }
        }
        Err(e) => msg.reply(&format!("Error: {:?}", e))
    }?;
});

command!(seximal(_ctx, msg, args) {
    let s = args.join("");
    match seximal::to_seximal_words(&s) {
        Ok(ref s) => msg.reply(s),
        Err(_) => msg.reply("Malformed number")
    }?;
});

const CSGO_MSGS: [&str; 6] = [
    "Vi varmer op med en comp!",
    "Jeg er på!",
    "Jeg er mere til Call of Duty ..",
    "Сука блядь!",
    "-skyder en bot for at få dens Bizon-",
    "Mongoskrald!"
];

const BEARTOOTH: [&str; 3] = [
    "I’m not useless! I’m just the king of excuses!",
    "One life and one decision! Make sure it ends with you still living!",
    "Lorteskat på T-shirts."
];

const RESPONSES: [&str; 4] = [
    "Undskyld, kan ikke snakke lige nu :(",
    "Hey, kan jeg ringe igen senere?",
    "Hva' så, din noob!? :P",
    "Ad, hvem er du?"
];

const REDALERT: [&str; 4] = [
    "Your base is under a salt!",
    "Det gamle lortespil?",
    "Jeg er mere til CSGO.",
    "\"Mine depleted\" ..."
];

struct BotUser;

impl Key for BotUser {
    type Value = String;
}

struct Handler;

fn main() {
    println!("{} in {}", WESTMANN, MEMES);

    let token = env::var("DISCORD_TOKEN")
        .expect("Expected a token in the environment");
    let mut client = Client::new(&token, Handler);

    client.with_framework(StandardFramework::new()
        .configure(|c| c.prefix(PREFIX))
        .command("ping", |c| c.exec_str("Pong!"))
        .on("info", info)
        .on("setgame", setgame)
        .on("rpn", rpn)
        .on("stalch", stalch)
        .on("seximal", seximal)
        .on("seticon", seticon)
    );

    {
        let mut data = client.data.lock();
        data.insert::<BotUser>(String::default());
    }

    if let Err(why) = client.start() {
        println!("Client error: {:?}", why);
    }
}

macro_rules! joke {
    ($s:expr; $($trigger:expr),+; $bl:block) => (
        if $($s.contains($trigger))||* $bl
    );
    ($s:expr, $channel_id:expr; $($trigger:expr),+;; $joke:expr) => (
        joke!($s; $($trigger),*; {
            $channel_id.say($joke).unwrap();
        })
    );
    ($s:expr, $channel_id:expr; $($trigger:expr),+; $jokes:expr) => (
        joke!($s; $($trigger),*; {
            send_random($channel_id, &$jokes).unwrap();
        })
    );
}

impl EventHandler for Handler {
    fn on_ready(&self, ctx: Context, ready: Ready) {
        println!("{} is connected!", ready.user.name);
        println!("Guilds:");
        for name in ready.guilds.iter().map(|g| g.id().get().unwrap().name) {
            println!("    {}", name);
        }
        {
            let mut data = ctx.data.lock();
            *data.get_mut::<BotUser>().unwrap() = ready.user.tag();
        }
    }

    fn on_message(&self, ctx: Context, msg: Message) {
        if msg.author.bot {
            return
        }
        eprintln!("{} in {}: image: {}", msg.channel_id.0, msg.author.id.0, msg.attachments.iter().any(|a| a.width.is_some()));
        if msg.channel_id == MEMES && msg.author.id == WESTMANN && msg.attachments.iter().any(|a| a.width.is_some()) {
            msg.channel_id.say("Den er gammel!").unwrap();
        }
        let s: String = msg.content.chars()
        .filter(|c| c.is_alphanumeric())
        .flat_map(|c|c.to_lowercase())
        .collect();

        joke!(s, msg.channel_id; "css", "source";; "Hvor er mine skins!?");
        joke!(s, msg.channel_id; "csgo", "counterstrike", "globaloffensive"; CSGO_MSGS);
        joke!(s, msg.channel_id; "mc", "minecraft";; "MINECRAFT!");
        joke!(s, msg.channel_id; "beartooth"; BEARTOOTH);
        joke!(s, msg.channel_id; "rep";; "Rep mig!");
        joke!(s, msg.channel_id; "ftl";; "Zoltan shield OP");
        joke!(s, msg.channel_id; "bindingofisaac";; "Mom OP");
        joke!(s, msg.channel_id; "meme";; "krydrede migmig'er");
        joke!(s, msg.channel_id; "gunsoficarus";; "Spillere online: 85");
        joke!(s, msg.channel_id; "doom";; "Rip and tear!");
        joke!(s, msg.channel_id; "dyinglight";; "Det dér Left 4 Dead-spil?");
        joke!(s, msg.channel_id; "report";; "ReviewBrah");
        joke!(s; "english"; {
            msg.channel_id.send_message(|cm| {
                cm.embed(|e| {
                    e.image("http://dev.lfalch.com/english.jpg")
                })
            }).unwrap();
        });
        joke!(s, msg.channel_id; "warthunder", "wt", "thunder", "tankspil";; "Jeg hader World of Tanks!");
        joke!(s, msg.channel_id; "ra3", "redalert"; REDALERT);
        joke!(s, msg.channel_id; "rusland", "russia", "росси", "russisk",
        "russian", "русск", "russer";; "Communism is the ultimate goal of socialism.");

        let user = {
            ctx.data.lock().get::<BotUser>().unwrap().clone()
        };
        if msg.mentions.iter().map(|u| u.tag()).any(|u| u == user) {
            send_random(msg.channel_id, &RESPONSES).unwrap();
        }
    }
}

fn send_random(chl: ChannelId, list: &[&str]) -> Result<Message> {
    let i = thread_rng().gen_range(0, list.len());
    chl.say(list[i])
}

#[derive(Debug, Copy, Clone)]
pub enum RpnError<'a> {
    StackTooSmall,
    UnknownOperator(&'a str)
}

use RpnError::*;

pub fn calculate<'a, T: IntoIterator<Item=&'a String>>(operations: T) -> StdResult<f64, RpnError<'a>> {
    let mut stack = Vec::new();

    for operation in operations {
        if let Some(d) = operation.parse::<f64>().ok() {
            stack.push(d)
        }else{
            calc(operation, &mut stack)?
        }
    }

    stack.pop().ok_or(StackTooSmall)
}

fn calc<'a>(op: &'a str, stack: &mut Vec<f64>) -> StdResult<(), RpnError<'a>>{
    let res = match (stack.pop(), stack.pop()){
        (Some(op1), Some(op2)) => match op{
            "+"|"add" => op2 + op1,
            "-"|"sub" => op2 - op1,
            "/"|"div" => op2 / op1,
            "*"|"mul" => op2 * op1,
            "^"|"pow" => op2.powf(op1),
            "log" => op2.log(op1),
            "hypot" => op2.hypot(op1),
            "%"|"rem" => op2 % op1,
            "|"|"or" => (op2 as i64 | op1 as i64) as f64,
            "&"|"and" => (op2 as i64 & op1 as i64) as f64,
            "xor" => (op2  as i64 ^ op1 as i64) as f64,
            _ => return Err(UnknownOperator(op))
        },
        _ => return Err(StackTooSmall)
    };
    Ok(stack.push(res))
}

fn stalch_run<'a>(s: String) -> StalchResult<(String, String)> {
    let mut state = State::new();
    let mut io = InOuter::new(Vec::new(), io::repeat(b'\n'));

    run_with_state(s.as_bytes(), &mut state, &mut io)?;

    let (output, _) = io.extract();

    let s = String::from_utf8(output).map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;

    Ok((s, format!("{:?}", state.stack())))
}
<commit_msg>Change prefix to ']'<commit_after>#[macro_use]
extern crate serenity;
extern crate rand;
extern crate typemap;
extern crate stalch;
extern crate seximal;
extern crate hyper;
extern crate base64;

use std::io;
use stalch::{run_with_state, InOuter, State, Result as StalchResult};

use std::env;
use std::io::Read;
use std::result::Result as StdResult;
use typemap::Key;

use rand::Rng;
use rand::thread_rng;

use serenity::prelude::*;
use serenity::model::*;
use serenity::Result;
use serenity::utils;
use serenity::CACHE;

use serenity::framework::StandardFramework;

const PREFIX: &str = "]";
const WESTMANN: UserId = UserId(229154015626264577);
const FALCH: UserId = UserId(165877785544491008);
const MEMES: ChannelId = ChannelId(306454829738491904);
const FALCHATS: GuildId = GuildId(189120762659995648);

command!(info(_ctx, msg, _args) {
    msg.channel_id.send_message(|cm| {
        cm.embed(|e| {
            e.title("falchbot")
             .colour(utils::Colour::blue())
             .description("(c) LFalch.com 2018")
             .footer(|f| f.text(serenity::constants::USER_AGENT))
        })
    }).unwrap();
});

command!(setgame(ctx, msg, args) {
    if msg.author.id == FALCH {
        ctx.set_game(Game::playing(&args.join(" ")));
    } else {
        msg.reply("Unauthorised")?;
    }
});

command!(seticon(_ctx, msg, args) {
    let s = args.join("/");

    if msg.author.id == FALCH {
        let img = {
            let client = hyper::Client::new();
            let mut resp = client.get(&format!("http://dev.lfalch.com/{}.png", s)).send()?;
            if !resp.status.is_success() {
                msg.reply("No success")?;
                return Ok(());
            }

            let mut v = Vec::new();

            resp.read_to_end(&mut v)?;

            let b64 = base64::encode(&v);
            let ext = "png";

            format!("data:image/{};base64,{}", ext, b64)
        };

        FALCHATS.edit(|e| e.icon(Some(&img)))?;
    } else {
        msg.reply("Unauthorised")?;
    }
});

command!(rpn(_ctx, msg, args) {
    match calculate(&*args) {
        Ok(r) => msg.reply(&format!("Result: {}", r)),
        Err(e) => msg.reply(&format!("Error: {:?}", e))
    }?;
});

command!(stalch(_ctx, msg, args) {
    match stalch_run(args.join(" ") + "\n") {
        Ok((r, s)) => {
            if r.is_empty() {
                msg.reply(&format!("Stack:\n```\n{}\n```", s))
            } else {
                msg.reply(&format!("Output:\n```\n{}\n```", r))
            }
        }
        Err(e) => msg.reply(&format!("Error: {:?}", e))
    }?;
});

command!(seximal(_ctx, msg, args) {
    let s = args.join("");
    match seximal::to_seximal_words(&s) {
        Ok(ref s) => msg.reply(s),
        Err(_) => msg.reply("Malformed number")
    }?;
});

const CSGO_MSGS: [&str; 6] = [
    "Vi varmer op med en comp!",
    "Jeg er på!",
    "Jeg er mere til Call of Duty ..",
    "Сука блядь!",
    "-skyder en bot for at få dens Bizon-",
    "Mongoskrald!"
];

const BEARTOOTH: [&str; 3] = [
    "I’m not useless! I’m just the king of excuses!",
    "One life and one decision! Make sure it ends with you still living!",
    "Lorteskat på T-shirts."
];

const RESPONSES: [&str; 4] = [
    "Undskyld, kan ikke snakke lige nu :(",
    "Hey, kan jeg ringe igen senere?",
    "Hva' så, din noob!? :P",
    "Ad, hvem er du?"
];

const REDALERT: [&str; 4] = [
    "Your base is under a salt!",
    "Det gamle lortespil?",
    "Jeg er mere til CSGO.",
    "\"Mine depleted\" ..."
];

struct BotUser;

impl Key for BotUser {
    type Value = String;
}

struct Handler;

fn main() {
    println!("{} in {}", WESTMANN, MEMES);

    let token = env::var("DISCORD_TOKEN")
        .expect("Expected a token in the environment");
    let mut client = Client::new(&token, Handler);

    client.with_framework(StandardFramework::new()
        .configure(|c| c.prefix(PREFIX))
        .command("ping", |c| c.exec_str("Pong!"))
        .on("info", info)
        .on("setgame", setgame)
        .on("rpn", rpn)
        .on("stalch", stalch)
        .on("seximal", seximal)
        .on("seticon", seticon)
    );

    {
        let mut data = client.data.lock();
        data.insert::<BotUser>(String::default());
    }

    if let Err(why) = client.start() {
        println!("Client error: {:?}", why);
    }
}

macro_rules! joke {
    ($s:expr; $($trigger:expr),+; $bl:block) => (
        if $($s.contains($trigger))||* $bl
    );
    ($s:expr, $channel_id:expr; $($trigger:expr),+;; $joke:expr) => (
        joke!($s; $($trigger),*; {
            $channel_id.say($joke).unwrap();
        })
    );
    ($s:expr, $channel_id:expr; $($trigger:expr),+; $jokes:expr) => (
        joke!($s; $($trigger),*; {
            send_random($channel_id, &$jokes).unwrap();
        })
    );
}

impl EventHandler for Handler {
    fn on_ready(&self, ctx: Context, ready: Ready) {
        println!("{} is connected!", ready.user.name);
        println!("Guilds:");
        for name in ready.guilds.iter().map(|g| g.id().get().unwrap().name) {
            println!("    {}", name);
        }
        {
            let mut data = ctx.data.lock();
            *data.get_mut::<BotUser>().unwrap() = ready.user.tag();
        }
    }

    fn on_message(&self, ctx: Context, msg: Message) {
        if msg.author.bot {
            return
        }
        eprintln!("{} in {}: image: {}", msg.channel_id.0, msg.author.id.0, msg.attachments.iter().any(|a| a.width.is_some()));
        if msg.channel_id == MEMES && msg.author.id == WESTMANN && msg.attachments.iter().any(|a| a.width.is_some()) {
            msg.channel_id.say("Den er gammel!").unwrap();
        }
        let s: String = msg.content.chars()
        .filter(|c| c.is_alphanumeric())
        .flat_map(|c|c.to_lowercase())
        .collect();

        joke!(s, msg.channel_id; "css", "source";; "Hvor er mine skins!?");
        joke!(s, msg.channel_id; "csgo", "counterstrike", "globaloffensive"; CSGO_MSGS);
        joke!(s, msg.channel_id; "mc", "minecraft";; "MINECRAFT!");
        joke!(s, msg.channel_id; "beartooth"; BEARTOOTH);
        joke!(s, msg.channel_id; "rep";; "Rep mig!");
        joke!(s, msg.channel_id; "ftl";; "Zoltan shield OP");
        joke!(s, msg.channel_id; "bindingofisaac";; "Mom OP");
        joke!(s, msg.channel_id; "meme";; "krydrede migmig'er");
        joke!(s, msg.channel_id; "gunsoficarus";; "Spillere online: 85");
        joke!(s, msg.channel_id; "doom";; "Rip and tear!");
        joke!(s, msg.channel_id; "dyinglight";; "Det dér Left 4 Dead-spil?");
        joke!(s, msg.channel_id; "report";; "ReviewBrah");
        joke!(s; "english"; {
            msg.channel_id.send_message(|cm| {
                cm.embed(|e| {
                    e.image("http://dev.lfalch.com/english.jpg")
                })
            }).unwrap();
        });
        joke!(s, msg.channel_id; "warthunder", "wt", "thunder", "tankspil";; "Jeg hader World of Tanks!");
        joke!(s, msg.channel_id; "ra3", "redalert"; REDALERT);
        joke!(s, msg.channel_id; "rusland", "russia", "росси", "russisk",
        "russian", "русск", "russer";; "Communism is the ultimate goal of socialism.");

        let user = {
            ctx.data.lock().get::<BotUser>().unwrap().clone()
        };
        if msg.mentions.iter().map(|u| u.tag()).any(|u| u == user) {
            send_random(msg.channel_id, &RESPONSES).unwrap();
        }
    }
}

fn send_random(chl: ChannelId, list: &[&str]) -> Result<Message> {
    let i = thread_rng().gen_range(0, list.len());
    chl.say(list[i])
}

#[derive(Debug, Copy, Clone)]
pub enum RpnError<'a> {
    StackTooSmall,
    UnknownOperator(&'a str)
}

use RpnError::*;

pub fn calculate<'a, T: IntoIterator<Item=&'a String>>(operations: T) -> StdResult<f64, RpnError<'a>> {
    let mut stack = Vec::new();

    for operation in operations {
        if let Some(d) = operation.parse::<f64>().ok() {
            stack.push(d)
        }else{
            calc(operation, &mut stack)?
        }
    }

    stack.pop().ok_or(StackTooSmall)
}

fn calc<'a>(op: &'a str, stack: &mut Vec<f64>) -> StdResult<(), RpnError<'a>>{
    let res = match (stack.pop(), stack.pop()){
        (Some(op1), Some(op2)) => match op{
            "+"|"add" => op2 + op1,
            "-"|"sub" => op2 - op1,
            "/"|"div" => op2 / op1,
            "*"|"mul" => op2 * op1,
            "^"|"pow" => op2.powf(op1),
            "log" => op2.log(op1),
            "hypot" => op2.hypot(op1),
            "%"|"rem" => op2 % op1,
            "|"|"or" => (op2 as i64 | op1 as i64) as f64,
            "&"|"and" => (op2 as i64 & op1 as i64) as f64,
            "xor" => (op2  as i64 ^ op1 as i64) as f64,
            _ => return Err(UnknownOperator(op))
        },
        _ => return Err(StackTooSmall)
    };
    Ok(stack.push(res))
}

fn stalch_run<'a>(s: String) -> StalchResult<(String, String)> {
    let mut state = State::new();
    let mut io = InOuter::new(Vec::new(), io::repeat(b'\n'));

    run_with_state(s.as_bytes(), &mut state, &mut io)?;

    let (output, _) = io.extract();

    let s = String::from_utf8(output).map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;

    Ok((s, format!("{:?}", state.stack())))
}
<|endoftext|>


<commit_before>extern crate env_logger;
extern crate getopts;
extern crate hyper;
#[macro_use] extern crate libotaplus;

use getopts::Options;
use hyper::Url;
use std::env;

use libotaplus::{config, read_interpret};
use libotaplus::config::Config;
use libotaplus::read_interpret::ReplEnv;
use libotaplus::ota_plus::{Client as OtaClient};
use libotaplus::auth_plus::{Client as AuthClient};
use libotaplus::package_manager::{PackageManager, Dpkg};

fn main() {

    env_logger::init().unwrap();

    let config = build_config();
    let pkg_manager = Dpkg::new();

    let _ = AuthClient::new(hyper::Client::new(), config.auth.clone())
        .authenticate()
        .map(|token| OtaClient::new(hyper::Client::new(), token, config.ota.clone()))
        .and_then(|client| pkg_manager.installed_packages()
                  .and_then(|pkgs| client.post_packages(pkgs)))
        .map(|_| println!("Installed packages were posted successfully."))
        .map_err(|err| println!("{}", err));

    if config.test.looping {
        read_interpret::read_interpret_loop(ReplEnv::new(pkg_manager.clone()));
    }

}

fn build_config() -> Config {

    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();

    let mut opts = Options::new();
    opts.optflag("h", "help",
                 "print this help menu");
    opts.optopt("", "config",
                "change config path", "PATH");
    opts.optopt("", "auth-server",
                "change the auth server URL", "URL");
    opts.optopt("", "auth-client-id",
                "change auth client id", "ID");
    opts.optopt("", "auth-secret",
                "change auth secret", "SECRET");
    opts.optopt("", "ota-server",
                "change ota server URL", "URL");
    opts.optopt("", "ota-vin",
                "change ota vin", "VIN");
    opts.optflag("", "test-looping",
                 "enable read-interpret test loop");

    let matches = opts.parse(&args[1..])
        .unwrap_or_else(|err| panic!(err.to_string()));

    if matches.opt_present("h") {
        let brief = format!("Usage: {} [options]", program);
        exit!("{}", opts.usage(&brief));
    }

    let mut config_file = env::var("OTA_PLUS_CLIENT_CFG")
        .unwrap_or("/opt/ats/ota/etc/ota.toml".to_string());

    if let Some(path) = matches.opt_str("config") {
        config_file = path;
    }

    let mut config = config::load_config(&config_file)
        .unwrap_or_else(|err| exit!("{}", err));

    if let Some(s) = matches.opt_str("auth-server") {
        match Url::parse(&s) {
            Ok(url)  => config.auth.server = url,
            Err(err) => exit!("Invalid auth-server URL: {}", err)
        }
    }

    if let Some(client_id) = matches.opt_str("auth-client-id") {
        config.auth.client_id = client_id;
    }

    if let Some(secret) = matches.opt_str("auth-secret") {
        config.auth.secret = secret;
    }

    if let Some(s) = matches.opt_str("ota-server") {
        match Url::parse(&s) {
            Ok(url)  => config.ota.server = url,
            Err(err) => exit!("Invalid ota-server URL: {}", err)
        }
    }

    if let Some(vin) = matches.opt_str("ota-vin") {
        config.ota.vin = vin;
    }

    if matches.opt_present("test-looping") {
        config.test.looping = true;
    }

    return config
}
<commit_msg>Make it possible to issue `cargo test` and have tests succeed without having to do `cargo build` first.<commit_after>extern crate env_logger;
extern crate getopts;
extern crate hyper;
#[macro_use] extern crate libotaplus;

use getopts::Options;
use hyper::Url;
use std::env;

use libotaplus::{config, read_interpret};
use libotaplus::config::Config;
use libotaplus::read_interpret::ReplEnv;
use libotaplus::ota_plus::{Client as OtaClient};
use libotaplus::auth_plus::{Client as AuthClient};
use libotaplus::package_manager::{PackageManager, Dpkg};

fn main() {

    env_logger::init().unwrap();

    let config = build_config();
    let pkg_manager = Dpkg::new();

    let _ = AuthClient::new(hyper::Client::new(), config.auth.clone())
        .authenticate()
        .map(|token| OtaClient::new(hyper::Client::new(), token, config.ota.clone()))
        .and_then(|client| pkg_manager.installed_packages()
                  .and_then(|pkgs| client.post_packages(pkgs)))
        .map(|_| println!("Installed packages were posted successfully."))
        .map_err(|err| println!("{}", err));

    if config.test.looping {
        read_interpret::read_interpret_loop(ReplEnv::new(pkg_manager.clone()));
    }

}

fn build_config() -> Config {

    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();

    let mut opts = Options::new();
    opts.optflag("h", "help",
                 "print this help menu");
    opts.optopt("", "config",
                "change config path", "PATH");
    opts.optopt("", "auth-server",
                "change the auth server URL", "URL");
    opts.optopt("", "auth-client-id",
                "change auth client id", "ID");
    opts.optopt("", "auth-secret",
                "change auth secret", "SECRET");
    opts.optopt("", "ota-server",
                "change ota server URL", "URL");
    opts.optopt("", "ota-vin",
                "change ota vin", "VIN");
    opts.optflag("", "test-looping",
                 "enable read-interpret test loop");

    let matches = opts.parse(&args[1..])
        .unwrap_or_else(|err| panic!(err.to_string()));

    if matches.opt_present("h") {
        let brief = format!("Usage: {} [options]", program);
        exit!("{}", opts.usage(&brief));
    }

    let mut config_file = env::var("OTA_PLUS_CLIENT_CFG")
        .unwrap_or("/opt/ats/ota/etc/ota.toml".to_string());

    if let Some(path) = matches.opt_str("config") {
        config_file = path;
    }

    let mut config = config::load_config(&config_file)
        .unwrap_or_else(|err| exit!("{}", err));

    if let Some(s) = matches.opt_str("auth-server") {
        match Url::parse(&s) {
            Ok(url)  => config.auth.server = url,
            Err(err) => exit!("Invalid auth-server URL: {}", err)
        }
    }

    if let Some(client_id) = matches.opt_str("auth-client-id") {
        config.auth.client_id = client_id;
    }

    if let Some(secret) = matches.opt_str("auth-secret") {
        config.auth.secret = secret;
    }

    if let Some(s) = matches.opt_str("ota-server") {
        match Url::parse(&s) {
            Ok(url)  => config.ota.server = url,
            Err(err) => exit!("Invalid ota-server URL: {}", err)
        }
    }

    if let Some(vin) = matches.opt_str("ota-vin") {
        config.ota.vin = vin;
    }

    if matches.opt_present("test-looping") {
        config.test.looping = true;
    }

    return config
}

// Hack to build a binary with a predictable path for use in tests/. We
// can remove this when https://github.com/rust-lang/cargo/issues/1924
// is resolved.
#[test]
fn build_binary() {
    let output = std::process::Command::new("cargo")
        .arg("build")
        .output()
        .unwrap_or_else(|e| panic!("failed to execute child: {}", e));

    assert!(output.status.success())
}
<|endoftext|>


<commit_before>extern crate iron;
extern crate router;
extern crate mount;
extern crate staticfile;

use iron::prelude::*;
use iron::status;
use router::Router;
use staticfile::Static;
use mount::Mount;
use std::path::Path;

fn main() {
	// the router (for RESTfull actions)
	let mut router = Router::new();

	router.get("/hello",hello_world);
	router.post("/acceptsriddle",accept_riddle);
	//router.get("/randomriddle",random_riddle);
	//router.post("/voteriddle",vote_riddle);
	//router.post("/interactdragon",interact_dragon);

	fn hello_world(_: &mut Request) -> IronResult<Response> {
		Ok(Response::with((status::Ok, "Hello World!")))
	}

	fn accept_riddle(_: &mut Request) -> IronResult<Response> {
		Ok(Response::with((status::Ok, "Riddle accepted!")))
	}

	// the mounter for static files
	let mut mount = Mount::new();
	mount
		.mount("/",Static::new(Path::new("../../static/index.html")))
		.mount("/api/",router)
		.mount("/react/",Static::new(Path::new("../../bower_components/react")));
	Iron::new(mount).http("192.168.0.238:3000").unwrap();
	println!("On 3000");
}
<commit_msg>serve react<commit_after>extern crate iron;
extern crate router;
extern crate mount;
extern crate staticfile;

use iron::prelude::*;
use iron::status;
use router::Router;
use staticfile::Static;
use mount::Mount;
use std::path::Path;
use std::env;

fn main() {
	// the router (for RESTfull actions)
	let mut router = Router::new();

	router.get("/hello",hello_world);
	router.post("/acceptsriddle",accept_riddle);
	//router.get("/randomriddle",random_riddle);
	//router.post("/voteriddle",vote_riddle);
	//router.post("/interactdragon",interact_dragon);

	fn hello_world(_: &mut Request) -> IronResult<Response> {
		Ok(Response::with((status::Ok, "Hello World!")))
	}

	fn accept_riddle(_: &mut Request) -> IronResult<Response> {
		Ok(Response::with((status::Ok, "Riddle accepted!")))
	}

	// the mounter for static files
	let mut mount = Mount::new();
	mount
		.mount("/",Static::new(Path::new("static")))
		.mount("/api/",router)
		.mount("/react/",Static::new(Path::new("bower_components/react")));
	let indexexists = Path::new("static/index.html").exists().to_string();
	println!("{}",indexexists);
	let p = env::current_dir().unwrap();
	println!("{}",p.display());
	Iron::new(mount).http("192.168.0.238:3000").unwrap();
	println!("On 3000");
}
<|endoftext|>


<commit_before>use std::env;

fn main() {
    let args = env::args().skip(1).collect::<Vec<String>>();

    if args.is_empty() {
        print_usage();
        return
    }

    match args[0].as_ref() {
        "help"    => print_usage(),
        "init"    => initialize(),
        "start"   => register_with_cron(),
        "end"     => unregister_cron(),
        "set"     => set_params(),
        "clean"   => clean(),
        "destroy" => destroy(),
        _         => print_usage(),
    }
}

fn print_usage() {
    let full_path_to_bin = env::current_exe().unwrap();
    let bin_name         = full_path_to_bin.file_name()
        .unwrap()
        .to_str()
        .unwrap();
    println!(
"Usage:
    {} <command>

Commands:
    help    # Print this message.
    init    # Register current directory.
    start   # Start \"{}\"
    end     # End \"{}\"
    set     # Set parameters.
    clean   # Clean current directory.
    destroy # Destroy \"{}\"",
        bin_name,
        bin_name,
        bin_name,
        bin_name,
    );
}

fn initialize() {
    println!("initialize");
}

fn register_with_cron() {
    println!("register");
}

fn unregister_cron() {
    println!("unregister");
}

fn set_params() {
    println!("set parameters");
}

fn clean() {
    println!("clean");
}

fn destroy() {
    println!("destroy");
}
<commit_msg>Replace positions<commit_after>use std::env;

fn main() {
    let args = env::args().skip(1).collect::<Vec<String>>();

    if args.is_empty() {
        print_usage();
        return
    }

    match args[0].as_ref() {
        "help"    => print_usage(),
        "init"    => initialize(),
        "set"     => set_params(),
        "clean"   => clean(),
        "start"   => register_with_cron(),
        "end"     => unregister_cron(),
        "destroy" => destroy(),
        _         => print_usage(),
    }
}

fn print_usage() {
    let full_path_to_bin = env::current_exe().unwrap();
    let bin_name         = full_path_to_bin.file_name()
        .unwrap()
        .to_str()
        .unwrap();
    println!(
"Usage:
    {} <command>

Commands:
    help    # Print this message.
    init    # Register current directory.
    start   # Start \"{}\"
    end     # End \"{}\"
    set     # Set parameters.
    clean   # Clean current directory.
    destroy # Destroy \"{}\"",
        bin_name,
        bin_name,
        bin_name,
        bin_name,
    );
}

fn initialize() {
    println!("initialize");
}

fn set_params() {
    println!("set parameters");
}

fn clean() {
    println!("clean");
}

fn register_with_cron() {
    println!("register");
}

fn unregister_cron() {
    println!("unregister");
}

fn destroy() {
    println!("destroy");
}
<|endoftext|>


<commit_before>extern crate libc;

use libc::{c_uint, c_uchar, c_int};
use std::io;

// used in Termios struct
pub const NCCS:uint = 32;

// stdin, stdout, stderr have standard file descriptors
pub const STDIN:c_int = 0;

// constants for control sequences is useful
pub const EOF:char = '\u{4}';
pub const DEL:char = '\u{7f}';

// select termios constants that we use
pub const ICANON:c_uint   = 2;
pub const ECHO:c_uint     = 8;
pub const TCSANOW:c_int   = 0;
pub const TCSADRAIN:c_int = 1;
pub const TCSAFLUSH:c_int = 2;

// types used in Termios struct
#[allow(non_camel_case_types)]
pub type cc_t = c_uchar;
#[allow(non_camel_case_types)]
pub type speed_t = c_uint;
#[allow(non_camel_case_types)]
pub type tcflag_t = c_uint;

#[repr(C)]
#[deriving(Copy)]
#[deriving(Clone)]
pub struct Termios {
    c_iflag: tcflag_t,
    c_oflag: tcflag_t,
    c_cflag: tcflag_t,
    c_lflag: tcflag_t,
    c_line: cc_t,
    c_cc: [c_uchar, ..NCCS],
    c_ispeed: speed_t,
    c_ospeed: speed_t,
}

impl Termios {
    pub fn new() -> Termios {
        Termios {
            c_cc: [0, ..NCCS],
            c_cflag: 0,
            c_iflag: 0,
            c_ispeed: 0,
            c_lflag: 0,
            c_line: 0,
            c_oflag: 0,
            c_ospeed: 0,
        }
    }

    pub fn get_from(&mut self, fd:c_int) -> bool {
        unsafe {
            return tcgetattr(fd, self) == 0;
        }
    }

    pub fn get(&mut self) -> bool {
        self.get_from(STDIN)
    }

    pub fn set_to(&self, fd:c_int) -> bool {
        unsafe {
            return tcsetattr(fd, TCSANOW, self) == 0;
        }
    }

    pub fn set(&self) -> bool {
        self.set_to(STDIN)
    }

    pub fn lenable(&mut self, flag:c_uint) {
        self.c_lflag |= flag;
    }

    pub fn ldisable(&mut self, flag:c_uint) {
        self.c_lflag &= !flag;
    }
}

#[link(name = "c")]
extern {
    pub fn tcgetattr(fd: c_int, termios: *mut Termios) -> c_int;
    pub fn tcsetattr(fd: c_int, optional_actions: c_int, termios: *const Termios) -> c_int;
}

fn empty_escape(esc:&mut Iterator<char>) -> String {
    let mut out = String::new();
    loop {
        match esc.next() {
            Some(c) => out.push(c),
            None => break
        }
    }
    return out;
}

fn main() {
    let mut tios = Termios::new();
    tios.get();
    let old_tios = tios.clone();
    // turn off canonical mode
    tios.ldisable(ICANON);
    // turn off echo mode
    tios.ldisable(ECHO);
    tios.set();
    let mut stdin = io::stdin();
    loop {
        match stdin.read_char() {
            Ok(EOF) => break,
            Ok(DEL) => {
                print!("{} {}", DEL, DEL);
            },
            Ok(c) => {
                print!("{}", empty_escape(&mut c.escape_default()))
            },
            Err(_) => {
                println!("Error: exiting");
                break;
            }
        }
    }
    // print so we know we've reached this code
    println!("Exiting");
    // restore old term state
    old_tios.set();
}
<commit_msg>Improve error handling<commit_after>extern crate libc;
extern crate term;

use libc::{c_uint, c_uchar, c_int};
use std::io;

// used in Termios struct
pub const NCCS:uint = 32;

// stdin, stdout, stderr have standard file descriptors
pub const STDIN:c_int = 0;

// constants for control sequences is useful
pub const EOF:char = '\u{4}';
pub const DEL:char = '\u{7f}';

// select termios constants that we use
pub const ICANON:c_uint   = 2;
pub const ECHO:c_uint     = 8;
pub const TCSANOW:c_int   = 0;
pub const TCSADRAIN:c_int = 1;
pub const TCSAFLUSH:c_int = 2;

// types used in Termios struct
#[allow(non_camel_case_types)]
pub type cc_t = c_uchar;
#[allow(non_camel_case_types)]
pub type speed_t = c_uint;
#[allow(non_camel_case_types)]
pub type tcflag_t = c_uint;

#[repr(C)]
#[deriving(Copy)]
#[deriving(Clone)]
pub struct Termios {
    c_iflag: tcflag_t,
    c_oflag: tcflag_t,
    c_cflag: tcflag_t,
    c_lflag: tcflag_t,
    c_line: cc_t,
    c_cc: [c_uchar, ..NCCS],
    c_ispeed: speed_t,
    c_ospeed: speed_t,
}

impl Termios {
    pub fn new() -> Termios {
        Termios {
            c_cc: [0, ..NCCS],
            c_cflag: 0,
            c_iflag: 0,
            c_ispeed: 0,
            c_lflag: 0,
            c_line: 0,
            c_oflag: 0,
            c_ospeed: 0,
        }
    }

    pub fn get_from(&mut self, fd:c_int) -> bool {
        unsafe {
            return tcgetattr(fd, self) == 0;
        }
    }

    pub fn get(&mut self) -> bool {
        self.get_from(STDIN)
    }

    pub fn set_to(&self, fd:c_int) -> bool {
        unsafe {
            return tcsetattr(fd, TCSANOW, self) == 0;
        }
    }

    pub fn set(&self) -> bool {
        self.set_to(STDIN)
    }

    pub fn lenable(&mut self, flag:c_uint) {
        self.c_lflag |= flag;
    }

    pub fn ldisable(&mut self, flag:c_uint) {
        self.c_lflag &= !flag;
    }
}

#[link(name = "c")]
extern {
    pub fn tcgetattr(fd: c_int, termios: *mut Termios) -> c_int;
    pub fn tcsetattr(fd: c_int, optional_actions: c_int, termios: *const Termios) -> c_int;
}

fn empty_escape(esc:&mut Iterator<char>) -> String {
    let mut out = String::new();
    loop {
        match esc.next() {
            Some(c) => out.push(c),
            None => break
        }
    }
    return out;
}

fn prepare_terminal() -> Termios {
    let mut tios = Termios::new();
    tios.get();
    let tios_clone = tios.clone();
    // turn off canonical mode
    tios.ldisable(ICANON);
    // turn off echo mode
    tios.ldisable(ECHO);
    // set the terminal mode
    if !tios.set() {
        io::stderr().write_line("Warning: Could not set terminal mode").unwrap_err();
    }
    // return the old terminal mode
    return tios_clone;
}

fn restore_terminal(tios:Termios) {
    if !tios.set() {
        io::stderr().write_line("Warning: Could not set terminal mode").unwrap_err();
    }
}

fn main() {
    let old_tios = prepare_terminal();
    let mut stdin = io::stdin();
    loop {
        match stdin.read_char() {
            Ok(EOF) => break,
            Ok(DEL) => {
                print!("{} {}", DEL, DEL);
            },
            Ok(c) => {
                print!("{}", empty_escape(&mut c.escape_default()))
            },
            Err(e) => {
                println!("Error: {}", e);
                break;
            }
        }
    }
    // print so we know we've reached this code
    println!("Exiting");
    // restore old term state
    restore_terminal(old_tios);
}
<|endoftext|>