use termion::color::{ Bg, Rgb };
use crate::{
color::*,
draw,
error,
flag::{ self, Flag },
state::State,
util::{ ansi_len, ansi_substr }
};
pub static V_EIGHTH: [char; 7] = ['▁', '▂', '▃', '▄', '▅', '▆', '▇'];
pub static H_EIGHTH: [char; 7] = ['▏', '▎', '▍', '▌', '▋', '▊', '▉'];
pub static SHADING: [char; 3] = ['░', '▒', '▓'];
pub static TRIANGLE_21: [char; 3] = ['', '🭬', ''];
pub static SLANT_23: [char; 2] = ['🭒', '🭏'];
pub fn progress(state: &State) -> Flag {
let red = bg(0xE50000);
let orange = bg(0xFF8D00);
let yellow = bg(0xFFEE00);
let green = bg(0x028121);
let blue = bg(0x004CFF);
let purple = bg(0x770088);
let black: u32 = 0;
let brown: u32 = 0x784F17;
let ltblue: u32 = 0xEAACB8;
let pink: u32 = 0x7ACBF5;
let white: u32 = 0xFFFFFF;
let (width, height) = state.size.get(18, 6);
if height < 6 || width < 6 { error::too_small(width, height); }
let stripes = [red, orange, yellow, green, blue, purple];
let chevrons = [white, ltblue, pink, brown, black];
let mut lines: Vec<String> = Vec::new();
let mut index = 0;
let linecount = height - (height % 6); let full_depth = width / 3;
let chevron_width = if full_depth > 6 { (full_depth / 6) - 1 } else { 0 };
let direction_thresh = linecount / 2;
let corner = linecount % 2 == 1;
let thresh = linecount / 6; let mut line_no = 0;
let build_chevron = | separator: char | -> String {
let mut output = format!(
"{fg}{bg}{stripe}{separator}",
fg = rgb(chevrons[0]),
bg = bg(chevrons[1]),
stripe = draw::BLOCK.repeat( usize::max(chevron_width as usize * 2, 1) )
);
let stripe = draw::BLOCK.repeat(chevron_width as usize);
for i in 1..4 {
output += &format!(
"{fg}{bg}{stripe}{separator}",
fg = rgb(chevrons[i]),
bg = bg(chevrons[i + 1])
);
}
output += &format!(
"{fg}{stripe}",
fg = rgb(chevrons[4])
);
output
};
let mut base = build_chevron(TRIANGLE_21[0]);
let base_length = base.len();
let display_length = ansi_len(&base) + 1; for n in 0..direction_thresh {
if line_no != 0 && line_no % thresh == 0 { index += 1; }
let start = (direction_thresh - n) as usize - 1;
let diff = if display_length >= start { display_length - start } else { 0 };
let mut line = ansi_substr(&base, start as usize, base_length);
line += &stripes[index].to_string();
if diff > 0 { line.push(TRIANGLE_21[0]); }
line += &" ".repeat(width as usize - diff);
lines.push(line);
line_no += 1;
}
if corner {
if line_no % thresh == 0 { index += 1; }
let base = build_chevron(TRIANGLE_21[1]);
let mut line = ansi_substr(&base, 0, base_length);
line += &format!(
"{stripe}{separator}{line}",
stripe = stripes[index],
separator = TRIANGLE_21[1],
line = " ".repeat(width as usize - display_length)
);
lines.push(line);
line_no += 1;
}
base = build_chevron(TRIANGLE_21[2]);
for n in 0..direction_thresh {
if line_no % thresh == 0 { index += 1; }
if index > 5 { break; }
let start = n as usize;
let diff = if display_length >= start { display_length - start } else { 0 };
let mut line = ansi_substr(&base, start, base_length);
line += &stripes[index].to_string();
if diff > 0 { line.push(TRIANGLE_21[2]); }
line += &" ".repeat(width as usize - diff);
lines.push(line);
line_no += 1;
}
Flag::Lines(lines)
}
pub fn aroace_halves(state: &State) -> Flag {
let Flag::Stripes(aro) = flag::aromantic() else { panic!() };
let Flag::Stripes(ace) = flag::asexual() else { panic!() };
let (width, height) = state.size.get(60, 20);
if height < 20 { error::too_small(width, height); }
let mut lines: Vec<String> = Vec::new();
let linecount = height - (height % 20);
let aro_thresh = linecount / 5; let ace_thresh = linecount / 4; let stripe = draw::BLOCK.repeat((width / 2) as usize);
let mut aro_index = 0;
let mut ace_index = 0;
for n in 0..linecount {
if n != 0 {
if n % aro_thresh == 0 { aro_index += 1; }
if n % ace_thresh == 0 { ace_index += 1; }
}
let line = format!("{}{stripe}{}{stripe}", aro[aro_index], ace[ace_index]);
lines.push(line);
}
Flag::Lines(lines)
}
fn demi_orientation_render(middle: Bg<Rgb>, bottom: Bg<Rgb>, width: u16, height: u16) -> Vec<String> {
let white = bg(0xFFFFFF);
if height < 5 { error::too_small(width, height); }
let stripes = vec![white, white, middle, bottom, bottom];
let mut lines: Vec<String> = draw::bg_stripes(stripes, width, height);
let linecount = lines.len();
let depth = linecount / 2;
let corner = linecount % 2 == 1;
for n in 0..depth {
let line = lines[n].clone();
let replacement = format!("{BLACK}{}{}", draw::BLOCK.repeat(n), TRIANGLE_21[0]);
lines[n] = line.replacen(&" ".repeat(n + 1), &replacement, 1);
}
if corner {
let line = lines[depth].clone();
let replacement = format!("{BLACK}{}{}", draw::BLOCK.repeat(depth), TRIANGLE_21[1]);
lines[depth] = line.replacen(&" ".repeat(depth + 1), &replacement, 1);
}
let start = depth + (linecount % 2);
for n in 0..depth {
let line = lines[start + n].clone();
let size = depth - n - 1;
let replacement = format!("{BLACK}{}{}", draw::BLOCK.repeat(size), TRIANGLE_21[2]);
lines[start + n] = line.replacen(&" ".repeat(size + 1), &replacement, 1);
}
lines
}
pub fn demiromantic(state: &State) -> Flag {
let green = bg(0x3DA542);
let gray = bg(0xD2D2D2);
let (width, height) = state.size.get(15, 5);
let lines = demi_orientation_render(green, gray, width, height);
Flag::Lines(lines)
}
pub fn demisexual(state: &State) -> Flag {
let purple = bg(0x832FA8);
let grey = bg(0x7B868C);
let (width, height) = state.size.get(15, 5);
let lines = demi_orientation_render(purple, grey, width, height);
Flag::Lines(lines)
}
pub fn disability() {
let gray = bg(0x575757);
let green: u32 = 0x3AAD7D;
let blue: u32 = 0x79BFE0;
let white: u32 = 0xE8E8E8;
let yellow: u32 = 0xEDDB76;
let red: u32 = 0xCD7281;
let stripes = [red, yellow, white, blue, green];
}
pub fn intersex() -> Flag {
let yellow = bg(0xFFDA00);
let purple = rgb(0x7A00AC);
let block = " ";
let stripe = block.repeat(9);
let part = block.repeat(4);
let lines = vec![
format!("{yellow}{stripe}"),
format!("{part}{purple}O{part}"),
format!("{stripe}")
];
Flag::Lines(lines)
}
pub fn polyamory(state: &State) -> Flag {
let blue = rgb(0x019FE3);
let magenta = rgb(0xE50051);
let purple = rgb(0x340C46);
let yellow = rgb(0xFCBF00);
let white = bg(0xFFFFFF);
let semicircle = '\u{E0B6}';
let separators = ['\u{E0BE}', '\u{E0BA}'];
let (width, height) = state.size.get(18, 6);
if height < 6 { error::too_small(width, height); }
let stripes = [magenta, purple]; let mut lines: Vec<String> = Vec::new();
let linecount = height - (height % 3); let full_depth = linecount;
let thresh = linecount / 3; let start = 2 * full_depth / 3;
let mut separator = separators[0];
for n in 0..thresh {
let size = start + n;
let line = format!(
"{white}{yellow}{cutin}{blue}{separator}{stripe}",
cutin = " ".repeat(size as usize),
stripe = draw::BLOCK.repeat((width - (size + 1)) as usize)
);
lines.push(line);
}
let mut index = 0; separator = separators[1];
for n in thresh..linecount {
if n == (thresh * 2) { index = 1; }
let size = (2 * start) - n - 1;
let color = stripes[index];
let line = format!(
"{white}{yellow}{cutin}{color}{separator}{stripe}",
cutin = " ".repeat(size as usize),
stripe = draw::BLOCK.repeat((width - (size + 1)) as usize)
);
lines.push(line);
}
Flag::Lines(lines)
}