<commit_before>use std::cmp::max;
use std::fs::File;
use std::io::prelude::*;
use std::collections::{HashSet, HashMap};

fn get_input() -> std::io::Result<String> {
    let mut file = File::open("17.txt")?;
    let mut contents = String::new();
    file.read_to_string(&mut contents)?;

    Ok(contents)
}

type Point = (isize, isize);
type DepthMap = HashSet<Point>;

fn parse(input: &str) -> DepthMap {
    input.lines()
    .flat_map(|line| {
        let parts = line.split(", ")
            .filter_map(|part| {
                let mut tokens = part.split('=');

                match (tokens.next(), tokens.next()) {
                    (Some(coord), Some(value)) => Some((coord, value)),
                    _ => None
                }
            })
            .map(|(coord, value)| (
                coord,
                match value.parse::<usize>() {
                    Ok(x) => vec![x, x],
                    _ => value.split("..").filter_map(|x| x.parse::<usize>().ok()).collect()
                }
            ))
            .filter(|(_, values)| values.len() == 2)
            .fold(HashMap::new(), |mut acc, (coord, values)| {
                acc.insert(coord, values);
                acc
            });

        let (xstart, xend) = parts.get(&"x")
            .map(|v| (v[0], v[1]))
            .unwrap_or((0, 0));

        let (ystart, yend) = parts.get(&"y")
            .map(|v| (v[0], v[1]))
            .unwrap_or((0, 0));

        (xstart..xend + 1)
        .flat_map(move |x| (ystart..yend + 1).map(move |y| (x as isize, y as isize)))
    })
    .collect()
}

fn fill_water(source: Point, map: &DepthMap) -> (DepthMap, DepthMap) {
    let miny = map.iter().cloned().map(|(_, y)| y).min().unwrap_or(source.1);
    let maxy = map.iter().cloned().map(|(_, y)| y).max().unwrap_or(source.1);

    let mut water = DepthMap::new();
    let mut flows = DepthMap::new();
    let mut blocked = map.clone();

    fn flows_through((x, y): Point, blocked: &DepthMap) -> bool {
        !blocked.contains(&(x, y + 1))
    }

    fn inner(
        source: Point,
        map: &DepthMap,
        water: &mut DepthMap,
        flows: &mut DepthMap,
        blocked: &mut DepthMap,
        miny: isize,
        maxy: isize
    ) {
        let (sx, sy) = source;

        let (ax, ay) = (sy..maxy + 1)
            .map(|y| (sx, y))
            .find(|&p| !flows_through(p, &blocked))
            .unwrap_or((sx, maxy));

        let ((lx, ly), (rx, ry)) = {
            let left = (0..)
                .map(|x| (ax - x, ay))
                .find(|&(x, y)| {
                    blocked.contains(&(x - 1, y))
                    || flows_through((x, y), &blocked)
                })
                .unwrap();

            let right = (0..)
                .map(|x| (ax + x, ay))
                .find(|&(x, y)| {
                    blocked.contains(&(x + 1, y))
                    || flows_through((x, y), &blocked)
                })
                .unwrap();

            (left, right)
        };

        // Update flows & water

        let left_overflow = flows_through((lx, ly), &blocked);
        let right_overflow = flows_through((rx, ry), &blocked);
        let overflow = left_overflow || right_overflow;
        let top = (lx..rx + 1).map(|x| (x, ay)).collect::<DepthMap>();

        let old_water_count = water.len();
        let old_flow_count = flows.len();

        println!("{:?} {:?} {:?}: {:?}, {:?}, {:?} - {}, {}", source, left_overflow, right_overflow, (lx, ly), (ax, ay), (rx, ry), water.len(), flows.len());

        if !overflow {
            *water = water.union(&top).cloned().collect();
            *blocked = blocked.union(&top).cloned().collect();
        } else {
            *flows = flows
                .union(&top)
                .cloned()
                .chain(
                    if !flows.contains(&(sx, sy + 1)) {
                        (max(sy, miny)..ay + 1)
                    } else {
                        (0..0)
                    }
                    .map(|y| (sx, y))
                )
                .collect();
        }

        // Propagate

        let (left_source, right_source) = (
            left_overflow && (lx, ly) != (ax, ay),
            right_overflow && (rx, ry) != (ax, ay)
        );

        if left_source {
            inner((lx, ly), map, water, flows, blocked, miny, maxy);
        }

        if right_source {
            inner((rx, ry), map, water, flows, blocked, miny, maxy);
        }

        if overflow && old_flow_count == flows.len() && old_water_count == water.len() {
            return;
        }

        if !overflow {
            inner(source, map, water, flows, blocked, miny, maxy);
        }
    }

    inner(source, map, &mut water, &mut flows, &mut blocked, miny, maxy);

    (water, flows)
}

fn main() {
    let input = get_input().unwrap();
    let depth_map = parse(&input);
    let (water, flows) = fill_water((500, 0), &depth_map);

    println!("Part 1: {}", water.union(&flows).count());
}
<commit_msg>Add 2018 day 17 solution<commit_after>use std::cmp::max;
use std::fs::File;
use std::io::prelude::*;
use std::collections::{HashSet, HashMap};

fn get_input() -> std::io::Result<String> {
    let mut file = File::open("17.txt")?;
    let mut contents = String::new();
    file.read_to_string(&mut contents)?;

    Ok(contents)
}

type Point = (isize, isize);
type DepthMap = HashSet<Point>;

fn parse(input: &str) -> DepthMap {
    input.lines()
    .flat_map(|line| {
        let parts = line.split(", ")
            .filter_map(|part| {
                let mut tokens = part.split('=');

                match (tokens.next(), tokens.next()) {
                    (Some(coord), Some(value)) => Some((coord, value)),
                    _ => None
                }
            })
            .map(|(coord, value)| (
                coord,
                match value.parse::<usize>() {
                    Ok(x) => vec![x, x],
                    _ => value.split("..").filter_map(|x| x.parse::<usize>().ok()).collect()
                }
            ))
            .filter(|(_, values)| values.len() == 2)
            .fold(HashMap::new(), |mut acc, (coord, values)| {
                acc.insert(coord, values);
                acc
            });

        let (xstart, xend) = parts.get(&"x")
            .map(|v| (v[0], v[1]))
            .unwrap_or((0, 0));

        let (ystart, yend) = parts.get(&"y")
            .map(|v| (v[0], v[1]))
            .unwrap_or((0, 0));

        (xstart..xend + 1)
        .flat_map(move |x| (ystart..yend + 1).map(move |y| (x as isize, y as isize)))
    })
    .collect()
}

fn fill_water(source: Point, map: &DepthMap) -> (DepthMap, DepthMap) {
    let miny = map.iter().cloned().map(|(_, y)| y).min().unwrap_or(source.1);
    let maxy = map.iter().cloned().map(|(_, y)| y).max().unwrap_or(source.1);

    let mut water = DepthMap::new();
    let mut flows = DepthMap::new();
    let mut blocked = map.clone();

    fn flows_down((x, y): Point, blocked: &DepthMap) -> bool {
        !blocked.contains(&(x, y + 1))
    }

    fn inner(
        source: Point,
        map: &DepthMap,
        water: &mut DepthMap,
        flows: &mut DepthMap,
        blocked: &mut DepthMap,
        miny: isize,
        maxy: isize
    ) {
        let (sx, sy) = source;

        if water.contains(&source) {
            return;
        }

        let (ax, ay) = (sy..maxy + 1)
            .map(|y| (sx, y))
            .find(|&p| !flows_down(p, &blocked))
            .unwrap_or((sx, maxy));

        let infinite = ay == maxy;

        let ((lx, ly), (rx, ry)) = {
            let left = (0..)
                .map(|x| (ax - x, ay))
                .find(|&(x, y)| {
                    blocked.contains(&(x - 1, y))
                    || flows_down((x, y), &blocked)
                })
                .unwrap();

            let right = (0..)
                .map(|x| (ax + x, ay))
                .find(|&(x, y)| {
                    blocked.contains(&(x + 1, y))
                    || flows_down((x, y), &blocked)
                })
                .unwrap();

            (left, right)
        };

        // Update flows & water

        let left_overflow = flows_down((lx, ly), &blocked);
        let right_overflow = flows_down((rx, ry), &blocked);
        let overflow = left_overflow || right_overflow;
        let top = (lx..rx + 1).map(|x| (x, ay)).collect::<DepthMap>();
        let old_flow_count = flows.len();

        if !overflow {
            *water = water.union(&top).cloned().collect();
            *blocked = blocked.union(&top).cloned().collect();
        } else {
            *flows = flows
                .union(&top)
                .cloned()
                .chain(
                    if !flows.contains(&(sx, sy + 1)) {
                        (max(sy, miny)..ay + 1)
                    } else {
                        (0..0)
                    }
                    .map(|y| (sx, y))
                )
                .collect();

            if old_flow_count == flows.len() {
                return;
            }
        }

        // Propagate

        let (left_source, right_source) = (
            left_overflow && (lx, ly) != (ax, ay),
            right_overflow && (rx, ry) != (ax, ay)
        );

        if left_source {
            inner((lx, ly), map, water, flows, blocked, miny, maxy);
        }

        if right_source {
            inner((rx, ry), map, water, flows, blocked, miny, maxy);
        }

        if !infinite {
            inner(source, map, water, flows, blocked, miny, maxy);
        }
    }

    inner(source, map, &mut water, &mut flows, &mut blocked, miny, maxy);

    (water, flows)
}

fn main() {
    let input = get_input().unwrap();
    let depth_map = parse(&input);
    let (water, flows) = fill_water((500, 0), &depth_map);

    println!("Part 1: {}", water.union(&flows).count());
    println!("Part 2: {}", water.len());
}
<|endoftext|>


<commit_before>use anyhow::*;
use rocket;
use rocket::config::{Environment, LoggingLevel};
use rocket_contrib::serve::StaticFiles;
use std::path::PathBuf;
use std::sync::Arc;

use super::api;
use crate::db::DB;
use crate::index::CommandSender;

pub fn get_server(
	port: u16,
	auth_secret: &[u8],
	api_url: &str,
	web_url: &str,
	web_dir_path: &PathBuf,
	swagger_url: &str,
	swagger_dir_path: &PathBuf,
	db: DB,
	command_sender: Arc<CommandSender>,
) -> Result<rocket::Rocket> {
	let mut config = rocket::Config::build(Environment::Production)
		.log_level(LoggingLevel::Normal)
		.port(port)
		.keep_alive(0)
		.finalize()?;

	let encoded = base64::encode(auth_secret);
	config.set_secret_key(encoded)?;

	let swagger_routes_rank = 0;
	let web_routes_rank = swagger_routes_rank + 1;

	Ok(rocket::custom(config)
		.manage(db)
		.manage(command_sender)
		.mount(&api_url, api::get_routes())
		.mount(
			&swagger_url,
			StaticFiles::from(swagger_dir_path).rank(swagger_routes_rank),
		)
		.mount(
			&web_url,
			StaticFiles::from(web_dir_path).rank(web_routes_rank),
		))
}

pub fn run(
	port: u16,
	auth_secret: &[u8],
	api_url: String,
	web_url: String,
	web_dir_path: PathBuf,
	swagger_url: String,
	swagger_dir_path: PathBuf,
	db: DB,
	command_sender: Arc<CommandSender>,
) -> Result<()> {
	let server = get_server(
		port,
		auth_secret,
		&api_url,
		&web_url,
		&web_dir_path,
		&swagger_url,
		&swagger_dir_path,
		db,
		command_sender,
	)?;
	std::thread::spawn(move || {
		server.launch();
	});
	Ok(())
}
<commit_msg>Added TODO<commit_after>use anyhow::*;
use rocket;
use rocket::config::{Environment, LoggingLevel};
use rocket_contrib::serve::StaticFiles;
use std::path::PathBuf;
use std::sync::Arc;

use super::api;
use crate::db::DB;
use crate::index::CommandSender;

pub fn get_server(
	port: u16,
	auth_secret: &[u8],
	api_url: &str,
	web_url: &str,
	web_dir_path: &PathBuf,
	swagger_url: &str,
	swagger_dir_path: &PathBuf,
	db: DB,
	command_sender: Arc<CommandSender>,
) -> Result<rocket::Rocket> {
	let mut config = rocket::Config::build(Environment::Production)
		.log_level(LoggingLevel::Normal)
		.port(port)
		.keep_alive(0)
		.finalize()?;

	let encoded = base64::encode(auth_secret);
	config.set_secret_key(encoded)?;

	let swagger_routes_rank = 0;
	let web_routes_rank = swagger_routes_rank + 1;

	Ok(rocket::custom(config)
		.manage(db)
		.manage(command_sender)
		.mount(&api_url, api::get_routes())
		.mount(
			&swagger_url,
			StaticFiles::from(swagger_dir_path).rank(swagger_routes_rank),
		)
		.mount(
			&web_url,
			StaticFiles::from(web_dir_path).rank(web_routes_rank),
		))
}

pub fn run(
	port: u16,
	auth_secret: &[u8],
	api_url: String,
	web_url: String,
	web_dir_path: PathBuf,
	swagger_url: String,
	swagger_dir_path: PathBuf,
	db: DB,
	command_sender: Arc<CommandSender>,
) -> Result<()> {
	let server = get_server(
		port,
		auth_secret,
		&api_url,
		&web_url,
		&web_dir_path,
		&swagger_url,
		&swagger_dir_path,
		db,
		command_sender,
	)?;
	// TODO do this in main
	std::thread::spawn(move || {
		server.launch();
	});
	Ok(())
}
<|endoftext|>


<commit_before>// Copyright 2019 Joe Wilm, The Alacritty Project Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::cmp::max;
use std::path::PathBuf;

use clap::{crate_authors, crate_description, crate_name, crate_version, App, Arg};
use log::{self, LevelFilter};

use alacritty_terminal::config::{Delta, Dimensions, Shell, DEFAULT_NAME};
use alacritty_terminal::index::{Column, Line};

use crate::config::Config;

/// Options specified on the command line
pub struct Options {
    pub live_config_reload: Option<bool>,
    pub print_events: bool,
    pub ref_test: bool,
    pub dimensions: Option<Dimensions>,
    pub position: Option<Delta<i32>>,
    pub title: Option<String>,
    pub class: Option<String>,
    pub embed: Option<String>,
    pub log_level: LevelFilter,
    pub command: Option<Shell<'static>>,
    pub hold: bool,
    pub working_dir: Option<PathBuf>,
    pub config: Option<PathBuf>,
    pub persistent_logging: bool,
}

impl Default for Options {
    fn default() -> Options {
        Options {
            live_config_reload: None,
            print_events: false,
            ref_test: false,
            dimensions: None,
            position: None,
            title: None,
            class: None,
            embed: None,
            log_level: LevelFilter::Warn,
            command: None,
            hold: false,
            working_dir: None,
            config: None,
            persistent_logging: false,
        }
    }
}

impl Options {
    /// Build `Options` from command line arguments.
    pub fn new() -> Self {
        let mut version = crate_version!().to_owned();
        let commit_hash = env!("GIT_HASH");
        if !commit_hash.is_empty() {
            version = format!("{} ({})", version, commit_hash);
        }

        let mut options = Options::default();

        let matches = App::new(crate_name!())
            .version(version.as_str())
            .author(crate_authors!("\n"))
            .about(crate_description!())
            .arg(Arg::with_name("ref-test").long("ref-test").help("Generates ref test"))
            .arg(
                Arg::with_name("live-config-reload")
                    .long("live-config-reload")
                    .help("Enable automatic config reloading"),
            )
            .arg(
                Arg::with_name("no-live-config-reload")
                    .long("no-live-config-reload")
                    .help("Disable automatic config reloading")
                    .conflicts_with("live-config-reload"),
            )
            .arg(
                Arg::with_name("print-events")
                    .long("print-events")
                    .help("Print all events to stdout"),
            )
            .arg(
                Arg::with_name("persistent-logging")
                    .long("persistent-logging")
                    .help("Keep the log file after quitting Alacritty"),
            )
            .arg(
                Arg::with_name("dimensions")
                    .long("dimensions")
                    .short("d")
                    .value_names(&["columns", "lines"])
                    .help(
                        "Defines the window dimensions. Falls back to size specified by window \
                         manager if set to 0x0 [default: 0x0]",
                    ),
            )
            .arg(
                Arg::with_name("position")
                    .long("position")
                    .allow_hyphen_values(true)
                    .value_names(&["x-pos", "y-pos"])
                    .help(
                        "Defines the window position. Falls back to position specified by window \
                         manager if unset [default: unset]",
                    ),
            )
            .arg(
                Arg::with_name("title")
                    .long("title")
                    .short("t")
                    .takes_value(true)
                    .help(&format!("Defines the window title [default: {}]", DEFAULT_NAME)),
            )
            .arg(
                Arg::with_name("class")
                    .long("class")
                    .takes_value(true)
                    .help(&format!("Defines window class on Linux [default: {}]", DEFAULT_NAME)),
            )
            .arg(
                Arg::with_name("embed").long("embed").takes_value(true).help(
                    "Defines the X11 window ID (as a decimal integer) to embed Alacritty within",
                ),
            )
            .arg(
                Arg::with_name("q")
                    .short("q")
                    .multiple(true)
                    .conflicts_with("v")
                    .help("Reduces the level of verbosity (the min level is -qq)"),
            )
            .arg(
                Arg::with_name("v")
                    .short("v")
                    .multiple(true)
                    .conflicts_with("q")
                    .help("Increases the level of verbosity (the max level is -vvv)"),
            )
            .arg(
                Arg::with_name("working-directory")
                    .long("working-directory")
                    .takes_value(true)
                    .help("Start the shell in the specified working directory"),
            )
            .arg(Arg::with_name("config-file").long("config-file").takes_value(true).help(
                "Specify alternative configuration file [default: \
                 $XDG_CONFIG_HOME/alacritty/alacritty.yml]",
            ))
            .arg(
                Arg::with_name("command")
                    .long("command")
                    .short("e")
                    .multiple(true)
                    .takes_value(true)
                    .min_values(1)
                    .allow_hyphen_values(true)
                    .help("Command and args to execute (must be last argument)"),
            )
            .arg(Arg::with_name("hold").long("hold").help("Remain open after child process exits"))
            .get_matches();

        if matches.is_present("ref-test") {
            options.ref_test = true;
        }

        if matches.is_present("print-events") {
            options.print_events = true;
        }

        if matches.is_present("live-config-reload") {
            options.live_config_reload = Some(true);
        } else if matches.is_present("no-live-config-reload") {
            options.live_config_reload = Some(false);
        }

        if matches.is_present("persistent-logging") {
            options.persistent_logging = true;
        }

        if let Some(mut dimensions) = matches.values_of("dimensions") {
            let width = dimensions.next().map(|w| w.parse().map(Column));
            let height = dimensions.next().map(|h| h.parse().map(Line));
            if let (Some(Ok(width)), Some(Ok(height))) = (width, height) {
                options.dimensions = Some(Dimensions::new(width, height));
            }
        }

        if let Some(mut position) = matches.values_of("position") {
            let x = position.next().map(str::parse);
            let y = position.next().map(str::parse);
            if let (Some(Ok(x)), Some(Ok(y))) = (x, y) {
                options.position = Some(Delta { x, y });
            }
        }

        options.class = matches.value_of("class").map(ToOwned::to_owned);
        options.title = matches.value_of("title").map(ToOwned::to_owned);
        options.embed = matches.value_of("embed").map(ToOwned::to_owned);

        match matches.occurrences_of("q") {
            0 => {},
            1 => options.log_level = LevelFilter::Error,
            2 | _ => options.log_level = LevelFilter::Off,
        }

        match matches.occurrences_of("v") {
            0 if !options.print_events => options.log_level = LevelFilter::Warn,
            0 | 1 => options.log_level = LevelFilter::Info,
            2 => options.log_level = LevelFilter::Debug,
            3 | _ => options.log_level = LevelFilter::Trace,
        }

        if let Some(dir) = matches.value_of("working-directory") {
            options.working_dir = Some(PathBuf::from(dir.to_string()));
        }

        if let Some(path) = matches.value_of("config-file") {
            options.config = Some(PathBuf::from(path.to_string()));
        }

        if let Some(mut args) = matches.values_of("command") {
            // The following unwrap is guaranteed to succeed.
            // If 'command' exists it must also have a first item since
            // Arg::min_values(1) is set.
            let command = String::from(args.next().unwrap());
            let args = args.map(String::from).collect();
            options.command = Some(Shell::new_with_args(command, args));
        }

        if matches.is_present("hold") {
            options.hold = true;
        }

        options
    }

    pub fn config_path(&self) -> Option<PathBuf> {
        self.config.clone()
    }

    pub fn into_config(self, mut config: Config) -> Config {
        config.set_live_config_reload(
            self.live_config_reload.unwrap_or_else(|| config.live_config_reload()),
        );
        config.set_working_directory(
            self.working_dir.or_else(|| config.working_directory().to_owned()),
        );
        config.shell = self.command.or(config.shell);

        config.hold = self.hold;

        config.window.dimensions = self.dimensions.unwrap_or(config.window.dimensions);
        config.window.position = self.position.or(config.window.position);
        config.window.embed = self.embed.and_then(|embed| embed.parse().ok());

        if let Some(title) = self.title {
            config.window.title = title.clone();
        }

        if let Some(class) = self.class {
            let parts: Vec<_> = class.split(',').collect();
            config.window.class.instance = parts[0].into();
            if let Some(&general) = parts.get(1) {
                config.window.class.general = general.into();
            }
        }

        config.set_dynamic_title(config.dynamic_title() && config.window.title == DEFAULT_NAME);

        config.debug.print_events = self.print_events || config.debug.print_events;
        config.debug.log_level = max(config.debug.log_level, self.log_level);
        config.debug.ref_test = self.ref_test || config.debug.ref_test;

        if config.debug.print_events {
            config.debug.log_level = max(config.debug.log_level, LevelFilter::Info);
        }

        config
    }
}

#[cfg(test)]
mod test {
    use crate::cli::Options;
    use crate::config::Config;

    #[test]
    fn dynamic_title_ignoring_options_by_default() {
        let config = Config::default();
        let old_dynamic_title = config.dynamic_title();

        let config = Options::default().into_config(config);

        assert_eq!(old_dynamic_title, config.dynamic_title());
    }

    #[test]
    fn dynamic_title_overridden_by_options() {
        let config = Config::default();

        let mut options = Options::default();
        options.title = Some("foo".to_owned());
        let config = options.into_config(config);

        assert!(!config.dynamic_title());
    }

    #[test]
    fn dynamic_title_overridden_by_config() {
        let mut config = Config::default();

        config.window.title = "foo".to_owned();
        let config = Options::default().into_config(config);

        assert!(!config.dynamic_title());
    }
}
<commit_msg>Fix setting persistent logging via CLI<commit_after>// Copyright 2019 Joe Wilm, The Alacritty Project Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::cmp::max;
use std::path::PathBuf;

use clap::{crate_authors, crate_description, crate_name, crate_version, App, Arg};
use log::{self, LevelFilter};

use alacritty_terminal::config::{Delta, Dimensions, Shell, DEFAULT_NAME};
use alacritty_terminal::index::{Column, Line};

use crate::config::Config;

/// Options specified on the command line
pub struct Options {
    pub live_config_reload: Option<bool>,
    pub print_events: bool,
    pub ref_test: bool,
    pub dimensions: Option<Dimensions>,
    pub position: Option<Delta<i32>>,
    pub title: Option<String>,
    pub class: Option<String>,
    pub embed: Option<String>,
    pub log_level: LevelFilter,
    pub command: Option<Shell<'static>>,
    pub hold: bool,
    pub working_dir: Option<PathBuf>,
    pub config: Option<PathBuf>,
    pub persistent_logging: bool,
}

impl Default for Options {
    fn default() -> Options {
        Options {
            live_config_reload: None,
            print_events: false,
            ref_test: false,
            dimensions: None,
            position: None,
            title: None,
            class: None,
            embed: None,
            log_level: LevelFilter::Warn,
            command: None,
            hold: false,
            working_dir: None,
            config: None,
            persistent_logging: false,
        }
    }
}

impl Options {
    /// Build `Options` from command line arguments.
    pub fn new() -> Self {
        let mut version = crate_version!().to_owned();
        let commit_hash = env!("GIT_HASH");
        if !commit_hash.is_empty() {
            version = format!("{} ({})", version, commit_hash);
        }

        let mut options = Options::default();

        let matches = App::new(crate_name!())
            .version(version.as_str())
            .author(crate_authors!("\n"))
            .about(crate_description!())
            .arg(Arg::with_name("ref-test").long("ref-test").help("Generates ref test"))
            .arg(
                Arg::with_name("live-config-reload")
                    .long("live-config-reload")
                    .help("Enable automatic config reloading"),
            )
            .arg(
                Arg::with_name("no-live-config-reload")
                    .long("no-live-config-reload")
                    .help("Disable automatic config reloading")
                    .conflicts_with("live-config-reload"),
            )
            .arg(
                Arg::with_name("print-events")
                    .long("print-events")
                    .help("Print all events to stdout"),
            )
            .arg(
                Arg::with_name("persistent-logging")
                    .long("persistent-logging")
                    .help("Keep the log file after quitting Alacritty"),
            )
            .arg(
                Arg::with_name("dimensions")
                    .long("dimensions")
                    .short("d")
                    .value_names(&["columns", "lines"])
                    .help(
                        "Defines the window dimensions. Falls back to size specified by window \
                         manager if set to 0x0 [default: 0x0]",
                    ),
            )
            .arg(
                Arg::with_name("position")
                    .long("position")
                    .allow_hyphen_values(true)
                    .value_names(&["x-pos", "y-pos"])
                    .help(
                        "Defines the window position. Falls back to position specified by window \
                         manager if unset [default: unset]",
                    ),
            )
            .arg(
                Arg::with_name("title")
                    .long("title")
                    .short("t")
                    .takes_value(true)
                    .help(&format!("Defines the window title [default: {}]", DEFAULT_NAME)),
            )
            .arg(
                Arg::with_name("class")
                    .long("class")
                    .takes_value(true)
                    .help(&format!("Defines window class on Linux [default: {}]", DEFAULT_NAME)),
            )
            .arg(
                Arg::with_name("embed").long("embed").takes_value(true).help(
                    "Defines the X11 window ID (as a decimal integer) to embed Alacritty within",
                ),
            )
            .arg(
                Arg::with_name("q")
                    .short("q")
                    .multiple(true)
                    .conflicts_with("v")
                    .help("Reduces the level of verbosity (the min level is -qq)"),
            )
            .arg(
                Arg::with_name("v")
                    .short("v")
                    .multiple(true)
                    .conflicts_with("q")
                    .help("Increases the level of verbosity (the max level is -vvv)"),
            )
            .arg(
                Arg::with_name("working-directory")
                    .long("working-directory")
                    .takes_value(true)
                    .help("Start the shell in the specified working directory"),
            )
            .arg(Arg::with_name("config-file").long("config-file").takes_value(true).help(
                "Specify alternative configuration file [default: \
                 $XDG_CONFIG_HOME/alacritty/alacritty.yml]",
            ))
            .arg(
                Arg::with_name("command")
                    .long("command")
                    .short("e")
                    .multiple(true)
                    .takes_value(true)
                    .min_values(1)
                    .allow_hyphen_values(true)
                    .help("Command and args to execute (must be last argument)"),
            )
            .arg(Arg::with_name("hold").long("hold").help("Remain open after child process exits"))
            .get_matches();

        if matches.is_present("ref-test") {
            options.ref_test = true;
        }

        if matches.is_present("print-events") {
            options.print_events = true;
        }

        if matches.is_present("live-config-reload") {
            options.live_config_reload = Some(true);
        } else if matches.is_present("no-live-config-reload") {
            options.live_config_reload = Some(false);
        }

        if matches.is_present("persistent-logging") {
            options.persistent_logging = true;
        }

        if let Some(mut dimensions) = matches.values_of("dimensions") {
            let width = dimensions.next().map(|w| w.parse().map(Column));
            let height = dimensions.next().map(|h| h.parse().map(Line));
            if let (Some(Ok(width)), Some(Ok(height))) = (width, height) {
                options.dimensions = Some(Dimensions::new(width, height));
            }
        }

        if let Some(mut position) = matches.values_of("position") {
            let x = position.next().map(str::parse);
            let y = position.next().map(str::parse);
            if let (Some(Ok(x)), Some(Ok(y))) = (x, y) {
                options.position = Some(Delta { x, y });
            }
        }

        options.class = matches.value_of("class").map(ToOwned::to_owned);
        options.title = matches.value_of("title").map(ToOwned::to_owned);
        options.embed = matches.value_of("embed").map(ToOwned::to_owned);

        match matches.occurrences_of("q") {
            0 => {},
            1 => options.log_level = LevelFilter::Error,
            2 | _ => options.log_level = LevelFilter::Off,
        }

        match matches.occurrences_of("v") {
            0 if !options.print_events => options.log_level = LevelFilter::Warn,
            0 | 1 => options.log_level = LevelFilter::Info,
            2 => options.log_level = LevelFilter::Debug,
            3 | _ => options.log_level = LevelFilter::Trace,
        }

        if let Some(dir) = matches.value_of("working-directory") {
            options.working_dir = Some(PathBuf::from(dir.to_string()));
        }

        if let Some(path) = matches.value_of("config-file") {
            options.config = Some(PathBuf::from(path.to_string()));
        }

        if let Some(mut args) = matches.values_of("command") {
            // The following unwrap is guaranteed to succeed.
            // If 'command' exists it must also have a first item since
            // Arg::min_values(1) is set.
            let command = String::from(args.next().unwrap());
            let args = args.map(String::from).collect();
            options.command = Some(Shell::new_with_args(command, args));
        }

        if matches.is_present("hold") {
            options.hold = true;
        }

        options
    }

    pub fn config_path(&self) -> Option<PathBuf> {
        self.config.clone()
    }

    pub fn into_config(self, mut config: Config) -> Config {
        config.set_live_config_reload(
            self.live_config_reload.unwrap_or_else(|| config.live_config_reload()),
        );
        config.set_working_directory(
            self.working_dir.or_else(|| config.working_directory().to_owned()),
        );
        config.shell = self.command.or(config.shell);

        config.hold = self.hold;

        config.window.dimensions = self.dimensions.unwrap_or(config.window.dimensions);
        config.window.position = self.position.or(config.window.position);
        config.window.embed = self.embed.and_then(|embed| embed.parse().ok());

        if let Some(title) = self.title {
            config.window.title = title.clone();
        }

        if let Some(class) = self.class {
            let parts: Vec<_> = class.split(',').collect();
            config.window.class.instance = parts[0].into();
            if let Some(&general) = parts.get(1) {
                config.window.class.general = general.into();
            }
        }

        config.set_dynamic_title(config.dynamic_title() && config.window.title == DEFAULT_NAME);

        config.debug.print_events = self.print_events || config.debug.print_events;
        config.debug.log_level = max(config.debug.log_level, self.log_level);
        config.debug.ref_test = self.ref_test || config.debug.ref_test;
        config.debug.persistent_logging =
            self.persistent_logging || config.debug.persistent_logging;

        if config.debug.print_events {
            config.debug.log_level = max(config.debug.log_level, LevelFilter::Info);
        }

        config
    }
}

#[cfg(test)]
mod test {
    use crate::cli::Options;
    use crate::config::Config;

    #[test]
    fn dynamic_title_ignoring_options_by_default() {
        let config = Config::default();
        let old_dynamic_title = config.dynamic_title();

        let config = Options::default().into_config(config);

        assert_eq!(old_dynamic_title, config.dynamic_title());
    }

    #[test]
    fn dynamic_title_overridden_by_options() {
        let config = Config::default();

        let mut options = Options::default();
        options.title = Some("foo".to_owned());
        let config = options.into_config(config);

        assert!(!config.dynamic_title());
    }

    #[test]
    fn dynamic_title_overridden_by_config() {
        let mut config = Config::default();

        config.window.title = "foo".to_owned();
        let config = Options::default().into_config(config);

        assert!(!config.dynamic_title());
    }
}
<|endoftext|>


<commit_before>use std::iter;
use super::stacks_and_queues::bag::{Bag, Iter};
use super::stacks_and_queues::Stack;
use super::stacks_and_queues::linked_stack;

#[derive(Clone, Debug)]
pub struct Graph {
    v: usize,
    e: usize,
    adj: Vec<Bag<usize>>
}

impl Graph {
    pub fn new(v: usize) -> Graph {
        Graph {
            v: v,
            e: 0,
            adj: iter::repeat(Bag::<usize>::new()).take(v).collect()
        }
    }

    fn validate_vertex(&self, v: usize) {
        assert!(v < self.v, "vertex is not between 0 and {}", self.v - 1)
    }

    pub fn vertices(&self) -> usize {
        self.v
    }

    pub fn edges(&self) -> usize {
        self.e
    }

    pub fn add_edge(&mut self, v: usize, w: usize) {
        self.validate_vertex(v);
        self.validate_vertex(w);

        self.e += 1;
        self.adj[v].add(w);
        self.adj[w].add(v);
    }

    // FIXME: should this be a global function
    pub fn degree(&self, v: usize) -> usize {
        self.validate_vertex(v);
        self.adj[v].len()
    }

    pub fn max_degree(&self) -> usize {
        (0 .. self.vertices()).map(|v| self.degree(v)).max().unwrap_or(0)
    }

    pub fn average_degree(&self) -> f64 {
        // (0 .. self.vertices()) .map(|v| self.degree(v)).sum::<usize>() as f64 / self.vertices() as f64
        2.0 * self.edges() as f64 / self.vertices() as f64
    }

    pub fn number_of_self_loops(&self) -> usize {
        let mut count = 0;
        for v in 0 .. self.vertices() {
            for w in self.adj(v) {
                if v == *w {
                    count += 1;
                }
            }
        }
        count / 2
    }

    pub fn to_dot(&self) -> String {
        let mut dot = String::new();

        dot.push_str("graph G {\n");
        for i in 0 .. self.v {
            dot.push_str(&format!("  {};\n", i));
        }

        for (v, adj) in self.adj.iter().enumerate() {
            for w in adj.iter() {
                dot.push_str(&format!("  {} -- {};\n", v, w));
            }
        }
        dot.push_str("}\n");
        dot
    }

    pub fn adj(&self, v: usize) -> Iter<usize> {
        self.adj[v].iter()
    }

    pub fn dfs<'a>(&'a self, s: usize) -> DepthFirstPaths<'a> {
        let marked = iter::repeat(false).take(self.vertices()).collect();
        let edge_to = iter::repeat(None).take(self.vertices()).collect();
        let mut path = DepthFirstPaths {
            graph: self,
            marked: marked,
            edge_to: edge_to,
            s: s
        };
        let s = path.s.clone();

        path.dfs(s);
        path
    }
}

pub struct DepthFirstPaths<'a> {
    graph: &'a Graph,
    marked: Vec<bool>,
    edge_to: Vec<Option<usize>>,
    s: usize
}

impl<'a> DepthFirstPaths<'a> {
    pub fn dfs(&mut self, v: usize) {
        self.marked[v] = true;
        for w in self.graph.adj(v) {
            if !self.marked[*w] {
                self.dfs(*w);
                self.edge_to[*w] = Some(v);
            }
        }
    }

    pub fn has_path_to(&self, v: usize) -> bool {
        self.marked[v]
    }

    pub fn path_to(&self, v: usize) -> Option<Vec<usize>> {
        if !self.has_path_to(v) {
            None
        } else {
            let mut path = linked_stack::LinkedStack::new();
            let mut x = v;
            while x != self.s {
                path.push(x);
                x = self.edge_to[x].unwrap();
            }
            path.push(self.s);
            Some(path.into_iter().collect())
        }
    }
}

#[test]
fn test_graph_visit() {
    let mut g = Graph::new(13);
    g.add_edge(0, 1);
    g.add_edge(0, 2);
    g.add_edge(0, 6);
    g.add_edge(0, 5);
    g.add_edge(5, 3);
    g.add_edge(5, 4);
    g.add_edge(3, 4);
    g.add_edge(4, 6);

    g.add_edge(7, 8);

    g.add_edge(9, 10);
    g.add_edge(9, 11);
    g.add_edge(9, 12);
    g.add_edge(11, 12);

    println!("dot => \n {}", g.to_dot());
    let path = g.dfs(0);
    println!("got path=> {:?}", path.edge_to);
    println!("path to 3 => {:?}", path.path_to(3));

}

#[test]
fn test_graph() {
    let mut g = Graph::new(10);
    g.add_edge(0, 3);
    g.add_edge(0, 5);
    g.add_edge(4, 5);
    g.add_edge(2, 9);
    g.add_edge(2, 8);
    g.add_edge(3, 7);

    g.add_edge(1, 6);
    g.add_edge(6, 9);
    g.add_edge(5, 8);

    // println!("got => \n{}", g.to_dot());

    assert_eq!(10, g.vertices());
    assert_eq!(9, g.edges());
    assert_eq!(3, g.degree(5));

    for w in g.adj(5) {
        assert!(vec![8, 4, 0].contains(w));
    }

    assert_eq!(g.max_degree(), 3);
    assert!(g.average_degree() < 2.0);
    assert_eq!(g.number_of_self_loops(), 0);
}
<commit_msg>undirected_graphs: add test case for graph functions<commit_after>use std::iter;
use super::stacks_and_queues::bag::{Bag, Iter};
use super::stacks_and_queues::Stack;
use super::stacks_and_queues::linked_stack;

#[derive(Clone, Debug)]
pub struct Graph {
    v: usize,
    e: usize,
    adj: Vec<Bag<usize>>
}

impl Graph {
    pub fn new(v: usize) -> Graph {
        Graph {
            v: v,
            e: 0,
            adj: iter::repeat(Bag::<usize>::new()).take(v).collect()
        }
    }

    fn validate_vertex(&self, v: usize) {
        assert!(v < self.v, "vertex is not between 0 and {}", self.v - 1)
    }

    pub fn vertices(&self) -> usize {
        self.v
    }

    pub fn edges(&self) -> usize {
        self.e
    }

    pub fn add_edge(&mut self, v: usize, w: usize) {
        self.validate_vertex(v);
        self.validate_vertex(w);

        self.e += 1;
        self.adj[v].add(w);
        self.adj[w].add(v);
    }

    // FIXME: should this be a global function
    pub fn degree(&self, v: usize) -> usize {
        self.validate_vertex(v);
        self.adj[v].len()
    }

    pub fn max_degree(&self) -> usize {
        (0 .. self.vertices()).map(|v| self.degree(v)).max().unwrap_or(0)
    }

    pub fn average_degree(&self) -> f64 {
        // (0 .. self.vertices()) .map(|v| self.degree(v)).sum::<usize>() as f64 / self.vertices() as f64
        2.0 * self.edges() as f64 / self.vertices() as f64
    }

    pub fn number_of_self_loops(&self) -> usize {
        let mut count = 0;
        for v in 0 .. self.vertices() {
            for w in self.adj(v) {
                if v == *w {
                    count += 1;
                }
            }
        }
        count / 2
    }

    pub fn to_dot(&self) -> String {
        let mut dot = String::new();

        dot.push_str("graph G {\n");
        for i in 0 .. self.v {
            dot.push_str(&format!("  {};\n", i));
        }

        for (v, adj) in self.adj.iter().enumerate() {
            for w in adj.iter() {
                dot.push_str(&format!("  {} -- {};\n", v, w));
            }
        }
        dot.push_str("}\n");
        dot
    }

    pub fn adj(&self, v: usize) -> Iter<usize> {
        self.adj[v].iter()
    }

    pub fn dfs<'a>(&'a self, s: usize) -> DepthFirstPaths<'a> {
        let marked = iter::repeat(false).take(self.vertices()).collect();
        let edge_to = iter::repeat(None).take(self.vertices()).collect();
        let mut path = DepthFirstPaths {
            graph: self,
            marked: marked,
            edge_to: edge_to,
            s: s
        };
        let s = path.s.clone();

        path.dfs(s);
        path
    }
}

pub struct DepthFirstPaths<'a> {
    graph: &'a Graph,
    marked: Vec<bool>,
    edge_to: Vec<Option<usize>>,
    s: usize
}

impl<'a> DepthFirstPaths<'a> {
    pub fn dfs(&mut self, v: usize) {
        self.marked[v] = true;
        for w in self.graph.adj(v) {
            if !self.marked[*w] {
                self.dfs(*w);
                self.edge_to[*w] = Some(v);
            }
        }
    }

    pub fn has_path_to(&self, v: usize) -> bool {
        self.marked[v]
    }

    pub fn path_to(&self, v: usize) -> Option<Vec<usize>> {
        if !self.has_path_to(v) {
            None
        } else {
            let mut path = linked_stack::LinkedStack::new();
            let mut x = v;
            while x != self.s {
                path.push(x);
                x = self.edge_to[x].unwrap();
            }
            path.push(self.s);
            Some(path.into_iter().collect())
        }
    }
}

#[test]
fn test_graph_visit() {
    let mut g = Graph::new(13);
    g.add_edge(0, 1);
    g.add_edge(0, 2);
    g.add_edge(0, 6);
    g.add_edge(0, 5);
    g.add_edge(5, 3);
    g.add_edge(5, 4);
    g.add_edge(3, 4);
    g.add_edge(4, 6);

    g.add_edge(7, 8);

    g.add_edge(9, 10);
    g.add_edge(9, 11);
    g.add_edge(9, 12);
    g.add_edge(11, 12);

    println!("dot => \n {}", g.to_dot());
    let path = g.dfs(0);
    assert!(path.path_to(3).is_some());

}

#[test]
fn test_graph() {
    let mut g = Graph::new(10);
    g.add_edge(0, 3);
    g.add_edge(0, 5);
    g.add_edge(4, 5);
    g.add_edge(2, 9);
    g.add_edge(2, 8);
    g.add_edge(3, 7);

    g.add_edge(1, 6);
    g.add_edge(6, 9);
    g.add_edge(5, 8);

    // println!("got => \n{}", g.to_dot());

    assert_eq!(10, g.vertices());
    assert_eq!(9, g.edges());
    assert_eq!(3, g.degree(5));

    for w in g.adj(5) {
        assert!(vec![8, 4, 0].contains(w));
    }

    assert_eq!(g.max_degree(), 3);
    assert!(g.average_degree() < 2.0);
    assert_eq!(g.number_of_self_loops(), 0);
}

#[test]
fn test_graph_functions() {
    let mut g = Graph::new(5);
    for i in 0 .. 5 {
        for j in 0 .. 5 {
            g.add_edge(i, j);
        }
    }

    assert_eq!(10, g.max_degree());
    assert_eq!(5, g.number_of_self_loops());
}
<|endoftext|>


<commit_before>use crate::controls;

pub mod imp;

pub mod adapter {
	pub use crate::inner::adapter::{Node, Change};
}

pub use crate::inner::{
    auto::{AsAny, Spawnable},
    adapter::{Adapter},
};

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum Visibility {
    Visible,
    Invisible,
    Gone,
}
impl Default for Visibility {
    fn default() -> Self {
        Visibility::Visible
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum WindowStartSize {
    Exact(u16, u16),
    Fullscreen,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Progress {
    Value(u32, u32),
    Undefined,
    None,
}
impl Default for Progress {
    fn default() -> Self {
        Progress::Undefined
    }
}

pub type Menu = Option<Vec<MenuItem>>;

#[derive(Debug, PartialEq)]
pub enum MenuItem {
    Action(String, crate::callbacks::Action, MenuItemRole),
    Delimiter,
    Sub(String, Vec<MenuItem>, MenuItemRole),
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MenuItemRole {
    None,
    Options,
    Help,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MessageSeverity {
    Info,
    Warning,
    Alert,
}

#[derive(Debug, Clone, PartialEq)]
pub enum TextContent {
    Plain(String),
    LabelDescription(String, String),
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ImageScalePolicy {
    CropCenter, // TODO variants
    FitCenter,  // TODO variants
                // TODO Tile
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum FindBy<'a> {
    Id(crate::ids::Id),
    Tag(&'a str),
}

#[derive(Debug, Clone)]
pub struct RecursiveHashMap<K: Sized>{ pub inner: ::std::collections::HashMap<K, Option<RecursiveHashMap<K>>> }

#[derive(Debug, Clone)]
pub struct RecursiveTupleVec<K: Sized>{ pub id: K, value: Option<Vec<RecursiveTupleVec<K>>> }

impl<K: Sized> RecursiveTupleVec<K> {
    pub fn get_mut(&mut self, indexes: &[usize]) -> Option<&mut K> {
        let mut value = self.value.as_mut();
        if let Some(ivalue) = value {
            let len = ivalue.len();
            for i in 0..indexes.len() {
                if indexes[i] < len {
                    if i == len-1 {
                        return Some(&mut ivalue[indexes[i]].id);
                    } else {
                        value = ivalue[indexes[i]].value.as_mut();
                    }
                }
            }
        }
        None
    }
}

pub enum ApplicationResult {
    New(Box<dyn controls::Application>),
    Existing(Box<dyn controls::Application>),
    ErrorNonUiThread,
    ErrorUnspecified,
}
impl ApplicationResult {
    pub fn unwrap(self) -> Box<dyn controls::Application> {
        match self {
            ApplicationResult::New(app) | ApplicationResult::Existing(app) => app,
            ApplicationResult::ErrorNonUiThread => panic!("Application requested from non-UI thread"),
            ApplicationResult::ErrorUnspecified => panic!("Error getting Application"),
        }
    }
}
<commit_msg>RecursiveTupleVec::put() looks like working<commit_after>use crate::controls;

pub mod imp;

pub mod adapter {
	pub use crate::inner::adapter::{Node, Change};
}

pub use crate::inner::{
    auto::{AsAny, Spawnable},
    adapter::{Adapter},
};

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum Visibility {
    Visible,
    Invisible,
    Gone,
}
impl Default for Visibility {
    fn default() -> Self {
        Visibility::Visible
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum WindowStartSize {
    Exact(u16, u16),
    Fullscreen,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Progress {
    Value(u32, u32),
    Undefined,
    None,
}
impl Default for Progress {
    fn default() -> Self {
        Progress::Undefined
    }
}

pub type Menu = Option<Vec<MenuItem>>;

#[derive(Debug, PartialEq)]
pub enum MenuItem {
    Action(String, crate::callbacks::Action, MenuItemRole),
    Delimiter,
    Sub(String, Vec<MenuItem>, MenuItemRole),
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MenuItemRole {
    None,
    Options,
    Help,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MessageSeverity {
    Info,
    Warning,
    Alert,
}

#[derive(Debug, Clone, PartialEq)]
pub enum TextContent {
    Plain(String),
    LabelDescription(String, String),
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ImageScalePolicy {
    CropCenter, // TODO variants
    FitCenter,  // TODO variants
                // TODO Tile
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum FindBy<'a> {
    Id(crate::ids::Id),
    Tag(&'a str),
}

#[derive(Debug, Clone)]
pub struct RecursiveTupleVec<K: Sized>{ pub id: K, pub value: Option<Vec<RecursiveTupleVec<K>>> }

impl<K: Sized> RecursiveTupleVec<K> {

}

impl<K: Sized + ::std::fmt::Debug> RecursiveTupleVec<K> {
    pub fn with_value(id: K, value: Option<Vec<RecursiveTupleVec<K>>>) -> Self {
        Self { id, value }
    }
    fn put_inner<'a, 'b: 'a>(value: Option<&'a mut Vec<RecursiveTupleVec<K>>>, indexes: &'b [usize], passed: usize, mut new: Option<RecursiveTupleVec<K>>) -> Result<Option<RecursiveTupleVec<K>>, &'b [usize]> {
        println!("{}, {:?}, {:#?}", passed, indexes, value);
        if indexes.len() == (passed+1) {
            if let Some(value) = value {
                if value.len() > indexes[passed] {
                    if new.is_some() {
                        if let Some(ref mut new) = new {
                            ::std::mem::swap(new, &mut value[indexes[passed]]);
                        }
                        Ok(new)
                    } else {
                        Ok(Some(value.remove(indexes[passed])))
                    }
                } else {
                    if value.len() == indexes[passed] {
                        if new.is_some() {
                            value.push(new.unwrap());
                        }
                        Ok(None)
                    } else {// here
                        Err(indexes)
                    }
                }
            } else {
                Err(indexes)
            }
        } else if indexes.len() > (passed+1) {
            if let Some(value) = value {
                Self::put_inner(value[indexes[passed]].value.as_mut(), indexes, passed+1, new)
            } else {
                Err(&indexes[..passed])
            }
        } else {
            Err(indexes)
        }
    }
    pub fn put<'a, 'b: 'a>(&'a mut self, indexes: &'b [usize], value: Option<RecursiveTupleVec<K>>) -> Result<Option<RecursiveTupleVec<K>>, &'b [usize]> {
        Self::put_inner(self.value.as_mut(), indexes, 0, value)
    }

    fn get_mut_inner<'a, 'b: 'a>(value: Option<&'a mut Vec<RecursiveTupleVec<K>>>, indexes: &'b [usize]) -> Option<&'a mut RecursiveTupleVec<K>> {
        if let Some(ivalue) = value {
            let len = ivalue.len();
            if indexes[0] < len {
                if len <= 1 {
                    return Some(&mut ivalue[indexes[0]]);
                } else {
                    return Self::get_mut_inner(ivalue[indexes[0]].value.as_mut(), &indexes[1..]);
                }
            }
        }
        None
    }
    pub fn get_mut<'a, 'b: 'a>(&'a mut self, indexes: &'b [usize]) -> Option<&'a mut RecursiveTupleVec<K>> {
        Self::get_mut_inner(self.value.as_mut(), indexes)
    }

    fn get_inner<'a, 'b: 'a>(value: Option<&'a Vec<RecursiveTupleVec<K>>>, indexes: &'b [usize]) -> Option<&'a RecursiveTupleVec<K>> {
        if let Some(ivalue) = value {
            let len = ivalue.len();
            if indexes[0] < len {
                if len <= 1 {
                    return Some(&ivalue[indexes[0]]);
                } else {
                    return Self::get_inner(ivalue[indexes[0]].value.as_ref(), &indexes[1..]);
                }
            }
        }
        None
    }
    pub fn get<'a, 'b: 'a>(&'a self, indexes: &'b [usize]) -> Option<&'a RecursiveTupleVec<K>> {
        Self::get_inner(self.value.as_ref(), indexes)
    }
}

pub enum ApplicationResult {
    New(Box<dyn controls::Application>),
    Existing(Box<dyn controls::Application>),
    ErrorNonUiThread,
    ErrorUnspecified,
}
impl ApplicationResult {
    pub fn unwrap(self) -> Box<dyn controls::Application> {
        match self {
            ApplicationResult::New(app) | ApplicationResult::Existing(app) => app,
            ApplicationResult::ErrorNonUiThread => panic!("Application requested from non-UI thread"),
            ApplicationResult::ErrorUnspecified => panic!("Error getting Application"),
        }
    }
}
<|endoftext|>


<commit_before>use super::Result;
use event;
use mapper::{BundleMapper, Mapper, TransactionMapper, TransactionRecord};
use mysql;
use std::collections::{HashSet, VecDeque};
use std::sync::{mpsc, Arc, Mutex};
use std::thread;
use std::time::{Instant, SystemTime};
use utils::{DurationUtils, SystemTimeUtils};

#[derive(Debug)]
pub enum ApproveMessage {
  Reverse(u64),
  Front(u64, u64, f64),
}

pub struct ApproveThread<'a> {
  pub approve_rx: mpsc::Receiver<ApproveMessage>,
  pub mysql_uri: &'a str,
  pub transaction_mapper: Arc<TransactionMapper>,
  pub bundle_mapper: Arc<BundleMapper>,
}

impl<'a> ApproveThread<'a> {
  pub fn spawn(self) {
    let Self {
      approve_rx,
      mysql_uri,
      transaction_mapper,
      bundle_mapper,
    } = self;
    let mut conn =
      mysql::Conn::new(mysql_uri).expect("MySQL connection failure");
    thread::spawn(move || {
      let transaction_mapper = &*transaction_mapper;
      let bundle_mapper = &*bundle_mapper;
      loop {
        let message = approve_rx.recv().expect("Thread communication failure");
        let duration = Instant::now();
        let result = match message {
          ApproveMessage::Reverse(id) => {
            perform_reverse(&mut conn, transaction_mapper, bundle_mapper, id)
          }
          ApproveMessage::Front(id_trunk, id_branch, mst_timestamp) => {
            perform_front(
              &mut conn,
              transaction_mapper,
              bundle_mapper,
              id_trunk,
              id_branch,
              mst_timestamp,
            )
          }
        };
        let duration = duration.elapsed().as_milliseconds();
        match result {
          Ok(()) => {
            info!("{:.3}ms {:?}", duration, message);
          }
          Err(err) => {
            error!("{:.3}ms {}", duration, err);
          }
        }
      }
    });
  }
}

fn perform_reverse(
  conn: &mut mysql::Conn,
  transaction_mapper: &TransactionMapper,
  bundle_mapper: &BundleMapper,
  id: u64,
) -> Result<()> {
  let mut mst_timestamp = reference_approval(
    conn,
    transaction_mapper,
    id,
    TransactionMapper::trunk_references,
  )?;
  if mst_timestamp.is_none() {
    mst_timestamp = reference_approval(
      conn,
      transaction_mapper,
      id,
      TransactionMapper::branch_references,
    )?;
  }
  if let Some(mst_timestamp) = mst_timestamp {
    let (id_trunk, id_branch) = {
      let transaction = transaction_mapper.fetch(conn, id)?;
      let mut transaction = transaction.lock().unwrap();
      approve(
        conn,
        bundle_mapper,
        &mut transaction,
        mst_timestamp,
        SystemTime::milliseconds_since_epoch()?,
      )?;
      (transaction.id_trunk(), transaction.id_branch())
    };
    if let (Some(id_trunk), Some(id_branch)) = (id_trunk, id_branch) {
      perform_front(
        conn,
        transaction_mapper,
        bundle_mapper,
        id_trunk,
        id_branch,
        mst_timestamp,
      )?;
    }
  }
  Ok(())
}

fn perform_front(
  conn: &mut mysql::Conn,
  transaction_mapper: &TransactionMapper,
  bundle_mapper: &BundleMapper,
  id_trunk: u64,
  id_branch: u64,
  mst_timestamp: f64,
) -> Result<()> {
  let (timestamp, mut counter) = (SystemTime::milliseconds_since_epoch()?, 0);
  let (mut nodes, mut visited) = (VecDeque::new(), HashSet::new());
  nodes.push_front(id_trunk);
  if id_branch != id_trunk {
    nodes.push_front(id_branch);
  }
  while let Some(id) = nodes.pop_back() {
    if !visited.insert(id) {
      continue;
    }
    let transaction = transaction_mapper.fetch(conn, id)?;
    let mut transaction = transaction.lock().unwrap();
    if transaction.mst_a() {
      continue;
    }
    if let Some(id_trunk) = transaction.id_trunk() {
      nodes.push_front(id_trunk);
    }
    if let Some(id_branch) = transaction.id_branch() {
      nodes.push_front(id_branch);
    }
    approve(
      conn,
      bundle_mapper,
      &mut transaction,
      mst_timestamp,
      timestamp,
    )?;
    counter += 1;
  }
  if counter > 0 {
    event::subtangle_confirmation(conn, timestamp, counter)?;
  }
  Ok(())
}

fn reference_approval<T>(
  conn: &mut mysql::Conn,
  transaction_mapper: &TransactionMapper,
  id: u64,
  f: T,
) -> Result<Option<f64>>
where
  T: FnOnce(&TransactionMapper, u64)
    -> Option<Arc<Mutex<Vec<u64>>>>,
{
  if let Some(references) = f(transaction_mapper, id) {
    for &id in &*references.lock().unwrap() {
      let record = transaction_mapper.fetch(conn, id)?;
      let record = record.lock().unwrap();
      if record.mst_a() {
        return Ok(Some(record.mst_timestamp()));
      }
    }
  }
  Ok(None)
}

fn approve(
  conn: &mut mysql::Conn,
  bundle_mapper: &BundleMapper,
  transaction: &mut TransactionRecord,
  mst_timestamp: f64,
  timestamp: f64,
) -> Result<()> {
  if transaction.current_idx() == 0 {
    let bundle = bundle_mapper.fetch(conn, transaction.id_bundle())?;
    bundle.lock().unwrap().set_confirmed(timestamp);
  }
  let timestamp = transaction.timestamp();
  transaction.set_conftime(mst_timestamp - timestamp);
  transaction.set_mst_a(true);
  Ok(())
}
<commit_msg>Approve fix<commit_after>use super::Result;
use event;
use mapper::{BundleMapper, Mapper, Record, TransactionMapper,
             TransactionRecord};
use mysql;
use std::collections::{HashSet, VecDeque};
use std::sync::{mpsc, Arc, Mutex};
use std::thread;
use std::time::{Instant, SystemTime};
use utils::{DurationUtils, SystemTimeUtils};

#[derive(Debug)]
pub enum ApproveMessage {
  Reverse(u64),
  Front(u64, u64, f64),
}

pub struct ApproveThread<'a> {
  pub approve_rx: mpsc::Receiver<ApproveMessage>,
  pub mysql_uri: &'a str,
  pub transaction_mapper: Arc<TransactionMapper>,
  pub bundle_mapper: Arc<BundleMapper>,
}

impl<'a> ApproveThread<'a> {
  pub fn spawn(self) {
    let Self {
      approve_rx,
      mysql_uri,
      transaction_mapper,
      bundle_mapper,
    } = self;
    let mut conn =
      mysql::Conn::new(mysql_uri).expect("MySQL connection failure");
    thread::spawn(move || {
      let transaction_mapper = &*transaction_mapper;
      let bundle_mapper = &*bundle_mapper;
      loop {
        let message = approve_rx.recv().expect("Thread communication failure");
        let duration = Instant::now();
        let result = match message {
          ApproveMessage::Reverse(id) => {
            perform_reverse(&mut conn, transaction_mapper, bundle_mapper, id)
          }
          ApproveMessage::Front(id_trunk, id_branch, mst_timestamp) => {
            perform_front(
              &mut conn,
              transaction_mapper,
              bundle_mapper,
              id_trunk,
              id_branch,
              mst_timestamp,
            )
          }
        };
        let duration = duration.elapsed().as_milliseconds();
        match result {
          Ok(()) => {
            info!("{:.3}ms {:?}", duration, message);
          }
          Err(err) => {
            error!("{:.3}ms {}", duration, err);
          }
        }
      }
    });
  }
}

fn perform_reverse(
  conn: &mut mysql::Conn,
  transaction_mapper: &TransactionMapper,
  bundle_mapper: &BundleMapper,
  id: u64,
) -> Result<()> {
  let mut mst_timestamp = reference_approval(
    conn,
    transaction_mapper,
    id,
    TransactionMapper::trunk_references,
  )?;
  if mst_timestamp.is_none() {
    mst_timestamp = reference_approval(
      conn,
      transaction_mapper,
      id,
      TransactionMapper::branch_references,
    )?;
  }
  if let Some(mst_timestamp) = mst_timestamp {
    let (id_trunk, id_branch) = {
      let transaction = transaction_mapper.fetch(conn, id)?;
      let mut transaction = transaction.lock().unwrap();
      approve(
        conn,
        bundle_mapper,
        &mut transaction,
        mst_timestamp,
        SystemTime::milliseconds_since_epoch()?,
      )?;
      (transaction.id_trunk(), transaction.id_branch())
    };
    if let (Some(id_trunk), Some(id_branch)) = (id_trunk, id_branch) {
      perform_front(
        conn,
        transaction_mapper,
        bundle_mapper,
        id_trunk,
        id_branch,
        mst_timestamp,
      )?;
    }
  }
  Ok(())
}

fn perform_front(
  conn: &mut mysql::Conn,
  transaction_mapper: &TransactionMapper,
  bundle_mapper: &BundleMapper,
  id_trunk: u64,
  id_branch: u64,
  mst_timestamp: f64,
) -> Result<()> {
  let (timestamp, mut counter) = (SystemTime::milliseconds_since_epoch()?, 0);
  let (mut nodes, mut visited) = (VecDeque::new(), HashSet::new());
  nodes.push_front(id_trunk);
  if id_branch != id_trunk {
    nodes.push_front(id_branch);
  }
  while let Some(id) = nodes.pop_back() {
    if !visited.insert(id) {
      continue;
    }
    let transaction = transaction_mapper.fetch(conn, id)?;
    let mut transaction = transaction.lock().unwrap();
    if transaction.mst_a() || !transaction.is_persisted() {
      continue;
    }
    if let Some(id_trunk) = transaction.id_trunk() {
      nodes.push_front(id_trunk);
    }
    if let Some(id_branch) = transaction.id_branch() {
      nodes.push_front(id_branch);
    }
    approve(
      conn,
      bundle_mapper,
      &mut transaction,
      mst_timestamp,
      timestamp,
    )?;
    counter += 1;
  }
  if counter > 0 {
    event::subtangle_confirmation(conn, timestamp, counter)?;
  }
  Ok(())
}

fn reference_approval<T>(
  conn: &mut mysql::Conn,
  transaction_mapper: &TransactionMapper,
  id: u64,
  f: T,
) -> Result<Option<f64>>
where
  T: FnOnce(&TransactionMapper, u64)
    -> Option<Arc<Mutex<Vec<u64>>>>,
{
  if let Some(references) = f(transaction_mapper, id) {
    for &id in &*references.lock().unwrap() {
      let record = transaction_mapper.fetch(conn, id)?;
      let record = record.lock().unwrap();
      if record.mst_a() {
        return Ok(Some(record.mst_timestamp()));
      }
    }
  }
  Ok(None)
}

fn approve(
  conn: &mut mysql::Conn,
  bundle_mapper: &BundleMapper,
  transaction: &mut TransactionRecord,
  mst_timestamp: f64,
  timestamp: f64,
) -> Result<()> {
  if transaction.current_idx() == 0 {
    let bundle = bundle_mapper.fetch(conn, transaction.id_bundle())?;
    bundle.lock().unwrap().set_confirmed(timestamp);
  }
  let timestamp = transaction.timestamp();
  transaction.set_conftime(mst_timestamp - timestamp);
  transaction.set_mst_a(true);
  Ok(())
}
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////////
//  File: rust-worldgen/tile/constraint.rs
//////////////////////////////////////////////////////////////////////////////
//  Copyright 2015 Samuel Sleight
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//////////////////////////////////////////////////////////////////////////////

use std::collections::HashMap;

use crate::noisemap::NoiseMapGeneratorBase;
use crate::world::Size;

#[derive(Copy, Clone)]
pub enum ConstraintType {
    /// This constraint is satisfied when the noise value is
    /// lower than the given threshold.
    LT(f64),

    /// This constraint is satisfied when the noise value is
    /// greater than the given threshold.
    GT(f64)
}

/// A constraint that limits when a tile should be chosen for
/// the generated world.
pub struct Constraint {
    nm: Box<dyn NoiseMapGeneratorBase>,
    constraint: ConstraintType
}

#[macro_export]
macro_rules! constraint {
    ($nm:expr, < $v:expr) => (Constraint::new($nm, ConstraintType::LT($v)));
    ($nm:expr, > $v:expr) => (Constraint::new($nm, ConstraintType::GT($v)));
}

impl Constraint {
    pub fn new(nm: Box<dyn NoiseMapGeneratorBase>, constraint: ConstraintType) -> Constraint {
        Constraint {
            nm,
            constraint
        }
    }

    /// Returns true is the given value would satisfy this constraint.
    pub fn satisfied_by(&self, x: i64, y: i64, size: Size, chunk_x: i64, chunk_y: i64, nms: &mut HashMap<u64, Vec<Vec<f64>>>) -> bool {
        let id = self.nm.id();

        let nm = nms.entry(id).or_insert_with(|| self.nm.generate_sized_chunk(size, chunk_x, chunk_y));

        match self.constraint {
            ConstraintType::LT(threshold) => nm[y as usize][x as usize] < threshold,
            ConstraintType::GT(threshold) => nm[y as usize][x as usize] > threshold
        }
    }
}
<commit_msg>Fixed crash when using chunks<commit_after>//////////////////////////////////////////////////////////////////////////////
//  File: rust-worldgen/tile/constraint.rs
//////////////////////////////////////////////////////////////////////////////
//  Copyright 2015 Samuel Sleight
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//////////////////////////////////////////////////////////////////////////////

use std::collections::HashMap;

use crate::noisemap::NoiseMapGeneratorBase;
use crate::world::Size;

#[derive(Copy, Clone)]
pub enum ConstraintType {
    /// This constraint is satisfied when the noise value is
    /// lower than the given threshold.
    LT(f64),

    /// This constraint is satisfied when the noise value is
    /// greater than the given threshold.
    GT(f64)
}

/// A constraint that limits when a tile should be chosen for
/// the generated world.
pub struct Constraint {
    nm: Box<dyn NoiseMapGeneratorBase>,
    constraint: ConstraintType
}

#[macro_export]
macro_rules! constraint {
    ($nm:expr, < $v:expr) => (Constraint::new($nm, ConstraintType::LT($v)));
    ($nm:expr, > $v:expr) => (Constraint::new($nm, ConstraintType::GT($v)));
}

impl Constraint {
    pub fn new(nm: Box<dyn NoiseMapGeneratorBase>, constraint: ConstraintType) -> Constraint {
        Constraint {
            nm,
            constraint
        }
    }

    /// Returns true is the given value would satisfy this constraint.
    pub fn satisfied_by(&self, x: i64, y: i64, size: Size, chunk_x: i64, chunk_y: i64, nms: &mut HashMap<u64, Vec<Vec<f64>>>) -> bool {
        let id = self.nm.id();

        let nm = nms.entry(id).or_insert_with(|| self.nm.generate_sized_chunk(size, chunk_x, chunk_y));

        let x = (x as i64) % size.w;
        let y = (y as i64) % size.h;

        match self.constraint {
            ConstraintType::LT(threshold) => nm[y as usize][x as usize] < threshold,
            ConstraintType::GT(threshold) => nm[y as usize][x as usize] > threshold
        }
    }
}
<|endoftext|>


<commit_before>struct Queue {
  older: Vec<char>,
  younger: Vec<char>
}

impl Queue {
  fn is_empty(self: &Queue) -> bool {
    self.older.is_empty() && self.younger.is_empty()
  }

  fn push(self: &mut Queue, c: char) {
    self.younger.push(c);
  }

  fn pop(self: &mut Queue) -> Option<char> {
    if self.older.is_empty() {
      if self.younger.is_empty() {
        return None;
      }
      use std::mem::swap;
      swap(&mut self.older, &mut self.younger);
      self.older.reverse();
    }

    self.older.pop()
  }
}

let mut q = Queue { older: Vec::new(), younger: Vec::new() };
q.push('0');
q.push('1');
assert_eq!(q.pop(), Some('0'));

q.push('w');
assert_eq!(q.pop(), Some('1'));
assert_eq!(q.pop(), Some('w'));
assert_eq!(q.pop(), None);

assert!(q.is_empty());
q.push('*');
assert!(!q.is_empty());
<commit_msg>add split method to Rust queue<commit_after>struct Queue {
  older: Vec<char>,
  younger: Vec<char>
}

impl Queue {
  fn is_empty(self: &Queue) -> bool {
    self.older.is_empty() && self.younger.is_empty()
  }

  fn push(self: &mut Queue, c: char) {
    self.younger.push(c);
  }

  fn pop(self: &mut Queue) -> Option<char> {
    if self.older.is_empty() {
      if self.younger.is_empty() {
        return None;
      }
      use std::mem::swap;
      swap(&mut self.older, &mut self.younger);
      self.older.reverse();
    }

    self.older.pop()
  }

  // Here will take ownership for queue
  fn split(self: Queue) -> (Vec<char>, Vec<char>) {
    (self.older, self.younger)
  }
}

let mut q = Queue { older: Vec::new(), younger: Vec::new() };
q.push('0');
q.push('1');
assert_eq!(q.pop(), Some('0'));

q.push('w');
assert_eq!(q.pop(), Some('1'));
assert_eq!(q.pop(), Some('w'));
assert_eq!(q.pop(), None);

assert!(q.is_empty());
q.push('*');
assert!(!q.is_empty());
q.pop();

q.push('P');
q.push('X');
assert_eq!(q.pop(), Some('P'));
q.push('Z');

let(older, younger) = q.split();
assert_eq!(older, vec!['X']);
assert_eq!(younger, vec!['Z']);
<|endoftext|>


<commit_before>mod card {
    use std::fmt;
    use std::iter::AdditiveIterator;
    use std::ops::Add;
    use std::slice;

    pub fn score(hand: Vec<Card>, start_card: Card) -> i32 {
        let mut with_start = hand.clone();
        with_start.push(start_card);
        2 * count_15s(&with_start)
            + 2 * count_pairs(&with_start)
            + score_runs(&with_start)
    }

    fn count_15s(cards: &Vec<Card>) -> i32 {
        power_set(&mut cards.iter()).iter()
            .filter(|ref x| x.iter().map(|ref x| x.rank.value()).sum() == 15)
            .count() as i32
    }

    fn count_pairs(cards: &Vec<Card>) -> i32 {
        power_set(&mut cards.iter()).iter()
            .filter(|&x| x.len() == 2)
            .filter(|ref x| x[0].rank == x[1].rank)
            .count() as i32
    }

    fn score_runs(cards: &Vec<Card>) -> i32 {
        let mut cpy = cards.clone();
        cpy.sort();
        let mut runs = Vec::new();
        let mut run: Vec<Card> = Vec::new();
        for card in cpy.iter() {
            //println!("Looking at {} and {}", card, run);
            if run.len() == 0 || run[run.len()-1].clone().rank + Rank(1) == card.rank {
                run.push(card.clone())
            } else {
                if run.len() > 1 {
                    runs.push(run);
                }
                run = Vec::new();
                run.push(card.clone());
            }
        }
        if run.len() > 1 {
            runs.push(run);
        }
        runs.iter()
            .map(|x| x.len() as i32)
            .sum()
    }

    fn power_set<'a, T: Clone + 'a>(items: &mut slice::Iter<'a,T>) -> Vec<Vec<T>> {
        let mut power = Vec::new();
        match items.next() {
            None       => power.push(Vec::new()),
            Some(item) => {
                for mut set in power_set(items).into_iter() {
                    power.push(set.clone());
                    set.push(item.clone());
                    power.push(set);
                }
            }
        }
        power
    }

    #[derive(PartialEq, Eq, PartialOrd, Ord, Clone)]
    struct Card {
        rank: Rank,
        suit: Suit,
    }

    pub fn new(rank: i32, suit: char) -> Card {
        Card{rank: Rank(rank), suit: from_char(suit)}
    }

    impl fmt::Show for Card {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "{}{}", self.rank, self.suit)
        }
    }

    #[derive(PartialEq, Eq, PartialOrd, Ord, Clone)]
    enum Suit {
        Spades,
        Hearts,
        Clubs,
        Diamonds,
    }

    impl Suit {
        pub fn to_char(&self) -> char {
            match *self {
                Suit::Spades   => 'S',
                Suit::Hearts   => 'H',
                Suit::Diamonds => 'D',
                Suit::Clubs    => 'C',
            }
        }
    }

    impl fmt::Show for Suit {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                    write!(f, "{}", self.to_char())
        }
    }

    pub fn from_char(a: char) -> Suit {
        match a {
            'S'=> Suit::Spades,
            'H'=> Suit::Hearts,
            'C'=> Suit::Clubs,
            'D'=> Suit::Diamonds,
            _  => panic!("Not a suit")
        }
    }

    #[derive(PartialEq, Eq, PartialOrd, Ord, Clone)]
    struct Rank(i32);

    impl fmt::Show for Rank {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            let value = match *self {
                Rank(13) => "K".to_string(),
                Rank(12) => "Q".to_string(),
                Rank(11) => "J".to_string(),
                Rank(aa) => aa.to_string(),
            };
            write!(f, "{}", value)
        }
    }

    impl Rank {
        fn value(&self) -> i32 {
            let Rank(x) = *self;
            if x > 10 {
                10
            } else {
                x
            }
        }
    }

    impl Add for Rank {
        type Output = Rank;

        fn add(self, rhs: Rank) -> Rank {
            let (Rank(lh), Rank(rh)) = (self, rhs);
            Rank(lh + rh)
        }
    }

}

fn main() {
    let cards = vec![
        card::new(12, 'H'),
        card::new(11, 'S'),
        card::new(10, 'S'),
        card::new(5, 'C'),
        ];
    println!("{}", card::score(cards, card::new(4, 'D')));
}
<commit_msg>Score flush. Print score pretty.<commit_after>mod card {
    use std::fmt;
    use std::iter::AdditiveIterator;
    use std::ops::Add;
    use std::slice;

    pub fn score(hand: Vec<Card>, start_card: Card, crib: bool) -> i32 {
        let mut with_start = hand.clone();
        with_start.push(start_card.clone());
        let fifteens = count_15s(&with_start);
        let pairs = count_pairs(&with_start);
        let flushpoints = score_flushes(&hand, start_card, crib);
        let runpoints = score_runs(&with_start);
        println!("fifteens: {}", fifteens);
        println!("pairs:    {}", pairs);
        println!("flush:    {} points", flushpoints);
        println!("runs:     {} points", runpoints);
        2 * fifteens
            + 2 * pairs
            + flushpoints
            + runpoints
    }

    fn count_15s(cards: &Vec<Card>) -> i32 {
        power_set(&mut cards.iter()).iter()
            .filter(|ref x| x.iter().map(|ref x| x.rank.value()).sum() == 15)
            .count() as i32
    }

    fn count_pairs(cards: &Vec<Card>) -> i32 {
        power_set(&mut cards.iter()).iter()
            .filter(|&x| x.len() == 2)
            .filter(|ref x| x[0].rank == x[1].rank)
            .count() as i32
    }

    fn score_runs(cards: &Vec<Card>) -> i32 {
        let mut cpy = cards.clone();
        cpy.sort();
        let mut runs = Vec::new();
        let mut run: Vec<Card> = Vec::new();
        for card in cpy.iter() {
            //println!("Looking at {} and {}", card, run);
            if run.len() == 0 || run[run.len()-1].clone().rank + Rank(1) == card.rank {
                run.push(card.clone())
            } else {
                if run.len() > 1 {
                    runs.push(run);
                }
                run = Vec::new();
                run.push(card.clone());
            }
        }
        if run.len() > 1 {
            runs.push(run);
        }
        runs.iter()
            .map(|x| x.len() as i32)
            .sum()
    }

    fn score_flushes(cards: &Vec<Card>, start: Card, crib: bool) -> i32 {
        let mut cards = cards.clone();
        let expected_suit = cards.pop().unwrap().suit;
        let four_flush = cards.iter()
            .fold(true, |so_far, next| so_far && next.suit == expected_suit);
        match (four_flush, start.suit==expected_suit, !crib) {
            (true, true, _)      => 5,
            (true, false, true)  => 4,
            (true, false, false) => 0,
            (false, _, _)        => 0,
        }
    }

    fn power_set<'a, T: Clone + 'a>(items: &mut slice::Iter<'a,T>) -> Vec<Vec<T>> {
        let mut power = Vec::new();
        match items.next() {
            None       => power.push(Vec::new()),
            Some(item) => {
                for mut set in power_set(items).into_iter() {
                    power.push(set.clone());
                    set.push(item.clone());
                    power.push(set);
                }
            }
        }
        power
    }

    #[derive(PartialEq, Eq, PartialOrd, Ord, Clone)]
    struct Card {
        rank: Rank,
        suit: Suit,
    }

    pub fn new(rank: i32, suit: char) -> Card {
        Card{rank: Rank(rank), suit: from_char(suit)}
    }

    impl fmt::Show for Card {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "{}{}", self.rank, self.suit)
        }
    }

    #[derive(PartialEq, Eq, PartialOrd, Ord, Clone)]
    enum Suit {
        Spades,
        Hearts,
        Clubs,
        Diamonds,
    }

    impl Suit {
        pub fn to_char(&self) -> char {
            match *self {
                Suit::Spades   => 'S',
                Suit::Hearts   => 'H',
                Suit::Diamonds => 'D',
                Suit::Clubs    => 'C',
            }
        }
    }

    impl fmt::Show for Suit {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                    write!(f, "{}", self.to_char())
        }
    }

    pub fn from_char(a: char) -> Suit {
        match a {
            'S'=> Suit::Spades,
            'H'=> Suit::Hearts,
            'C'=> Suit::Clubs,
            'D'=> Suit::Diamonds,
            _  => panic!("Not a suit")
        }
    }

    #[derive(PartialEq, Eq, PartialOrd, Ord, Clone)]
    struct Rank(i32);

    impl fmt::Show for Rank {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            let value = match *self {
                Rank(13) => "K".to_string(),
                Rank(12) => "Q".to_string(),
                Rank(11) => "J".to_string(),
                Rank(aa) => aa.to_string(),
            };
            write!(f, "{}", value)
        }
    }

    impl Rank {
        fn value(&self) -> i32 {
            let Rank(x) = *self;
            if x > 10 {
                10
            } else {
                x
            }
        }
    }

    impl Add for Rank {
        type Output = Rank;

        fn add(self, rhs: Rank) -> Rank {
            let (Rank(lh), Rank(rh)) = (self, rhs);
            Rank(lh + rh)
        }
    }

}

fn main() {
    let cards = vec![
        card::new(5, 'H'),
        card::new(5, 'D'),
        card::new(5, 'C'),
        card::new(11, 'S'),
        ];
    println!("{}", card::score(cards, card::new(5, 'S'), false));
}
<|endoftext|>