cp-cli 0.7.0

Human-first command-line client for competitive-programming platforms
Documentation
use std::fmt::Write as _;

const WIDTH: usize = 42;
const HEIGHT: usize = 17;
const FRAME_COUNT: usize = 4;
const MIN_WIDTH: u16 = 28;
const PALETTE: [u8; 16] = [
    0, 234, 237, 240, 244, 95, 138, 131, 181, 174, 187, 255, 23, 51, 198, 167,
];
const GLYPHS: [char; 10] = [' ', '.', ':', '-', '=', '+', '*', '#', '%', '@'];

#[derive(Clone, Copy)]
pub(crate) enum Pose {
    Cursor = 0,
    Blink = 1,
    Scratch = 2,
    Idle = 3,
}

pub(crate) fn render(pose: Pose, columns: u16, color: bool) -> Option<String> {
    render_frame(pose, columns, color, false)
}

pub(crate) fn render_alive(pose: Pose, columns: u16, color: bool) -> Option<String> {
    render_frame(pose, columns, color, true)
}

fn render_frame(pose: Pose, columns: u16, color: bool, alive: bool) -> Option<String> {
    if !color || columns < MIN_WIDTH {
        return None;
    }

    let width = usize::from(columns).min(WIDTH);
    let height = (width * HEIGHT).div_ceil(WIDTH);
    let mut output = String::with_capacity(width * height * 8);
    for y in 0..height {
        let source_y = y * HEIGHT / height;
        let last = (0..width)
            .rposition(|x| pixel(pose, source_y, x * WIDTH / width) != 0)
            .unwrap_or_default();
        let mut previous = (0, 0);
        for x in 0..=last {
            let source_x = x * WIDTH / width;
            let value = pixel(pose, source_y, source_x);
            let color = usize::from(value >> 4);
            let motion = if alive && eye(source_y, source_x) {
                5
            } else if alive && matches!(pose, Pose::Scratch) && itch(source_y, source_x) {
                6
            } else {
                0
            };
            if (color, motion) != previous {
                if color == 0 {
                    output.push_str("\x1b[0m");
                } else if motion > 0 {
                    let _ = write!(output, "\x1b[0;{motion};38;5;{}m", PALETTE[color]);
                } else {
                    let _ = write!(output, "\x1b[0;38;5;{}m", PALETTE[color]);
                }
                previous = (color, motion);
            }
            output.push(GLYPHS[usize::from(value & 0x0f)]);
        }
        if previous != (0, 0) {
            output.push_str("\x1b[0m");
        }
        if y + 1 != height {
            output.push('\n');
        }
    }
    Some(output)
}

fn eye(y: usize, x: usize) -> bool {
    matches!((y, x), (5, 31 | 37) | (6, 31 | 32 | 37))
}

fn itch(y: usize, x: usize) -> bool {
    (2..=8).contains(&y) && x >= 34 && pixel(Pose::Scratch, y, x) != pixel(Pose::Cursor, y, x)
}

pub(crate) fn loading_frames(columns: u16, color: bool, motion: bool) -> Vec<String> {
    let width = columns.min(30);
    let Some(idle) = render(Pose::Cursor, width, color) else {
        let frames = if motion {
            &["▹ P0SSUM//", "▸ POS_SUM//", "▹ POSSUM//", "▸ POSSUM//"][..]
        } else {
            &["POSSUM//", "POSSUM//"][..]
        };
        return frames.iter().map(|frame| (*frame).to_owned()).collect();
    };
    if !motion {
        return vec![idle.clone(), idle];
    }

    let blink = render(Pose::Blink, width, color).unwrap_or_else(|| idle.clone());
    let scratch = render(Pose::Scratch, width, color).unwrap_or_else(|| idle.clone());
    vec![
        idle.clone(),
        blink,
        idle.clone(),
        scratch.clone(),
        scratch,
        idle.clone(),
        idle.clone(),
        idle.clone(),
        idle.clone(),
        idle,
    ]
}

fn pixel(pose: Pose, y: usize, x: usize) -> u8 {
    let row = FRAMES[pose as usize][y].as_bytes();
    (hex(row[x * 2]) << 4) | hex(row[x * 2 + 1])
}

fn hex(value: u8) -> u8 {
    match value {
        b'0'..=b'9' => value - b'0',
        b'a'..=b'f' => value - b'a' + 10,
        _ => 0,
    }
}

// Each byte stores one palette slot and one glyph-density slot
const FRAMES: [[&str; HEIGHT]; FRAME_COUNT] = [
    [
        "000000000000000000000000000000000000000000000000001124241200000000000000000000000000",
        "000000000000000000000000000011121424242424242412222838282834121100000000000011121200",
        "000000000000000000000011c43838383847575838382828283838777738193838242212243838283824",
        "00000000000000000000c43838585747666747573828282829a686f7f728198666282838197877583811",
        "000000000000000011c8385858474767676647383838572829666767662886666686285766587786f200",
        "0000000000000011c857385757574747676657385757573828678657a657282938b54766662877f20000",
        "00000000000011c8385738383828586767675738574747475857b5b58686281919a566672819f7000000",
        "000000000000c438584767675758383857666728674758576686a5b5b5b5b58657679667388662003100",
        "0000000000c2385847474747678686664767a567574758383867a5b5b5a686a566779697746251710000",
        "0000000011c838573838383838574786a567a5b567573857575757a6a586675758521111000000000000",
        "00000011c8283857573838382838574786a666b5b5a64738585757678628192838540000000000000000",
        "0000346667582857675728283838385786a5676767475728243857578654222857777422000000000000",
        "314686f75422242434282819282838576686281928282822001124384766525174779696f40000000000",
        "4485972100000011525474512114283858382219283877f7777200125857579472512222000000000000",
        "21978574000000000021f48672001438587767947772f152543411003277677754000000000000000000",
        "002174969694725252f49697220000002174546767540000000000000000110000000000000000000000",
        "000000002132545454522200000000000000001100000000000000000000000000000000000000000000",
    ],
    [
        "000000000000000000000000000000000000000000000000001124241200000000000000000000000000",
        "000000000000000000000000000011121424242424242412222838282824121100000000000011121100",
        "000000000000000000000011c42838383847575838382829283838777738192838242212243838283822",
        "00000000000000000000c23838575747666747573828282829a686f7f728196666282858197877583811",
        "000000000000000011c43858584747676667673838385728296667676638668666672957675877867200",
        "0000000000000011c8373858575747476766573857575738286786578657575766b55766865877f20000",
        "00000000000000c8385738383838586767675738584747475857b5b58667475738a56667575874000000",
        "000000000000c438584767675757383857666728474758576786a5b5b5b5b58658679667388662005100",
        "0000000000c2c83847474757478686664767a567574758385867a6b5b5a686a5666796f7746251510000",
        "0000000000c838583838383838574786a567a5b56757385757575786a586665758721111000000000000",
        "00000011c4283857573838382838574786a566b5b5865738585757678628192938540000000000000000",
        "0000326697582857475728383838385786a5676767475728242858578654222857777421000000000000",
        "216686f75422242438282919283838576686282928282851001124384766523154779696720000000000",
        "22a59751000000115254745131142838583822192838779797f200125857779472512222000000000000",
        "11978694210000000021f485520024285877979777725122343411003277676754000000000000000000",
        "001174979694723252749697220000001174576767540000000000000000110000000000000000000000",
        "000000002132547454522211000000000000001100000000000000000000000000000000000000000000",
    ],
    [
        "000000000000000000000000000000000000000000000000000000222424220000000000000000000000",
        "000000000000000000000000000000111212121212111100000024283828382200000000000000000000",
        "00000000000000000000001112c438283857573838282828242437385777382812000000000000000000",
        "00000000000000000011c4383858585767675757382828281947b597f7f7581938382412122224282412",
        "0000000000000000c2c83858574747666667473828285828388696776728384766382928195858383824",
        "00000000000000c2c838585757674747666638385758282886a577574747676686571957587867672400",
        "000000000000c2c857583858583847666657384757574767573867a667191928b5674786573886520000",
        "000000000011c838574747573838385767473847576747382957b5a5a5572947a547662929f721000000",
        "0000000000c838574767676767866647578666383828283847668686a5a5776696673857677100000000",
        "0000000022c8385757385838576767868667a5b58666668686866666674757f7967764926171e1000000",
        "00000021c82857583838382838385767868666b5b5b5a586866647382819285872005100000000000000",
        "0000326777383847475828383838385766a5676786666747585812121428385858720000000000000000",
        "116686f7742428385838281928283858678657292828282828210000001112589797f452000000000000",
        "328597510000003134575452222428385838322219283858f79774210000002254676797510000000000",
        "11f78694210000000021f486740012283857779494747211323454210000000000111100000000000000",
        "001172979694743252f29696520000001154546767742100000000000000000000000000000000000000",
        "000000002132545454322211000000000000001111000000000000000000000000000000000000000000",
    ],
    [
        "000000000000000000000000000000000000000000000000001124241200000000000000000000000000",
        "000000000000000000000000000011122424242424242412222838282824121100000000000011121100",
        "000000000000000000000011c42838383847575838382828283838777738193838242212243838283822",
        "00000000000000000000c23838585747666747573828283829a686f7f738198666292838197777582821",
        "000000000000000011c43858584747676667673838385738296766676628866666862847665877867200",
        "0000000000000021c857585757574747676647385757573828678657a547282938b54766672877720000",
        "00000000000011c8385738383838586766675738584747475857b5b58686281919a666672829f4000000",
        "000000000000c438584767675758383857666728474758576686a5b5b5b5b58657679667588662005100",
        "0000000000c2c85847474747478686665767a567574758585867a5b5b5a586a566779696746271710000",
        "0000000011c838573838583838576786a567a5b56757385757575786a586665758521111000051000000",
        "00000011c82838575738383838385747868666b5b5865738385757678628192938540000000000000000",
        "0000346697582857675728383838384786a5676767475728243857578654222857777451000000000000",
        "316686f77422242434282819283838576686281929282811001114384766523154779696720000000000",
        "528596110000001154547451211428385838221928387777f7f20022385757f772312222000000000000",
        "11f786942100000000217486720014385877979477727152343421003477676754000000000000000000",
        "001132969694f45232749697520000002174576767540000000000000000110000000000000000000000",
        "000000002132545454522200000000000000001100000000000000000000000000000000000000000000",
    ],
];