use crate::tcp::{stock::Kline, Tdx};
use std::error::Error;
#[derive(Debug, Clone)]
pub struct KlineBuilder<'a> {
code: Option<&'a str>,
market: Option<u16>,
category: Option<u16>,
start: Option<u16>,
count: Option<u16>,
}
impl<'a> KlineBuilder<'a> {
pub fn new() -> Self {
Self {
code: None,
market: None,
category: None,
start: None,
count: None,
}
}
pub fn code(mut self, code: &'a str) -> Self {
self.code = Some(code);
self
}
pub fn market(mut self, market: u16) -> Self {
self.market = Some(market);
self
}
pub fn category(mut self, category: u16) -> Self {
self.category = Some(category);
self
}
pub fn start(mut self, start: u16) -> Self {
self.start = Some(start);
self
}
pub fn count(mut self, count: u16) -> Self {
self.count = Some(count);
self
}
pub fn build(self) -> Result<Kline<'a>, String> {
let code = self.code.ok_or("缺少必填参数: code(股票代码)")?;
let market = self.market.unwrap_or_else(|| {
if code.starts_with('6') {
1 } else if code.starts_with('0') || code.starts_with('3') {
0 } else {
0 }
});
let category = self.category.unwrap_or(9); let start = self.start.unwrap_or(0); let count = self.count.unwrap_or(100);
if count > 800 {
return Err("count 参数不能超过 800".to_string());
}
Ok(Kline::new(market, code, category, start, count))
}
}
impl<'a> Default for KlineBuilder<'a> {
fn default() -> Self {
Self::new()
}
}
impl<'a> KlineBuilder<'a> {
pub fn daily(code: &'a str, count: u16) -> Result<Kline<'a>, String> {
Self::new()
.code(code)
.category(9)
.count(count)
.build()
}
pub fn min60(code: &'a str, count: u16) -> Result<Kline<'a>, String> {
Self::new()
.code(code)
.category(3)
.count(count)
.build()
}
pub fn min30(code: &'a str, count: u16) -> Result<Kline<'a>, String> {
Self::new()
.code(code)
.category(2)
.count(count)
.build()
}
pub fn min15(code: &'a str, count: u16) -> Result<Kline<'a>, String> {
Self::new()
.code(code)
.category(1)
.count(count)
.build()
}
pub fn min5(code: &'a str, count: u16) -> Result<Kline<'a>, String> {
Self::new()
.code(code)
.category(0)
.count(count)
.build()
}
pub fn min1(code: &'a str, count: u16) -> Result<Kline<'a>, String> {
Self::new()
.code(code)
.category(7)
.count(count)
.build()
}
pub fn weekly(code: &'a str, count: u16) -> Result<Kline<'a>, String> {
Self::new()
.code(code)
.category(5)
.count(count)
.build()
}
pub fn monthly(code: &'a str, count: u16) -> Result<Kline<'a>, String> {
Self::new()
.code(code)
.category(6)
.count(count)
.build()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_builder_basic() {
let kline = KlineBuilder::new()
.code("600000")
.category(9)
.count(100)
.build()
.unwrap();
assert_eq!(kline.code, "600000");
assert_eq!(kline.category, 9);
assert_eq!(kline.count, 100);
}
#[test]
fn test_builder_defaults() {
let kline = KlineBuilder::new()
.code("600000")
.build()
.unwrap();
assert_eq!(kline.code, "600000");
assert_eq!(kline.category, 9); assert_eq!(kline.count, 100); assert_eq!(kline.start, 0); }
#[test]
fn test_builder_auto_market() {
let kline1 = KlineBuilder::new()
.code("600000")
.build()
.unwrap();
assert_eq!(kline1.market, 1);
let kline2 = KlineBuilder::new()
.code("000001")
.build()
.unwrap();
assert_eq!(kline2.market, 0);
let kline3 = KlineBuilder::new()
.code("300001")
.build()
.unwrap();
assert_eq!(kline3.market, 0); }
#[test]
fn test_builder_convenience_methods() {
let kline1 = KlineBuilder::daily("600000", 100).unwrap();
assert_eq!(kline1.category, 9);
let kline2 = KlineBuilder::min60("600000", 100).unwrap();
assert_eq!(kline2.category, 3);
let kline3 = KlineBuilder::min30("600000", 100).unwrap();
assert_eq!(kline3.category, 2);
let kline4 = KlineBuilder::min15("600000", 100).unwrap();
assert_eq!(kline4.category, 1);
let kline5 = KlineBuilder::min5("600000", 100).unwrap();
assert_eq!(kline5.category, 0);
let kline6 = KlineBuilder::min1("600000", 100).unwrap();
assert_eq!(kline6.category, 7);
let kline7 = KlineBuilder::weekly("600000", 100).unwrap();
assert_eq!(kline7.category, 5);
let kline8 = KlineBuilder::monthly("600000", 100).unwrap();
assert_eq!(kline8.category, 6);
}
#[test]
fn test_builder_missing_code() {
let result = KlineBuilder::new().build();
assert!(result.is_err());
assert_eq!(result.unwrap_err(), "缺少必填参数: code(股票代码)");
}
#[test]
fn test_builder_count_too_large() {
let result = KlineBuilder::new()
.code("600000")
.count(801)
.build();
assert!(result.is_err());
assert_eq!(result.unwrap_err(), "count 参数不能超过 800");
}
#[test]
fn test_builder_chain() {
let kline = KlineBuilder::new()
.code("600000")
.market(1)
.category(9)
.start(0)
.count(200)
.build()
.unwrap();
assert_eq!(kline.code, "600000");
assert_eq!(kline.market, 1);
assert_eq!(kline.category, 9);
assert_eq!(kline.start, 0);
assert_eq!(kline.count, 200);
}
}