第八版

This commit is contained in:
YuWuKunCheng
2026-05-29 04:05:36 +08:00
parent ae57090d7f
commit 5c3179eec8
31 changed files with 4111 additions and 1730 deletions
+495 -135
View File
@@ -29,30 +29,32 @@ use crate::kline::chan_kline::缠论K线;
use crate::structure::fractal_obj::;
use crate::structure::segment_feat::线;
use crate::types::{, , };
use std::rc::Rc;
use std::sync::atomic::{AtomicBool, AtomicI64, Ordering};
use std::sync::{Arc, RwLock};
/// 虚线 — 笔和线段的通用数据结构
///
/// 笔和线段共享此 struct,通过 `标识` 字段区分 ("笔"/"线段"/"扩展线段"等)
#[derive(Debug, Clone)]
/// 可变字段使用 Cell/RefCell 实现内部可变性,确保 Rc 指针身份一致
#[derive(Debug)]
pub struct 线 {
pub : String,
pub : i64,
pub : i64,
pub : Rc<>,
pub : Rc<>,
pub : bool,
pub : Vec<Rc<线>>,
pub : Vec<Option<Rc<线>>>,
pub _中枢序列: Vec<Rc<>>,
pub _中枢序列: Vec<Rc<>>,
pub _中枢序列: Vec<Rc<>>,
pub K线: Option<Rc<K线>>,
pub : String,
pub _特征序列_显示: bool,
pub : Option<>,
pub : Option<Rc<线>>,
pub : bool,
pub : RwLock<String>,
pub : AtomicI64,
pub : AtomicI64,
pub : Arc<>,
pub : RwLock<Arc<>>,
pub : AtomicBool,
pub : RwLock<Vec<Arc<线>>>,
pub : RwLock<Vec<Option<Arc<线>>>>,
pub _中枢序列: RwLock<Vec<Arc<>>>,
pub _中枢序列: RwLock<Vec<Arc<>>>,
pub _中枢序列: RwLock<Vec<Arc<>>>,
pub K线: RwLock<Option<Arc<K线>>>,
pub : RwLock<String>,
pub _特征序列_显示: AtomicBool,
pub : RwLock<Option<>>,
pub : RwLock<Option<Arc<线>>>,
pub : AtomicBool,
}
/// MACD行为统计 — 统计MACD行为 方法的返回类型
@@ -67,51 +69,73 @@ pub struct MACD行为统计 {
pub : Vec<(usize, usize, usize)>,
}
impl Clone for 线 {
fn clone(&self) -> Self {
Self {
: RwLock::new(self..read().unwrap().clone()),
: AtomicI64::new(self..load(Ordering::Relaxed)),
: AtomicI64::new(self..load(Ordering::Relaxed)),
: Arc::clone(&self.),
: RwLock::new(Arc::clone(&self..read().unwrap())),
: AtomicBool::new(self..load(Ordering::Relaxed)),
: RwLock::new(self..read().unwrap().clone()),
: RwLock::new(self..read().unwrap().clone()),
_中枢序列: RwLock::new(self._中枢序列.read().unwrap().clone()),
_中枢序列: RwLock::new(self._中枢序列.read().unwrap().clone()),
_中枢序列: RwLock::new(self._中枢序列.read().unwrap().clone()),
K线: RwLock::new(self.K线.read().unwrap().clone()),
: RwLock::new(self..read().unwrap().clone()),
_特征序列_显示: AtomicBool::new(self._特征序列_显示.load(Ordering::Relaxed)),
: RwLock::new(*self..read().unwrap()),
: RwLock::new(self..read().unwrap().clone()),
: AtomicBool::new(self..load(Ordering::Relaxed)),
}
}
}
impl 线 {
pub fn new(
: i64,
: String,
: Rc<>,
: Rc<>,
: Arc<>,
: Arc<>,
: i64,
: bool,
) -> Self {
Self {
,
,
,
: AtomicI64::new(),
: RwLock::new(),
: AtomicI64::new(),
,
,
,
: Vec::new(),
: Vec::new(),
_中枢序列: Vec::new(),
_中枢序列: Vec::new(),
_中枢序列: Vec::new(),
K线: None,
: "文武".into(),
_特征序列_显示: false,
: None,
: None,
: false,
: RwLock::new(),
: AtomicBool::new(),
: RwLock::new(Vec::new()),
: RwLock::new(Vec::new()),
_中枢序列: RwLock::new(Vec::new()),
_中枢序列: RwLock::new(Vec::new()),
_中枢序列: RwLock::new(Vec::new()),
K线: RwLock::new(None),
: RwLock::new("文武".into()),
_特征序列_显示: AtomicBool::new(false),
: RwLock::new(None),
: RwLock::new(None),
: AtomicBool::new(false),
}
}
/// 笔序列(基础序列的别名)
pub fn (&self) -> &Vec<Rc<线>> {
&self.
}
pub fn (&self) -> String {
format!(
"{}:{}:{}:{}",
self..., self..., self., self.
self...,
self...,
self..read().unwrap(),
self..load(Ordering::Relaxed)
)
}
/// 方向 — 文到武的方向
pub fn (&self) -> {
match (self.., self..) {
match (self.., self..read().unwrap().) {
(::, ::) => ::,
(::, ::) => ::,
(::, ::) => ::,
@@ -123,54 +147,60 @@ impl 虚线 {
/// 虚线高
pub fn (&self) -> f64 {
if self.() == :: {
self...
self....get()
} else {
self...
self..read().unwrap()...get()
}
}
/// 虚线低
pub fn (&self) -> f64 {
if self.() == :: {
self...
self..read().unwrap()...get()
} else {
self...
self....get()
}
}
/// 判断两个虚线是否首尾相连
pub fn (&self, : &线) -> bool {
if self. != . {
if *self..read().unwrap() != *..read().unwrap() {
return false;
}
Rc::as_ptr(&.) == Rc::as_ptr(&self.)
Arc::as_ptr(&*..read().unwrap()) == Arc::as_ptr(&self.)
}
/// 判断两个虚线是否首尾相连
pub fn (&self, : &线) -> bool {
if self. != . {
if *self..read().unwrap() != *..read().unwrap() {
return false;
}
Rc::as_ptr(&self.) == Rc::as_ptr(&.)
Arc::as_ptr(&*self..read().unwrap()) == Arc::as_ptr(&.)
}
/// 获取该虚线范围内的普K序列
pub fn K序列(&self, K序列: &[Rc<K线>]) -> Vec<Rc<K线>> {
pub fn K序列(&self, K序列: &[Arc<K线>]) -> Vec<Arc<K线>> {
// 使用指针查找(与 Python list.index 身份匹配行为一致),
// 而非序号切片——因为序号可能与实际位置不一致。
let = K序列
.iter()
.position(|k| Rc::as_ptr(k) == Rc::as_ptr(&self...K线));
let = K序列
.iter()
.position(|k| Rc::as_ptr(k) == Rc::as_ptr(&self...K线));
.position(|k| Arc::as_ptr(k) == Arc::as_ptr(&*self...K线.read().unwrap()));
let = K序列.iter().position(|k| {
Arc::as_ptr(k) == Arc::as_ptr(&*self..read().unwrap()..K线.read().unwrap())
});
match (, ) {
(Some(s), Some(e)) if s <= e => K序列[s..=e].to_vec(),
_ => {
// 指针查找失败时回退到序号方式
println!("[警告]虚线.获取普K序列 <指针查找失败时回退到序号方式>");
let = self... as usize;
let = self... as usize;
let = self
.
.read()
.unwrap()
.
.
.load(Ordering::Relaxed) as usize;
if < K序列.len() && < K序列.len() && <= {
K序列[..=].to_vec()
} else {
@@ -181,36 +211,43 @@ impl 虚线 {
}
/// 获取该虚线范围内的缠K序列
pub fn K序列(&self, K序列: &[Rc<K线>]) -> Vec<Rc<K线>> {
K线::(K序列, &self.., &self..).unwrap_or_default()
pub fn K序列(&self, K序列: &[Arc<K线>]) -> Vec<Arc<K线>> {
K线::(K序列, &self.., &self..read().unwrap().).unwrap_or_default()
}
/// 获取_武 — 递归获取虚线的终点分型(笔直接返回武,线段递归到底层笔的武)
pub fn _武(&self) -> Rc<> {
if self. == "" {
return Rc::clone(&self.);
pub fn _武(&self) -> Arc<> {
if *self..read().unwrap() == "" {
return self..read().unwrap().clone();
}
let mut current: &线 = self;
while current. != "" {
current = &*current..last().unwrap();
let mut current_rc = Arc::clone(self..read().unwrap().last().unwrap());
loop {
if *current_rc..read().unwrap() == "" {
return current_rc..read().unwrap().clone();
}
let next = Arc::clone(current_rc..read().unwrap().last().unwrap());
current_rc = next;
}
Rc::clone(&current.)
}
/// 获取数据文本(用于保存/调试)
pub fn (&self) -> String {
use crate::utils::format_f64_g;
if self. == "" {
if *self..read().unwrap() == "" {
return format!(
"{}, {}, {}, 文:({},{}), 武:({},{}), {}",
self.,
self.,
self.,
self..read().unwrap(),
self..load(Ordering::Relaxed),
self..load(Ordering::Relaxed),
self..,
format_f64_g(self..),
self..,
format_f64_g(self..),
if self. { "True" } else { "False" },
self..read().unwrap().,
format_f64_g(self..read().unwrap().),
if self..load(Ordering::Relaxed) {
"True"
} else {
"False"
},
);
}
@@ -225,11 +262,11 @@ impl 虚线 {
}
};
let _str = match &self. {
let _str = match &*self..read().unwrap() {
Some(g) => format!("{}", g),
None => "None".to_string(),
};
let _str = match &self. {
let _str = match &*self..read().unwrap() {
Some(d) => format!("{}", d),
None => "None".to_string(),
};
@@ -238,6 +275,8 @@ impl 虚线 {
let _str = format!(
"[{}]",
self._中枢序列
.read()
.unwrap()
.iter()
.map(|h| format!("{}", h))
.collect::<Vec<_>>()
@@ -246,6 +285,8 @@ impl 虚线 {
let _str = format!(
"[{}]",
self._中枢序列
.read()
.unwrap()
.iter()
.map(|h| format!("{}", h))
.collect::<Vec<_>>()
@@ -254,6 +295,8 @@ impl 虚线 {
let _str = format!(
"[{}]",
self._中枢序列
.read()
.unwrap()
.iter()
.map(|h| format!("{}", h))
.collect::<Vec<_>>()
@@ -284,15 +327,15 @@ impl 虚线 {
format!(
"{}, {}, {}, 文:({},{}), 武:({},{}), {}, {}, ({}, {}, {}), (前: {}, 后: {}, 三: {}, 伤: {}), 实: {}, 虚: {}, 合: {}, {}, {}, {}, {}",
self.,
self.,
self.,
self..read().unwrap(),
self..load(Ordering::Relaxed),
self..load(Ordering::Relaxed),
self..,
format_f64_g(self..),
self..,
format_f64_g(self..),
if self. { "True" } else { "False" },
self..len(),
self..read().unwrap().,
format_f64_g(self..read().unwrap().),
if self..load(Ordering::Relaxed) { "True" } else { "False" },
self..read().unwrap().len(),
_bool(_a),
_bool(_b),
_bool(_c),
@@ -303,33 +346,39 @@ impl 虚线 {
_str,
_str,
_str,
self.,
self..read().unwrap(),
_str,
_str,
if self. { "True" } else { "False" },
if self..load(Ordering::Relaxed) { "True" } else { "False" },
)
}
// ---- 关联函数(静态工厂方法) ----
/// 创建笔
pub fn (: Rc<>, : Rc<>, : bool) -> Self {
pub fn (: Arc<>, : Arc<>, : bool) -> Self {
Self::new(0, "".into(), , , 1, )
}
/// 创建线段
pub fn 线(线: &[Rc<线>]) -> Self {
let = Rc::clone(&线[0].);
let = Rc::clone(&线[线.len() - 1].);
let = if 线[0]. == "" {
pub fn 线(线: &[Arc<线>]) -> Self {
let = Arc::clone(&线[0].);
let = Arc::clone(&*线[线.len() - 1]..read().unwrap());
assert!(
. != .,
"创建线段: 文.结构 == 武.结构 文={}, 武={}",
,
);
let : String = if *线[0]..read().unwrap() == "" {
"线段".into()
} else {
format!("线段<{}>", 线[0].)
format!("线段<{}>", 线[0]..read().unwrap())
};
let = 线[0]. + 1;
let mut = Self::new(0, , , , , true);
. = 线.to_vec();
. = "文武".into();
let = 线[0]..load(Ordering::Relaxed) + 1;
let = Self::new(0, , , , , true);
*..write().unwrap() = 线.to_vec();
*..write().unwrap() = "文武".into();
}
@@ -383,8 +432,12 @@ impl 虚线 {
// ---- MACD柱子均值计算 ----
/// 计算MACD柱子均值 — 虚线范围内所有MACD柱的绝对值均值
pub fn MACD柱子均值(K序列: &[Rc<K线>], 线: &线) -> f64 {
let K线序列 = K线::rc(K序列, &线...K线, &线...K线);
pub fn MACD柱子均值(K序列: &[Arc<K线>], 线: &线) -> f64 {
let K线序列 = K线::rc(
K序列,
&*线...K线.read().unwrap(),
&*线..read().unwrap()..K线.read().unwrap(),
);
if K线序列.is_empty() {
return 0.0;
}
@@ -397,8 +450,12 @@ impl 虚线 {
}
/// 计算MACD柱子均值_阴 — 负柱的绝对值均值
pub fn MACD柱子均值_阴(K序列: &[Rc<K线>], 线: &线) -> Option<f64> {
let K线序列 = K线::rc(K序列, &线...K线, &线...K线);
pub fn MACD柱子均值_阴(K序列: &[Arc<K线>], 线: &线) -> Option<f64> {
let K线序列 = K线::rc(
K序列,
&*线...K线.read().unwrap(),
&*线..read().unwrap()..K线.read().unwrap(),
);
let : Vec<f64> = K线序列
.iter()
.filter_map(|k| k.macd.as_ref())
@@ -413,8 +470,12 @@ impl 虚线 {
}
/// 计算MACD柱子均值_阳 — 正柱的绝对值均值
pub fn MACD柱子均值_阳(K序列: &[Rc<K线>], 线: &线) -> Option<f64> {
let K线序列 = K线::rc(K序列, &线...K线, &线...K线);
pub fn MACD柱子均值_阳(K序列: &[Arc<K线>], 线: &线) -> Option<f64> {
let K线序列 = K线::rc(
K序列,
&*线...K线.read().unwrap(),
&*线..read().unwrap()..K线.read().unwrap(),
);
let : Vec<f64> = K线序列
.iter()
.filter_map(|k| k.macd.as_ref())
@@ -431,8 +492,10 @@ impl 虚线 {
// ---- 武之MACD比较 ----
/// 武之全量MACD均值 — 武端MACD柱是否小于均值(背驰)
pub fn MACD均值(K序列: &[Rc<K线>], 线: &线) -> bool {
let _MACD = match &线...K线.macd {
pub fn MACD均值(K序列: &[Arc<K线>], 线: &线) -> bool {
let _ref = 线..read().unwrap();
let = _ref..K线.read().unwrap();
let _MACD = match .macd.as_ref() {
Some(m) => m.MACD柱.abs(),
None => return false,
};
@@ -440,7 +503,7 @@ impl 虚线 {
}
/// 武之MACD均值 — 按方向选择阴/阳均值比对
pub fn MACD均值(K序列: &[Rc<K线>], 线: &线) -> bool {
pub fn MACD均值(K序列: &[Arc<K线>], 线: &线) -> bool {
if 线.() == :: {
Self::MACD均值_阳(K序列, 线)
} else {
@@ -449,8 +512,10 @@ impl 虚线 {
}
/// 武之MACD均值_阴 — 武端负柱是否小于阴均值
pub fn MACD均值_阴(K序列: &[Rc<K线>], 线: &线) -> bool {
let _MACD = match &线...K线.macd {
pub fn MACD均值_阴(K序列: &[Arc<K线>], 线: &线) -> bool {
let _ref = 线..read().unwrap();
let = _ref..K线.read().unwrap();
let _MACD = match .macd.as_ref() {
Some(m) => m.MACD柱.abs(),
None => return false,
};
@@ -461,8 +526,10 @@ impl 虚线 {
}
/// 武之MACD均值_阳 — 武端正柱是否小于阳均值
pub fn MACD均值_阳(K序列: &[Rc<K线>], 线: &线) -> bool {
let _MACD = match &线...K线.macd {
pub fn MACD均值_阳(K序列: &[Arc<K线>], 线: &线) -> bool {
let _ref = 线..read().unwrap();
let = _ref..K线.read().unwrap();
let _MACD = match .macd.as_ref() {
Some(m) => m.MACD柱.abs(),
None => return false,
};
@@ -473,12 +540,18 @@ impl 虚线 {
}
/// 武之MACD极值 — 武端MACD柱是否为区间极值
pub fn MACD极值(K序列: &[Rc<K线>], 线: &线) -> bool {
let _MACD = match &线...K线.macd {
pub fn MACD极值(K序列: &[Arc<K线>], 线: &线) -> bool {
let _ref = 线..read().unwrap();
let = _ref..K线.read().unwrap();
let _MACD = match .macd.as_ref() {
Some(m) => m.MACD柱,
None => return false,
};
let K线序列 = K线::rc(K序列, &线...K线, &线...K线);
let K线序列 = K线::rc(
K序列,
&*线...K线.read().unwrap(),
&*线..read().unwrap()..K线.read().unwrap(),
);
let : Vec<f64> = K线序列
.iter()
.filter_map(|k| k.macd.as_ref())
@@ -500,7 +573,7 @@ impl 虚线 {
/// 计算K线序列MACD趋向背驰 — 分析 MACD柱/DIF/DEA 三项背驰信号
pub fn K线序列MACD趋向背驰(
K序列: &[Rc<K线>], :
K序列: &[Arc<K线>], :
) -> [bool; 3] {
if K序列.is_empty() {
return [false, false, false];
@@ -508,7 +581,7 @@ impl 虚线 {
let = &K序列[K序列.len() - 1];
if == :: {
let : Vec<&Rc<K线>> = K序列
let : Vec<&Arc<K线>> = K序列
.iter()
.filter(|k| k.macd.as_ref().map_or(false, |m| m.MACD柱 > 0.0))
.collect();
@@ -530,7 +603,7 @@ impl 虚线 {
.unwrap_or(std::cmp::Ordering::Equal)
})
.unwrap();
let mut = vec![Rc::clone(*), Rc::clone()];
let mut = vec![Arc::clone(*), Arc::clone()];
.sort_by_key(|k| k.);
if let (Some(m0), Some(m1)) = ([0].macd.as_ref(), [1].macd.as_ref()) {
if m0.MACD柱 > m1.MACD柱 && [0]. < [1]. {
@@ -574,7 +647,7 @@ impl 虚线 {
} else {
let : Vec<&Rc<K线>> = K序列
let : Vec<&Arc<K线>> = K序列
.iter()
.filter(|k| k.macd.as_ref().map_or(false, |m| m.MACD柱 < 0.0))
.collect();
@@ -597,7 +670,7 @@ impl 虚线 {
.unwrap_or(std::cmp::Ordering::Equal)
})
.unwrap();
let mut = vec![Rc::clone(*), Rc::clone()];
let mut = vec![Arc::clone(*), Arc::clone()];
.sort_by_key(|k| k.);
if let (Some(m0), Some(m1)) = ([0].macd.as_ref(), [1].macd.as_ref()) {
if m0.MACD柱 < m1.MACD柱 && [0]. > [1]. {
@@ -646,7 +719,7 @@ impl 虚线 {
// ---- MACD柱子分段 ----
/// 计算MACD柱子分段 — 按正负号将MACD柱子分段
pub fn MACD柱子分段(k线序列: &[Rc<K线>]) -> Vec<Vec<f64>> {
pub fn MACD柱子分段(k线序列: &[Arc<K线>]) -> Vec<Vec<f64>> {
if k线序列.is_empty() {
return Vec::new();
}
@@ -729,7 +802,7 @@ impl 虚线 {
/// 统计MACD行为 — 分析DIF/DEA穿零轴和金叉死叉
pub fn MACD行为(
K序列: &[Rc<K线>],
K序列: &[Arc<K线>],
: usize,
: usize,
) -> MACD行为统计 {
@@ -820,34 +893,39 @@ impl 虚线 {
let K序列 = &.K线序列;
let = &.;
if 线. != "" && 线. != "线段" && !线..starts_with("线段<")
if *线..read().unwrap() != ""
&& *线..read().unwrap() != "线段"
&& !线..read().unwrap().starts_with("线段<")
{
return (false, "标识不在范围内".into());
}
// KDJ指标完整性检查
match &线...K线.kdj {
let _ref = 线..read().unwrap();
let = _ref..K线.read().unwrap();
match .kdj.as_ref() {
Some(kdj) if kdj.K.is_some() && kdj.D.is_some() && kdj.J.is_some() => {}
_ => return (false, "KDJ指标不完整".into()),
}
let = Self::K买卖点模式(&._指标模式, &线.., );
let =
Self::K买卖点模式(&._指标模式, &线..read().unwrap()., );
let = false;
let : Vec<Rc<K线>> = if 线. == "" {
let : Vec<Arc<K线>> = if *线..read().unwrap() == "" {
crate::algorithm::bi::::(线, )
} else {
crate::algorithm::segment::线::(线, )
};
if {
if 线. == "" {
if *线..read().unwrap() == "" {
if Self::MACD均值(K序列, 线) {
return (true, "武之MACD均值".into());
}
if Self::MACD极值(K序列, 线) && !.is_empty() {
return (true, "背驰过且极值".into());
} else if 线..MACD柱子分型匹配() {
} else if 线..read().unwrap().MACD柱子分型匹配() {
return (
true,
format!(
@@ -862,14 +940,14 @@ impl 虚线 {
);
}
}
if 线. != ""
if *线..read().unwrap() != ""
&& crate::algorithm::segment::线::线(线, )
{
return (true, "线段内部背驰".into());
}
}
if ! && && 线...MACD柱子匹配() {
if ! && && 线..read().unwrap()..MACD柱子匹配() {
if Self::MACD极值(K序列, 线) && .len() > 2 {
return (true, "没结果, 极值, 柱子分型匹配, 背驰过大于2次".into());
}
@@ -879,18 +957,300 @@ impl 虚线 {
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::kline::bar::K线;
use crate::kline::chan_kline::K线;
use crate::types::;
/// 辅助:创建一根最小化的原始K线
fn _创建K线(: i64, : f64, : f64, : f64, : f64) -> K线 {
let mut k = K线::default();
k. = ;
k. = ;
k. = ;
k. = ;
k. = ;
k
}
/// 辅助:创建一根缠论K线
fn _创建缠K(
: i64,
: f64,
: f64,
: ,
: Option<>,
: i64,
) -> Arc<K线> {
let K = Arc::new(_创建K线(, , , , ));
let K = K线::K(, , , , , , K, None);
Arc::new(K)
}
/// 辅助:创建顶分型
fn _创建顶分型(: i64, : f64, : f64, : i64) -> Arc<> {
let = _创建缠K(
- 2,
- 2.0,
- 2.0,
::,
Some(::),
- 2,
);
let = _创建缠K(, , , ::, Some(::), );
let = _创建缠K(
+ 2,
- 1.0,
- 1.0,
::,
Some(::),
+ 2,
);
Arc::new(::new(Some(), , Some()))
}
/// 辅助:创建底分型
fn _创建底分型(: i64, : f64, : f64, : i64) -> Arc<> {
let = _创建缠K(
- 2,
+ 2.0,
+ 2.0,
::,
Some(::),
- 2,
);
let = K线::K(
,
,
,
::,
Some(::),
,
Arc::new(_创建K线(, , , , )),
None,
);
..set();
let = Arc::new();
let = _创建缠K(
+ 2,
+ 1.0,
+ 1.0,
::,
Some(::),
+ 2,
);
Arc::new(::new(Some(), , Some()))
}
// ============================================================
// Cell 字段读写测试
// ============================================================
#[test]
fn test_Cell字段读写一致性() {
let = _创建顶分型(100, 50.0, 40.0, 5);
let = _创建底分型(200, 30.0, 20.0, 10);
let = 线::(, , true);
assert_eq!(..load(Ordering::Relaxed), 0);
assert!(..load(Ordering::Relaxed));
assert!(!..load(Ordering::Relaxed));
assert!(..read().unwrap().is_none());
// 修改 Cell 字段
..store(42, Ordering::Relaxed);
..store(false, Ordering::Relaxed);
..store(true, Ordering::Relaxed);
*..write().unwrap() = Some(::new(200.0, 100.0));
assert_eq!(..load(Ordering::Relaxed), 42);
assert!(!..load(Ordering::Relaxed));
assert!(..load(Ordering::Relaxed));
let qk = ..read().unwrap().unwrap();
assert!((qk. - 200.0).abs() < 0.01);
assert!((qk. - 100.0).abs() < 0.01);
}
// ============================================================
// RefCell 字段读写测试
// ============================================================
#[test]
fn test_RefCell字段读写一致性() {
let = _创建顶分型(100, 50.0, 40.0, 5);
let = _创建底分型(200, 30.0, 20.0, 10);
let = 线::(, , true);
// 标识
assert_eq!(*..read().unwrap(), "");
*..write().unwrap() = "测试标识".into();
assert_eq!(*..read().unwrap(), "测试标识");
// 模式
assert_eq!(*..read().unwrap(), "文武");
*..write().unwrap() = "全量".into();
assert_eq!(*..read().unwrap(), "全量");
// 基础序列
assert!(..read().unwrap().is_empty());
let = _创建底分型(300, 20.0, 10.0, 15);
let 2 = 线::(Arc::clone(&*..read().unwrap()), , true);
..write().unwrap().push(Arc::new(2));
assert_eq!(..read().unwrap().len(), 1);
// 武 - Replace with new 分型
let = _创建底分型(400, 15.0, 5.0, 20);
let _ptr = Arc::as_ptr(&);
*..write().unwrap() = Arc::clone(&);
assert_eq!(Arc::as_ptr(&*..read().unwrap()), _ptr);
}
// ============================================================
// Clone 后 Rc 指针身份一致
// ============================================================
#[test]
fn test_虚线Clone后文Rc指针一致() {
let = _创建顶分型(100, 50.0, 40.0, 5);
let = _创建底分型(200, 30.0, 20.0, 10);
let = 线::(Arc::clone(&), Arc::clone(&), true);
let = .clone();
// 文 Rc 指针应一致
assert_eq!(Arc::as_ptr(&.), Arc::as_ptr(&));
assert_eq!(Arc::as_ptr(&.), Arc::as_ptr(&.));
// 武 Rc 指针应一致
assert_eq!(Arc::as_ptr(&*..read().unwrap()), Arc::as_ptr(&));
assert_eq!(
Arc::as_ptr(&*..read().unwrap()),
Arc::as_ptr(&*..read().unwrap())
);
}
#[test]
fn test_虚线Clone是深拷贝Cell值而非共享() {
let = _创建顶分型(100, 50.0, 40.0, 5);
let = _创建底分型(200, 30.0, 20.0, 10);
let = 线::(, , true);
..store(10, Ordering::Relaxed);
let = .clone();
// Clone 后序号应独立(deep copy for Cell
..store(99, Ordering::Relaxed);
assert_eq!(..load(Ordering::Relaxed), 10);
assert_eq!(..load(Ordering::Relaxed), 99);
// Rc 指针仍应一致(文/武 共享)
assert_eq!(Arc::as_ptr(&.), Arc::as_ptr(&.));
}
// ============================================================
// 多 Rc 共享下 Cell/RefCell 修改可见性
// ============================================================
#[test]
fn test_多Rc共享下Cell修改对所有引用可见() {
let = _创建顶分型(100, 50.0, 40.0, 5);
let = _创建底分型(200, 30.0, 20.0, 10);
let _rc1 = Arc::new(线::(, , true));
let _rc2 = Arc::clone(&_rc1);
// 通过 rc1 修改 Cell
_rc1..store(77, Ordering::Relaxed);
// rc2 应能看到
assert_eq!(_rc2..load(Ordering::Relaxed), 77);
// 通过 rc1 修改 RefCell
*_rc1..write().unwrap() = "配置".into();
assert_eq!(*_rc2..read().unwrap(), "配置");
// 通过 rc1 修改 武
let = _创建底分型(400, 15.0, 5.0, 20);
let _ptr = Arc::as_ptr(&);
*_rc1..write().unwrap() = Arc::clone(&);
assert_eq!(Arc::as_ptr(&*_rc2..read().unwrap()), _ptr);
}
// ============================================================
// 获取_武 递归正确性
// ============================================================
#[test]
fn test_获取武_笔级别直接返回武() {
let = _创建顶分型(100, 50.0, 40.0, 5);
let = _创建底分型(200, 30.0, 20.0, 10);
let = 线::(Arc::clone(&), Arc::clone(&), true);
let wu = ._武();
assert_eq!(Arc::as_ptr(&*..read().unwrap()), Arc::as_ptr(&wu));
assert_eq!(Arc::as_ptr(&wu), Arc::as_ptr(&));
}
#[test]
fn test_获取武_线段级别递归到底层笔() {
let 1 = _创建顶分型(100, 50.0, 40.0, 5);
let 1 = _创建底分型(200, 30.0, 20.0, 10);
let 2 = _创建顶分型(300, 55.0, 45.0, 15);
let 2 = _创建底分型(400, 25.0, 15.0, 20);
let 1 = Arc::new(线::(Arc::clone(&1), Arc::clone(&1), true));
let 2 = Arc::new(线::(Arc::clone(&1), Arc::clone(&2), true));
let 3 = Arc::new(线::(Arc::clone(&2), Arc::clone(&2), true));
let = 线::线(&[Arc::clone(&1), Arc::clone(&2), Arc::clone(&3)]);
// 线段的 获取_武 应返回底层最后一笔的武(底2)
let wu = ._武();
assert_eq!(Arc::as_ptr(&wu), Arc::as_ptr(&2));
// 笔1 的 获取_武 应返回底1
let wu1 = 1._武();
assert_eq!(Arc::as_ptr(&wu1), Arc::as_ptr(&1));
}
// ============================================================
// 虚线 字段原子性 - 修改不影响文(不可变字段)
// ============================================================
#[test]
fn test_修改武不影响文Rc指针() {
let = _创建顶分型(100, 50.0, 40.0, 5);
let 1 = _创建底分型(200, 30.0, 20.0, 10);
let 2 = _创建底分型(300, 25.0, 15.0, 15);
let = 线::(Arc::clone(&), Arc::clone(&1), true);
let _ptr_before = Arc::as_ptr(&.);
// 修改武
*..write().unwrap() = Arc::clone(&2);
// 文指针不变
assert_eq!(Arc::as_ptr(&.), _ptr_before);
// 但方向变了(因为武从底1变成底2)
let = ..read().unwrap().;
assert_eq!(, 300);
}
}
impl std::fmt::Display for 线 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self. == "" {
if *self..read().unwrap() == "" {
write!(
f,
"笔({}, {}, {}, {}, 周期: {}, 数量: {})",
self.,
self..load(Ordering::Relaxed),
self.(),
self.,
self.,
self..read().unwrap(),
self...,
self... - self... + 1
self..read().unwrap()...load(Ordering::Relaxed)
- self....load(Ordering::Relaxed)
+ 1
)
} else {
let = crate::algorithm::segment::线::(self);
@@ -899,20 +1259,20 @@ impl std::fmt::Display for 虚线 {
Some(g) => format!("{}", g),
None => "None".to_string(),
};
let K线_str = match &self.K线 {
let K线_str = match &*self.K线.read().unwrap() {
Some(k) => format!("{}", k),
None => "None".to_string(),
};
write!(
f,
"{}<{}, {}, {}, {}, {}, 数量: {}, 缺口: {}, {}>",
self.,
self.,
self..read().unwrap(),
self..load(Ordering::Relaxed),
,
self.(),
self.,
self.,
self..len(),
self..read().unwrap(),
self..read().unwrap().len(),
_str,
K线_str,
)
+5 -5
View File
@@ -24,20 +24,20 @@
use crate::structure::segment_feat::线;
use crate::types::;
use std::rc::Rc;
use std::sync::Arc;
/// 特征分型 — 由三个线段特征元素构成的分型
#[derive(Debug, Clone)]
pub struct {
pub : Rc<线>,
pub : Rc<线>,
pub : Rc<线>,
pub : Arc<线>,
pub : Arc<线>,
pub : Arc<线>,
pub : ,
}
impl {
pub fn new(
: Rc<线>, : Rc<线>, : Rc<线>, :
: Arc<线>, : Arc<线>, : Arc<线>, :
) -> Self {
Self {
, , ,
+42 -28
View File
@@ -25,14 +25,15 @@
use crate::kline::chan_kline::K线;
use crate::types::;
use crate::types::;
use std::rc::Rc;
use std::sync::atomic::Ordering;
use std::sync::Arc;
/// 分型 — 由三根缠K构成(可能缺左或右)
#[derive(Debug, Clone)]
pub struct {
pub : Option<Rc<K线>>,
pub : Rc<K线>,
pub : Option<Rc<K线>>,
pub : Option<Arc<K线>>,
pub : Arc<K线>,
pub : Option<Arc<K线>>,
pub : ,
pub : i64,
pub : f64,
@@ -40,11 +41,11 @@ pub struct 分型 {
impl {
pub fn new(
: Option<Rc<K线>>, : Rc<K线>, : Option<Rc<K线>>
: Option<Arc<K线>>, : Arc<K线>, : Option<Arc<K线>>
) -> Self {
let = ..unwrap_or(::);
let = .;
let = .;
let = ..read().unwrap().unwrap_or(::);
let = ..load(Ordering::Relaxed);
let = ..get();
Self {
,
,
@@ -60,9 +61,9 @@ impl 分型 {
let = self..as_ref()?;
let = self..as_ref()?;
Some((
::(., ., self.., self..),
::(self.., self.., ., .),
::(., ., ., .),
::(..get(), ..get(), self...get(), self...get()),
::(self...get(), self...get(), ..get(), ..get()),
::(..get(), ..get(), ..get(), ..get()),
))
}
@@ -97,17 +98,19 @@ impl 分型 {
if let (Some(ref ), Some(ref )) = (&self., &self.) {
if self. == :: {
if .K线. > .K线. {
if .K线.read().unwrap(). > .K线.read().unwrap(). {
return "";
} else if .K线. > self..K线. {
} else if .K线.read().unwrap(). > self..K线.read().unwrap().
{
return "";
} else {
return "";
}
} else if self. == :: {
if .K线. < .K线. {
if .K线.read().unwrap(). < .K线.read().unwrap(). {
return "";
} else if .K线. < self..K线. {
} else if .K线.read().unwrap(). < self..K线.read().unwrap().
{
return "";
} else {
return "";
@@ -121,15 +124,21 @@ impl 分型 {
pub fn MACD柱子分型匹配(&self) -> bool {
if let (Some(ref ), Some(ref )) = (&self., &self.) {
if self. == :: {
let _k = .K线.read().unwrap();
let _k = self..K线.read().unwrap();
let _k = .K线.read().unwrap();
if let (Some(ref macd), Some(ref macd), Some(ref macd)) =
(&.K线.macd, &self..K线.macd, &.K线.macd)
(&_k.macd, &_k.macd, &_k.macd)
{
return macd.MACD柱 > macd.MACD柱 && macd.MACD柱 < macd.MACD柱;
}
}
if self. == :: {
let _k = .K线.read().unwrap();
let _k = self..K线.read().unwrap();
let _k = .K线.read().unwrap();
if let (Some(ref macd), Some(ref macd), Some(ref macd)) =
(&.K线.macd, &self..K线.macd, &.K线.macd)
(&_k.macd, &_k.macd, &_k.macd)
{
return macd.MACD柱 < macd.MACD柱 && macd.MACD柱 > macd.MACD柱;
}
@@ -139,35 +148,36 @@ impl 分型 {
}
/// 判断两个分型是否匹配
pub fn (: &Rc<>, : &Rc<>, : &str) -> bool {
pub fn (: &Arc<>, : &Arc<>, : &str) -> bool {
match {
"" => Rc::as_ptr() == Rc::as_ptr(),
"" => Arc::as_ptr() == Arc::as_ptr(),
_ => false,
}
}
/// 从缠K序列中获取以指定缠K为中元素的分型
pub fn K序列中获取分型(
K线序列: &[Rc<K线>], : &Rc<K线>
K线序列: &[Arc<K线>],
: &Arc<K线>,
) -> Option<Self> {
let idx = K线序列
.iter()
.position(|k| Rc::as_ptr(k) == Rc::as_ptr())?;
.position(|k| Arc::as_ptr(k) == Arc::as_ptr())?;
let = if idx > 0 {
Some(Rc::clone(&K线序列[idx - 1]))
Some(Arc::clone(&K线序列[idx - 1]))
} else {
None
};
let = if idx + 1 < K线序列.len() {
Some(Rc::clone(&K线序列[idx + 1]))
Some(Arc::clone(&K线序列[idx + 1]))
} else {
None
};
Some(Self::new(, Rc::clone(), ))
Some(Self::new(, Arc::clone(), ))
}
/// 向分型序列中添加新分型
pub fn (: &mut Vec<Rc<>>, : Rc<>) {
pub fn (: &mut Vec<Arc<>>, : Arc<>) {
if .is_empty() {
if . != :: && . != ::
{
@@ -188,10 +198,10 @@ impl 分型 {
impl crate::types::fractal:: for {
fn (&self) -> f64 {
self..
self...get()
}
fn (&self) -> f64 {
self..
self...get()
}
}
@@ -200,7 +210,11 @@ impl std::fmt::Display for 分型 {
write!(
f,
"{}<{}, {}, None: {}, None: {}>",
self...unwrap_or(crate::types::::),
self.
.
.read()
.unwrap()
.unwrap_or(crate::types::::),
self.,
crate::utils::format_f64_g(self.),
if self..is_none() { "True" } else { "False" },
+335 -40
View File
@@ -26,7 +26,8 @@ use crate::structure::dash_line::虚线;
use crate::structure::feat_fractal::;
use crate::structure::fractal_obj::;
use crate::types::{, };
use std::rc::Rc;
use std::sync::atomic::Ordering;
use std::sync::Arc;
/// 线段特征 — 特征序列元素(内部是虚线的集合)
#[derive(Debug, Clone)]
@@ -34,11 +35,11 @@ pub struct 线段特征 {
pub : i64,
pub : String,
pub 线: ,
pub : Vec<Rc<线>>,
pub : Vec<Arc<线>>,
}
impl 线 {
pub fn new(: String, : Vec<Rc<线>>, 线: ) -> Self {
pub fn new(: String, : Vec<Arc<线>>, 线: ) -> Self {
Self {
: 0,
,
@@ -53,7 +54,7 @@ impl 线段特征 {
/// 文 — 取特征序列元素中分型特征值最大/最小的文分型
/// tiebreaker: later时间戳 wins when特征值 equal (matches Python)
pub fn (&self) -> Rc<> {
pub fn (&self) -> Arc<> {
if self.线.() {
self.
.iter()
@@ -64,8 +65,8 @@ impl 线段特征 {
.unwrap_or(std::cmp::Ordering::Equal)
.then_with(|| a...cmp(&b..))
})
.map(|x| Rc::clone(&x.))
.unwrap_or_else(|| Rc::clone(&self.[0].))
.map(|x| Arc::clone(&x.))
.unwrap_or_else(|| Arc::clone(&self.[0].))
} else {
self.
.iter()
@@ -76,38 +77,54 @@ impl 线段特征 {
.unwrap_or(std::cmp::Ordering::Equal)
.then_with(|| b...cmp(&a..))
})
.map(|x| Rc::clone(&x.))
.unwrap_or_else(|| Rc::clone(&self.[0].))
.map(|x| Arc::clone(&x.))
.unwrap_or_else(|| Arc::clone(&self.[0].))
}
}
/// 武 — 取特征序列元素中分型特征值最大/最小的武分型
/// tiebreaker: later时间戳 wins when特征值 equal (matches Python)
pub fn (&self) -> Rc<> {
pub fn (&self) -> Arc<> {
if self.线.() {
self.
.iter()
.max_by(|a, b| {
a.
.read()
.unwrap()
.
.partial_cmp(&b..)
.partial_cmp(&b..read().unwrap().)
.unwrap_or(std::cmp::Ordering::Equal)
.then_with(|| a...cmp(&b..))
.then_with(|| {
a.
.read()
.unwrap()
.
.cmp(&b..read().unwrap().)
})
})
.map(|x| Rc::clone(&x.))
.unwrap_or_else(|| Rc::clone(&self.[0].))
.map(|x| x..read().unwrap().clone())
.unwrap_or_else(|| self.[0]..read().unwrap().clone())
} else {
self.
.iter()
.min_by(|a, b| {
a.
.read()
.unwrap()
.
.partial_cmp(&b..)
.partial_cmp(&b..read().unwrap().)
.unwrap_or(std::cmp::Ordering::Equal)
.then_with(|| b...cmp(&a..))
.then_with(|| {
b.
.read()
.unwrap()
.
.cmp(&a..read().unwrap().)
})
})
.map(|x| Rc::clone(&x.))
.unwrap_or_else(|| Rc::clone(&self.[0].))
.map(|x| x..read().unwrap().clone())
.unwrap_or_else(|| self.[0]..read().unwrap().clone())
}
}
@@ -129,7 +146,7 @@ impl 线段特征 {
}
/// 向特征序列元素中添加虚线
pub fn (&mut self, 线: Rc<线>) -> Result<(), String> {
pub fn (&mut self, 线: Arc<线>) -> Result<(), String> {
if 线.() == self.线 {
return Err("添加方向与线段方向相同".into());
}
@@ -138,14 +155,14 @@ impl 线段特征 {
}
/// 从特征序列元素中删除虚线
pub fn (&mut self, 线: &Rc<线>) -> Result<(), String> {
pub fn (&mut self, 线: &Arc<线>) -> Result<(), String> {
if 线.() == self.() {
return Err("删除方向与特征序列方向相同".into());
}
if let Some(pos) = self
.
.iter()
.position(|x| Rc::as_ptr(x) == Rc::as_ptr(线))
.position(|x| Arc::as_ptr(x) == Arc::as_ptr(线))
{
self..remove(pos);
Ok(())
@@ -155,19 +172,19 @@ impl 线段特征 {
}
/// 新建特征序列元素
pub fn (线: Vec<Rc<线>>, 线: ) -> Self {
pub fn (线: Vec<Arc<线>>, 线: ) -> Self {
let = format!("特征<虚线>");
Self::new(, 线, 线)
}
/// 静态分析 — 从虚线序列生成特征序列元素列表
pub fn (
线: &[Rc<线>],
线: &[Arc<线>],
线: ,
: &str,
: bool,
) -> Vec<Rc<线>> {
let mut : Vec<Rc<线>> = Vec::new();
) -> Vec<Arc<线>> {
let mut : Vec<Arc<线>> = Vec::new();
// 需要被合并的方向集合
let : Vec<> = match {
@@ -179,9 +196,9 @@ impl 线段特征 {
// 情况1:方向相同(可能触发分型替换)
if 线.() == 线 {
if .len() >= 3 {
let = Rc::clone(&[.len() - 3]);
let = Rc::clone(&[.len() - 2]);
let = Rc::clone(&[.len() - 1]);
let = Arc::clone(&[.len() - 3]);
let = Arc::clone(&[.len() - 2]);
let = Arc::clone(&[.len() - 1]);
if let Some() = ::(&*, &*, &*, true, true) {
let = (线 == ::
@@ -192,16 +209,24 @@ impl 线段特征 {
&& 线.() < .());
if {
let 线 = ..iter().min_by_key(|o| o.).unwrap();
let 线 = ..iter().max_by_key(|o| o.).unwrap();
let 线 =
.
.iter()
.min_by_key(|o| o..load(Ordering::Relaxed))
.unwrap();
let 线 =
.
.iter()
.max_by_key(|o| o..load(Ordering::Relaxed))
.unwrap();
let fake = 线::(
Rc::clone(&线.),
Rc::clone(&线.),
Arc::clone(&线.),
线..read().unwrap().clone(),
false,
);
.pop();
let idx = .len() - 1;
[idx] = Rc::new(Self::(vec![Rc::new(fake)], 线));
[idx] = Arc::new(Self::(vec![Arc::new(fake)], 线));
}
}
}
@@ -210,7 +235,7 @@ impl 线段特征 {
// 情况2:方向不同(执行特征序列的合并/添加)
if .is_empty() {
.push(Rc::new(Self::(vec![Rc::clone(线)], 线)));
.push(Arc::new(Self::(vec![Arc::clone(线)], 线)));
continue;
}
@@ -225,10 +250,10 @@ impl 线段特征 {
)) {
// Clone-modify-replace
let mut = (*[_idx]).clone();
let _ = .(Rc::clone(线));
[_idx] = Rc::new();
let _ = .(Arc::clone(线));
[_idx] = Arc::new();
} else {
.push(Rc::new(Self::(vec![Rc::clone(线)], 线)));
.push(Arc::new(Self::(vec![Arc::clone(线)], 线)));
}
}
@@ -236,15 +261,15 @@ impl 线段特征 {
}
/// 获取分型序列
pub fn (: &[Rc<线>]) -> Vec<> {
pub fn (: &[Arc<线>]) -> Vec<> {
let mut = Vec::new();
if .len() < 3 {
return ;
}
for i in 2...len() {
let = Rc::clone(&[i - 2]);
let = Rc::clone(&[i - 1]);
let = Rc::clone(&[i]);
let = Arc::clone(&[i - 2]);
let = Arc::clone(&[i - 1]);
let = Arc::clone(&[i]);
let = ::_对象(
&* as &dyn crate::types::fractal::,
@@ -285,3 +310,273 @@ impl std::fmt::Display for 线段特征 {
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::kline::bar::K线;
use crate::kline::chan_kline::K线;
use crate::structure::fractal_obj::;
use crate::types::;
fn _创建K线(: i64, : f64, : f64, : f64, : f64) -> K线 {
let mut k = K线::default();
k. = ;
k. = ;
k. = ;
k. = ;
k. = ;
k
}
fn _创建缠K(
: i64,
: f64,
: f64,
: ,
: Option<>,
: i64,
) -> Arc<K线> {
let K = Arc::new(_创建K线(, , , , ));
Arc::new(K线::K(
, , , , , , K, None,
))
}
fn _创建顶分型(: i64, : f64, : f64, : i64) -> Arc<> {
let = _创建缠K(
- 2,
- 2.0,
- 2.0,
::,
Some(::),
- 2,
);
let = _创建缠K(, , , ::, Some(::), );
let = _创建缠K(
+ 2,
- 1.0,
- 1.0,
::,
Some(::),
+ 2,
);
Arc::new(::new(Some(), , Some()))
}
fn _创建底分型(: i64, : f64, : f64, : i64) -> Arc<> {
let = _创建缠K(
- 2,
+ 2.0,
+ 2.0,
::,
Some(::),
- 2,
);
let = K线::K(
,
,
,
::,
Some(::),
,
Arc::new(_创建K线(, , , , )),
None,
);
..set();
let = Arc::new();
let = _创建缠K(
+ 2,
+ 1.0,
+ 1.0,
::,
Some(::),
+ 2,
);
Arc::new(::new(Some(), , Some()))
}
fn _创建笔(
: i64,
: f64,
: f64,
: i64,
: f64,
: f64,
) -> Arc<线> {
let = _创建顶分型(, , , 1);
let = _创建底分型(, , , 2);
Arc::new(线::(, , true))
}
// ============================================================
// 文 — 取特征值最大/最小的分型
// 特征序列元素方向与线段方向相反:
// 向上线段 → 元素为向下笔(顶→底) → 文=顶分型 → 取max
// 向下线段 → 元素为向上笔(底→顶) → 文=底分型 → 取min
// ============================================================
#[test]
fn test_文_向上线段取最大特征值分型() {
// 向上线段,元素用向下笔(顶→底),文=顶分型
// 笔1: 顶(特征值=100)→底(80), 文=顶(100)
let 1 = _创建笔(100, 100.0, 90.0, 200, 90.0, 80.0);
// 笔2: 顶(特征值=110)→底(90), 文=顶(110)
let 2 = _创建笔(200, 110.0, 100.0, 300, 90.0, 80.0);
let feat = 线::new(
"测试".into(),
vec![Arc::clone(&1), Arc::clone(&2)],
::,
);
// 向上取max → 笔2.文=110
let = feat.();
assert!((. - 110.0).abs() < 0.01);
}
#[test]
fn test_文_向下线段取最小特征值分型() {
// 向下线段,元素用向上笔(底→顶),文=底分型
// 笔1: 底(特征值=80)→顶(100), 文=底(80)
let 1 = _创建底分型(100, 90.0, 80.0, 5);
let 1 = _创建顶分型(200, 100.0, 90.0, 10);
let 1 = Arc::new(线::(1, 1, true));
// 笔2: 底(特征值=70)→顶(95), 文=底(70)
let 2 = _创建底分型(200, 80.0, 70.0, 15);
let 2 = _创建顶分型(300, 95.0, 85.0, 20);
let 2 = Arc::new(线::(2, 2, true));
let feat = 线::new(
"测试".into(),
vec![Arc::clone(&1), Arc::clone(&2)],
::,
);
// 向下取min → 笔2.文=70
let = feat.();
assert!((. - 70.0).abs() < 0.01);
}
// ============================================================
// 武 — 取特征值最大/最小的分型
// 向上线段 → 元素为向下笔 → 武=底分型 → 取max
// 向下线段 → 元素为向上笔 → 武=顶分型 → 取min
// ============================================================
#[test]
fn test_武_向上线段取最大特征值分型() {
// 向上线段,元素用向下笔(顶→底),武=底分型
// 笔1: 顶(100)→底(特征值=80), 武=底(80)
let 1 = _创建笔(100, 100.0, 90.0, 200, 90.0, 80.0);
// 笔2: 顶(110)→底(特征值=90), 武=底(90)
let 2 = _创建笔(200, 110.0, 100.0, 300, 100.0, 90.0);
let feat = 线::new(
"测试".into(),
vec![Arc::clone(&1), Arc::clone(&2)],
::,
);
// 向上取max → 笔2.武=90
let = feat.();
assert!((. - 90.0).abs() < 0.01);
}
#[test]
fn test_武_向下线段取最小特征值分型() {
// 向下线段,元素用向上笔(底→顶),武=顶分型
// 笔1: 底(80)→顶(特征值=100), 武=顶(100)
let 1 = _创建底分型(100, 90.0, 80.0, 5);
let 1 = _创建顶分型(200, 100.0, 90.0, 10);
let 1 = Arc::new(线::(1, 1, true));
// 笔2: 底(60)→顶(特征值=85), 武=顶(85)
let 2 = _创建底分型(200, 70.0, 60.0, 15);
let 2 = _创建顶分型(300, 85.0, 75.0, 20);
let 2 = Arc::new(线::(2, 2, true));
let feat = 线::new(
"测试".into(),
vec![Arc::clone(&1), Arc::clone(&2)],
::,
);
// 向下取min → 笔2.武=85
let = feat.();
assert!((. - 85.0).abs() < 0.01);
}
// ============================================================
// 文/武 tiebreaker — 同特征值取后时间戳
// ============================================================
#[test]
fn test_文_同特征值取后时间戳() {
// 两个笔的文特征值相同=100,但时间戳不同
let 1 = _创建顶分型(100, 100.0, 90.0, 5);
let 1 = _创建底分型(200, 90.0, 80.0, 10);
let 1 = Arc::new(线::(1, 1, true));
let 2 = _创建顶分型(300, 100.0, 90.0, 15); // 同特征值,后时间戳
let 2 = _创建底分型(400, 80.0, 70.0, 20);
let 2 = Arc::new(线::(2, 2, true));
let feat = 线::new("测试".into(), vec![1, 2], ::);
let = feat.();
// 向上取最大特征值:都是100 → tiebreaker取后时间戳 → 笔2.文(300)
assert_eq!(., 300);
}
#[test]
fn test_武_同特征值取后时间戳_向上() {
let 1 = _创建顶分型(100, 100.0, 90.0, 5);
let 1 = _创建底分型(200, 80.0, 70.0, 10); // 特征值80
let 1 = Arc::new(线::(1, 1, true));
let 2 = _创建顶分型(300, 80.0, 70.0, 15); // 特征值80
let 2 = _创建底分型(400, 80.0, 70.0, 20); // 特征值80
let 2 = Arc::new(线::(2, 2, true));
let feat = 线::new("测试".into(), vec![1, 2], ::);
let = feat.();
// 向上取最大特征值:都是80 → tiebreaker取后时间戳 → 笔2.武(400)
assert_eq!(., 400);
}
// ============================================================
// 添加/删除 操作
// ============================================================
#[test]
fn test_添加方向与线段方向相反的虚线可成功() {
// 向下笔(顶→底,方向=向下) 添加到 向上线段(方向=向上) → 方向不同, 可添加
let 1 = _创建笔(100, 100.0, 90.0, 200, 90.0, 80.0);
let mut feat = 线::new("测试".into(), vec![], ::);
let result = feat.(Arc::clone(&1));
assert!(result.is_ok());
}
#[test]
fn test_添加方向与线段方向相同的虚线应报错() {
// 向下笔(顶→底,方向=向下) 添加到 向下线段(方向=向下) → 方向相同, 应报错
let 1 = _创建笔(100, 100.0, 90.0, 200, 90.0, 80.0);
let mut feat = 线::new("测试".into(), vec![], ::);
let result = feat.(Arc::clone(&1));
assert!(result.is_err());
}
#[test]
fn test_空线段特征文返回第一个元素的文() {
let 1 = _创建笔(100, 100.0, 90.0, 200, 90.0, 80.0);
let feat = 线::new("测试".into(), vec![Arc::clone(&1)], ::);
let = feat.();
assert_eq!(Arc::as_ptr(&), Arc::as_ptr(&1.));
}
}