<commit_before>//! Useful stuff for finding points in a line

use std::collections::HashSet;

use point::Point;

/// Find the points in a line between the current point and the one provided
///
/// # Example
///
/// ```
/// use std::collections::HashSet;
///
/// use hex_math::{line, Point};
///
/// let point: Point = Point::new(1, 2, 5);
/// let other: Point = Point::new(3, 4, 10);
/// let set: HashSet<Point> = line(&point, &other);
///
/// assert_eq!(set.len(), 5);
/// assert!(set.contains(&Point::new(1, 2, 5)));
/// assert!(set.contains(&Point::new(2, 2, 6)));
/// assert!(set.contains(&Point::new(2, 3, 8)));
/// assert!(set.contains(&Point::new(3, 3, 9)));
/// assert!(set.contains(&Point::new(3, 4, 10)));
/// ```
///
/// ```
/// use std::collections::HashSet;
///
/// use hex_math::{line, Point};
///
/// let point: Point = Point::new_2d(1, 2);
/// let other: Point = Point::new_2d(3, 4);
/// let set: HashSet<Point> = line(&point, &other);
///
/// assert_eq!(set.len(), 5);
/// assert!(set.contains(&Point::new_2d(1, 2)));
/// assert!(set.contains(&Point::new_2d(2, 2)));
/// assert!(set.contains(&Point::new_2d(2, 3)));
/// assert!(set.contains(&Point::new_2d(3, 3)));
/// assert!(set.contains(&Point::new_2d(3, 4)));
/// ```
pub fn line(point: &Point, other: &Point) -> HashSet<Point> {
  util::line(&point, &other, None, None)
}

/// Find the points within range in a line through two points
///
/// # Example
///
/// ```
/// use std::collections::HashSet;
///
/// use hex_math::{line_through, Point};
///
/// let point: Point = Point::new(1, 2, 5);
/// let other: Point = Point::new(2, 2, 6);
/// let set: HashSet<Point> = line_through(&point, &other, 3);
///
/// assert_eq!(set.len(), 4);
/// assert!(set.contains(&Point::new(1, 2, 5)));
/// assert!(set.contains(&Point::new(2, 2, 6)));
/// assert!(set.contains(&Point::new(3, 2, 7)));
/// assert!(set.contains(&Point::new(4, 2, 8)));
/// ```
///
/// ```
/// use std::collections::HashSet;
///
/// use hex_math::{line_through, Point};
///
/// let point: Point = Point::new_2d(1, 2);
/// let other: Point = Point::new_2d(2, 2);
/// let set: HashSet<Point> = line_through(&point, &other, 3);
///
/// assert_eq!(set.len(), 4);
/// assert!(set.contains(&Point::new_2d(1, 2)));
/// assert!(set.contains(&Point::new_2d(2, 2)));
/// assert!(set.contains(&Point::new_2d(3, 2)));
/// assert!(set.contains(&Point::new_2d(4, 2)));
/// ```
pub fn line_through(
  point: &Point,
  other: &Point,
  range: i32,
) -> HashSet<Point> {
  util::line(point, other, Some(range), None)
}

/// Find unblocked points in a line between two points
///
/// # Example
///
/// ```
/// use std::collections::HashSet;
///
/// use hex_math::{ray, Point};
///
/// let point: Point = Point::new(1, 2, 5);
/// let other: Point = Point::new(3, 4, 10);
/// let mut opaque: HashSet<Point> = HashSet::new();
///
/// opaque.insert(Point::new(3, 3, 9));
///
/// let set: HashSet<Point> = ray(&point, &other, &opaque);
///
/// assert_eq!(set.len(), 4);
/// assert!(set.contains(&Point::new(1, 2, 5)));
/// assert!(set.contains(&Point::new(2, 2, 6)));
/// assert!(set.contains(&Point::new(2, 3, 8)));
/// assert!(set.contains(&Point::new(3, 3, 9)));
/// ```
///
/// ```
/// use std::collections::HashSet;
///
/// use hex_math::{ray, Point};
///
/// let point: Point = Point::new_2d(1, 2);
/// let other: Point = Point::new_2d(3, 4);
/// let mut opaque: HashSet<Point> = HashSet::new();
///
/// opaque.insert(Point::new_2d(3, 3));
///
/// let set: HashSet<Point> = ray(&point, &other, &opaque);
///
/// assert_eq!(set.len(), 4);
/// assert!(set.contains(&Point::new_2d(1, 2)));
/// assert!(set.contains(&Point::new_2d(2, 2)));
/// assert!(set.contains(&Point::new_2d(2, 3)));
/// assert!(set.contains(&Point::new_2d(3, 3)));
/// ```
pub fn ray(
  point: &Point,
  other: &Point,
  opaque: &HashSet<Point>,
) -> HashSet<Point> {
  util::line(point, other, None, Some(opaque))
}

/// Find unblocked points within range in a line through two points
///
/// # Example
///
/// ```
/// use std::collections::HashSet;
///
/// use hex_math::{ray_through, Point};
///
/// let point: Point = Point::new(1, 2, 5);
/// let other: Point = Point::new(2, 2, 6);
/// let mut opaque: HashSet<Point> = HashSet::new();
///
/// opaque.insert(Point::new(3, 2, 7));
///
/// let set: HashSet<Point> = ray_through(&point, &other, 3, &opaque);
///
/// assert_eq!(set.len(), 3);
/// assert!(set.contains(&Point::new(1, 2, 5)));
/// assert!(set.contains(&Point::new(2, 2, 6)));
/// assert!(set.contains(&Point::new(3, 2, 7)));
/// ```
///
/// ```
/// use std::collections::HashSet;
///
/// use hex_math::{ray_through, Point};
///
/// let point: Point = Point::new_2d(1, 2);
/// let other: Point = Point::new_2d(2, 2);
/// let mut opaque: HashSet<Point> = HashSet::new();
///
/// opaque.insert(Point::new_2d(3, 2));
///
/// let set: HashSet<Point> = ray_through(&point, &other, 3, &opaque);
///
/// assert_eq!(set.len(), 3);
/// assert!(set.contains(&Point::new_2d(1, 2)));
/// assert!(set.contains(&Point::new_2d(2, 2)));
/// assert!(set.contains(&Point::new_2d(3, 2)));
/// ```
pub fn ray_through(
  point: &Point,
  other: &Point,
  range: i32,
  opaque: &HashSet<Point>,
) -> HashSet<Point> {
  util::line(point, other, Some(range), Some(opaque))
}

mod util {
  use std::collections::HashSet;

  use traits::has_values::HasValues;
  use point::Point;
  use distance::{distance, distance_2d};

  /// Linear interpolation of floats with specified offset
  pub fn lerp(a: i32, b: i32, t: f32, o: f32) -> f32 {
    let a = a as f32 + o;
    let b = b as f32 + o;

    a + ((b - a) * t)
  }

  /// Linear interpolation of points with small offset
  ///
  /// The offset is used to prevent the interpolation from falling exactly
  /// on a border between two points. It is eliminated with rounding later.
  pub fn point_lerp(a: &Point, b: &Point, t: f32) -> (f32, f32, f32, f32) {
    let (qa, ra, sa, ta) = a.values_cube();
    let (qb, rb, sb, tb) = b.values_cube();

    let result = (
      lerp(qa, qb, t, 1e-6),
      lerp(ra, rb, t, 1e-6),
      lerp(sa, sb, t, -2e-6),
      lerp(ta, tb, t, 1e-6),
    );

    result
  }

  /// Round a float point back to a standard point
  pub fn point_round((q, r, s, t): (f32, f32, f32, f32)) -> Point {
    let mut rq = q.round();
    let mut rr = r.round();

    let rs = s.round();
    let rt = t.round();

    let dq = (rq - q).abs();
    let dr = (rr - r).abs();
    let ds = (rs - s).abs();

    if (dq > ds) && (dq > dr) {
      rq = -rs - rr;
    } else if ds < dr {
      rr = -rq - rs;
    }

    let point: Point = Point::new(rq as i32, rr as i32, rt as i32);

    point
  }

  /// Find the points in a line between two points
  ///
  /// Optionally provide a range. The line will end at that range.
  ///
  /// Optionally provide a set of opaque point which are impassable.
  pub fn line(
    point: &Point,
    other: &Point,
    range: Option<i32>,
    opaque: Option<&HashSet<Point>>,
  ) -> HashSet<Point> {
    let mut set: HashSet<Point> = HashSet::new();

    if point == other {
      set.insert(point.clone());

      return set;
    }

    let distance: i32 = if point.values_2d() == other.values_2d() {
      distance(point, other)
    } else {
      distance_2d(point, other)
    };

    let empty: HashSet<Point> = HashSet::new();
    let opaque: &HashSet<Point> = opaque.unwrap_or(&empty);
    let should_check_opaque: bool = !opaque.is_empty();

    for index in 0..range.unwrap_or(distance) + 1 {
      let t: f32 = index as f32 / distance as f32;
      let lerp: (f32, f32, f32, f32) = point_lerp(point, other, t);
      let found: Point = point_round(lerp);

      set.insert(found);

      if should_check_opaque && opaque.contains(&found) {
        break;
      }
    }

    set
  }

}

#[cfg(test)]
mod tests {
  use std::collections::HashSet;

  use point::Point;

  use super::util;

  #[test]
  fn lerp() {
    let result = util::lerp(1, 2, 0.5, 1e-6);

    assert_eq!(result, 1.5 + 1e-6);
  }

  #[test]
  fn point_lerp() {
    let point: Point = Point::new(1, 2, 5);
    let other: Point = Point::new(3, 4, 10);
    let result = util::point_lerp(&point, &other, 0.5);
    let expect = (2f32 + 1e-6, 3f32 + 1e-6, -5f32 - 2e-6, 7.5f32 + 1e-6);

    assert_eq!(result, expect);
  }

  #[test]
  fn point_round() {
    let coordinates = (1.6, 1.6, -3.2, 2.5);
    let point: Point = util::point_round(coordinates);

    assert_eq!(point, Point::new(2, 1, 3));
  }

  #[test]
  fn line_vertical() {
    let point: Point = Point::new(1, 2, 5);
    let other: Point = Point::new(1, 2, 7);
    let line: HashSet<Point> = util::line(&point, &other, None, None);

    assert!(line.contains(&Point::new(1, 2, 5)));
    assert!(line.contains(&Point::new(1, 2, 6)));
    assert!(line.contains(&Point::new(1, 2, 7)));
  }

}

<commit_msg>Issue #7: Line now generic<commit_after>//! Useful stuff for finding points in a line

use std::collections::HashSet;

use traits::has_values::HasValues;
use point::Point;

/// Find the points in a line between the current point and the one provided
///
/// # Example
///
/// ```
/// use std::collections::HashSet;
///
/// use hex_math::{line, Point};
///
/// let point: Point = Point::new(1, 2, 5);
/// let other: Point = Point::new(3, 4, 10);
/// let set: HashSet<Point> = line(&point, &other);
///
/// assert_eq!(set.len(), 5);
/// assert!(set.contains(&Point::new(1, 2, 5)));
/// assert!(set.contains(&Point::new(2, 2, 6)));
/// assert!(set.contains(&Point::new(2, 3, 8)));
/// assert!(set.contains(&Point::new(3, 3, 9)));
/// assert!(set.contains(&Point::new(3, 4, 10)));
/// ```
///
/// ```
/// use std::collections::HashSet;
///
/// use hex_math::{line, Point};
///
/// let point: Point = Point::new_2d(1, 2);
/// let other: Point = Point::new_2d(3, 4);
/// let set: HashSet<Point> = line(&point, &other);
///
/// assert_eq!(set.len(), 5);
/// assert!(set.contains(&Point::new_2d(1, 2)));
/// assert!(set.contains(&Point::new_2d(2, 2)));
/// assert!(set.contains(&Point::new_2d(2, 3)));
/// assert!(set.contains(&Point::new_2d(3, 3)));
/// assert!(set.contains(&Point::new_2d(3, 4)));
/// ```
pub fn line<T: HasValues>(point: &T, other: &T) -> HashSet<Point> {
  util::line(point, other, None, None)
}

/// Find the points within range in a line through two points
///
/// # Example
///
/// ```
/// use std::collections::HashSet;
///
/// use hex_math::{line_through, Point};
///
/// let point: Point = Point::new(1, 2, 5);
/// let other: Point = Point::new(2, 2, 6);
/// let set: HashSet<Point> = line_through(&point, &other, 3);
///
/// assert_eq!(set.len(), 4);
/// assert!(set.contains(&Point::new(1, 2, 5)));
/// assert!(set.contains(&Point::new(2, 2, 6)));
/// assert!(set.contains(&Point::new(3, 2, 7)));
/// assert!(set.contains(&Point::new(4, 2, 8)));
/// ```
///
/// ```
/// use std::collections::HashSet;
///
/// use hex_math::{line_through, Point};
///
/// let point: Point = Point::new_2d(1, 2);
/// let other: Point = Point::new_2d(2, 2);
/// let set: HashSet<Point> = line_through(&point, &other, 3);
///
/// assert_eq!(set.len(), 4);
/// assert!(set.contains(&Point::new_2d(1, 2)));
/// assert!(set.contains(&Point::new_2d(2, 2)));
/// assert!(set.contains(&Point::new_2d(3, 2)));
/// assert!(set.contains(&Point::new_2d(4, 2)));
/// ```
pub fn line_through<T: HasValues>(
  point: &T,
  other: &T,
  range: i32,
) -> HashSet<Point> {
  util::line(point, other, Some(range), None)
}

/// Find unblocked points in a line between two points
///
/// # Example
///
/// ```
/// use std::collections::HashSet;
///
/// use hex_math::{ray, Point};
///
/// let point: Point = Point::new(1, 2, 5);
/// let other: Point = Point::new(3, 4, 10);
/// let mut opaque: HashSet<Point> = HashSet::new();
///
/// opaque.insert(Point::new(3, 3, 9));
///
/// let set: HashSet<Point> = ray(&point, &other, &opaque);
///
/// assert_eq!(set.len(), 4);
/// assert!(set.contains(&Point::new(1, 2, 5)));
/// assert!(set.contains(&Point::new(2, 2, 6)));
/// assert!(set.contains(&Point::new(2, 3, 8)));
/// assert!(set.contains(&Point::new(3, 3, 9)));
/// ```
///
/// ```
/// use std::collections::HashSet;
///
/// use hex_math::{ray, Point};
///
/// let point: Point = Point::new_2d(1, 2);
/// let other: Point = Point::new_2d(3, 4);
/// let mut opaque: HashSet<Point> = HashSet::new();
///
/// opaque.insert(Point::new_2d(3, 3));
///
/// let set: HashSet<Point> = ray(&point, &other, &opaque);
///
/// assert_eq!(set.len(), 4);
/// assert!(set.contains(&Point::new_2d(1, 2)));
/// assert!(set.contains(&Point::new_2d(2, 2)));
/// assert!(set.contains(&Point::new_2d(2, 3)));
/// assert!(set.contains(&Point::new_2d(3, 3)));
/// ```
pub fn ray<T: HasValues>(
  point: &T,
  other: &T,
  opaque: &HashSet<Point>,
) -> HashSet<Point> {
  util::line(point, other, None, Some(opaque))
}

/// Find unblocked points within range in a line through two points
///
/// # Example
///
/// ```
/// use std::collections::HashSet;
///
/// use hex_math::{ray_through, Point};
///
/// let point: Point = Point::new(1, 2, 5);
/// let other: Point = Point::new(2, 2, 6);
/// let mut opaque: HashSet<Point> = HashSet::new();
///
/// opaque.insert(Point::new(3, 2, 7));
///
/// let set: HashSet<Point> = ray_through(&point, &other, 3, &opaque);
///
/// assert_eq!(set.len(), 3);
/// assert!(set.contains(&Point::new(1, 2, 5)));
/// assert!(set.contains(&Point::new(2, 2, 6)));
/// assert!(set.contains(&Point::new(3, 2, 7)));
/// ```
///
/// ```
/// use std::collections::HashSet;
///
/// use hex_math::{ray_through, Point};
///
/// let point: Point = Point::new_2d(1, 2);
/// let other: Point = Point::new_2d(2, 2);
/// let mut opaque: HashSet<Point> = HashSet::new();
///
/// opaque.insert(Point::new_2d(3, 2));
///
/// let set: HashSet<Point> = ray_through(&point, &other, 3, &opaque);
///
/// assert_eq!(set.len(), 3);
/// assert!(set.contains(&Point::new_2d(1, 2)));
/// assert!(set.contains(&Point::new_2d(2, 2)));
/// assert!(set.contains(&Point::new_2d(3, 2)));
/// ```
pub fn ray_through<T: HasValues>(
  point: &T,
  other: &T,
  range: i32,
  opaque: &HashSet<Point>,
) -> HashSet<Point> {
  util::line(point, other, Some(range), Some(opaque))
}

mod util {
  use std::collections::HashSet;

  use traits::has_values::HasValues;
  use point::Point;
  use distance::{distance, distance_2d};

  /// Linear interpolation of floats with specified offset
  pub fn lerp(a: i32, b: i32, t: f32, o: f32) -> f32 {
    let a = a as f32 + o;
    let b = b as f32 + o;

    a + ((b - a) * t)
  }

  /// Linear interpolation of points with small offset
  ///
  /// The offset is used to prevent the interpolation from falling exactly
  /// on a border between two points. It is eliminated with rounding later.
  pub fn point_lerp<T: HasValues>(
    a: &T,
    b: &T,
    t: f32
  ) -> (f32, f32, f32, f32) {
    let (qa, ra, sa, ta) = a.values_cube();
    let (qb, rb, sb, tb) = b.values_cube();

    let result = (
      lerp(qa, qb, t, 1e-6),
      lerp(ra, rb, t, 1e-6),
      lerp(sa, sb, t, -2e-6),
      lerp(ta, tb, t, 1e-6),
    );

    result
  }

  /// Round a float point back to a standard point
  pub fn point_round((q, r, s, t): (f32, f32, f32, f32)) -> Point {
    let mut rq = q.round();
    let mut rr = r.round();

    let rs = s.round();
    let rt = t.round();

    let dq = (rq - q).abs();
    let dr = (rr - r).abs();
    let ds = (rs - s).abs();

    if (dq > ds) && (dq > dr) {
      rq = -rs - rr;
    } else if ds < dr {
      rr = -rq - rs;
    }

    let point: Point = Point::new(rq as i32, rr as i32, rt as i32);

    point
  }

  /// Find the points in a line between two points
  ///
  /// Optionally provide a range. The line will end at that range.
  ///
  /// Optionally provide a set of opaque point which are impassable.
  pub fn line<T: HasValues>(
    point: &T,
    other: &T,
    range: Option<i32>,
    opaque: Option<&HashSet<Point>>,
  ) -> HashSet<Point> {
    let mut set: HashSet<Point> = HashSet::new();

    if point.values() == other.values() {
      set.insert(Point::from_values(point.values()));

      return set;
    }

    let distance: i32 = if point.values_2d() == other.values_2d() {
      distance(point, other)
    } else {
      distance_2d(point, other)
    };

    let empty: HashSet<Point> = HashSet::new();
    let opaque: &HashSet<Point> = opaque.unwrap_or(&empty);
    let should_check_opaque: bool = !opaque.is_empty();

    for index in 0..range.unwrap_or(distance) + 1 {
      let t: f32 = index as f32 / distance as f32;
      let lerp: (f32, f32, f32, f32) = point_lerp(point, other, t);
      let found: Point = point_round(lerp);

      set.insert(found);

      if should_check_opaque && opaque.contains(&found) {
        break;
      }
    }

    set
  }

}

#[cfg(test)]
mod tests {
  use std::collections::HashSet;

  use point::Point;

  use super::util;

  #[test]
  fn lerp() {
    let result = util::lerp(1, 2, 0.5, 1e-6);

    assert_eq!(result, 1.5 + 1e-6);
  }

  #[test]
  fn point_lerp() {
    let point: Point = Point::new(1, 2, 5);
    let other: Point = Point::new(3, 4, 10);
    let result = util::point_lerp(&point, &other, 0.5);
    let expect = (2f32 + 1e-6, 3f32 + 1e-6, -5f32 - 2e-6, 7.5f32 + 1e-6);

    assert_eq!(result, expect);
  }

  #[test]
  fn point_round() {
    let coordinates = (1.6, 1.6, -3.2, 2.5);
    let point: Point = util::point_round(coordinates);

    assert_eq!(point, Point::new(2, 1, 3));
  }

  #[test]
  fn line_vertical() {
    let point: Point = Point::new(1, 2, 5);
    let other: Point = Point::new(1, 2, 7);
    let line: HashSet<Point> = util::line(&point, &other, None, None);

    assert!(line.contains(&Point::new(1, 2, 5)));
    assert!(line.contains(&Point::new(1, 2, 6)));
    assert!(line.contains(&Point::new(1, 2, 7)));
  }

}

<|endoftext|>


<commit_before>extern crate hkg;
extern crate termion;
extern crate rustc_serialize;
extern crate kuchiki;
extern crate chrono;
extern crate cancellation;

#[macro_use]
extern crate log;
extern crate log4rs;

use std::io::{stdout, stdin, Write};
use std::thread;
use std::sync::mpsc::channel;
use std::sync::mpsc::Sender;
use std::sync::{Arc, Mutex};
use cancellation::{CancellationToken, CancellationTokenSource, OperationCanceled};
use kuchiki::traits::*;
use rustc_serialize::json;
use termion::input::TermRead;
use termion::raw::IntoRawMode;
use termion::event::Key;
use hkg::status::*;
use hkg::model::IconItem;
use hkg::model::ListTopicItem;
use hkg::state_manager::*;
use hkg::screen_manager::*;
use hkg::caches::file_cache::*;
use hkg::resources::*;
use hkg::resources::web_resource::*;
use hkg::resources::common::*;
use hkg::web::*;

use log4rs::*;

fn main() {

    // Initialize
    log4rs::init_file("config/log4rs.yaml", Default::default());

    let stdout = stdout();
    let mut stdout = stdout.lock().into_raw_mode().expect("fail to lock stdout");

    // Clear the screen.
    hkg::screen::common::clear_screen();

    // web background services
    let (tx_req, rx_req) = channel::<ChannelItem>();
    let (tx_res, rx_res) = channel::<ChannelItem>();

    let mut app = {

        let icon_collection: Box<Vec<IconItem>> = {
            let icon_manifest_string = hkg::utility::readfile(String::from("data/icon.manifest.json"));
            Box::new(json::decode(&icon_manifest_string).expect("fail to lock stdout"))
        };

        hkg::App {
            builder: hkg::builder::Builder::new(),
            state_manager: StateManager::new(),
            screen_manager: ScreenManager::new(),

            // initialize empty page
            list_topic_items: vec![],
            show_item: hkg::builder::Builder::new().default_show_item(),

            status_bar: hkg::screen::status_bar::StatusBar::new(),
            index: hkg::screen::index::Index::new(),
            show: hkg::screen::show::Show::new(icon_collection),
            image_request_count_lock: Arc::new(Mutex::new(0)),
            is_bg_request: false,
            tx_req: &tx_req,
            rx_res: &rx_res
        }
    };

    Requester::new(rx_req, tx_res);

    // topics request
    let status_message = list_page(&mut app.state_manager, &tx_req);
    app.status_bar.append(&app.screen_manager, &status_message);

    loop {

        match app.rx_res.try_recv() {
            Ok(item) => {
                match item.extra {
                    ChannelItemType::Show(extra) => {
                        let document = kuchiki::parse_html().from_utf8().one(item.result.as_bytes());

                        let posturl = get_posturl(&extra.postid, extra.page);
                        app.show_item = app.builder.show_item(&document, &posturl);

                        app.status_bar.append(&app.screen_manager, &format!("[{}-{}:ROK][{}]",
                                 app.show_item.url_query.message,
                                 app.show_item.page,
                                 app.state_manager.isWebRequest()));

                        // get all images links in an array, and send to background download
                        let maps = app.show_item.replies.iter().flat_map(|reply|
                            {
                                 let f = reply.body.iter().filter(|node| {
                                     let node2 = node.clone();
                                     match *node2 {
                                         hkg::reply_model::NodeType::Image(ref n) => (n.data.starts_with("http") || n.data.starts_with("https")) && n.alt.starts_with("[img]") && n.alt.ends_with("[/img]"),
                                         _ => false
                                     }
                                 }).collect::<Vec<_>>();
                                 return f;
                            }
                        ).collect::<Vec<_>>();

                        let mut count = app.image_request_count_lock.lock().expect("fail to lock image request count");
                        *count = maps.len();
                        app.is_bg_request = true;
                        app.status_bar.append(&app.screen_manager,
                                                &format!("[SIMG:{count}]", count = *count ));

                        for node in &maps {
                            let node2 = node.clone();
                            match *node2 {
                                 hkg::reply_model::NodeType::Image(ref n) => {
                                     let status_message = image_request(&n.data, &mut app.state_manager, &app.tx_req);
                                     app.status_bar.append(&app.screen_manager,&status_message);
                                 },
                                 _ => {}
                            }
                        }

                        app.show.resetY();
                        hkg::screen::common::clear_screen();
                        app.state_manager.updateState(Status::Show); //state = Status::Show;
                        app.state_manager.setWebRequest(false); // is_web_requesting = false;
                    },
                    ChannelItemType::Index(_) => {
                        let document = kuchiki::parse_html().from_utf8().one(item.result.as_bytes());

                        app.list_topic_items.clear();
                        for item in app.builder.list_topic_items(&document) {
                            app.list_topic_items.push(item);
                        }

                        app.status_bar.append(&app.screen_manager,
                                               &format!("[TOPICS:ROK]"));

                        hkg::screen::common::clear_screen();

                        app.state_manager.updateState(Status::List); // state = Status::List;
                        app.state_manager.setWebRequest(false); // is_web_requesting = false;

                    },
                    ChannelItemType::Image(extra) => {
                        match app.image_request_count_lock.lock() {
                            Ok(mut count) => {
                                if *count == 0 {
                                    app.status_bar.append(&app.screen_manager,
                                                           &format!("[RIMG:CERR]"));
                                } else {
                                    *count -= 1;
                                    if (item.result != "") {
                                        app.status_bar.append(&app.screen_manager,
                                                           &format!("[RIMG:E-{count}-{error}]", count = *count, error = item.result ));
                                    } else {
                                        app.status_bar.append(&app.screen_manager,
                                                           &format!("[RIMG:S-{count}]", count = *count ));
                                    }
                                }

                                if *count <= 0 {
                                    app.is_bg_request = false;
                                    hkg::screen::common::clear_screen();
                                    app.state_manager.setWebRequest(false); // is_web_requesting = false;
                                }
                            },
                            Err(poisoned) => { app.status_bar.append(&app.screen_manager,
                                                   &format!("[IMAGES:LOCKERR]")); }
                        };
                    }
                }
            }
            Err(_) => {}
        }

        match app.state_manager.getState() {
            Status::Startup => {

            },
            Status::List => {
                app.index.print(&mut stdout, &app.list_topic_items);
            }
            Status::Show => {
                app.show.print(&mut stdout, &app.show_item);
            }
        }

        app.status_bar.print(&app.screen_manager);

        stdout.flush().expect("fail to flush the stdout");

        if !app.state_manager.isWebRequest() {

            let stdin = stdin();

            for c in stdin.keys() {

                if app.screen_manager.isWidthChanged() {
                    hkg::screen::common::clear_screen();
                }

                match app.state_manager.getState() {
                    Status::Startup => {},
                    Status::List => {
                        match c.ok().expect("fail to get stdin keys") {
                            Key::Char('q') => {
                                hkg::screen::common::reset_screen();
                                return
                            },
                            Key::Char('\n') => {
                                app.status_bar.append(&app.screen_manager, "ENTER");
                                let i = app.index.get_selected_topic();
                                if i > 0 {
                                    let topic_item = &app.list_topic_items[i - 1];
                                    let postid = &topic_item.title.url_query.message;
                                    let page = 1;
                                    let status_message = show_page(&postid, page, &mut app.state_manager, &app.tx_req);

                                    app.status_bar.append(&app.screen_manager,
                                                           &get_show_page_status_message(postid, page, &status_message));
                                }
                                break
                            },
                            Key::PageUp => {
                                app.status_bar.append(&app.screen_manager, "↑");
                                let tmp = app.index.get_selected_topic();
                                app.status_bar.append(&app.screen_manager, &format!("{}", tmp));

                                if tmp > 1 {
                                    app.index.select_topic(tmp - 1);
                                }
                                break
                            },
                            Key::Up => {
                                app.status_bar.append(&app.screen_manager, "↑");
                                let tmp = app.index.get_selected_topic();
                                app.status_bar.append(&app.screen_manager, &format!("{}", tmp));

                                if tmp > 1 {
                                    app.index.select_topic(tmp - 1);
                                }
                                break
                            },
                            Key::Down => {
                                app.status_bar.append(&app.screen_manager, "↓");
                                let tmp = app.index.get_selected_topic();
                                app.status_bar.append(&app.screen_manager, &format!("{}", tmp));

                                if tmp < app.index.body_height() {
                                    app.index.select_topic(tmp + 1);
                                }
                                break
                            },
                            _ => {},
                        }
                    },
                    Status::Show => {
                            match c.ok().expect("fail to get stdin keys") {
                                Key::Char('q') => {
                                    hkg::screen::common::reset_screen(); // print!("{}{}{}", termion::clear::All, style::Reset, termion::cursor::Show);
                                    return
                                },
                                Key::Left => {
                                    app.status_bar.append(&app.screen_manager, &format!("←"));
                                    if app.show_item.page > 1 {
                                        let postid = &app.show_item.url_query.message;
                                        let page = &app.show_item.page - 1;
                                        let status_message = show_page(&postid, page, &mut app.state_manager, &app.tx_req);

                                        app.status_bar.append(&app.screen_manager,
                                                               &get_show_page_status_message(postid, page, &status_message));
                                    }
                                    break
                                }
                                Key::Right => {
                                    app.status_bar.append(&app.screen_manager, &format!("→"));
                                    if app.show_item.max_page > app.show_item.page {
                                        let postid = &app.show_item.url_query.message;
                                        let page = &app.show_item.page + 1;
                                        let status_message = show_page(&postid, page, &mut app.state_manager, &app.tx_req);

                                        app.status_bar.append(&app.screen_manager,
                                                               &get_show_page_status_message(postid, page, &status_message));
                                    }
                                    break
                                },
                                Key::PageUp => {
                                    app.status_bar.append(&app.screen_manager, "↑");
                                    let bh = app.show.body_height();
                                    if app.show.scrollUp(bh) {
                                    hkg::screen::common::clear_screen();
                                    }
                                    break
                                },
                                Key::PageDown => {
                                    app.status_bar.append(&app.screen_manager, "↓");
                                    let bh = app.show.body_height();
                                    if app.show.scrollDown(bh) {
                                        hkg::screen::common::clear_screen();
                                    }
                                    break
                                },
                                Key::Up => {
                                    app.status_bar.append(&app.screen_manager, "↑");
                                    if app.show.scrollUp(2) {
                                        hkg::screen::common::clear_screen();
                                    }
                                    break
                                },
                                Key::Down => {
                                    app.status_bar.append(&app.screen_manager, "↓");
                                    if app.show.scrollDown(2) {
                                        hkg::screen::common::clear_screen();
                                    }
                                    break
                                },
                                Key::Backspace => {
                                    app.status_bar.append(&app.screen_manager, "B");
                                    app.state_manager.updateState(Status::List); // state = Status::List;
                                    hkg::screen::common::clear_screen();
                                    break
                                },
                                _ => {},
                            }
                        }
                }

            }
        }

    }
}
fn get_posturl(postid: &String, page: usize) -> String {
    let base_url = "http://forum1.hkgolden.com/view.aspx";
    let posturl = format!("{base_url}?type=BW&message={postid}&page={page}",
                          base_url = base_url,
                          postid = postid,
                          page = page);
    posturl
}

fn list_page(state_manager: &mut StateManager, tx_req: &Sender<ChannelItem>) -> String {

    let ci = ChannelItem {
        extra: ChannelItemType::Index(ChannelIndexItem { }),
        result: String::from(""),
    };

    let status_message = match tx_req.send(ci) {
        Ok(()) => {
            state_manager.setWebRequest(true);    // *is_web_requesting = true;
            "SOK".to_string()
        }
        Err(e) => format!("{}:{}", "SFAIL", e).to_string(),
    };

    status_message
}

fn show_page(postid: &String, page: usize, state_manager: &mut StateManager, tx_req: &Sender<ChannelItem>) -> String {

    let ci = ChannelItem {
        extra: ChannelItemType::Show(ChannelShowItem { postid: postid.clone(), page: page }),
        result: String::from(""),
    };

    let status_message = match tx_req.send(ci) {
        Ok(()) => {
            state_manager.setWebRequest(true); // *is_web_requesting = true;
            "SOK".to_string()
        }
        Err(e) => format!("{}:{}", "SFAIL", e).to_string(),
    };

    status_message
}

fn image_request(url: &String, state_manager: &mut StateManager, tx_req: &Sender<ChannelItem>) -> String {

    let ci = ChannelItem {
        extra: ChannelItemType::Image(ChannelImageItem { url: url.to_string(), bytes: Vec::new() }),
        result: String::from(""),
    };

    let status_message = match tx_req.send(ci) {
        Ok(()) => {
            state_manager.setWebRequest(true); // *is_web_requesting = true;
            "SOK".to_string()
        }
        Err(e) => format!("{}:{}", "SFAIL", e).to_string(),
    };

    status_message
}

fn get_show_page_status_message(postid: &String, page: usize, status_message: &String) -> String {
    format!("[{}-{}:{}]", postid, page, status_message)
}
<commit_msg>break main loop<commit_after>extern crate hkg;
extern crate termion;
extern crate rustc_serialize;
extern crate kuchiki;
extern crate chrono;
extern crate cancellation;

#[macro_use]
extern crate log;
extern crate log4rs;

use std::io::{stdout, stdin, Write};
use std::thread;
use std::sync::mpsc::channel;
use std::sync::mpsc::Sender;
use std::sync::{Arc, Mutex};
use cancellation::{CancellationToken, CancellationTokenSource, OperationCanceled};
use kuchiki::traits::*;
use rustc_serialize::json;
use termion::input::TermRead;
use termion::raw::IntoRawMode;
use termion::event::Key;
use hkg::status::*;
use hkg::model::IconItem;
use hkg::model::ListTopicItem;
use hkg::state_manager::*;
use hkg::screen_manager::*;
use hkg::caches::file_cache::*;
use hkg::resources::*;
use hkg::resources::web_resource::*;
use hkg::resources::common::*;
use hkg::web::*;

use log4rs::*;

fn main() {

    // Initialize
    log4rs::init_file("config/log4rs.yaml", Default::default());

    let stdout = stdout();
    let mut stdout = stdout.lock().into_raw_mode().expect("fail to lock stdout");

    // Clear the screen.
    hkg::screen::common::clear_screen();

    // web background services
    let (tx_req, rx_req) = channel::<ChannelItem>();
    let (tx_res, rx_res) = channel::<ChannelItem>();

    let mut app = {

        let icon_collection: Box<Vec<IconItem>> = {
            let icon_manifest_string = hkg::utility::readfile(String::from("data/icon.manifest.json"));
            Box::new(json::decode(&icon_manifest_string).expect("fail to lock stdout"))
        };

        hkg::App {
            builder: hkg::builder::Builder::new(),
            state_manager: StateManager::new(),
            screen_manager: ScreenManager::new(),

            // initialize empty page
            list_topic_items: vec![],
            show_item: hkg::builder::Builder::new().default_show_item(),

            status_bar: hkg::screen::status_bar::StatusBar::new(),
            index: hkg::screen::index::Index::new(),
            show: hkg::screen::show::Show::new(icon_collection),
            image_request_count_lock: Arc::new(Mutex::new(0)),
            is_bg_request: false,
            tx_req: &tx_req,
            rx_res: &rx_res
        }
    };

    Requester::new(rx_req, tx_res);

    // topics request
    let status_message = list_page(&mut app.state_manager, &tx_req);
    app.status_bar.append(&app.screen_manager, &status_message);

    loop {

        responser(&mut app);
        print_screen(&mut app, &mut stdout);

        app.status_bar.print(&app.screen_manager);

        stdout.flush().expect("fail to flush the stdout");

        if !app.state_manager.isWebRequest() {

            let stdin = stdin();

            for c in stdin.keys() {

                if app.screen_manager.isWidthChanged() {
                    hkg::screen::common::clear_screen();
                }

                match app.state_manager.getState() {
                    Status::Startup => {}
                    Status::List => {
                        match index_control(c.ok().expect("fail to get stdin keys"),
                                            &mut app,
                                            &mut stdout) {
                            Some(i) => return if i == 0 { return } else { break },
                            None => {}
                        }
                    }
                    Status::Show => {
                        match show_control(c.ok().expect("fail to get stdin keys"),
                                           &mut app,
                                           &mut stdout) {
                            Some(i) => return if i == 0 { return } else { break },
                            None => {}
                        }
                    }
                }

            }
        }

    }
}
fn get_posturl(postid: &String, page: usize) -> String {
    let base_url = "http://forum1.hkgolden.com/view.aspx";
    let posturl = format!("{base_url}?type=BW&message={postid}&page={page}",
                          base_url = base_url,
                          postid = postid,
                          page = page);
    posturl
}

fn list_page(state_manager: &mut StateManager, tx_req: &Sender<ChannelItem>) -> String {

    let ci = ChannelItem {
        extra: ChannelItemType::Index(ChannelIndexItem {}),
        result: String::from(""),
    };

    let status_message = match tx_req.send(ci) {
        Ok(()) => {
            state_manager.setWebRequest(true);    // *is_web_requesting = true;
            "SOK".to_string()
        }
        Err(e) => format!("{}:{}", "SFAIL", e).to_string(),
    };

    status_message
}

fn show_page(postid: &String, page: usize, state_manager: &mut StateManager, tx_req: &Sender<ChannelItem>) -> String {

    let ci = ChannelItem {
        extra: ChannelItemType::Show(ChannelShowItem {
                                         postid: postid.clone(),
                                         page: page,
                                     }),
        result: String::from(""),
    };

    let status_message = match tx_req.send(ci) {
        Ok(()) => {
            state_manager.setWebRequest(true); // *is_web_requesting = true;
            "SOK".to_string()
        }
        Err(e) => format!("{}:{}", "SFAIL", e).to_string(),
    };

    status_message
}

fn image_request(url: &String, state_manager: &mut StateManager, tx_req: &Sender<ChannelItem>) -> String {

    let ci = ChannelItem {
        extra: ChannelItemType::Image(ChannelImageItem {
                                          url: url.to_string(),
                                          bytes: Vec::new(),
                                      }),
        result: String::from(""),
    };

    let status_message = match tx_req.send(ci) {
        Ok(()) => {
            state_manager.setWebRequest(true); // *is_web_requesting = true;
            "SOK".to_string()
        }
        Err(e) => format!("{}:{}", "SFAIL", e).to_string(),
    };

    status_message
}

fn get_show_page_status_message(postid: &String, page: usize, status_message: &String) -> String {
    format!("[{}-{}:{}]", postid, page, status_message)
}

fn responser(app: &mut hkg::App) {
    match app.rx_res.try_recv() {
        Ok(item) => {
            match item.extra {
                ChannelItemType::Show(extra) => {
                    let document = kuchiki::parse_html().from_utf8().one(item.result.as_bytes());

                    let posturl = get_posturl(&extra.postid, extra.page);
                    app.show_item = app.builder.show_item(&document, &posturl);

                    app.status_bar.append(&app.screen_manager,
                                          &format!("[{}-{}:ROK][{}]",
                                                   app.show_item.url_query.message,
                                                   app.show_item.page,
                                                   app.state_manager.isWebRequest()));

                    // get all images links in an array, and send to background download
                    let maps = app.show_item.replies.iter().flat_map(|reply| {
                            let f = reply.body.iter().filter(|node| {
                                    let node2 = node.clone();
                                    match *node2 {
                                        hkg::reply_model::NodeType::Image(ref n) => {
                                            (n.data.starts_with("http") || n.data.starts_with("https")) && n.alt.starts_with("[img]") &&
                                            n.alt.ends_with("[/img]")
                                        }
                                        _ => false,
                                    }
                                }).collect::<Vec<_>>();
                            f
                        })
                        .collect::<Vec<_>>();

                    let mut count = app.image_request_count_lock.lock().expect("fail to lock image request count");
                    *count = maps.len();
                    app.is_bg_request = true;
                    app.status_bar.append(&app.screen_manager,
                                          &format!("[SIMG:{count}]", count = *count));

                    for node in &maps {
                        let node2 = node.clone();
                        match *node2 {
                            hkg::reply_model::NodeType::Image(ref n) => {
                                let status_message = image_request(&n.data, &mut app.state_manager, &app.tx_req);
                                app.status_bar.append(&app.screen_manager, &status_message);
                            }
                            _ => {}
                        }
                    }

                    app.show.resetY();
                    hkg::screen::common::clear_screen();
                    app.state_manager.updateState(Status::Show); //state = Status::Show;
                    app.state_manager.setWebRequest(false); // is_web_requesting = false;
                }
                ChannelItemType::Index(_) => {
                    let document = kuchiki::parse_html().from_utf8().one(item.result.as_bytes());

                    app.list_topic_items.clear();
                    for item in app.builder.list_topic_items(&document) {
                        app.list_topic_items.push(item);
                    }

                    app.status_bar.append(&app.screen_manager, &format!("[TOPICS:ROK]"));

                    hkg::screen::common::clear_screen();

                    app.state_manager.updateState(Status::List); // state = Status::List;
                    app.state_manager.setWebRequest(false); // is_web_requesting = false;

                }
                ChannelItemType::Image(extra) => {
                    match app.image_request_count_lock.lock() {
                        Ok(mut count) => {
                            if *count == 0 {
                                app.status_bar.append(&app.screen_manager, &format!("[RIMG:CERR]"));
                            } else {
                                *count -= 1;
                                if (item.result != "") {
                                    app.status_bar.append(&app.screen_manager,
                                                          &format!("[RIMG:E-{count}-{error}]",
                                                                   count = *count,
                                                                   error = item.result));
                                } else {
                                    app.status_bar.append(&app.screen_manager,
                                                          &format!("[RIMG:S-{count}]", count = *count));
                                }
                            }

                            if *count <= 0 {
                                app.is_bg_request = false;
                                hkg::screen::common::clear_screen();
                                app.state_manager.setWebRequest(false); // is_web_requesting = false;
                            }
                        }
                        Err(poisoned) => {
                            app.status_bar.append(&app.screen_manager, &format!("[IMAGES:LOCKERR]"));
                        }
                    };
                }
            }
        }
        Err(_) => {}
    }
}

fn print_screen(app: &mut hkg::App, mut stdout: &mut termion::raw::RawTerminal<std::io::StdoutLock>) {
    match app.state_manager.getState() {
        Status::Startup => {}
        Status::List => {
            app.index.print(&mut stdout, &app.list_topic_items);
        }
        Status::Show => {
            app.show.print(&mut stdout, &app.show_item);
        }
    }
}

fn show_control(c: termion::event::Key,
                app: &mut hkg::App,
                mut stdout: &mut termion::raw::RawTerminal<std::io::StdoutLock>)
                -> Option<i32> {
    match c {
        Key::Char('q') => {
            hkg::screen::common::reset_screen(); // print!("{}{}{}", termion::clear::All, style::Reset, termion::cursor::Show);
            Some(0)
        }
        Key::Left => {
            app.status_bar.append(&app.screen_manager, &format!("←"));
            if app.show_item.page > 1 {
                let postid = &app.show_item.url_query.message;
                let page = &app.show_item.page - 1;
                let status_message = show_page(&postid, page, &mut app.state_manager, &app.tx_req);

                app.status_bar.append(&app.screen_manager,
                                      &get_show_page_status_message(postid, page, &status_message));
            }
            Some(1)
        }
        Key::Right => {
            app.status_bar.append(&app.screen_manager, &format!("→"));
            if app.show_item.max_page > app.show_item.page {
                let postid = &app.show_item.url_query.message;
                let page = &app.show_item.page + 1;
                let status_message = show_page(&postid, page, &mut app.state_manager, &app.tx_req);

                app.status_bar.append(&app.screen_manager,
                                      &get_show_page_status_message(postid, page, &status_message));
            }
            Some(1)
        }
        Key::PageUp => {
            app.status_bar.append(&app.screen_manager, "↑");
            let bh = app.show.body_height();
            if app.show.scrollUp(bh) {
                hkg::screen::common::clear_screen();
            }
            Some(1)
        }
        Key::PageDown => {
            app.status_bar.append(&app.screen_manager, "↓");
            let bh = app.show.body_height();
            if app.show.scrollDown(bh) {
                hkg::screen::common::clear_screen();
            }
            Some(1)
        }
        Key::Up => {
            app.status_bar.append(&app.screen_manager, "↑");
            if app.show.scrollUp(2) {
                hkg::screen::common::clear_screen();
            }
            Some(1)
        }
        Key::Down => {
            app.status_bar.append(&app.screen_manager, "↓");
            if app.show.scrollDown(2) {
                hkg::screen::common::clear_screen();
            }
            Some(1)
        }
        Key::Backspace => {
            app.status_bar.append(&app.screen_manager, "B");
            app.state_manager.updateState(Status::List); // state = Status::List;
            hkg::screen::common::clear_screen();
            Some(1)
        }
        _ => None,
    }
}

fn index_control(c: termion::event::Key,
                 app: &mut hkg::App,
                 mut stdout: &mut termion::raw::RawTerminal<std::io::StdoutLock>)
                 -> Option<i32> {
    match c {
        Key::Char('q') => {
            hkg::screen::common::reset_screen();
            Some(0)
        }
        Key::Char('\n') => {
            app.status_bar.append(&app.screen_manager, "ENTER");
            let i = app.index.get_selected_topic();
            if i > 0 {
                let topic_item = &app.list_topic_items[i - 1];
                let postid = &topic_item.title.url_query.message;
                let page = 1;
                let status_message = show_page(&postid, page, &mut app.state_manager, &app.tx_req);

                app.status_bar.append(&app.screen_manager,
                                      &get_show_page_status_message(postid, page, &status_message));
            }
            Some(1)
        }
        Key::PageUp => {
            app.status_bar.append(&app.screen_manager, "↑");
            let tmp = app.index.get_selected_topic();
            app.status_bar.append(&app.screen_manager, &format!("{}", tmp));

            if tmp > 1 {
                app.index.select_topic(tmp - 1);
            }
            Some(1)
        }
        Key::Up => {
            app.status_bar.append(&app.screen_manager, "↑");
            let tmp = app.index.get_selected_topic();
            app.status_bar.append(&app.screen_manager, &format!("{}", tmp));

            if tmp > 1 {
                app.index.select_topic(tmp - 1);
            }
            Some(1)
        }
        Key::Down => {
            app.status_bar.append(&app.screen_manager, "↓");
            let tmp = app.index.get_selected_topic();
            app.status_bar.append(&app.screen_manager, &format!("{}", tmp));

            if tmp < app.index.body_height() {
                app.index.select_topic(tmp + 1);
            }
            Some(1)
        }
        _ => None,
    }
}
<|endoftext|>


<commit_before>mod domain;

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

use chrono::prelude::*;
use clap::{App, Arg};
use dotenv::dotenv;
use serde_derive::{Deserialize, Serialize};

use self::domain::{
    Entry, EntryId, EntryKind, Project, ProjectHeadwayEntry, ProjectId, ProjectStatus,
};

#[derive(Serialize, Deserialize)]
pub struct Log {
    pub projects: Vec<Project>,
    pub entries: Vec<Entry>,
}

fn main() {
    dotenv().ok();

    let matches = App::new("scribe")
        .version("0.1.0")
        .author("Marshall Bowers <elliott.codes@gmail.com>")
        .arg(
            Arg::with_name("config")
                .short("c")
                .long("config")
                .value_name("FILE")
                .takes_value(true),
        )
        .get_matches();

    let config = matches.value_of("config").unwrap_or(".scribe");

    println!("{}", config);
}
<commit_msg>Use crate version and author<commit_after>#[macro_use]
extern crate clap;

mod domain;

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

use chrono::prelude::*;
use clap::{App, Arg};
use dotenv::dotenv;
use serde_derive::{Deserialize, Serialize};

use self::domain::{
    Entry, EntryId, EntryKind, Project, ProjectHeadwayEntry, ProjectId, ProjectStatus,
};

#[derive(Serialize, Deserialize)]
pub struct Log {
    pub projects: Vec<Project>,
    pub entries: Vec<Entry>,
}

fn main() {
    dotenv().ok();

    let matches = App::new("scribe")
        .version(crate_version!())
        .author(crate_authors!())
        .arg(
            Arg::with_name("config")
                .short("c")
                .long("config")
                .value_name("FILE")
                .takes_value(true),
        )
        .get_matches();

    let config = matches.value_of("config").unwrap_or(".scribe");

    println!("{}", config);
}
<|endoftext|>


<commit_before>#![allow(non_snake_case)]

extern crate rand;
use rand::Rng;
use rand::distributions::{IndependentSample, Range};
mod energy;
use energy::*;
use std::io::prelude::*;

const LJ_EPS : f64 = 1.0;
const LJ_SIG : f64 = 1.0;

const TAILCORR : bool = true;
const SHIFT: bool = false;

// easy printing to stderr
macro_rules! println_stderr(
    ($($arg:tt)*) => { {
        let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
        r.expect("failed printing to stderr");
    } }
);

fn main() {

    // define all the stuff
    let minim_steps  = 1000000;
    let sample_steps = 100000;

    let num_particles: usize = 512;
    let density = 0.7;
    let temperature = 0.9;

    let cutoff = 3.0;
    let displacement = 0.1;

    println_stderr!("");
    println_stderr!("################################################################");
    println_stderr!("##################  LJ Monte Carlo Simulation  #################");
    println_stderr!("################################################################");
    println_stderr!("");

    // initialize stuff
    let beta = 1.0/temperature;
    let volume = (num_particles as f64)/ density;
    let length  = volume.cbrt();
    let (l_x, l_y, l_z) = (length, length, length);
    let cutoff_squared = cutoff * cutoff;

    let mut rng = rand::thread_rng();
    let particle_range = Range::new(0, num_particles-1);

    let mut rx : Vec<f64> = vec![];
    let mut ry : Vec<f64> = vec![];
    let mut rz : Vec<f64> = vec![];
    loop {
        rx.push(l_x * rng.gen::<f64>());
        ry.push(l_y * rng.gen::<f64>());
        rz.push(l_z * rng.gen::<f64>());
        if rx.len() == num_particles { break; }
    }

    let e_corr = if TAILCORR { 8.0/3.0*std::f64::consts::PI*density*LJ_EPS*LJ_SIG.powi(3)*((1.0/3.0*(LJ_SIG/cutoff).powi(9)) - (LJ_SIG/cutoff).powi(3)) } else { 0.0 };
    let p_corr = if TAILCORR { 16.0/3.0*std::f64::consts::PI*density.powi(2)*LJ_EPS*LJ_SIG.powi(3)*((2.0/3.0*(LJ_SIG/cutoff).powi(9)) - (LJ_SIG/cutoff).powi(3)) } else { 0.0 };

    println_stderr!("Particles: {}, Density: {}, Temperature: {}", num_particles, density, temperature);
    println_stderr!("System volume: {:8.3}, Dimensions {:.3}/{:.3}/{:.3}", volume, l_x, l_y, l_z);
    println_stderr!("Minimization steps: {}, Sampling steps: {}", minim_steps, sample_steps);
    println_stderr!("LJ params eps: {}, sigma: {}, cutoff: {}", LJ_EPS, LJ_SIG, cutoff);
    println_stderr!("Tailcorr: {:8.3}, Shift: {:8.3}, Pressurecprr: {:8.3}", e_corr, SHIFT, p_corr);

    let (mut energy, mut virial) = get_total_energy(&rx, &ry, &rz, num_particles, l_x, l_y, l_z, cutoff_squared, e_corr);
    let mut energy_sum = 0.0;
    let mut virial_sum = 0.0;
    let mut step_counter = 0;
    let mut accept_counter = 0;

    println_stderr!("");
    println_stderr!("################################################################");
    println_stderr!("#####################  Energy Minimization  ####################");
    println_stderr!("################################################################");
    println_stderr!("");

    for step in 0..minim_steps+sample_steps {

        // select rnd particle
        let rnd_index = particle_range.ind_sample(&mut rng);

        // store old position
        let oldX = rx[rnd_index];
        let oldY = ry[rnd_index];
        let oldZ = rz[rnd_index];

        // old particle energy
        let (old_particle_energy, old_particle_virial) = get_particle_energy(&rx, &ry, &rz, rnd_index, num_particles, l_x, l_y, l_z, cutoff_squared);

        // rnd displacement and PBC
        rx[rnd_index] += ( rng.gen::<f64>() - 0.5 ) * displacement;
        ry[rnd_index] += ( rng.gen::<f64>() - 0.5 ) * displacement;
        rz[rnd_index] += ( rng.gen::<f64>() - 0.5 ) * displacement;
        if rx[rnd_index] < 0.0 { rx[rnd_index] += l_x }
        if rx[rnd_index] > l_x { rx[rnd_index] -= l_x }
        if ry[rnd_index] < 0.0 { ry[rnd_index] += l_y }
        if ry[rnd_index] > l_y { ry[rnd_index] -= l_y }
        if rz[rnd_index] < 0.0 { rz[rnd_index] += l_z }
        if rz[rnd_index] > l_z { rz[rnd_index] -= l_z }

        // calculate energy difference
        let (new_particle_energy, new_particle_virial) = get_particle_energy(&rx, &ry, &rz, rnd_index, num_particles, l_x, l_y, l_z, cutoff_squared);
        let dE = new_particle_energy - old_particle_energy;

        //accept move
        if rng.gen::<f64>() < (-beta * dE).exp() {
            accept_counter += 1;
            if step % 1000 == 0 { // calculate total energy every 1000 steps to account for rounding errors
                let (e, v) = get_total_energy(&rx, &ry, &rz, num_particles, l_x, l_y, l_z, cutoff_squared, e_corr);
                energy = e;
                virial = v;
            } else {
                energy += dE;
                virial += new_particle_virial - old_particle_virial;
            }
        } else { // or restore old position
            rx[rnd_index] = oldX;
            ry[rnd_index] = oldY;
            rz[rnd_index] = oldZ;
        }

        // update sums for averaging
        step_counter += 1;
        energy_sum += energy;
        virial_sum += virial;

        if step_counter % 5000 == 0 {
            println!("{} {}\tEnergy: {:.3}\tVirial: {:.3}\tAcceptance:{:.1}\tDisplacement: {:.3}", if step < minim_steps {"Minim"} else {"Step"} ,step_counter, energy, virial, 666, displacement);
        }

        // reset sums for sampling
        if step == minim_steps-1 {
            println_stderr!("");
            println_stderr!("################################################################");
            println_stderr!("##########################  Sampling  ##########################");
            println_stderr!("################################################################");
            println_stderr!("");
            step_counter = 0;
            accept_counter = 0;
            energy_sum = 0.0;
            virial_sum = 0.0;
        }

    }

    let final_energy = energy_sum/step_counter as f64;
    let particle_energy = final_energy / num_particles as f64;
    let final_virial = virial_sum / 3.0 / step_counter as f64 / volume;
    let pressure = virial_sum / 3.0 / step_counter as f64 / volume + density * temperature + p_corr;
    let final_acceptance_rate = 1.0/((accept_counter as f64)/(step_counter as f64)) * 100.0;

    println_stderr!("Done sampling!");
    println!("");
    println!("################################################################");
    println!("##########################  Results  ###########################");
    println!("################################################################");
    println!("");
    println!(
        "Minimization: {}
        Steps: {}

        # Lennard Jones Params
        epsilon: {}
        sigma: {}
        cutoff: {}

        # System
        Particles: {}
        Density: {}
        Temperature: {}
        Volume: {}
        Box dimension: {:.3}/{:.3}/{:.3}
        Max Displacement: {}

        # Correction
        Energy correction: {}
        Shift: {}
        P-Correction: {}

        # Averages
        Tries: {}
        Accepted: {}
        Acceptance: {:.2}%
        Energy: {}
        Energy per particle: {}
        Virial: {}
        Pressure: {}

    ",

        minim_steps, sample_steps,
        LJ_EPS, LJ_SIG, cutoff,
        num_particles, density, temperature, volume, l_x, l_y, l_z, displacement,
        e_corr, SHIFT, p_corr,
        step_counter, accept_counter, final_acceptance_rate, final_energy, particle_energy, final_virial, pressure);

}

<commit_msg>scale displacement<commit_after>#![allow(non_snake_case)]

extern crate rand;
use rand::Rng;
use rand::distributions::{IndependentSample, Range};
mod energy;
use energy::*;
use std::io::prelude::*;

const LJ_EPS : f64 = 1.0;
const LJ_SIG : f64 = 1.0;

const TAILCORR : bool = true;
const SHIFT: bool = false;

const TRIES_INTENDED : f64 = 3.0;
const DISP_SCALE_FACTOR : f64 = 0.1;

// easy printing to stderr
macro_rules! println_stderr(
    ($($arg:tt)*) => { {
        let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
        r.expect("failed printing to stderr");
    } }
);

fn main() {

    // define all the stuff
    let minim_steps  = 1000000;
    let sample_steps = 100000;

    let num_particles: usize = 512;
    let density = 0.7;
    let temperature = 0.9;

    let cutoff = 3.0;
    let mut displacement = 0.1;

    println_stderr!("");
    println_stderr!("################################################################");
    println_stderr!("##################  LJ Monte Carlo Simulation  #################");
    println_stderr!("################################################################");
    println_stderr!("");

    // initialize stuff
    let beta = 1.0/temperature;
    let volume = (num_particles as f64)/ density;
    let length  = volume.cbrt();
    let (l_x, l_y, l_z) = (length, length, length);
    let cutoff_squared = cutoff * cutoff;
    let max_displacement = length / 2.0;

    let mut rng = rand::thread_rng();
    let particle_range = Range::new(0, num_particles-1);

    let mut rx : Vec<f64> = vec![];
    let mut ry : Vec<f64> = vec![];
    let mut rz : Vec<f64> = vec![];
    loop {
        rx.push(l_x * rng.gen::<f64>());
        ry.push(l_y * rng.gen::<f64>());
        rz.push(l_z * rng.gen::<f64>());
        if rx.len() == num_particles { break; }
    }

    let e_corr = if TAILCORR { 8.0/3.0*std::f64::consts::PI*density*LJ_EPS*LJ_SIG.powi(3)*((1.0/3.0*(LJ_SIG/cutoff).powi(9)) - (LJ_SIG/cutoff).powi(3)) } else { 0.0 };
    let p_corr = if TAILCORR { 16.0/3.0*std::f64::consts::PI*density.powi(2)*LJ_EPS*LJ_SIG.powi(3)*((2.0/3.0*(LJ_SIG/cutoff).powi(9)) - (LJ_SIG/cutoff).powi(3)) } else { 0.0 };

    println_stderr!("Particles: {}, Density: {}, Temperature: {}", num_particles, density, temperature);
    println_stderr!("System volume: {:8.3}, Dimensions {:.3}/{:.3}/{:.3}", volume, l_x, l_y, l_z);
    println_stderr!("Minimization steps: {}, Sampling steps: {}", minim_steps, sample_steps);
    println_stderr!("LJ params eps: {}, sigma: {}, cutoff: {}", LJ_EPS, LJ_SIG, cutoff);
    println_stderr!("Tailcorr: {:8.3}, Shift: {:8.3}, Pressurecprr: {:8.3}", e_corr, SHIFT, p_corr);

    let (mut energy, mut virial) = get_total_energy(&rx, &ry, &rz, num_particles, l_x, l_y, l_z, cutoff_squared, e_corr);
    let mut energy_sum = 0.0;
    let mut virial_sum = 0.0;
    let mut step_counter = 0;
    let mut accept_counter = 0;

    println_stderr!("");
    println_stderr!("################################################################");
    println_stderr!("#####################  Energy Minimization  ####################");
    println_stderr!("################################################################");
    println_stderr!("");

    for step in 0..minim_steps+sample_steps {

        // select rnd particle
        let rnd_index = particle_range.ind_sample(&mut rng);

        // store old position
        let oldX = rx[rnd_index];
        let oldY = ry[rnd_index];
        let oldZ = rz[rnd_index];

        // old particle energy
        let (old_particle_energy, old_particle_virial) = get_particle_energy(&rx, &ry, &rz, rnd_index, num_particles, l_x, l_y, l_z, cutoff_squared);

        // rnd displacement and PBC
        rx[rnd_index] += ( rng.gen::<f64>() - 0.5 ) * displacement;
        ry[rnd_index] += ( rng.gen::<f64>() - 0.5 ) * displacement;
        rz[rnd_index] += ( rng.gen::<f64>() - 0.5 ) * displacement;
        if rx[rnd_index] < 0.0 { rx[rnd_index] += l_x }
        if rx[rnd_index] > l_x { rx[rnd_index] -= l_x }
        if ry[rnd_index] < 0.0 { ry[rnd_index] += l_y }
        if ry[rnd_index] > l_y { ry[rnd_index] -= l_y }
        if rz[rnd_index] < 0.0 { rz[rnd_index] += l_z }
        if rz[rnd_index] > l_z { rz[rnd_index] -= l_z }

        // calculate energy difference
        let (new_particle_energy, new_particle_virial) = get_particle_energy(&rx, &ry, &rz, rnd_index, num_particles, l_x, l_y, l_z, cutoff_squared);
        let dE = new_particle_energy - old_particle_energy;

        //accept move
        if rng.gen::<f64>() < (-beta * dE).exp() {
            accept_counter += 1;
            if step % 1000 == 0 { // calculate total energy every 1000 steps to account for rounding errors
                let (e, v) = get_total_energy(&rx, &ry, &rz, num_particles, l_x, l_y, l_z, cutoff_squared, e_corr);
                energy = e;
                virial = v;
            } else {
                energy += dE;
                virial += new_particle_virial - old_particle_virial;
            }
        } else { // or restore old position
            rx[rnd_index] = oldX;
            ry[rnd_index] = oldY;
            rz[rnd_index] = oldZ;
        }

        // update sums for averaging
        step_counter += 1;
        energy_sum += energy;
        virial_sum += virial;

        // print some output during minimization
        if step < minim_steps && step_counter % 5000 == 0 && step != 0 {
            let tries_per_step : f64 = step_counter as f64 /accept_counter as f64;
            let acceptance_rate = 1.0/tries_per_step * 100.0;
            println_stderr!("Minim {}\tEnergy: {:.3}\tVirial: {:.3}\tAcceptance:{:.1}%\tDisplacement: {:.3}", step_counter, energy, virial, acceptance_rate, displacement);

            let mut scale_factor = (TRIES_INTENDED/tries_per_step * DISP_SCALE_FACTOR).abs();
            if tries_per_step < TRIES_INTENDED - 0.2 && displacement < max_displacement {
                displacement += displacement * scale_factor;
            } else if tries_per_step > TRIES_INTENDED + 0.2 && displacement > 0.0 {
                displacement -= displacement * scale_factor;
            }
        }

        // reset sums for sampling
        if step == minim_steps-1 {
            println_stderr!("");
            println_stderr!("################################################################");
            println_stderr!("##########################  Sampling  ##########################");
            println_stderr!("################################################################");
            println_stderr!("");
            step_counter = 0;
            accept_counter = 0;
            energy_sum = 0.0;
            virial_sum = 0.0;
        }

        if step > minim_steps && step_counter % 5000 == 0 {
            println_stderr!("Step {}\tEnergy: {:.3}\tVirial: {:.3}\t", step_counter, energy, virial);

        }

    }

    let final_energy = energy_sum/step_counter as f64;
    let particle_energy = final_energy / num_particles as f64;
    let final_virial = virial_sum / 3.0 / step_counter as f64 / volume;
    let pressure = virial_sum / 3.0 / step_counter as f64 / volume + density * temperature + p_corr;
    let final_acceptance_rate = 1.0/((accept_counter as f64)/(step_counter as f64)) * 100.0;

    println_stderr!("Done sampling!");
    println!("");
    println!("################################################################");
    println!("##########################  Results  ###########################");
    println!("################################################################");
    println!("");
    println!(
"Minimization: {}
Steps: {}

# Lennard Jones Params
epsilon: {}
sigma: {}
cutoff: {}

# System
Particles: {}
Density: {}
Temperature: {}
Volume: {}
Box dimension: {:.3}/{:.3}/{:.3}
Max Displacement: {}

# Correction
Energy correction: {}
Shift: {}
P-Correction: {}

# Averages
Tries: {}
Accepted: {}
Acceptance: {:.2}%
Energy: {}
Energy per particle: {}
Virial: {}
Pressure: {}",
         minim_steps, sample_steps,
        LJ_EPS, LJ_SIG, cutoff,
        num_particles, density, temperature, volume, l_x, l_y, l_z, displacement,
        e_corr, SHIFT, p_corr,
        step_counter, accept_counter, final_acceptance_rate, final_energy, particle_energy, final_virial, pressure);

}
<|endoftext|>


<commit_before>use std::env;

extern crate shaman;
extern crate libc;
extern crate nix;
extern crate rand;
extern crate rustc_serialize;
extern crate env_logger;
extern crate argparse;
extern crate quire;
extern crate time;
extern crate unshare;
extern crate signal;
#[macro_use] extern crate log;
#[macro_use] extern crate quick_error;

#[macro_use] mod macros;
mod config;
mod container;
mod file_util;
mod path_util;
mod process_util;
mod options;

// Commands
mod launcher;
mod network;
mod setup_netns;
mod version;
mod wrapper;
mod builder;

fn main() {
    env_logger::init().unwrap();
    match env::args().next().as_ref().map(|x| &x[..]) {
        Some("vagga") => launcher::main(),
        Some("vagga_launcher") => launcher::main(),
        Some("vagga_network") => network::main(),
        Some("vagga_setup_netns") => setup_netns::main(),
        Some("vagga_version") => version::main(),
        Some("vagga_wrapper") => wrapper::main(),
        Some("vagga_build") => builder::main(),
        _ => launcher::main(),
    }
}
<commit_msg>Set `warn` log level by default<commit_after>use std::env;

extern crate shaman;
extern crate libc;
extern crate nix;
extern crate rand;
extern crate rustc_serialize;
extern crate env_logger;
extern crate argparse;
extern crate quire;
extern crate time;
extern crate unshare;
extern crate signal;
#[macro_use] extern crate log;
#[macro_use] extern crate quick_error;

#[macro_use] mod macros;
mod config;
mod container;
mod file_util;
mod path_util;
mod process_util;
mod options;

// Commands
mod launcher;
mod network;
mod setup_netns;
mod version;
mod wrapper;
mod builder;

fn main() {
    if let Err(_) = env::var("RUST_LOG") {
        env::set_var("RUST_LOG", "warn");
    }
    env_logger::init().unwrap();
    match env::args().next().as_ref().map(|x| &x[..]) {
        Some("vagga") => launcher::main(),
        Some("vagga_launcher") => launcher::main(),
        Some("vagga_network") => network::main(),
        Some("vagga_setup_netns") => setup_netns::main(),
        Some("vagga_version") => version::main(),
        Some("vagga_wrapper") => wrapper::main(),
        Some("vagga_build") => builder::main(),
        _ => launcher::main(),
    }
}
<|endoftext|>


<commit_before>extern crate taiga;

use std::process;
use taiga::structs::common::Taiga;

fn main() {
    let taiga = Taiga::new("http://localhost:8000/api/v1".to_string());

    let taiga_logged = match taiga.auth("admin".to_string(), "123123".to_string()) {
        Ok(taiga_logged) => taiga_logged,
        Err(api_error) => {
            println!("{}", api_error.message);
            process::exit(1);
        }
    };

    match taiga_logged.projects().run() {
        Ok(response) => {
            for project in response {
                println!("{} - {}",
                    project.id,
                    project.name,
                );
            }
        },
        Err(e) => println!("{}", e.message)
    }

    match taiga_logged.projects().get(1).run() {
        Ok(project) => {
            println!("{} - {}",
                project.id,
                project.name,
            );
        },
        Err(e) => println!("{}", e.message)
    }

    match taiga_logged.projects().get(1).userstories().run() {
        Ok(userstories) => {
            for us in userstories {
                println!("{} - {}",
                    us.id,
                    us.subject,
                );
            }
        },
        Err(e) => println!("{}", e.message)
    }

    match taiga_logged.projects().get(1).userstories().get(1).run() {
        Ok(us) => {
            println!("{} - {}",
                us.id,
                us.subject,
            );
        },
        Err(e) => println!("{}", e.message)
    }

    match taiga_logged.userstories().run() {
        Ok(userstories) => {
            for us in userstories {
                println!("{} - {}",
                    us.id,
                    us.subject,
                );
            }
        },
        Err(e) => println!("{}", e.message)
    }
}
<commit_msg>Remove main.rs<commit_after><|endoftext|>


<commit_before>#[macro_use]
extern crate error_chain;
#[macro_use]
extern crate serde_derive;
extern crate toml;
extern crate clap;
extern crate walkdir;
extern crate pulldown_cmark;
extern crate liquid;
extern crate image;
extern crate ftp;
extern crate checksums;
extern crate term_painter;
extern crate rpassword;
extern crate rayon;

mod config;
mod render;
mod template;
mod sync;
mod filter;
mod errors;

use std::fs;
use std::path::Path;
use clap::{App, Arg, SubCommand};
use config::Config;
use sync::Synchronizer;

fn build(path: &Path, conf: &Config) {
    if let Err(ref e) = render::build(path, conf) {
        errors::print_error(e);
    }
}

fn sync(path: &Path, conf: &Config, with_build: bool, overwrite: bool) {
    if with_build {
        build(path, conf);
    }
    let mut synchronizer = Synchronizer::new(conf);
    if overwrite {
        synchronizer.push_all_files();
    } else {
        synchronizer.execute();
    }
}

fn main() {
    // parse command line options
    //
    let matches = App::new("neptungen")
        .about("Simple website generator")
        .version("0.0.1")
        .arg(Arg::with_name("project_path")
            .short("p")
            .long("project_path")
            .help("Path to the root folder of the website project")
            .multiple(false)
            .takes_value(true))
        .subcommand(SubCommand::with_name("show_config")
            .about("Prints the configuration of the config.toml file"))
        .subcommand(SubCommand::with_name("build").about("Generate the website"))
        .subcommand(SubCommand::with_name("sync")
            .about("Used to synchronize the website with an ftp server")
            .arg(Arg::with_name("overwrite")
                .short("o")
                .long("overwrite")
                .help("Overwrites all remote files")
                .multiple(false)
                .takes_value(false))
            .arg(Arg::with_name("with_build")
                .short("n")
                .long("with_build")
                .help("Build the project before executing the sync")
                .multiple(false)
                .takes_value(false)))
        .get_matches();
    let path = if matches.is_present("project_path") {
        fs::canonicalize(matches.value_of("project_path").unwrap_or("."))
            .expect("could not determine path")
    } else {
        std::env::current_dir().unwrap_or(fs::canonicalize(".").expect("could not determine path"))
    };

    // load configuration from config.toml if present
    let conf = match Config::load(path.as_path()) {
        Ok(conf) => conf,
        Err(ref e) => {
            errors::print_message(e);
            Config::new(path.as_path())
        }
    };

    match matches.subcommand() {
        ("show_config", Some(_)) => {
            conf.print();
        }
        ("build", Some(_)) => {
            build(path.as_path(), &conf);
        }
        ("sync", Some(matches)) => {
            sync(path.as_path(),
                 &conf,
                 matches.is_present("with_build"),
                 matches.is_present("overwrite"))
        }
        _ => {
            println!("{}", matches.usage());
        }
    }
}<commit_msg>let clap automatically determine the version from cargo.toml<commit_after>#[macro_use]
extern crate error_chain;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate clap;
extern crate toml;
extern crate walkdir;
extern crate pulldown_cmark;
extern crate liquid;
extern crate image;
extern crate ftp;
extern crate checksums;
extern crate term_painter;
extern crate rpassword;
extern crate rayon;

mod config;
mod render;
mod template;
mod sync;
mod filter;
mod errors;

use std::fs;
use std::path::Path;
use clap::{App, Arg, SubCommand};
use config::Config;
use sync::Synchronizer;

fn build(path: &Path, conf: &Config) {
    if let Err(ref e) = render::build(path, conf) {
        errors::print_error(e);
    }
}

fn sync(path: &Path, conf: &Config, with_build: bool, overwrite: bool) {
    if with_build {
        build(path, conf);
    }
    let mut synchronizer = Synchronizer::new(conf);
    if overwrite {
        synchronizer.push_all_files();
    } else {
        synchronizer.execute();
    }
}

fn main() {
    // parse command line options
    //
    let matches = App::new("neptungen")
        .about("Simple website generator")
        .version(crate_version!())
        .arg(Arg::with_name("project_path")
            .short("p")
            .long("project_path")
            .help("Path to the root folder of the website project")
            .multiple(false)
            .takes_value(true))
        .subcommand(SubCommand::with_name("show_config")
            .about("Prints the configuration of the config.toml file"))
        .subcommand(SubCommand::with_name("build").about("Generate the website"))
        .subcommand(SubCommand::with_name("sync")
            .about("Used to synchronize the website with an ftp server")
            .arg(Arg::with_name("overwrite")
                .short("o")
                .long("overwrite")
                .help("Overwrites all remote files")
                .multiple(false)
                .takes_value(false))
            .arg(Arg::with_name("with_build")
                .short("n")
                .long("with_build")
                .help("Build the project before executing the sync")
                .multiple(false)
                .takes_value(false)))
        .get_matches();
    let path = if matches.is_present("project_path") {
        fs::canonicalize(matches.value_of("project_path").unwrap_or("."))
            .expect("could not determine path")
    } else {
        std::env::current_dir().unwrap_or(fs::canonicalize(".").expect("could not determine path"))
    };

    // load configuration from config.toml if present
    let conf = match Config::load(path.as_path()) {
        Ok(conf) => conf,
        Err(ref e) => {
            errors::print_message(e);
            Config::new(path.as_path())
        }
    };

    match matches.subcommand() {
        ("show_config", Some(_)) => {
            conf.print();
        }
        ("build", Some(_)) => {
            build(path.as_path(), &conf);
        }
        ("sync", Some(matches)) => {
            sync(path.as_path(),
                 &conf,
                 matches.is_present("with_build"),
                 matches.is_present("overwrite"))
        }
        _ => {
            println!("{}", matches.usage());
        }
    }
}<|endoftext|>


<commit_before>#![feature(globs)]
#![allow(dead_code)]

extern crate libc;
extern crate collections;
use libc::funcs::posix88::unistd::*;
use std::os;
use std::mem;
use posix::*;
use std::c_str::CString;

mod ptrace;
mod posix;
mod syscall;

fn main () {
    let env = "/usr/bin/env";
    let mut c = vec!["env".to_string()];
    if os::args().tail().len() != 0 {
        c.push_all(os::args().tail());
    } else {
        c.push_all(["echo".to_string(), "No argumets".to_string()]);
    }
    unsafe {
        let result = fork_wrapper();
        match result {
            ForkChild =>  {
                let mut vec = Vec::with_capacity(c.len());
                let mut ptr_vec = Vec::with_capacity(c.len());

                for v in c.iter()
                {
                    let c_str = v.as_slice().to_c_str();
                    ptr_vec.push(c_str.as_ptr());
                    vec.push(c_str);
                }

                let t = ptr_vec.as_mut_ptr();
                ptrace::trace_me();
                execv(env.to_c_str().as_ptr(), t);
            }
            ForkFailure(_) => {
                println!("An error occurred: {}", result.get_error_as_string());
            }
            ForkParent(child_pid) => {
                let result = ptrace::init_trace(child_pid);

                if result.is_error() {
                    println!("An error in init_ptrace occurred: {}", result.get_error_as_string());
                }
                loop {
                    let result = posix::waitpid_wrapper(child_pid, 0);
                    match result {
                        WaitPidFailure(_) => {
                            println!("An error in wait occurred: {}", result.get_error_as_string());
                            break;
                        },
                        WaitPidSuccess(pid, status) => {
                            if ((status >> 8) & (0x80 | posix::SIGTRAP)) != 0 {
                                match ptrace::get_registers(pid) {
                                    Ok(ptrace::UserRegs { orig_rax: syscall_no, rdi: rdi, .. }) => {
                                            //println!("Syscall {} with {}", syscall::get_syscall_name_as_str(syscall_no as uint), handle_syscall_arguments(pid, rdi));
                                        if syscall_no == 2 {
                                            println!("{}", handle_syscall_arguments(pid, rdi));
                                        }
                                        ptrace::syscall(pid); //need this to get only at end
                                        posix::waitpid_wrapper(pid, 0); // and this too
                                    },
                                    Err(errno) => {
                                        println!("Error in ptrace {}", get_strerror(errno)); break;
                                    },
                                }
                            }
                            let result = ptrace::resume_trace(child_pid);
                            if result.is_error() {
                                println!("An error in ptrace_resume occurred: {}", result.get_error_as_string());
                                break;
                            }
                        },
                    }
                }

            }
        }
    }
}

fn pstrdup(word: u64) -> String {
    unsafe {
        let mut bytes    = Vec::new();
        //let mut mut_addr = addr as libc::uint64_t;

        let mut i = 0;

        // XXX I'm not using a for loop because of a bug in Rust
        while i < mem::size_of::<libc::uint64_t>() {
            // XXX byte order
            let lsb = (word >> (i * 8)) & 0xFF;
            if lsb == 0 {
                break;
            }
            bytes.push(lsb as u8);
            i += 1;
        }
        //mut_addr += mem::size_of::<libc::uint64_t>() as libc::uint64_t;
        let result = std::str::raw::from_utf8(bytes.as_slice()).to_string();
        result
            //TODO notes touch shows no open, > shows open
        //println!("Syscall {} with {}", syscall::get_syscall_name_as_str(syscall_no as uint), CString::new(rdi as *const i8, false).as_str()); //TODO
    }
}

fn get_program_args(pid: int, addr: *mut libc::c_void) -> String {
    let mut args     = Vec::new();
    let mut mut_addr = addr as libc::uint64_t;

    loop {
        match ptrace::peektext(pid, mut_addr as *mut libc::c_void) {
            Err(_) | Ok(0) => break,
            Ok(word)       => {
                args.push(pstrdup(word));
            }
        }

        mut_addr += mem::size_of::<libc::uint64_t>() as libc::uint64_t;
    }
    args.concat()
}

fn handle_syscall_arguments(pid: int, argv_ptr: libc::uint64_t) -> String {
    let argv = get_program_args(pid, argv_ptr as *mut libc::c_void);
    argv
}
<commit_msg>How to properly do argument retrieving<commit_after>#![feature(globs)]
#![allow(dead_code)]

extern crate libc;
extern crate collections;
use libc::funcs::posix88::unistd::*;
use std::os;
use std::mem;
use posix::*;
use std::c_str::CString;

mod ptrace;
mod posix;
mod syscall;

fn main () {
    let env = "/usr/bin/env";
    let mut c = vec!["env".to_string()];
    if os::args().tail().len() != 0 {
        c.push_all(os::args().tail());
    } else {
        c.push_all(["echo".to_string(), "No argumets".to_string()]);
    }
    unsafe {
        let result = fork_wrapper();
        match result {
            ForkChild =>  {
                let mut vec = Vec::with_capacity(c.len());
                let mut ptr_vec = Vec::with_capacity(c.len());

                for v in c.iter()
                {
                    let c_str = v.as_slice().to_c_str();
                    ptr_vec.push(c_str.as_ptr());
                    vec.push(c_str);
                }

                let t = ptr_vec.as_mut_ptr();
                ptrace::trace_me();
                execv(env.to_c_str().as_ptr(), t);
            }
            ForkFailure(_) => {
                println!("An error occurred: {}", result.get_error_as_string());
            }
            ForkParent(child_pid) => {
                let result = ptrace::init_trace(child_pid);

                if result.is_error() {
                    println!("An error in init_ptrace occurred: {}", result.get_error_as_string());
                }
                loop {
                    let result = posix::waitpid_wrapper(child_pid, 0);
                    match result {
                        WaitPidFailure(_) => {
                            println!("An error in wait occurred: {}", result.get_error_as_string());
                            break;
                        },
                        WaitPidSuccess(pid, status) => {
                            if ((status >> 8) & (0x80 | posix::SIGTRAP)) != 0 {
                                match ptrace::get_registers(pid) {
                                    Ok(ptrace::UserRegs { orig_rax: syscall_no, rdi: rdi, .. }) => {
                                            //println!("Syscall {} with {}", syscall::get_syscall_name_as_str(syscall_no as uint), handle_syscall_arguments(pid, rdi));
                                        if syscall_no == 2 {
                                            println!("{}", handle_syscall_arguments(pid, rdi));
                                        }
                                        ptrace::syscall(pid); //need this to get only at end
                                        posix::waitpid_wrapper(pid, 0); // and this too
                                    },
                                    Err(errno) => {
                                        println!("Error in ptrace {}", get_strerror(errno)); break;
                                    },
                                }
                            }
                            let result = ptrace::resume_trace(child_pid);
                            if result.is_error() {
                                println!("An error in ptrace_resume occurred: {}", result.get_error_as_string());
                                break;
                            }
                        },
                    }
                }

            }
        }
    }
}

fn pstrdup(word: u64) -> String {
    unsafe {
        let mut bytes    = Vec::new();
        //let mut mut_addr = addr as libc::uint64_t;

        let mut i = 0;

        // XXX I'm not using a for loop because of a bug in Rust
        while i < mem::size_of::<libc::uint64_t>() {
            // XXX byte order
            let lsb = (word >> (i * 8)) & 0xFF;
            if lsb == 0 {
                break;
            }
            bytes.push(lsb as u8);
            i += 1;
        }
        //mut_addr += mem::size_of::<libc::uint64_t>() as libc::uint64_t;
        let result = std::str::raw::from_utf8(bytes.as_slice()).to_string();
        result
            //TODO notes touch shows no open, > shows open
        //println!("Syscall {} with {}", syscall::get_syscall_name_as_str(syscall_no as uint), CString::new(rdi as *const i8, false).as_str()); //TODO
    }
}

fn get_program_args(pid: int, addr: *mut libc::c_void) -> String {
    let mut args     = Vec::new();
    let mut mut_addr = addr as libc::uint64_t;
    let byte_stack

    loop {
        match ptrace::peektext(pid, mut_addr as *mut libc::c_void) {
            Err(_) | Ok(0) => break,
            Ok(word)       => {

                for b in bytes(word):
                    push(b)
                    if (b == 0):
                        break loop
            }
        }

    }

    from_utf8(byte_stack)
}

fn handle_syscall_arguments(pid: int, argv_ptr: libc::uint64_t) -> String {
    let argv = get_program_args(pid, argv_ptr as *mut libc::c_void);
    argv
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate clap;
use clap::{App, Arg, SubCommand};
extern crate glob;
extern crate reqwest;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate toml;

#[macro_use]
extern crate lazy_static;

mod structs;
mod ghclient;
mod statics;
use statics::CLIENT;

fn main() {
    let user_arg = Arg::with_name("USER").required(true)
                                         .index(1)
                                         .help("user name");
    let conf_arg = Arg::with_name("CONF").required(true)
                                         .index(1)
                                         .help("conf path");
    let app = App::new(crate_name!()).version(crate_version!())
                                     .author(crate_authors!())
                                     .about(crate_description!())
                                     .subcommand(SubCommand::with_name("key").about("Gets user public key")
                                                                             .arg(user_arg))
                                     .subcommand(SubCommand::with_name("pam").about("Executes pam check"))
                                     .subcommand(SubCommand::with_name("cleanup").about("Cleans caches up"))
                                     .subcommand(SubCommand::with_name("check").about("Check configuration")
                                                                               .arg(conf_arg))
                                     .get_matches();

    match app.subcommand() {
        ("key", Some(sub)) => match CLIENT.print_user_public_key(sub.value_of("USER").unwrap()) {
            Ok(_) => std::process::exit(0),
            Err(_) => std::process::exit(21),
        },
        ("check", Some(sub)) => match structs::Config::new(std::path::Path::new(sub.value_of("CONF").unwrap())) {
            Ok(_) => std::process::exit(0),
            Err(_) => std::process::exit(11),
        },
        ("cleanup", Some(_)) => CLIENT.clear_all_caches().unwrap(),
        ("pam", Some(_)) => match std::env::var("PAM_USER") {
            Ok(user) => {
                if CLIENT.check_pam(&user).unwrap() {
                    std::process::exit(0);
                } else {
                    std::process::exit(1)
                }
            }
            Err(e) => println!("PAM_USER: {}", e),
        },
        (&_, _) => println!("{}", app.usage()),
    }
}
<commit_msg>Refactor stds<commit_after>#[macro_use]
extern crate clap;
use clap::{App, Arg, SubCommand};
extern crate glob;
extern crate reqwest;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate toml;

#[macro_use]
extern crate lazy_static;

mod structs;
mod ghclient;
mod statics;
use statics::CLIENT;

fn main() {
    let user_arg = Arg::with_name("USER").required(true)
                                         .index(1)
                                         .help("user name");
    let conf_arg = Arg::with_name("CONF").required(true)
                                         .index(1)
                                         .help("conf path");
    let app = App::new(crate_name!()).version(crate_version!())
                                     .author(crate_authors!())
                                     .about(crate_description!())
                                     .subcommand(SubCommand::with_name("key").about("Gets user public key")
                                                                             .arg(user_arg))
                                     .subcommand(SubCommand::with_name("pam").about("Executes pam check"))
                                     .subcommand(SubCommand::with_name("cleanup").about("Cleans caches up"))
                                     .subcommand(SubCommand::with_name("check").about("Check configuration")
                                                                               .arg(conf_arg))
                                     .get_matches();

    use std::env;
    use std::path::Path;
    use std::process;

    match app.subcommand() {
        ("key", Some(sub)) => match CLIENT.print_user_public_key(sub.value_of("USER").unwrap()) {
            Ok(_) => process::exit(0),
            Err(_) => process::exit(21),
        },
        ("check", Some(sub)) => match structs::Config::new(Path::new(sub.value_of("CONF").unwrap())) {
            Ok(_) => process::exit(0),
            Err(_) => process::exit(11),
        },
        ("cleanup", Some(_)) => CLIENT.clear_all_caches().unwrap(),
        ("pam", Some(_)) => match env::var("PAM_USER") {
            Ok(user) => {
                if CLIENT.check_pam(&user).unwrap() {
                    process::exit(0);
                } else {
                    process::exit(1)
                }
            }
            Err(e) => println!("PAM_USER: {}", e),
        },
        (&_, _) => println!("{}", app.usage()),
    }
}
<|endoftext|>


<commit_before>#![feature(slice_patterns)]
extern crate nix;
extern crate libc;
use std::env;
use libc::{pid_t,c_void};
use nix::sys::ptrace;
use nix::sys::ptrace::ptrace::{PTRACE_ATTACH,PTRACE_DETACH,PTRACE_GETREGS};

#[cfg(target_arch = "x86_64")]
#[derive(Debug,Default)]
#[repr(C)]
struct user_regs_struct {
    r15: u64,
    r14: u64,
    r13: u64,
    r12: u64,
    rbp: u64,
    rbx: u64,
    r11: u64,
    r10: u64,
    r9: u64,
    r8: u64,
    rax: u64,
    rcx: u64,
    rdx: u64,
    rsi: u64,
    rdi: u64,
    orig_rax: u64,
    rip: u64,
    cs: u64,
    eflags: u64,
    rsp: u64,
    ss: u64,
    fs_base: u64,
    gs_base: u64,
    ds: u64,
    es: u64,
    fs: u64,
    gs: u64,
}

fn infect(pid: pid_t) -> Result<(),()> {
    ptrace::ptrace(PTRACE_ATTACH,pid,0 as *mut c_void ,0 as *mut c_void);
    let mut regs: user_regs_struct = user_regs_struct::default();
    ptrace::ptrace(PTRACE_GETREGS,pid,&mut regs as *mut user_regs_struct as *mut c_void,&mut regs as *mut user_regs_struct as *mut c_void);
    println!("{:?}",regs);
    ptrace::ptrace(PTRACE_DETACH,pid,0 as *mut c_void ,0 as *mut c_void);
    unimplemented!()
}
fn main() {
     let args: Vec<String> = env::args().collect();

     match &args[1..] {
         &[ref pid, ref code] => {
            infect(2138);
             },
         _ => unimplemented!(),
     }
}
<commit_msg>getregs working<commit_after>#![feature(slice_patterns)]
extern crate nix;
extern crate libc;
use std::{env, ptr,mem};
use libc::{pid_t, c_void, waitpid};
use nix::sys::ptrace;
use nix::sys::ptrace::ptrace::{PTRACE_ATTACH, PTRACE_DETACH, PTRACE_GETREGS};

// #[cfg(target_arch = "x86_64")]
#[derive(Debug,Default)]
#[repr(C)]
struct user_regs_struct {
    r15: u64,
    r14: u64,
    r13: u64,
    r12: u64,
    rbp: u64,
    rbx: u64,
    r11: u64,
    r10: u64,
    r9: u64,
    r8: u64,
    rax: u64,
    rcx: u64,
    rdx: u64,
    rsi: u64,
    rdi: u64,
    orig_rax: u64,
    rip: u64,
    cs: u64,
    eflags: u64,
    rsp: u64,
    ss: u64,
    fs_base: u64,
    gs_base: u64,
    ds: u64,
    es: u64,
    fs: u64,
    gs: u64,
}

fn infect(pid: pid_t) -> Result<(), ()> {
    ptrace::ptrace(PTRACE_ATTACH, pid, 0 as *mut c_void, 0 as *mut c_void);
    let mut regs: user_regs_struct;
    unsafe {
        waitpid(pid, 0 as *mut i32, 0);
        regs = mem::uninitialized();
    }

    ptrace::ptrace(PTRACE_GETREGS,
                   pid,
                   &mut regs as *mut user_regs_struct as *mut c_void,
                   &mut regs as *mut user_regs_struct as *mut c_void);
    println!("{:?}", regs);
    ptrace::ptrace(PTRACE_DETACH, pid, 0 as *mut c_void, 0 as *mut c_void);
    Ok(())
}
fn main() {
    let args: Vec<String> = env::args().collect();

    match &args[1..] {
        &[ref pid, ref code] => {
            infect(pid.parse::<i32>().unwrap());
        }
        _ => unimplemented!(),
    }
}
<|endoftext|>