use super::*;
use coord_2d::{ICoord, UCoord};
use direction::*;
struct Grid<T> {
size: UCoord,
cells: Vec<T>,
}
impl<T> Grid<T> {
fn new_fn<F: FnMut(ICoord) -> T>(size: UCoord, mut f: F) -> Self {
let mut cells = Vec::with_capacity(size.count());
for i in 0..size.height() {
for j in 0..size.width() {
cells.push(f(ICoord::new(j as i32, i as i32)));
}
}
Self { size, cells }
}
fn index(&self, coord: ICoord) -> Option<usize> {
if coord.is_valid(self.size) {
Some((coord.y as u32 * self.size.width() + coord.x as u32) as usize)
} else {
None
}
}
fn get(&self, coord: ICoord) -> Option<&T> {
self.index(coord).map(|index| &self.cells[index])
}
fn get_mut(&mut self, coord: ICoord) -> Option<&mut T> {
self.index(coord).map(move |index| &mut self.cells[index])
}
}
type TestOutputGrid = Grid<Option<DirectionBitmap>>;
struct TestInputGrid;
impl InputGrid for TestInputGrid {
type Grid = Grid<u8>;
type Opacity = u8;
fn size(&self, grid: &Self::Grid) -> UCoord {
grid.size
}
fn get_opacity(&self, grid: &Self::Grid, coord: ICoord) -> Self::Opacity {
*grid.get(coord).unwrap()
}
}
fn input_from_strs(strs: &[&str]) -> (Grid<u8>, ICoord) {
let size = UCoord::new(strs[0].len() as u32, strs.len() as u32);
let mut grid = Grid::new_fn(size, |_| 0);
let mut eye = None;
for (i, row) in strs.iter().enumerate() {
for (j, ch) in row.chars().enumerate() {
let coord = ICoord::new(j as i32, i as i32);
let cell = match ch {
'@' => {
eye = Some(coord);
0
}
'.' => 0,
'#' => 255,
'&' => 128,
_ => panic!("unknown char"),
};
*grid.get_mut(coord).expect("out of bounds") = cell;
}
}
(grid, eye.expect("no eye"))
}
fn output_to_strings(eye: ICoord, grid: &TestOutputGrid) -> Vec<String> {
let mut strings = Vec::new();
for i in 0..grid.size.height() {
let mut string = String::new();
for j in 0..grid.size.width() {
let coord = ICoord::new(j as i32, i as i32);
let ch = if coord == eye {
'@'
} else if let Some(directions) = grid.get(coord).unwrap() {
use self::Direction::*;
let directions = *directions;
if directions == DirectionBitmap::all() {
','
} else if directions == North.bitmap() {
'▀'
} else if directions == East.bitmap() {
'▐'
} else if directions == South.bitmap() {
'▄'
} else if directions == West.bitmap() {
'▌'
} else if directions == NorthEast.bitmap() {
'▝'
} else if directions == NorthWest.bitmap() {
'▘'
} else if directions == SouthWest.bitmap() {
'▖'
} else if directions == SouthEast.bitmap() {
'▗'
} else if directions == North.bitmap() | East.bitmap() {
'▜'
} else if directions == South.bitmap() | East.bitmap() {
'▟'
} else if directions == South.bitmap() | West.bitmap() {
'▙'
} else if directions == North.bitmap() | West.bitmap() {
'▛'
} else {
eprintln!("unknown {:b}", directions.raw);
'?'
}
} else {
'%'
};
string.push(ch);
}
strings.push(string);
}
strings
}
fn check_output(eye: ICoord, output: &TestOutputGrid, expected_output_strings: &[&str]) {
let output_strings = output_to_strings(eye, output);
if output_strings != expected_output_strings {
panic!(
"Unexpected output:\n{:#?}\n\nExpected:\n{:#?}",
output_strings, expected_output_strings
);
}
}
fn check_scenario_with_vision_distance<VD: VisionDistance>(
vision_distance: VD,
input_strs: &[&str],
expected_output: &[&str],
) {
let (input, eye) = input_from_strs(input_strs);
let mut output = Grid::new_fn(input.size, |_| None);
let mut ctx: Context<u8> = Context::default();
ctx.for_each_visible(
eye,
&TestInputGrid,
&input,
vision_distance,
255,
|coord, direction_map, _visibility| {
if let Some(v) = output.get_mut(coord) {
if v.is_some() {
panic!("already have value at {:?}", coord);
}
*v = Some(direction_map);
} else {
panic!("access out of bounds {:?}", coord);
}
},
);
check_output(eye, &output, expected_output);
}
fn check_scenario(input_strs: &[&str], expected_output: &[&str]) {
check_scenario_with_vision_distance(
vision_distance::Circle::new(100),
input_strs,
expected_output,
);
}
#[test]
fn single() {
check_scenario(&["@"], &["@"]);
}
#[test]
fn empty() {
check_scenario(
&[
"...........",
"...........",
"...........",
"...........",
".....@.....",
"...........",
"...........",
"...........",
"...........",
],
&[
",,,,,,,,,,,",
",,,,,,,,,,,",
",,,,,,,,,,,",
",,,,,,,,,,,",
",,,,,@,,,,,",
",,,,,,,,,,,",
",,,,,,,,,,,",
",,,,,,,,,,,",
",,,,,,,,,,,",
],
);
}
#[test]
fn full() {
check_scenario(
&[
"###########",
"###########",
"###########",
"###########",
"#####@#####",
"###########",
"###########",
"###########",
"###########",
],
&[
"%%%%%%%%%%%",
"%%%%%%%%%%%",
"%%%%%%%%%%%",
"%%%%▗▄▖%%%%",
"%%%%▐@▌%%%%",
"%%%%▝▀▘%%%%",
"%%%%%%%%%%%",
"%%%%%%%%%%%",
"%%%%%%%%%%%",
],
);
}
#[test]
fn corners() {
check_scenario(
&[
"...............",
".#############.",
".#...........#.",
".#...........#.",
".#.......#...#.",
".#...........#.",
".#..#........#.",
".#.....@.....#.",
".#...........#.",
".#...........#.",
".#.......#...#.",
".#....#......#.",
".#...........#.",
".#...........#.",
".#...........#.",
".#############.",
"...............",
],
&[
"%%%%%%%%%%%%%%%",
"%▗▄▄▄▄▄▄▄▄▖%%▖%",
"%▐,,,,,,,,%%,▌%",
"%%,,,,,,,,%,,▌%",
"%%%,,,,,,▙,,,▌%",
"%%%%,,,,,,,,,▌%",
"%▐,,▟,,,,,,,,▌%",
"%▐,,,,,@,,,,,▌%",
"%▐,,,,,,,,,,,▌%",
"%▐,,,,,,,,,,,▌%",
"%▐,,,,,,,▛,,,▌%",
"%▐,,,,▜,,,%,,▌%",
"%▐,,,%,,,,%%,▌%",
"%▐,,%%,,,,,%%▘%",
"%▐,,%%,,,,,%%%%",
"%▝▀▀%%▀▀▀▀▀%%%%",
"%%%%%%%%%%%%%%%",
],
);
}
#[test]
fn gaps() {
check_scenario(
&[
"..........#",
"......#...#",
"..##..#...#",
"..........#",
"...@......#",
"......#...#",
"##....#...#",
"..........#",
"####..##..#",
],
&[
"%%%%%,,%%%%",
",%%%%,▌%%,▌",
",,▄▄,,▙,,,▌",
",,,,,,,,,,▌",
",,,@,,,,,,▌",
",,,,,,▛,,,▌",
"▀▜,,,,▌%%%%",
"%,,,,,,%%%%",
"%▀▀▀,,▛▘%%%",
],
);
}
#[test]
fn long_semi_transparent() {
check_scenario(
&[
"...............&..@&............",
"...............&...&............",
"...............&...&............",
"...............&...&............",
"...............&...&............",
"...............&...&............",
"...............&...&............",
"...............&...&............",
"...............&...&............",
"...............&...&............",
"...............&...&............",
"...............&...&............",
"...............&...&............",
"...............&...&............",
"...............&...&............",
"...............&...&............",
"...............&...&............",
"...............&...&............",
"...............&...&............",
"...............&...&............",
"...............&...&............",
],
&[
",,,,,,,,,,,,,,,,,,@,,,,,,,,,,,,,",
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
",,,,,,,,,,,,,,,,,,,,%,,,,,,,,,,,",
",,,,,,,,,,,,,,,,,,,,%,,,,,,,,,,,",
",,,,,,,,,,,,,,%,,,,,%,,,,,,,,,,,",
",,,,,,,,,,,,,,%,,,,,%%,,,,,,,,,,",
",,,,,,,,,,,,,%%,,,,,%%,,,,,,,,,,",
",,,,,,,,,,,,%%%,,,,,%%,,,,,,,,,,",
",,,,,,,,,,,,%%%,,,,,%%%,,,,,,,,,",
",,,,,,,,,,,%%%%,,,,,%%%,,,,,,,,,",
",,,,,,,,,,,%%%%,,,,,%%%,,,,,,,,,",
",,,,,,,,,,%%%%%,,,,,%%%%,,,,,,,,",
",,,,,,,,,,%%%%%,,,,,%%%%,,,,,,,,",
",,,,,,,,,%%%%%%,,,,,%%%%,,,,,,,,",
",,,,,,,,,%%%%%%,,,,,%%%%%,,,,,,,",
",,,,,,,,%%%%%%%,,,,,%%%%%,,,,,,,",
",,,,,,,%%%%%%%%,,,,,%%%%%,,,,,,,",
",,,,,,,%%%%%%%%,,,,,%%%%%%,,,,,,",
],
);
}
#[test]
fn near_wall() {
check_scenario(
&[
"...............",
".#############.",
".#@..........#.",
".#...........#.",
".#...........#.",
".#...........#.",
".#...........#.",
".#...........#.",
".#...........#.",
".#...........#.",
".#...........#.",
".#...........#.",
".#...........#.",
".#...........#.",
".#...........#.",
".#############.",
"...............",
],
&[
"%%%%%%%%%%%%%%%",
"%▗▄▄▄▄▄▄▄▄▄▄▄▖%",
"%▐@,,,,,,,,,,▌%",
"%▐,,,,,,,,,,,▌%",
"%▐,,,,,,,,,,,▌%",
"%▐,,,,,,,,,,,▌%",
"%▐,,,,,,,,,,,▌%",
"%▐,,,,,,,,,,,▌%",
"%▐,,,,,,,,,,,▌%",
"%▐,,,,,,,,,,,▌%",
"%▐,,,,,,,,,,,▌%",
"%▐,,,,,,,,,,,▌%",
"%▐,,,,,,,,,,,▌%",
"%▐,,,,,,,,,,,▌%",
"%▐,,,,,,,,,,,▌%",
"%▝▀▀▀▀▀▀▀▀▀▀▀▘%",
"%%%%%%%%%%%%%%%",
],
);
}
#[test]
fn semi_transparent_walls() {
check_scenario(
&[
".......................",
".......................",
".......................",
".......................",
".......................",
".....&&&&&&...&&&&&&&..",
".......................",
"...............&.....&.",
"....&&&&&......&.....&.",
"...............&.....&.",
"..........@....&.....&.",
"...............&.....&.",
".&...................&.",
".&..&&&&&............&.",
".&...................&.",
".&.............&&&&&.&.",
".&...................&.",
".......................",
"......&&&&&&&&&&&&.....",
"............&..........",
".......................",
],
&[
"%%%%,,,,,,,,,,,,,,,,,,%",
"%%%%%,,,,,,,,,,,,,,,,%%",
",%%%%,,,,,,,,,,,,,,,%%%",
",,,%%%,,,,,,,,,,,,%%%%%",
"%,,,%%,,,,,,,,,,,%%%%%%",
"%%%,,▄▄,,,,,,,,,▄▄▄▄▄,,",
"%%%%%,,,,,,,,,,,,,,,,,%",
"%%%%%%,,,,,,,,,,,,,,,▌%",
",,,,,,,,,,,,,,,,,,,,,▌%",
",,,,,,,,,,,,,,,,,,,,,▌%",
",,,,,,,,,,@,,,,,,,,,,▌%",
",,,,,,,,,,,,,,,,,,,,,▌%",
",,,,,,,,,,,,,,,,,,,,,▌%",
",,,,,,,,,,,,,,,,,,,,,▌%",
",%%%,,,,,,,,,,,,,,,,,▘%",
"%%,,,,,,,,,,,,,,,,,,,,,",
"%▐,,,,,,,,,,,,,,,,,,%%,",
"%,,,,,,,,,,,,,,,,,,,,%%",
",,,,,,▀,,,,,,,,,,,,,,,,",
",,,,,%,,,,,,▛,,,,,,,,,,",
",,,,%%,,,,,,,%,,,,,,,,,",
],
);
}
#[test]
fn distant_pillar() {
check_scenario(
&[
".......................",
".#........#.......#....",
".......................",
".......................",
".......................",
".......................",
".......................",
".......................",
".......................",
".......................",
".#........@..........#.",
".......................",
".......................",
".......................",
".......................",
".......................",
".......................",
".......................",
".................#.....",
"..#.......#............",
".......................",
],
&[
"%,,,,,,,,%%%,,,,,,,%,,,",
",▟,,,,,,,,▄,,,,,,,▙,,,,",
",,,,,,,,,,,,,,,,,,,,,,,",
",,,,,,,,,,,,,,,,,,,,,,,",
",,,,,,,,,,,,,,,,,,,,,,,",
",,,,,,,,,,,,,,,,,,,,,,,",
",,,,,,,,,,,,,,,,,,,,,,,",
",,,,,,,,,,,,,,,,,,,,,,,",
",,,,,,,,,,,,,,,,,,,,,,,",
"%,,,,,,,,,,,,,,,,,,,,,%",
"%▐,,,,,,,,@,,,,,,,,,,▌%",
"%,,,,,,,,,,,,,,,,,,,,,%",
",,,,,,,,,,,,,,,,,,,,,,,",
",,,,,,,,,,,,,,,,,,,,,,,",
",,,,,,,,,,,,,,,,,,,,,,,",
",,,,,,,,,,,,,,,,,,,,,,,",
",,,,,,,,,,,,,,,,,,,,,,,",
",,,,,,,,,,,,,,,,,,,,,,,",
",,,,,,,,,,,,,,,,,▛,,,,,",
",,▜,,,,,,,▀,,,,,,,%,,,,",
",%,,,,,,,%%%,,,,,,,%,,,",
],
);
}
#[test]
fn simple_transparent() {
check_scenario(
&[
"@..........",
"...........",
"...&.......",
"...........",
"...........",
"...........",
"...........",
"...........",
],
&[
"@,,,,,,,,,,",
",,,,,,,,,,,",
",,,,,,,,,,,",
",,,,,,,,,,,",
",,,,,,,,,,,",
",,,,,,,,,,,",
",,,,,,,,,,,",
",,,,,,,,,,,",
],
);
}
#[test]
fn circle() {
check_scenario_with_vision_distance(
vision_distance::Circle::new(10),
&[
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
".................@.................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
],
&[
"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%",
"%%%%%%%%%%%%%%%%%,%%%%%%%%%%%%%%%%%",
"%%%%%%%%%%%%%,,,,,,,,,%%%%%%%%%%%%%",
"%%%%%%%%%%%,,,,,,,,,,,,,%%%%%%%%%%%",
"%%%%%%%%%%,,,,,,,,,,,,,,,%%%%%%%%%%",
"%%%%%%%%%,,,,,,,,,,,,,,,,,%%%%%%%%%",
"%%%%%%%%%,,,,,,,,,,,,,,,,,%%%%%%%%%",
"%%%%%%%%,,,,,,,,,,,,,,,,,,,%%%%%%%%",
"%%%%%%%%,,,,,,,,,,,,,,,,,,,%%%%%%%%",
"%%%%%%%%,,,,,,,,,,,,,,,,,,,%%%%%%%%",
"%%%%%%%%,,,,,,,,,,,,,,,,,,,%%%%%%%%",
"%%%%%%%,,,,,,,,,,@,,,,,,,,,,%%%%%%%",
"%%%%%%%%,,,,,,,,,,,,,,,,,,,%%%%%%%%",
"%%%%%%%%,,,,,,,,,,,,,,,,,,,%%%%%%%%",
"%%%%%%%%,,,,,,,,,,,,,,,,,,,%%%%%%%%",
"%%%%%%%%,,,,,,,,,,,,,,,,,,,%%%%%%%%",
"%%%%%%%%%,,,,,,,,,,,,,,,,,%%%%%%%%%",
"%%%%%%%%%,,,,,,,,,,,,,,,,,%%%%%%%%%",
"%%%%%%%%%%,,,,,,,,,,,,,,,%%%%%%%%%%",
"%%%%%%%%%%%,,,,,,,,,,,,,%%%%%%%%%%%",
"%%%%%%%%%%%%%,,,,,,,,,%%%%%%%%%%%%%",
"%%%%%%%%%%%%%%%%%,%%%%%%%%%%%%%%%%%",
"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%",
],
);
}
#[test]
fn circle_squared() {
check_scenario_with_vision_distance(
vision_distance::Circle::new_squared(90),
&[
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
".................@.................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
],
&[
"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%",
"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%",
"%%%%%%%%%%%%%%,,,,,,,%%%%%%%%%%%%%%",
"%%%%%%%%%%%%,,,,,,,,,,,%%%%%%%%%%%%",
"%%%%%%%%%%%,,,,,,,,,,,,,%%%%%%%%%%%",
"%%%%%%%%%%,,,,,,,,,,,,,,,%%%%%%%%%%",
"%%%%%%%%%,,,,,,,,,,,,,,,,,%%%%%%%%%",
"%%%%%%%%%,,,,,,,,,,,,,,,,,%%%%%%%%%",
"%%%%%%%%,,,,,,,,,,,,,,,,,,,%%%%%%%%",
"%%%%%%%%,,,,,,,,,,,,,,,,,,,%%%%%%%%",
"%%%%%%%%,,,,,,,,,,,,,,,,,,,%%%%%%%%",
"%%%%%%%%,,,,,,,,,@,,,,,,,,,%%%%%%%%",
"%%%%%%%%,,,,,,,,,,,,,,,,,,,%%%%%%%%",
"%%%%%%%%,,,,,,,,,,,,,,,,,,,%%%%%%%%",
"%%%%%%%%,,,,,,,,,,,,,,,,,,,%%%%%%%%",
"%%%%%%%%%,,,,,,,,,,,,,,,,,%%%%%%%%%",
"%%%%%%%%%,,,,,,,,,,,,,,,,,%%%%%%%%%",
"%%%%%%%%%%,,,,,,,,,,,,,,,%%%%%%%%%%",
"%%%%%%%%%%%,,,,,,,,,,,,,%%%%%%%%%%%",
"%%%%%%%%%%%%,,,,,,,,,,,%%%%%%%%%%%%",
"%%%%%%%%%%%%%%,,,,,,,%%%%%%%%%%%%%%",
"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%",
"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%",
],
);
}
#[test]
fn square() {
check_scenario_with_vision_distance(
vision_distance::Square::new(10),
&[
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
".................@.................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
],
&[
"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%",
"%%%%%%%,,,,,,,,,,,,,,,,,,,,,%%%%%%%",
"%%%%%%%,,,,,,,,,,,,,,,,,,,,,%%%%%%%",
"%%%%%%%,,,,,,,,,,,,,,,,,,,,,%%%%%%%",
"%%%%%%%,,,,,,,,,,,,,,,,,,,,,%%%%%%%",
"%%%%%%%,,,,,,,,,,,,,,,,,,,,,%%%%%%%",
"%%%%%%%,,,,,,,,,,,,,,,,,,,,,%%%%%%%",
"%%%%%%%,,,,,,,,,,,,,,,,,,,,,%%%%%%%",
"%%%%%%%,,,,,,,,,,,,,,,,,,,,,%%%%%%%",
"%%%%%%%,,,,,,,,,,,,,,,,,,,,,%%%%%%%",
"%%%%%%%,,,,,,,,,,,,,,,,,,,,,%%%%%%%",
"%%%%%%%,,,,,,,,,,@,,,,,,,,,,%%%%%%%",
"%%%%%%%,,,,,,,,,,,,,,,,,,,,,%%%%%%%",
"%%%%%%%,,,,,,,,,,,,,,,,,,,,,%%%%%%%",
"%%%%%%%,,,,,,,,,,,,,,,,,,,,,%%%%%%%",
"%%%%%%%,,,,,,,,,,,,,,,,,,,,,%%%%%%%",
"%%%%%%%,,,,,,,,,,,,,,,,,,,,,%%%%%%%",
"%%%%%%%,,,,,,,,,,,,,,,,,,,,,%%%%%%%",
"%%%%%%%,,,,,,,,,,,,,,,,,,,,,%%%%%%%",
"%%%%%%%,,,,,,,,,,,,,,,,,,,,,%%%%%%%",
"%%%%%%%,,,,,,,,,,,,,,,,,,,,,%%%%%%%",
"%%%%%%%,,,,,,,,,,,,,,,,,,,,,%%%%%%%",
"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%",
],
);
}
#[test]
fn diamond() {
check_scenario_with_vision_distance(
vision_distance::Diamond::new(10),
&[
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
".................@.................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
"...................................",
],
&[
"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%",
"%%%%%%%%%%%%%%%%%,%%%%%%%%%%%%%%%%%",
"%%%%%%%%%%%%%%%%,,,%%%%%%%%%%%%%%%%",
"%%%%%%%%%%%%%%%,,,,,%%%%%%%%%%%%%%%",
"%%%%%%%%%%%%%%,,,,,,,%%%%%%%%%%%%%%",
"%%%%%%%%%%%%%,,,,,,,,,%%%%%%%%%%%%%",
"%%%%%%%%%%%%,,,,,,,,,,,%%%%%%%%%%%%",
"%%%%%%%%%%%,,,,,,,,,,,,,%%%%%%%%%%%",
"%%%%%%%%%%,,,,,,,,,,,,,,,%%%%%%%%%%",
"%%%%%%%%%,,,,,,,,,,,,,,,,,%%%%%%%%%",
"%%%%%%%%,,,,,,,,,,,,,,,,,,,%%%%%%%%",
"%%%%%%%,,,,,,,,,,@,,,,,,,,,,%%%%%%%",
"%%%%%%%%,,,,,,,,,,,,,,,,,,,%%%%%%%%",
"%%%%%%%%%,,,,,,,,,,,,,,,,,%%%%%%%%%",
"%%%%%%%%%%,,,,,,,,,,,,,,,%%%%%%%%%%",
"%%%%%%%%%%%,,,,,,,,,,,,,%%%%%%%%%%%",
"%%%%%%%%%%%%,,,,,,,,,,,%%%%%%%%%%%%",
"%%%%%%%%%%%%%,,,,,,,,,%%%%%%%%%%%%%",
"%%%%%%%%%%%%%%,,,,,,,%%%%%%%%%%%%%%",
"%%%%%%%%%%%%%%%,,,,,%%%%%%%%%%%%%%%",
"%%%%%%%%%%%%%%%%,,,%%%%%%%%%%%%%%%%",
"%%%%%%%%%%%%%%%%%,%%%%%%%%%%%%%%%%%",
"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%",
],
);
}