<commit_before>// extern crate euclid;

use std::collections::BTreeMap;
use std::collections::VecDeque;

use rug::Integer;
use euclid::{TypedRect, TypedVector2D};

use defs::*;
use math;
use delta::*;
use polyomino::*;

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ShapeId(u32);

#[derive(Debug)]
pub struct Shape {
    // Gameplay:
    pub id: ShapeId,

    //TODO: use a faster hash table or just a vec https://github.com/servo/rust-fnv
    pub parent_ids: BTreeMap<ShapeId, ChildPoint>,
    // TODO: instead store a distinguished parent?
    pub polyomino: Polyomino,

    // Drawing:
    pub fill_color: [f32; 3],
    pub outline_color: [f32; 3],
}

impl Shape {
    pub fn has_position(&self, p: UPoint) -> bool {
        self.polyomino.has_position(p)
    }

    pub fn has_parent(&self, parent: &Shape) -> bool {
        self.parent_ids.contains_key(&parent.id)
    }

    pub fn first_parent_id(&self) -> ShapeId {
        let (&first_key, _) = self.parent_ids.iter().next().unwrap();
        first_key
    }

    pub fn position_on(&self, parent: &Shape) -> ChildPoint {
        self.parent_ids[&parent.id]
    }

    pub fn delta_from_parent(&self, parent: &Shape) -> Delta {
        Delta::from(self.position_on(parent).to_vector())
    }

    pub fn delta_to_child(&self, child: &Shape) -> Delta {
        child.delta_from_parent(self)
    }

    pub fn delta_to_parent(&self, parent: &Shape) -> FractionalDelta {
        let coords = self.parent_ids[&parent.id].to_vector();
        FractionalDelta {
            zdelta: 1,
            scale: 0,
            coords: TypedVector2D::new(Integer::from(coords.x), Integer::from(coords.y))
        }
    }
}

impl PartialEq for Shape {
    fn eq(&self, other: &Shape) -> bool {
        self.id == other.id
    }
}

impl Eq for Shape {}<commit_msg>A HasSquares trait<commit_after>// extern crate euclid;

use itertools::Itertools;
use std::collections::{BTreeMap, HashSet, VecDeque};

use euclid::{TypedRect, TypedVector2D};
use rug::Integer;

use defs::*;
use delta::*;
use math;
use math::Direction;
use polyomino::*;

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ShapeId(u32);

#[derive(Debug)]
pub struct Shape {
    // Gameplay:
    pub id: ShapeId,

    //TODO: use a faster hash table or just a vec https://github.com/servo/rust-fnv
    pub parent_ids: BTreeMap<ShapeId, ChildPoint>,
    // TODO: instead store a distinguished parent?
    pub polyomino: Polyomino,

    // Drawing:
    pub fill_color: [f32; 3],
    pub outline_color: [f32; 3],
}

impl Shape {
    pub fn has_position(&self, p: UPoint) -> bool {
        self.polyomino.has_position(p)
    }

    pub fn has_parent(&self, parent: &Shape) -> bool {
        self.parent_ids.contains_key(&parent.id)
    }

    pub fn first_parent_id(&self) -> ShapeId {
        let (&first_key, _) = self.parent_ids.iter().next().unwrap();
        first_key
    }

    pub fn position_on(&self, parent: &Shape) -> ChildPoint {
        self.parent_ids[&parent.id]
    }

    pub fn delta_from_parent(&self, parent: &Shape) -> Delta {
        Delta::from(self.position_on(parent).to_vector())
    }

    pub fn delta_to_child(&self, child: &Shape) -> Delta {
        child.delta_from_parent(self)
    }

    pub fn delta_to_parent(&self, parent: &Shape) -> FractionalDelta {
        let coords = self.parent_ids[&parent.id].to_vector();
        FractionalDelta {
            zdelta: 1,
            scale: 0,
            coords: TypedVector2D::new(Integer::from(coords.x), Integer::from(coords.y)),
        }
    }
}

impl PartialEq for Shape {
    fn eq(&self, other: &Shape) -> bool {
        self.id == other.id
    }
}

impl Eq for Shape {}

trait HasSquares {
    // TODO: Would be nice if this could be impl Iterator
    #[inline]
    fn constituent_squares<'a>(&self, universe: &Universe) -> Box<Iterator<Item = Square> + 'a>;

    fn locations<'a>(&self, universe: &'a Universe) -> Box<Iterator<Item = Location> + 'a> {
        Box::new(
            self.constituent_squares(universe)
                .map(move |s| s.location(universe)),
        )
    }

    #[inline]
    fn constituent_shapes(&self, universe: &Universe) -> Box<Iterator<Item = ShapeId>> {
        Box::new(
            self.constituent_squares(universe)
                .map(|s| s.shape_id)
                .unique(),
        )
    }

    #[inline]
    fn constituent_locations<'a>(
        &self,
        universe: &'a Universe,
    ) -> Box<Iterator<Item = Location> + 'a> {
        Box::new(
            self.constituent_squares(universe)
                .cartesian_product(Location::all_subpositions())
                .map(|(s, subp)| Location {
                    square: s,
                    subposition: subp,
                }),
        )
    }

    #[inline]
    fn child_shapes<'a>(&self, universe: &'a Universe) -> Box<Iterator<Item = ShapeId> + 'a> {
        Box::new(
            self.constituent_locations(universe)
                .filter_map(move |l| l.inhabitant(universe))
                .map(|s| s.shape_id)
                .unique(),
        )
    }

    #[inline]
    fn unblocked(&self, universe: &Universe, d: Direction) -> bool {
        self.locations(universe).map(|l| l.nudge(universe, d)).all(|o| o.is_some()) // This is doing a little more calculation than is necessary...
    }
    //     fringe u d a = (filter (not . inhabits u a) justs, length allMaybes /= length justs)
    // where allMaybes = fmap (nudgeLocation u d) $ locations u a
    //     justs = catMaybes allMaybes
}
{'fraction_non_alphanumeric': 0.14188218390804597, 'fraction_numerical': 0.004310344827586207, 'mean_word_length': 2.5025157232704403, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 41, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3982503', 'n_tokens_mistral': 1915, 'n_tokens_neox': 1864, 'n_words': 436}