<commit_before>extern crate hyper;
extern crate hyper_openssl;
extern crate hubcaps;
extern crate chrono;
extern crate rand;
extern crate reqwest;
extern crate docopt;

#[macro_use]
extern crate error_chain;

#[macro_use]
extern crate serde_derive;

use std::fs::File;
use std::io::{self, BufRead, BufReader, Write};
use std::process::{Command, Stdio};
use std::fmt;

use hyper::Client;
use hyper::net::HttpsConnector;
use hyper_openssl::OpensslClient;

use hubcaps::{Credentials, Github};
use hubcaps::repositories::Repository;
use hubcaps::rep::{IssueListOptionsBuilder, Issue};

use chrono::{DateTime, UTC};

use docopt::Docopt;

const USAGE: &'static str = "
nag-rs

Usage:
  nag-rs [-d] <token> <file>

Options:
  -d       Dry run; prints emails to stdout
";

error_chain! {
    foreign_links {
        Hubcaps(::hubcaps::Error);
        Reqwest(::reqwest::Error);
        Io(::std::io::Error);
    }
}

#[derive(Debug, Deserialize)]
struct FcpItem {
    issue: FcpIssue,
}

#[derive(Debug, Deserialize)]
struct FcpIssue {
    repository: String,
    number: u64,
    title: String,
    updated_at: String,
}

#[derive(Debug, Deserialize)]
struct FcpUser {
    login: String,
}

#[derive(Debug, Deserialize)]
struct FcpList(FcpUser, Vec<FcpItem>);

#[derive(Debug)]
enum Kind {
    FCP,
    RFC,
    PR,
}

struct Item {
    number: u64,
    kind: Kind,
    url: String,
    title: String,
    last_update: DateTime<UTC>,
}

impl Item {
    fn from_issue(issue: &Issue, kind: Kind) -> Item {
        Item {
            number: issue.number,
            kind: kind,
            url: issue.html_url.clone(),
            title: issue.title.clone(),
            last_update: issue.updated_at.parse()
                .unwrap_or(UTC::now()),
        }
    }

    fn from_fcp(item: &FcpItem) -> Item {
        Item {
            number: item.issue.number,
            kind: Kind::FCP,
            url: format!("https://github.com/{}/issues/{}",
                         item.issue.repository,
                         item.issue.number),
            title: item.issue.title.clone(),
            last_update: (item.issue.updated_at.clone() + "Z").parse()
                .unwrap_or(UTC::now()),
        }
    }
}

impl fmt::Display for Item {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "
{:?}: {}
Last update: {}",
               self.kind, self.url, self.title, self.last_update.date().format("%Y-%m-%d"))
    }
}

#[derive(Clone)]
struct TeamMember {
    login: String,
    email: String,
}

impl TeamMember {
    fn items(&self, rust: &Repository, rfcs: &Repository) -> Result<Vec<Item>> {
        let filter = IssueListOptionsBuilder::new()
            .assignee(&self.login[..])
            .build();
        let mut items: Vec<Item> = rust.issues().list(&filter)?
            .iter()
            .map(|issue| Item::from_issue(issue, Kind::PR))
            .filter(|item| item.url.contains("pull"))
            .collect();

        let filter = IssueListOptionsBuilder::new()
            .assignee(&self.login[..])
            .build();
        items.extend(rfcs.issues().list(&filter)?
                     .iter()
                     .map(|issue| Item::from_issue(issue, Kind::RFC))
                     .filter(|item| item.url.contains("pull")));

        let mut url = String::from("http://rusty-dash.com/api/fcp/");
        url.push_str(&self.login);

        let mut resp = reqwest::get(&url)?;
        let list: FcpList = resp.json()?;
        items.extend(list.1.iter().map(Item::from_fcp));

        items.sort_by_key(|item| item.number);
        items.dedup_by_key(|item| item.number);
        items.sort_by_key(|item| item.last_update);

        Ok(items)
    }

    fn process(&self, dry_run: bool, rust: &Repository, rfcs: &Repository) -> Result<()> {
        let items = self.items(rust, rfcs)?;
        if !items.is_empty() {
            if dry_run {
                write_email(&mut io::stdout(), self, items)
            } else {
                send_email(self, items)
            }
        } else {
            Ok(())
        }
    }
}

fn write_email<W: Write>(f: &mut W, member: &TeamMember, mut items: Vec<Item>)
                         -> Result<()>
{
    writeln!(f, "\
Subject: Rust review list for {date}
From: {from}
To: {to}
MIME-Version: 1.0
Content-Type: text/html

Hello Rust subteam member! You have {total} items awaiting review.
This email contains your reviewing mission for today.
",
                 date=UTC::now().format("%Y-%m-%d"),
                 total=items.len(),
                 from="nagbot@rust-lang.org",
                 to=member.email)?;

    if items.len() > 6 {
        writeln!(f, "
Three stalest items:")?;
        for item in items.drain(..3) {
            writeln!(f, "{}", item)?
        }

        writeln!(f, "
Three random items:")?;
        for _ in 0..3 {
            let len = items.len();
            if len == 0 { break; }
            let item = items.swap_remove(rand::random::<usize>() % len);
            writeln!(f, "{}", item)?
        }
    } else {
        writeln!(f, "
All items:")?;
        for item in items {
            writeln!(f, "{}", item)?
        }
    }

    Ok(())
}

fn send_email(member: &TeamMember, items: Vec<Item>) -> Result<()> {
    let mut child = Command::new("sendmail").arg("-t")
        .stdin(Stdio::piped())
        .spawn()?;

    write_email(&mut io::BufWriter::new(child.stdin.as_mut().unwrap()), member, items)?;

    let status = child.wait()?;
    if !status.success() {
        panic!()
    }

    Ok(())
}

fn run(dry_run: bool, token: &str, input_file: &str) -> Result<()> {
    let ssl = OpensslClient::new().chain_err(|| "couldn't set up SSL")?;
    let connector = HttpsConnector::new(ssl);
    let client = Client::with_connector(connector);
    let github = Github::new(
        "nag-rs",
        client,
        Credentials::Token(token.to_owned())
    );

    let rust = github.repo("rust-lang", "rust");
    let rfcs = github.repo("rust-lang", "rfcs");
    let input = File::open(input_file)
        .chain_err(|| format!("couldn't open input file {}", input_file))?;

    for line in BufReader::new(input).lines() {
        let line = line.chain_err(|| "couldn't read line")?;
        let mut line_iter = line.split(",");
        let member= TeamMember {
            login: line_iter.next().ok_or("malformed input")?.to_owned(),
            email: line_iter.next().ok_or("malformed input")?.to_owned(),
        };

        print_if_err(member.process(dry_run, &rust, &rfcs),
                     &format!("error for {}", member.login));
    }

    Ok(())
}

fn print_if_err(res: Result<()>, msg: &str) {
    if let Err(ref e) = res {
        writeln!(io::stderr(), "{}: {}", e, msg).unwrap();

        for e in e.iter().skip(1) {
            writeln!(io::stderr(), "caused by: {}", e).unwrap();
        }
    }
}

fn main() {
    let args = Docopt::new(USAGE)
        .and_then(|dopt| dopt.parse())
        .unwrap_or_else(|e| e.exit());

    let res = run(args.get_bool("-d"),
                  &args.get_str("<token>"),
                  &args.get_str("<file>"));
    print_if_err(res, "error");
}
<commit_msg>work on stable rust, clean up magic numbers<commit_after>extern crate hyper;
extern crate hyper_openssl;
extern crate hubcaps;
extern crate chrono;
extern crate rand;
extern crate reqwest;
extern crate docopt;

#[macro_use]
extern crate error_chain;

#[macro_use]
extern crate serde_derive;

use std::fs::File;
use std::io::{self, BufRead, BufReader, Write};
use std::process::{Command, Stdio};
use std::fmt;

use hyper::Client;
use hyper::net::HttpsConnector;
use hyper_openssl::OpensslClient;

use hubcaps::{Credentials, Github};
use hubcaps::repositories::Repository;
use hubcaps::rep::{IssueListOptionsBuilder, Issue};

use chrono::{DateTime, UTC};

use docopt::Docopt;

const USAGE: &'static str = "
nag-rs

Usage:
  nag-rs [-d] <token> <file>

Options:
  -d       Dry run; prints emails to stdout
";

error_chain! {
    foreign_links {
        Hubcaps(::hubcaps::Error);
        Reqwest(::reqwest::Error);
        Io(::std::io::Error);
    }
}

#[derive(Debug, Deserialize)]
struct FcpItem {
    issue: FcpIssue,
}

#[derive(Debug, Deserialize)]
struct FcpIssue {
    repository: String,
    number: u64,
    title: String,
    updated_at: String,
}

#[derive(Debug, Deserialize)]
struct FcpUser {
    login: String,
}

#[derive(Debug, Deserialize)]
struct FcpList(FcpUser, Vec<FcpItem>);

#[derive(Debug)]
enum Kind {
    FCP,
    RFC,
    PR,
}

struct Item {
    number: u64,
    kind: Kind,
    url: String,
    title: String,
    last_update: DateTime<UTC>,
}

impl Item {
    fn from_issue(issue: &Issue, kind: Kind) -> Item {
        Item {
            number: issue.number,
            kind: kind,
            url: issue.html_url.clone(),
            title: issue.title.clone(),
            last_update: issue.updated_at.parse()
                .unwrap_or(UTC::now()),
        }
    }

    fn from_fcp(item: &FcpItem) -> Item {
        Item {
            number: item.issue.number,
            kind: Kind::FCP,
            url: format!("https://github.com/{}/issues/{}",
                         item.issue.repository,
                         item.issue.number),
            title: item.issue.title.clone(),
            last_update: (item.issue.updated_at.clone() + "Z").parse()
                .unwrap_or(UTC::now()),
        }
    }
}

impl fmt::Display for Item {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "
{:?}: {}
Last update: {}",
               self.kind, self.url, self.title, self.last_update.date().format("%Y-%m-%d"))
    }
}

#[derive(Clone)]
struct TeamMember {
    login: String,
    email: String,
}

impl TeamMember {
    fn items(&self, rust: &Repository, rfcs: &Repository) -> Result<Vec<Item>> {
        let filter = IssueListOptionsBuilder::new()
            .assignee(&self.login[..])
            .build();
        let mut items: Vec<Item> = rust.issues().list(&filter)?
            .iter()
            .map(|issue| Item::from_issue(issue, Kind::PR))
            .filter(|item| item.url.contains("pull"))
            .collect();

        let filter = IssueListOptionsBuilder::new()
            .assignee(&self.login[..])
            .build();
        items.extend(rfcs.issues().list(&filter)?
                     .iter()
                     .map(|issue| Item::from_issue(issue, Kind::RFC))
                     .filter(|item| item.url.contains("pull")));

        let mut url = String::from("http://rusty-dash.com/api/fcp/");
        url.push_str(&self.login);

        let mut resp = reqwest::get(&url)?;
        let list: FcpList = resp.json()?;
        items.extend(list.1.iter().map(Item::from_fcp));

        // wait until Rust 1.16
        //items.sort_by_key(|item| item.number);
        //items.dedup_by_key(|item| item.number);
        items.sort_by_key(|item| item.last_update);

        Ok(items)
    }

    fn process(&self, dry_run: bool, rust: &Repository, rfcs: &Repository) -> Result<()> {
        let items = self.items(rust, rfcs)?;
        if !items.is_empty() {
            if dry_run {
                write_email(&mut io::stdout(), self, items)
            } else {
                send_email(self, items)
            }
        } else {
            Ok(())
        }
    }
}

fn write_email<W: Write>(f: &mut W, member: &TeamMember, mut items: Vec<Item>)
                         -> Result<()>
{
    writeln!(f, "\
Subject: Rust review list for {date}
From: {from}
To: {to}
MIME-Version: 1.0
Content-Type: text/html

Hello Rust subteam member! You have {total} items awaiting review.
This email contains your reviewing mission for today.
",
                 date=UTC::now().format("%Y-%m-%d"),
                 total=items.len(),
                 from="nagbot@rust-lang.org",
                 to=member.email)?;

    const STALE_COUNT: usize = 3;
    const RAND_COUNT: usize = 2;

    if items.len() > STALE_COUNT + RAND_COUNT {
        writeln!(f, "
Three stalest items:")?;
        for item in items.drain(..STALE_COUNT) {
            writeln!(f, "{}", item)?
        }

        writeln!(f, "
Three random items:")?;
        for _ in 0..RAND_COUNT {
            let len = items.len();
            if len == 0 { break; }
            let item = items.swap_remove(rand::random::<usize>() % len);
            writeln!(f, "{}", item)?
        }
    } else {
        writeln!(f, "
All items:")?;
        for item in items {
            writeln!(f, "{}", item)?
        }
    }

    Ok(())
}

fn send_email(member: &TeamMember, items: Vec<Item>) -> Result<()> {
    let mut child = Command::new("sendmail").arg("-t")
        .stdin(Stdio::piped())
        .spawn()?;

    write_email(&mut io::BufWriter::new(child.stdin.as_mut().unwrap()), member, items)?;

    let status = child.wait()?;
    if !status.success() {
        panic!()
    }

    Ok(())
}

fn run(dry_run: bool, token: &str, input_file: &str) -> Result<()> {
    let ssl = OpensslClient::new().chain_err(|| "couldn't set up SSL")?;
    let connector = HttpsConnector::new(ssl);
    let client = Client::with_connector(connector);
    let github = Github::new(
        "nag-rs",
        client,
        Credentials::Token(token.to_owned())
    );

    let rust = github.repo("rust-lang", "rust");
    let rfcs = github.repo("rust-lang", "rfcs");
    let input = File::open(input_file)
        .chain_err(|| format!("couldn't open input file {}", input_file))?;

    for line in BufReader::new(input).lines() {
        let line = line.chain_err(|| "couldn't read line")?;
        let mut line_iter = line.split(",");
        let member= TeamMember {
            login: line_iter.next().ok_or("malformed input")?.to_owned(),
            email: line_iter.next().ok_or("malformed input")?.to_owned(),
        };

        print_if_err(member.process(dry_run, &rust, &rfcs),
                     &format!("error for {}", member.login));
    }

    Ok(())
}

fn print_if_err(res: Result<()>, msg: &str) {
    if let Err(ref e) = res {
        writeln!(io::stderr(), "{}: {}", e, msg).unwrap();

        for e in e.iter().skip(1) {
            writeln!(io::stderr(), "caused by: {}", e).unwrap();
        }
    }
}

fn main() {
    let args = Docopt::new(USAGE)
        .and_then(|dopt| dopt.parse())
        .unwrap_or_else(|e| e.exit());

    let res = run(args.get_bool("-d"),
                  &args.get_str("<token>"),
                  &args.get_str("<file>"));
    print_if_err(res, "error");
}
<|endoftext|>


<commit_before>extern crate inotify;

use inotify::wrapper::INotify;

use std::vec::Vec;
use std::os;

use package::Package;

pub mod package;

fn main() {
    let repo_name = "siosm-aur";
    // let db_filename = "siosm-aur.db";

    // let mut packages_ready = Vec::new();
    // let mut signatures_ready = Vec::new();

    println!("Looking for packages in repo {}", repo_name);

    let mut handler = INotify::init().unwrap();
    handler.add_watch(&os::getcwd(), inotify::ffi::IN_CLOSE_WRITE).unwrap();

    loop {
        let event = handler.event().unwrap();
        // println!("{} {}", event.name, event.mask);
        spawn(proc () {
            let filename = event.name;
            println!("Handling file: {}", filename);
            // let package = match from_str::<Package>(filename.as_slice()) {
            //     None    => return,
            //     Some(p) => {
            //         if p.is_signed() {
            //             signatures_ready.push(p);
            //         } else {
            //             packages_ready.push(p);
            //         }
            //     }
            // };
        });
    }
}
<commit_msg>WIP; fix main<commit_after>extern crate inotify;

use inotify::wrapper::INotify;

use std::vec::Vec;
use std::os;

use package::Package;

pub mod package;

fn main() {
    let repo_name = "siosm-aur";
    // let db_filename = "siosm-aur.db";

    let mut packages_ready = Vec::new();
    let mut signatures_ready = Vec::new();

    println!("Looking for packages in repo {}", repo_name);

    let mut handler = INotify::init().unwrap();
    handler.add_watch(&os::getcwd(), inotify::ffi::IN_CLOSE_WRITE).unwrap();

    loop {
        let event = handler.event().unwrap();
        let filename = event.name;
        println!("Handling file: {}", filename);
        match from_str::<Package>(filename.as_slice()) {
            None    => println!("Uploaded file is not a valid package name!"),
            Some(p) => {
                if p.is_signed() {
                    signatures_ready.push(p);
                } else {
                    packages_ready.push(p);
                }
            }
        };
    }
}
<|endoftext|>


<commit_before>extern crate clap;
#[macro_use]
extern crate glium;
extern crate rand;

use std::collections::{HashSet, VecDeque};

use glium::Surface;
use glium::glutin;

/// Maximum frames per second.
const FPS: u32 = 30;

#[derive(Clone, Copy, Debug, PartialEq)]
enum Color {
    Red,
    Yellow,
    Green,
    LightBrown,
    Purple,
    Cyan,
    Blue,
    Fuchsia,
}

const COLORS: &[Color] = &[
    Color::Red,
    Color::Yellow,
    Color::Green,
    Color::LightBrown,
    Color::Purple,
    Color::Cyan,
    Color::Blue,
    Color::Fuchsia,
];

impl rand::Rand for Color {
    fn rand<R: rand::Rng>(rng: &mut R) -> Self {
        *rng.choose(COLORS).unwrap()
    }
}

struct Grid {
    width: u8,
    height: u8,
    num_colors: u8,

    cells: Vec<Color>,
    population: Vec<u16>,

    max_clicks: u16,
    num_clicks: u16,
}

impl Grid {
    pub fn new(num_colors: u8, size: u8) -> Self {
        use rand::distributions::{IndependentSample, Range};
        let between = Range::new(0, num_colors as usize);
        let mut rng = rand::thread_rng();

        let cells: Vec<Color> = (0..size as u64 * size as u64)
            .map(|_| COLORS[between.ind_sample(&mut rng)])
            .collect();
        let max_clicks = 25 * 2 * size as u16 * num_colors as u16 / (2 * 14 * 6);
        let mut population = vec![0; COLORS.len()];
        for &c in &cells {
            population[c as usize] += 1;
        }

        Self {
            width: size,
            height: size,
            num_colors,

            cells,
            population,

            max_clicks,
            num_clicks: 0,
        }
    }

    fn index(&self, row: u8, column: u8) -> usize {
        self.width as usize * row as usize + column as usize
    }

    fn current_color(&self) -> Color {
        self.cells[0]
    }

    fn solved(&self) -> bool {
        let mut colors_present = 0;
        for &x in &self.population {
            if x > 0 {
                colors_present += 1;
            }
        }
        colors_present == 1
    }

    pub fn click(&mut self, row: u8, column: u8) -> bool {
        let i = self.index(row, column);
        let new_color = self.cells[i];
        if self.current_color() == new_color {
            return false;
        }

        self.num_clicks += 1;
        self.flood(new_color);
        self.solved()
    }

    /// Flood the grid from the top left cell and return the number of cell which are connected to
    /// the top left cell by cells of indentical color.
    fn flood(&mut self, new_color: Color) {
        let current_color = self.current_color();

        let rows = self.height as usize;
        let columns = self.width as usize;

        let mut visited = HashSet::new();
        let mut queue = VecDeque::new();
        queue.push_back(0);

        while let Some(i) = queue.pop_front() {
            if self.cells[i] == new_color {
                continue;
            }
            let c = self.cells[i];
            self.population[c as usize] -= 1;
            self.cells[i] = new_color;
            self.population[new_color as usize] += 1;
            visited.insert(i);

            if i % columns > 0 && self.cells[i - 1] == current_color &&
                !visited.contains(&(i - 1))
            {
                queue.push_back(i - 1);
            }
            if i % columns < columns - 1 && self.cells[i + 1] == current_color &&
                !visited.contains(&(i + 1))
            {
                queue.push_back(i + 1);
            }
            if i >= columns && self.cells[i - columns] == current_color &&
                !visited.contains(&(i - columns))
            {
                queue.push_back(i - columns);
            }
            if i < (rows - 1) * columns && self.cells[i + columns] == current_color &&
                !visited.contains(&(i + columns))
            {
                queue.push_back(i + columns);
            }
        }
    }

    pub fn aspect_ratio(&self) -> f32 {
        self.height as f32 / self.width as f32
    }

    pub fn reset(&mut self) {
        use rand::distributions::{IndependentSample, Range};
        let between = Range::new(0, self.num_colors as usize);
        let mut rng = rand::thread_rng();

        self.cells.iter_mut().for_each(|x| {
            *x = COLORS[between.ind_sample(&mut rng)]
        });

        self.population = vec![0; COLORS.len()];
        for &c in &self.cells {
            self.population[c as usize] += 1;
        }
        self.num_clicks = 0;
    }
}

#[derive(Copy, Clone)]
struct Vertex {
    color: f32,
    position: [f32; 2],
}

implement_vertex!(Vertex, color, position);

const TITLE: &'static str = "Flood-It";

const VERTEX_SHADER: &str = r#"
    #version 140
    in vec2 position;
    in float color;
    uniform mat4 matrix;
    out float c;
    void main() {
        c = color;
        gl_Position = matrix * vec4(position, 0.0, 1.0);
    }
"#;

/// Map Color::* to RGB values.
const FRAGMENT_SHADER: &str = r#"
    #version 140
    in float c;
    out vec4 color;
    void main() {
        if (c <= 0.0)
            color = vec4(1.0, 0.0, 0.0, 1.0);
        else if (c <= 1.0)
            color = vec4(1.0, 1.0, 0.0, 1.0);
        else if (c <= 2.0)
            color = vec4(0.0, 0.69, 0.0, 1.0);
        else if (c <= 3.0)
            color = vec4(1.0, 0.8, 0.4, 1.0);
        else if (c <= 4.0)
            color = vec4(0.5, 0.0, 0.5, 1.0);
        else if (c <= 5.0)
            color = vec4(0.0, 1.0, 1.0, 1.0);
        else if (c <= 6.0)
            color = vec4(0.0, 0.0, 1.0, 1.0);
        else if (c <= 7.0)
            color = vec4(1.0, 0.0, 1.0, 1.0);
        else
            // Should never happen
            color = vec4(1.0, 1.0, 1.0, 1.0);
    }
"#;

fn parse_args() -> (u8, u8) {
    use clap::{App, Arg};

    let matches = App::new(TITLE)
        .author(env!("CARGO_PKG_AUTHORS"))
        .version(env!("CARGO_PKG_VERSION"))
        .arg(
            Arg::with_name("colors")
                .takes_value(true)
                .help("The number of different colors")
                .default_value("6"),
        )
        .arg(
            Arg::with_name("size")
                .takes_value(true)
                .help("The height and width of the grid")
                .default_value("14"),
        )
        .get_matches();

    let colors = {
        let tmp: u8 = matches
            .value_of("colors")
            .and_then(|x| x.parse().ok())
            .unwrap_or(6);
        if tmp < 3 || tmp > 8 {
            panic!("Flood-It only supports 3 through 8 (inclusive) colors.");
        } else {
            tmp
        }
    };
    let size: u8 = {
        let tmp: u8 = matches
            .value_of("size")
            .and_then(|x| x.parse().ok())
            .unwrap_or(14);
        if tmp < 2 {
            panic!("Flood-It needs a grid of at least 2x2 cells.");
        } else {
            tmp
        }
    };

    (colors, size)
}

fn main() {
    use glium::glutin::{ContextBuilder, ElementState, EventsLoop, KeyboardInput, WindowBuilder};
    use glutin::{Event, WindowEvent};

    let (colors, size) = parse_args();

    let mut events_loop = EventsLoop::new();
    let window = WindowBuilder::new().with_title(TITLE);
    let context = ContextBuilder::new();
    let display = glium::Display::new(window, context, &events_loop).unwrap();

    let program = glium::Program::from_source(&display, VERTEX_SHADER, FRAGMENT_SHADER, None)
        .unwrap();

    let indices = glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList);

    let params = glium::DrawParameters {
        backface_culling: glium::draw_parameters::BackfaceCullingMode::CullCounterClockwise,
        ..Default::default()
    };

    let mut grid = Grid::new(colors, size);
    let grid_aspect_ratio = grid.aspect_ratio();

    let mut cursor_position = (0.0, 0.0);

    main_loop(|| {
        let mut target = display.draw();
        target.clear_color(0.0, 0.0, 0.0, 1.0);
        let (width, height) = target.get_dimensions();
        let screen_aspect_ratio = height as f32 / width as f32;

        let (ratio_x, ratio_y) = if screen_aspect_ratio < grid_aspect_ratio {
            (screen_aspect_ratio, 1.0)
        } else {
            (1.0, screen_aspect_ratio.recip())
        };

        let uniforms =
            uniform! {
            matrix: [
                [ratio_x, 0.0, 0.0, 0.0],
                [0.0, -ratio_y, 0.0, 0.0],
                [0.0, 0.0, 1.0, 0.0],
                [0.0, 0.0, 0.0, 1.0_f32],
            ]
        };

        let mut triangles = vec![];

        for i in 0..grid.cells.len() {
            let x = (i % grid.width as usize) as f32;
            let y = (i / grid.width as usize) as f32;

            let cell_size = 2.0 / grid.height.max(grid.width) as f32;

            let mut quad = generate_rectangle_vertices(
                x * cell_size - 1.0,
                y * cell_size - 1.0,
                (x + 1.0) * cell_size - 1.0,
                (y + 1.0) * cell_size - 1.0,
                grid.cells[i],
            );
            triangles.append(&mut quad);
        }

        let vertex_buffer = glium::VertexBuffer::new(&display, &triangles).unwrap();
        target
            .draw(&vertex_buffer, &indices, &program, &uniforms, &params)
            .unwrap();

        target.finish().unwrap();

        let mut closed = false;
        events_loop.poll_events(|event| match event {
            Event::WindowEvent { event, .. } => {
                match event {
                    WindowEvent::Closed => closed = true,
                    WindowEvent::MouseMoved { position, .. } =>
                        cursor_position = position,
                    WindowEvent::KeyboardInput { input: KeyboardInput{virtual_keycode: Some(key), state: ElementState::Released, ..}, ..} => {
                        use glium::glutin::VirtualKeyCode;
                        match key {
                            VirtualKeyCode::Space | VirtualKeyCode::N | VirtualKeyCode::R =>
                                if grid.solved() {
                                    grid.reset();
                                }
                            _ => (),
                        }
                    }
                    WindowEvent::MouseInput {
                        state: glium::glutin::ElementState::Released,
                        button: glium::glutin::MouseButton::Left,
                        ..
                    } => {
                        let offsets = {
                            let offset = (width as f64 - height as f64).abs() / 2.0;
                            if screen_aspect_ratio < grid_aspect_ratio {
                                (offset, 0.0)
                            } else {
                                (0.0, offset)
                            }
                        };
                        if cursor_position.0 - offsets.0 >= 0.0 &&
                            cursor_position.1 - offsets.1 >= 0.0
                        {
                            let column = ((cursor_position.0 - offsets.0) * grid.width as f64 /
                                              (width as f64 - 2.0 * offsets.0))
                                .floor() as u8;
                            let row = ((cursor_position.1 - offsets.1) * grid.height as f64 /
                                           (height as f64 - 2.0 * offsets.1))
                                .floor() as u8;
                            if grid.click(row, column) {
                                    if grid.num_clicks <= grid.max_clicks {
                                        println!("You win! You used {} out of {} available moves.", grid.num_clicks, grid.max_clicks);
                                    } else {
                                        println!("You lose. You took {} moves but should have finished in {}.", grid.num_clicks, grid.max_clicks);
                                }
                            }
                        }
                    }
                    _ => (),
                }
            }
            _ => (),
        });
        !closed
    });
}

fn generate_rectangle_vertices(
    left: f32,
    bottom: f32,
    right: f32,
    top: f32,
    color: Color,
) -> Vec<Vertex> {
    let color = color as u32 as f32;
    vec![
        Vertex {
            color,
            position: [left, bottom],
        },
        Vertex {
            color,
            position: [right, bottom],
        },
        Vertex {
            color,
            position: [left, top],
        },
        Vertex {
            color,
            position: [right, bottom],
        },
        Vertex {
            color,
            position: [right, top],
        },
        Vertex {
            color,
            position: [left, top],
        },
    ]
}

fn main_loop<F: FnMut() -> bool>(mut callback: F) {
    use std::time::{Duration, Instant};
    use std::thread;

    let one_frame = Duration::new(0, 10 ^ 9 / FPS + 1);
    let mut last_frame = Instant::now();

    while callback() {
        let now = Instant::now();
        let remaining = one_frame.checked_sub(now - last_frame).unwrap_or_default();
        last_frame = now;
        thread::sleep(remaining);
    }
}
<commit_msg>Ignore out of bounds clicks<commit_after>extern crate clap;
#[macro_use]
extern crate glium;
extern crate rand;

use std::collections::{HashSet, VecDeque};

use glium::Surface;
use glium::glutin;

/// Maximum frames per second.
const FPS: u32 = 30;

#[derive(Clone, Copy, Debug, PartialEq)]
enum Color {
    Red,
    Yellow,
    Green,
    LightBrown,
    Purple,
    Cyan,
    Blue,
    Fuchsia,
}

const COLORS: &[Color] = &[
    Color::Red,
    Color::Yellow,
    Color::Green,
    Color::LightBrown,
    Color::Purple,
    Color::Cyan,
    Color::Blue,
    Color::Fuchsia,
];

impl rand::Rand for Color {
    fn rand<R: rand::Rng>(rng: &mut R) -> Self {
        *rng.choose(COLORS).unwrap()
    }
}

struct Grid {
    width: u8,
    height: u8,
    num_colors: u8,

    cells: Vec<Color>,
    population: Vec<u16>,

    max_clicks: u16,
    num_clicks: u16,
}

impl Grid {
    pub fn new(num_colors: u8, size: u8) -> Self {
        use rand::distributions::{IndependentSample, Range};
        let between = Range::new(0, num_colors as usize);
        let mut rng = rand::thread_rng();

        let cells: Vec<Color> = (0..size as u64 * size as u64)
            .map(|_| COLORS[between.ind_sample(&mut rng)])
            .collect();
        let max_clicks = 25 * 2 * size as u16 * num_colors as u16 / (2 * 14 * 6);
        let mut population = vec![0; COLORS.len()];
        for &c in &cells {
            population[c as usize] += 1;
        }

        Self {
            width: size,
            height: size,
            num_colors,

            cells,
            population,

            max_clicks,
            num_clicks: 0,
        }
    }

    fn index(&self, row: u8, column: u8) -> usize {
        self.width as usize * row as usize + column as usize
    }

    fn current_color(&self) -> Color {
        self.cells[0]
    }

    fn solved(&self) -> bool {
        let mut colors_present = 0;
        for &x in &self.population {
            if x > 0 {
                colors_present += 1;
            }
        }
        colors_present == 1
    }

    pub fn click(&mut self, row: u8, column: u8) -> bool {
        if row > self.height || column > self.width {
            return false;
        }

        let i = self.index(row, column);
        let new_color = self.cells[i];
        if self.current_color() == new_color {
            return false;
        }

        self.num_clicks += 1;
        self.flood(new_color);
        self.solved()
    }

    /// Flood the grid from the top left cell and return the number of cell which are connected to
    /// the top left cell by cells of indentical color.
    fn flood(&mut self, new_color: Color) {
        let current_color = self.current_color();

        let rows = self.height as usize;
        let columns = self.width as usize;

        let mut visited = HashSet::new();
        let mut queue = VecDeque::new();
        queue.push_back(0);

        while let Some(i) = queue.pop_front() {
            if self.cells[i] == new_color {
                continue;
            }
            let c = self.cells[i];
            self.population[c as usize] -= 1;
            self.cells[i] = new_color;
            self.population[new_color as usize] += 1;
            visited.insert(i);

            if i % columns > 0 && self.cells[i - 1] == current_color &&
                !visited.contains(&(i - 1))
            {
                queue.push_back(i - 1);
            }
            if i % columns < columns - 1 && self.cells[i + 1] == current_color &&
                !visited.contains(&(i + 1))
            {
                queue.push_back(i + 1);
            }
            if i >= columns && self.cells[i - columns] == current_color &&
                !visited.contains(&(i - columns))
            {
                queue.push_back(i - columns);
            }
            if i < (rows - 1) * columns && self.cells[i + columns] == current_color &&
                !visited.contains(&(i + columns))
            {
                queue.push_back(i + columns);
            }
        }
    }

    pub fn aspect_ratio(&self) -> f32 {
        self.height as f32 / self.width as f32
    }

    pub fn reset(&mut self) {
        use rand::distributions::{IndependentSample, Range};
        let between = Range::new(0, self.num_colors as usize);
        let mut rng = rand::thread_rng();

        self.cells.iter_mut().for_each(|x| {
            *x = COLORS[between.ind_sample(&mut rng)]
        });

        self.population = vec![0; COLORS.len()];
        for &c in &self.cells {
            self.population[c as usize] += 1;
        }
        self.num_clicks = 0;
    }
}

#[derive(Copy, Clone)]
struct Vertex {
    color: f32,
    position: [f32; 2],
}

implement_vertex!(Vertex, color, position);

const TITLE: &'static str = "Flood-It";

const VERTEX_SHADER: &str = r#"
    #version 140
    in vec2 position;
    in float color;
    uniform mat4 matrix;
    out float c;
    void main() {
        c = color;
        gl_Position = matrix * vec4(position, 0.0, 1.0);
    }
"#;

/// Map Color::* to RGB values.
const FRAGMENT_SHADER: &str = r#"
    #version 140
    in float c;
    out vec4 color;
    void main() {
        if (c <= 0.0)
            color = vec4(1.0, 0.0, 0.0, 1.0);
        else if (c <= 1.0)
            color = vec4(1.0, 1.0, 0.0, 1.0);
        else if (c <= 2.0)
            color = vec4(0.0, 0.69, 0.0, 1.0);
        else if (c <= 3.0)
            color = vec4(1.0, 0.8, 0.4, 1.0);
        else if (c <= 4.0)
            color = vec4(0.5, 0.0, 0.5, 1.0);
        else if (c <= 5.0)
            color = vec4(0.0, 1.0, 1.0, 1.0);
        else if (c <= 6.0)
            color = vec4(0.0, 0.0, 1.0, 1.0);
        else if (c <= 7.0)
            color = vec4(1.0, 0.0, 1.0, 1.0);
        else
            // Should never happen
            color = vec4(1.0, 1.0, 1.0, 1.0);
    }
"#;

fn parse_args() -> (u8, u8) {
    use clap::{App, Arg};

    let matches = App::new(TITLE)
        .author(env!("CARGO_PKG_AUTHORS"))
        .version(env!("CARGO_PKG_VERSION"))
        .arg(
            Arg::with_name("colors")
                .takes_value(true)
                .help("The number of different colors")
                .default_value("6"),
        )
        .arg(
            Arg::with_name("size")
                .takes_value(true)
                .help("The height and width of the grid")
                .default_value("14"),
        )
        .get_matches();

    let colors = {
        let tmp: u8 = matches
            .value_of("colors")
            .and_then(|x| x.parse().ok())
            .unwrap_or(6);
        if tmp < 3 || tmp > 8 {
            panic!("Flood-It only supports 3 through 8 (inclusive) colors.");
        } else {
            tmp
        }
    };
    let size: u8 = {
        let tmp: u8 = matches
            .value_of("size")
            .and_then(|x| x.parse().ok())
            .unwrap_or(14);
        if tmp < 2 {
            panic!("Flood-It needs a grid of at least 2x2 cells.");
        } else {
            tmp
        }
    };

    (colors, size)
}

fn main() {
    use glium::glutin::{ContextBuilder, ElementState, EventsLoop, KeyboardInput, WindowBuilder};
    use glutin::{Event, WindowEvent};

    let (colors, size) = parse_args();

    let mut events_loop = EventsLoop::new();
    let window = WindowBuilder::new().with_title(TITLE);
    let context = ContextBuilder::new();
    let display = glium::Display::new(window, context, &events_loop).unwrap();

    let program = glium::Program::from_source(&display, VERTEX_SHADER, FRAGMENT_SHADER, None)
        .unwrap();

    let indices = glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList);

    let params = glium::DrawParameters {
        backface_culling: glium::draw_parameters::BackfaceCullingMode::CullCounterClockwise,
        ..Default::default()
    };

    let mut grid = Grid::new(colors, size);
    let grid_aspect_ratio = grid.aspect_ratio();

    let mut cursor_position = (0.0, 0.0);

    main_loop(|| {
        let mut target = display.draw();
        target.clear_color(0.0, 0.0, 0.0, 1.0);
        let (width, height) = target.get_dimensions();
        let screen_aspect_ratio = height as f32 / width as f32;

        let (ratio_x, ratio_y) = if screen_aspect_ratio < grid_aspect_ratio {
            (screen_aspect_ratio, 1.0)
        } else {
            (1.0, screen_aspect_ratio.recip())
        };

        let uniforms =
            uniform! {
            matrix: [
                [ratio_x, 0.0, 0.0, 0.0],
                [0.0, -ratio_y, 0.0, 0.0],
                [0.0, 0.0, 1.0, 0.0],
                [0.0, 0.0, 0.0, 1.0_f32],
            ]
        };

        let mut triangles = vec![];

        for i in 0..grid.cells.len() {
            let x = (i % grid.width as usize) as f32;
            let y = (i / grid.width as usize) as f32;

            let cell_size = 2.0 / grid.height.max(grid.width) as f32;

            let mut quad = generate_rectangle_vertices(
                x * cell_size - 1.0,
                y * cell_size - 1.0,
                (x + 1.0) * cell_size - 1.0,
                (y + 1.0) * cell_size - 1.0,
                grid.cells[i],
            );
            triangles.append(&mut quad);
        }

        let vertex_buffer = glium::VertexBuffer::new(&display, &triangles).unwrap();
        target
            .draw(&vertex_buffer, &indices, &program, &uniforms, &params)
            .unwrap();

        target.finish().unwrap();

        let mut closed = false;
        events_loop.poll_events(|event| match event {
            Event::WindowEvent { event, .. } => {
                match event {
                    WindowEvent::Closed => closed = true,
                    WindowEvent::MouseMoved { position, .. } =>
                        cursor_position = position,
                    WindowEvent::KeyboardInput { input: KeyboardInput{virtual_keycode: Some(key), state: ElementState::Released, ..}, ..} => {
                        use glium::glutin::VirtualKeyCode;
                        match key {
                            VirtualKeyCode::Space | VirtualKeyCode::N | VirtualKeyCode::R =>
                                if grid.solved() {
                                    grid.reset();
                                }
                            _ => (),
                        }
                    }
                    WindowEvent::MouseInput {
                        state: glium::glutin::ElementState::Released,
                        button: glium::glutin::MouseButton::Left,
                        ..
                    } => {
                        let offsets = {
                            let offset = (width as f64 - height as f64).abs() / 2.0;
                            if screen_aspect_ratio < grid_aspect_ratio {
                                (offset, 0.0)
                            } else {
                                (0.0, offset)
                            }
                        };
                        if cursor_position.0 - offsets.0 >= 0.0 &&
                            cursor_position.1 - offsets.1 >= 0.0
                        {
                            let column = ((cursor_position.0 - offsets.0) * grid.width as f64 /
                                              (width as f64 - 2.0 * offsets.0))
                                .floor() as u8;
                            let row = ((cursor_position.1 - offsets.1) * grid.height as f64 /
                                           (height as f64 - 2.0 * offsets.1))
                                .floor() as u8;
                            if grid.click(row, column) {
                                    if grid.num_clicks <= grid.max_clicks {
                                        println!("You win! You used {} out of {} available moves.", grid.num_clicks, grid.max_clicks);
                                    } else {
                                        println!("You lose. You took {} moves but should have finished in {}.", grid.num_clicks, grid.max_clicks);
                                }
                            }
                        }
                    }
                    _ => (),
                }
            }
            _ => (),
        });
        !closed
    });
}

fn generate_rectangle_vertices(
    left: f32,
    bottom: f32,
    right: f32,
    top: f32,
    color: Color,
) -> Vec<Vertex> {
    let color = color as u32 as f32;
    vec![
        Vertex {
            color,
            position: [left, bottom],
        },
        Vertex {
            color,
            position: [right, bottom],
        },
        Vertex {
            color,
            position: [left, top],
        },
        Vertex {
            color,
            position: [right, bottom],
        },
        Vertex {
            color,
            position: [right, top],
        },
        Vertex {
            color,
            position: [left, top],
        },
    ]
}

fn main_loop<F: FnMut() -> bool>(mut callback: F) {
    use std::time::{Duration, Instant};
    use std::thread;

    let one_frame = Duration::new(0, 10 ^ 9 / FPS + 1);
    let mut last_frame = Instant::now();

    while callback() {
        let now = Instant::now();
        let remaining = one_frame.checked_sub(now - last_frame).unwrap_or_default();
        last_frame = now;
        thread::sleep(remaining);
    }
}
<|endoftext|>


<commit_before>extern crate libc;
extern crate numbat;

mod forza;
mod plugins;

use std::thread;
use std::collections::BTreeMap;
use forza::ForzaPlugin;

fn start_plugin<T: ForzaPlugin>(mut plugin: T) {
  plugin.start();
}

fn main() {
  let mut emitter = numbat::Emitter::new(BTreeMap::new(), "forza");
  emitter.connect("tcp://127.0.0.1:1337");

  let heartbeat = plugins::heartbeat::Heartbeat::new(emitter.clone());
  thread::spawn(|| {
    start_plugin(heartbeat);
  });

  let memory = plugins::memory::Memory::new(emitter.clone());
  thread::spawn(|| {
    start_plugin(memory);
  });

  let load_average = plugins::load_average::LoadAverage::new(emitter.clone());
  thread::spawn(|| {
    start_plugin(load_average);
  }).join();
}
<commit_msg>Accept `METRICS`<commit_after>extern crate libc;
extern crate numbat;

mod forza;
mod plugins;

use std::thread;
use std::collections::BTreeMap;
use forza::ForzaPlugin;

fn start_plugin<T: ForzaPlugin>(mut plugin: T) {
  plugin.start();
}

fn main() {
  let mut emitter = numbat::Emitter::new(BTreeMap::new(), "forza");
  emitter.connect(&match std::env::var_os("METRICS") {
    Some(url) => url.into_string().expect("expected METRICS to be valid UTF-8"),
    None => String::from("tcp://127.0.0.1:1337")
  });

  let heartbeat = plugins::heartbeat::Heartbeat::new(emitter.clone());
  thread::spawn(|| {
    start_plugin(heartbeat);
  });

  let memory = plugins::memory::Memory::new(emitter.clone());
  thread::spawn(|| {
    start_plugin(memory);
  });

  let load_average = plugins::load_average::LoadAverage::new(emitter.clone());
  thread::spawn(|| {
    start_plugin(load_average);
  }).join();
}
<|endoftext|>


<commit_before>use reqwest::blocking::Client;
use reqwest::header::{HeaderMap, HeaderValue, USER_AGENT};
use std::collections::HashMap;
use std::env;
use std::fs;
use std::io::{self, prelude::*, Error, Write};
use std::path::Path;
use std::process;
use std::time::Duration;

use monolith::html::{
    add_favicon, create_metadata_tag, get_base_url, has_favicon, html_to_dom, set_base_url,
    stringify_document, walk_and_embed_assets,
};
use monolith::opts::Options;
use monolith::url::{
    data_to_data_url, is_data_url, is_file_url, is_http_url, parse_data_url, resolve_url,
};
use monolith::utils::retrieve_asset;

mod macros;

enum Output {
    Stdout(io::Stdout),
    File(fs::File),
}

impl Output {
    fn new(file_path: &str) -> Result<Output, Error> {
        if file_path.is_empty() || file_path.eq("-") {
            Ok(Output::Stdout(io::stdout()))
        } else {
            Ok(Output::File(fs::File::create(file_path)?))
        }
    }

    fn writeln_str(&mut self, s: &str) -> Result<(), Error> {
        match self {
            Output::Stdout(stdout) => {
                writeln!(stdout, "{}", s)?;
                stdout.flush()
            }
            Output::File(f) => {
                writeln!(f, "{}", s)?;
                f.flush()
            }
        }
    }
}

pub fn read_stdin() -> String {
    let mut buffer = String::new();
    for line in io::stdin().lock().lines() {
        buffer += line.unwrap_or_default().as_str();
        buffer += "\n";
    }
    buffer
}

fn main() {
    let options = Options::from_args();
    let original_target: &str = &options.target;
    let target_url: &str;
    let mut base_url: String;
    let mut dom;
    let mut use_stdin: bool = false;

    // Pre-process the input
    let cwd_normalized: String =
        str!(env::current_dir().unwrap().to_str().unwrap()).replace("\\", "/");
    let path = Path::new(original_target);
    let mut target: String = str!(original_target.clone()).replace("\\", "/");
    let path_is_relative: bool = path.is_relative();

    // Determine exact target URL
    if target.clone().len() == 0 {
        if !options.silent {
            eprintln!("No target specified");
        }
        process::exit(1);
    } else if target.clone() == "-" {
        // Read from pipe (stdin)
        use_stdin = true;
        // Default target URL to empty data URL; the user can control it via --base-url
        target_url = "data:text/html,"
    } else if is_http_url(target.clone()) || is_data_url(target.clone()) {
        target_url = target.as_str();
    } else if is_file_url(target.clone()) {
        target_url = target.as_str();
    } else if path.exists() {
        if !path.is_file() {
            if !options.silent {
                eprintln!("Local target is not a file: {}", original_target);
            }
            process::exit(1);
        }
        target.insert_str(0, if cfg!(windows) { "file:///" } else { "file://" });
        if path_is_relative {
            target.insert_str(if cfg!(windows) { 8 } else { 7 }, &cwd_normalized);
            target.insert_str(
                if cfg!(windows) { 8 } else { 7 } + &cwd_normalized.len(),
                "/",
            );
        }
        target_url = target.as_str();
    } else {
        target.insert_str(0, "http://");
        target_url = target.as_str();
    }

    // Define output
    let mut output = Output::new(&options.output).expect("Could not prepare output");

    // Initialize client
    let mut cache = HashMap::new();
    let mut header_map = HeaderMap::new();
    if let Some(user_agent) = &options.user_agent {
        header_map.insert(
            USER_AGENT,
            HeaderValue::from_str(&user_agent).expect("Invalid User-Agent header specified"),
        );
    }
    let timeout: u64 = if options.timeout > 0 {
        options.timeout
    } else {
        std::u64::MAX / 4
    };
    let client = Client::builder()
        .timeout(Duration::from_secs(timeout))
        .danger_accept_invalid_certs(options.insecure)
        .default_headers(header_map)
        .build()
        .expect("Failed to initialize HTTP client");

    // At this stage we assume that the base URL is the same as the target URL
    base_url = str!(target_url);

    // Retrieve target document
    if use_stdin {
        dom = html_to_dom(&read_stdin());
    } else if is_file_url(target_url) || is_http_url(target_url) {
        match retrieve_asset(&mut cache, &client, target_url, target_url, &options, 0) {
            Ok((data, final_url, _media_type)) => {
                if options.base_url.clone().unwrap_or(str!()).is_empty() {
                    base_url = final_url
                }
                dom = html_to_dom(&String::from_utf8_lossy(&data));
            }
            Err(_) => {
                if !options.silent {
                    eprintln!("Could not retrieve target document");
                }
                process::exit(1);
            }
        }
    } else if is_data_url(target_url) {
        let (media_type, data): (String, Vec<u8>) = parse_data_url(target_url);
        if !media_type.eq_ignore_ascii_case("text/html") {
            if !options.silent {
                eprintln!("Unsupported data URL media type");
            }
            process::exit(1);
        }
        dom = html_to_dom(&String::from_utf8_lossy(&data));
    } else {
        process::exit(1);
    }

    // Use custom base URL if specified, read and use what's in the DOM otherwise
    if !options.base_url.clone().unwrap_or(str!()).is_empty() {
        if is_data_url(options.base_url.clone().unwrap()) {
            if !options.silent {
                eprintln!("Data URLs cannot be used as base URL");
            }
            process::exit(1);
        } else {
            base_url = options.base_url.clone().unwrap();
        }
    } else {
        if let Some(existing_base_url) = get_base_url(&dom.document) {
            base_url = resolve_url(target_url, existing_base_url).unwrap();
        }
    }

    // Embed remote assets
    walk_and_embed_assets(&mut cache, &client, &base_url, &dom.document, &options, 0);

    // Update or add new BASE tag to reroute network requests and hash-links in the final document
    if let Some(new_base_url) = options.base_url.clone() {
        dom = set_base_url(&dom.document, new_base_url);
    }

    // Request and embed /favicon.ico (unless it's already linked in the document)
    if !options.no_images && is_http_url(target_url) && !has_favicon(&dom.document) {
        let favicon_ico_url: String = resolve_url(&base_url, "/favicon.ico").unwrap();

        match retrieve_asset(
            &mut cache,
            &client,
            &base_url,
            &favicon_ico_url,
            &options,
            0,
        ) {
            Ok((data, final_url, media_type)) => {
                let favicon_data_url: String = data_to_data_url(&media_type, &data, &final_url);
                dom = add_favicon(&dom.document, favicon_data_url);
            }
            Err(_) => {
                // Failed to retrieve favicon.ico
            }
        }
    }

    // Remove charset meta-tag
    // set_charset_meta_to_utf8(&dom.document);

    // Serialize DOM tree
    let mut result: String = stringify_document(&dom.document, &options);

    // Add metadata tag
    if !options.no_metadata {
        let metadata_comment: String = create_metadata_tag(&target_url);
        result.insert_str(0, &metadata_comment);
        if metadata_comment.len() > 0 {
            result.insert_str(metadata_comment.len(), "\n");
        }
    }

    // Write result into stdout or file
    output
        .writeln_str(&result)
        .expect("Could not write HTML output");
}
<commit_msg>clean up unused code<commit_after>use reqwest::blocking::Client;
use reqwest::header::{HeaderMap, HeaderValue, USER_AGENT};
use std::collections::HashMap;
use std::env;
use std::fs;
use std::io::{self, prelude::*, Error, Write};
use std::path::Path;
use std::process;
use std::time::Duration;

use monolith::html::{
    add_favicon, create_metadata_tag, get_base_url, has_favicon, html_to_dom, set_base_url,
    stringify_document, walk_and_embed_assets,
};
use monolith::opts::Options;
use monolith::url::{
    data_to_data_url, is_data_url, is_file_url, is_http_url, parse_data_url, resolve_url,
};
use monolith::utils::retrieve_asset;

mod macros;

enum Output {
    Stdout(io::Stdout),
    File(fs::File),
}

impl Output {
    fn new(file_path: &str) -> Result<Output, Error> {
        if file_path.is_empty() || file_path.eq("-") {
            Ok(Output::Stdout(io::stdout()))
        } else {
            Ok(Output::File(fs::File::create(file_path)?))
        }
    }

    fn writeln_str(&mut self, s: &str) -> Result<(), Error> {
        match self {
            Output::Stdout(stdout) => {
                writeln!(stdout, "{}", s)?;
                stdout.flush()
            }
            Output::File(f) => {
                writeln!(f, "{}", s)?;
                f.flush()
            }
        }
    }
}

pub fn read_stdin() -> String {
    let mut buffer = String::new();
    for line in io::stdin().lock().lines() {
        buffer += line.unwrap_or_default().as_str();
        buffer += "\n";
    }
    buffer
}

fn main() {
    let options = Options::from_args();
    let original_target: &str = &options.target;
    let target_url: &str;
    let mut base_url: String;
    let mut dom;
    let mut use_stdin: bool = false;

    // Pre-process the input
    let cwd_normalized: String =
        str!(env::current_dir().unwrap().to_str().unwrap()).replace("\\", "/");
    let path = Path::new(original_target);
    let mut target: String = str!(original_target.clone()).replace("\\", "/");
    let path_is_relative: bool = path.is_relative();

    // Determine exact target URL
    if target.clone().len() == 0 {
        if !options.silent {
            eprintln!("No target specified");
        }
        process::exit(1);
    } else if target.clone() == "-" {
        // Read from pipe (stdin)
        use_stdin = true;
        // Default target URL to empty data URL; the user can control it via --base-url
        target_url = "data:text/html,"
    } else if is_http_url(target.clone()) || is_data_url(target.clone()) {
        target_url = target.as_str();
    } else if is_file_url(target.clone()) {
        target_url = target.as_str();
    } else if path.exists() {
        if !path.is_file() {
            if !options.silent {
                eprintln!("Local target is not a file: {}", original_target);
            }
            process::exit(1);
        }
        target.insert_str(0, if cfg!(windows) { "file:///" } else { "file://" });
        if path_is_relative {
            target.insert_str(if cfg!(windows) { 8 } else { 7 }, &cwd_normalized);
            target.insert_str(
                if cfg!(windows) { 8 } else { 7 } + &cwd_normalized.len(),
                "/",
            );
        }
        target_url = target.as_str();
    } else {
        target.insert_str(0, "http://");
        target_url = target.as_str();
    }

    // Define output
    let mut output = Output::new(&options.output).expect("Could not prepare output");

    // Initialize client
    let mut cache = HashMap::new();
    let mut header_map = HeaderMap::new();
    if let Some(user_agent) = &options.user_agent {
        header_map.insert(
            USER_AGENT,
            HeaderValue::from_str(&user_agent).expect("Invalid User-Agent header specified"),
        );
    }
    let timeout: u64 = if options.timeout > 0 {
        options.timeout
    } else {
        std::u64::MAX / 4
    };
    let client = Client::builder()
        .timeout(Duration::from_secs(timeout))
        .danger_accept_invalid_certs(options.insecure)
        .default_headers(header_map)
        .build()
        .expect("Failed to initialize HTTP client");

    // At this stage we assume that the base URL is the same as the target URL
    base_url = str!(target_url);

    // Retrieve target document
    if use_stdin {
        dom = html_to_dom(&read_stdin());
    } else if is_file_url(target_url) || is_http_url(target_url) {
        match retrieve_asset(&mut cache, &client, target_url, target_url, &options, 0) {
            Ok((data, final_url, _media_type)) => {
                if options.base_url.clone().unwrap_or(str!()).is_empty() {
                    base_url = final_url
                }
                dom = html_to_dom(&String::from_utf8_lossy(&data));
            }
            Err(_) => {
                if !options.silent {
                    eprintln!("Could not retrieve target document");
                }
                process::exit(1);
            }
        }
    } else if is_data_url(target_url) {
        let (media_type, data): (String, Vec<u8>) = parse_data_url(target_url);
        if !media_type.eq_ignore_ascii_case("text/html") {
            if !options.silent {
                eprintln!("Unsupported data URL media type");
            }
            process::exit(1);
        }
        dom = html_to_dom(&String::from_utf8_lossy(&data));
    } else {
        process::exit(1);
    }

    // Use custom base URL if specified, read and use what's in the DOM otherwise
    if !options.base_url.clone().unwrap_or(str!()).is_empty() {
        if is_data_url(options.base_url.clone().unwrap()) {
            if !options.silent {
                eprintln!("Data URLs cannot be used as base URL");
            }
            process::exit(1);
        } else {
            base_url = options.base_url.clone().unwrap();
        }
    } else {
        if let Some(existing_base_url) = get_base_url(&dom.document) {
            base_url = resolve_url(target_url, existing_base_url).unwrap();
        }
    }

    // Embed remote assets
    walk_and_embed_assets(&mut cache, &client, &base_url, &dom.document, &options, 0);

    // Update or add new BASE tag to reroute network requests and hash-links in the final document
    if let Some(new_base_url) = options.base_url.clone() {
        dom = set_base_url(&dom.document, new_base_url);
    }

    // Request and embed /favicon.ico (unless it's already linked in the document)
    if !options.no_images && is_http_url(target_url) && !has_favicon(&dom.document) {
        let favicon_ico_url: String = resolve_url(&base_url, "/favicon.ico").unwrap();

        match retrieve_asset(
            &mut cache,
            &client,
            &base_url,
            &favicon_ico_url,
            &options,
            0,
        ) {
            Ok((data, final_url, media_type)) => {
                let favicon_data_url: String = data_to_data_url(&media_type, &data, &final_url);
                dom = add_favicon(&dom.document, favicon_data_url);
            }
            Err(_) => {
                // Failed to retrieve favicon.ico
            }
        }
    }

    // Serialize DOM tree
    let mut result: String = stringify_document(&dom.document, &options);

    // Add metadata tag
    if !options.no_metadata {
        let metadata_comment: String = create_metadata_tag(&target_url);
        result.insert_str(0, &metadata_comment);
        if metadata_comment.len() > 0 {
            result.insert_str(metadata_comment.len(), "\n");
        }
    }

    // Write result into stdout or file
    output
        .writeln_str(&result)
        .expect("Could not write HTML output");
}
<|endoftext|>


<commit_before>#![feature(globs, phase, macro_rules, default_type_params, overloaded_calls)]
extern crate collections;
#[phase(plugin, link)]
extern crate log;

extern crate EmbedLang;

#[cfg(not(test))]
use EmbedLang::vm::{run_main, run_buffer_main};

mod repl;

#[cfg(not(test))]
fn main() {
    let args = ::std::os::args();
	println!("{}", args);
    if args.len() == 1 {
        let mut buffer = ::std::io::stdin();
        let (_, value) = run_buffer_main(&mut buffer)
            .unwrap_or_else(|err| fail!("{}", err));
        println!("{}", value);
    }
    else if args[1].as_slice() == "-i" {
        repl::run();
    }
    else if args.len() == 2 {
        println!("{}", run_main(args[1].as_slice()));
    }
}
<commit_msg>Updated main.rs<commit_after>#![feature(globs, phase, macro_rules, default_type_params, overloaded_calls)]
extern crate collections;
#[phase(plugin, link)]
extern crate log;

extern crate EmbedLang;

#[cfg(not(test))]
use EmbedLang::vm::{VM, run_main, run_buffer_main};

mod repl;

#[cfg(not(test))]
fn main() {
    let args = ::std::os::args();
	println!("{}", args);
    if args.len() == 1 {
        let vm = VM::new();
        let mut buffer = ::std::io::stdin();
        let value = run_buffer_main(&vm, &mut buffer)
            .unwrap_or_else(|err| fail!("{}", err));
        println!("{}", value);
    }
    else if args[1].as_slice() == "-i" {
        repl::run();
    }
    else if args.len() == 2 {
        let vm = VM::new();
        println!("{}", run_main(&vm, args[1].as_slice()));
    }
}
<|endoftext|>


<commit_before>extern crate discord;

use discord::Discord;
use discord::model::Event;
use std::env;

mod modules;
use modules::*;

fn main() {
    print_logo();

    let mods: Vec<Box<KModule>> = vec![
        Box::new(modules::About)
    ];

    for m in &mods {
        println!("Loading module {:?}...", m.name());
        m.init();
        println!("Done");
    }

    let bot = Discord::from_bot_token(
        &env::var("DISCORD_TOKEN").expect("Expecting token in $DISCORD_TOKEN")
    ).expect("Login failed. Wrong token?");

    let (mut connection, _) = bot.connect().expect("Error while connecting to discord!");

    println!("Bot ready. Starting event loop!");

    loop {
        match connection.recv_event() {
            Ok(Event::MessageCreate(message)) => {}

            Ok(_) => {}

            Err(discord::Error::Closed(code, body)) => {
                println!("Gateway closed with code {:?} : {:?}", code, body);
                break;
            }

            Err(err) => println!("Received error: {:?}", err),
        }
    }
}

fn print_logo() {
    let v = vec![
        "",
        "Welcome to...",
        " ▄    ▄  ▄▄▄▄▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄▄▄  ▄▄        ▄ ",
        "▐░▌  ▐░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░▌      ▐░▌",
        "▐░▌ ▐░▌ ▐░█▀▀▀▀▀▀▀█░▌▐░█▀▀▀▀▀▀▀█░▌▐░█▀▀▀▀▀▀▀▀▀ ▐░▌░▌     ▐░▌",
        "▐░▌▐░▌  ▐░▌       ▐░▌▐░▌       ▐░▌▐░▌          ▐░▌▐░▌    ▐░▌",
        "▐░▌░▌   ▐░█▄▄▄▄▄▄▄█░▌▐░█▄▄▄▄▄▄▄█░▌▐░█▄▄▄▄▄▄▄▄▄ ▐░▌ ▐░▌   ▐░▌",
        "▐░░▌    ▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░▌  ▐░▌  ▐░▌",
        "▐░▌░▌   ▐░█▀▀▀▀▀▀▀█░▌▐░█▀▀▀▀█░█▀▀ ▐░█▀▀▀▀▀▀▀▀▀ ▐░▌   ▐░▌ ▐░▌",
        "▐░▌▐░▌  ▐░▌       ▐░▌▐░▌     ▐░▌  ▐░▌          ▐░▌    ▐░▌▐░▌",
        "▐░▌ ▐░▌ ▐░▌       ▐░▌▐░▌      ▐░▌ ▐░█▄▄▄▄▄▄▄▄▄ ▐░▌     ▐░▐░▌",
        "▐░▌  ▐░▌▐░▌       ▐░▌▐░▌       ▐░▌▐░░░░░░░░░░░▌▐░▌      ▐░░▌",
        " ▀    ▀  ▀         ▀  ▀         ▀  ▀▀▀▀▀▀▀▀▀▀▀  ▀        ▀▀ ",
        "Version 0.1.0!                                        INDEV!",
        ""
    ];

    for line in v {
        println!("{}", line);
    }
}<commit_msg>Fix dumb loop error<commit_after>extern crate discord;

use discord::Discord;
use discord::model::Event;
use std::env;

mod modules;
use modules::*;

fn main() {
    print_logo();

    let mods: Vec<Box<KModule>> = vec![
        Box::new(modules::About)
    ];

    for m in &mods {
        println!("Loading module {:?}...", m.name());
        m.init();
    }

    println!("Done");

    let bot = Discord::from_bot_token(
        &env::var("DISCORD_TOKEN").expect("Expecting token in $DISCORD_TOKEN")
    ).expect("Login failed. Wrong token?");

    let (mut connection, _) = bot.connect().expect("Error while connecting to discord!");

    println!("Bot ready. Starting event loop!");

    loop {
        match connection.recv_event() {
            Ok(Event::MessageCreate(message)) => {}

            Ok(_) => {}

            Err(discord::Error::Closed(code, body)) => {
                println!("Gateway closed with code {:?} : {:?}", code, body);
                break;
            }

            Err(err) => println!("Received error: {:?}", err),
        }
    }
}

fn print_logo() {
    let v = vec![
        "",
        "Welcome to...",
        " ▄    ▄  ▄▄▄▄▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄▄▄  ▄▄        ▄ ",
        "▐░▌  ▐░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░▌      ▐░▌",
        "▐░▌ ▐░▌ ▐░█▀▀▀▀▀▀▀█░▌▐░█▀▀▀▀▀▀▀█░▌▐░█▀▀▀▀▀▀▀▀▀ ▐░▌░▌     ▐░▌",
        "▐░▌▐░▌  ▐░▌       ▐░▌▐░▌       ▐░▌▐░▌          ▐░▌▐░▌    ▐░▌",
        "▐░▌░▌   ▐░█▄▄▄▄▄▄▄█░▌▐░█▄▄▄▄▄▄▄█░▌▐░█▄▄▄▄▄▄▄▄▄ ▐░▌ ▐░▌   ▐░▌",
        "▐░░▌    ▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░▌  ▐░▌  ▐░▌",
        "▐░▌░▌   ▐░█▀▀▀▀▀▀▀█░▌▐░█▀▀▀▀█░█▀▀ ▐░█▀▀▀▀▀▀▀▀▀ ▐░▌   ▐░▌ ▐░▌",
        "▐░▌▐░▌  ▐░▌       ▐░▌▐░▌     ▐░▌  ▐░▌          ▐░▌    ▐░▌▐░▌",
        "▐░▌ ▐░▌ ▐░▌       ▐░▌▐░▌      ▐░▌ ▐░█▄▄▄▄▄▄▄▄▄ ▐░▌     ▐░▐░▌",
        "▐░▌  ▐░▌▐░▌       ▐░▌▐░▌       ▐░▌▐░░░░░░░░░░░▌▐░▌      ▐░░▌",
        " ▀    ▀  ▀         ▀  ▀         ▀  ▀▀▀▀▀▀▀▀▀▀▀  ▀        ▀▀ ",
        "Version 0.1.0!                                        INDEV!",
        ""
    ];

    for line in v {
        println!("{}", line);
    }
}<|endoftext|>


<commit_before>#![allow(dead_code)]

// `error_chain!` can recurse deeply
#![recursion_limit = "1024"]

#[macro_use] extern crate error_chain;
#[macro_use] extern crate glium;
extern crate rand;

#[cfg(test)]
#[macro_use]
mod test_utils;

mod drawer;
mod errors;
mod graph;
mod map;
mod math;
mod mouse;
mod square;
mod state;
mod visible_graph;

use drawer::Drawer;
use graph::Graph;
use map::{Map, Player};
use math::{apply, compose};
use mouse::Mouse;
use square::SquareGrid;
use state::{MAX_GOOP, Occupied, State};
use visible_graph::GraphPt;

use glium::glutin::{Event, ElementState, MouseButton, VirtualKeyCode};
use glium::Surface;

use std::rc::Rc;
use std::time::{Duration, Instant};

// This only gives access within this module. Make this `pub use errors::*;`
// instead if the types must be accessible from other modules (e.g., within
// a `links` section).
use errors::*;

fn main() {
    if let Err(ref e) = run() {
        use ::std::io::Write;
        let stderr = &mut ::std::io::stderr();
        let errmsg = "Error writing to stderr";

        writeln!(stderr, "error: {}", e).expect(errmsg);

        for e in e.iter().skip(1) {
            writeln!(stderr, "caused by: {}", e).expect(errmsg);
        }

        // The backtrace is not always generated. Try to run this example
        // with `RUST_BACKTRACE=1`.
        if let Some(backtrace) = e.backtrace() {
            writeln!(stderr, "backtrace: {:?}", backtrace).expect(errmsg);
        }

        ::std::process::exit(1);
    }
}

fn run() -> Result<()> {
    use glium::DisplayBuild;

    let display = glium::glutin::WindowBuilder::new()
        .with_title("rbattle".to_string())
        .build_glium()
        .chain_err(|| "unable to open window")?;

    let graph = SquareGrid::new(15, 15);
    let sources = vec![16, 45];
    let colors = vec![(0x9f, 0x20, 0xb1), (0xb1, 0x20, 0x44),
                      (0x20, 0xb1, 0x21), (0x20, 0x67, 0xb1),
                      (0xe0, 0x6f, 0x3a)];
    let map = Rc::new(Map::new(graph, sources, colors));
    let drawer = Drawer::new(&display, &map)
        .chain_err(|| "failed to construct Drawer for map")?;

    let mut state = State::new(map.clone());

    state.nodes[45] = Some(Occupied {
        player: Player(2),
        outflows: map.graph.neighbors(45),
        goop: MAX_GOOP
    });

    state.nodes[30] = Some(Occupied {
        player: Player(2),
        outflows: vec![15],
        goop: 0
    });

    state.nodes[16] = Some(Occupied {
        player: Player(0),
        outflows: map.graph.neighbors(16),
        goop: MAX_GOOP
    });

    state.nodes[17] = Some(Occupied {
        player: Player(1),
        outflows: vec![],
        goop: 2
    });

    let mut mouse = Mouse::new(map.clone());
    let mut single_step = true;

    loop {
        let mut frame = display.draw();
        frame.clear_color(1.0, 1.0, 1.0, 1.0);
        let status = drawer.draw(&mut frame, &state, &mouse);
        frame.finish()
            .chain_err(|| "drawing finish failed")?;

        let window_to_game = status?;
        let window_to_graph = compose(map.game_to_graph, window_to_game);

        for event in display.poll_events() {
            match event {
                Event::Closed => return Ok(()),
                Event::KeyboardInput(ElementState::Pressed, _,
                                     Some(VirtualKeyCode::Space)) => {
                    single_step = true;
                    state.flow();
                    state.generate_goop();
                }
                Event::KeyboardInput(ElementState::Pressed, _,
                                     Some(VirtualKeyCode::Return)) => {
                    single_step = false;
                }
                Event::MouseMoved(x, y) => {
                    let graph_pos = apply(window_to_graph, [x as f32, y as f32]);
                    mouse.move_to(GraphPt(graph_pos));
                }
                Event::MouseInput(ElementState::Pressed, MouseButton::Left) => {
                    mouse.click();
                }
                Event::MouseInput(ElementState::Released, MouseButton::Left) => {
                    if let Some(action) = mouse.release() {
                        state.take_action(action);
                    }
                }
                _ => ()
            }
        }

        if !single_step {
            state.flow();
            state.generate_goop();
        }
    }
}
<commit_msg>Add some instrumentation. Tweak single-step mode.<commit_after>#![allow(dead_code)]

// `error_chain!` can recurse deeply
#![recursion_limit = "1024"]

#[macro_use] extern crate error_chain;
#[macro_use] extern crate glium;
extern crate rand;

#[cfg(test)]
#[macro_use]
mod test_utils;

mod drawer;
mod errors;
mod graph;
mod map;
mod math;
mod mouse;
mod square;
mod state;
mod timer;
mod visible_graph;

use drawer::Drawer;
use graph::Graph;
use map::{Map, Player};
use math::{apply, compose};
use mouse::Mouse;
use square::SquareGrid;
use state::{MAX_GOOP, Occupied, State};
use visible_graph::GraphPt;

use glium::glutin::{Event, ElementState, MouseButton, VirtualKeyCode};
use glium::Surface;

use std::rc::Rc;
use std::time::{Duration, Instant};

// This only gives access within this module. Make this `pub use errors::*;`
// instead if the types must be accessible from other modules (e.g., within
// a `links` section).
use errors::*;

fn main() {
    if let Err(ref e) = run() {
        use ::std::io::Write;
        let stderr = &mut ::std::io::stderr();
        let errmsg = "Error writing to stderr";

        writeln!(stderr, "error: {}", e).expect(errmsg);

        for e in e.iter().skip(1) {
            writeln!(stderr, "caused by: {}", e).expect(errmsg);
        }

        // The backtrace is not always generated. Try to run this example
        // with `RUST_BACKTRACE=1`.
        if let Some(backtrace) = e.backtrace() {
            writeln!(stderr, "backtrace: {:?}", backtrace).expect(errmsg);
        }

        ::std::process::exit(1);
    }
}

fn run() -> Result<()> {
    use glium::DisplayBuild;

    let display = glium::glutin::WindowBuilder::new()
        .with_title("rbattle".to_string())
        .build_glium()
        .chain_err(|| "unable to open window")?;

    let graph = SquareGrid::new(15, 15);
    let sources = vec![16, 45];
    let colors = vec![(0x9f, 0x20, 0xb1), (0xb1, 0x20, 0x44),
                      (0x20, 0xb1, 0x21), (0x20, 0x67, 0xb1),
                      (0xe0, 0x6f, 0x3a)];
    let map = Rc::new(Map::new(graph, sources, colors));
    let drawer = Drawer::new(&display, &map)
        .chain_err(|| "failed to construct Drawer for map")?;

    let mut state = State::new(map.clone());

    state.nodes[45] = Some(Occupied {
        player: Player(2),
        outflows: map.graph.neighbors(45),
        goop: MAX_GOOP
    });

    state.nodes[30] = Some(Occupied {
        player: Player(2),
        outflows: vec![15],
        goop: 0
    });

    state.nodes[16] = Some(Occupied {
        player: Player(0),
        outflows: map.graph.neighbors(16),
        goop: MAX_GOOP
    });

    state.nodes[17] = Some(Occupied {
        player: Player(1),
        outflows: vec![],
        goop: 2
    });

    let mut mouse = Mouse::new(map.clone());

    let mut turn = 0;
    let start = Instant::now();

    // True if we should run a game step on every frame.
    let mut free_running = false;

    loop {
        // It seems like glium always makes a frame take a full 16ms, regardless
        // of how much work we ask it to do, but I don't see anything in the
        // documentation about this. We're leaning on that for now to keep
        // timing consistent, but we'll need to add something to control timing
        // explicitly to avoid depending on this behavior.
        let mut frame = display.draw();
        frame.clear_color(1.0, 1.0, 1.0, 1.0);
        let status = drawer.draw(&mut frame, &state, &mouse);
        frame.finish()
            .chain_err(|| "drawing finish failed")?;

        let window_to_game = status?;
        let window_to_graph = compose(map.game_to_graph, window_to_game);

        let mut single_step = false;
        for event in display.poll_events() {
            match event {
                Event::Closed => return Ok(()),
                Event::KeyboardInput(ElementState::Pressed, _,
                                     Some(VirtualKeyCode::Space)) => {
                    free_running = false;
                    single_step = true;
                }
                Event::KeyboardInput(ElementState::Pressed, _,
                                     Some(VirtualKeyCode::Return)) => {
                    free_running = true;
                }
                Event::MouseMoved(x, y) => {
                    let graph_pos = apply(window_to_graph, [x as f32, y as f32]);
                    mouse.move_to(GraphPt(graph_pos));
                }
                Event::MouseInput(ElementState::Pressed, MouseButton::Left) => {
                    mouse.click();
                }
                Event::MouseInput(ElementState::Released, MouseButton::Left) => {
                    if let Some(action) = mouse.release() {
                        state.take_action(action);
                    }
                }
                _ => ()
            }
        }

        if free_running || single_step {
            println!("Turn {} at {:9.3}s:", turn, elapsed_since(&start));

            let start_generation = Instant::now();
            state.advance();
            println!("    advance to next state: {:9.6}s:", elapsed_since(&start_generation));
            turn += 1;
        }
    }
}

/// Return the number of seconds that have elasped since `instant`. Partial
/// seconds are returned as fractional values.
fn elapsed_since(instant: &Instant) -> f64 {
    let elapsed = instant.elapsed();
    elapsed.as_secs() as f64 +
        (elapsed.subsec_nanos() as f64 / 1e9)
}
<|endoftext|>


<commit_before>#[macro_use]

extern crate capnp;
extern crate chrono;
#[cfg(feature = "coroutines")]
extern crate coio;
extern crate kafka;
extern crate log;
extern crate openssl;
extern crate rand;
extern crate redis;
extern crate serde;
extern crate serde_json;
extern crate toml;

mod flowgger;
pub use flowgger::record_capnp;

const DEFAULT_CONFIG_FILE: &'static str = "flowgger.toml";
const FLOWGGER_VERSION_STRING: &'static str = "0.2.0";

fn main() {
    println!("Flowgger v{}", FLOWGGER_VERSION_STRING);
    let config_file = std::env::args().skip(1).next().unwrap_or(DEFAULT_CONFIG_FILE.to_owned());
    flowgger::start(&config_file);
}
<commit_msg>0.2.1<commit_after>#[macro_use]

extern crate capnp;
extern crate chrono;
#[cfg(feature = "coroutines")]
extern crate coio;
extern crate kafka;
extern crate log;
extern crate openssl;
extern crate rand;
extern crate redis;
extern crate serde;
extern crate serde_json;
extern crate toml;

mod flowgger;
pub use flowgger::record_capnp;

const DEFAULT_CONFIG_FILE: &'static str = "flowgger.toml";
const FLOWGGER_VERSION_STRING: &'static str = "0.2.1";

fn main() {
    println!("Flowgger v{}", FLOWGGER_VERSION_STRING);
    let config_file = std::env::args().skip(1).next().unwrap_or(DEFAULT_CONFIG_FILE.to_owned());
    flowgger::start(&config_file);
}
<|endoftext|>


<commit_before>use std::io::{BufRead, Read, Write, self};
use std::fs::File;
use std::string::ToString;
use std::env;

mod label;
mod parser;
mod interpreter;
mod assembler;
use interpreter::{Interpreter, Program};

#[derive(Debug, Clone)]
struct Args {
    program: String,        // this is where we read the program from.
    input: Option<String>,  // this is where we read input for the program from. if None, stdin
    output: Option<String>, // this is where we output data to. if None, stdin
    format: FileFormat,     // format of input file. default is Whitespace
    action: Action          // output format. translate or execute.
}

#[derive(Debug, Clone)]
enum FileFormat {
    Whitespace,
    Assembly
}

#[derive(Debug, Clone)]
enum Action {
    Translate,
    Execute
}

fn main() {
    match console_main() {
        Ok(()) => (),
        Err(s) => write!(io::stderr(), "{}\n", s).unwrap()
    }
}

fn console_main() -> Result<(), String> {
    let args = try!(parse_args());

    let data = {
        let mut file = try!(File::open(&args.program).map_err(|e| e.to_string()));

        let mut data = String::new();

        try!(file.read_to_string(&mut data).map_err(|e| e.to_string()));

        data
    };

    let program = try!(match args.format {
        FileFormat::Whitespace => Program::parse(data.as_bytes()),
        FileFormat::Assembly => Program::assemble(&data)
    });

    let mut output: Box<Write> = if let Some(path) = args.output {
        Box::new(io::BufWriter::new(
            try!(File::create(&path).map_err(|e| e.to_string()))
        ))
    } else {
        Box::new(io::BufWriter::new(
            io::stdout()
        ))
    };

    match args.action {
        Action::Translate => try!(
            match args.format {
                FileFormat::Whitespace => output.write_all(program.disassemble().as_bytes()),
                FileFormat::Assembly   => output.write_all(program.dump().as_slice())
            }.map_err(|e| e.to_string())
        ),
        Action::Execute => {
            let input: Box<BufRead> = if let Some(path) = args.input {
                Box::new(io::BufReader::new(
                    try!(File::open(&path).map_err(|e| e.to_string()))
                ))
            } else {
                Box::new(io::BufReader::new(
                    io::stdin()
                ))
            };
            let mut interpreter = Interpreter::new(program, input, output);
            try!(interpreter.run());
        }
    }
    Ok(())
}

macro_rules! try_opt {
    ($o:expr, $e:expr) => (
        match $o {
            Some(x) => x,
            None => return Err($e)
        }
    )
}

fn parse_args() -> Result<Args, String> {;
    let mut input = None;
    let mut output = None;
    let mut format = None;
    let mut action = Action::Execute;

    let mut args = env::args();
    let mut pos_args = Vec::new();
    // discard executable name
    args.next();

    // sort out args and kwargs (also parsing kwargs)
    loop {
        match args.next() {
            Some(arg) => match arg.as_ref() {
                "-i" | "--input" => if let Some(_) = input {
                    return Err("Option --input was specified twice".to_string());
                } else {
                    input = Some(try_opt!(args.next(), "Missing argument to --input".to_string()));
                },
                "-o" | "--output" => if let Some(_) = output {
                    return Err("Option --output was specified twice".to_string());
                } else {
                    output = Some(try_opt!(args.next(), "Missing argument to --output".to_string()));
                },
                "-f" | "--format" => if let Some(_) = format {
                    return Err("Option --format was specified twice".to_string());
                } else {
                    format = match try_opt!(args.next(), "Missing argument to --format".to_string()).as_ref() {
                        "whitespace" | "ws" => Some(FileFormat::Whitespace),
                        "assembly" | "asm"  => Some(FileFormat::Assembly),
                        f => return Err(format!("Unrecognized input format {}", f))
                    };
                },
                "-t" | "--translate" => if let Action::Translate = action {
                    return Err("Option --translate was specified twice".to_string())
                } else {
                    action = Action::Translate;
                },
                "--" => {
                    pos_args.extend(args);
                    break;
                },
                _ => if arg.chars().next() == Some('-') {
                    return Err(format!("Unrecognized option {}", arg));
                } else {
                    pos_args.push(arg);
                }
            },
            None => break
        }
    }

    // parse positional args
    let mut pos_args = pos_args.into_iter();
    let program = try_opt!(pos_args.next(), "Missing required positional argument 'program'".to_string());
    if let Some(x) = pos_args.next() {
        return Err(format!("Unexpected positional argument {}", x));
    }

    return Ok(Args {
        program: program,
        input: input,
        output: output,
        format: format.unwrap_or(FileFormat::Whitespace),
        action: action
    })
}
<commit_msg>Add a -h command line parameter<commit_after>use std::io::{BufRead, Read, Write, self};
use std::fs::File;
use std::string::ToString;
use std::env;

mod label;
mod parser;
mod interpreter;
mod assembler;
use interpreter::{Interpreter, Program};

#[derive(Debug, Clone)]
struct Args {
    program: String,        // this is where we read the program from.
    input: Option<String>,  // this is where we read input for the program from. if None, stdin
    output: Option<String>, // this is where we output data to. if None, stdin
    format: FileFormat,     // format of input file. default is Whitespace
    action: Action          // output format. translate or execute.
}

#[derive(Debug, Clone)]
enum FileFormat {
    Whitespace,
    Assembly
}

#[derive(Debug, Clone)]
enum Action {
    Translate,
    Execute
}

fn main() {
    match console_main() {
        Ok(()) => (),
        Err(s) => write!(io::stderr(), "{}\n", s).unwrap()
    }
}

fn console_main() -> Result<(), String> {
    let args = try!(parse_args());

    let data = {
        let mut file = try!(File::open(&args.program).map_err(|e| e.to_string()));

        let mut data = String::new();

        try!(file.read_to_string(&mut data).map_err(|e| e.to_string()));

        data
    };

    let program = try!(match args.format {
        FileFormat::Whitespace => Program::parse(data.as_bytes()),
        FileFormat::Assembly => Program::assemble(&data)
    });

    let mut output: Box<Write> = if let Some(path) = args.output {
        Box::new(io::BufWriter::new(
            try!(File::create(&path).map_err(|e| e.to_string()))
        ))
    } else {
        Box::new(io::BufWriter::new(
            io::stdout()
        ))
    };

    match args.action {
        Action::Translate => try!(
            match args.format {
                FileFormat::Whitespace => output.write_all(program.disassemble().as_bytes()),
                FileFormat::Assembly   => output.write_all(program.dump().as_slice())
            }.map_err(|e| e.to_string())
        ),
        Action::Execute => {
            let input: Box<BufRead> = if let Some(path) = args.input {
                Box::new(io::BufReader::new(
                    try!(File::open(&path).map_err(|e| e.to_string()))
                ))
            } else {
                Box::new(io::BufReader::new(
                    io::stdin()
                ))
            };
            let mut interpreter = Interpreter::new(program, input, output);
            try!(interpreter.run());
        }
    }
    Ok(())
}

macro_rules! try_opt {
    ($o:expr, $e:expr) => (
        match $o {
            Some(x) => x,
            None => return Err($e)
        }
    )
}

fn parse_args() -> Result<Args, String> {;
    let mut input = None;
    let mut output = None;
    let mut format = None;
    let mut action = Action::Execute;

    let mut args = env::args();
    let mut pos_args = Vec::new();
    // discard executable name
    args.next();

    // sort out args and kwargs (also parsing kwargs)
    loop {
        match args.next() {
            Some(arg) => match arg.as_ref() {
                "-i" | "--input" => if let Some(_) = input {
                    return Err("Option --input was specified twice".to_string());
                } else {
                    input = Some(try_opt!(args.next(), "Missing argument to --input".to_string()));
                },
                "-o" | "--output" => if let Some(_) = output {
                    return Err("Option --output was specified twice".to_string());
                } else {
                    output = Some(try_opt!(args.next(), "Missing argument to --output".to_string()));
                },
                "-f" | "--format" => if let Some(_) = format {
                    return Err("Option --format was specified twice".to_string());
                } else {
                    format = match try_opt!(args.next(), "Missing argument to --format".to_string()).as_ref() {
                        "whitespace" | "ws" => Some(FileFormat::Whitespace),
                        "assembly" | "asm"  => Some(FileFormat::Assembly),
                        f => return Err(format!("Unrecognized input format {}", f))
                    };
                },
                "-t" | "--translate" => if let Action::Translate = action {
                    return Err("Option --translate was specified twice".to_string())
                } else {
                    action = Action::Translate;
                },
                "-h" | "--help" => return Err("Usage: whitespacers INPUT [-h | -i INFILE | -o OUTFILE | -t | -f FORMAT]

Options:
    -h --help            Display this message
    -i --input  INFILE   File to read input from (defaults to stdin)
    -o --output OUTFILE  File to write output to (defaults to stdout)
    -f --format FORMAT   Input file format. Supported options are [whitespace|ws|assembly|asm],
                          the default is whitespace.
    -t --translate       Translate the file from whitespace to assembly (or in reverse).
".to_string()),
                "--" => {
                    pos_args.extend(args);
                    break;
                },
                _ => if arg.chars().next() == Some('-') {
                    return Err(format!("Unrecognized option {}", arg));
                } else {
                    pos_args.push(arg);
                }
            },
            None => break
        }
    }

    // parse positional args
    let mut pos_args = pos_args.into_iter();
    let program = try_opt!(pos_args.next(), "Missing required positional argument 'program'".to_string());
    if let Some(x) = pos_args.next() {
        return Err(format!("Unexpected positional argument {}", x));
    }

    return Ok(Args {
        program: program,
        input: input,
        output: output,
        format: format.unwrap_or(FileFormat::Whitespace),
        action: action
    })
}
<|endoftext|>


<commit_before>use std::env;
use std::error::Error;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;

fn main() {
    // skip the first element as it is the program name
    for arg in env::args().skip(1) {
        let path = Path::new(&arg);
        cat(&path);
    }
}

fn cat(path: &Path) {
    let display = path.display();
    let mut file = match File::open(path) {
        Err(why) => panic!("cat: failed to open {}: {}", display, why.description()),
        Ok(file) => file,
    };
    let mut s = String::new();
    match file.read_to_string(&mut s) {
        Err(why) => panic!("cat: failed to read {}: {}", display, why.description()),
        Ok(_) => print!("{}", s),
    };
}
<commit_msg>added ability to read from stdin<commit_after>use std::env;
use std::error::Error;
use std::fs::File;
use std::io;
use std::io::prelude::*;
use std::path::Path;

fn main() {
    // skip the first element as it is the program name
    let args = env::args();
    if args.len() == 1 {
        println!("args.len() == 1");
        cat_stdin();
    } else {
        println!("args.len() != 1");
        for arg in args.skip(1) {
            let path = Path::new(&arg);
            cat(&path);
        }
    }
}

fn cat_stdin() {
    let stdin = io::stdin();
    let mut s = String::new();
    loop {
        match stdin.read_line(&mut s) {
            Err(why) => panic!("cat: failed to read from stdin: {}", why),
            Ok(n) => if n == 0 {
                break;
            } else {
                print!("{}", s);
                s.clear();
            },
        };
    }
}

fn cat(path: &Path) {
    let display = path.display();
    let mut file = match File::open(path) {
        Err(why) => panic!("cat: failed to open {}: {}", display, why.description()),
        Ok(file) => file,
    };
    let mut s = String::new();
    match file.read_to_string(&mut s) {
        Err(why) => panic!("cat: failed to read {}: {}", display, why.description()),
        Ok(_) => print!("{}", s),
    };
}
<|endoftext|>


<commit_before>use crossbeam_channel::bounded;
use crossbeam_channel::Receiver;
use crossbeam_channel::Sender;
use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::process::ExitCode;
use std::thread;
use std::vec::Vec;

#[derive(Debug)]
struct TranscodeJob {
    src: PathBuf,
    dest: PathBuf,
}

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

    let (srcdir, destdir) = match args.len() {
        1 => {
            let src = env::current_dir().unwrap();
            let mut dest = src.clone();
            dest.push("transcoded");
            (src, dest)
        }
        3 => (PathBuf::from(&args[1]), PathBuf::from(&args[2])),
        _ => {
            println!("usage using current dir: {}", args[0]);
            println!("usage explicit dirs: {} <src dir> <dest dir>", args[0]);
            std::process::exit(1)
        }
    };

    println!(
        "videos src: {} dest: {}",
        srcdir.display(),
        destdir.display()
    );

    thread::scope(|s| {
        const NTHREADS: i32 = 4;

        let (job_sender, job_recv) = bounded::<TranscodeJob>(0);

        for i in 0..NTHREADS {
            let job_recv = job_recv.clone();
            s.spawn(move || transcoder(i, job_recv));
        }

        jobscheduler(srcdir.as_path(), job_sender);
    });

    println!("done");

    ExitCode::SUCCESS
}

fn jobscheduler(path: &Path, job_sender: Sender<TranscodeJob>) {
    println!("starting job scheduler");

    let entries = fs::read_dir(path).unwrap();
    let mut srcs = Vec::new();

    for entry in entries {
        match entry {
            Ok(entry) => {
                let path = entry.path();
                if let Some(extension) = path.extension() {
                    let extension = extension
                        .to_str()
                        .expect("file extensions should be valid utf-8");

                    match extension {
                        "avi" => {
                            srcs.push(path);
                        }
                        _ => {
                            println!("ignoring file with extension: {}", extension)
                        }
                    }
                }
            }
            Err(err) => {
                print!("error reading dir {}: {}", path.display(), err);
            }
        }
    }

    let job = TranscodeJob {
        src: PathBuf::from("src"),
        dest: PathBuf::from("dest"),
    };
    job_sender.send(job).expect("failed to send job to workers");
    drop(job_sender);
}

fn transcoder(id: i32, job_recv: Receiver<TranscodeJob>) {
    println!("starting transcoder {}", id);

    while let Ok(job) = job_recv.recv() {
        println!(
            "transcoder {} transcoding from {} to {}",
            id,
            job.src.display(),
            job.dest.display()
        );
    }

    println!("finishing transcoder {}", id);
}
<commit_msg>feat: finish dest/src dirs logic<commit_after>use crossbeam_channel::bounded;
use crossbeam_channel::Receiver;
use crossbeam_channel::Sender;
use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::process::ExitCode;
use std::thread;
use std::vec::Vec;

#[derive(Debug)]
struct TranscodeJob {
    src: PathBuf,
    dest: PathBuf,
}

fn main() -> Result<(), ExitCode> {
    let (srcdir, destdir) = parse_args()?;

    println!(
        "videos src: {} dest: {}",
        srcdir.display(),
        destdir.display()
    );

    if srcdir == destdir {
        println!("src and dest dirs must differ");
        return Err(ExitCode::FAILURE);
    }

    thread::scope(|s| {
        const NTHREADS: i32 = 4;

        let (job_sender, job_recv) = bounded::<TranscodeJob>(0);

        for i in 0..NTHREADS {
            let job_recv = job_recv.clone();
            s.spawn(move || transcoder(i, job_recv));
        }

        jobscheduler(srcdir.as_path(), destdir.as_path(), job_sender);
    });

    println!("done");

    Ok(())
}

fn jobscheduler(srcdir: &Path, destdir: &Path, job_sender: Sender<TranscodeJob>) {
    println!("starting job scheduler");

    let entries = fs::read_dir(srcdir).unwrap();
    let mut srcs = Vec::new();

    for entry in entries {
        match entry {
            Ok(entry) => {
                let srcdir = entry.path();
                if let Some(extension) = srcdir.extension() {
                    let extension = extension
                        .to_str()
                        .expect("file extensions should be valid utf-8");

                    match extension {
                        "avi" => {
                            srcs.push(srcdir);
                        }
                        _ => {
                            println!("ignoring file with extension: {}", extension)
                        }
                    }
                }
            }
            Err(err) => {
                print!("error reading dir {}: {}", srcdir.display(), err);
            }
        }
    }

    for src in srcs {
        let mut dest = destdir.to_path_buf();
        // We already validated srcs, so they always have a filename
        dest.push(src.file_name().unwrap());

        let job = TranscodeJob {
            src: src,
            dest: dest,
        };
        job_sender.send(job).expect("failed to send job to workers");
    }

    drop(job_sender);
}

fn transcoder(id: i32, job_recv: Receiver<TranscodeJob>) {
    println!("starting transcoder {}", id);

    while let Ok(job) = job_recv.recv() {
        println!(
            "transcoder {} transcoding from {} to {}",
            id,
            job.src.display(),
            job.dest.display()
        );
    }

    println!("finishing transcoder {}", id);
}

fn parse_args() -> Result<(PathBuf, PathBuf), ExitCode> {
    let args: Vec<String> = env::args().collect();

    return match args.len() {
        1 => {
            let src = env::current_dir().unwrap();
            let mut dest = src.clone();
            dest.push("transcoded");
            Ok((src, dest))
        }
        3 => Ok((PathBuf::from(&args[1]), PathBuf::from(&args[2]))),
        _ => {
            println!("usage using current dir: {}", args[0]);
            println!("usage explicit dirs: {} <src dir> <dest dir>", args[0]);
            Err(ExitCode::FAILURE)
        }
    };
}
<|endoftext|>