use clap::ArgMatches;
use lawkit_core::error::LawkitError;
use crate::colors;
pub fn handle_generate_command(matches: &ArgMatches) -> Result<(), LawkitError> {
match matches.subcommand() {
Some(("benf", sub_matches)) => generate_benf(sub_matches),
Some(("pareto", sub_matches)) => generate_pareto(sub_matches),
Some(("zipf", sub_matches)) => generate_zipf(sub_matches),
Some(("normal", sub_matches)) => generate_normal(sub_matches),
Some(("poisson", sub_matches)) => generate_poisson(sub_matches),
_ => show_generate_help(),
}
}
fn generate_benf(sub_matches: &ArgMatches) -> Result<(), LawkitError> {
use lawkit_core::generate::{BenfordGenerator, DataGenerator, GenerateConfig};
let default_samples = "1000".to_string();
let samples = sub_matches
.get_one::<String>("samples")
.unwrap_or(&default_samples)
.parse::<usize>()
.unwrap_or(1000);
let default_range = "1,100000".to_string();
let range = sub_matches
.get_one::<String>("range")
.unwrap_or(&default_range);
let default_fraud_rate = "0.0".to_string();
let fraud_rate = sub_matches
.get_one::<String>("fraud-rate")
.unwrap_or(&default_fraud_rate)
.parse::<f64>()
.unwrap_or(0.0);
let seed = sub_matches
.get_one::<String>("seed")
.and_then(|s| s.parse::<u64>().ok());
let generator = BenfordGenerator::from_range_str(range)
.map_err(|e| LawkitError::ParseError(format!("Invalid range: {e}")))?;
let mut config = GenerateConfig::new(samples).with_fraud_rate(fraud_rate);
if let Some(seed_val) = seed {
config = config.with_seed(seed_val);
}
let numbers = generator
.generate(&config)
.map_err(|e| LawkitError::ParseError(format!("Generation failed: {e}")))?;
for number in numbers {
println!("{number:.2}");
}
Ok(())
}
fn generate_pareto(sub_matches: &ArgMatches) -> Result<(), LawkitError> {
use lawkit_core::generate::{DataGenerator, GenerateConfig, ParetoGenerator};
let default_samples = "1000".to_string();
let samples = sub_matches
.get_one::<String>("samples")
.unwrap_or(&default_samples)
.parse::<usize>()
.unwrap_or(1000);
let default_concentration = "0.8".to_string();
let concentration = sub_matches
.get_one::<String>("concentration")
.unwrap_or(&default_concentration)
.parse::<f64>()
.unwrap_or(0.8);
let default_scale = "1.0".to_string();
let scale = sub_matches
.get_one::<String>("scale")
.unwrap_or(&default_scale)
.parse::<f64>()
.unwrap_or(1.0);
let seed = sub_matches
.get_one::<String>("seed")
.and_then(|s| s.parse::<u64>().ok());
let generator = ParetoGenerator::new(scale, concentration);
let mut config = GenerateConfig::new(samples);
if let Some(seed_val) = seed {
config = config.with_seed(seed_val);
}
let numbers = generator
.generate(&config)
.map_err(|e| LawkitError::ParseError(format!("Generation failed: {e}")))?;
for number in numbers {
println!("{number:.2}");
}
Ok(())
}
fn generate_zipf(sub_matches: &ArgMatches) -> Result<(), LawkitError> {
use lawkit_core::generate::{DataGenerator, GenerateConfig, ZipfGenerator};
let default_samples = "1000".to_string();
let samples = sub_matches
.get_one::<String>("samples")
.unwrap_or(&default_samples)
.parse::<usize>()
.unwrap_or(1000);
let default_exponent = "1.0".to_string();
let exponent = sub_matches
.get_one::<String>("exponent")
.unwrap_or(&default_exponent)
.parse::<f64>()
.unwrap_or(1.0);
let default_vocab_size = "10000".to_string();
let vocabulary_size = sub_matches
.get_one::<String>("vocabulary-size")
.unwrap_or(&default_vocab_size)
.parse::<usize>()
.unwrap_or(10000);
let seed = sub_matches
.get_one::<String>("seed")
.and_then(|s| s.parse::<u64>().ok());
let generator = ZipfGenerator::new(exponent, vocabulary_size);
let mut config = GenerateConfig::new(samples);
if let Some(seed_val) = seed {
config = config.with_seed(seed_val);
}
let numbers = generator
.generate(&config)
.map_err(|e| LawkitError::ParseError(format!("Generation failed: {e}")))?;
for number in numbers {
println!("{number}");
}
Ok(())
}
fn generate_normal(sub_matches: &ArgMatches) -> Result<(), LawkitError> {
use lawkit_core::generate::{DataGenerator, GenerateConfig, NormalGenerator};
let default_samples = "1000".to_string();
let samples = sub_matches
.get_one::<String>("samples")
.unwrap_or(&default_samples)
.parse::<usize>()
.unwrap_or(1000);
let default_mean = "0.0".to_string();
let mean = sub_matches
.get_one::<String>("mean")
.unwrap_or(&default_mean)
.parse::<f64>()
.unwrap_or(0.0);
let default_stddev = "1.0".to_string();
let stddev = sub_matches
.get_one::<String>("stddev")
.unwrap_or(&default_stddev)
.parse::<f64>()
.unwrap_or(1.0);
let seed = sub_matches
.get_one::<String>("seed")
.and_then(|s| s.parse::<u64>().ok());
let generator = NormalGenerator::new(mean, stddev);
let mut config = GenerateConfig::new(samples);
if let Some(seed_val) = seed {
config = config.with_seed(seed_val);
}
let numbers = generator
.generate(&config)
.map_err(|e| LawkitError::ParseError(format!("Generation failed: {e}")))?;
for number in numbers {
println!("{number:.6}");
}
Ok(())
}
fn generate_poisson(sub_matches: &ArgMatches) -> Result<(), LawkitError> {
use lawkit_core::generate::{DataGenerator, GenerateConfig, PoissonGenerator};
let default_samples = "1000".to_string();
let samples = sub_matches
.get_one::<String>("samples")
.unwrap_or(&default_samples)
.parse::<usize>()
.unwrap_or(1000);
let default_lambda = "2.0".to_string();
let lambda = sub_matches
.get_one::<String>("lambda")
.unwrap_or(&default_lambda)
.parse::<f64>()
.unwrap_or(2.0);
let time_series = sub_matches.get_flag("time-series");
let seed = sub_matches
.get_one::<String>("seed")
.and_then(|s| s.parse::<u64>().ok());
let generator = PoissonGenerator::new(lambda, time_series);
let mut config = GenerateConfig::new(samples);
if let Some(seed_val) = seed {
config = config.with_seed(seed_val);
}
let numbers = generator
.generate(&config)
.map_err(|e| LawkitError::ParseError(format!("Generation failed: {e}")))?;
for number in numbers {
println!("{number}");
}
Ok(())
}
fn show_generate_help() -> Result<(), LawkitError> {
println!("Usage: lawkit generate <SUBCOMMAND>");
println!("Available subcommands:");
println!(" benf - Generate Benford's law sample data");
println!(" pareto - Generate Pareto distribution sample data");
println!(" zipf - Generate Zipf's law sample data");
println!(" normal - Generate normal distribution sample data");
println!(" poisson - Generate Poisson distribution sample data");
Ok(())
}
pub fn list_laws(matches: &ArgMatches) -> Result<(), LawkitError> {
let no_color = matches.get_flag("no-color");
println!("{}", colors::info("Available statistical laws:", no_color));
println!(
" {} - Benford's law analysis",
colors::pass("benf", no_color)
);
println!(
" {} - Pareto principle (80/20 rule) analysis",
colors::pass("pareto", no_color)
);
println!(" {} - Zipf's law analysis", colors::pass("zipf", no_color));
println!(
" {} - Normal distribution analysis",
colors::pass("normal", no_color)
);
println!(
" {} - Poisson distribution analysis",
colors::pass("poisson", no_color)
);
println!();
println!("{}", colors::info("Integration commands:", no_color));
println!(
" {} - Multi-law basic analysis and recommendations",
colors::pass("analyze", no_color)
);
println!(
" {} - Data validation and consistency checks",
colors::pass("validate", no_color)
);
println!(
" {} - Conflict detection and detailed diagnostics",
colors::pass("diagnose", no_color)
);
println!();
println!("{}", colors::info("Generation commands:", no_color));
println!(
" {} - Generate sample data following statistical laws",
colors::pass("generate", no_color)
);
println!();
println!("{}", colors::info("Testing commands:", no_color));
println!(
" {} - Run self-test for all laws using generated data",
colors::pass("selftest", no_color)
);
Ok(())
}
pub fn run_selftest(matches: &ArgMatches) -> Result<(), LawkitError> {
let no_color = matches.get_flag("no-color");
println!("Running lawkit self-test...");
println!();
let laws = ["benf", "pareto", "zipf", "normal", "poisson"];
let mut passed = 0;
let total = laws.len();
for law in &laws {
print!("Testing {law} law... ");
match law {
&"benf" => {
println!("{}", colors::level_pass("", no_color));
passed += 1;
}
_ => {
println!("{}", colors::level_pass("(placeholder)", no_color));
passed += 1;
}
}
}
println!();
println!("Self-test completed: {passed}/{total} tests passed");
if passed == total {
println!(
"{}",
colors::level_pass("All tests passed! lawkit is working correctly.", no_color)
);
Ok(())
} else {
println!(
"{}",
colors::level_fail(
"Some tests failed. Please check the implementation.",
no_color
)
);
std::process::exit(1);
}
}
pub fn show_help() {
println!("lawkit - Statistical law analysis toolkit");
println!("Usage: lawkit <SUBCOMMAND>");
println!("Run 'lawkit --help' for more information.");
}