<commit_before>extern crate byteorder;
extern crate regex;
extern crate flate2;
extern crate peekable_reader;
extern crate getopts;
extern crate tempdir;

use std::fs::File;
use std::io;
use std::io::{BufReader, BufWriter, Write};
use std::path::Path;
use std::env;
use std::process::exit;
use std::process::Command;
use std::error::Error;

use getopts::Options;

use tempdir::TempDir;

/** Create an InvalidData io::Error with the description being a
 * formatted string */
macro_rules! io_error {
    ($fmtstr:tt) => { io_error!($fmtstr,) };
    ($fmtstr:tt, $( $args:expr ),* ) => {
        Err(::std::io::Error::new(::std::io::ErrorKind::InvalidData,
                                  format!($fmtstr, $( $args ),* )));
    };
}

/** Alternative to println! that prints to stderr instead of stdout */
macro_rules! printerrln {
    ($fmtstr:tt) => { printerrln!($fmtstr,) };
    ($fmtstr:tt, $( $args:expr ),* ) => {
        writeln!(&mut io::stderr(), $fmtstr, $( $args ),* )
            .expect("Error writing to stderr")
    }
}

pub mod data;
mod write;
mod read;
mod string_write;
mod string_read;
#[cfg(test)]
mod tests;

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

    let mut opts = Options::new();
    opts.optflagopt("e", "edit", "edit a NBT file with your $EDITOR.
    If [FILE] is specified, then that file is edited in place, but specifying --input and/or --output will override the input/output.
    If no file is specified, default to read from --input and writing to --output.", "FILE");
    opts.optflagopt("p", "print", "print NBT file to text format. Adding an argument to this is the same as specifying --input", "FILE");
    opts.optflagopt("r", "reverse", "reverse a file in text format to NBT format. Adding an argument to this is the same as specifying --input", "FILE");
    opts.optopt("i",
                "input",
                "specify the input file, defaults to stdin",
                "FILE");
    opts.optopt("o",
                "output",
                "specify the output file, defaults to stdout",
                "FILE");
    opts.optflag("h", "help", "print the help menu");
    opts.optflag("", "version", "print program version");

    let matches = match opts.parse(&args[1..]) {
        Ok(x) => x,
        Err(e) => {
            error(&format!("Error parsing options: {:?}", e.description()))
        },
    };

    if matches.opt_present("h") {
        print_usage(opts);
        return;
    }

    if matches.opt_present("version") {
        println!("{} {} {}",
                 env!("CARGO_PKG_NAME"),
                 env!("CARGO_PKG_VERSION"),
                 /* See build.rs for the git-revision.txt file */
                 include!(concat!(env!("OUT_DIR"), "/git-revision.txt")));
        println!("{}", env!("CARGO_PKG_HOMEPAGE"));
        return;
    }

    /* Figure out the input file, by trying to read the arguments for all of
     * --input, --edit, --print and --reverse, prioritizing --input over the
     * other arguments, if none of the arguments are specified but there is a
     * free argument, use that, else we finally default to - (stdin) */
    let input = match matches.opt_str("input") {
        Some(x) => x,
        None => {
            match matches.opts_str(&["edit".to_string(),
                                     "print".to_string(),
                                     "reverse".to_string()]) {

                Some(x) => x,
                None if matches.free.len() > 0 => matches.free[0].clone(),
                None => "-".to_string(),
            }
        },
    };

    /* Analogous to the input */
    let output = match matches.opt_str("output") {
        Some(x) => x,
        None => {
            match matches.opt_str("edit") {
                Some(x) => x,
                None if matches.free.len() > 0 => matches.free[0].clone(),
                None => "-".to_string(),
            }
        },
    };

    if matches.opt_present("print") {
        print(&input, &output);
        return;
    }

    if matches.opt_present("reverse") {
        reverse(&input, &output);
        return;
    }

    /* Default to --edit */
    edit(&input, &output);
}

/** When the user wants to edit a specific file in place */
fn edit(input: &str, output: &str) {

    /* First we read the NBT data from the input */
    let nbt = if input == "-" {
        let mut f = io::stdin();
        match read::read_file(&mut f) {
            Ok(x) => x,
            Err(_) => {
                error(&format!("Unable to parse {}, are you sure it's an NBT file?",
                               input))
            },
        }
    } else {
        let path: &Path = Path::new(input);
        let f = match File::open(path) {
            Ok(f) => f,
            Err(_) => error(&format!("Unable to open file {}", input)),
        };
        let mut f = BufReader::new(f);

        match read::read_file(&mut f) {
            Ok(x) => x,
            Err(_) => {
                error(&format!("Unable to parse {}, are you sure it's an NBT file?",
                               input))
            },
        }
    };

    /* Then we create a temporary file and write the NBT data in text format
     * to the temporary file */
    let tmpdir = match TempDir::new("nbted") {
        Ok(x) => x,
        Err(e) => {
            error(&format!("Unable to create temporary directory: {:?}",
                           e.description()))
        },
    };

    let tmp_path = tmpdir.path().join(format!("{}.txt", &input));

    {
        let mut f = match File::create(&tmp_path) {
            Ok(x) => x,
            Err(e) => {
                error(&format!("Unable to create temporary file: {:?}",
                               e.description()))
            },
        };

        match string_write::write_file(&mut f, &nbt) {
            Ok(()) => (),
            Err(e) => {
                error(&format!("Unable to write temporary file: {:?}",
                               e.description()))
            },
        };

        match f.sync_all() {
            Ok(()) => (),
            Err(e) => {
                error(&format!("Unable to synchronize file: {:?}",
                               e.description()))
            },
        }
    }

    /* Then we open the user's $EDITOR on the temporary file */
    let editor = match env::var("EDITOR") {
        Ok(x) => x,
        Err(_) => {
            match env::var("VISUAL") {
                Ok(x) => x,
                Err(_) => error("Unable to find $EDITOR"),
            }
        },
    };

    let mut cmd = Command::new(editor);
    cmd.arg(&tmp_path.as_os_str());
    let mut cmd = match cmd.spawn() {
        Ok(x) => x,
        Err(e) => {
            error(&format!("Error opening editor: {:?}", e.description()))
        },
    };

    match cmd.wait() {
        Ok(x) if x.success() => (),
        Err(e) => {
            error(&format!("Error executing editor: {:?}", e.description()))
        },
        _ => error("Editor did not exit correctly"),
    }

    /* Then we parse the text format in the temporary file into NBT */
    let mut f = match File::open(&tmp_path) {
        Ok(x) => x,
        Err(e) => {
            error(&format!("Unable to read temporary file: {:?}.\n\
        Nothing was changed",
                           e.description()))
        },
    };

    let new_nbt = match string_read::read_file(&mut f) {
        Ok(x) => x,
        Err(e) => {
            error(&format!("Unable to parse edited file: {:?}.\n\
        Nothing was changed",
                           e.description()))
        },
    };

    if nbt == new_nbt {
        printerrln!("No changes, will do nothing.");
        return;
    }

    /* And finally we write the edited nbt (new_nbt) into the output file */
    if output == "-" {
        let mut f = io::stdout();
        write::write_file(&mut f, &new_nbt).expect("Error writing to stdout");
    } else {
        let path: &Path = Path::new(output);
        let f = match File::create(&path) {
            Ok(x) => x,
            Err(e) => {
                error(&format!("Unable to write to output NBT file {}: {:?}.\n\
            Nothing was changed",
                               output,
                               e.description()))
            },
        };
        let mut f = BufWriter::new(f);

        match write::write_file(&mut f, &new_nbt) {
            Ok(()) => (),
            Err(e) => {
                error(&format!("Error writing NBT file {}: {:?}.\n\
            State of NBT file is unknown, consider restoring it from a backup.",
                               output,
                               e.description()))
            },
        }
    }

    printerrln!("File edited successfully.");
}

/** When the user wants to print an NBT file to text format */
fn print(input: &str, output: &str) {
    /* First we read a NBTFile from the input */
    let nbt = if input == "-" {
        let mut f = io::stdin();
        match read::read_file(&mut f) {
            Ok(x) => x,
            Err(_) => {
                error(&format!("Unable to parse {}, are you sure it's an NBT file?",
                               input))
            },
        }
    } else {
        let path: &Path = Path::new(input);
        let f = match File::open(path) {
            Ok(f) => f,
            Err(_) => error(&format!("Unable to open file {}", input)),
        };
        let mut f = BufReader::new(f);

        match read::read_file(&mut f) {
            Ok(x) => x,
            Err(_) => {
                error(&format!("Unable to parse {}, are you sure it's an NBT file?",
                               input))
            },
        }
    };

    /* Then we write the NBTFile to the output in text format */
    if output == "-" {
        let mut f = io::stdout();
        string_write::write_file(&mut f, &nbt)
            .expect("Error writing to stdout");
    } else {
        let path: &Path = Path::new(output);
        let f = match File::create(&path) {
            Ok(x) => x,
            Err(e) => {
                error(&format!("Unable to write to output NBT file {}: {:?}.\n\
            Nothing was changed",
                               output,
                               e.description()))
            },
        };
        let mut f = BufWriter::new(f);

        match string_write::write_file(&mut f, &nbt) {
            Ok(()) => (),
            Err(e) => {
                error(&format!("Error writing NBT file {}: {:?}.\n\
            State of NBT file is unknown, consider restoring it from a backup.",
                               output,
                               e.description()))
            },
        }
    }
}

/** When the user wants to convert a text format file into an NBT file */
fn reverse(input: &str, output: &str) {
    /* First we read the input file in the text format */
    let path: &Path = Path::new(input);
    let mut f = match File::open(&path) {
        Ok(x) => x,
        Err(e) => {
            error(&format!("Unable to read text file {}: {:?}",
                           input,
                           e.description()))
        },
    };

    let nbt = match string_read::read_file(&mut f) {
        Ok(x) => x,
        Err(e) => {
            error(&format!("Unable to parse text file {}: {:?}",
                           input,
                           e.description()))
        },
    };

    /* Then we write the parsed NBT to the output file in NBT format */
    if output == "-" {
        let mut f = io::stdout();
        write::write_file(&mut f, &nbt).expect("Error writing to stdout");
    } else {
        let path: &Path = Path::new(output);
        let f = match File::create(&path) {
            Ok(x) => x,
            Err(e) => {
                error(&format!("Unable to write to output NBT file {}: {:?}.\n\
            Nothing was changed",
                               output,
                               e.description()))
            },
        };
        let mut f = BufWriter::new(f);

        match write::write_file(&mut f, &nbt) {
            Ok(()) => (),
            Err(e) => {
                error(&format!("Error writing NBT file {}: {:?}.\n\
            State of NBT file is unknown, consider restoring it from a backup.",
                               output,
                               e.description()))
            },
        }
    }
}

/** Print the given message and exit with status code 1 */
fn error(message: &str) -> ! {
    printerrln!("Error: {}", message);
    printerrln!("Run with --help for help, or read the manpage.");
    exit(1);
}

fn print_usage(opts: Options) {
    let brief = "Usage: nbted [options] FILE";
    print!("{}", opts.usage(&brief));
    println!("\nFor detailed usage information, read the manpage.");
}
<commit_msg>Allow users to attempt reediting files with syntax errors<commit_after>extern crate byteorder;
extern crate regex;
extern crate flate2;
extern crate peekable_reader;
extern crate getopts;
extern crate tempdir;

use std::fs::File;
use std::io;
use std::io::{BufReader, BufWriter, Write};
use std::path::Path;
use std::env;
use std::process::exit;
use std::process::Command;
use std::error::Error;

use getopts::Options;

use tempdir::TempDir;

/** Create an InvalidData io::Error with the description being a
 * formatted string */
macro_rules! io_error {
    ($fmtstr:tt) => { io_error!($fmtstr,) };
    ($fmtstr:tt, $( $args:expr ),* ) => {
        Err(::std::io::Error::new(::std::io::ErrorKind::InvalidData,
                                  format!($fmtstr, $( $args ),* )));
    };
}

/** Alternative to println! that prints to stderr instead of stdout */
macro_rules! printerrln {
    ($fmtstr:tt) => { printerrln!($fmtstr,) };
    ($fmtstr:tt, $( $args:expr ),* ) => {
        writeln!(&mut io::stderr(), $fmtstr, $( $args ),* )
            .expect("Error writing to stderr")
    }
}

pub mod data;
mod write;
mod read;
mod string_write;
mod string_read;
#[cfg(test)]
mod tests;

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

    let mut opts = Options::new();
    opts.optflagopt("e", "edit", "edit a NBT file with your $EDITOR.
    If [FILE] is specified, then that file is edited in place, but specifying --input and/or --output will override the input/output.
    If no file is specified, default to read from --input and writing to --output.", "FILE");
    opts.optflagopt("p", "print", "print NBT file to text format. Adding an argument to this is the same as specifying --input", "FILE");
    opts.optflagopt("r", "reverse", "reverse a file in text format to NBT format. Adding an argument to this is the same as specifying --input", "FILE");
    opts.optopt("i",
                "input",
                "specify the input file, defaults to stdin",
                "FILE");
    opts.optopt("o",
                "output",
                "specify the output file, defaults to stdout",
                "FILE");
    opts.optflag("h", "help", "print the help menu");
    opts.optflag("", "version", "print program version");

    let matches = match opts.parse(&args[1..]) {
        Ok(x) => x,
        Err(e) => {
            error(&format!("Error parsing options: {:?}", e.description()))
        },
    };

    if matches.opt_present("h") {
        print_usage(opts);
        return;
    }

    if matches.opt_present("version") {
        println!("{} {} {}",
                 env!("CARGO_PKG_NAME"),
                 env!("CARGO_PKG_VERSION"),
                 /* See build.rs for the git-revision.txt file */
                 include!(concat!(env!("OUT_DIR"), "/git-revision.txt")));
        println!("{}", env!("CARGO_PKG_HOMEPAGE"));
        return;
    }

    /* Figure out the input file, by trying to read the arguments for all of
     * --input, --edit, --print and --reverse, prioritizing --input over the
     * other arguments, if none of the arguments are specified but there is a
     * free argument, use that, else we finally default to - (stdin) */
    let input = match matches.opt_str("input") {
        Some(x) => x,
        None => {
            match matches.opts_str(&["edit".to_string(),
                                     "print".to_string(),
                                     "reverse".to_string()]) {

                Some(x) => x,
                None if matches.free.len() > 0 => matches.free[0].clone(),
                None => "-".to_string(),
            }
        },
    };

    /* Analogous to the input */
    let output = match matches.opt_str("output") {
        Some(x) => x,
        None => {
            match matches.opt_str("edit") {
                Some(x) => x,
                None if matches.free.len() > 0 => matches.free[0].clone(),
                None => "-".to_string(),
            }
        },
    };

    if matches.opt_present("print") {
        print(&input, &output);
        return;
    }

    if matches.opt_present("reverse") {
        reverse(&input, &output);
        return;
    }

    /* Default to --edit */
    edit(&input, &output);
}

/** When the user wants to edit a specific file in place */
fn edit(input: &str, output: &str) {

    /* First we read the NBT data from the input */
    let nbt = if input == "-" {
        let mut f = io::stdin();
        match read::read_file(&mut f) {
            Ok(x) => x,
            Err(_) => {
                error(&format!("Unable to parse {}, are you sure it's an NBT file?",
                               input))
            },
        }
    } else {
        let path: &Path = Path::new(input);
        let f = match File::open(path) {
            Ok(f) => f,
            Err(_) => error(&format!("Unable to open file {}", input)),
        };
        let mut f = BufReader::new(f);

        match read::read_file(&mut f) {
            Ok(x) => x,
            Err(_) => {
                error(&format!("Unable to parse {}, are you sure it's an NBT file?",
                               input))
            },
        }
    };

    /* Then we create a temporary file and write the NBT data in text format
     * to the temporary file */
    let tmpdir = match TempDir::new("nbted") {
        Ok(x) => x,
        Err(e) => {
            error(&format!("Unable to create temporary directory: {:?}",
                           e.description()))
        },
    };

    let tmp_path = tmpdir.path().join(format!("{}.txt", &input));

    {
        let mut f = match File::create(&tmp_path) {
            Ok(x) => x,
            Err(e) => {
                error(&format!("Unable to create temporary file: {:?}",
                               e.description()))
            },
        };

        match string_write::write_file(&mut f, &nbt) {
            Ok(()) => (),
            Err(e) => {
                error(&format!("Unable to write temporary file: {:?}",
                               e.description()))
            },
        };

        match f.sync_all() {
            Ok(()) => (),
            Err(e) => {
                error(&format!("Unable to synchronize file: {:?}",
                               e.description()))
            },
        }
    }

    let new_nbt = {
        let mut new_nbt = open_editor(&tmp_path);

        while let Err(e) = new_nbt {
            printerrln!("Unable to parse edited file: {}.\n\
            Do you want to open the file for editing again? (y/N)",
                        e.description());

            let mut line = String::new();
            match io::stdin().read_line(&mut line) {
                Ok(_) => (),
                Err(e) => {
                    error(&format!("Error reading from stdin: {}\n\
                                   Nothing was changed.",
                                   e.description()))
                },
            }

            if line.trim() == "y" {
                new_nbt = open_editor(&tmp_path);
            } else {
                printerrln!("Exiting ... File is unchanged.");
                std::process::exit(1);
            }
        }

        new_nbt.expect("new_nbt was Error")
    };

    if nbt == new_nbt {
        printerrln!("No changes, will do nothing.");
        return;
    }

    /* And finally we write the edited nbt (new_nbt) into the output file */
    if output == "-" {
        let mut f = io::stdout();
        write::write_file(&mut f, &new_nbt).expect("Error writing to stdout");
    } else {
        let path: &Path = Path::new(output);
        let f = match File::create(&path) {
            Ok(x) => x,
            Err(e) => {
                error(&format!("Unable to write to output NBT file {}: {:?}.\n\
            Nothing was changed",
                               output,
                               e.description()))
            },
        };
        let mut f = BufWriter::new(f);

        match write::write_file(&mut f, &new_nbt) {
            Ok(()) => (),
            Err(e) => {
                error(&format!("Error writing NBT file {}: {:?}.\n\
            State of NBT file is unknown, consider restoring it from a backup.",
                               output,
                               e.description()))
            },
        }
    }

    printerrln!("File edited successfully.");
}

/// Open the user's $EDITOR on the temporary file, wait until the editor is
/// closed again, read the temporary file and attempt to parse it into NBT,
/// returning the result.
fn open_editor(tmp_path: &Path) -> io::Result<data::NBTFile> {
    let editor = match env::var("EDITOR") {
        Ok(x) => x,
        Err(_) => {
            match env::var("VISUAL") {
                Ok(x) => x,
                Err(_) => error("Unable to find $EDITOR"),
            }
        },
    };

    let mut cmd = Command::new(editor);
    cmd.arg(&tmp_path.as_os_str());
    let mut cmd = match cmd.spawn() {
        Ok(x) => x,
        Err(e) => {
            error(&format!("Error opening editor: {:?}", e.description()))
        },
    };

    match cmd.wait() {
        Ok(x) if x.success() => (),
        Err(e) => {
            error(&format!("Error executing editor: {:?}", e.description()))
        },
        _ => error("Editor did not exit correctly"),
    }

    /* Then we parse the text format in the temporary file into NBT */
    let mut f = match File::open(&tmp_path) {
        Ok(x) => x,
        Err(e) => {
            error(&format!("Unable to read temporary file: {:?}.\n\
        Nothing was changed",
                           e.description()))
        },
    };

    string_read::read_file(&mut f)
}

/** When the user wants to print an NBT file to text format */
fn print(input: &str, output: &str) {
    /* First we read a NBTFile from the input */
    let nbt = if input == "-" {
        let mut f = io::stdin();
        match read::read_file(&mut f) {
            Ok(x) => x,
            Err(_) => {
                error(&format!("Unable to parse {}, are you sure it's an NBT file?",
                               input))
            },
        }
    } else {
        let path: &Path = Path::new(input);
        let f = match File::open(path) {
            Ok(f) => f,
            Err(_) => error(&format!("Unable to open file {}", input)),
        };
        let mut f = BufReader::new(f);

        match read::read_file(&mut f) {
            Ok(x) => x,
            Err(_) => {
                error(&format!("Unable to parse {}, are you sure it's an NBT file?",
                               input))
            },
        }
    };

    /* Then we write the NBTFile to the output in text format */
    if output == "-" {
        let mut f = io::stdout();
        string_write::write_file(&mut f, &nbt)
            .expect("Error writing to stdout");
    } else {
        let path: &Path = Path::new(output);
        let f = match File::create(&path) {
            Ok(x) => x,
            Err(e) => {
                error(&format!("Unable to write to output NBT file {}: {:?}.\n\
            Nothing was changed",
                               output,
                               e.description()))
            },
        };
        let mut f = BufWriter::new(f);

        match string_write::write_file(&mut f, &nbt) {
            Ok(()) => (),
            Err(e) => {
                error(&format!("Error writing NBT file {}: {:?}.\n\
            State of NBT file is unknown, consider restoring it from a backup.",
                               output,
                               e.description()))
            },
        }
    }
}

/** When the user wants to convert a text format file into an NBT file */
fn reverse(input: &str, output: &str) {
    /* First we read the input file in the text format */
    let path: &Path = Path::new(input);
    let mut f = match File::open(&path) {
        Ok(x) => x,
        Err(e) => {
            error(&format!("Unable to read text file {}: {:?}",
                           input,
                           e.description()))
        },
    };

    let nbt = match string_read::read_file(&mut f) {
        Ok(x) => x,
        Err(e) => {
            error(&format!("Unable to parse text file {}: {:?}",
                           input,
                           e.description()))
        },
    };

    /* Then we write the parsed NBT to the output file in NBT format */
    if output == "-" {
        let mut f = io::stdout();
        write::write_file(&mut f, &nbt).expect("Error writing to stdout");
    } else {
        let path: &Path = Path::new(output);
        let f = match File::create(&path) {
            Ok(x) => x,
            Err(e) => {
                error(&format!("Unable to write to output NBT file {}: {:?}.\n\
            Nothing was changed",
                               output,
                               e.description()))
            },
        };
        let mut f = BufWriter::new(f);

        match write::write_file(&mut f, &nbt) {
            Ok(()) => (),
            Err(e) => {
                error(&format!("Error writing NBT file {}: {:?}.\n\
            State of NBT file is unknown, consider restoring it from a backup.",
                               output,
                               e.description()))
            },
        }
    }
}

/** Print the given message and exit with status code 1 */
fn error(message: &str) -> ! {
    printerrln!("Error: {}", message);
    printerrln!("Run with --help for help, or read the manpage.");
    exit(1);
}

fn print_usage(opts: Options) {
    let brief = "Usage: nbted [options] FILE";
    print!("{}", opts.usage(&brief));
    println!("\nFor detailed usage information, read the manpage.");
}
<|endoftext|>


<commit_before>use std::cmp;
use std::mem;
use std::f64;

extern crate time;

type StreamType = f64;

const HLINE: &'static str = "-------------------------------------------------------------\n";
const STREAM_ARRAY_SIZE: usize = 10000000;
const NTIMES: usize = 10;
const M: usize = 10;

static mut A: [StreamType; STREAM_ARRAY_SIZE] = [0.0; STREAM_ARRAY_SIZE];
static mut B: [StreamType; STREAM_ARRAY_SIZE] = [0.0; STREAM_ARRAY_SIZE];
static mut C: [StreamType; STREAM_ARRAY_SIZE] = [0.0; STREAM_ARRAY_SIZE];

fn main() {
    /* --- SETUP --- determine precision and check timing --- */
    println!("{}", HLINE);
    println!("STREAM version $Revision: 5.10 $");
    println!("{}", HLINE);
    let bytes_per_word = mem::size_of::<StreamType>();
    println!("This system uses {} bytes per array element.", bytes_per_word);

    println!("{}", HLINE);

    println!("Array size = {} (elements)", STREAM_ARRAY_SIZE);
    println!("Memory per array = {:.1} MiB (= {:.1} GiB).",
             bytes_per_word as f64 * (STREAM_ARRAY_SIZE as f64 / 1024.0 / 1024.0),
             bytes_per_word as f64 * (STREAM_ARRAY_SIZE as f64 / 1024.0 / 1024.0 / 1024.0));
    println!("Total memory required = {:.1} MiB (= {:.1} GiB).",
            (3.0 * bytes_per_word as f64) * (STREAM_ARRAY_SIZE as f64 / 1024.0 / 1024.0),
            (3.0 * bytes_per_word as f64) * (STREAM_ARRAY_SIZE as f64 / 1024.0/1024./1024.0));
    println!("Each kernel will be executed {} times.", NTIMES);
    println!(" The *best* time for each kernel (excluding the first iteration)");
    println!(" will be used to compute the reported bandwidth.");

	println!("{}", HLINE);

    unsafe {
        for i in 0..STREAM_ARRAY_SIZE {
            A[i] = 1.0;
            B[i] = 2.0;
            C[i] = 0.0;
        }
    }

    let mut quantum = check_tick();
    if  quantum >= 1 {
        println!("Your clock granularity/precision appears to be {} microseconds.", quantum);
    } else {
	    println!("Your clock granularity appears to be less than one microsecond.");
	    quantum = 1;
    }

    let mut t = time::precise_time_s();
    unsafe {
        for i in 0..STREAM_ARRAY_SIZE {
            A[i] = 2.0 * A[i];
        }
    }
    t = 1.0E6 * (time::precise_time_s() - t);

    println!("Each test below will take on the order of {} microseconds.", t as i32);
    println!("   (= {} clock ticks)", (t / quantum as f64) as i32);
    println!("Increase the size of the arrays if this shows that");
    println!("you are not getting at least 20 clock ticks per test.");

    println!("{}", HLINE);

    println!("WARNING -- The above is only a rough guideline.");
    println!("For best results, please be sure you know the");
    println!("precision of your system timer.");
    println!("{}", HLINE);

    let mut times: [[f64; NTIMES]; 4] = [[0.0; NTIMES]; 4];

    /*	--- MAIN LOOP --- repeat test cases NTIMES times --- */

    let scalar:StreamType = 3.0;
    for k in 0..NTIMES {
        times[0][k] = time::precise_time_s();
        unsafe {
            for j in 0..STREAM_ARRAY_SIZE {
                C[j] = A[j];
            }
        }
        times[0][k] = time::precise_time_s() - times[0][k];

        times[1][k] = time::precise_time_s();
        unsafe {
            for j in 0..STREAM_ARRAY_SIZE {
                B[j] = scalar * C[j];
            }
        }
        times[1][k] = time::precise_time_s() - times[1][k];

        times[2][k] = time::precise_time_s();
        unsafe {
            for j in 0..STREAM_ARRAY_SIZE {
                C[j] = A[j] + B[j];
            }
        }
        times[2][k] = time::precise_time_s() - times[2][k];

        times[3][k] = time::precise_time_s();
        unsafe {
            for j in 0..STREAM_ARRAY_SIZE {
                A[j] = B[j] + scalar * C[j];
            }
        }
        times[3][k] = time::precise_time_s() - times[3][k];
    }

    let mut avg_time: [f64; 4] = [0.0; 4];
    let mut max_time: [f64; 4] = [0.0; 4];
    let mut min_time: [f64; 4] = [f64::MAX, f64::MAX, f64::MAX, f64::MAX];

    let label: [&'static str; 4] = ["Copy:      ", "Scale:     ",  "Add:       ", "Triad:     "];
    let bytes: [usize; 4] = [
        2 * bytes_per_word * STREAM_ARRAY_SIZE ,
        2 * bytes_per_word * STREAM_ARRAY_SIZE ,
        3 * bytes_per_word * STREAM_ARRAY_SIZE ,
        3 * bytes_per_word * STREAM_ARRAY_SIZE
    ];

    /*	--- SUMMARY --- */

    for k in 1..NTIMES /* note -- skip first iteration */
    {
        for j in 0..4
        {
            avg_time[j] = avg_time[j] + times[j][k];
            if min_time[j] > times[j][k] {
                min_time[j] = times[j][k];
            }
            if max_time[j] < times[j][k] {
                max_time[j] = times[j][k];
            }
        }
    }

    println!("Function    Best Rate MB/s  Avg time     Min time     Max time");
    for j in 0..4 {
        avg_time[j] = avg_time[j] / (NTIMES-1) as f64;

        println!("{}{:12.1}  {:11.6}  {:11.6}  {:11.6}", label[j],
            1.0E-06 * bytes[j] as f64 / min_time[j],
            avg_time[j],
            min_time[j],
            max_time[j]);
    }
    println!("{}", HLINE);

    check_stream_results();
    println!("{}", HLINE);
}

fn check_tick() -> i32 {
    let mut times_found: [f64; M] = [0.0; M];

    for i in 0..M {
        let t1 = time::precise_time_s();

        loop {
            let t2 = time::precise_time_s();
            if (t2 - t1) >= 1.0E-6 {
                times_found[i] = t2;
                break;
            }
        }
    }

    let mut min_delta = 1000000;
    for i in 1..M {
        let delta = (1.0E6 * (times_found[i] - times_found[i-1])) as i32;
        min_delta = cmp::min(min_delta, cmp::max(delta, 0));
    }

    min_delta

}

fn check_stream_results() {
    /* reproduce initialization */
    let mut aj: StreamType = 1.0;
    let mut bj: StreamType = 2.0;
    let mut cj: StreamType = 0.0;
    /* a[] is modified during timing check */
    aj = 2.0E0 * aj;
    /* now execute timing loop */
    let scalar: StreamType = 3.0;
    for _ in 0..NTIMES {
        cj = aj;
        bj = scalar * cj;
        cj = aj + bj;
        aj = bj + scalar * cj;
    }

    /* accumulate deltas between observed and expected results */
    let mut a_sum_err: StreamType = 0.0;
    let mut b_sum_err: StreamType = 0.0;
    let mut c_sum_err: StreamType = 0.0;
    for j in 0..STREAM_ARRAY_SIZE {
        unsafe {
            a_sum_err += (A[j] - aj).abs();
            b_sum_err += (B[j] - bj).abs();
            c_sum_err += (C[j] - cj).abs();
        }
    }
    let a_avg_err = a_sum_err / STREAM_ARRAY_SIZE as f64;
    let b_avg_err = b_sum_err / STREAM_ARRAY_SIZE as f64;
    let c_avg_err = c_sum_err / STREAM_ARRAY_SIZE as f64;

    let epsilon = 1.0E-13;

    let mut err = 0;
    let mut ierr = 0;

    if (a_avg_err / aj).abs() > epsilon {
        err = err + 1;
        println!("Failed Validation on array a[], AvgRelAbsErr > epsilon ({})", epsilon);
        println!("     Expected Value: {}, AvgAbsErr: {}, AvgRelAbsErr: {}",aj, a_avg_err, a_avg_err.abs()/aj);
        for j in 0..STREAM_ARRAY_SIZE {
            unsafe {
                if (A[j] / aj - 1.0).abs() > epsilon {
                    ierr = ierr + 1;
                }
            }
        }
        println!("     For array a[], {} errors were found.", ierr);
    }

    if (b_avg_err / bj).abs() > epsilon {
        err = err + 1;
        println!("Failed Validation on array b[], AvgRelAbsErr > epsilon ({})", epsilon);
        println! ("     Expected Value: {}, AvgAbsErr: {}, AvgRelAbsErr: {}",bj, b_avg_err, b_avg_err.abs()/bj);
        println! ("     AvgRelAbsErr > Epsilon {}", epsilon);
        ierr = 0;
        for j in 0..STREAM_ARRAY_SIZE {
            unsafe {
                if (B[j]/ bj - 1.0).abs() > epsilon {
                    ierr = ierr + 1;
                }
            }
        }
        println!("     For array b[], {} errors were found.", ierr);
    }

    if (c_avg_err / cj).abs() > epsilon {
        err = err + 1;
        println! ("Failed Validation on array c[], AvgRelAbsErr > epsilon ({})", epsilon);
        println! ("     Expected Value: {}, AvgAbsErr: {}, AvgRelAbsErr: {}",cj, c_avg_err, c_avg_err.abs() / cj);
        println! ("     AvgRelAbsErr > Epsilon ({})",epsilon);
        ierr = 0;
        for j in 0..STREAM_ARRAY_SIZE {
            unsafe {
                if (C[j] / cj - 1.0).abs() > epsilon {
                    ierr = ierr + 1;
                }
            }
        }
        println!("     For array c[], {} errors were found.", ierr);
    }

    if err == 0 {
        println! ("Solution Validates: avg error less than {:e} on all three arrays", epsilon);
    }

}

<commit_msg>Adjust main.rs.<commit_after>extern crate time;

use std::cmp;
use std::mem;
use std::f64;

type StreamType = f64;

const HLINE: &'static str = "-------------------------------------------------------------\n";
const STREAM_ARRAY_SIZE: usize = 10000000;
const NTIMES: usize = 10;
const M: usize = 10;

static mut A: [StreamType; STREAM_ARRAY_SIZE] = [0.0; STREAM_ARRAY_SIZE];
static mut B: [StreamType; STREAM_ARRAY_SIZE] = [0.0; STREAM_ARRAY_SIZE];
static mut C: [StreamType; STREAM_ARRAY_SIZE] = [0.0; STREAM_ARRAY_SIZE];

fn main() {
    /* --- SETUP --- determine precision and check timing --- */
    println!("{}", HLINE);
    println!("STREAM version $Revision: 5.10 $");
    println!("{}", HLINE);
    let bytes_per_word = mem::size_of::<StreamType>();
    println!("This system uses {} bytes per array element.", bytes_per_word);

    println!("{}", HLINE);

    println!("Array size = {} (elements)", STREAM_ARRAY_SIZE);
    println!("Memory per array = {:.1} MiB (= {:.1} GiB).",
             bytes_per_word as f64 * (STREAM_ARRAY_SIZE as f64 / 1024.0 / 1024.0),
             bytes_per_word as f64 * (STREAM_ARRAY_SIZE as f64 / 1024.0 / 1024.0 / 1024.0));
    println!("Total memory required = {:.1} MiB (= {:.1} GiB).",
            (3.0 * bytes_per_word as f64) * (STREAM_ARRAY_SIZE as f64 / 1024.0 / 1024.0),
            (3.0 * bytes_per_word as f64) * (STREAM_ARRAY_SIZE as f64 / 1024.0/1024./1024.0));
    println!("Each kernel will be executed {} times.", NTIMES);
    println!(" The *best* time for each kernel (excluding the first iteration)");
    println!(" will be used to compute the reported bandwidth.");

	println!("{}", HLINE);

    unsafe {
        for i in 0..STREAM_ARRAY_SIZE {
            A[i] = 1.0;
            B[i] = 2.0;
            C[i] = 0.0;
        }
    }

    let mut quantum = check_tick();
    if  quantum >= 1 {
        println!("Your clock granularity/precision appears to be {} microseconds.", quantum);
    } else {
	    println!("Your clock granularity appears to be less than one microsecond.");
	    quantum = 1;
    }

    let mut t = time::precise_time_s();
    unsafe {
        for i in 0..STREAM_ARRAY_SIZE {
            A[i] = 2.0 * A[i];
        }
    }
    t = 1.0E6 * (time::precise_time_s() - t);

    println!("Each test below will take on the order of {} microseconds.", t as i32);
    println!("   (= {} clock ticks)", (t / quantum as f64) as i32);
    println!("Increase the size of the arrays if this shows that");
    println!("you are not getting at least 20 clock ticks per test.");

    println!("{}", HLINE);

    println!("WARNING -- The above is only a rough guideline.");
    println!("For best results, please be sure you know the");
    println!("precision of your system timer.");
    println!("{}", HLINE);

    let mut times: [[f64; NTIMES]; 4] = [[0.0; NTIMES]; 4];

    /*	--- MAIN LOOP --- repeat test cases NTIMES times --- */

    let scalar:StreamType = 3.0;
    for k in 0..NTIMES {
        times[0][k] = time::precise_time_s();
        unsafe {
            for j in 0..STREAM_ARRAY_SIZE {
                C[j] = A[j];
            }
        }
        times[0][k] = time::precise_time_s() - times[0][k];

        times[1][k] = time::precise_time_s();
        unsafe {
            for j in 0..STREAM_ARRAY_SIZE {
                B[j] = scalar * C[j];
            }
        }
        times[1][k] = time::precise_time_s() - times[1][k];

        times[2][k] = time::precise_time_s();
        unsafe {
            for j in 0..STREAM_ARRAY_SIZE {
                C[j] = A[j] + B[j];
            }
        }
        times[2][k] = time::precise_time_s() - times[2][k];

        times[3][k] = time::precise_time_s();
        unsafe {
            for j in 0..STREAM_ARRAY_SIZE {
                A[j] = B[j] + scalar * C[j];
            }
        }
        times[3][k] = time::precise_time_s() - times[3][k];
    }

    let mut avg_time: [f64; 4] = [0.0; 4];
    let mut max_time: [f64; 4] = [0.0; 4];
    let mut min_time: [f64; 4] = [f64::MAX, f64::MAX, f64::MAX, f64::MAX];

    let label: [&'static str; 4] = ["Copy:      ", "Scale:     ",  "Add:       ", "Triad:     "];
    let bytes: [usize; 4] = [
        2 * bytes_per_word * STREAM_ARRAY_SIZE ,
        2 * bytes_per_word * STREAM_ARRAY_SIZE ,
        3 * bytes_per_word * STREAM_ARRAY_SIZE ,
        3 * bytes_per_word * STREAM_ARRAY_SIZE
    ];

    /*	--- SUMMARY --- */

    for k in 1..NTIMES /* note -- skip first iteration */
    {
        for j in 0..4
        {
            avg_time[j] = avg_time[j] + times[j][k];
            if min_time[j] > times[j][k] {
                min_time[j] = times[j][k];
            }
            if max_time[j] < times[j][k] {
                max_time[j] = times[j][k];
            }
        }
    }

    println!("Function    Best Rate MB/s  Avg time     Min time     Max time");
    for j in 0..4 {
        avg_time[j] = avg_time[j] / (NTIMES-1) as f64;

        println!("{}{:12.1}  {:11.6}  {:11.6}  {:11.6}", label[j],
            1.0E-06 * bytes[j] as f64 / min_time[j],
            avg_time[j],
            min_time[j],
            max_time[j]);
    }
    println!("{}", HLINE);

    check_stream_results();
    println!("{}", HLINE);
}

fn check_tick() -> i32 {
    let mut times_found: [f64; M] = [0.0; M];

    for i in 0..M {
        let t1 = time::precise_time_s();

        loop {
            let t2 = time::precise_time_s();
            if (t2 - t1) >= 1.0E-6 {
                times_found[i] = t2;
                break;
            }
        }
    }

    let mut min_delta = 1000000;
    for i in 1..M {
        let delta = (1.0E6 * (times_found[i] - times_found[i-1])) as i32;
        min_delta = cmp::min(min_delta, cmp::max(delta, 0));
    }

    min_delta

}

fn check_stream_results() {
    /* reproduce initialization */
    let mut aj: StreamType = 1.0;
    let mut bj: StreamType = 2.0;
    let mut cj: StreamType = 0.0;
    /* a[] is modified during timing check */
    aj = 2.0E0 * aj;
    /* now execute timing loop */
    let scalar: StreamType = 3.0;
    for _ in 0..NTIMES {
        cj = aj;
        bj = scalar * cj;
        cj = aj + bj;
        aj = bj + scalar * cj;
    }

    /* accumulate deltas between observed and expected results */
    let mut a_sum_err: StreamType = 0.0;
    let mut b_sum_err: StreamType = 0.0;
    let mut c_sum_err: StreamType = 0.0;
    for j in 0..STREAM_ARRAY_SIZE {
        unsafe {
            a_sum_err += (A[j] - aj).abs();
            b_sum_err += (B[j] - bj).abs();
            c_sum_err += (C[j] - cj).abs();
        }
    }
    let a_avg_err = a_sum_err / STREAM_ARRAY_SIZE as f64;
    let b_avg_err = b_sum_err / STREAM_ARRAY_SIZE as f64;
    let c_avg_err = c_sum_err / STREAM_ARRAY_SIZE as f64;

    let epsilon = 1.0E-13;

    let mut err = 0;
    let mut ierr = 0;

    if (a_avg_err / aj).abs() > epsilon {
        err = err + 1;
        println!("Failed Validation on array a[], AvgRelAbsErr > epsilon ({})", epsilon);
        println!("     Expected Value: {}, AvgAbsErr: {}, AvgRelAbsErr: {}",aj, a_avg_err, a_avg_err.abs()/aj);
        for j in 0..STREAM_ARRAY_SIZE {
            unsafe {
                if (A[j] / aj - 1.0).abs() > epsilon {
                    ierr = ierr + 1;
                }
            }
        }
        println!("     For array a[], {} errors were found.", ierr);
    }

    if (b_avg_err / bj).abs() > epsilon {
        err = err + 1;
        println!("Failed Validation on array b[], AvgRelAbsErr > epsilon ({})", epsilon);
        println! ("     Expected Value: {}, AvgAbsErr: {}, AvgRelAbsErr: {}",bj, b_avg_err, b_avg_err.abs()/bj);
        println! ("     AvgRelAbsErr > Epsilon {}", epsilon);
        ierr = 0;
        for j in 0..STREAM_ARRAY_SIZE {
            unsafe {
                if (B[j]/ bj - 1.0).abs() > epsilon {
                    ierr = ierr + 1;
                }
            }
        }
        println!("     For array b[], {} errors were found.", ierr);
    }

    if (c_avg_err / cj).abs() > epsilon {
        err = err + 1;
        println! ("Failed Validation on array c[], AvgRelAbsErr > epsilon ({})", epsilon);
        println! ("     Expected Value: {}, AvgAbsErr: {}, AvgRelAbsErr: {}",cj, c_avg_err, c_avg_err.abs() / cj);
        println! ("     AvgRelAbsErr > Epsilon ({})",epsilon);
        ierr = 0;
        for j in 0..STREAM_ARRAY_SIZE {
            unsafe {
                if (C[j] / cj - 1.0).abs() > epsilon {
                    ierr = ierr + 1;
                }
            }
        }
        println!("     For array c[], {} errors were found.", ierr);
    }

    if err == 0 {
        println! ("Solution Validates: avg error less than {:e} on all three arrays", epsilon);
    }

}

<|endoftext|>


<commit_before>extern crate graphics;
extern crate piston;
extern crate glfw_game_window;
extern crate opengl_graphics;

use glfw_game_window::GameWindowGLFW;
use piston::{
    Game,
    GameIteratorSettings,
    GameWindowSettings,
};

use game::{
    App,
    CELL_SIZE,
    CELL_WIDTH,
    CELL_HEIGHT
};

mod game;
mod block;

fn main() {
    // Create a GLFW window.
    let mut window = GameWindowGLFW::new(
        GameWindowSettings {
            title: "My Game".to_string(),
            size: [game::CELL_SIZE * game::CELL_WIDTH, game::CELL_SIZE * game::CELL_HEIGHT],
            fullscreen: false,
            exit_on_esc: true
        }
    );

    // Some settings for how the game should be run.
    let game_iter_settings = GameIteratorSettings {
        updates_per_second: 60,
        max_frames_per_second: 60
    };

    // Create a new game and run it.
    let game: &mut Game<GameWindowGLFW> = &mut App::new();
    game.run(&mut window, &game_iter_settings);
}
<commit_msg>main.rs<commit_after>extern crate graphics;
extern crate piston;
extern crate glfw_game_window;
extern crate opengl_graphics;

use glfw_game_window::GameWindowGLFW;
use piston::{
    Game,
    GameIteratorSettings,
    GameWindowSettings,
};

use game::{
    App,
    CELL_SIZE,
    CELL_WIDTH,
    CELL_HEIGHT
};

mod game;
mod block;

fn main() {
    // Create a GLFW window.
    let mut window = GameWindowGLFW::new(
        GameWindowSettings {
            title: "My Game".to_string(),
            size: [game::CELL_SIZE * game::CELL_WIDTH,
                   game::CELL_SIZE * game::CELL_HEIGHT],
            fullscreen: false,
            exit_on_esc: true
        }
    );

    // Some settings for how the game should be run.
    let game_iter_settings = GameIteratorSettings {
        updates_per_second: 60,
        max_frames_per_second: 60
    };

    // Create a new game and run it.
    let game: &mut Game<GameWindowGLFW> = &mut App::new();
    game.run(&mut window, &game_iter_settings);
}
<|endoftext|>


<commit_before>extern crate lp_modeler;

use lp_modeler::variables::*;
use lp_modeler::problem::*;

fn main() {

    let b = LpVariable::new("toto", LpType::Binary);
    //let c = ContinuousVariable::new("t");
    //let c1 = ContinuousVariable::new("t");

    //let prob = LpProblem::new("p1", Objective::Maximize);

//    let l1 = LpVariable::new("l1".to_string(), Category::Binary);
    println!("{:?}", b);

    //println!("{:?}", b + c);
}
<commit_msg>New data structures<commit_after>extern crate lp_modeler;

use lp_modeler::variables::*;
use lp_modeler::problem::*;

fn main() {

    let b = LpVariable::new("toto", LpType::Binary);
    //let c = ContinuousVariable::new("t");
    //let c1 = ContinuousVariable::new("t");

    //let prob = LpProblem::new("p1", Objective::Maximize);

//    let l1 = LpVariable::new("l1".to_string(), Category::Binary);
    println!("{:?}", b + b);

    //println!("{:?}", b + c);
}
<|endoftext|>


<commit_before>extern crate byteorder;
extern crate camera_controllers;
extern crate docopt;
extern crate piston;
extern crate flate2;
extern crate fps_counter;
#[macro_use]
extern crate gfx;
extern crate gfx_device_gl;
extern crate gfx_voxel;
extern crate image;
extern crate libc;
extern crate memmap;
extern crate rustc_serialize;
extern crate sdl2;
extern crate sdl2_window;
extern crate shader_version;
extern crate time;
extern crate vecmath;
extern crate zip;

use gfx::traits::{Device, Stream, StreamFactory};
// Reexport modules from gfx_voxel while stuff is moving
// from Hematite to the library.
pub use gfx_voxel::{ array, cube };

use std::cell::RefCell;
use std::cmp::max;
use std::f32::consts::PI;
use std::f32::INFINITY;
use std::fs::File;
use std::path::{Path, PathBuf};
use std::rc::Rc;

use array::*;
use docopt::Docopt;
use piston::event_loop::{ Events, EventLoop };
use flate2::read::GzDecoder;
use sdl2_window::Sdl2Window;
use shader::Renderer;
use vecmath::{ vec3_add, vec3_scale, vec3_normalized };
use piston::window::{ Size, Window, AdvancedWindow, OpenGLWindow,
    WindowSettings };

pub mod minecraft;
pub mod chunk;
pub mod shader;

use minecraft::*;
use minecraft::biome::Biomes;
use minecraft::block_state::BlockStates;

static USAGE: &'static str = "
hematite, Minecraft made in Rust!

Usage:
    hematite [options] <world>

Options:
    -p, --path     Fully qualified path for world folder.
    --mcv          Minecraft version. [default: 1.8.3]
";

#[derive(RustcDecodable)]
struct Args {
    arg_world: String,
    flag_path: bool,
    flag_mcversion: String,
}

fn main() {
    let opt = Docopt::new(USAGE).unwrap_or_else(|e| e.exit());
    let args = match opt.decode::<Args>() {
        Ok(args) => { args }
        Err(err) => { panic!("{:?}", err); }
    };

    // Automagically pull MC assets
    minecraft::fetch_assets(&args.flag_mcversion);

    // Automagically expand path if world is located at
    // $MINECRAFT_ROOT/saves/<world_name>
    let world = if args.flag_path {
        PathBuf::from(&args.arg_world)
    } else {
        let mut mc_path = minecraft::vanilla_root_path();
        mc_path.push("saves");
        mc_path.push(args.arg_world);
        mc_path
    };

    let file_name = PathBuf::from(world.join("level.dat"));
    let level_reader = GzDecoder::new(File::open(file_name).unwrap()).unwrap();
    let level = minecraft::nbt::Nbt::from_reader(level_reader).unwrap();
    println!("{:?}", level);
    let player_pos: [f32; 3] = Array::from_iter(
            level["Data"]["Player"]["Pos"]
            .as_double_list().unwrap().iter().map(|&x| x as f32)
        );
    let player_chunk = [player_pos.x(), player_pos.z()]
        .map(|x| (x / 16.0).floor() as i32);
    let player_rot = level["Data"]["Player"]["Rotation"]
        .as_float_list().unwrap();
    let player_yaw = player_rot[0];
    let player_pitch = player_rot[1];

    let regions = player_chunk.map(|x| x >> 5);
    let region_file = world.join(
            format!("region/r.{}.{}.mca", regions[0], regions[1])
        );
    let region = minecraft::region::Region::open(&region_file).unwrap();

    let loading_title = format!(
            "Hematite loading... - {}",
            world.file_name().unwrap().to_str().unwrap()
        );
    let mut window: Sdl2Window = WindowSettings::new(
            loading_title,
            Size { width: 854, height: 480 })
            .fullscreen(false)
            .exit_on_esc(true)
            .samples(0)
            .vsync(false)
            .build()
            .unwrap();

    let (mut device, mut factory) = gfx_device_gl::create(|s|
        window.get_proc_address(s)
    );

    let Size { width: w, height: h } = window.size();
    let frame = factory.make_fake_output(w as u16, h as u16);
    let stream: gfx::OwnedStream<gfx_device_gl::Device, _> = factory.create_stream(frame);

    let assets = Path::new("./assets");

    // Load biomes.
    let biomes = Biomes::load(&assets);

    // Load block state definitions and models.
    let block_states = BlockStates::load(&assets, &mut factory);

    let mut renderer = Renderer::new(factory, stream, block_states.texture.handle());

    let mut chunk_manager = chunk::ChunkManager::new();

    println!("Started loading chunks...");
    let c_bases = player_chunk.map(|x| max(0, (x & 0x1f) - 8) as u8);
    for cz in c_bases[1]..c_bases[1] + 16 {
        for cx in c_bases[0]..c_bases[0] + 16 {
            match region.get_chunk_column(cx, cz) {
                Some(column) => {
                    let (cx, cz) = (
                        cx as i32 + regions[0] * 32,
                        cz as i32 + regions[1] * 32
                    );
                    chunk_manager.add_chunk_column(cx, cz, column)
                }
                None => {}
            }
        }
    }
    println!("Finished loading chunks.");

    let projection_mat = camera_controllers::CameraPerspective {
        fov: 70.0,
        near_clip: 0.1,
        far_clip: 1000.0,
        aspect_ratio: {
            let Size { width: w, height: h } = window.size();
            (w as f32) / (h as f32)
        }
    }.projection();
    renderer.set_projection(projection_mat);

    let mut first_person_settings = camera_controllers::FirstPersonSettings::keyboard_wasd();
    first_person_settings.speed_horizontal = 8.0;
    first_person_settings.speed_vertical = 4.0;
    let mut first_person = camera_controllers::FirstPerson::new(
        player_pos,
        first_person_settings
    );
    first_person.yaw = PI - player_yaw / 180.0 * PI;
    first_person.pitch = player_pitch / 180.0 * PI;

    let mut fps_counter = fps_counter::FPSCounter::new();

    let mut pending_chunks = vec![];
    chunk_manager.each_chunk_and_neighbors(
        |coords, buffer, chunks, column_biomes| {
            pending_chunks.push((coords, buffer, chunks, column_biomes));
        }
    );

    let mut capture_cursor = false;
    println!("Press C to capture mouse");

    let mut staging_buffer = vec![];
    let ref window = Rc::new(RefCell::new(window));
    for e in window.clone().events()
        .ups(120)
        .max_fps(10_000)
    {
        use piston::input::Button::Keyboard;
        use piston::input::Input::{ Move, Press };
        use piston::input::keyboard::Key;
        use piston::input::Motion::MouseRelative;
        use piston::input::Event;

        match e {
            Event::Render(_) => {
                // Apply the same y/z camera offset vanilla minecraft has.
                let mut camera = first_person.camera(0.0);
                camera.position[1] += 1.62;
                let mut xz_forward = camera.forward;
                xz_forward[1] = 0.0;
                xz_forward = vec3_normalized(xz_forward);
                camera.position = vec3_add(
                    camera.position,
                    vec3_scale(xz_forward, 0.1)
                );

                let view_mat = camera.orthogonal();
                renderer.set_view(view_mat);
                renderer.clear();
                let mut num_chunks: usize = 0;
                let mut num_sorted_chunks: usize = 0;
                let mut num_total_chunks: usize = 0;
                let start_time = time::precise_time_ns();
                chunk_manager.each_chunk(|cx, cy, cz, _, buffer| {
                    match buffer.borrow_mut().as_mut() {
                        Some(buffer) => {
                            num_total_chunks += 1;

                            let inf = INFINITY;
                            let mut bb_min = [inf, inf, inf];
                            let mut bb_max = [-inf, -inf, -inf];
                            let xyz = [cx, cy, cz].map(|x| x as f32 * 16.0);
                            for &dx in [0.0, 16.0].iter() {
                                for &dy in [0.0, 16.0].iter() {
                                    for &dz in [0.0, 16.0].iter() {
                                        use vecmath::col_mat4_transform;

                                        let v = vec3_add(xyz, [dx, dy, dz]);
                                        let xyzw = col_mat4_transform(view_mat, [v[0], v[1], v[2], 1.0]);
                                        let v = col_mat4_transform(projection_mat, xyzw);
                                        let xyz = vec3_scale([v[0], v[1], v[2]], 1.0 / v[3]);
                                        bb_min = Array::from_fn(|i| bb_min[i].min(xyz[i]));
                                        bb_max = Array::from_fn(|i| bb_max[i].max(xyz[i]));
                                    }
                                }
                            }

                            let cull_bits: [bool; 3] = Array::from_fn(|i| {
                                let (min, max) = (bb_min[i], bb_max[i]);
                                min.signum() == max.signum()
                                    && min.abs().min(max.abs()) >= 1.0
                            });

                            if !cull_bits.iter().any(|&cull| cull) {
                                renderer.render(buffer);
                                num_chunks += 1;

                                if bb_min[0] < 0.0 && bb_max[0] > 0.0
                                || bb_min[1] < 0.0 && bb_max[1] > 0.0 {
                                    num_sorted_chunks += 1;
                                }
                            }
                        }
                        None => {}
                    }
                });
                let end_time = time::precise_time_ns();
                renderer.stream.flush(&mut device);
                let frame_end_time = time::precise_time_ns();

                let fps = fps_counter.tick();
                let title = format!(
"Hematite sort={} render={} total={} in {:.2}ms+{:.2}ms @ {}FPS - {}",
                        num_sorted_chunks,
                        num_chunks,
                        num_total_chunks,
                        (end_time - start_time) as f64 / 1e6,
                        (frame_end_time - end_time) as f64 / 1e6,
                        fps, world.file_name().unwrap().to_str().unwrap()
                    );
                window.borrow_mut().set_title(title);
            }
            Event::AfterRender(_) => {
                device.cleanup();
            }
            Event::Update(_) => {
                use std::i32;
                // HACK(eddyb) find the closest chunk to the player.
                // The pending vector should be sorted instead.
                let pp = first_person.position.map(|x| (x / 16.0).floor() as i32);
                let closest = pending_chunks.iter().enumerate().fold(
                    (None, i32::max_value()),
                    |(best_i, best_dist), (i, &(cc, _, _, _))| {
                        let xyz = [cc[0] - pp[0], cc[1] - pp[1], cc[2] - pp[2]]
                            .map(|x| x * x);
                        let dist = xyz[0] + xyz[1] + xyz[2];
                        if dist < best_dist {
                            (Some(i), dist)
                        } else {
                            (best_i, best_dist)
                        }
                    }
                ).0;
                let pending = closest.and_then(|i| {
                    // Vec swap_remove doesn't return Option anymore
                    match pending_chunks.len() {
                        0 => None,
                        _ => Some(pending_chunks.swap_remove(i))
                    }
                });
                match pending {
                    Some((coords, buffer, chunks, column_biomes)) => {
                        minecraft::block_state::fill_buffer(
                            &block_states, &biomes, &mut staging_buffer,
                            coords, chunks, column_biomes
                        );
                        *buffer.borrow_mut() = Some(
                            renderer.create_buffer(&staging_buffer[..])
                        );
                        staging_buffer.clear();

                        if pending_chunks.is_empty() {
                            println!("Finished filling chunk vertex buffers.");
                        }
                    }
                    None => {}
                }
            }
            Event::Input(Press(Keyboard(Key::C))) => {
                println!("Turned cursor capture {}",
                    if capture_cursor { "off" } else { "on" });
                capture_cursor = !capture_cursor;

                window.borrow_mut().set_capture_cursor(capture_cursor);
            }
            Event::Input(Move(MouseRelative(_, _))) => {
                if !capture_cursor {
                    // Don't send the mouse event to the FPS controller.
                    continue;
                }
            }
            _ => {}
        }

        first_person.event(&e);
    }
}
<commit_msg>Fixes Minecraft version flag<commit_after>extern crate byteorder;
extern crate camera_controllers;
extern crate docopt;
extern crate piston;
extern crate flate2;
extern crate fps_counter;
#[macro_use]
extern crate gfx;
extern crate gfx_device_gl;
extern crate gfx_voxel;
extern crate image;
extern crate libc;
extern crate memmap;
extern crate rustc_serialize;
extern crate sdl2;
extern crate sdl2_window;
extern crate shader_version;
extern crate time;
extern crate vecmath;
extern crate zip;

use gfx::traits::{Device, Stream, StreamFactory};
// Reexport modules from gfx_voxel while stuff is moving
// from Hematite to the library.
pub use gfx_voxel::{ array, cube };

use std::cell::RefCell;
use std::cmp::max;
use std::f32::consts::PI;
use std::f32::INFINITY;
use std::fs::File;
use std::path::{Path, PathBuf};
use std::rc::Rc;

use array::*;
use docopt::Docopt;
use piston::event_loop::{ Events, EventLoop };
use flate2::read::GzDecoder;
use sdl2_window::Sdl2Window;
use shader::Renderer;
use vecmath::{ vec3_add, vec3_scale, vec3_normalized };
use piston::window::{ Size, Window, AdvancedWindow, OpenGLWindow,
    WindowSettings };

pub mod minecraft;
pub mod chunk;
pub mod shader;

use minecraft::*;
use minecraft::biome::Biomes;
use minecraft::block_state::BlockStates;

static USAGE: &'static str = "
hematite, Minecraft made in Rust!

Usage:
    hematite [options] <world>

Options:
    -p, --path               Fully qualified path for world folder.
    --mcversion=<version>    Minecraft version [default: 1.8.3].
";

#[derive(RustcDecodable)]
struct Args {
    arg_world: String,
    flag_path: bool,
    flag_mcversion: String,
}

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

    // Automagically pull MC assets
    minecraft::fetch_assets(&args.flag_mcversion);

    // Automagically expand path if world is located at
    // $MINECRAFT_ROOT/saves/<world_name>
    let world = if args.flag_path {
        PathBuf::from(&args.arg_world)
    } else {
        let mut mc_path = minecraft::vanilla_root_path();
        mc_path.push("saves");
        mc_path.push(args.arg_world);
        mc_path
    };

    let file_name = PathBuf::from(world.join("level.dat"));
    let level_reader = GzDecoder::new(File::open(file_name).unwrap()).unwrap();
    let level = minecraft::nbt::Nbt::from_reader(level_reader).unwrap();
    println!("{:?}", level);
    let player_pos: [f32; 3] = Array::from_iter(
            level["Data"]["Player"]["Pos"]
            .as_double_list().unwrap().iter().map(|&x| x as f32)
        );
    let player_chunk = [player_pos.x(), player_pos.z()]
        .map(|x| (x / 16.0).floor() as i32);
    let player_rot = level["Data"]["Player"]["Rotation"]
        .as_float_list().unwrap();
    let player_yaw = player_rot[0];
    let player_pitch = player_rot[1];

    let regions = player_chunk.map(|x| x >> 5);
    let region_file = world.join(
            format!("region/r.{}.{}.mca", regions[0], regions[1])
        );
    let region = minecraft::region::Region::open(&region_file).unwrap();

    let loading_title = format!(
            "Hematite loading... - {}",
            world.file_name().unwrap().to_str().unwrap()
        );
    let mut window: Sdl2Window = WindowSettings::new(
            loading_title,
            Size { width: 854, height: 480 })
            .fullscreen(false)
            .exit_on_esc(true)
            .samples(0)
            .vsync(false)
            .build()
            .unwrap();

    let (mut device, mut factory) = gfx_device_gl::create(|s|
        window.get_proc_address(s)
    );

    let Size { width: w, height: h } = window.size();
    let frame = factory.make_fake_output(w as u16, h as u16);
    let stream: gfx::OwnedStream<gfx_device_gl::Device, _> = factory.create_stream(frame);

    let assets = Path::new("./assets");

    // Load biomes.
    let biomes = Biomes::load(&assets);

    // Load block state definitions and models.
    let block_states = BlockStates::load(&assets, &mut factory);

    let mut renderer = Renderer::new(factory, stream, block_states.texture.handle());

    let mut chunk_manager = chunk::ChunkManager::new();

    println!("Started loading chunks...");
    let c_bases = player_chunk.map(|x| max(0, (x & 0x1f) - 8) as u8);
    for cz in c_bases[1]..c_bases[1] + 16 {
        for cx in c_bases[0]..c_bases[0] + 16 {
            match region.get_chunk_column(cx, cz) {
                Some(column) => {
                    let (cx, cz) = (
                        cx as i32 + regions[0] * 32,
                        cz as i32 + regions[1] * 32
                    );
                    chunk_manager.add_chunk_column(cx, cz, column)
                }
                None => {}
            }
        }
    }
    println!("Finished loading chunks.");

    let projection_mat = camera_controllers::CameraPerspective {
        fov: 70.0,
        near_clip: 0.1,
        far_clip: 1000.0,
        aspect_ratio: {
            let Size { width: w, height: h } = window.size();
            (w as f32) / (h as f32)
        }
    }.projection();
    renderer.set_projection(projection_mat);

    let mut first_person_settings = camera_controllers::FirstPersonSettings::keyboard_wasd();
    first_person_settings.speed_horizontal = 8.0;
    first_person_settings.speed_vertical = 4.0;
    let mut first_person = camera_controllers::FirstPerson::new(
        player_pos,
        first_person_settings
    );
    first_person.yaw = PI - player_yaw / 180.0 * PI;
    first_person.pitch = player_pitch / 180.0 * PI;

    let mut fps_counter = fps_counter::FPSCounter::new();

    let mut pending_chunks = vec![];
    chunk_manager.each_chunk_and_neighbors(
        |coords, buffer, chunks, column_biomes| {
            pending_chunks.push((coords, buffer, chunks, column_biomes));
        }
    );

    let mut capture_cursor = false;
    println!("Press C to capture mouse");

    let mut staging_buffer = vec![];
    let ref window = Rc::new(RefCell::new(window));
    for e in window.clone().events()
        .ups(120)
        .max_fps(10_000)
    {
        use piston::input::Button::Keyboard;
        use piston::input::Input::{ Move, Press };
        use piston::input::keyboard::Key;
        use piston::input::Motion::MouseRelative;
        use piston::input::Event;

        match e {
            Event::Render(_) => {
                // Apply the same y/z camera offset vanilla minecraft has.
                let mut camera = first_person.camera(0.0);
                camera.position[1] += 1.62;
                let mut xz_forward = camera.forward;
                xz_forward[1] = 0.0;
                xz_forward = vec3_normalized(xz_forward);
                camera.position = vec3_add(
                    camera.position,
                    vec3_scale(xz_forward, 0.1)
                );

                let view_mat = camera.orthogonal();
                renderer.set_view(view_mat);
                renderer.clear();
                let mut num_chunks: usize = 0;
                let mut num_sorted_chunks: usize = 0;
                let mut num_total_chunks: usize = 0;
                let start_time = time::precise_time_ns();
                chunk_manager.each_chunk(|cx, cy, cz, _, buffer| {
                    match buffer.borrow_mut().as_mut() {
                        Some(buffer) => {
                            num_total_chunks += 1;

                            let inf = INFINITY;
                            let mut bb_min = [inf, inf, inf];
                            let mut bb_max = [-inf, -inf, -inf];
                            let xyz = [cx, cy, cz].map(|x| x as f32 * 16.0);
                            for &dx in [0.0, 16.0].iter() {
                                for &dy in [0.0, 16.0].iter() {
                                    for &dz in [0.0, 16.0].iter() {
                                        use vecmath::col_mat4_transform;

                                        let v = vec3_add(xyz, [dx, dy, dz]);
                                        let xyzw = col_mat4_transform(view_mat, [v[0], v[1], v[2], 1.0]);
                                        let v = col_mat4_transform(projection_mat, xyzw);
                                        let xyz = vec3_scale([v[0], v[1], v[2]], 1.0 / v[3]);
                                        bb_min = Array::from_fn(|i| bb_min[i].min(xyz[i]));
                                        bb_max = Array::from_fn(|i| bb_max[i].max(xyz[i]));
                                    }
                                }
                            }

                            let cull_bits: [bool; 3] = Array::from_fn(|i| {
                                let (min, max) = (bb_min[i], bb_max[i]);
                                min.signum() == max.signum()
                                    && min.abs().min(max.abs()) >= 1.0
                            });

                            if !cull_bits.iter().any(|&cull| cull) {
                                renderer.render(buffer);
                                num_chunks += 1;

                                if bb_min[0] < 0.0 && bb_max[0] > 0.0
                                || bb_min[1] < 0.0 && bb_max[1] > 0.0 {
                                    num_sorted_chunks += 1;
                                }
                            }
                        }
                        None => {}
                    }
                });
                let end_time = time::precise_time_ns();
                renderer.stream.flush(&mut device);
                let frame_end_time = time::precise_time_ns();

                let fps = fps_counter.tick();
                let title = format!(
"Hematite sort={} render={} total={} in {:.2}ms+{:.2}ms @ {}FPS - {}",
                        num_sorted_chunks,
                        num_chunks,
                        num_total_chunks,
                        (end_time - start_time) as f64 / 1e6,
                        (frame_end_time - end_time) as f64 / 1e6,
                        fps, world.file_name().unwrap().to_str().unwrap()
                    );
                window.borrow_mut().set_title(title);
            }
            Event::AfterRender(_) => {
                device.cleanup();
            }
            Event::Update(_) => {
                use std::i32;
                // HACK(eddyb) find the closest chunk to the player.
                // The pending vector should be sorted instead.
                let pp = first_person.position.map(|x| (x / 16.0).floor() as i32);
                let closest = pending_chunks.iter().enumerate().fold(
                    (None, i32::max_value()),
                    |(best_i, best_dist), (i, &(cc, _, _, _))| {
                        let xyz = [cc[0] - pp[0], cc[1] - pp[1], cc[2] - pp[2]]
                            .map(|x| x * x);
                        let dist = xyz[0] + xyz[1] + xyz[2];
                        if dist < best_dist {
                            (Some(i), dist)
                        } else {
                            (best_i, best_dist)
                        }
                    }
                ).0;
                let pending = closest.and_then(|i| {
                    // Vec swap_remove doesn't return Option anymore
                    match pending_chunks.len() {
                        0 => None,
                        _ => Some(pending_chunks.swap_remove(i))
                    }
                });
                match pending {
                    Some((coords, buffer, chunks, column_biomes)) => {
                        minecraft::block_state::fill_buffer(
                            &block_states, &biomes, &mut staging_buffer,
                            coords, chunks, column_biomes
                        );
                        *buffer.borrow_mut() = Some(
                            renderer.create_buffer(&staging_buffer[..])
                        );
                        staging_buffer.clear();

                        if pending_chunks.is_empty() {
                            println!("Finished filling chunk vertex buffers.");
                        }
                    }
                    None => {}
                }
            }
            Event::Input(Press(Keyboard(Key::C))) => {
                println!("Turned cursor capture {}",
                    if capture_cursor { "off" } else { "on" });
                capture_cursor = !capture_cursor;

                window.borrow_mut().set_capture_cursor(capture_cursor);
            }
            Event::Input(Move(MouseRelative(_, _))) => {
                if !capture_cursor {
                    // Don't send the mouse event to the FPS controller.
                    continue;
                }
            }
            _ => {}
        }

        first_person.event(&e);
    }
}
<|endoftext|>


<commit_before>#![feature(globs)]
extern crate rgtk;

use rgtk::*;
use std::collections::HashSet;

mod projects;
mod utils;

fn main() {
    gtk::init();

    // constants

    let width = 1242;
    let height = 768;
    let editor_height = ((height as f32) * 0.8) as i32;

    // window

    let mut window = gtk::Window::new(gtk::window_type::TopLevel).unwrap();
    window.set_title("SolidOak");
    window.set_window_position(gtk::window_position::Center);
    window.set_default_size(width, height);

    window.connect(gtk::signals::DeleteEvent::new(|_| {
        gtk::main_quit();
        true
    }));

    // project pane

    let new_project_button = gtk::Button::new_with_label("New Project").unwrap();
    let import_button = gtk::Button::new_with_label("Import").unwrap();
    let rename_button = gtk::Button::new_with_label("Rename").unwrap();
    let remove_button = gtk::Button::new_with_label("Remove").unwrap();

    let mut project_buttons = gtk::Box::new(gtk::orientation::Horizontal, 0).unwrap();
    project_buttons.set_size_request(-1, -1);
    project_buttons.add(&new_project_button);
    project_buttons.add(&import_button);
    project_buttons.add(&rename_button);
    project_buttons.add(&remove_button);

    let mut project_tree = gtk::TreeView::new().unwrap();
    let column_types = vec![glib::ffi::g_type_string];
    let store = gtk::ListStore::new(column_types).unwrap();
    let model = store.get_model().unwrap();
    project_tree.set_model(&model);
    project_tree.set_headers_visible(false);

    let column = gtk::TreeViewColumn::new().unwrap();
    project_tree.append_column(&column);

    let cell = gtk::CellRendererText::new().unwrap();
    column.pack_start(&cell, true);
    column.add_attribute(&cell, "text", 0);

    let mut iter = gtk::ffi::C_GtkTreeIter;
    model.get_iter_first(&mut iter);
    store.append(&mut iter);
    store.set_column_text(&mut iter, 0, "Hello, world!");

    let mut project_pane = gtk::Box::new(gtk::orientation::Vertical, 0).unwrap();
    project_pane.set_size_request(-1, -1);
    project_pane.pack_start(&project_buttons, false, true, 0);
    project_pane.pack_start(&project_tree, true, true, 0);

    // editor pane

    let editor_pane = gtk::TextView::new().unwrap();
    editor_pane.set_size_request(-1, editor_height);

    // build pane

    let build_pane = gtk::TextView::new().unwrap();

    // content

    let mut content = gtk::Box::new(gtk::orientation::Vertical, 0).unwrap();
    content.pack_start(&editor_pane, false, true, 0);
    content.pack_start(&build_pane, true, true, 0);

    // hbox

    let mut hbox = gtk::Box::new(gtk::orientation::Horizontal, 0).unwrap();
    hbox.pack_start(&project_pane, false, true, 0);
    hbox.pack_start(&content, true, true, 0);
    window.add(&hbox);

    // state

    let mut state = ::utils::State{
        projects: HashSet::new(),
        expansions: HashSet::new(),
        selection: None,
        tree_model: &model
    };

    // connections

    new_project_button.connect(gtk::signals::Clicked::new(|| {::projects::new_project(&mut state)}));
    import_button.connect(gtk::signals::Clicked::new(|| {::projects::import_project(&mut state)}));
    rename_button.connect(gtk::signals::Clicked::new(|| {::projects::rename_project(&mut state)}));
    remove_button.connect(gtk::signals::Clicked::new(|| {::projects::remove_project(&mut state)}));

    // show window

    window.show_all();
    gtk::main();
}
<commit_msg>Use convenience function<commit_after>#![feature(globs)]
extern crate rgtk;

use rgtk::*;
use std::collections::HashSet;

mod projects;
mod utils;

fn main() {
    gtk::init();

    // constants

    let width = 1242;
    let height = 768;
    let editor_height = ((height as f32) * 0.8) as i32;

    // window

    let mut window = gtk::Window::new(gtk::window_type::TopLevel).unwrap();
    window.set_title("SolidOak");
    window.set_window_position(gtk::window_position::Center);
    window.set_default_size(width, height);

    window.connect(gtk::signals::DeleteEvent::new(|_| {
        gtk::main_quit();
        true
    }));

    // project pane

    let new_project_button = gtk::Button::new_with_label("New Project").unwrap();
    let import_button = gtk::Button::new_with_label("Import").unwrap();
    let rename_button = gtk::Button::new_with_label("Rename").unwrap();
    let remove_button = gtk::Button::new_with_label("Remove").unwrap();

    let mut project_buttons = gtk::Box::new(gtk::orientation::Horizontal, 0).unwrap();
    project_buttons.set_size_request(-1, -1);
    project_buttons.add(&new_project_button);
    project_buttons.add(&import_button);
    project_buttons.add(&rename_button);
    project_buttons.add(&remove_button);

    let mut project_tree = gtk::TreeView::new().unwrap();
    let column_types = vec![glib::ffi::g_type_string];
    let store = gtk::ListStore::new(column_types).unwrap();
    let model = store.get_model().unwrap();
    project_tree.set_model(&model);
    project_tree.set_headers_visible(false);

    let column = gtk::TreeViewColumn::new().unwrap();
    project_tree.append_text_column(&column);

    let mut iter = gtk::ffi::C_GtkTreeIter;
    model.get_iter_first(&mut iter);
    store.append(&mut iter);
    store.set_column_text(&mut iter, 0, "Hello, world!");

    let mut project_pane = gtk::Box::new(gtk::orientation::Vertical, 0).unwrap();
    project_pane.set_size_request(-1, -1);
    project_pane.pack_start(&project_buttons, false, true, 0);
    project_pane.pack_start(&project_tree, true, true, 0);

    // editor pane

    let editor_pane = gtk::TextView::new().unwrap();
    editor_pane.set_size_request(-1, editor_height);

    // build pane

    let build_pane = gtk::TextView::new().unwrap();

    // content

    let mut content = gtk::Box::new(gtk::orientation::Vertical, 0).unwrap();
    content.pack_start(&editor_pane, false, true, 0);
    content.pack_start(&build_pane, true, true, 0);

    // hbox

    let mut hbox = gtk::Box::new(gtk::orientation::Horizontal, 0).unwrap();
    hbox.pack_start(&project_pane, false, true, 0);
    hbox.pack_start(&content, true, true, 0);
    window.add(&hbox);

    // state

    let mut state = ::utils::State{
        projects: HashSet::new(),
        expansions: HashSet::new(),
        selection: None,
        tree_model: &model
    };

    // connections

    new_project_button.connect(gtk::signals::Clicked::new(|| {::projects::new_project(&mut state)}));
    import_button.connect(gtk::signals::Clicked::new(|| {::projects::import_project(&mut state)}));
    rename_button.connect(gtk::signals::Clicked::new(|| {::projects::rename_project(&mut state)}));
    remove_button.connect(gtk::signals::Clicked::new(|| {::projects::remove_project(&mut state)}));

    // show window

    window.show_all();
    gtk::main();
}
<|endoftext|>


<commit_before>use crossbeam::bounded;
use crossterm::{AlternateScreen, InputEvent, KeyEvent, TerminalInput};
use rand::distributions::Uniform;
use rand::prelude::Distribution;
use rusty_audio::Audio;
use rusty_sword::coord::{key_to_direction, Coord};
use rusty_sword::monster::Monster;
use rusty_sword::render::render_loop;
use rusty_sword::timer::Timer;
use rusty_sword::world::World;
use std::thread::{sleep, spawn};
use std::time::{Duration, Instant};

fn main() {
    let mut audio = Audio::new();
    audio.add("monster_dies", "clips/monster_dies.wav");
    audio.add("monster_spawns", "clips/monster_spawns.wav");
    audio.add("player_dies", "clips/player_dies.wav");

    let mut world = World::new(30, 60);

    // Make a channel to send the world to the render thread, and a channel to receive it back
    // This is a silly design, we can demonstrate using channels for thread communication. :-P
    let (render_tx, render_rx) = bounded::<World>(0);
    let (main_tx, main_rx) = bounded::<World>(0);

    // Render Thread
    let render_thread = { spawn(move || render_loop(render_rx, main_tx)) };

    // Game Loop
    let alternate_screen = AlternateScreen::to_alternate(true).unwrap();
    let input = TerminalInput::new();
    let mut reader = input.read_async();
    let mut rng = rand::thread_rng();
    let mut spawn_timer = Timer::from_millis(1000);
    let mut last_instant = Instant::now();
    'gameloop: loop {
        let delta = last_instant.elapsed();
        last_instant = Instant::now();
        let mut player = &mut world.player;

        // Player moves?
        let mut player_moved = false;
        while let Some(event) = reader.next() {
            match event {
                InputEvent::Keyboard(KeyEvent::Char('q')) | InputEvent::Keyboard(KeyEvent::Esc) => {
                    break 'gameloop
                }
                InputEvent::Keyboard(k) => {
                    if let Some(direction) = key_to_direction(k) {
                        player_moved =
                            player.travel(direction, &world.floor, &mut world.dirty_coords);
                    }
                }
                _ => {}
            }
        }

        // Update monster timers
        for monster in world.monsters.iter_mut() {
            monster.move_timer.update(delta);
        }

        // Monsters move?
        if !player_moved {
            for monster in world.monsters.iter_mut() {
                monster.try_travel(player.coord, &mut world.dirty_coords);
            }
        }

        // Did a monster die?
        let num_monsters = world.monsters.len();
        world
            .monsters
            .retain(|monster| monster.coord != player.sword_coord);
        let num_killed = num_monsters - world.monsters.len();
        if num_killed > 0 {
            player.score += num_killed as u64;
            audio.play("monster_dies");
        }

        // Spawn a new monster!
        spawn_timer.update(delta);
        if spawn_timer.ready {
            spawn_timer = Timer::from_millis(Uniform::new(1000, 5000).sample(&mut rng));
            let to_coord = Coord::new(
                Uniform::new(1, world.floor.rows).sample(&mut rng),
                Uniform::new(1, world.floor.cols).sample(&mut rng),
            );
            if to_coord != player.coord {
                world.monsters.push(Monster::new(to_coord, &mut rng));
                audio.play("monster_spawns");
            }
        }

        // Did the player die?
        if world
            .monsters
            .iter()
            .any(|monster| monster.coord == player.coord)
        {
            audio.play("player_dies");
            audio.wait(); // Wait until the sound finishes, so we can hear it before quitting.
            break 'gameloop;
        }

        // Give the whole world to the renderer
        render_tx.send(world).unwrap();
        // Get the whole world back
        world = main_rx.recv().unwrap();
        // Don't exceed ~60/fps
        if let Some(t) = Duration::from_secs_f64(1. / 60.).checked_sub(last_instant.elapsed()) {
            sleep(t);
        }
    }

    // Close the render_tx channel, which will trigger the render thread to exit
    drop(render_tx);
    // Wait for the render thread to actually exit
    render_thread.join().unwrap();

    drop(alternate_screen);
    println!("Thanks for playing!");
}
<commit_msg>Call functions through modules, to be idiomatic.<commit_after>use crossbeam::bounded;
use crossterm::{AlternateScreen, InputEvent, KeyEvent, TerminalInput};
use rand::distributions::Uniform;
use rand::prelude::Distribution;
use rusty_audio::Audio;
use rusty_sword::coord::{key_to_direction, Coord};
use rusty_sword::monster::Monster;
use rusty_sword::render::render_loop;
use rusty_sword::timer::Timer;
use rusty_sword::world::World;
use std::thread;
use std::time::{Duration, Instant};

fn main() {
    let mut audio = Audio::new();
    audio.add("monster_dies", "clips/monster_dies.wav");
    audio.add("monster_spawns", "clips/monster_spawns.wav");
    audio.add("player_dies", "clips/player_dies.wav");

    let mut world = World::new(30, 60);

    // Make a channel to send the world to the render thread, and a channel to receive it back
    // This is a silly design, we can demonstrate using channels for thread communication. :-P
    let (render_tx, render_rx) = bounded::<World>(0);
    let (main_tx, main_rx) = bounded::<World>(0);

    // Render Thread
    let render_thread = { thread::spawn(move || render_loop(render_rx, main_tx)) };

    // Game Loop
    let alternate_screen = AlternateScreen::to_alternate(true).unwrap();
    let input = TerminalInput::new();
    let mut reader = input.read_async();
    let mut rng = rand::thread_rng();
    let mut spawn_timer = Timer::from_millis(1000);
    let mut last_instant = Instant::now();
    'gameloop: loop {
        let delta = last_instant.elapsed();
        last_instant = Instant::now();
        let mut player = &mut world.player;

        // Player moves?
        let mut player_moved = false;
        while let Some(event) = reader.next() {
            match event {
                InputEvent::Keyboard(KeyEvent::Char('q')) | InputEvent::Keyboard(KeyEvent::Esc) => {
                    break 'gameloop
                }
                InputEvent::Keyboard(k) => {
                    if let Some(direction) = key_to_direction(k) {
                        player_moved =
                            player.travel(direction, &world.floor, &mut world.dirty_coords);
                    }
                }
                _ => {}
            }
        }

        // Update monster timers
        for monster in world.monsters.iter_mut() {
            monster.move_timer.update(delta);
        }

        // Monsters move?
        if !player_moved {
            for monster in world.monsters.iter_mut() {
                monster.try_travel(player.coord, &mut world.dirty_coords);
            }
        }

        // Did a monster die?
        let num_monsters = world.monsters.len();
        world
            .monsters
            .retain(|monster| monster.coord != player.sword_coord);
        let num_killed = num_monsters - world.monsters.len();
        if num_killed > 0 {
            player.score += num_killed as u64;
            audio.play("monster_dies");
        }

        // Spawn a new monster!
        spawn_timer.update(delta);
        if spawn_timer.ready {
            spawn_timer = Timer::from_millis(Uniform::new(1000, 5000).sample(&mut rng));
            let to_coord = Coord::new(
                Uniform::new(1, world.floor.rows).sample(&mut rng),
                Uniform::new(1, world.floor.cols).sample(&mut rng),
            );
            if to_coord != player.coord {
                world.monsters.push(Monster::new(to_coord, &mut rng));
                audio.play("monster_spawns");
            }
        }

        // Did the player die?
        if world
            .monsters
            .iter()
            .any(|monster| monster.coord == player.coord)
        {
            audio.play("player_dies");
            audio.wait(); // Wait until the sound finishes, so we can hear it before quitting.
            break 'gameloop;
        }

        // Give the whole world to the renderer
        render_tx.send(world).unwrap();
        // Get the whole world back
        world = main_rx.recv().unwrap();
        // Don't exceed ~60/fps
        if let Some(t) = Duration::from_secs_f64(1. / 60.).checked_sub(last_instant.elapsed()) {
            thread::sleep(t);
        }
    }

    // Close the render_tx channel, which will trigger the render thread to exit
    drop(render_tx);
    // Wait for the render thread to actually exit
    render_thread.join().unwrap();

    drop(alternate_screen);
    println!("Thanks for playing!");
}
<|endoftext|>