<commit_before>#![allow(non_snake_case, non_upper_case_globals)]
// #![cfg_attr(test, feature(test))]
extern crate time;

use time::precise_time_s;
use std::mem;

///////////////////////////////////////////////////////////////////////////////
// 1. Calibration
///////////////////////////////////////////////////////////////////////////////
const aalpha:f64 = 0.33333333333;  // Elasticity of output w.r.t. capital
const bbeta:f64 = 0.95;           // Discount factor

// Productivity values
const vProductivity:[f64; 5] = [0.9792, 0.9896, 1.0000, 1.0106, 1.0212];

// Transition matrix
const mTransition:[[f64; 5]; 5] = [[0.9727, 0.0273, 0.0000, 0.0000, 0.0000],
                                   [0.0041, 0.9806, 0.0153, 0.0000, 0.0000],
                                   [0.0000, 0.0082, 0.9837, 0.0082, 0.0000],
                                   [0.0000, 0.0000, 0.0153, 0.9806, 0.0041],
                                   [0.0000, 0.0000, 0.0000, 0.0273, 0.9727]];

// Dimensions to generate the grid of capital
const nGridCapital: usize = 17820;
const nGridProductivity: usize = 5;

fn solve(print: bool) -> f64 {
  /////////////////////////////////////////////////////////////////////////////
  // 2. Steady State
  /////////////////////////////////////////////////////////////////////////////

    let capitalSteadyState: f64 = (aalpha * bbeta).powf(1_f64 / (1_f64 - aalpha));
    let outputSteadyState: f64 = capitalSteadyState.powf(aalpha);
    let consumptionSteadyState: f64 = outputSteadyState - capitalSteadyState;

    if print {
        println!("Output = {}, Capital = {}, Consumption = {}",
                 outputSteadyState,
                 capitalSteadyState,
                 consumptionSteadyState);
    }

    let vGridCapital = (0..nGridCapital)
                           .map(|nCapital| 0.5 * capitalSteadyState + 0.00001 * (nCapital as f64))
                           .collect::<Vec<f64>>();

    // 3. Required matrices and vectors
    let mut mValueFunction = vec![[0f64; nGridProductivity]; nGridCapital];
    let mut mValueFunctionNew = mValueFunction.clone();
    let mut mPolicyFunction = mValueFunction.clone();
    let mut expectedValueFunction = mValueFunction.clone();

    // 4. We pre-build output for each point in the grid
    let mOutput = (0..nGridCapital)
                      .map(|nCapital| {
                          (0..nGridProductivity).map(|nProductivity|
        vProductivity[nProductivity]*vGridCapital[nCapital].powf(aalpha)
      ).collect::<Vec<f64>>()
                      })
                      .collect::<Vec<Vec<f64>>>();

  // 5. Main iteration
  // TODO: one could implement a macro for the multiple declarations
    let mut maxDifference = 10_f64;
    const tolerance: f64 = 0.0000001; // compiler warn: variable does not need to be mutable
    let mut capitalChoice: f64;

    let mut iteration = 0;

    while maxDifference > tolerance {
        for nProductivity in 0..nGridProductivity {
            for nCapital in 0..nGridCapital {
                expectedValueFunction[nCapital][nProductivity] = 0.0;
                for nProductivityNextPeriod in 0..nGridProductivity {
                    expectedValueFunction[nCapital][nProductivity] +=
                        mTransition[nProductivity][nProductivityNextPeriod] *
                        mValueFunction[nCapital][nProductivityNextPeriod];
                }
            }
        }

        for nProductivity in 0..nGridProductivity {

        // We start from previous choice (monotonicity of policy function)
            let mut gridCapitalNextPeriod = 0;

            for nCapital in 0..nGridCapital {

                let mut valueHighSoFar = -100000.0;

                for nCapitalNextPeriod in gridCapitalNextPeriod..nGridCapital {

                    let consumption = mOutput[nCapital][nProductivity] -
                                  vGridCapital[nCapitalNextPeriod];
                    let valueProvisional = (1_f64 - bbeta) * (consumption.ln()) +
                                       bbeta *
                                       expectedValueFunction[nCapitalNextPeriod][nProductivity];

                    if valueProvisional > valueHighSoFar {
                        valueHighSoFar = valueProvisional;
                        capitalChoice = vGridCapital[nCapitalNextPeriod];
                        gridCapitalNextPeriod = nCapitalNextPeriod;
                    } else {
                        break; // We break when we have achieved the max
                    }

                    mValueFunctionNew[nCapital][nProductivity] = valueHighSoFar;
                    mPolicyFunction[nCapital][nProductivity] = capitalChoice;
                }

            }

        }

        let mut diffHighSoFar = -100000.0;
        for nProductivity in 0..nGridProductivity {
            for nCapital in 0..nGridCapital {
                let diff = (mValueFunction[nCapital][nProductivity] -
                        mValueFunctionNew[nCapital][nProductivity])
                           .abs();
                if diff > diffHighSoFar {
                    diffHighSoFar = diff;
                }
            }
        }

        // swap buffers after the loop
        mem::swap(&mut mValueFunction, &mut mValueFunctionNew);

        maxDifference = diffHighSoFar;

        iteration += 1;
        if print && (iteration % 10 == 0 || iteration == 1) {
            println!("Iteration = {}, Sup Diff = {}", iteration, maxDifference);
        }
    }

    if print {
        println!("Iteration = {}, Sup Diff = {}", iteration, maxDifference);
    }

    mPolicyFunction[999][2]
}

fn main() {
    let sample = false;

    if sample {
        let mut samples = (0..5).map(|i| {
            let cpu0 = precise_time_s();
            let result = solve(false);
            let cpu1 = precise_time_s();

            assert_eq!(result, 0.1465491436956954);

            let diff = cpu1 - cpu0;
            println!("Sample #{}, Time: {}s", i + 1, diff);
            diff
        }).collect::<Vec<f64>>();

        samples.sort_by(|a, b| a.partial_cmp(b).unwrap());
        println!("\nMedian time is = {}", samples[2]);
    } else {
        let cpu0 = precise_time_s();
        let result = solve(true);
        let cpu1 = precise_time_s();

        println!("My check = {}\n", result);
        assert_eq!(result, 0.1465491436956954);
        println!("Elapsed time is = {}", cpu1 - cpu0);
    }
}

// FIXME: Can't use bench as the loop is too slow (takes 8mins to get samples)
// #[cfg(test)]
// mod test {
//     extern crate test;
//     use self::test::Bencher;
//     use super::solve;

//     #[bench]
//     fn bench(b: &mut Bencher) {
//         b.iter(|| {
//             // use `test::black_box` to prevent compiler optimizations from disregarding
//             // unused values
//             test::black_box(solve(false));
//         });
//     }
// }
<commit_msg>Rewrite first inner loop to use iterators<commit_after>#![allow(non_snake_case, non_upper_case_globals)]
// #![cfg_attr(test, feature(test))]
extern crate time;

use time::precise_time_s;
use std::mem;

///////////////////////////////////////////////////////////////////////////////
// 1. Calibration
///////////////////////////////////////////////////////////////////////////////
const aalpha:f64 = 0.33333333333;  // Elasticity of output w.r.t. capital
const bbeta:f64 = 0.95;           // Discount factor

// Productivity values
const vProductivity:[f64; 5] = [0.9792, 0.9896, 1.0000, 1.0106, 1.0212];

// Transition matrix
const mTransition:[[f64; 5]; 5] = [[0.9727, 0.0273, 0.0000, 0.0000, 0.0000],
                                   [0.0041, 0.9806, 0.0153, 0.0000, 0.0000],
                                   [0.0000, 0.0082, 0.9837, 0.0082, 0.0000],
                                   [0.0000, 0.0000, 0.0153, 0.9806, 0.0041],
                                   [0.0000, 0.0000, 0.0000, 0.0273, 0.9727]];

// Dimensions to generate the grid of capital
const nGridCapital: usize = 17820;
const nGridProductivity: usize = 5;

fn solve(print: bool) -> f64 {
  /////////////////////////////////////////////////////////////////////////////
  // 2. Steady State
  /////////////////////////////////////////////////////////////////////////////

    let capitalSteadyState: f64 = (aalpha * bbeta).powf(1_f64 / (1_f64 - aalpha));
    let outputSteadyState: f64 = capitalSteadyState.powf(aalpha);
    let consumptionSteadyState: f64 = outputSteadyState - capitalSteadyState;

    if print {
        println!("Output = {}, Capital = {}, Consumption = {}",
                 outputSteadyState,
                 capitalSteadyState,
                 consumptionSteadyState);
    }

    let vGridCapital = (0..nGridCapital)
                           .map(|nCapital| 0.5 * capitalSteadyState + 0.00001 * (nCapital as f64))
                           .collect::<Vec<f64>>();

    // 3. Required matrices and vectors
    let mut mValueFunction = vec![[0f64; nGridProductivity]; nGridCapital];
    let mut mValueFunctionNew = mValueFunction.clone();
    let mut mPolicyFunction = mValueFunction.clone();
    let mut expectedValueFunction = mValueFunction.clone();

    // 4. We pre-build output for each point in the grid
    let mOutput = (0..nGridCapital)
                      .map(|nCapital| {
                          (0..nGridProductivity).map(|nProductivity|
        vProductivity[nProductivity]*vGridCapital[nCapital].powf(aalpha)
      ).collect::<Vec<f64>>()
                      })
                      .collect::<Vec<Vec<f64>>>();

  // 5. Main iteration
  // TODO: one could implement a macro for the multiple declarations
    let mut maxDifference = 10_f64;
    const tolerance: f64 = 0.0000001; // compiler warn: variable does not need to be mutable
    let mut capitalChoice: f64;

    let mut iteration = 0;

    while maxDifference > tolerance {
        for nProductivity in 0..nGridProductivity {
            let transitions = &mTransition[nProductivity];

            for nCapital in 0..nGridCapital {
                let value_fns = &mValueFunction[nCapital];

                let expected_value = transitions.iter()
                                                .zip(value_fns.iter())
                                                .fold(0.0f64, |acc, (transition, value_fn)| {
                    acc + (transition * value_fn)
                });

                expectedValueFunction[nCapital][nProductivity] = expected_value;
            }
        }

        for nProductivity in 0..nGridProductivity {

        // We start from previous choice (monotonicity of policy function)
            let mut gridCapitalNextPeriod = 0;

            for nCapital in 0..nGridCapital {

                let mut valueHighSoFar = -100000.0;

                for nCapitalNextPeriod in gridCapitalNextPeriod..nGridCapital {

                    let consumption = mOutput[nCapital][nProductivity] -
                                  vGridCapital[nCapitalNextPeriod];
                    let valueProvisional = (1_f64 - bbeta) * (consumption.ln()) +
                                       bbeta *
                                       expectedValueFunction[nCapitalNextPeriod][nProductivity];

                    if valueProvisional > valueHighSoFar {
                        valueHighSoFar = valueProvisional;
                        capitalChoice = vGridCapital[nCapitalNextPeriod];
                        gridCapitalNextPeriod = nCapitalNextPeriod;
                    } else {
                        break; // We break when we have achieved the max
                    }

                    mValueFunctionNew[nCapital][nProductivity] = valueHighSoFar;
                    mPolicyFunction[nCapital][nProductivity] = capitalChoice;
                }

            }

        }

        let mut diffHighSoFar = -100000.0;
        for nProductivity in 0..nGridProductivity {
            for nCapital in 0..nGridCapital {
                let diff = (mValueFunction[nCapital][nProductivity] -
                        mValueFunctionNew[nCapital][nProductivity])
                           .abs();
                if diff > diffHighSoFar {
                    diffHighSoFar = diff;
                }
            }
        }

        // swap buffers after the loop
        mem::swap(&mut mValueFunction, &mut mValueFunctionNew);

        maxDifference = diffHighSoFar;

        iteration += 1;
        if print && (iteration % 10 == 0 || iteration == 1) {
            println!("Iteration = {}, Sup Diff = {}", iteration, maxDifference);
        }
    }

    if print {
        println!("Iteration = {}, Sup Diff = {}", iteration, maxDifference);
    }

    mPolicyFunction[999][2]
}

fn main() {
    let sample = false;

    if sample {
        let mut samples = (0..5).map(|i| {
            let cpu0 = precise_time_s();
            let result = solve(false);
            let cpu1 = precise_time_s();

            assert_eq!(result, 0.1465491436956954);

            let diff = cpu1 - cpu0;
            println!("Sample #{}, Time: {}s", i + 1, diff);
            diff
        }).collect::<Vec<f64>>();

        samples.sort_by(|a, b| a.partial_cmp(b).unwrap());
        println!("\nMedian time is = {}", samples[2]);
    } else {
        let cpu0 = precise_time_s();
        let result = solve(true);
        let cpu1 = precise_time_s();

        println!("My check = {}\n", result);
        assert_eq!(result, 0.1465491436956954);
        println!("Elapsed time is = {}", cpu1 - cpu0);
    }
}

// FIXME: Can't use bench as the loop is too slow (takes 8mins to get samples)
// #[cfg(test)]
// mod test {
//     extern crate test;
//     use self::test::Bencher;
//     use super::solve;

//     #[bench]
//     fn bench(b: &mut Bencher) {
//         b.iter(|| {
//             // use `test::black_box` to prevent compiler optimizations from disregarding
//             // unused values
//             test::black_box(solve(false));
//         });
//     }
// }
<|endoftext|>


<commit_before>#![crate_id(name="tr", vers="1.0.0", author="Michael Gehring")]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Michael Gehring <mg@ebfe.org>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern crate collections;
extern crate getopts;

use collections::bitv::BitvSet;
use collections::smallintmap::SmallIntMap;
use getopts::OptGroup;
use std::char::from_u32;
use std::io::print;
use std::io::stdio::{stdin,stdout};
use std::iter::FromIterator;
use std::os;
use std::vec::Vec;

static NAME : &'static str = "tr";
static VERSION : &'static str = "1.0.0";

fn unescape_char(c: char) -> char {
    match c {
        'a' => 0x07u8 as char,
        'b' => 0x08u8 as char,
        'f' => 0x0cu8 as char,
        'v' => 0x0bu8 as char,
        'n' => '\n',
        'r' => '\r',
        't' => '\t',
        _ => c,
    }
}

fn unescape(v: Vec<char>) -> Vec<char> {
    let mut out = Vec::new();
    let mut input = v.as_slice();
    loop {
        input = match input {
            ['\\', e, ..rest] => {
                out.push(unescape_char(e));
                rest
            }
            [c, ..rest] => {
                out.push(c);
                rest
            }
            [] => break
        }
    }
    out
}

fn expand_range(from: char, to: char) -> Vec<char> {
    range(from as u32, to as u32 + 1).map(|c| from_u32(c).unwrap()).collect()
}

fn expand_set(s: &str) -> Vec<char> {
    let mut set = Vec::<char>::new();
    let unesc = unescape(FromIterator::from_iter(s.chars()));
    let mut input = unesc.as_slice();

    loop {
        input = match input {
            [f, '-', t, ..rest] => {
                set.push_all(expand_range(f, t).as_slice());
                rest
            }
            [c, ..rest] => {
                set.push(c);
                rest
            }
            [] => break
        };
    }
    set
}

fn delete(set: Vec<char>) {
    let mut bset = BitvSet::new();
    let mut out = stdout();

    for &c in set.iter() {
        bset.insert(c as uint);
    }

    for c in stdin().chars() {
        match c {
            Ok(c) if !bset.contains(&(c as uint)) => out.write_char(c).unwrap(),
            Ok(_) => (),
            Err(err) => fail!("{}", err),
        };
    }
}

fn tr(set1: &[char], set2: &[char]) {
    let mut map = SmallIntMap::<char>::new();
    let mut out = stdout();

    for i in range(0, set1.len()) {
        if i >= set2.len() {
            map.insert(set1[i] as uint, set2[set2.len()-1]);
        } else {
            map.insert(set1[i] as uint, set2[i]);
        }
    }

    for c in stdin().chars() {
        match c {
            Ok(inc) => {
                let trc = match map.find(&(inc as uint)) {
                    Some(t) => *t,
                    None => inc,
                };
                out.write_char(trc).unwrap();
            }
            Err(err) => {
                fail!("{}", err);
            }
        }
    }
}

fn usage(opts: &[OptGroup]) {
        println!("{} {}", NAME, VERSION);
        println!("");
        println!("Usage:");
        println!("  {} [OPTIONS] SET1 [SET2]", NAME);
        println!("");
        print(getopts::usage("Translate or delete characters.", opts).as_slice());
}

pub fn main() {
    let args: Vec<StrBuf> = os::args().iter().map(|x| x.to_strbuf()).collect();
    let opts = [
        getopts::optflag("d", "delete", "delete characters in SET1"),
        getopts::optflag("h", "help", "display this help and exit"),
        getopts::optflag("V", "version", "output version information and exit"),
    ];

    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => m,
        Err(err) => fail!("{}", err.to_err_msg()),
    };

    if matches.opt_present("help") {
        usage(opts);
        return
    }

    if matches.opt_present("version") {
        println!("{} {}", NAME, VERSION);
        return;
    }

    if matches.free.len() == 0 {
        usage(opts);
        os::set_exit_status(1);
        return
    }

    let dflag = matches.opt_present("d");
    let sets = matches.free;

    if dflag {
        let set1 = expand_set(sets.get(0).as_slice());
        delete(set1);
    } else {
        let set1 = expand_set(sets.get(0).as_slice());
        let set2 = expand_set(sets.get(1).as_slice());
        tr(set1.as_slice(), set2.as_slice());
    }
}
<commit_msg>tr: add --complement<commit_after>#![crate_id(name="tr", vers="1.0.0", author="Michael Gehring")]
#![feature(macro_rules)]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Michael Gehring <mg@ebfe.org>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern crate collections;
extern crate getopts;

use collections::bitv::BitvSet;
use collections::smallintmap::SmallIntMap;
use getopts::OptGroup;
use std::char::from_u32;
use std::io::print;
use std::io::stdio::{stdin,stdout};
use std::iter::FromIterator;
use std::os;
use std::vec::Vec;

#[path="../common/util.rs"]
mod util;

static NAME : &'static str = "tr";
static VERSION : &'static str = "1.0.0";

fn unescape_char(c: char) -> char {
    match c {
        'a' => 0x07u8 as char,
        'b' => 0x08u8 as char,
        'f' => 0x0cu8 as char,
        'v' => 0x0bu8 as char,
        'n' => '\n',
        'r' => '\r',
        't' => '\t',
        _ => c,
    }
}

fn unescape(v: Vec<char>) -> Vec<char> {
    let mut out = Vec::new();
    let mut input = v.as_slice();
    loop {
        input = match input {
            ['\\', e, ..rest] => {
                out.push(unescape_char(e));
                rest
            }
            [c, ..rest] => {
                out.push(c);
                rest
            }
            [] => break
        }
    }
    out
}

fn expand_range(from: char, to: char) -> Vec<char> {
    range(from as u32, to as u32 + 1).map(|c| from_u32(c).unwrap()).collect()
}

fn expand_set(s: &str) -> Vec<char> {
    let mut set = Vec::<char>::new();
    let unesc = unescape(FromIterator::from_iter(s.chars()));
    let mut input = unesc.as_slice();

    loop {
        input = match input {
            [f, '-', t, ..rest] => {
                set.push_all(expand_range(f, t).as_slice());
                rest
            }
            [c, ..rest] => {
                set.push(c);
                rest
            }
            [] => break
        };
    }
    set
}

fn delete(set: Vec<char>, complement: bool) {
    let mut bset = BitvSet::new();
    let mut out = stdout();

    for &c in set.iter() {
        bset.insert(c as uint);
    }

    let is_allowed = if complement {
        |c: char| bset.contains(&(c as uint))
    } else {
        |c: char| !bset.contains(&(c as uint))
    };

    for c in stdin().chars() {
        match c {
            Ok(c) if is_allowed(c) => out.write_char(c).unwrap(),
            Ok(_) => (),
            Err(err) => fail!("{}", err),
        };
    }
}

fn tr(set1: &[char], set2: &[char]) {
    let mut map = SmallIntMap::<char>::new();
    let mut out = stdout();

    for i in range(0, set1.len()) {
        if i >= set2.len() {
            map.insert(set1[i] as uint, set2[set2.len()-1]);
        } else {
            map.insert(set1[i] as uint, set2[i]);
        }
    }

    for c in stdin().chars() {
        match c {
            Ok(inc) => {
                let trc = match map.find(&(inc as uint)) {
                    Some(t) => *t,
                    None => inc,
                };
                out.write_char(trc).unwrap();
            }
            Err(err) => {
                fail!("{}", err);
            }
        }
    }
}

fn usage(opts: &[OptGroup]) {
        println!("{} {}", NAME, VERSION);
        println!("");
        println!("Usage:");
        println!("  {} [OPTIONS] SET1 [SET2]", NAME);
        println!("");
        print(getopts::usage("Translate or delete characters.", opts).as_slice());
}

pub fn main() {
    let args: Vec<StrBuf> = os::args().iter().map(|x| x.to_strbuf()).collect();
    let opts = [
        getopts::optflag("c", "complement", "use the complement of SET1"),
        getopts::optflag("C", "", "same as -c"),
        getopts::optflag("d", "delete", "delete characters in SET1"),
        getopts::optflag("h", "help", "display this help and exit"),
        getopts::optflag("V", "version", "output version information and exit"),
    ];

    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => m,
        Err(err) => {
            show_error!(1, "{}", err.to_err_msg());
            return;
        }
    };

    if matches.opt_present("help") {
        usage(opts);
        return;
    }

    if matches.opt_present("version") {
        println!("{} {}", NAME, VERSION);
        return;
    }

    if matches.free.len() == 0 {
        usage(opts);
        os::set_exit_status(1);
        return;
    }

    let dflag = matches.opt_present("d");
    let cflag = matches.opts_present(["c".to_strbuf(), "C".to_strbuf()]);
    let sets = matches.free;

    if cflag && !dflag {
        show_error!(1, "-c is only supported with -d");
        return;
    }

    if dflag {
        let set1 = expand_set(sets.get(0).as_slice());
        delete(set1, cflag);
    } else {
        let set1 = expand_set(sets.get(0).as_slice());
        let set2 = expand_set(sets.get(1).as_slice());
        tr(set1.as_slice(), set2.as_slice());
    }
}
<|endoftext|>


<commit_before>use crate::airport_data::{Airport, AirportType, Position, Runway};
use actix_web::{post, web, HttpResponse};
use rand::seq::SliceRandom;
use serde_derive::{Deserialize, Serialize};
use smallvec::{smallvec, SmallVec};
use smol_str::SmolStr;
use std::ptr;
use std::{f32, u8};

const MAX_AIRPORTS_TO_GET: usize = 2000;
const MAX_AIRPORTS_TO_RETURN: usize = 100;

#[derive(Serialize)]
struct Response<'a> {
    routes: &'a [Route<'a>],
}

impl<'a> Response<'a> {
    #[inline(always)]
    fn new(routes: &'a [Route<'a>]) -> Self {
        Self { routes }
    }
}

#[post("/search_routes")]
pub async fn search_routes(
    filters: web::Json<Filters>,
    airports: web::Data<Vec<Airport>>,
) -> HttpResponse {
    let departures = filters
        .departure
        .as_ref()
        .map(|filters| filters.matching_airports(&airports))
        .unwrap_or_else(|| random_airport_set(&airports));

    let arrivals = filters
        .arrival
        .as_ref()
        .map(|filters| filters.matching_airports(&airports))
        .unwrap_or_else(|| random_airport_set(&airports));

    let mut routes = Vec::with_capacity(MAX_AIRPORTS_TO_RETURN / 2);

    for departure in departures {
        for arrival in &arrivals {
            if ptr::eq(departure, *arrival) {
                continue;
            }

            let route = Route::new(departure, arrival, filters.speed);

            if let Some(min) = filters.time_range.min {
                if route.time < min {
                    continue;
                }
            }

            if let Some(max) = filters.time_range.max {
                if route.time > max {
                    continue;
                }
            }

            routes.push(route);
        }
    }

    let mut routes = routes.as_mut_slice();

    if routes.len() > 1 {
        let (shuffled, _) = routes.partial_shuffle(&mut rand::thread_rng(), MAX_AIRPORTS_TO_RETURN);
        routes = shuffled;
    }

    HttpResponse::Ok().json(Response::new(routes))
}

#[inline(always)]
fn random_airport_set(airports: &[Airport]) -> AirportList {
    airports
        .choose_multiple(&mut rand::thread_rng(), MAX_AIRPORTS_TO_GET)
        .collect()
}

#[derive(Debug, Serialize)]
struct Route<'a> {
    from: &'a Airport,
    to: &'a Airport,
    distance: f32,
    time: Time,
}

impl<'a> Route<'a> {
    #[inline(always)]
    fn new(from: &'a Airport, to: &'a Airport, speed: Speed) -> Self {
        let distance = Self::calculate_distance(from.position, to.position);
        let time = Time::from_distance(distance, speed);

        Self {
            from,
            to,
            distance,
            time,
        }
    }

    /// Get the distance in nautical miles between two longitude and latitude points
    /// using the Haversine formula.
    fn calculate_distance(from: Position, to: Position) -> f32 {
        // Radius of Earth in nautical miles
        const RADIUS_NM: f32 = 3440.0;

        let from_lat = from.latitude_deg.to_radians();
        let to_lat = to.latitude_deg.to_radians();
        let lat = to_lat - from_lat;

        let lon = (to.longitude_deg - from.longitude_deg).to_radians();

        let a =
            (lat / 2.0).sin().powi(2) + from_lat.cos() * to_lat.cos() * (lon / 2.0).sin().powi(2);
        let c = 2.0 * a.sqrt().atan2((1.0 - a).sqrt());

        RADIUS_NM * c
    }
}

#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq, PartialOrd)]
pub struct Time {
    pub hour: u8,
    pub minutes: u8,
}

impl Time {
    fn from_distance(distance: f32, speed: Speed) -> Self {
        let total_hours = distance / speed.as_knots();

        let hour = total_hours.floor().min(99.0);
        let minutes = ((total_hours - hour) * 60.0).floor().min(59.0);

        Self {
            hour: hour as u8,
            minutes: minutes as u8,
        }
    }
}

#[derive(Debug, Default, Deserialize)]
pub struct TimeRange {
    pub min: Option<Time>,
    pub max: Option<Time>,
}

#[derive(Copy, Clone, Debug, Deserialize)]
#[serde(rename_all = "lowercase")]
#[serde(tag = "type", content = "value")]
pub enum Speed {
    Mach(f32),
    Knots(f32),
}

impl Speed {
    #[inline(always)]
    fn as_knots(self) -> f32 {
        const KNOTS_PER_MACH: f32 = 666.739;

        match self {
            Self::Mach(mach) => mach * KNOTS_PER_MACH,
            Self::Knots(knots) => knots,
        }
    }
}

#[derive(Debug, Deserialize)]
pub struct Filters {
    pub speed: Speed,
    pub departure: Option<AirportFilters>,
    pub arrival: Option<AirportFilters>,
    #[serde(rename = "timeRange", default)]
    pub time_range: TimeRange,
}

type AirportList<'a> = SmallVec<[&'a Airport; 1]>;

#[derive(Debug, Deserialize)]
pub struct AirportFilters {
    pub icao: Option<SmolStr>,
    #[serde(rename = "airportType", default)]
    pub airport_type: AirportType,
    #[serde(rename = "runwayLength")]
    pub runway_length: Option<RunwayLength>,
    #[serde(default)]
    pub countries: Vec<String>,
}

impl AirportFilters {
    pub fn matching_airports<'a>(&self, airports: &'a [Airport]) -> AirportList<'a> {
        if let Some(icao) = &self.icao {
            let index = airports
                .binary_search_by(|arpt| arpt.icao.as_str().cmp(icao.as_str()))
                .ok();

            let index = match index {
                Some(index) => index,
                None => return SmallVec::new(),
            };

            return smallvec![&airports[index]];
        }

        // TODO: convert to macro
        match (
            self.airport_type,
            &self.runway_length,
            self.countries.as_slice(),
        ) {
            (AirportType::Unknown, None, []) => Self::airport_matches(|_| true, airports),
            (arpt_type, None, []) => {
                Self::airport_matches(|arpt| arpt.class == arpt_type, airports)
            }
            (AirportType::Unknown, Some(len), []) => {
                Self::airport_matches(|arpt| len.fits_any(&arpt.runways), airports)
            }
            (arpt_type, Some(len), []) => Self::airport_matches(
                |arpt| arpt.class == arpt_type && len.fits_any(&arpt.runways),
                airports,
            ),
            (AirportType::Unknown, Some(len), countries) => Self::airport_matches(
                |arpt| {
                    len.fits_any(&arpt.runways) && Self::list_has_any(&arpt.country_name, countries)
                },
                airports,
            ),
            (arpt_type, Some(len), countries) => Self::airport_matches(
                |arpt| {
                    arpt.class == arpt_type
                        && len.fits_any(&arpt.runways)
                        && Self::list_has_any(&arpt.country_name, countries)
                },
                airports,
            ),
            (AirportType::Unknown, None, countries) => Self::airport_matches(
                |arpt| Self::list_has_any(&arpt.country_name, countries),
                airports,
            ),
            (arpt_type, None, countries) => Self::airport_matches(
                |arpt| arpt.class == arpt_type && Self::list_has_any(&arpt.country_name, countries),
                airports,
            ),
        }
    }

    fn airport_matches<'a, F>(matcher: F, airports: &'a [Airport]) -> AirportList<'a>
    where
        F: Fn(&Airport) -> bool,
    {
        let mut results = SmallVec::new();

        for airport in airports {
            if !matcher(airport) {
                continue;
            }

            results.push(airport);

            if results.len() >= MAX_AIRPORTS_TO_GET {
                break;
            }
        }

        results
    }

    #[inline(always)]
    fn list_has_any(name: &str, list: &[String]) -> bool {
        list.iter().any(|x| x.eq_ignore_ascii_case(name))
    }
}

#[derive(Copy, Clone, Debug, Deserialize)]
#[serde(tag = "selector", content = "length")]
pub enum RunwayLength {
    #[serde(rename = "eq")]
    Equal(u32),
    #[serde(rename = "gt")]
    GreaterThan(u32),
    #[serde(rename = "lt")]
    LessThan(u32),
}

impl RunwayLength {
    #[inline(always)]
    pub fn fits(self, length: u32) -> bool {
        match self {
            Self::Equal(len) => len == length,
            Self::GreaterThan(len) => length > len,
            Self::LessThan(len) => length < len,
        }
    }

    #[inline(always)]
    pub fn fits_any(self, runways: &[Runway]) -> bool {
        runways.iter().any(|runway| match runway.length_ft {
            Some(len) => self.fits(len),
            None => false,
        })
    }
}
<commit_msg>backend: Fix clippy warning<commit_after>use crate::airport_data::{Airport, AirportType, Position, Runway};
use actix_web::{post, web, HttpResponse};
use rand::seq::SliceRandom;
use serde_derive::{Deserialize, Serialize};
use smallvec::{smallvec, SmallVec};
use smol_str::SmolStr;
use std::ptr;
use std::{f32, u8};

const MAX_AIRPORTS_TO_GET: usize = 2000;
const MAX_AIRPORTS_TO_RETURN: usize = 100;

#[derive(Serialize)]
struct Response<'a> {
    routes: &'a [Route<'a>],
}

impl<'a> Response<'a> {
    #[inline(always)]
    fn new(routes: &'a [Route<'a>]) -> Self {
        Self { routes }
    }
}

#[post("/search_routes")]
pub async fn search_routes(
    filters: web::Json<Filters>,
    airports: web::Data<Vec<Airport>>,
) -> HttpResponse {
    let departures = filters
        .departure
        .as_ref()
        .map(|filters| filters.matching_airports(&airports))
        .unwrap_or_else(|| random_airport_set(&airports));

    let arrivals = filters
        .arrival
        .as_ref()
        .map(|filters| filters.matching_airports(&airports))
        .unwrap_or_else(|| random_airport_set(&airports));

    let mut routes = Vec::with_capacity(MAX_AIRPORTS_TO_RETURN / 2);

    for departure in departures {
        for arrival in &arrivals {
            if ptr::eq(departure, *arrival) {
                continue;
            }

            let route = Route::new(departure, arrival, filters.speed);

            if let Some(min) = filters.time_range.min {
                if route.time < min {
                    continue;
                }
            }

            if let Some(max) = filters.time_range.max {
                if route.time > max {
                    continue;
                }
            }

            routes.push(route);
        }
    }

    let mut routes = routes.as_mut_slice();

    if routes.len() > 1 {
        let (shuffled, _) = routes.partial_shuffle(&mut rand::thread_rng(), MAX_AIRPORTS_TO_RETURN);
        routes = shuffled;
    }

    HttpResponse::Ok().json(Response::new(routes))
}

#[inline(always)]
fn random_airport_set(airports: &[Airport]) -> AirportList {
    airports
        .choose_multiple(&mut rand::thread_rng(), MAX_AIRPORTS_TO_GET)
        .collect()
}

#[derive(Debug, Serialize)]
struct Route<'a> {
    from: &'a Airport,
    to: &'a Airport,
    distance: f32,
    time: Time,
}

impl<'a> Route<'a> {
    #[inline(always)]
    fn new(from: &'a Airport, to: &'a Airport, speed: Speed) -> Self {
        let distance = Self::calculate_distance(from.position, to.position);
        let time = Time::from_distance(distance, speed);

        Self {
            from,
            to,
            distance,
            time,
        }
    }

    /// Get the distance in nautical miles between two longitude and latitude points
    /// using the Haversine formula.
    fn calculate_distance(from: Position, to: Position) -> f32 {
        // Radius of Earth in nautical miles
        const RADIUS_NM: f32 = 3440.0;

        let from_lat = from.latitude_deg.to_radians();
        let to_lat = to.latitude_deg.to_radians();
        let lat = to_lat - from_lat;

        let lon = (to.longitude_deg - from.longitude_deg).to_radians();

        let a =
            (lat / 2.0).sin().powi(2) + from_lat.cos() * to_lat.cos() * (lon / 2.0).sin().powi(2);
        let c = 2.0 * a.sqrt().atan2((1.0 - a).sqrt());

        RADIUS_NM * c
    }
}

#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq, PartialOrd)]
pub struct Time {
    pub hour: u8,
    pub minutes: u8,
}

impl Time {
    fn from_distance(distance: f32, speed: Speed) -> Self {
        let total_hours = distance / speed.as_knots();

        let hour = total_hours.floor().min(99.0);
        let minutes = ((total_hours - hour) * 60.0).floor().min(59.0);

        Self {
            hour: hour as u8,
            minutes: minutes as u8,
        }
    }
}

#[derive(Debug, Default, Deserialize)]
pub struct TimeRange {
    pub min: Option<Time>,
    pub max: Option<Time>,
}

#[derive(Copy, Clone, Debug, Deserialize)]
#[serde(rename_all = "lowercase")]
#[serde(tag = "type", content = "value")]
pub enum Speed {
    Mach(f32),
    Knots(f32),
}

impl Speed {
    #[inline(always)]
    fn as_knots(self) -> f32 {
        const KNOTS_PER_MACH: f32 = 666.739;

        match self {
            Self::Mach(mach) => mach * KNOTS_PER_MACH,
            Self::Knots(knots) => knots,
        }
    }
}

#[derive(Debug, Deserialize)]
pub struct Filters {
    pub speed: Speed,
    pub departure: Option<AirportFilters>,
    pub arrival: Option<AirportFilters>,
    #[serde(rename = "timeRange", default)]
    pub time_range: TimeRange,
}

type AirportList<'a> = SmallVec<[&'a Airport; 1]>;

#[derive(Debug, Deserialize)]
pub struct AirportFilters {
    pub icao: Option<SmolStr>,
    #[serde(rename = "airportType", default)]
    pub airport_type: AirportType,
    #[serde(rename = "runwayLength")]
    pub runway_length: Option<RunwayLength>,
    #[serde(default)]
    pub countries: Vec<String>,
}

impl AirportFilters {
    pub fn matching_airports<'a>(&self, airports: &'a [Airport]) -> AirportList<'a> {
        if let Some(icao) = &self.icao {
            let index = airports
                .binary_search_by(|arpt| arpt.icao.as_str().cmp(icao.as_str()))
                .ok();

            let index = match index {
                Some(index) => index,
                None => return SmallVec::new(),
            };

            return smallvec![&airports[index]];
        }

        // TODO: convert to macro
        match (
            self.airport_type,
            &self.runway_length,
            self.countries.as_slice(),
        ) {
            (AirportType::Unknown, None, []) => Self::airport_matches(|_| true, airports),
            (arpt_type, None, []) => {
                Self::airport_matches(|arpt| arpt.class == arpt_type, airports)
            }
            (AirportType::Unknown, Some(len), []) => {
                Self::airport_matches(|arpt| len.fits_any(&arpt.runways), airports)
            }
            (arpt_type, Some(len), []) => Self::airport_matches(
                |arpt| arpt.class == arpt_type && len.fits_any(&arpt.runways),
                airports,
            ),
            (AirportType::Unknown, Some(len), countries) => Self::airport_matches(
                |arpt| {
                    len.fits_any(&arpt.runways) && Self::list_has_any(&arpt.country_name, countries)
                },
                airports,
            ),
            (arpt_type, Some(len), countries) => Self::airport_matches(
                |arpt| {
                    arpt.class == arpt_type
                        && len.fits_any(&arpt.runways)
                        && Self::list_has_any(&arpt.country_name, countries)
                },
                airports,
            ),
            (AirportType::Unknown, None, countries) => Self::airport_matches(
                |arpt| Self::list_has_any(&arpt.country_name, countries),
                airports,
            ),
            (arpt_type, None, countries) => Self::airport_matches(
                |arpt| arpt.class == arpt_type && Self::list_has_any(&arpt.country_name, countries),
                airports,
            ),
        }
    }

    fn airport_matches<F>(matcher: F, airports: &[Airport]) -> AirportList
    where
        F: Fn(&Airport) -> bool,
    {
        let mut results = SmallVec::new();

        for airport in airports {
            if !matcher(airport) {
                continue;
            }

            results.push(airport);

            if results.len() >= MAX_AIRPORTS_TO_GET {
                break;
            }
        }

        results
    }

    #[inline(always)]
    fn list_has_any(name: &str, list: &[String]) -> bool {
        list.iter().any(|x| x.eq_ignore_ascii_case(name))
    }
}

#[derive(Copy, Clone, Debug, Deserialize)]
#[serde(tag = "selector", content = "length")]
pub enum RunwayLength {
    #[serde(rename = "eq")]
    Equal(u32),
    #[serde(rename = "gt")]
    GreaterThan(u32),
    #[serde(rename = "lt")]
    LessThan(u32),
}

impl RunwayLength {
    #[inline(always)]
    pub fn fits(self, length: u32) -> bool {
        match self {
            Self::Equal(len) => len == length,
            Self::GreaterThan(len) => length > len,
            Self::LessThan(len) => length < len,
        }
    }

    #[inline(always)]
    pub fn fits_any(self, runways: &[Runway]) -> bool {
        runways.iter().any(|runway| match runway.length_ft {
            Some(len) => self.fits(len),
            None => false,
        })
    }
}
<|endoftext|>


<commit_before>use time;
use cgmath::point::{Point2};
use cgmath::vector::{Vector2};
use cgmath::aabb::{Aabb, Aabb2};
use color::rgb::{RGB, ToRGB};
use color::rgb::consts::*;
use stb::image;
use rectutil::RectUtil;
use engine::{App, Engine, Image};
use tile::Tile;
use world::area;
use world::area::{TerrainType, Location, ChartPos};
use world::fov;
use world::sprite::{Sprite, BLOCK_Z, FLOOR_Z, DrawContext};
use world::state::State;

static TILE_DATA: &'static [u8] = include_bin!("../../assets/tile.png");

pub static CUBE : uint = 0;
pub static CURSOR_BOTTOM : uint = 1;
pub static CURSOR_TOP : uint = 2;
pub static BLOCK_NW : uint = 3;
pub static BLOCK_N : uint = 4;
pub static BLOCK_NE : uint = 5;
pub static BLOCK_DARK : uint = 6;
pub static CHASM : uint = 7;
pub static SHALLOWS : uint = 8;
pub static PORTAL : uint = 9;
pub static BLANK_FLOOR : uint = 10;
pub static FLOOR : uint = 11;
pub static GRASS : uint = 12;
pub static WATER : uint = 13;
pub static MAGMA : uint = 14;
pub static DOWNSTAIRS : uint = 15;
pub static ROCKWALL : uint = 16;
pub static WALL : uint = 20;
pub static FENCE : uint = 24;
pub static BARS : uint = 28;
pub static WINDOW : uint = 32;
pub static DOOR : uint = 36;
pub static TREE_TRUNK : uint = 48;
pub static TREE_FOLIAGE : uint = 49;
pub static TABLE : uint = 50;
pub static AVATAR : uint = 51;
pub static BLOCK : uint = 52;
pub static FOUNTAIN : uint = 53;
pub static ALTAR : uint = 54;
pub static BARREL : uint = 55;
pub static STALAGMITE : uint = 56;
pub static GRAVE : uint = 58;
pub static STONE : uint = 69;
pub static MENHIR : uint = 70;
pub static TALLGRASS : uint = 80;

/// 3x3 grid of terrain cells. Use this as the input for terrain tile
/// computation, which will need to consider the immediate vicinity of cells.
pub struct Kernel<C> {
    n: C,
    ne: C,
    e: C,
    nw: C,
    center: C,
    se: C,
    w: C,
    sw: C,
    s: C,
}

impl<C: Clone> Kernel<C> {
    pub fn new(get: |Location| -> C, loc: Location) -> Kernel<C> {
        Kernel {
            n: get(loc + Vector2::new(-1, -1)),
            ne: get(loc + Vector2::new(0, -1)),
            e: get(loc + Vector2::new(1, -1)),
            nw: get(loc + Vector2::new(-1, 0)),
            center: get(loc),
            se: get(loc + Vector2::new(1, 0)),
            w: get(loc + Vector2::new(-1, 1)),
            sw: get(loc + Vector2::new(0, 1)),
            s: get(loc + Vector2::new(1, 1)),
        }
    }

    pub fn new_default(center: C, edge: C) -> Kernel<C> {
        Kernel {
            n: edge.clone(),
            ne: edge.clone(),
            e: edge.clone(),
            nw: edge.clone(),
            center: center,
            se: edge.clone(),
            w: edge.clone(),
            sw: edge.clone(),
            s: edge.clone(),
        }
    }
}

pub fn terrain_sprites<C: DrawContext>(
    ctx: &mut C, k: &Kernel<TerrainType>, pos: &Point2<f32>) {
    match k.center {
        area::Void => {
            ctx.draw(BLANK_FLOOR, pos, FLOOR_Z, &BLACK);
        },
        area::Water => {
            ctx.draw(WATER, pos, FLOOR_Z, &ROYALBLUE);
        },
        area::Shallows => {
            ctx.draw(SHALLOWS, pos, FLOOR_Z, &CORNFLOWERBLUE);
        },
        area::Magma => {
            ctx.draw(MAGMA, pos, FLOOR_Z, &DARKRED);
        },
        area::Tree => {
            // A two-toner, with floor, using two z-layers
            ctx.draw(FLOOR, pos, FLOOR_Z, &SLATEGRAY);
            ctx.draw(TREE_TRUNK, pos, BLOCK_Z, &SADDLEBROWN);
            ctx.draw(TREE_FOLIAGE, pos, BLOCK_Z, &GREEN);
        },
        area::Floor => {
            ctx.draw(FLOOR, pos, FLOOR_Z, &SLATEGRAY);
        },
        area::Chasm => {
            ctx.draw(CHASM, pos, FLOOR_Z, &DARKSLATEGRAY);
        },
        area::Grass => {
            ctx.draw(GRASS, pos, FLOOR_Z, &DARKGREEN);
        },
        area::Downstairs => {
            ctx.draw(FLOOR, pos, FLOOR_Z, &SLATEGRAY);
            ctx.draw(DOWNSTAIRS, pos, BLOCK_Z, &SLATEGRAY);
        },
        area::Portal => {
            let glow = (127.0 *(1.0 + (time::precise_time_s()).sin())) as u8;
            let portal_col = RGB::new(glow, glow, 255);
            ctx.draw(PORTAL, pos, BLOCK_Z, &portal_col);
        },
        area::Rock => {
            blockform(ctx, k, pos, BLOCK, &DARKGOLDENROD);
        }
        area::Wall => {
            ctx.draw(FLOOR, pos, FLOOR_Z, &SLATEGRAY);
            wallform(ctx, k, pos, WALL, &LIGHTSLATEGRAY, true);
        },
        area::RockWall => {
            ctx.draw(FLOOR, pos, FLOOR_Z, &SLATEGRAY);
            wallform(ctx, k, pos, ROCKWALL, &LIGHTSLATEGRAY, true);
        },
        area::Fence => {
            // The floor type beneath the fence tile is visible, make it grass if there's grass
            // behind the fence.
            if k.n == area::Grass || k.ne == area::Grass || k.nw == area::Grass {
                ctx.draw(GRASS, pos, FLOOR_Z, &DARKGREEN);
            } else {
                ctx.draw(FLOOR, pos, FLOOR_Z, &SLATEGRAY);
            }
            wallform(ctx, k, pos, FENCE, &DARKGOLDENROD, false);
        },
        area::Bars => {
            ctx.draw(FLOOR, pos, FLOOR_Z, &SLATEGRAY);
            wallform(ctx, k, pos, BARS, &GAINSBORO, false);
        },
        area::Stalagmite => {
            ctx.draw(FLOOR, pos, FLOOR_Z, &SLATEGRAY);
            ctx.draw(STALAGMITE, pos, BLOCK_Z, &DARKGOLDENROD);
        },
        area::Window => {
            ctx.draw(FLOOR, pos, FLOOR_Z, &SLATEGRAY);
            wallform(ctx, k, pos, WINDOW, &LIGHTSLATEGRAY, false);
        },
        area::Door => {
            ctx.draw(FLOOR, pos, FLOOR_Z, &SLATEGRAY);
            wallform(ctx, k, pos, DOOR, &LIGHTSLATEGRAY, true);
            wallform(ctx, k, pos, DOOR + 4, &SADDLEBROWN, false);
        },
        area::Table => {
            ctx.draw(FLOOR, pos, FLOOR_Z, &SLATEGRAY);
            ctx.draw(TABLE, pos, BLOCK_Z, &DARKKHAKI);
        },
        area::Fountain => {
            ctx.draw(FLOOR, pos, FLOOR_Z, &SLATEGRAY);
            ctx.draw(FOUNTAIN, pos, BLOCK_Z, &GAINSBORO);
        },
        area::Altar => {
            ctx.draw(FLOOR, pos, FLOOR_Z, &SLATEGRAY);
            ctx.draw(ALTAR, pos, BLOCK_Z, &GAINSBORO);
        },
        area::Barrel => {
            ctx.draw(FLOOR, pos, FLOOR_Z, &SLATEGRAY);
            ctx.draw(BARREL, pos, BLOCK_Z, &DARKKHAKI);
        },
        area::Grave => {
            ctx.draw(FLOOR, pos, FLOOR_Z, &SLATEGRAY);
            ctx.draw(GRAVE, pos, BLOCK_Z, &SLATEGRAY);
        },
        area::Stone => {
            ctx.draw(FLOOR, pos, FLOOR_Z, &SLATEGRAY);
            ctx.draw(STONE, pos, BLOCK_Z, &SLATEGRAY);
        },
        area::Menhir => {
            ctx.draw(FLOOR, pos, FLOOR_Z, &SLATEGRAY);
            ctx.draw(MENHIR, pos, BLOCK_Z, &SLATEGRAY);
        },
        area::DeadTree => {
            ctx.draw(FLOOR, pos, FLOOR_Z, &SLATEGRAY);
            ctx.draw(TREE_TRUNK, pos, BLOCK_Z, &SADDLEBROWN);
        },
        area::TallGrass => {
            ctx.draw(TALLGRASS, pos, FLOOR_Z, &GOLD);
        },
    }

    fn blockform<C: DrawContext>(ctx: &mut C, k: &Kernel<TerrainType>, pos: &Point2<f32>, idx: uint, color: &RGB<u8>) {
        ctx.draw(idx, pos, BLOCK_Z, color);
        // Back lines for blocks with open floor behind them.
        if !k.nw.is_wall() {
            ctx.draw(BLOCK_NW, pos, BLOCK_Z, color);
        }
        if !k.n.is_wall() {
            ctx.draw(BLOCK_N, pos, BLOCK_Z, color);
        }
        if !k.ne.is_wall() {
            ctx.draw(BLOCK_NE, pos, BLOCK_Z, color);
        }
    }

    fn wallform<C: DrawContext>(ctx: &mut C, k: &Kernel<TerrainType>, pos: &Point2<f32>, idx: uint, color: &RGB<u8>, opaque: bool) {
        let (left_wall, right_wall, block) = wall_flags_lrb(k);
        if block {
            if opaque {
                ctx.draw(CUBE, pos, BLOCK_Z, color);
            } else {
                ctx.draw(idx + 2, pos, BLOCK_Z, color);
                return;
            }
        }
        if left_wall && right_wall {
            ctx.draw(idx + 2, pos, BLOCK_Z, color);
        } else if left_wall {
            ctx.draw(idx, pos, BLOCK_Z, color);
        } else if right_wall {
            ctx.draw(idx + 1, pos, BLOCK_Z, color);
        } else if !block || !k.s.is_wall() {
            // NB: This branch has some actual local kernel logic not
            // handled by wall_flags_lrb.
            ctx.draw(idx + 3, pos, BLOCK_Z, color);
        }
    }

    // Return code:
    // (there is a wall piece to the left front of the tile,
    //  there is a wall piece to the right front of the tile,
    //  there is a solid block in the tile)
    fn wall_flags_lrb(k: &Kernel<TerrainType>) -> (bool, bool, bool) {
        if k.nw.is_wall() && k.n.is_wall() && k.ne.is_wall() {
            // If there is open space to east or west, even if this block
            // has adjacent walls to the southeast or the southwest, those
            // will be using thin wall sprites, so this block needs to have
            // the corresponding wall bit to make the wall line not have
            // gaps.
            (!k.w.is_wall() || !k.sw.is_wall(), !k.e.is_wall() || !k.se.is_wall(), true)
        } else {
            (k.nw.is_wall(), k.ne.is_wall(), false)
        }
    }
}

// TODO: Set up invariants so that draw_area cannot be called unless the tile
// set is set up.
pub fn init_tiles(ctx: &mut Engine) -> Vec<Image> {
    let tiles = image::Image::load_from_memory(TILE_DATA, 1).unwrap();
    let tiles = Tile::new_alpha_set(
        &Vector2::new(32, 32),
        &Vector2::new(tiles.width as int, tiles.height as int),
        tiles.pixels,
        &Vector2::new(-16, -16));
    ctx.make_images(&tiles)
}

struct SpriteCollector<'a> {
    pub sprites: Vec<Sprite>,
    pub mode: SpriteMode,
    engine: &'a mut Engine,
    tiles: &'a Vec<Image>,
}

enum SpriteMode {
    Normal,
    FogOfWar,
}

impl<'a> SpriteCollector<'a> {
    pub fn new<'a>(engine: &'a mut Engine, tiles: &'a Vec<Image>) -> SpriteCollector<'a> {
        SpriteCollector {
            sprites: vec!(),
            mode: Normal,
            engine: engine,
            tiles: tiles,
        }
    }
}

impl<'a> DrawContext for SpriteCollector<'a> {
    fn draw<C: ToRGB>(
        &mut self, idx: uint, pos: &Point2<f32>, z: f32, color: &C) {
        let color = match self.mode {
            Normal => color.to_rgb::<u8>(),
            FogOfWar => RGB::new(0x22u8, 0x22u8, 0x11u8),
        };

        self.engine.set_layer(z);
        self.engine.set_color(&color);
        self.engine.draw_image(self.tiles.get(idx), pos);
    }
}

pub fn draw_area<S: State>(ctx: &mut Engine, state: &S, tiles: &Vec<Image>) {
    let xf = state.transform();

    let mut rect = Aabb2::new(
        *xf.to_chart(&Point2::new(0f32, 0f32)).p(),
        *xf.to_chart(&Point2::new(640f32, 392f32)).p());
    rect = rect.grow(xf.to_chart(&Point2::new(640f32, 0f32)).p());
    rect = rect.grow(xf.to_chart(&Point2::new(0f32, 392f32)).p());

    for pt in rect.points() {
        let p = ChartPos::new(pt.x, pt.y);
        let offset = xf.to_screen(p);

        let loc = p.to_location();
        let kernel = Kernel::new(|p| state.area().get(p), loc);
        let mut acc = SpriteCollector::new(ctx, tiles);

        let fov = state.fov(loc);

        if fov == fov::Unknown {
            // Solid blocks for unseen areas, cover stuff in front.
            acc.draw(BLOCK_DARK, &offset, BLOCK_Z, &BLACK);
        } else {
            if fov == fov::Remembered { acc.mode = FogOfWar }
            terrain_sprites(&mut acc, &kernel, &offset);
        }

        /*
        if fov == fov::Seen {
            match state.drawable_mob_at(loc) {
                Some(mob) => {
                    for s in mob.sprites(&xf).iter() {
                        s.draw(ctx);
                    }
                }
                _ => ()
            };
        }
        */
    }
}
<commit_msg>Fix furniture colors<commit_after>use time;
use cgmath::point::{Point2};
use cgmath::vector::{Vector2};
use cgmath::aabb::{Aabb, Aabb2};
use color::rgb::{RGB, ToRGB};
use color::rgb::consts::*;
use stb::image;
use rectutil::RectUtil;
use engine::{App, Engine, Image};
use tile::Tile;
use world::area;
use world::area::{TerrainType, Location, ChartPos};
use world::fov;
use world::sprite::{Sprite, BLOCK_Z, FLOOR_Z, DrawContext};
use world::state::State;

static TILE_DATA: &'static [u8] = include_bin!("../../assets/tile.png");

pub static CUBE : uint = 0;
pub static CURSOR_BOTTOM : uint = 1;
pub static CURSOR_TOP : uint = 2;
pub static BLOCK_NW : uint = 3;
pub static BLOCK_N : uint = 4;
pub static BLOCK_NE : uint = 5;
pub static BLOCK_DARK : uint = 6;
pub static CHASM : uint = 7;
pub static SHALLOWS : uint = 8;
pub static PORTAL : uint = 9;
pub static BLANK_FLOOR : uint = 10;
pub static FLOOR : uint = 11;
pub static GRASS : uint = 12;
pub static WATER : uint = 13;
pub static MAGMA : uint = 14;
pub static DOWNSTAIRS : uint = 15;
pub static ROCKWALL : uint = 16;
pub static WALL : uint = 20;
pub static FENCE : uint = 24;
pub static BARS : uint = 28;
pub static WINDOW : uint = 32;
pub static DOOR : uint = 36;
pub static TREE_TRUNK : uint = 48;
pub static TREE_FOLIAGE : uint = 49;
pub static TABLE : uint = 50;
pub static AVATAR : uint = 51;
pub static BLOCK : uint = 52;
pub static FOUNTAIN : uint = 53;
pub static ALTAR : uint = 54;
pub static BARREL : uint = 55;
pub static STALAGMITE : uint = 56;
pub static GRAVE : uint = 58;
pub static STONE : uint = 69;
pub static MENHIR : uint = 70;
pub static TALLGRASS : uint = 80;

/// 3x3 grid of terrain cells. Use this as the input for terrain tile
/// computation, which will need to consider the immediate vicinity of cells.
pub struct Kernel<C> {
    n: C,
    ne: C,
    e: C,
    nw: C,
    center: C,
    se: C,
    w: C,
    sw: C,
    s: C,
}

impl<C: Clone> Kernel<C> {
    pub fn new(get: |Location| -> C, loc: Location) -> Kernel<C> {
        Kernel {
            n: get(loc + Vector2::new(-1, -1)),
            ne: get(loc + Vector2::new(0, -1)),
            e: get(loc + Vector2::new(1, -1)),
            nw: get(loc + Vector2::new(-1, 0)),
            center: get(loc),
            se: get(loc + Vector2::new(1, 0)),
            w: get(loc + Vector2::new(-1, 1)),
            sw: get(loc + Vector2::new(0, 1)),
            s: get(loc + Vector2::new(1, 1)),
        }
    }

    pub fn new_default(center: C, edge: C) -> Kernel<C> {
        Kernel {
            n: edge.clone(),
            ne: edge.clone(),
            e: edge.clone(),
            nw: edge.clone(),
            center: center,
            se: edge.clone(),
            w: edge.clone(),
            sw: edge.clone(),
            s: edge.clone(),
        }
    }
}

pub fn terrain_sprites<C: DrawContext>(
    ctx: &mut C, k: &Kernel<TerrainType>, pos: &Point2<f32>) {
    match k.center {
        area::Void => {
            ctx.draw(BLANK_FLOOR, pos, FLOOR_Z, &BLACK);
        },
        area::Water => {
            ctx.draw(WATER, pos, FLOOR_Z, &ROYALBLUE);
        },
        area::Shallows => {
            ctx.draw(SHALLOWS, pos, FLOOR_Z, &CORNFLOWERBLUE);
        },
        area::Magma => {
            ctx.draw(MAGMA, pos, FLOOR_Z, &DARKRED);
        },
        area::Tree => {
            // A two-toner, with floor, using two z-layers
            ctx.draw(FLOOR, pos, FLOOR_Z, &SLATEGRAY);
            ctx.draw(TREE_TRUNK, pos, BLOCK_Z, &SADDLEBROWN);
            ctx.draw(TREE_FOLIAGE, pos, BLOCK_Z, &GREEN);
        },
        area::Floor => {
            ctx.draw(FLOOR, pos, FLOOR_Z, &SLATEGRAY);
        },
        area::Chasm => {
            ctx.draw(CHASM, pos, FLOOR_Z, &DARKSLATEGRAY);
        },
        area::Grass => {
            ctx.draw(GRASS, pos, FLOOR_Z, &DARKGREEN);
        },
        area::Downstairs => {
            ctx.draw(FLOOR, pos, FLOOR_Z, &SLATEGRAY);
            ctx.draw(DOWNSTAIRS, pos, BLOCK_Z, &SLATEGRAY);
        },
        area::Portal => {
            let glow = (127.0 *(1.0 + (time::precise_time_s()).sin())) as u8;
            let portal_col = RGB::new(glow, glow, 255);
            ctx.draw(PORTAL, pos, BLOCK_Z, &portal_col);
        },
        area::Rock => {
            blockform(ctx, k, pos, BLOCK, &DARKGOLDENROD);
        }
        area::Wall => {
            ctx.draw(FLOOR, pos, FLOOR_Z, &SLATEGRAY);
            wallform(ctx, k, pos, WALL, &LIGHTSLATEGRAY, true);
        },
        area::RockWall => {
            ctx.draw(FLOOR, pos, FLOOR_Z, &SLATEGRAY);
            wallform(ctx, k, pos, ROCKWALL, &LIGHTSLATEGRAY, true);
        },
        area::Fence => {
            // The floor type beneath the fence tile is visible, make it grass if there's grass
            // behind the fence.
            if k.n == area::Grass || k.ne == area::Grass || k.nw == area::Grass {
                ctx.draw(GRASS, pos, FLOOR_Z, &DARKGREEN);
            } else {
                ctx.draw(FLOOR, pos, FLOOR_Z, &SLATEGRAY);
            }
            wallform(ctx, k, pos, FENCE, &DARKGOLDENROD, false);
        },
        area::Bars => {
            ctx.draw(FLOOR, pos, FLOOR_Z, &SLATEGRAY);
            wallform(ctx, k, pos, BARS, &GAINSBORO, false);
        },
        area::Stalagmite => {
            ctx.draw(FLOOR, pos, FLOOR_Z, &SLATEGRAY);
            ctx.draw(STALAGMITE, pos, BLOCK_Z, &DARKGOLDENROD);
        },
        area::Window => {
            ctx.draw(FLOOR, pos, FLOOR_Z, &SLATEGRAY);
            wallform(ctx, k, pos, WINDOW, &LIGHTSLATEGRAY, false);
        },
        area::Door => {
            ctx.draw(FLOOR, pos, FLOOR_Z, &SLATEGRAY);
            wallform(ctx, k, pos, DOOR, &LIGHTSLATEGRAY, true);
            wallform(ctx, k, pos, DOOR + 4, &SADDLEBROWN, false);
        },
        area::Table => {
            ctx.draw(FLOOR, pos, FLOOR_Z, &SLATEGRAY);
            ctx.draw(TABLE, pos, BLOCK_Z, &DARKGOLDENROD);
        },
        area::Fountain => {
            ctx.draw(FLOOR, pos, FLOOR_Z, &SLATEGRAY);
            ctx.draw(FOUNTAIN, pos, BLOCK_Z, &GAINSBORO);
        },
        area::Altar => {
            ctx.draw(FLOOR, pos, FLOOR_Z, &SLATEGRAY);
            ctx.draw(ALTAR, pos, BLOCK_Z, &GAINSBORO);
        },
        area::Barrel => {
            ctx.draw(FLOOR, pos, FLOOR_Z, &SLATEGRAY);
            ctx.draw(BARREL, pos, BLOCK_Z, &DARKGOLDENROD);
        },
        area::Grave => {
            ctx.draw(FLOOR, pos, FLOOR_Z, &SLATEGRAY);
            ctx.draw(GRAVE, pos, BLOCK_Z, &SLATEGRAY);
        },
        area::Stone => {
            ctx.draw(FLOOR, pos, FLOOR_Z, &SLATEGRAY);
            ctx.draw(STONE, pos, BLOCK_Z, &SLATEGRAY);
        },
        area::Menhir => {
            ctx.draw(FLOOR, pos, FLOOR_Z, &SLATEGRAY);
            ctx.draw(MENHIR, pos, BLOCK_Z, &SLATEGRAY);
        },
        area::DeadTree => {
            ctx.draw(FLOOR, pos, FLOOR_Z, &SLATEGRAY);
            ctx.draw(TREE_TRUNK, pos, BLOCK_Z, &SADDLEBROWN);
        },
        area::TallGrass => {
            ctx.draw(TALLGRASS, pos, FLOOR_Z, &GOLD);
        },
    }

    fn blockform<C: DrawContext>(ctx: &mut C, k: &Kernel<TerrainType>, pos: &Point2<f32>, idx: uint, color: &RGB<u8>) {
        ctx.draw(idx, pos, BLOCK_Z, color);
        // Back lines for blocks with open floor behind them.
        if !k.nw.is_wall() {
            ctx.draw(BLOCK_NW, pos, BLOCK_Z, color);
        }
        if !k.n.is_wall() {
            ctx.draw(BLOCK_N, pos, BLOCK_Z, color);
        }
        if !k.ne.is_wall() {
            ctx.draw(BLOCK_NE, pos, BLOCK_Z, color);
        }
    }

    fn wallform<C: DrawContext>(ctx: &mut C, k: &Kernel<TerrainType>, pos: &Point2<f32>, idx: uint, color: &RGB<u8>, opaque: bool) {
        let (left_wall, right_wall, block) = wall_flags_lrb(k);
        if block {
            if opaque {
                ctx.draw(CUBE, pos, BLOCK_Z, color);
            } else {
                ctx.draw(idx + 2, pos, BLOCK_Z, color);
                return;
            }
        }
        if left_wall && right_wall {
            ctx.draw(idx + 2, pos, BLOCK_Z, color);
        } else if left_wall {
            ctx.draw(idx, pos, BLOCK_Z, color);
        } else if right_wall {
            ctx.draw(idx + 1, pos, BLOCK_Z, color);
        } else if !block || !k.s.is_wall() {
            // NB: This branch has some actual local kernel logic not
            // handled by wall_flags_lrb.
            ctx.draw(idx + 3, pos, BLOCK_Z, color);
        }
    }

    // Return code:
    // (there is a wall piece to the left front of the tile,
    //  there is a wall piece to the right front of the tile,
    //  there is a solid block in the tile)
    fn wall_flags_lrb(k: &Kernel<TerrainType>) -> (bool, bool, bool) {
        if k.nw.is_wall() && k.n.is_wall() && k.ne.is_wall() {
            // If there is open space to east or west, even if this block
            // has adjacent walls to the southeast or the southwest, those
            // will be using thin wall sprites, so this block needs to have
            // the corresponding wall bit to make the wall line not have
            // gaps.
            (!k.w.is_wall() || !k.sw.is_wall(), !k.e.is_wall() || !k.se.is_wall(), true)
        } else {
            (k.nw.is_wall(), k.ne.is_wall(), false)
        }
    }
}

// TODO: Set up invariants so that draw_area cannot be called unless the tile
// set is set up.
pub fn init_tiles(ctx: &mut Engine) -> Vec<Image> {
    let tiles = image::Image::load_from_memory(TILE_DATA, 1).unwrap();
    let tiles = Tile::new_alpha_set(
        &Vector2::new(32, 32),
        &Vector2::new(tiles.width as int, tiles.height as int),
        tiles.pixels,
        &Vector2::new(-16, -16));
    ctx.make_images(&tiles)
}

struct SpriteCollector<'a> {
    pub sprites: Vec<Sprite>,
    pub mode: SpriteMode,
    engine: &'a mut Engine,
    tiles: &'a Vec<Image>,
}

enum SpriteMode {
    Normal,
    FogOfWar,
}

impl<'a> SpriteCollector<'a> {
    pub fn new<'a>(engine: &'a mut Engine, tiles: &'a Vec<Image>) -> SpriteCollector<'a> {
        SpriteCollector {
            sprites: vec!(),
            mode: Normal,
            engine: engine,
            tiles: tiles,
        }
    }
}

impl<'a> DrawContext for SpriteCollector<'a> {
    fn draw<C: ToRGB>(
        &mut self, idx: uint, pos: &Point2<f32>, z: f32, color: &C) {
        let color = match self.mode {
            Normal => color.to_rgb::<u8>(),
            FogOfWar => RGB::new(0x22u8, 0x22u8, 0x11u8),
        };

        self.engine.set_layer(z);
        self.engine.set_color(&color);
        self.engine.draw_image(self.tiles.get(idx), pos);
    }
}

pub fn draw_area<S: State>(ctx: &mut Engine, state: &S, tiles: &Vec<Image>) {
    let xf = state.transform();

    let mut rect = Aabb2::new(
        *xf.to_chart(&Point2::new(0f32, 0f32)).p(),
        *xf.to_chart(&Point2::new(640f32, 392f32)).p());
    rect = rect.grow(xf.to_chart(&Point2::new(640f32, 0f32)).p());
    rect = rect.grow(xf.to_chart(&Point2::new(0f32, 392f32)).p());

    for pt in rect.points() {
        let p = ChartPos::new(pt.x, pt.y);
        let offset = xf.to_screen(p);

        let loc = p.to_location();
        let kernel = Kernel::new(|p| state.area().get(p), loc);
        let mut acc = SpriteCollector::new(ctx, tiles);

        let fov = state.fov(loc);

        if fov == fov::Unknown {
            // Solid blocks for unseen areas, cover stuff in front.
            acc.draw(BLOCK_DARK, &offset, BLOCK_Z, &BLACK);
        } else {
            if fov == fov::Remembered { acc.mode = FogOfWar }
            terrain_sprites(&mut acc, &kernel, &offset);
        }

        /*
        if fov == fov::Seen {
            match state.drawable_mob_at(loc) {
                Some(mob) => {
                    for s in mob.sprites(&xf).iter() {
                        s.draw(ctx);
                    }
                }
                _ => ()
            };
        }
        */
    }
}
<|endoftext|>


<commit_before>use intern::intern;
use grammar::repr::*;
use test_util::{compare, expect_debug, normalized_grammar};
use lr1::build;
use lr1::core::*;
use tls::Tls;

use super::lane::LaneTracer;
use super::table::ConflictIndex;

fn sym(t: &str) -> Symbol {
    if t.chars().next().unwrap().is_uppercase() {
        Symbol::Nonterminal(nt(t))
    } else {
        Symbol::Terminal(term(t))
    }
}

fn term(t: &str) -> TerminalString {
    TerminalString::Literal(TerminalLiteral::Quoted(intern(t)))
}

fn nt(t: &str) -> NonterminalString {
    NonterminalString(intern(t))
}

/// A simplified version of the paper's initial grammar; this version
/// only has one inconsistent state (the same state they talk about in
/// the paper).
pub fn paper_example_small() -> Grammar {
    normalized_grammar(r#"
grammar;

pub G: () = {
    X "c",
    Y "d",
};

X: () = {
    "e" X,
    "e",
};

Y: () = {
    "e" Y,
    "e"
};
"#)
}

#[test]
fn small_conflict_1() {
    let _tls = Tls::test();
    let grammar = paper_example_small();
    let lr0_states = build::build_lr0_states(&grammar, nt("G")).unwrap_err().states;
    assert_eq!(lr0_states.iter().filter(|s| !s.conflicts.is_empty()).count(), 1);
    let inconsistent_state = lr0_states.iter()
                                       .filter(|s| !s.conflicts.is_empty())
                                       .next()
                                       .unwrap();
    let conflicting_items = super::conflicting_items(inconsistent_state);
    println!("{:#?}", conflicting_items);
    let mut tracer = LaneTracer::new(&grammar, &lr0_states, conflicting_items.len());
    for (i, &conflicting_item) in conflicting_items.iter().enumerate() {
        tracer.start_trace(inconsistent_state.index,
                           ConflictIndex::new(i),
                           conflicting_item);
    }
    let table = tracer.into_table();
    println!("{:#?}", table);
    expect_debug(&table, r#"
| State | C0    | C1    | C2    | C3    | C4    | C5    | Successors |
| S0    | ["c"] | ["c"] | ["c"] | ["d"] | ["d"] | ["d"] |            |
| S3    | []    | []    | []    | []    | []    | []    | {S0, S3}   |
"#.trim_left());
}

pub fn paper_example_large() -> Grammar {
    normalized_grammar(r#"
grammar;

pub G: () = {
    "x" W "a",
    "x" V "t",
    "y" W "b",
    "y" V "t",
    "z" W "r",
    "z" V "b",
    "u" U X "a",
    "u" U Y "r",
};

W: () = {
    U X C
};

V: () = {
    U Y "d"
};

X: () = {
    "k" "t" U X P,
    "k" "t"
};

Y: () = {
    "k" "t" U Y "u",
    "k" "t"
};

U: () = {
    U "k" "t",
    "s"
};

E: () = {
    "a",
    "b",
    "c",
    "v",
};

C: () = {
    "c",
    "w"
};

P: () = {
    "z"
};
"#)
}

<commit_msg>add test for big lane table<commit_after>use intern::intern;
use grammar::repr::*;
use test_util::{compare, expect_debug, normalized_grammar};
use lr1::build;
use lr1::core::*;
use lr1::interpret;
use tls::Tls;

use super::lane::*;
use super::table::*;

fn sym(t: &str) -> Symbol {
    if t.chars().next().unwrap().is_uppercase() {
        Symbol::Nonterminal(nt(t))
    } else {
        Symbol::Terminal(term(t))
    }
}

fn term(t: &str) -> TerminalString {
    TerminalString::Literal(TerminalLiteral::Quoted(intern(t)))
}

fn nt(t: &str) -> NonterminalString {
    NonterminalString(intern(t))
}

fn traverse(states: &[LR0State], tokens: &[&str]) -> StateIndex {
    interpret::interpret_partial(states, tokens.iter().map(|&s| term(s))).unwrap().pop().unwrap()
}

/// A simplified version of the paper's initial grammar; this version
/// only has one inconsistent state (the same state they talk about in
/// the paper).
pub fn paper_example_small() -> Grammar {
    normalized_grammar(r#"
grammar;

pub G: () = {
    X "c",
    Y "d",
};

X: () = {
    "e" X,
    "e",
};

Y: () = {
    "e" Y,
    "e"
};
"#)
}

fn build_table<'grammar>(grammar: &'grammar Grammar,
                         goal: &str,
                         tokens: &[&str])
                         -> LaneTable<'grammar> {
    let lr0_states = build::build_lr0_states(&grammar, nt(goal)).unwrap_err().states;
    assert_eq!(lr0_states.iter().filter(|s| !s.conflicts.is_empty()).count(),
               1);

    // Push the `tokens` to find the index of the inconsistent state
    let inconsistent_state_index = traverse(&lr0_states, tokens);
    let inconsistent_state = &lr0_states[inconsistent_state_index.0];
    assert!(!inconsistent_state.conflicts.is_empty());
    println!("inconsistent_state={:#?}", inconsistent_state.items);

    // Extract conflicting items and trace the lanes, constructing a table
    let conflicting_items = super::conflicting_items(inconsistent_state);
    println!("conflicting_items={:#?}", conflicting_items);
    let mut tracer = LaneTracer::new(&grammar, &lr0_states, conflicting_items.len());
    for (i, &conflicting_item) in conflicting_items.iter().enumerate() {
        tracer.start_trace(inconsistent_state.index,
                           ConflictIndex::new(i),
                           conflicting_item);
    }

    tracer.into_table()
}

#[test]
fn small_conflict_1() {
    let _tls = Tls::test();
    let grammar = paper_example_small();
    let table = build_table(&grammar, "G", &["e"]);
    println!("{:#?}", table);
    expect_debug(&table,
                 r#"
| State | C0    | C1    | C2    | C3    | C4    | C5    | Successors |
| S0    | ["c"] | ["c"] | ["c"] | ["d"] | ["d"] | ["d"] |            |
| S3    | []    | []    | []    | []    | []    | []    | {S0, S3}   |
"#
                     .trim_left());
}

pub fn paper_example_large() -> Grammar {
    normalized_grammar(r#"
grammar;

pub G: () = {
    "x" W "a",
    "x" V "t",
    "y" W "b",
    "y" V "t",
    "z" W "r",
    "z" V "b",
    "u" U X "a",
    "u" U Y "r",
};

W: () = {
    U X C
};

V: () = {
    U Y "d"
};

X: () = {
    "k" "t" U X P,
    "k" "t"
};

Y: () = {
    "k" "t" U Y "u",
    "k" "t"
};

U: () = {
    U "k" "t",
    "s"
};

E: () = {
    "a",
    "b",
    "c",
    "v",
};

C: () = {
    "c",
    "w"
};

P: () = {
    "z"
};
"#)
}

#[test]
fn large_conflict_1() {
    let _tls = Tls::test();
    let grammar = paper_example_large();
    let table = build_table(&grammar, "G", &["x", "s", "k", "t"]);
    println!("{:#?}", table);
    expect_debug(&table,
                 r#"
| State | C0    | C1    | C2         | C3    | Successors |
| S1    | ["k"] |       |            |       | {S5}       |
| S2    | ["k"] |       |            |       | {S7}       |
| S3    | ["k"] |       |            |       | {S7}       |
| S4    | ["k"] |       |            |       | {S7}       |
| S5    |       |       | ["a"]      | ["r"] | {S16}      |
| S7    |       |       | ["c", "w"] | ["d"] | {S16}      |
| S16   |       |       |            |       | {S27}      |
| S27   | ["k"] | ["s"] |            |       | {S32}      |
| S32   |       |       | ["z"]      | ["u"] | {S16}      |
"#
                 .trim_left());

    // ^^ This differs in some particulars from what appears in the
    // paper, but I believe it to be correct, and the paper to be wrong.
    //
    // Here is the table using the state names from the paper. I've marked
    // the differences with `(*)`.
    //
    // | State | pi1   | pi2   | pi3        | Successors |
    // | B     | ["k"] |       | *1         | {G}        |
    // | C     | ["k"] |       | *1         | {G}        |
    // | D     | ["k"] |       | *1         | {G}        |
    // | E     | ["k"] |       |            | {F}        |
    // | F     |       | ["r"] | ["a"]      | {H}        |
    // | G     |       | ["d"] | ["c", "w"] | {H}        |
    // | H     |       |       |            | {I}        |
    // | I     | ["k"] |       |            | {J}        |
    // | J     |       | ["u"] | ["z"] *2   | {H}        |
    //
    // *1 - the paper lists "a", "b", and "r" here as lookaheads.  We
    // do not. This is because when we trace back pi3, we never reach
    // those states, as we have already acquired the necessary token
    // of context earlier. I can imagine a distinct lane tracing
    // algorithm that considers *sets* of conflicts and only
    // terminates when all sets have context, but it's much more
    // complex to implement, and seems to add little value.
    //
    // *2 - the paper does not list this context, and yet it seems to
    // present. If you trace back "t" and "k" you reach state J which
    // has the item "X = k t (*)". This "unepsilons" to "X = k t U (*)
    // X P", and the lookahead from the "X" here is FIRST(P) which is
    // "z".
}
<|endoftext|>


<commit_before>//! Starts a timely dataflow execution from configuration information and per-worker logic.

use crate::communication::{initialize_from, Configuration, Allocator, allocator::AllocateBuilder, WorkerGuards};
use crate::dataflow::scopes::Child;
use crate::worker::Worker;

/// Executes a single-threaded timely dataflow computation.
///
/// The `example` method takes a closure on a `Scope` which it executes to initialize and run a
/// timely dataflow computation on a single thread. This method is intended for use in examples,
/// rather than programs that may need to run across multiple workers.
///
/// The `example` method returns whatever the single worker returns from its closure.
/// This is often nothing, but the worker can return something about the data it saw in order to
/// test computations.
///
/// The method aggressively unwraps returned `Result<_>` types.
///
/// # Examples
///
/// The simplest example creates a stream of data and inspects it.
///
/// ```rust
/// use timely::dataflow::operators::{ToStream, Inspect};
///
/// timely::example(|scope| {
///     (0..10).to_stream(scope)
///            .inspect(|x| println!("seen: {:?}", x));
/// });
/// ```
///
/// This next example captures the data and displays them once the computation is complete.
///
/// More precisely, the example captures a stream of events (receiving batches of data,
/// updates to input capabilities) and displays these events.
///
/// ```rust
/// use timely::dataflow::operators::{ToStream, Inspect, Capture};
/// use timely::dataflow::operators::capture::Extract;
///
/// let data = timely::example(|scope| {
///     (0..10).to_stream(scope)
///            .inspect(|x| println!("seen: {:?}", x))
///            .capture()
/// });
///
/// // the extracted data should have data (0..10) at timestamp 0.
/// assert_eq!(data.extract()[0].1, (0..10).collect::<Vec<_>>());
/// ```
pub fn example<T, F>(func: F) -> T
where
    T: Send+'static,
    F: FnOnce(&mut Child<Worker<crate::communication::allocator::thread::Thread>,u64>)->T+Send+Sync+'static
{
    crate::execute::execute_directly(|worker| worker.dataflow(|scope| func(scope)))
}

/// Executes a single-threaded timely dataflow computation.
///
/// The `execute_directly` constructs a `Worker` and directly executes the supplied
/// closure to construct and run a timely dataflow computation. It does not create any
/// worker threads, and simply uses the current thread of control.
///
/// The closure may return a result, which will be returned from the computation.
///
/// # Examples
/// ```rust
/// use timely::dataflow::operators::{ToStream, Inspect};
///
/// // execute a timely dataflow using three worker threads.
/// timely::execute_directly(|worker| {
///     worker.dataflow::<(),_,_>(|scope| {
///         (0..10).to_stream(scope)
///                .inspect(|x| println!("seen: {:?}", x));
///     })
/// });
/// ```
pub fn execute_directly<T, F>(func: F) -> T
where
    T: Send+'static,
    F: FnOnce(&mut Worker<crate::communication::allocator::thread::Thread>)->T+Send+Sync+'static
{
    let alloc = crate::communication::allocator::thread::Thread::new();
    let mut worker = crate::worker::Worker::new(alloc);
    let result = func(&mut worker);
    while worker.step_or_park() { }
    result
}

/// Executes a timely dataflow from a configuration and per-communicator logic.
///
/// The `execute` method takes a `Configuration` and spins up some number of
/// workers threads, each of which execute the supplied closure to construct
/// and run a timely dataflow computation.
///
/// The closure may return a `T: Send+'static`, and `execute` returns a result
/// containing a `WorkerGuards<T>` (or error information), which can be joined
/// to recover the result `T` values from the local workers.
///
/// # Examples
/// ```rust
/// use timely::dataflow::operators::{ToStream, Inspect};
///
/// // execute a timely dataflow using three worker threads.
/// timely::execute(timely::Configuration::Process(3), |worker| {
///     worker.dataflow::<(),_,_>(|scope| {
///         (0..10).to_stream(scope)
///                .inspect(|x| println!("seen: {:?}", x));
///     })
/// }).unwrap();
/// ```
///
/// The following example demonstrates how one can extract data from a multi-worker execution.
/// In a multi-process setting, each process will only receive those records present at workers
/// in the process.
///
/// ```rust
/// use std::sync::{Arc, Mutex};
/// use timely::dataflow::operators::{ToStream, Inspect, Capture};
/// use timely::dataflow::operators::capture::Extract;
///
/// // get send and recv endpoints, wrap send to share
/// let (send, recv) = ::std::sync::mpsc::channel();
/// let send = Arc::new(Mutex::new(send));
///
/// // execute a timely dataflow using three worker threads.
/// timely::execute(timely::Configuration::Process(3), move |worker| {
///     let send = send.lock().unwrap().clone();
///     worker.dataflow::<(),_,_>(move |scope| {
///         (0..10).to_stream(scope)
///                .inspect(|x| println!("seen: {:?}", x))
///                .capture_into(send);
///     });
/// }).unwrap();
///
/// // the extracted data should have data (0..10) thrice at timestamp 0.
/// assert_eq!(recv.extract()[0].1, (0..30).map(|x| x / 3).collect::<Vec<_>>());
/// ```
pub fn execute<T, F>(mut config: Configuration, func: F) -> Result<WorkerGuards<T>,String>
where
    T:Send+'static,
    F: Fn(&mut Worker<Allocator>)->T+Send+Sync+'static {

    if let Configuration::Cluster { ref mut log_fn, .. } = config {

        *log_fn = Box::new(|events_setup| {

            let mut result = None;
            if let Ok(addr) = ::std::env::var("TIMELY_COMM_LOG_ADDR") {

                use ::std::net::TcpStream;
                use crate::logging::BatchLogger;
                use crate::dataflow::operators::capture::EventWriter;

                eprintln!("enabled COMM logging to {}", addr);

                if let Ok(stream) = TcpStream::connect(&addr) {
                    let writer = EventWriter::new(stream);
                    let mut logger = BatchLogger::new(writer);
                    result = Some(crate::logging_core::Logger::new(
                        ::std::time::Instant::now(),
                        events_setup,
                        move |time, data| logger.publish_batch(time, data)
                    ));
                }
                else {
                    panic!("Could not connect to communication log address: {:?}", addr);
                }
            }
            result
        });
    }

    let (allocators, other) = config.try_build()?;

    initialize_from(allocators, other, move |allocator| {

        let mut worker = Worker::new(allocator);

        // If an environment variable is set, use it as the default timely logging.
        if let Ok(addr) = ::std::env::var("TIMELY_WORKER_LOG_ADDR") {

            use ::std::net::TcpStream;
            use crate::logging::{BatchLogger, TimelyEvent};
            use crate::dataflow::operators::capture::EventWriter;

            if let Ok(stream) = TcpStream::connect(&addr) {
                let writer = EventWriter::new(stream);
                let mut logger = BatchLogger::new(writer);
                worker.log_register()
                    .insert::<TimelyEvent,_>("timely", move |time, data|
                        logger.publish_batch(time, data)
                    );
            }
            else {
                panic!("Could not connect logging stream to: {:?}", addr);
            }
        }

        let result = func(&mut worker);
        while worker.step_or_park(None) { }
        result
    })
}

/// Executes a timely dataflow from supplied arguments and per-communicator logic.
///
/// The `execute` method takes arguments (typically `std::env::args()`) and spins up some number of
/// workers threads, each of which execute the supplied closure to construct and run a timely
/// dataflow computation.
///
/// The closure may return a `T: Send+'static`, and `execute` returns a result
/// containing a `WorkerGuards<T>` (or error information), which can be joined
/// to recover the result `T` values from the local workers.
///
/// The arguments `execute` currently understands are:
///
/// `-w, --workers`: number of per-process worker threads.
///
/// `-n, --processes`: number of processes involved in the computation.
///
/// `-p, --process`: identity of this process; from 0 to n-1.
///
/// `-h, --hostfile`: a text file whose lines are "hostname:port" in order of process identity.
/// If not specified, `localhost` will be used, with port numbers increasing from 2101 (chosen
/// arbitrarily).
///
/// # Examples
///
/// ```rust
/// use timely::dataflow::operators::{ToStream, Inspect};
///
/// // execute a timely dataflow using command line parameters
/// timely::execute_from_args(std::env::args(), |worker| {
///     worker.dataflow::<(),_,_>(|scope| {
///         (0..10).to_stream(scope)
///                .inspect(|x| println!("seen: {:?}", x));
///     })
/// }).unwrap();
/// ```
/// ```ignore
/// host0% cargo run -- -w 2 -n 4 -h hosts.txt -p 0
/// host1% cargo run -- -w 2 -n 4 -h hosts.txt -p 1
/// host2% cargo run -- -w 2 -n 4 -h hosts.txt -p 2
/// host3% cargo run -- -w 2 -n 4 -h hosts.txt -p 3
/// ```
/// ```ignore
/// % cat hosts.txt
/// host0:port
/// host1:port
/// host2:port
/// host3:port
/// ```
pub fn execute_from_args<I, T, F>(iter: I, func: F) -> Result<WorkerGuards<T>,String>
    where I: Iterator<Item=String>,
          T:Send+'static,
          F: Fn(&mut Worker<Allocator>)->T+Send+Sync+'static, {
    let configuration = Configuration::from_args(iter)?;
    execute(configuration, func)
}

/// Executes a timely dataflow from supplied allocators and logging.
///
/// Refer to [`execute`](fn.execute.html) for more details.
///
/// ```rust
/// use timely::dataflow::operators::{ToStream, Inspect};
///
/// // execute a timely dataflow using command line parameters
/// let (builders, other) = timely::Configuration::Process(3).try_build().unwrap();
/// timely::execute::execute_from(builders, other, |worker| {
///     worker.dataflow::<(),_,_>(|scope| {
///         (0..10).to_stream(scope)
///                .inspect(|x| println!("seen: {:?}", x));
///     })
/// }).unwrap();
/// ```
pub fn execute_from<A, T, F>(builders: Vec<A>, others: Box<::std::any::Any>, func: F) -> Result<WorkerGuards<T>,String>
where
    A: AllocateBuilder+'static,
    T: Send+'static,
    F: Fn(&mut Worker<<A as AllocateBuilder>::Allocator>)->T+Send+Sync+'static {
    initialize_from(builders, others, move |allocator| {
        let mut worker = Worker::new(allocator);
        let result = func(&mut worker);
        while worker.step_or_park(None) { }
        result
    })
}<commit_msg>oops; add None argument<commit_after>//! Starts a timely dataflow execution from configuration information and per-worker logic.

use crate::communication::{initialize_from, Configuration, Allocator, allocator::AllocateBuilder, WorkerGuards};
use crate::dataflow::scopes::Child;
use crate::worker::Worker;

/// Executes a single-threaded timely dataflow computation.
///
/// The `example` method takes a closure on a `Scope` which it executes to initialize and run a
/// timely dataflow computation on a single thread. This method is intended for use in examples,
/// rather than programs that may need to run across multiple workers.
///
/// The `example` method returns whatever the single worker returns from its closure.
/// This is often nothing, but the worker can return something about the data it saw in order to
/// test computations.
///
/// The method aggressively unwraps returned `Result<_>` types.
///
/// # Examples
///
/// The simplest example creates a stream of data and inspects it.
///
/// ```rust
/// use timely::dataflow::operators::{ToStream, Inspect};
///
/// timely::example(|scope| {
///     (0..10).to_stream(scope)
///            .inspect(|x| println!("seen: {:?}", x));
/// });
/// ```
///
/// This next example captures the data and displays them once the computation is complete.
///
/// More precisely, the example captures a stream of events (receiving batches of data,
/// updates to input capabilities) and displays these events.
///
/// ```rust
/// use timely::dataflow::operators::{ToStream, Inspect, Capture};
/// use timely::dataflow::operators::capture::Extract;
///
/// let data = timely::example(|scope| {
///     (0..10).to_stream(scope)
///            .inspect(|x| println!("seen: {:?}", x))
///            .capture()
/// });
///
/// // the extracted data should have data (0..10) at timestamp 0.
/// assert_eq!(data.extract()[0].1, (0..10).collect::<Vec<_>>());
/// ```
pub fn example<T, F>(func: F) -> T
where
    T: Send+'static,
    F: FnOnce(&mut Child<Worker<crate::communication::allocator::thread::Thread>,u64>)->T+Send+Sync+'static
{
    crate::execute::execute_directly(|worker| worker.dataflow(|scope| func(scope)))
}

/// Executes a single-threaded timely dataflow computation.
///
/// The `execute_directly` constructs a `Worker` and directly executes the supplied
/// closure to construct and run a timely dataflow computation. It does not create any
/// worker threads, and simply uses the current thread of control.
///
/// The closure may return a result, which will be returned from the computation.
///
/// # Examples
/// ```rust
/// use timely::dataflow::operators::{ToStream, Inspect};
///
/// // execute a timely dataflow using three worker threads.
/// timely::execute_directly(|worker| {
///     worker.dataflow::<(),_,_>(|scope| {
///         (0..10).to_stream(scope)
///                .inspect(|x| println!("seen: {:?}", x));
///     })
/// });
/// ```
pub fn execute_directly<T, F>(func: F) -> T
where
    T: Send+'static,
    F: FnOnce(&mut Worker<crate::communication::allocator::thread::Thread>)->T+Send+Sync+'static
{
    let alloc = crate::communication::allocator::thread::Thread::new();
    let mut worker = crate::worker::Worker::new(alloc);
    let result = func(&mut worker);
    while worker.step_or_park(None) { }
    result
}

/// Executes a timely dataflow from a configuration and per-communicator logic.
///
/// The `execute` method takes a `Configuration` and spins up some number of
/// workers threads, each of which execute the supplied closure to construct
/// and run a timely dataflow computation.
///
/// The closure may return a `T: Send+'static`, and `execute` returns a result
/// containing a `WorkerGuards<T>` (or error information), which can be joined
/// to recover the result `T` values from the local workers.
///
/// # Examples
/// ```rust
/// use timely::dataflow::operators::{ToStream, Inspect};
///
/// // execute a timely dataflow using three worker threads.
/// timely::execute(timely::Configuration::Process(3), |worker| {
///     worker.dataflow::<(),_,_>(|scope| {
///         (0..10).to_stream(scope)
///                .inspect(|x| println!("seen: {:?}", x));
///     })
/// }).unwrap();
/// ```
///
/// The following example demonstrates how one can extract data from a multi-worker execution.
/// In a multi-process setting, each process will only receive those records present at workers
/// in the process.
///
/// ```rust
/// use std::sync::{Arc, Mutex};
/// use timely::dataflow::operators::{ToStream, Inspect, Capture};
/// use timely::dataflow::operators::capture::Extract;
///
/// // get send and recv endpoints, wrap send to share
/// let (send, recv) = ::std::sync::mpsc::channel();
/// let send = Arc::new(Mutex::new(send));
///
/// // execute a timely dataflow using three worker threads.
/// timely::execute(timely::Configuration::Process(3), move |worker| {
///     let send = send.lock().unwrap().clone();
///     worker.dataflow::<(),_,_>(move |scope| {
///         (0..10).to_stream(scope)
///                .inspect(|x| println!("seen: {:?}", x))
///                .capture_into(send);
///     });
/// }).unwrap();
///
/// // the extracted data should have data (0..10) thrice at timestamp 0.
/// assert_eq!(recv.extract()[0].1, (0..30).map(|x| x / 3).collect::<Vec<_>>());
/// ```
pub fn execute<T, F>(mut config: Configuration, func: F) -> Result<WorkerGuards<T>,String>
where
    T:Send+'static,
    F: Fn(&mut Worker<Allocator>)->T+Send+Sync+'static {

    if let Configuration::Cluster { ref mut log_fn, .. } = config {

        *log_fn = Box::new(|events_setup| {

            let mut result = None;
            if let Ok(addr) = ::std::env::var("TIMELY_COMM_LOG_ADDR") {

                use ::std::net::TcpStream;
                use crate::logging::BatchLogger;
                use crate::dataflow::operators::capture::EventWriter;

                eprintln!("enabled COMM logging to {}", addr);

                if let Ok(stream) = TcpStream::connect(&addr) {
                    let writer = EventWriter::new(stream);
                    let mut logger = BatchLogger::new(writer);
                    result = Some(crate::logging_core::Logger::new(
                        ::std::time::Instant::now(),
                        events_setup,
                        move |time, data| logger.publish_batch(time, data)
                    ));
                }
                else {
                    panic!("Could not connect to communication log address: {:?}", addr);
                }
            }
            result
        });
    }

    let (allocators, other) = config.try_build()?;

    initialize_from(allocators, other, move |allocator| {

        let mut worker = Worker::new(allocator);

        // If an environment variable is set, use it as the default timely logging.
        if let Ok(addr) = ::std::env::var("TIMELY_WORKER_LOG_ADDR") {

            use ::std::net::TcpStream;
            use crate::logging::{BatchLogger, TimelyEvent};
            use crate::dataflow::operators::capture::EventWriter;

            if let Ok(stream) = TcpStream::connect(&addr) {
                let writer = EventWriter::new(stream);
                let mut logger = BatchLogger::new(writer);
                worker.log_register()
                    .insert::<TimelyEvent,_>("timely", move |time, data|
                        logger.publish_batch(time, data)
                    );
            }
            else {
                panic!("Could not connect logging stream to: {:?}", addr);
            }
        }

        let result = func(&mut worker);
        while worker.step_or_park(None) { }
        result
    })
}

/// Executes a timely dataflow from supplied arguments and per-communicator logic.
///
/// The `execute` method takes arguments (typically `std::env::args()`) and spins up some number of
/// workers threads, each of which execute the supplied closure to construct and run a timely
/// dataflow computation.
///
/// The closure may return a `T: Send+'static`, and `execute` returns a result
/// containing a `WorkerGuards<T>` (or error information), which can be joined
/// to recover the result `T` values from the local workers.
///
/// The arguments `execute` currently understands are:
///
/// `-w, --workers`: number of per-process worker threads.
///
/// `-n, --processes`: number of processes involved in the computation.
///
/// `-p, --process`: identity of this process; from 0 to n-1.
///
/// `-h, --hostfile`: a text file whose lines are "hostname:port" in order of process identity.
/// If not specified, `localhost` will be used, with port numbers increasing from 2101 (chosen
/// arbitrarily).
///
/// # Examples
///
/// ```rust
/// use timely::dataflow::operators::{ToStream, Inspect};
///
/// // execute a timely dataflow using command line parameters
/// timely::execute_from_args(std::env::args(), |worker| {
///     worker.dataflow::<(),_,_>(|scope| {
///         (0..10).to_stream(scope)
///                .inspect(|x| println!("seen: {:?}", x));
///     })
/// }).unwrap();
/// ```
/// ```ignore
/// host0% cargo run -- -w 2 -n 4 -h hosts.txt -p 0
/// host1% cargo run -- -w 2 -n 4 -h hosts.txt -p 1
/// host2% cargo run -- -w 2 -n 4 -h hosts.txt -p 2
/// host3% cargo run -- -w 2 -n 4 -h hosts.txt -p 3
/// ```
/// ```ignore
/// % cat hosts.txt
/// host0:port
/// host1:port
/// host2:port
/// host3:port
/// ```
pub fn execute_from_args<I, T, F>(iter: I, func: F) -> Result<WorkerGuards<T>,String>
    where I: Iterator<Item=String>,
          T:Send+'static,
          F: Fn(&mut Worker<Allocator>)->T+Send+Sync+'static, {
    let configuration = Configuration::from_args(iter)?;
    execute(configuration, func)
}

/// Executes a timely dataflow from supplied allocators and logging.
///
/// Refer to [`execute`](fn.execute.html) for more details.
///
/// ```rust
/// use timely::dataflow::operators::{ToStream, Inspect};
///
/// // execute a timely dataflow using command line parameters
/// let (builders, other) = timely::Configuration::Process(3).try_build().unwrap();
/// timely::execute::execute_from(builders, other, |worker| {
///     worker.dataflow::<(),_,_>(|scope| {
///         (0..10).to_stream(scope)
///                .inspect(|x| println!("seen: {:?}", x));
///     })
/// }).unwrap();
/// ```
pub fn execute_from<A, T, F>(builders: Vec<A>, others: Box<::std::any::Any>, func: F) -> Result<WorkerGuards<T>,String>
where
    A: AllocateBuilder+'static,
    T: Send+'static,
    F: Fn(&mut Worker<<A as AllocateBuilder>::Allocator>)->T+Send+Sync+'static {
    initialize_from(builders, others, move |allocator| {
        let mut worker = Worker::new(allocator);
        let result = func(&mut worker);
        while worker.step_or_park(None) { }
        result
    })
}<|endoftext|>