<commit_before>extern crate ppbert;
#[macro_use] extern crate clap;

use std::io::{self, BufReader, Read};
use std::fs::File;
use std::process::exit;
use std::time::Instant;

use clap::{Arg, App};

use ppbert::bertterm::{
    self,
    BertTerm,
    DEFAULT_INDENT_WIDTH,
    DEFAULT_MAX_TERMS_PER_LINE
};
use ppbert::error::Result;
use ppbert::parser;

const PROG_NAME: &str = "ppbert";

fn main() {
    let matches = App::new(PROG_NAME)
        .version(crate_version!())
        .author("Vincent Foley")
        .about("Pretty print structure encoded in Erlang's External Term Format")
        .arg(Arg::with_name("input_files")
             .value_name("FILES")
             .multiple(true))
        .arg(Arg::with_name("indent_width")
             .help("Indents with <num> spaces")
             .value_name("num")
             .short("i")
             .long("indent-width")
             .takes_value(true))
        .arg(Arg::with_name("max_per_line")
             .help("Prints at most <num> basic terms per line")
             .value_name("num")
             .short("m")
             .long("max-terms-per-line")
             .takes_value(true))
        .arg(Arg::with_name("verbose")
             .help("Enables verbose mode")
             .short("v")
             .long("verbose"))
        .arg(Arg::with_name("parse")
             .help("Parses the input, doesn't pretty print it")
             .short("p")
             .long("parse"))
        .arg(Arg::with_name("bert2")
             .help("Parses .bert2 files")
             .short("2")
             .long("bert2"))
        .arg(Arg::with_name("disk_log")
             .help("Parses disk_log files")
             .short("d")
             .long("disk-log"))
        .arg(Arg::with_name("json")
             .help("Outputs in JSON")
             .short("j")
             .long("json"))
        .arg(Arg::with_name("transform-proplists")
             .help("Transforms proplists into JSON objects (only valid with --json)")
             .long("transform-proplists"))
        .get_matches();

    let files: Vec<&str> = match matches.values_of("input_files") {
        Some(files) => files.collect(),
        None => vec!["-"]
    };

    let indent_level = value_t!(matches, "indent_width", usize)
        .unwrap_or(DEFAULT_INDENT_WIDTH);
    let max_per_line = value_t!(matches, "max_per_line", usize)
        .unwrap_or(DEFAULT_MAX_TERMS_PER_LINE);
    let verbose = matches.is_present("verbose");
    let parse_only = matches.is_present("parse");

    let transform_proplists = matches.is_present("transform-proplists");
    let parse_fn =
        if matches.is_present("bert2") {
            parse_bert2
        } else if matches.is_present("disk_log") {
            parse_disk_log
        } else {
            parse_bert1
        };
    let output_fn =
        if matches.is_present("json") {
            if transform_proplists {
                bertterm::pp_json_proplist
            } else {
                bertterm::pp_json
            }
        } else {
            if transform_proplists {
                eprintln!("{}: warning: --transform-proplists is only valid with the --json flag",
                          PROG_NAME);
            }
            bertterm::pp_bert
        };

    let mut return_code = 0;
    for file in files {
        let res = handle_file(file, parse_only, verbose,
                              indent_level, max_per_line,
                              parse_fn, output_fn);
        match res {
            Ok(()) => (),
            Err(e) => {
                return_code = 1;
                eprintln!("{}: {}: {}", PROG_NAME, file, e);
            }
        }
    }
    exit(return_code);
}

fn handle_file<T>(
    file: &str,
    parse_only: bool,
    verbose: bool,
    indent: usize,
    terms_per_line: usize,
    parse_fn: fn(Vec<u8>) -> Result<T>,
    pp_fn: fn(T, usize, usize) -> ()
) -> Result<()> {

    // Read file or stdin into buffer
    let mut buf: Vec<u8> = Vec::new();
    let now = Instant::now();
    if file == "-" {
        let stdin = io::stdin();
        let mut stdin = stdin.lock();
        stdin.read_to_end(&mut buf)?;
    } else {
        let f = File::open(file)?;
        let mut rdr = BufReader::new(f);
        rdr.read_to_end(&mut buf)?;
    }
    let dur = now.elapsed();
    if verbose {
        eprintln!("{}: read time: {}.{:09}",
                  PROG_NAME, dur.as_secs(), dur.subsec_nanos());
    }

    // Parse input
    let now = Instant::now();
    let parse_output = parse_fn(buf)?;
    let dur = now.elapsed();

    if verbose {
        eprintln!("{}: parse time: {}.{:09}",
                  PROG_NAME, dur.as_secs(), dur.subsec_nanos());
    }

    // Early exit if parse-only
    if parse_only {
        return Ok(());
    }

    // Pretty print
    let now = Instant::now();
    pp_fn(parse_output, indent, terms_per_line);
    let dur = now.elapsed();

    if verbose {
        eprintln!("{}: print time: {}.{:09}",
                  PROG_NAME, dur.as_secs(), dur.subsec_nanos());
    }

    return Ok(());
}

fn parse_bert1(buf: Vec<u8>) -> Result<Vec<BertTerm>> {
    let mut parser = parser::Parser::new(buf);
    let term = parser.parse()?;
    return Ok(vec![term]);
}

fn parse_bert2(buf: Vec<u8>) -> Result<Vec<BertTerm>> {
    let mut parser = parser::Parser::new(buf);
    return parser.parse_bert2();
}

fn parse_disk_log(buf: Vec<u8>) -> Result<Vec<BertTerm>> {
    let mut parser = parser::Parser::new(buf);
    return parser.parse_disk_log();
}
<commit_msg>Ensure --disk-log and --bert2 are conflicting<commit_after>extern crate ppbert;
#[macro_use] extern crate clap;

use std::io::{self, BufReader, Read};
use std::fs::File;
use std::process::exit;
use std::time::Instant;

use clap::{Arg, App};

use ppbert::bertterm::{
    self,
    BertTerm,
    DEFAULT_INDENT_WIDTH,
    DEFAULT_MAX_TERMS_PER_LINE
};
use ppbert::error::Result;
use ppbert::parser;

const PROG_NAME: &str = "ppbert";

fn main() {
    let matches = App::new(PROG_NAME)
        .version(crate_version!())
        .author("Vincent Foley")
        .about("Pretty print structure encoded in Erlang's External Term Format")
        .arg(Arg::with_name("input_files")
             .value_name("FILES")
             .multiple(true))
        .arg(Arg::with_name("indent_width")
             .help("Indents with <num> spaces")
             .value_name("num")
             .short("i")
             .long("indent-width")
             .takes_value(true))
        .arg(Arg::with_name("max_per_line")
             .help("Prints at most <num> basic terms per line")
             .value_name("num")
             .short("m")
             .long("max-terms-per-line")
             .takes_value(true))
        .arg(Arg::with_name("verbose")
             .help("Enables verbose mode")
             .short("v")
             .long("verbose"))
        .arg(Arg::with_name("parse")
             .help("Parses the input, doesn't pretty print it")
             .short("p")
             .long("parse"))
        .arg(Arg::with_name("bert2")
             .help("Parses .bert2 files")
             .conflicts_with("disk_log")
             .short("2")
             .long("bert2"))
        .arg(Arg::with_name("disk_log")
             .help("Parses disk_log files")
             .conflicts_with("bert2")
             .short("d")
             .long("disk-log"))
        .arg(Arg::with_name("json")
             .help("Outputs in JSON")
             .short("j")
             .long("json"))
        .arg(Arg::with_name("transform-proplists")
             .help("Transforms proplists into JSON objects (only valid with --json)")
             .long("transform-proplists"))
        .get_matches();

    let files: Vec<&str> = match matches.values_of("input_files") {
        Some(files) => files.collect(),
        None => vec!["-"]
    };

    let indent_level = value_t!(matches, "indent_width", usize)
        .unwrap_or(DEFAULT_INDENT_WIDTH);
    let max_per_line = value_t!(matches, "max_per_line", usize)
        .unwrap_or(DEFAULT_MAX_TERMS_PER_LINE);
    let verbose = matches.is_present("verbose");
    let parse_only = matches.is_present("parse");

    let transform_proplists = matches.is_present("transform-proplists");
    let parse_fn =
        if matches.is_present("bert2") {
            parse_bert2
        } else if matches.is_present("disk_log") {
            parse_disk_log
        } else {
            parse_bert1
        };
    let output_fn =
        if matches.is_present("json") {
            if transform_proplists {
                bertterm::pp_json_proplist
            } else {
                bertterm::pp_json
            }
        } else {
            if transform_proplists {
                eprintln!("{}: warning: --transform-proplists is only valid with the --json flag",
                          PROG_NAME);
            }
            bertterm::pp_bert
        };

    let mut return_code = 0;
    for file in files {
        let res = handle_file(file, parse_only, verbose,
                              indent_level, max_per_line,
                              parse_fn, output_fn);
        match res {
            Ok(()) => (),
            Err(e) => {
                return_code = 1;
                eprintln!("{}: {}: {}", PROG_NAME, file, e);
            }
        }
    }
    exit(return_code);
}

fn handle_file<T>(
    file: &str,
    parse_only: bool,
    verbose: bool,
    indent: usize,
    terms_per_line: usize,
    parse_fn: fn(Vec<u8>) -> Result<T>,
    pp_fn: fn(T, usize, usize) -> ()
) -> Result<()> {

    // Read file or stdin into buffer
    let mut buf: Vec<u8> = Vec::new();
    let now = Instant::now();
    if file == "-" {
        let stdin = io::stdin();
        let mut stdin = stdin.lock();
        stdin.read_to_end(&mut buf)?;
    } else {
        let f = File::open(file)?;
        let mut rdr = BufReader::new(f);
        rdr.read_to_end(&mut buf)?;
    }
    let dur = now.elapsed();
    if verbose {
        eprintln!("{}: read time: {}.{:09}",
                  PROG_NAME, dur.as_secs(), dur.subsec_nanos());
    }

    // Parse input
    let now = Instant::now();
    let parse_output = parse_fn(buf)?;
    let dur = now.elapsed();

    if verbose {
        eprintln!("{}: parse time: {}.{:09}",
                  PROG_NAME, dur.as_secs(), dur.subsec_nanos());
    }

    // Early exit if parse-only
    if parse_only {
        return Ok(());
    }

    // Pretty print
    let now = Instant::now();
    pp_fn(parse_output, indent, terms_per_line);
    let dur = now.elapsed();

    if verbose {
        eprintln!("{}: print time: {}.{:09}",
                  PROG_NAME, dur.as_secs(), dur.subsec_nanos());
    }

    return Ok(());
}

fn parse_bert1(buf: Vec<u8>) -> Result<Vec<BertTerm>> {
    let mut parser = parser::Parser::new(buf);
    let term = parser.parse()?;
    return Ok(vec![term]);
}

fn parse_bert2(buf: Vec<u8>) -> Result<Vec<BertTerm>> {
    let mut parser = parser::Parser::new(buf);
    return parser.parse_bert2();
}

fn parse_disk_log(buf: Vec<u8>) -> Result<Vec<BertTerm>> {
    let mut parser = parser::Parser::new(buf);
    return parser.parse_disk_log();
}
<|endoftext|>


<commit_before>extern crate ncurses;
extern crate voodoo;

use ncurses::*;

fn main() {
    use voodoo::terminal::{Mode, Terminal};

    let locale = LcCategory::all;
    setlocale(locale, "en_US.UTF-8");

    let term = Terminal::new();
    term.cbreak(Mode::Enabled).unwrap();
    term.echo(Mode::Disabled).unwrap();

    keypad(stdscr(), true);
    curs_set(CURSOR_VISIBILITY::CURSOR_INVISIBLE);

    mousemask((ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION) as u64, None);

    start_color();
    init_pair(1, COLOR_BLACK, COLOR_WHITE);

    wbkgd(stdscr(), 1);

    let info = newwin(24, 20, 0, 0);
    let map = newwin(24, 60, 0, 20);

    box_(info, 0, 0);
    box_(map, 0, 0);

    refresh();
    wrefresh(info);
    wrefresh(map);

    print!("\x1B[?1003h\n"); // Makes the terminal report mouse movement events

    loop {
        match voodoo::poll_event() {
            Some(WchResult::KeyCode(KEY_MOUSE)) => {
                let event = get_mouse_state();
                mvwprintw(map, event.y, event.x - 20, "y");
                wrefresh(map);
            }

            Some(WchResult::Char(10)) => {
                break;
            }

            Some(WchResult::Char(a)) => {
                // mvwprintw(map, 0, 0, &keyname(a as i32));
            }

            _ => {}
        }
    }

    print!("\x1B[?1003l\n"); // Disable mouse movement events, as l = low

    endwin();
}

fn get_mouse_state() -> MEVENT {
    let mut event = MEVENT { id: 0, x: 0, y: 0, z: 0, bstate: 0 };
    let res = getmouse(&mut event);
    if res != 0 {
        panic!("getmouse");
    }
    event
}
<commit_msg>refactor: make event polling clearer<commit_after>extern crate ncurses;
extern crate voodoo;

use ncurses::*;

fn main() {
    use voodoo::terminal::{Mode, Terminal};

    let locale = LcCategory::all;
    setlocale(locale, "en_US.UTF-8");

    let term = Terminal::new();
    term.cbreak(Mode::Enabled).unwrap();
    term.echo(Mode::Disabled).unwrap();

    keypad(stdscr(), true);
    curs_set(CURSOR_VISIBILITY::CURSOR_INVISIBLE);

    mousemask((ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION) as u64, None);

    start_color();
    init_pair(1, COLOR_BLACK, COLOR_WHITE);

    wbkgd(stdscr(), 1);

    let info = newwin(24, 20, 0, 0);
    let map = newwin(24, 60, 0, 20);

    box_(info, 0, 0);
    box_(map, 0, 0);

    refresh();
    wrefresh(info);
    wrefresh(map);

    print!("\x1B[?1003h\n"); // Makes the terminal report mouse movement events

    loop {
        match voodoo::poll_event() {
            Some(voodoo::Event::Mouse) => {
                let event = get_mouse_state();
                mvwprintw(map, event.y, event.x - 20, "y");
                wrefresh(map);
            }

            Some(voodoo::Event::Char('\n')) => {
                break;
            }

            _ => {}
        }
    }

    print!("\x1B[?1003l\n"); // Disable mouse movement events, as l = low

    endwin();
}

fn get_mouse_state() -> MEVENT {
    let mut event = MEVENT { id: 0, x: 0, y: 0, z: 0, bstate: 0 };
    let res = getmouse(&mut event);
    if res != 0 {
        panic!("getmouse");
    }
    event
}
<|endoftext|>


<commit_before>use std::env;

fn multiply () {

}

fn main () {
    let args: Vec<_> = env::args().collect();
    let tokens: Vec<&str> = args[1].split(" ").collect();
    let mut output: Vec<i32> = vec![];
    let mut operator: Vec<_> = vec![];

    for i in 1..tokens.len() {
        let r = tokens[i].parse::<i32>();

        match r {
            Ok(_) => output.push(r.unwrap()),
            Err(_) => {
                if operator.len() > 0 {

                }
                operator.push(&tokens[i])
            }
        }
    }
}
<commit_msg>Add operator functions<commit_after>use std::env;

fn multiply (a: f32, b: f32) -> f32 {
    return a * b;
}

fn add (a: f32, b: f32) -> f32 {
    return a + b;
}

fn divide (a: f32, b: f32) -> f32 {
    return a / b;
}

fn subtract (a: f32, b: f32) -> f32 {
    return a - b;
}

fn exponent (a: f32, b: f32) -> f32 {
    return a.powf(b);
}

fn main () {
    let args: Vec<_> = env::args().collect();
    let tokens: Vec<&str> = args[1].split(" ").collect();
    let mut output: Vec<i32> = vec![];
    let mut operator: Vec<_> = vec![];

    for i in 1..tokens.len() {
        let r = tokens[i].parse::<i32>();

        match r {
            Ok(_) => output.push(r.unwrap()),
            Err(_) => {
                if operator.len() > 0 {

                }
                operator.push(&tokens[i])
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate piston;
extern crate graphics;
extern crate glutin_window;
extern crate opengl_graphics;
extern crate rand;

pub mod tetris;

use piston::window::WindowSettings;
use piston::event::*;
use glutin_window::GlutinWindow as Glutin_Window;
use opengl_graphics::{ GlGraphics, OpenGL };
use opengl_graphics::glyph_cache::GlyphCache;
use graphics::{ Transformed };
use piston::input::Button::{ Keyboard };
use piston::input::Input;
use piston::input::keyboard::Key;
use std::path::Path;

use tetris::*;

struct App {
    gl: GlGraphics,
    tetris: Tetris,
    elapsed_time: f64,
    cache: GlyphCache<'static>,
    should_redraw: bool
}

const WHITE: [f32; 4] = [1.0, 1.0, 1.0, 1.0];
const BLACK: [f32; 4] = [0.0, 0.0, 0.0, 1.0];
const DARK_GRAY: [f32; 4] = [0.1, 0.1, 0.1, 1.0];
const GREEN: [f32; 4] = [0.0, 1.0, 0.0, 1.0];
const CYAN: [f32; 4] = [0.0, 1.0, 1.0, 1.0];
const RED: [f32; 4] = [1.0, 0.0, 0.0, 1.0];
const BLUE: [f32; 4] = [0.0, 0.0, 1.0, 1.0];
const ORANGE: [f32; 4] = [1.0, 0.5, 0.0, 1.0];
const YELLOW: [f32; 4] = [1.0, 1.0, 0.0, 1.0];
const PURPLE: [f32; 4] = [0.5, 0.0, 1.0, 1.0];

fn get_shape_color(shape_index: i32) -> [f32; 4] {
    match shape_index {
        0 => PURPLE,
        1 => YELLOW,
        2 => RED,
        3 => GREEN,
        4 => ORANGE,
        5 => BLUE,
        6 => CYAN,
        _ => {
            BLACK
        }
    }
}

impl App {
    fn render(&mut self, args: &RenderArgs) {
        self.should_redraw = false;

        const CELL_SIZE: f64 = 30.0;
        const LEFT_MARGIN: f64 = 20f64;
        const TOP_MARGIN: f64 = 30f64;

        const STATUS_LEFT_MARGIN: f64 = 400f64;
        const STATUS_TOP_MARGIN: f64 = 100f64;
        const LINE_HEIGHT: f64 = 40f64;
        const STATUS_PREVIEW_GRID_HEIGHT: f64 = CELL_SIZE * 6f64;

        // so that we can access inside clojure
        let use_cache = &mut self.cache;
        let use_tetris = &mut self.tetris;

        self.gl.draw(args.viewport(), |c, gl| {
            // clear the viewport
            graphics::clear(BLACK, gl);

            // render the current score and level
            let mut text = graphics::Text::new(22);
            text.color = ORANGE;
            let mut transform = c.trans(STATUS_LEFT_MARGIN, STATUS_TOP_MARGIN);
            text.draw(&format!("Level: {}", use_tetris.get_level()), use_cache, &c.draw_state,
                transform.transform, gl);
            transform = transform.trans(0f64, LINE_HEIGHT);

            text.draw(&format!("Score: {}", use_tetris.get_score()), use_cache, &c.draw_state,
                transform.transform, gl);
            transform = transform.trans(0f64, LINE_HEIGHT);

            // render the next shape as a preview of what's coming next
            for point in use_tetris.get_next_shape().iter() {
                let square = graphics::rectangle::square(0f64, 0f64, CELL_SIZE);
                let color = get_shape_color(use_tetris.get_next_shape_index() as i32);
                // render the shape at col 2 and row 2
                let (x, y) = ((2 as i16 + point.x) as f64 * CELL_SIZE,
                    (2 as i16 + point.y) as f64 * CELL_SIZE);
                graphics::rectangle(color, square, transform.trans(x, y).transform, gl);
                let tetromino_border = graphics::Rectangle::new_border(DARK_GRAY, 1.0);
                tetromino_border.draw([0f64, 0f64, CELL_SIZE, CELL_SIZE], &c.draw_state,
                    transform.trans(x, y).transform, gl);
            }
            transform = transform.trans(0f64, STATUS_PREVIEW_GRID_HEIGHT);

            // render GAME OVER text if necessary
            if use_tetris.get_game_over() {
                text.draw(&"GAME OVER", use_cache, &c.draw_state,
                    transform.transform, gl);
                transform = transform.trans(0f64, LINE_HEIGHT);

                text.draw(&"Press 'N' for a new game", use_cache, &c.draw_state,
                    transform.transform, gl);
                transform = transform.trans(0f64, LINE_HEIGHT);

                text.draw(&"Use arrow keys to move and rotate", use_cache, &c.draw_state,
                    transform.transform, gl);
                transform = transform.trans(0f64, LINE_HEIGHT);

                text.draw(&"Press spacebar to drop", use_cache, &c.draw_state,
                    transform.transform, gl);
                transform = transform.trans(0f64, LINE_HEIGHT);

                text.draw(&format!("Press 'K' to decrease starting level ({})", use_tetris.get_starting_level()),
                    use_cache, &c.draw_state, transform.transform, gl);
                transform = transform.trans(0f64, LINE_HEIGHT);

                text.draw(&"Press 'L' to increase starting level",
                    use_cache, &c.draw_state, transform.transform, gl);
                // uncomment if drawing additional text in the status area
                //transform = transform.trans(0f64, LINE_HEIGHT);
            }

            // draw a white border around the game board
            let rect_border = graphics::Rectangle::new_border(WHITE, 1.5);
            rect_border.draw([
                LEFT_MARGIN,
                TOP_MARGIN,
                (CELL_SIZE * COL_COUNT as f64) + 1f64,
                (CELL_SIZE * ROW_COUNT as f64) + 1f64,
            ], &c.draw_state, c.transform, gl);

            // render each cell in the game board
            for col in 0..COL_COUNT as i32 {
                for row in 0..ROW_COUNT as i32 {
                    let cell = use_tetris.get_grid_cell(col, row);
                    if cell.cell_type != GridCellType::Void {
                        let (x, y) = (col as f64 * CELL_SIZE, row as f64 * CELL_SIZE);
                        let square = graphics::rectangle::square(0.0f64, 0.0f64, CELL_SIZE);
                        let color = match cell.cell_type {
                            GridCellType::Shape => get_shape_color(cell.shape_index),
                            GridCellType::Fixed => get_shape_color(cell.shape_index),
                            GridCellType::Ghost => DARK_GRAY,
                            _ => {
                                assert!(false);
                                BLACK
                            }
                        };
                        let transform = c.transform.trans(LEFT_MARGIN, TOP_MARGIN).trans(x, y);
                        graphics::rectangle(color, square, transform, gl);
                        let tetromino_border = graphics::Rectangle::new_border(DARK_GRAY, 1.0);
                        tetromino_border.draw([0f64, 0f64, CELL_SIZE, CELL_SIZE], &c.draw_state, transform, gl);
                    }
                }
            }
        });
    }

    fn update(&mut self, args: &UpdateArgs) {
        if self.tetris.get_game_over() {
            self.elapsed_time = 0.0;
        } else {
            // Here we increment the time elapsed between update()'s
            self.elapsed_time += args.dt;
            // if the elapsed time is now greater than the time allotted between ticks, then invoke tetris.tick()
            if self.elapsed_time > self.tetris.get_tick_time() as f64 {
                self.elapsed_time = 0.0;
                self.tetris.tick();
                self.should_redraw = true;
            }
        }
    }

    fn handle_input(&mut self, i: Input) {
        let prev_should_redraw = self.should_redraw;
        self.should_redraw = true;
        match i {
            Input::Press(Keyboard(Key::Left)) => {
                let col: i32 = self.tetris.get_col();
                self.tetris.set_col(col - 1);
            },

            Input::Press(Keyboard(Key::Right)) => {
                let col: i32 = self.tetris.get_col();
                self.tetris.set_col(col + 1);
            },

            Input::Press(Keyboard(Key::Up)) => {
                self.tetris.rotate(true);
            },

            Input::Press(Keyboard(Key::Down)) => {
                let row: i32 = self.tetris.get_row() + 1;
                self.tetris.set_row(row);
            },

            Input::Press(Keyboard(Key::Space)) => {
                let mut row: i32 = self.tetris.get_row() + 1;
                while self.tetris.set_row(row) {
                    row += 1;
                }
                // hard drop immediately spawns next shape
                self.tetris.tick();
            },

            Input::Press(Keyboard(Key::N)) => {
                self.tetris.start_game();
            },

            Input::Press(Keyboard(Key::K)) => {
                if self.tetris.get_starting_level() > 0 {
                    let new_level: u32 = self.tetris.get_starting_level() - 1;
                    self.tetris.set_starting_level(new_level);
                }
            },

            Input::Press(Keyboard(Key::L)) => {
                let new_level: u32 = self.tetris.get_starting_level() + 1;
                self.tetris.set_starting_level(new_level);
            },

            _ => {
                self.should_redraw = prev_should_redraw;
            }
        }
    }
}

fn main() {
    start_app();
}

fn start_app() {
    let opengl = OpenGL::_3_2;

    let window = Glutin_Window::new(
        opengl,
        WindowSettings::new("Piston Tetris", [1024, 768])
                       .exit_on_esc(true)
                       .vsync(true)
                       .samples(1)
    );

    let font_path = Path::new("FiraMono-Bold.ttf");

    let mut app = App {
        gl: GlGraphics::new(opengl),
        tetris: Tetris::new(),
        elapsed_time: 0.0,
        cache: GlyphCache::new(font_path).unwrap(),
        should_redraw: true,
    };

    for e in window.events().max_fps(60).ups(120) {
        match e {
            Event::Input(i) => {
                app.handle_input(i);
            }

            Event::Render(args) if app.should_redraw => {
                app.render(&args);
            }

            Event::Update(args) => {
                app.update(&args);
            }

            _ => {}
        }
    }
}<commit_msg>let user pick starting level<commit_after>extern crate piston;
extern crate graphics;
extern crate glutin_window;
extern crate opengl_graphics;
extern crate rand;

pub mod tetris;

use piston::window::WindowSettings;
use piston::event::*;
use glutin_window::GlutinWindow as Glutin_Window;
use opengl_graphics::{ GlGraphics, OpenGL };
use opengl_graphics::glyph_cache::GlyphCache;
use graphics::{ Transformed };
use piston::input::Button::{ Keyboard };
use piston::input::Input;
use piston::input::keyboard::Key;
use std::path::Path;

use tetris::*;

struct App {
    gl: GlGraphics,
    tetris: Tetris,
    elapsed_time: f64,
    cache: GlyphCache<'static>,
    should_redraw: bool
}

const WHITE: [f32; 4] = [1.0, 1.0, 1.0, 1.0];
const BLACK: [f32; 4] = [0.0, 0.0, 0.0, 1.0];
const DARK_GRAY: [f32; 4] = [0.1, 0.1, 0.1, 1.0];
const GREEN: [f32; 4] = [0.0, 1.0, 0.0, 1.0];
const CYAN: [f32; 4] = [0.0, 1.0, 1.0, 1.0];
const RED: [f32; 4] = [1.0, 0.0, 0.0, 1.0];
const BLUE: [f32; 4] = [0.0, 0.0, 1.0, 1.0];
const ORANGE: [f32; 4] = [1.0, 0.5, 0.0, 1.0];
const YELLOW: [f32; 4] = [1.0, 1.0, 0.0, 1.0];
const PURPLE: [f32; 4] = [0.5, 0.0, 1.0, 1.0];

fn get_shape_color(shape_index: i32) -> [f32; 4] {
    match shape_index {
        0 => PURPLE,
        1 => YELLOW,
        2 => RED,
        3 => GREEN,
        4 => ORANGE,
        5 => BLUE,
        6 => CYAN,
        _ => {
            BLACK
        }
    }
}

impl App {
    fn render(&mut self, args: &RenderArgs) {
        self.should_redraw = false;

        const CELL_SIZE: f64 = 30.0;
        const LEFT_MARGIN: f64 = 20f64;
        const TOP_MARGIN: f64 = 30f64;

        const STATUS_LEFT_MARGIN: f64 = 400f64;
        const STATUS_TOP_MARGIN: f64 = 100f64;
        const LINE_HEIGHT: f64 = 40f64;
        const STATUS_PREVIEW_GRID_HEIGHT: f64 = CELL_SIZE * 6f64;

        // so that we can access inside clojure
        let use_cache = &mut self.cache;
        let use_tetris = &mut self.tetris;

        self.gl.draw(args.viewport(), |c, gl| {
            // clear the viewport
            graphics::clear(BLACK, gl);

            // render the current score and level
            let mut text = graphics::Text::new(22);
            text.color = ORANGE;
            let mut transform = c.trans(STATUS_LEFT_MARGIN, STATUS_TOP_MARGIN);
            text.draw(&format!("Level: {}", use_tetris.get_level()), use_cache, &c.draw_state,
                transform.transform, gl);
            transform = transform.trans(0f64, LINE_HEIGHT);

            text.draw(&format!("Score: {}", use_tetris.get_score()), use_cache, &c.draw_state,
                transform.transform, gl);
            transform = transform.trans(0f64, LINE_HEIGHT);

            // render the next shape as a preview of what's coming next
            for point in use_tetris.get_next_shape().iter() {
                let square = graphics::rectangle::square(0f64, 0f64, CELL_SIZE);
                let color = get_shape_color(use_tetris.get_next_shape_index() as i32);
                // render the shape at col 2 and row 2
                let (x, y) = ((2 as i16 + point.x) as f64 * CELL_SIZE,
                    (2 as i16 + point.y) as f64 * CELL_SIZE);
                graphics::rectangle(color, square, transform.trans(x, y).transform, gl);
                let tetromino_border = graphics::Rectangle::new_border(DARK_GRAY, 1.0);
                tetromino_border.draw([0f64, 0f64, CELL_SIZE, CELL_SIZE], &c.draw_state,
                    transform.trans(x, y).transform, gl);
            }
            transform = transform.trans(0f64, STATUS_PREVIEW_GRID_HEIGHT);

            // render GAME OVER text if necessary
            if use_tetris.get_game_over() {
                text.draw(&"GAME OVER", use_cache, &c.draw_state,
                    transform.transform, gl);
                transform = transform.trans(0f64, LINE_HEIGHT);

                text.draw(&"Press 'N' for a new game", use_cache, &c.draw_state,
                    transform.transform, gl);
                transform = transform.trans(0f64, LINE_HEIGHT);

                text.draw(&"Use arrow keys to move and rotate", use_cache, &c.draw_state,
                    transform.transform, gl);
                transform = transform.trans(0f64, LINE_HEIGHT);

                text.draw(&"Press spacebar to drop", use_cache, &c.draw_state,
                    transform.transform, gl);
                transform = transform.trans(0f64, LINE_HEIGHT);

                text.draw(&format!("Press 'K' to decrease starting level ({})", use_tetris.get_starting_level()),
                    use_cache, &c.draw_state, transform.transform, gl);
                transform = transform.trans(0f64, LINE_HEIGHT);

                text.draw(&"Press 'L' to increase starting level",
                    use_cache, &c.draw_state, transform.transform, gl);
                // uncomment if drawing additional text in the status area
                //transform = transform.trans(0f64, LINE_HEIGHT);
            }

            // draw a white border around the game board
            let rect_border = graphics::Rectangle::new_border(WHITE, 1.5);
            rect_border.draw([
                LEFT_MARGIN,
                TOP_MARGIN,
                (CELL_SIZE * COL_COUNT as f64) + 1f64,
                (CELL_SIZE * ROW_COUNT as f64) + 1f64,
            ], &c.draw_state, c.transform, gl);

            // render each cell in the game board
            for col in 0..COL_COUNT as i32 {
                for row in 0..ROW_COUNT as i32 {
                    let cell = use_tetris.get_grid_cell(col, row);
                    if cell.cell_type != GridCellType::Void {
                        let (x, y) = (col as f64 * CELL_SIZE, row as f64 * CELL_SIZE);
                        let square = graphics::rectangle::square(0.0f64, 0.0f64, CELL_SIZE);
                        let color = match cell.cell_type {
                            GridCellType::Shape => get_shape_color(cell.shape_index),
                            GridCellType::Fixed => get_shape_color(cell.shape_index),
                            GridCellType::Ghost => DARK_GRAY,
                            _ => {
                                assert!(false);
                                BLACK
                            }
                        };
                        let transform = c.transform.trans(LEFT_MARGIN, TOP_MARGIN).trans(x, y);
                        graphics::rectangle(color, square, transform, gl);
                        let tetromino_border = graphics::Rectangle::new_border(DARK_GRAY, 1.0);
                        tetromino_border.draw([0f64, 0f64, CELL_SIZE, CELL_SIZE], &c.draw_state, transform, gl);
                    }
                }
            }
        });
    }

    fn update(&mut self, args: &UpdateArgs) {
        if self.tetris.get_game_over() {
            self.elapsed_time = 0.0;
        } else {
            // Here we increment the time elapsed between update()'s
            self.elapsed_time += args.dt;
            // if the elapsed time is now greater than the time allotted between ticks, then invoke tetris.tick()
            if self.elapsed_time > self.tetris.get_tick_time() as f64 {
                self.elapsed_time = 0.0;
                self.tetris.tick();
                self.should_redraw = true;
            }
        }
    }

    fn handle_input(&mut self, i: Input) {
        let prev_should_redraw = self.should_redraw;
        self.should_redraw = true;
        match i {
            Input::Press(Keyboard(Key::Left)) => {
                let col: i32 = self.tetris.get_col();
                self.tetris.set_col(col - 1);
            },

            Input::Press(Keyboard(Key::Right)) => {
                let col: i32 = self.tetris.get_col();
                self.tetris.set_col(col + 1);
            },

            Input::Press(Keyboard(Key::Up)) => {
                self.tetris.rotate(true);
            },

            Input::Press(Keyboard(Key::Down)) => {
                let row: i32 = self.tetris.get_row() + 1;
                self.tetris.set_row(row);
            },

            Input::Press(Keyboard(Key::Space)) => {
                let mut row: i32 = self.tetris.get_row() + 1;
                while self.tetris.set_row(row) {
                    row += 1;
                }
                // hard drop immediately spawns next shape
                self.tetris.tick();
            },

            Input::Press(Keyboard(Key::N)) => {
                self.tetris.start_game();
            },

            Input::Press(Keyboard(Key::K)) => {
                if self.tetris.get_starting_level() > 0 {
                    let new_level: u32 = self.tetris.get_starting_level() - 1;
                    self.tetris.set_starting_level(new_level);
                }
            },

            Input::Press(Keyboard(Key::L)) => {
                if self.tetris.get_starting_level() < 30 {
                    let new_level: u32 = self.tetris.get_starting_level() + 1;
                    self.tetris.set_starting_level(new_level);
                }
            },

            _ => {
                self.should_redraw = prev_should_redraw;
            }
        }
    }
}

fn main() {
    start_app();
}

fn start_app() {
    let opengl = OpenGL::_3_2;

    let window = Glutin_Window::new(
        opengl,
        WindowSettings::new("Piston Tetris", [1024, 768])
                       .exit_on_esc(true)
                       .vsync(true)
                       .samples(1)
    );

    let font_path = Path::new("FiraMono-Bold.ttf");

    let mut app = App {
        gl: GlGraphics::new(opengl),
        tetris: Tetris::new(),
        elapsed_time: 0.0,
        cache: GlyphCache::new(font_path).unwrap(),
        should_redraw: true,
    };

    for e in window.events().max_fps(60).ups(120) {
        match e {
            Event::Input(i) => {
                app.handle_input(i);
            }

            Event::Render(args) if app.should_redraw => {
                app.render(&args);
            }

            Event::Update(args) => {
                app.update(&args);
            }

            _ => {}
        }
    }
}<|endoftext|>


<commit_before>#[macro_use]
extern crate clap;

#[macro_use]
extern crate serde_derive;

extern crate serde_json;

mod timesheet;

fn main() {
    let mut session = timesheet::Session::new();

    /* Handle command line arguments with clap */
    let matches = clap_app!(trk =>
        (version: "0.1")
        (author: "Rafael B. <mediumendian@gmail.com>")
        (about: "Create timesheets from git history and meta info")
            (@arg CONFIG: -c --config +takes_value "[UNUSED] Sets a custom config file")
            (@arg debug: -d ... "[UNUSED] Sets the level of debugging information")

            (@subcommand beginperiod =>
                (about: "Begin period")
                (version: "0.1")
                (author:  "Rafael B. <mediumendian@gmail.com>")
            )
            (@subcommand beginsession =>
                    (about: "Begin session")
                    (version: "0.1")
                    (author:  "Rafael B. <mediumendian@gmail.com>")
            )
            (@subcommand endperiod =>
                (about: "End period")
                (version: "0.1")
                (author:  "Rafael B. <mediumendian@gmail.com>")
            )
            (@subcommand endsession =>
                (about: "End session")
                (version: "0.1")
                (author:  "Rafael B. <mediumendian@gmail.com>")
            )
            (@subcommand pause =>
                (about: "Pause current session")
                (version: "0.1")
                (author: "mediumendian@gmail.com")
            )
            (@subcommand proceed =>
                (about: "Proceed with currently paused session")
                (version: "0.1")
                (author: "mediumendian@gmail.com")
            )
            (@subcommand meta =>
                (about: "Proceed with currently paused session")
                (version: "0.1")
                (author: "mediumendian@gmail.com")
                (@arg text: +required "Meta information about work")
            )
            (@subcommand commit =>
                (about: "add a commit to the event list")
                (version: "0.1")
                (author: "mediumendian@gmail.com")
                (@arg hash: +required "Commit hash id")
            )
            (@subcommand branch =>
                (about: "add a topic to the event list")
                (version: "0.1")
                (author: "mediumendian@gmail.com")
                (@arg name: +required "New branch name")
            )
       )
            .get_matches();

    // Gets a value for config if supplied by user, or defaults to "default.conf"
    let config = matches.value_of("config").unwrap_or("default.conf");
    println!("Value for config: {}", config);

    // You can handle information about subcommands by requesting their matches by name
    // TODO: Find a way to do this in a better way than an if sequence
    if matches.is_present("beginperiod") {
        session.append_event(timesheet::Event::BeginPeriod)
    }
    if matches.is_present("beginsession") {
        session.append_event(timesheet::Event::BeginSession)
    }
    if matches.is_present("endperiod") {
        session.append_event(timesheet::Event::EndPeriod)
    }
    if matches.is_present("endsession") {
        session.append_event(timesheet::Event::EndSession)
    }

    if matches.is_present("pause") {
        session.append_event(timesheet::Event::Pause)
    }
    if matches.is_present("proceed") {
        session.append_event(timesheet::Event::Proceed)
    }

    match matches.subcommand() {
        ("meta", Some(sub_input)) => {
            let metatext = sub_input.value_of("text").unwrap();
            session.append_event(timesheet::Event::Meta { text: metatext.to_string() });
        }
        ("commit", Some(sub_input)) => {
            let commit_hash = sub_input.value_of("hash").unwrap();
            let hash_parsed = u64::from_str_radix(commit_hash, 16).unwrap();
            session.append_event(timesheet::Event::Commit { hash: hash_parsed });
        }
        ("branch", Some(sub_input)) => {
            let branch_name = sub_input.value_of("name").unwrap();
            session.append_event(timesheet::Event::Branch { name: branch_name.to_string() });
        }
        _ => {}
    }
    println!("{:?}", session);

    // Convert the Point to a JSON string.
    let serialized = serde_json::to_string(&session).unwrap();

    // Prints serialized = {"x":1,"y":2}
    println!("serialized = {}", serialized);

    // Convert the JSON string back to a Point.
    let deserialized: timesheet::Session = serde_json::from_str(&serialized).unwrap();

    // Prints deserialized = Point { x: 1, y: 2 }
    println!("deserialized = {:?}", deserialized);
}
<commit_msg>rename append methods to push<commit_after>#[macro_use]
extern crate clap;

#[macro_use]
extern crate serde_derive;

extern crate serde_json;

mod timesheet;

fn main() {
    let mut session = timesheet::Session::new();

    /* Handle command line arguments with clap */
    let matches = clap_app!(trk =>
        (version: "0.1")
        (author: "Rafael B. <mediumendian@gmail.com>")
        (about: "Create timesheets from git history and meta info")
            (@arg CONFIG: -c --config +takes_value "[UNUSED] Sets a custom config file")
            (@arg debug: -d ... "[UNUSED] Sets the level of debugging information")

            (@subcommand beginperiod =>
                (about: "Begin period")
                (version: "0.1")
                (author:  "Rafael B. <mediumendian@gmail.com>")
            )
            (@subcommand beginsession =>
                    (about: "Begin session")
                    (version: "0.1")
                    (author:  "Rafael B. <mediumendian@gmail.com>")
            )
            (@subcommand endperiod =>
                (about: "End period")
                (version: "0.1")
                (author:  "Rafael B. <mediumendian@gmail.com>")
            )
            (@subcommand endsession =>
                (about: "End session")
                (version: "0.1")
                (author:  "Rafael B. <mediumendian@gmail.com>")
            )
            (@subcommand pause =>
                (about: "Pause current session")
                (version: "0.1")
                (author: "mediumendian@gmail.com")
            )
            (@subcommand proceed =>
                (about: "Proceed with currently paused session")
                (version: "0.1")
                (author: "mediumendian@gmail.com")
            )
            (@subcommand meta =>
                (about: "Proceed with currently paused session")
                (version: "0.1")
                (author: "mediumendian@gmail.com")
                (@arg text: +required "Meta information about work")
            )
            (@subcommand commit =>
                (about: "add a commit to the event list")
                (version: "0.1")
                (author: "mediumendian@gmail.com")
                (@arg hash: +required "Commit hash id")
            )
            (@subcommand branch =>
                (about: "add a topic to the event list")
                (version: "0.1")
                (author: "mediumendian@gmail.com")
                (@arg name: +required "New branch name")
            )
       )
            .get_matches();

    // Gets a value for config if supplied by user, or defaults to "default.conf"
    let config = matches.value_of("config").unwrap_or("default.conf");
    println!("Value for config: {}", config);

    // You can handle information about subcommands by requesting their matches by name
    // TODO: Find a way to do this in a better way than an if sequence
    if matches.is_present("beginperiod") {
        session.push_event(timesheet::Event::BeginPeriod)
    }
    if matches.is_present("beginsession") {
        session.push_event(timesheet::Event::BeginSession)
    }
    if matches.is_present("endperiod") {
        session.push_event(timesheet::Event::EndPeriod)
    }
    if matches.is_present("endsession") {
        session.push_event(timesheet::Event::EndSession)
    }

    if matches.is_present("pause") {
        session.push_event(timesheet::Event::Pause)
    }
    if matches.is_present("proceed") {
        session.push_event(timesheet::Event::Proceed)
    }

    match matches.subcommand() {
        ("meta", Some(sub_input)) => {
            let metatext = sub_input.value_of("text").unwrap();
            session.push_event(timesheet::Event::Meta { text: metatext.to_string() });
        }
        ("commit", Some(sub_input)) => {
            let commit_hash = sub_input.value_of("hash").unwrap();
            let hash_parsed = u64::from_str_radix(commit_hash, 16).unwrap();
            session.push_event(timesheet::Event::Commit { hash: hash_parsed });
        }
        ("branch", Some(sub_input)) => {
            let branch_name = sub_input.value_of("name").unwrap();
            session.push_event(timesheet::Event::Branch { name: branch_name.to_string() });
        }
        _ => {}
    }
    println!("{:?}", session);

    // Convert the Point to a JSON string.
    let serialized = serde_json::to_string(&session).unwrap();

    // Prints serialized = {"x":1,"y":2}
    println!("serialized = {}", serialized);

    // Convert the JSON string back to a Point.
    let deserialized: timesheet::Session = serde_json::from_str(&serialized).unwrap();

    // Prints deserialized = Point { x: 1, y: 2 }
    println!("deserialized = {:?}", deserialized);
}
<|endoftext|>


<commit_before>extern crate regex;

use std::rc::Rc;
use regex::Regex;
use std::collections::HashMap;
use std::io::prelude::*;
use std::io::stdin;
use std::iter::Iterator;
use std::string::String;

#[derive(Debug, PartialEq, Clone)]
enum Atom {
    Integer(i64),
    Float(f64),
    Symbol(String),
    Nil
}

type Function = Fn(Vec<Atom>) -> Atom;
type FunctionMap = HashMap<String, Box<Function>>;

fn nil_func(v: Vec<Atom>) -> Atom {
    return Atom::Nil;
}

struct Env {
    func_map: FunctionMap
}

fn add(v: Vec<Atom>) -> Atom {
    let mut result = 0;

    for i in v {
        match i {
            Atom::Integer(d) => result += d,
            _ => panic!("Can only add integers right now!"),
        }
    }

    return Atom::Integer(result);
}

// fn define(args: Vec<Atom>, env: &mut Env) -> Atom {
//     if let Atom::Symbol(ref s) = args[0] {
//         env..insert(s.to_string(), EnvValue::Value(args[0].clone()));
//         return Atom::Nil;
//     } else {
//         panic!("can't define a non symbol!");
//     }
// }

fn default_env() -> Env {
    let mut env = Env{func_map: HashMap::new()};

    env.func_map.insert("nil".to_string(), Box::new(nil_func) as Box<Function>);
    env.func_map.insert("+".to_string(), Box::new(add) as Box<Function>);

    return env;
}

fn tokenize(line: &str) -> Node {
    let r = Regex::new(r"\s+").unwrap();
    let l = line.replace("(", " ( ").replace(")", " ) ").trim().to_string();
    let iter = r.split(&l);
    read_tokens(&mut iter.peekable())
}

fn atom(token: &str) -> Atom {
    let i = token.parse::<i64>();
     match i {
         Ok(v) => Atom::Integer(v),
         _ => {
             let f = token.parse::<f64>();
             match f {
                 Ok(x) => Atom::Float(x),
                 _ => Atom::Symbol(token.to_string())
             }
         },
     }
}

#[derive(Debug,PartialEq)]
struct Node {
    atom: Atom,
    children: Vec<Node>
}

fn read_tokens(iter: &mut std::iter::Peekable<regex::RegexSplits>) -> Node {
    let mut node = Node{ atom: Atom::Nil, children: vec![] };

    match iter.next() {
        Some("(") => {
            loop {
                match iter.peek() {
                    Some(&")") => break,
                    Some(_) => {},
                    None => panic!("unexpected EOF"),
                }
                node.children.push(read_tokens(iter));
            }
        },
        Some(")") => panic!("mismatched )"),
        Some(x) => {
            node.atom = atom(x);
        },
        None => panic!("unexpected EOF")
    }
    return node;
}

fn eval(node: &Node, env: &mut Env) -> Atom {
     match node.atom {
        Atom::Nil => {
            let args: Vec<Atom> = node.children.iter().skip(1).map(|node| eval(node, env)).collect();

            match node.children[0].atom {
                Atom::Symbol(ref s) => {
                    if *s == "define" {
                        println!("define!");
                        return Atom::Nil;
                    }

                    match env.func_map.get(s) {
                        Some(f) => return f(args),
                        None => return Atom::Nil
                    }
                },
                _ => panic!("has to be a symbol!")
            }
        },
        Atom::Integer(i) => {
            println!("an integer: {}", i);
        },
        Atom::Float(f) => {
            println!("a float: {}", f);
        },
        Atom::Symbol(ref s) => {
            println!("a symbol, {}", s);
        }
    }

    return Atom::Nil;
}

fn parse(line: &str) -> Node {
    tokenize(line)
}

fn flush() {
    let out = std::io::stdout();
    let mut o = out.lock();
    o.flush().unwrap();
}

fn repl() {
    println!("Rust Lisp!");
    let mut input = stdin();
    let mut line = String::new();
    let mut env = default_env();
    loop {
        print!(">");
        flush();

        match input.read_line(&mut line) {
            Ok(size) => {
                if size == 0 {
                    break;
                } else {
                    let r = eval(&parse(&line), &mut env);
                    println!("{:?}", r);
                }
            },
            Err(e) => {
                println!("Error: {:?}", e);
                break;
            }
        }
    }
}

pub fn main() {
    repl();
}

#[cfg(test)]
mod test {
    fn make_atom_node(s: &str) -> Node {
        return Node{ atom: atom(s), children: vec![]};
    }

    #[test]
    fn atom_test() {
        assert_eq!(Atom::Integer(32), atom("32"));
        assert_eq!(Atom::Symbol("symbol".to_string()), atom("symbol"));
    }

    #[test]
    fn simple_read_tokens() {
        let x = parse("(+ 1 2)");

        assert_eq!(Atom::Nil, x.atom);
        assert_eq!(3, x.children.len());

        let xx : Vec<Node> = vec![make_atom_node("+"), make_atom_node("1"), make_atom_node("2")];

        for pair in xx.iter().zip(x.children.iter()) {
            assert_eq!(pair.0, pair.1);
        }
    }

    #[test]
    fn nested_read_tokens() {
        let x = parse("(+ 1 (* 2 2))");

        assert_eq!( atom("+"), x.children[0].atom);
        assert_eq!( atom("1"), x.children[1].atom);
        assert_eq!( Atom::Nil, x.children[2].atom);

        assert_eq!( 3, x.children[2].children.len());
        assert_eq!( atom("*"), x.children[2].children[0].atom);
        assert_eq!( atom("2"), x.children[2].children[1].atom);
        assert_eq!( atom("2"), x.children[2].children[2].atom);
    }

    #[test]
    #[should_panic]
    fn unmatched_bracket() {
        let x = parse("(+ 1");
    }

    #[test]
    #[should_panic]
    fn eof() {
        let x = parse("");
    }
}
<commit_msg>use refs<commit_after>extern crate regex;

use regex::Regex;
use std::collections::HashMap;
use std::io::prelude::*;
use std::io::stdin;
use std::iter::Iterator;
use std::string::String;

#[derive(Debug, PartialEq, Clone)]
enum Atom {
    Integer(i64),
    Float(f64),
    Symbol(String),
    Nil
}

type Function = Fn(&Vec<Atom>) -> Atom;
type FunctionMap = HashMap<String, Box<Function>>;

fn nil_func(_: &Vec<Atom>) -> Atom {
    return Atom::Nil;
}

struct Env {
    func_map: FunctionMap
}

fn add(v: &Vec<Atom>) -> Atom {
    let mut result = 0;

    for i in v {
        match *i {
            Atom::Integer(d) => result += d,
            _ => panic!("Can only add integers right now!"),
        }
    }

    return Atom::Integer(result);
}

fn default_env() -> Env {
    let mut env = Env{func_map: HashMap::new()};

    env.func_map.insert("nil".to_string(), Box::new(nil_func) as Box<Function>);
    env.func_map.insert("+".to_string(), Box::new(add) as Box<Function>);

    return env;
}

fn tokenize(line: &str) -> Node {
    let r = Regex::new(r"\s+").unwrap();
    let l = line.replace("(", " ( ").replace(")", " ) ").trim().to_string();
    let iter = r.split(&l);
    read_tokens(&mut iter.peekable())
}

fn atom(token: &str) -> Atom {
    let i = token.parse::<i64>();
     match i {
         Ok(v) => Atom::Integer(v),
         _ => {
             let f = token.parse::<f64>();
             match f {
                 Ok(x) => Atom::Float(x),
                 _ => Atom::Symbol(token.to_string())
             }
         },
     }
}

#[derive(Debug,PartialEq)]
struct Node {
    atom: Atom,
    children: Vec<Node>
}

fn read_tokens(iter: &mut std::iter::Peekable<regex::RegexSplits>) -> Node {
    let mut node = Node{ atom: Atom::Nil, children: vec![] };

    match iter.next() {
        Some("(") => {
            loop {
                match iter.peek() {
                    Some(&")") => break,
                    Some(_) => {},
                    None => panic!("unexpected EOF"),
                }
                node.children.push(read_tokens(iter));
            }
        },
        Some(")") => panic!("mismatched )"),
        Some(x) => {
            node.atom = atom(x);
        },
        None => panic!("unexpected EOF")
    }
    return node;
}

fn eval(node: &Node, env: &mut Env) -> Atom {
     match node.atom {
        Atom::Nil => {
            let args: Vec<Atom> = node.children.iter().skip(1).map(|node| eval(node, env)).collect();

            match node.children[0].atom {
                Atom::Symbol(ref s) => {
                    if *s == "define" {
                        println!("define!");
                        return Atom::Nil;
                    }

                    match env.func_map.get(s) {
                        Some(f) => return f(&args),
                        None => return Atom::Nil
                    }
                },
                _ => panic!("has to be a symbol!")
            }
        },
        Atom::Integer(i) => {
            println!("an integer: {}", i);
        },
        Atom::Float(f) => {
            println!("a float: {}", f);
        },
        Atom::Symbol(ref s) => {
            println!("a symbol, {}", s);
        }
    }

    return Atom::Nil;
}

fn parse(line: &str) -> Node {
    tokenize(line)
}

fn flush() {
    let out = std::io::stdout();
    let mut o = out.lock();
    o.flush().unwrap();
}

fn repl() {
    println!("Rust Lisp!");
    let mut input = stdin();
    let mut line = String::new();
    let mut env = default_env();
    loop {
        print!(">");
        flush();

        match input.read_line(&mut line) {
            Ok(size) => {
                if size == 0 {
                    break;
                } else {
                    let r = eval(&parse(&line), &mut env);
                    println!("{:?}", r);
                }
            },
            Err(e) => {
                println!("Error: {:?}", e);
                break;
            }
        }
    }
}

pub fn main() {
    repl();
}

#[cfg(test)]
mod test {
    fn make_atom_node(s: &str) -> Node {
        return Node{ atom: atom(s), children: vec![]};
    }

    #[test]
    fn atom_test() {
        assert_eq!(Atom::Integer(32), atom("32"));
        assert_eq!(Atom::Symbol("symbol".to_string()), atom("symbol"));
    }

    #[test]
    fn simple_read_tokens() {
        let x = parse("(+ 1 2)");

        assert_eq!(Atom::Nil, x.atom);
        assert_eq!(3, x.children.len());

        let xx : Vec<Node> = vec![make_atom_node("+"), make_atom_node("1"), make_atom_node("2")];

        for pair in xx.iter().zip(x.children.iter()) {
            assert_eq!(pair.0, pair.1);
        }
    }

    #[test]
    fn nested_read_tokens() {
        let x = parse("(+ 1 (* 2 2))");

        assert_eq!( atom("+"), x.children[0].atom);
        assert_eq!( atom("1"), x.children[1].atom);
        assert_eq!( Atom::Nil, x.children[2].atom);

        assert_eq!( 3, x.children[2].children.len());
        assert_eq!( atom("*"), x.children[2].children[0].atom);
        assert_eq!( atom("2"), x.children[2].children[1].atom);
        assert_eq!( atom("2"), x.children[2].children[2].atom);
    }

    #[test]
    #[should_panic]
    fn unmatched_bracket() {
        let x = parse("(+ 1");
    }

    #[test]
    #[should_panic]
    fn eof() {
        let x = parse("");
    }
}
<|endoftext|>


<commit_before>extern crate zwreec;
extern crate getopts;
#[macro_use] extern crate log;
extern crate time;
extern crate term;

use std::env;
use std::vec::Vec;
use std::fs::File;
use std::io::Write;

mod utils;
use self::utils::logger;

// shorthand to display program usage
macro_rules! print_usage {
    ($prog:ident, $opts:ident) => {{
        print_stderr!("{}", $opts.usage(&format!("Usage: {} [-hV] [-vq] [-l [LOGFILE]] [-o OUTPUT] INPUT", $prog)));
    }}
}

// found in:
// http://stackoverflow.com/a/27590832
macro_rules! print_stderr(
    ($($arg:tt)*) => (
        match write!(&mut ::std::io::stderr(), $($arg)* ) {
            Ok(_) => {},
            Err(x) => panic!("Unable to write to stderr: {}", x),
        }
    )
);

fn main() {
    //early init

    // handling command line parameters
    let args: Vec<String> = env::args().collect();
    let ref program = args[0];
    let mut loggers: Vec<Box<logger::SharedLogger>> = vec![];

    // define options
    let mut opts = getopts::Options::new();
    opts.optflagmulti("v", "verbose", "be more verbose. Can be used multiple times.");
    opts.optflag("q", "quiet", "be quiet");
    opts.optflagopt("l", "logfile", "specify log file (default zwreec.log)", "LOGFILE");
    opts.optopt("o", "", "name of the output file", "FILE");
    opts.optflag("h", "help", "display this help and exit");
    opts.optflag("V", "version", "display version");

    let parsed_opts = match opts.parse(&args[1..]) {
        Ok(m)  => { m }
        Err(f) => {
            // parsing error
            // display usage and return
            print_stderr!("{}\n", f.to_string());
            print_usage!(program, opts);
            // TODO: figure out a way to set exit code
            return;
        }
    };

    // examine options
    if parsed_opts.opt_present("h") {
        // parsed "-h|--help"
        // display usage and return
        print_usage!(program, opts);
        return;
    }

    if parsed_opts.opt_present("V") {
        // parsed "-V|--version"
        // display current version
        println!("{} {}", program, match option_env!("CFG_VERSION") {
            Some(s) => s.to_string(),
            None => format!("{}.{}.{}{}",
                            env!("CARGO_PKG_VERSION_MAJOR"),
                            env!("CARGO_PKG_VERSION_MINOR"),
                            env!("CARGO_PKG_VERSION_PATCH"),
                            option_env!("CARGO_PKG_VERSION_PRE").unwrap_or(""))
        });
        return;
    }

    if parsed_opts.opt_present("v") {
        // parsed "-v|--verbose"
        // set log level to verbose
        loggers.push(logger::TermLogger::new(
                match parsed_opts.opt_count("v") {
                    1 => logger::LogLevelFilter::Info,
                    2 => logger::LogLevelFilter::Debug,
                    _ => logger::LogLevelFilter::Trace,
                }));
    } else if parsed_opts.opt_present("q") {
        // parsed "-q|--quiet"
        // set log level to error
        loggers.push(logger::TermLogger::new(logger::LogLevelFilter::Error));
    } else {
        // default
        // set log level to warn
        loggers.push(logger::TermLogger::new(logger::LogLevelFilter::Warn));
    }

    if parsed_opts.opt_present("l") {
        // parsed "-l|--logfile"
        // sets a logger to output to logfile
        let name = if let Some(n) = parsed_opts.opt_str("l") {
            n
        } else {
            "zwreec.log".to_string()
        };
        loggers.push(logger::FileLogger::new(
                        logger::LogLevelFilter::Trace,
                        File::create(name).unwrap())
            );
    }

    let outfile = if let Some(file) = parsed_opts.opt_str("o") {
        // parsed "-o FILE"
        // set of to filename
        file
    } else {
        // NOTE: string manipulation in rust is still weird.
        let mut s = String::new();
        s.push_str("a.out");
        s
    };

    let infile = if parsed_opts.free.len() == 1 {
         // check number of 'free' parameter
         // one free parameter is the input file name
         parsed_opts.free[0].clone()
    } else {
        print_stderr!("Input file name missing\n");
        print_usage!(program, opts);
        // TODO: figure out a way to set exit code
        return;
    };

    // activate logger
    // NOTE: I am not sure, if there is a *good* way to do this earlier

    let _ = logger::CombinedLogger::init(loggers);

    debug!("parsed command line options");
    info!("main started");

    // call library
    zwreec::compile(&infile, &outfile);

    // only for testing
    debug!("(1) {}", zwreec::frontend::temp_hello());
    debug!("(2) {}", zwreec::backend::temp_hello());
    debug!("(3) {}", zwreec::file::temp_hello());

    info!("main finished");
}
<commit_msg>Better String Handling and other cleanup<commit_after>extern crate zwreec;
extern crate getopts;
#[macro_use] extern crate log;
extern crate time;
extern crate term;

use std::env;
use std::vec::Vec;
use std::fs::File;
use std::io::Write;

mod utils;
use self::utils::logger;

// shorthand to display program usage
macro_rules! print_usage(
    ($prog:ident, $opts:ident) => (
    print_stderr!("{}", $opts.usage(&format!("Usage: {} [-hV] [-vq] [-l [LOGFILE]] [-o OUTPUT] INPUT", $prog)));
    )
);

// found in:
// http://stackoverflow.com/a/27590832
macro_rules! print_stderr(
    ($($arg:tt)*) => (
        match write!(&mut ::std::io::stderr(), $($arg)* ) {
            Ok(_) => {},
            Err(x) => panic!("Unable to write to stderr: {}", x),
        }
    )
);

fn main() {
    //early init

    // handling command line parameters
    let args: Vec<String> = env::args().collect();
    let ref program = args[0];
    let mut loggers: Vec<Box<logger::SharedLogger>> = vec![];

    // define options
    let mut opts = getopts::Options::new();
    opts.optflagmulti("v", "verbose", "be more verbose. Can be used multiple times.");
    opts.optflag("q", "quiet", "be quiet");
    opts.optflagopt("l", "logfile", "specify log file (default zwreec.log)", "LOGFILE");
    opts.optopt("o", "", "name of the output file", "FILE");
    opts.optflag("h", "help", "display this help and exit");
    opts.optflag("V", "version", "display version");

    let parsed_opts = match opts.parse(&args[1..]) {
        Ok(m)  => { m }
        Err(f) => {
            // parsing error
            // display usage and return
            print_stderr!("{}\n", f.to_string());
            print_usage!(program, opts);
            // TODO: figure out a way to set exit code
            return;
        }
    };

    // examine options
    if parsed_opts.opt_present("h") {
        // parsed "-h|--help"
        // display usage and return
        print_usage!(program, opts);
        return;
    }

    if parsed_opts.opt_present("V") {
        // parsed "-V|--version"
        // display current version
        println!("{} {}", program, match option_env!("CFG_VERSION") {
            Some(s) => s.to_string(),
            None => format!("{}.{}.{}{}",
                            env!("CARGO_PKG_VERSION_MAJOR"),
                            env!("CARGO_PKG_VERSION_MINOR"),
                            env!("CARGO_PKG_VERSION_PATCH"),
                            option_env!("CARGO_PKG_VERSION_PRE").unwrap_or(""))
        });
        return;
    }

    if parsed_opts.opt_present("v") {
        // parsed "-v|--verbose"
        // set log level to verbose
        loggers.push(logger::TermLogger::new(
                match parsed_opts.opt_count("v") {
                    1 => logger::LogLevelFilter::Info,
                    2 => logger::LogLevelFilter::Debug,
                    _ => logger::LogLevelFilter::Trace,
                }));
    } else if parsed_opts.opt_present("q") {
        // parsed "-q|--quiet"
        // set log level to error
        loggers.push(logger::TermLogger::new(logger::LogLevelFilter::Error));
    } else {
        // default
        // set log level to warn
        loggers.push(logger::TermLogger::new(logger::LogLevelFilter::Warn));
    }

    if parsed_opts.opt_present("l") {
        // parsed "-l|--logfile"
        // sets a logger to output to logfile
        let name = if let Some(n) = parsed_opts.opt_str("l") {
            n
        } else {
            "zwreec.log".to_string()
        };
        loggers.push(logger::FileLogger::new(
                        logger::LogLevelFilter::Trace,
                        File::create(name).unwrap())
            );
    }

    let outfile = if let Some(file) = parsed_opts.opt_str("o") {
        // parsed "-o FILE"
        // set of to filename
        file
    } else {
        // assume default
        "a.out".to_string()
    };

    let infile = if parsed_opts.free.len() == 1 {
         // check number of 'free' parameter
         // one free parameter is the input file name
         parsed_opts.free[0].clone()
    } else {
        print_stderr!("Input file name missing\n");
        print_usage!(program, opts);
        // TODO: figure out a way to set exit code
        return;
    };

    // activate logger
    let _ = logger::CombinedLogger::init(loggers);

    debug!("parsed command line options");
    info!("main started");

    // call library
    zwreec::compile(&infile, &outfile);

    // only for testing
    debug!("(1) {}", zwreec::frontend::temp_hello());
    debug!("(2) {}", zwreec::backend::temp_hello());
    debug!("(3) {}", zwreec::file::temp_hello());

    info!("main finished");
}
<|endoftext|>


<commit_before>extern crate osmio;
extern crate image;
extern crate gif;

use std::fs;
use osmio::OSMReader;
use osmio::pbf::PBFReader;
use std::env::args;
use std::io::{Write, BufReader, BufWriter, BufRead};

use gif::SetParameter;

fn read_file(filename: &str, output_csv: &str) {
    let file = BufReader::new(fs::File::open(&filename).unwrap());
    let mut node_reader = PBFReader::new(file);
    let node_reader = node_reader.nodes();

    let mut output_file = BufWriter::new(fs::File::create(&output_csv).expect("Could not open output CSV"));

    let mut num_nodes = 0;
    for node in node_reader {
        // Might be quicker to use binary search thing
        if let (Some(lat), Some(lon)) = (node.lat, node.lon) {
            let timestamp = node.timestamp.to_epoch_number();
            writeln!(output_file, "{},{},{}", timestamp, lat, lon).expect("Could not write line");
            num_nodes += 1;
            if num_nodes % 10_000_000 == 0 {
                println!("Written {} nodes", num_nodes);
            }
        }
    }
}

#[allow(unused_variables)]
fn age_to_colour(age: u32) -> [u8; 3] {
    if age < 7*24*60*60 {
        [255, 0, 0]
    } else {
        [0, 0, 0]
    }
}

fn create_equirectangular_map(input_csv_filename: &str, output_image_filename: &str, height: u32, frames_per_sec: u32) {
    let input_csv = BufReader::new(fs::File::open(input_csv_filename).expect("Cannot open CSV file"));
    let mut output_file = fs::File::create(output_image_filename).expect("Can't create image");
    let width = height * 2;
    // FIXME change width/height to u16?
    let mut encoder = gif::Encoder::new(&mut output_file, width as u16, height as u16, &[]).expect("Couldn't create encoder");
    encoder.set(gif::Repeat::Infinite).expect("Couldn't get inf repeat");

    //let mut frame_no = 0;
    let mut image = vec![0u32; (width*height) as usize];
    let mut timestamp_of_last_frame = 0;

    for line in input_csv.lines() {
        let line = line.expect("Cannot read line");
        let nums: Vec<_> = line.split(",").take(3).collect();
        let timestamp: u32 = nums[0].parse().expect("not a number");
        let lat: f32 = nums[1].parse().expect("not a number");
        let lon: f32 = nums[2].parse().expect("not a number");
        //println!("Doing change for timestamp {}", timestamp);

        if lat > 90. || lat < -90. || lon > 180. || lon < -180. {
            //println!("Bad location lat = {} lon = {}", lat, lon);
            // WTF bad data?
            continue;
        }

        if timestamp_of_last_frame == 0 {
            timestamp_of_last_frame = timestamp;
        }

        if timestamp < timestamp_of_last_frame {
            panic!("Input CSV file isn't sorted! run 'sort -o {} {}' to sort it", input_csv_filename, input_csv_filename);
        }

        if timestamp - timestamp_of_last_frame >= frames_per_sec {
            // Write out a new frame
            let img = image::ImageBuffer::from_fn(width, height as u32, |x, y| {
                //println!("x = {} y = {} width = {} height = {} x*width+y = {}", x, y, width, height, x*width+y);
                let curr_value = image[(y*width+x) as usize];
                let age = timestamp - curr_value;
                image::Rgb(age_to_colour(age))
            });

            //let mut f = fs::File::create(format!("{}-frame{:08}.png", output_image_filename, frame_no)).expect("Couldn't create frame");
            //image::ImageRgb8(img.clone()).save(&mut f, image::PNG).expect("Couldn't save image");
            //frame_no += 1;

            let mut frame = gif::Frame::from_rgb(width as u16, height as u16, &img.into_vec());
            // 30 fps, and delay is in units of 10ms.
            frame.delay = 100 / 30;

            encoder.write_frame(&frame).expect("Couldn't write frame");

            timestamp_of_last_frame = timestamp;
            let iso = osmio::utils::epoch_to_iso(timestamp_of_last_frame as i32);
            println!("Wrote frame for timestamp {} ({})", iso, timestamp);
        }

        //let lat = lat * -1.;

        // update the image
        let x = (((lon + 90.)/180.)*(width as f32)) as u32;
        let y = (((lat + 180.)/360.)*(height as f32)) as u32;

        //println!("lat = {} lon = {} x = {} y = {} y*width+x = {}", lat, lon, x, y, y*width+x);
        let i = (y * width + x) as usize;
        image[i] = timestamp;

    }

}

fn main() {
    let command = args().nth(1).expect("Need a command");
    if command == "parsepbf" {
        let input_filename = args().nth(2).expect("Missing inputfilename");
        let output_csv = args().nth(3).expect("Missing csv output");
        println!("Writing node history CSV to {}", output_csv);
        read_file(&input_filename, &output_csv);
        // FIXME call sort(1) here
    } else if command == "createimage" {
        let input_csv = args().nth(2).expect("Missing input csv");
        let output_image = args().nth(3).expect("Missing output image");
        let height: u32 = args().nth(4).expect("need to provide a height").parse().expect("Not an integer");
        let frames_per_sec: u32 = args().nth(5).expect("need to provide a speed").parse().expect("Not an integer");
        //let  = args().nth(3).expect("Missing output image");
        println!("Creating image from {}", input_csv);
        create_equirectangular_map(&input_csv, &output_image, height, frames_per_sec);
    } else {
        panic!("Nothing to do");

    }

    println!("\nFinished");
}
<commit_msg>stuff<commit_after>extern crate osmio;
extern crate image;
extern crate gif;

use std::fs;
use osmio::OSMReader;
use osmio::pbf::PBFReader;
use std::env::args;
use std::io::BufReader;
use std::collections::{HashMap, HashSet};

use gif::SetParameter;

type Frames = Vec<(u32, Vec<u32>)>;

fn read_file(filename: &str, height: u32, sec_per_frame: u32) -> Frames {
    let file = BufReader::new(fs::File::open(&filename).unwrap());
    let mut node_reader = PBFReader::new(file);
    let node_reader = node_reader.nodes();

    println!("Parsing {}", filename);

    let mut results: HashMap<u32, HashSet<u32>> = HashMap::new();

    // 1st April 2005, midnight GMT. We presume no OSM editing before then.
    let osm_epoch = 1109635200;

    let width = height * 2;

    // FIXME use a btreemap?

    let mut first_frame_no = std::u32::MAX;
    let mut last_frame_no = 0;

    let mut num_nodes = 0;
    for node in node_reader {
        if let (Some(lat), Some(lon)) = (node.lat, node.lon) {
            let timestamp = node.timestamp.to_epoch_number() as u64;
            if timestamp < osm_epoch {
                panic!("timestamp before epoch. Change code. {}", timestamp);
            }
            let offset = (timestamp - osm_epoch) as u32;
            // TODO double check that this rounds down
            let frame_no = offset / sec_per_frame;

            if frame_no < first_frame_no {
                first_frame_no = frame_no;
            }
            if frame_no > last_frame_no {
                last_frame_no = frame_no;
            }

            let pixel_idx = latlon_to_pixel_index(lat, lon, width, height);
            results.entry(frame_no).or_insert(HashSet::new()).insert(pixel_idx);

            num_nodes += 1;
            if num_nodes % 10_000_000 == 0 {
                println!("Done {} nodes", num_nodes);
            }
        }
    }
    let num_frames = last_frame_no - first_frame_no + 1;
    println!("There are {} frames, which is {} sec", num_frames, num_frames as f32/30.);

    let mut sorted_results = Vec::with_capacity((last_frame_no-first_frame_no+1) as usize);

    for frame_no in 0..num_frames {
        match results.remove(&(frame_no+first_frame_no)) {
            None => { sorted_results.push((frame_no, Vec::with_capacity(0))) },
            Some(pixels) => {
                let pixels = pixels.into_iter().collect();
                sorted_results.push((frame_no, pixels));
            }
        }
    }

    sorted_results
}

#[inline(always)]
fn age_to_colour(curr_value: u32, frame_no: u32) -> [u8; 3] {
    if curr_value == 0 {
        // This means the pixel has never been used
        [0, 0, 0]
    } else {
        let age = frame_no - curr_value;
        if age > 255 {
            [0, 0, 0]
        } else {
            [(255 - age) as u8, 0, 0]
        }

    }
}

fn latlon_to_pixel_index(lat: f32, lon: f32, width: u32, height: u32) -> u32 {
    // update the image
    let x = (((lon + 90.)/180.)*(width as f32)) as u32;
    let y = (((lat + 180.)/360.)*(height as f32)) as u32;

    //println!("lat = {} lon = {} x = {} y = {} y*width+x = {}", lat, lon, x, y, y*width+x);
    let i = y * width + x;

    i
}

fn create_equirectangular_map(frames: Frames, output_image_filename: &str, height: u32) {
    let mut output_file = fs::File::create(output_image_filename).expect("Can't create image");

    let width = height * 2;
    // FIXME change width/height to u16?
    let mut encoder = gif::Encoder::new(&mut output_file, width as u16, height as u16, &[]).expect("Couldn't create encoder");
    encoder.set(gif::Repeat::Infinite).expect("Couldn't get inf repeat");

    // 0 means never done.
    let mut image = vec![0u32; (width*height) as usize];

    for (frame_no, pixels) in frames.into_iter() {
        for i in pixels {
            image[i as usize] = frame_no;
        }

        // Write out a new frame
        let img = image::ImageBuffer::from_fn(width, height, |x, y| {
            //println!("x = {} y = {} width = {} height = {} x*width+y = {}", x, y, width, height, x*width+y);
            let curr_value = image[(y*width+x) as usize];
            image::Rgb(age_to_colour(curr_value, frame_no))
        });

        //let mut f = fs::File::create(format!("{}-frame{:08}.png", output_image_filename, frame_no)).expect("Couldn't create frame");
        //image::ImageRgb8(img.clone()).save(&mut f, image::PNG).expect("Couldn't save image");
        //frame_no += 1;

        let mut frame = gif::Frame::from_rgb(width as u16, height as u16, &img.into_vec());
        // 30 fps, and delay is in units of 10ms.
        frame.delay = 100 / 30;

        encoder.write_frame(&frame).expect("Couldn't write frame");

        println!("Wrote frame {}", frame_no);
        //println!("Wrote frame for timestamp {} ({})", iso, timestamp);

    }

}

fn main() {
    let input_filename = args().nth(1).expect("Missing inputfilename");
    let output_image = args().nth(2).expect("Missing output image");
    let height: u32 = args().nth(3).expect("need to provide a height").parse().expect("Not an integer");
    let frames_per_sec: u32 = args().nth(4).expect("need to provide a speed").parse().expect("Not an integer");

    let frames = read_file(&input_filename, height, frames_per_sec);

    println!("Creating image {}", output_image);

    create_equirectangular_map(frames, &output_image, height);

    println!("\nFinished");
}
<|endoftext|>


<commit_before>extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate hyper;
extern crate chrono;

use std::env;
use hyper::Client;
use hyper::header::Connection;
use std::vec::Vec;

header! { (XToken, "x-token") => [String] }

include!(concat!(env!("OUT_DIR"), "/serde_types.rs"));

fn main() {
    let token = env::args().skip(1).next().unwrap();

    let client = Client::new();

    println!("send request for token {}", token);
    let res = client.
        get("https://api.debitoor.com/api/expenses/v3").
        //if we keep the connection open the parsing will wait for a minute in between for a timeout
        //don't know why this is, so just disable keep alive for now
        header(Connection::close()).
        //the access token to authenticate with
        header(XToken(token.to_owned())).
        send().unwrap();
    assert_eq!(res.status, hyper::Ok);

    println!("create parser");

    let expenses: Vec<Expense> = serde_json::from_reader(res).unwrap();

    println!("printing value");

    for expense in expenses {
        for line in expense.lines.iter().filter(|line| line.category_type == "asset") {
            println!("{:?}", line);
        }
    }

    println!("all done");
}
<commit_msg>listen on port 8080 and output result there<commit_after>extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate hyper;
extern crate chrono;

use std::env;
use hyper::Client;
use hyper::Server;
use hyper::header::Connection;
use std::vec::Vec;

header! { (XToken, "x-token") => [String] }

include!(concat!(env!("OUT_DIR"), "/serde_types.rs"));

fn main() {
    let port = env::var("DEBITOOR_EXTENSIONS_PORT").or(Ok::<String, std::env::VarError>("8080".to_string())).unwrap().parse::<i32>().unwrap();

    fn hello(serverReq: hyper::server::Request, serverRes: hyper::server::Response) {
        //println!("Incoming request {:?}", req);

        let token = env::args().skip(1).next().unwrap();

        let client = Client::new();

        println!("send request for token {}", token);
        let res = client.
            get("https://api.debitoor.com/api/expenses/v3").
            //if we keep the connection open the parsing will wait for a minute in between for a timeout
            //don't know why this is, so just disable keep alive for now
            header(Connection::close()).
            //the access token to authenticate with
            header(XToken(token.to_owned())).
            send().unwrap();
        assert_eq!(res.status, hyper::Ok);

        println!("create parser");

        let expenses: Vec<Expense> = serde_json::from_reader(res).unwrap();

        println!("printing value");

        let mut asset_string = "".to_string();

        for expense in expenses {
            for line in expense.lines.iter().filter(|line| line.category_type == "asset") {
                println!("{:?}", line);
                asset_string = asset_string + &*format!("{:?}\n", line);
            }
        }

        println!("Sending response");
        serverRes.send(asset_string.as_bytes()).unwrap();

        println!("all done");
    }

    println!("listening on {:?}", port);
    Server::http(&*format!("0.0.0.0:{}", port)).unwrap().handle(hello).unwrap();
}
<|endoftext|>


<commit_before>#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]

#[macro_use]
extern crate clap;
extern crate reqwest;
#[macro_use]
extern crate serde_derive;
extern crate toml;

use std::env;
use std::io::prelude::*;
use std::fs::File;
use clap::App;

mod github;

static GITHUB_TOKEN: &'static str = "RP_GITHUBTOKEN";

fn main() {
    let yaml = load_yaml!("release-party.yml");
    let matches = App::from_yaml(yaml).get_matches();

    let org_url = make_org_url(&matches);
    let token = get_github_token();
    let reqwest_client = get_reqwest_client();

    print_party_links(get_pr_links(
        &get_repos_we_care_about(&token, &org_url, &reqwest_client),
        &token,
        &reqwest_client,
        is_dryrun(&matches),
    ));
}

fn is_dryrun(matches: &clap::ArgMatches) -> bool {
    matches.is_present("DRYRUN")
}

fn make_org_url(matches: &clap::ArgMatches) -> String {
    let org = matches
        .value_of("ORG")
        .expect("Please specify a github org");

    format!("https://api.github.com/orgs/{}/repos", org)
}

fn get_pr_links(repos: &Vec<github::GithubRepo>, token: &str, reqwest_client: &reqwest::Client, dryrun: bool) -> Vec<Option<String>> {
    let mut pr_links: Vec<Option<String>> = repos
        .into_iter()
        .map(|repo| match get_release_pr_for(&repo, &token, reqwest_client, dryrun) {
            Some(pr_url) => Some(pr_url),
            None => None,
        })
        .collect();
    // only keep the Some(PR_URL) items:
    pr_links.retain(|maybe_pr_link| maybe_pr_link.is_some());
    pr_links
}

fn get_reqwest_client() -> reqwest::Client {
    match reqwest::Client::new() {
        Ok(new_client) => new_client,
        Err(e) => panic!("Couldn't create new reqwest client: {}", e),
    }
}

fn get_repos_we_care_about(token: &str, github_org_url: &str, reqwest_client: &reqwest::Client) -> Vec<github::GithubRepo> {
    let mut repos = match github::get_repos_at(github_org_url, token, reqwest_client) {
        Ok(repos) => repos,
        Err(e) => panic!(format!("Couldn't get repos from github: {}", e)),
    };
    let repos_to_ignore = ignored_repos();

    // remove repos we don't care about:
    repos.retain(|repo| !repos_to_ignore.contains(&repo.name));

    repos
}

fn get_release_pr_for(repo: &github::GithubRepo, token: &str, client: &reqwest::Client, dryrun: bool) -> Option<String> {
    println!("looking for release PR for {}", repo.name);
    match github::existing_release_pr_location(repo, token, client) {
        Some(url) => Some(url),
        None => if !github::is_release_up_to_date_with_master(&repo.url, token, client) {
            if dryrun {
                Some(format!("Dry run: {} would get a release PR.", repo.url))
            } else {
                match github::create_release_pull_request(repo, token, client) {
                    Ok(pr_url) => Some(pr_url),
                    Err(_) => None,
                }
            }
        } else {
            None
        },
    }
}

fn print_party_links(pr_links: Vec<Option<String>>) {
    if !pr_links.is_empty() {
        println!("\nIt's a release party!  PRs to review and approve:");
        for link in pr_links {
            match link {
                Some(pr_link) => println!("{}", pr_link),
                None => println!("Party link is None: this shouldn't happen."),
            }
        }
    } else {
        println!("\nNo party today, all releases are done.");
    }
}

#[derive(Deserialize, Debug)]
struct IgnoredRepo {
    ignore: Option<Vec<String>>,
}

fn ignored_repos() -> Vec<String> {
    let mut f = match File::open("ignoredrepos.toml") {
        Ok(file) => file,
        Err(e) => {
            println!("Couldn't load ignoredrepos.toml, not ignoring any repos. Reason: {}", e);
            return Vec::new();
        }
    };
    let mut buffer = String::new();
    match f.read_to_string(&mut buffer) {
        Ok(_) => (),
        Err(e) => {
            println!("Couldn't read from ignoredrepos.toml, not ignoring any repos. Reason: {}", e);
            return Vec::new();
        }
    }

    let ignored: IgnoredRepo = match toml::from_str(&buffer) {
        Ok(ignored_repos) => ignored_repos,
        Err(e) => {
            println!(
                "Couldn't parse toml from ignoredrepos.toml, not ignoring any repos. Reason: {}",
                e
            );
            return Vec::new();
        }
    };
    match ignored.ignore {
        Some(repos_to_ignore) => repos_to_ignore,
        None => Vec::new(),
    }
}

fn get_github_token() -> String {
    match env::var(GITHUB_TOKEN) {
        Ok(gh_token) => gh_token,
        Err(e) => panic!(format!("Couldn't find {}: {}", GITHUB_TOKEN, e)),
    }
}
<commit_msg>Adding tests.<commit_after>#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]

#[macro_use]
extern crate clap;
extern crate reqwest;
#[macro_use]
extern crate serde_derive;
extern crate toml;

use std::env;
use std::io::prelude::*;
use std::fs::File;
use clap::App;

mod github;

static GITHUB_TOKEN: &'static str = "RP_GITHUBTOKEN";

fn main() {
    let yaml = load_yaml!("release-party.yml");
    let matches = App::from_yaml(yaml).get_matches();

    let org_url = make_org_url(&matches);
    let token = get_github_token();
    let reqwest_client = get_reqwest_client();

    print_party_links(get_pr_links(
        &get_repos_we_care_about(&token, &org_url, &reqwest_client),
        &token,
        &reqwest_client,
        is_dryrun(&matches),
    ));
}

fn is_dryrun(matches: &clap::ArgMatches) -> bool {
    matches.is_present("DRYRUN")
}

fn make_org_url(matches: &clap::ArgMatches) -> String {
    let org = matches
        .value_of("ORG")
        .expect("Please specify a github org");

    format!("https://api.github.com/orgs/{}/repos", org)
}

fn get_pr_links(repos: &Vec<github::GithubRepo>, token: &str, reqwest_client: &reqwest::Client, dryrun: bool) -> Vec<Option<String>> {
    let mut pr_links: Vec<Option<String>> = repos
        .into_iter()
        .map(|repo| match get_release_pr_for(&repo, &token, reqwest_client, dryrun) {
            Some(pr_url) => Some(pr_url),
            None => None,
        })
        .collect();
    // only keep the Some(PR_URL) items:
    pr_links.retain(|maybe_pr_link| maybe_pr_link.is_some());
    pr_links
}

fn get_reqwest_client() -> reqwest::Client {
    match reqwest::Client::new() {
        Ok(new_client) => new_client,
        Err(e) => panic!("Couldn't create new reqwest client: {}", e),
    }
}

fn get_repos_we_care_about(token: &str, github_org_url: &str, reqwest_client: &reqwest::Client) -> Vec<github::GithubRepo> {
    let mut repos = match github::get_repos_at(github_org_url, token, reqwest_client) {
        Ok(repos) => repos,
        Err(e) => panic!(format!("Couldn't get repos from github: {}", e)),
    };
    let repos_to_ignore = ignored_repos();

    // remove repos we don't care about:
    repos.retain(|repo| !repos_to_ignore.contains(&repo.name));

    repos
}

fn get_release_pr_for(repo: &github::GithubRepo, token: &str, client: &reqwest::Client, dryrun: bool) -> Option<String> {
    println!("looking for release PR for {}", repo.name);
    match github::existing_release_pr_location(repo, token, client) {
        Some(url) => Some(url),
        None => if !github::is_release_up_to_date_with_master(&repo.url, token, client) {
            if dryrun {
                Some(format!("Dry run: {} would get a release PR.", repo.url))
            } else {
                match github::create_release_pull_request(repo, token, client) {
                    Ok(pr_url) => Some(pr_url),
                    Err(_) => None,
                }
            }
        } else {
            None
        },
    }
}

fn print_party_links(pr_links: Vec<Option<String>>) {
    if !pr_links.is_empty() {
        println!("\nIt's a release party!  PRs to review and approve:");
        for link in pr_links {
            match link {
                Some(pr_link) => println!("{}", pr_link),
                None => println!("Party link is None: this shouldn't happen."),
            }
        }
    } else {
        println!("\nNo party today, all releases are done.");
    }
}

#[derive(Deserialize, Debug)]
struct IgnoredRepo {
    ignore: Option<Vec<String>>,
}

fn ignored_repos() -> Vec<String> {
    let mut f = match File::open("ignoredrepos.toml") {
        Ok(file) => file,
        Err(e) => {
            println!("Couldn't load ignoredrepos.toml, not ignoring any repos. Reason: {}", e);
            return Vec::new();
        }
    };
    let mut buffer = String::new();
    match f.read_to_string(&mut buffer) {
        Ok(_) => (),
        Err(e) => {
            println!("Couldn't read from ignoredrepos.toml, not ignoring any repos. Reason: {}", e);
            return Vec::new();
        }
    }

    let ignored: IgnoredRepo = match toml::from_str(&buffer) {
        Ok(ignored_repos) => ignored_repos,
        Err(e) => {
            println!(
                "Couldn't parse toml from ignoredrepos.toml, not ignoring any repos. Reason: {}",
                e
            );
            return Vec::new();
        }
    };
    match ignored.ignore {
        Some(repos_to_ignore) => repos_to_ignore,
        None => Vec::new(),
    }
}

fn get_github_token() -> String {
    match env::var(GITHUB_TOKEN) {
        Ok(gh_token) => gh_token,
        Err(e) => panic!(format!("Couldn't find {}: {}", GITHUB_TOKEN, e)),
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn token_from_env_happy_path() {
        env::set_var(GITHUB_TOKEN, "a token");
        assert_eq!("a token", get_github_token());
        env::remove_var(GITHUB_TOKEN);
    }

    #[test]
    #[should_panic]
    fn token_from_env_sad_path() {
        env::remove_var(GITHUB_TOKEN);
        get_github_token();
    }
}<|endoftext|>