use crate::core::{SeqReader, SeqRecord, LOOKUP_TABLES};
use anyhow::Result;
use clap::Args;
use rand::Rng;
#[derive(Args, Debug)]
pub struct RandbaseArgs {
#[arg(value_name = "in.fa")]
pub input: String,
}
pub fn run(args: &RandbaseArgs) -> Result<()> {
let mut reader = if args.input == "-" {
SeqReader::from_stdin()
} else {
SeqReader::from_path(&args.input)?
};
let mut record = SeqRecord::new(Vec::new(), Vec::new());
let mut rng = rand::rng();
while reader.read_next(&mut record)? {
print!(">{}", String::from_utf8_lossy(&record.name));
for (i, &base) in record.seq.iter().enumerate() {
let c = LOOKUP_TABLES.nt16[base as usize];
let bitcnt = LOOKUP_TABLES.bitcnt[c as usize];
let output_base = if bitcnt == 2 {
let m = rng.random::<bool>();
let mut selected = 0;
let mut count = 0;
for j in 0..4 {
if (1 << j) & c != 0 {
if count == (m as usize) {
selected = j;
break;
}
count += 1;
}
}
if base.is_ascii_lowercase() {
b"acgt"[selected]
} else {
b"ACGT"[selected]
}
} else {
base
};
if i % 60 == 0 {
println!();
}
print!("{}", output_base as char);
}
println!();
}
Ok(())
}