mod key;
pub use key::KEY;
mod fq;
pub use fq::*;
use crate::{bytes_helper::*, Result};
use std::collections::HashMap;
pub type StockGbbq<'a> = HashMap<u32, Vec<Gbbq<'a>>>;
#[derive(Debug, Clone, serde::Serialize)]
pub struct Gbbq<'a> {
pub market: u8,
pub code: &'a str,
#[serde(serialize_with = "ser_date_string")]
pub date: u32,
pub category: u8,
pub fh_qltp: f32,
pub pgj_qzgb: f32,
pub sg_hltp: f32,
pub pg_hzgb: f32,
}
impl<'a> Gbbq<'a> {
#[inline]
pub fn from_chunk(chunk: &'a [u8]) -> Gbbq<'a> {
Self {
market: u8_from_le_bytes(chunk, 0),
code: std::str::from_utf8(&chunk[1..7]).unwrap(),
date: u32_from_le_bytes(chunk, 8),
category: u8_from_le_bytes(chunk, 12),
fh_qltp: f32_from_le_bytes(chunk, 13),
pgj_qzgb: f32_from_le_bytes(chunk, 17),
sg_hltp: f32_from_le_bytes(chunk, 21),
pg_hzgb: f32_from_le_bytes(chunk, 25),
}
}
pub fn iter(bytes: &mut [u8]) -> impl Iterator<Item = Gbbq<'_>> {
bytes.chunks_exact_mut(29).map(parse).map(Gbbq::from_chunk)
}
pub fn iter_deciphered(bytes: &'a [u8]) -> impl Iterator<Item = Gbbq<'a>> {
bytes.chunks_exact(29).map(Self::from_chunk)
}
#[inline]
pub fn compute_pre_pct(&self, close: f32, mut preclose: f64, flag: bool) -> [f64; 3] {
if flag {
preclose = (preclose * 10. - self.fh_qltp as f64
+ self.pg_hzgb as f64 * self.pgj_qzgb as f64)
/ (10. + self.pg_hzgb as f64 + self.sg_hltp as f64)
}
let close = close as f64;
[preclose, close, close / preclose]
}
pub fn filter_hashmap(gbbq: impl Iterator<Item = Self>) -> StockGbbq<'a> {
let mut code = 0;
let mut vec = Vec::with_capacity(128); let mut hm = HashMap::with_capacity(5000); gbbq.filter(|g| {
g.code
.chars()
.take(1)
.map(|c| c == '6' || c == '0' || c == '3') .next()
.unwrap_or(false)
&& g.category == 1 })
.map(|g| {
let c = g.code.parse().unwrap();
if c != code {
hm.insert(code, vec.clone()); code = c;
vec.clear();
vec.push(g);
} else {
vec.push(g);
}
})
.last();
hm.insert(code, vec); hm.remove(&0);
hm
}
}
pub struct Gbbqs {
data: Vec<u8>,
pub count: usize,
pub parsed: bool,
}
impl Gbbqs {
pub fn from_file(p: impl AsRef<std::path::Path>) -> Result<Self> {
let vec = std::fs::read(p)?;
let count = u32_from_le_bytes(&vec[..4], 0) as usize;
Ok(Self {
data: vec,
count,
parsed: false,
})
}
pub fn to_vec(&mut self) -> Vec<Gbbq<'_>> {
if self.parsed {
self.data[4..]
.chunks_exact(29)
.map(Gbbq::from_chunk)
.collect()
} else {
let res = self.data[4..]
.chunks_exact_mut(29)
.map(parse)
.map(Gbbq::from_chunk)
.collect();
self.parsed = true;
res
}
}
pub fn get_data(&self) -> &[u8] {
&self.data[4..]
}
pub fn get_data_mut(&mut self) -> &mut [u8] {
&mut self.data[4..]
}
}
pub fn parse(encrypt: &mut [u8]) -> &[u8] {
let mut pos = 0usize;
for i in (0usize..24).step_by(8) {
let mut eax = u32_from_le_bytes(KEY, 0x44);
let mut ebx = u32_from_le_bytes(encrypt, pos);
let mut num = eax ^ ebx;
let mut numold = u32_from_le_bytes(encrypt, pos + 4);
for j in (4usize..68).step_by(4).rev() {
ebx = (num & 0xff0000) >> 16;
eax = u32_from_le_bytes(KEY, ebx as usize * 4 + 0x448);
ebx = num >> 24;
let mut eax_add = u32_from_le_bytes(KEY, ebx as usize * 4 + 0x48);
eax = eax.overflowing_add(eax_add).0;
ebx = (num & 0xff00) >> 8;
let mut eax_xor = u32_from_le_bytes(KEY, ebx as usize * 4 + 0x848);
eax ^= eax_xor;
ebx = num & 0xff;
eax_add = u32_from_le_bytes(KEY, ebx as usize * 4 + 0xc48);
eax = eax.overflowing_add(eax_add).0;
eax_xor = u32_from_le_bytes(KEY, j);
eax ^= eax_xor;
ebx = num;
num = numold ^ eax;
numold = ebx;
}
numold ^= u32_from_le_bytes(KEY, 0);
encrypt[i..i + 4].swap_with_slice(&mut numold.to_le_bytes());
encrypt[i + 4..i + 8].swap_with_slice(&mut num.to_le_bytes());
pos += 8;
}
encrypt
}