namerena-rs/miner/src/name.rs

812 lines
31 KiB
Rust
Raw Normal View History

2024-03-02 15:48:44 +08:00
use std::cmp::min;
2024-03-02 12:06:59 +08:00
#[cfg(feature = "simd")]
2024-05-15 00:16:15 +08:00
// 考虑到 avx512 的普及性
// 咱还是用 u8x32 吧
use std::simd::u8x32;
2024-03-01 21:57:29 +08:00
2024-02-28 21:49:09 +08:00
use tracing::warn;
2024-03-03 17:12:29 +08:00
#[inline(always)]
2024-02-28 22:22:47 +08:00
pub fn median<T>(x: T, y: T, z: T) -> T
where
T: std::cmp::Ord + std::marker::Copy,
{
2024-03-02 01:14:24 +08:00
// std::max(std::min(x, y), std::min(std::max(x, y), z))
2024-05-04 00:27:17 +08:00
// x.min(y).max(x.max(y).min(z))
2024-05-04 01:06:29 +08:00
if x < y {
if y < z {
2024-05-04 00:27:17 +08:00
y
2024-05-04 01:06:29 +08:00
} else if x < z {
2024-05-04 00:27:17 +08:00
z
} else {
x
}
2024-05-04 01:06:29 +08:00
} else if x < z {
2024-05-04 00:27:17 +08:00
x
2024-05-04 01:06:29 +08:00
} else if y < z {
2024-05-04 00:27:17 +08:00
z
} else {
y
}
2024-02-28 19:04:57 +08:00
}
2024-02-29 19:49:49 +08:00
#[derive(Debug, Clone)]
pub struct TeamNamer {
pub team: String,
pub val: [u8; 256],
}
impl TeamNamer {
/// 方便使用的 new
/// 会检查长度是否超过 256
#[inline(always)]
pub fn new(team: &str) -> Option<Self> {
if team.len() > 256 {
warn!("Team too long({}): {}", team.len(), team);
return None;
}
Some(Self::new_unchecked(team))
}
#[inline(always)]
pub fn new_unchecked(team: &str) -> Self {
let team_bytes = team.as_bytes();
let mut val: [u8; 256] = (0..=255).collect::<Vec<u8>>().try_into().unwrap();
let mut s = 0_u8;
let t_len = team.len() + 1;
for i in 0..256 {
if (i % t_len) != 0 {
s = s.wrapping_add(team_bytes[(i % t_len) - 1]);
}
s = s.wrapping_add(val[i]);
val.swap(i, s as usize);
}
Self {
team: team.to_string(),
val,
}
}
#[inline(always)]
2024-04-28 20:34:39 +08:00
pub fn clone_vals(&self) -> [u8; 256] { self.val }
2024-02-29 19:49:49 +08:00
}
2024-05-25 00:19:59 +08:00
#[repr(C)]
2024-02-28 21:49:09 +08:00
#[derive(Debug, Clone)]
pub struct Namer {
2024-02-28 22:22:47 +08:00
pub name: String,
pub team: String,
pub val: [u8; 256],
pub name_base: [u8; 128],
pub name_prop: [u32; 8],
pub skl_id: [u8; 40],
pub skl_freq: [u8; 40],
2024-02-28 19:04:57 +08:00
}
2024-02-28 19:18:30 +08:00
2024-04-28 20:34:39 +08:00
#[allow(dead_code)]
2024-02-28 21:49:09 +08:00
impl Namer {
2024-02-29 19:49:49 +08:00
/// 最完整的、最简单的 new
/// 可以直接丢一个 name 进来
2024-02-29 01:59:03 +08:00
#[inline(always)]
2024-02-29 19:49:49 +08:00
pub fn new(full_name: &String) -> Option<Self> {
// name@team
// name
2024-03-31 00:23:27 +08:00
let (name, team) = full_name.split_once('@').unwrap_or((full_name, full_name));
2024-02-29 19:49:49 +08:00
if name.len() > 256 {
warn!("Name too long({}): {}", name.len(), name);
return None;
}
if team.len() > 256 {
warn!("Team too long({}): {}", team.len(), team);
return None;
}
Some(Self::new_raw_unchecked(name, team))
}
/// 用起来也很方便的
/// 只不过是需要分别输入, 也挺好用的
/// 包括了长度检测
#[inline(always)]
pub fn new_raw(name: &str, team: &str) -> Option<Self> {
if name.len() > 256 {
warn!("Name too long({}): {}", name.len(), name);
return None;
2024-02-28 22:22:47 +08:00
}
2024-02-29 19:49:49 +08:00
if team.len() > 256 {
warn!("Team too long({}): {}", team.len(), team);
return None;
}
Some(Self::new_raw_unchecked(name, team))
}
/// 不带检查长度的 new
/// 依然可以传一个完整的进来
#[inline(always)]
pub fn new_unchecked(full_name: &str) -> Self {
2024-03-31 00:23:27 +08:00
let (name, team) = full_name.split_once('@').unwrap_or((full_name, full_name));
2024-02-29 19:49:49 +08:00
Self::new_raw_unchecked(name, team)
}
/// 大部分情况下的实际调用 p1
/// p2 是 new_from_team_namer_unchecked
/// 实际上还是个包装
#[inline(always)]
pub fn new_raw_unchecked(name: &str, team: &str) -> Self {
let team_namer = TeamNamer::new_unchecked(team);
Self::new_from_team_namer_unchecked(&team_namer, name)
}
/// 带检查长度的 from namer
/// 我其实也不知道为啥要有他, 就带上了吧
#[inline(always)]
pub fn new_from_team_namer(team_namer: &TeamNamer, name: &str) -> Option<Self> {
if name.len() > 256 {
warn!("Name too long({}): {}", name.len(), name);
return None;
}
Some(Self::new_from_team_namer_unchecked(team_namer, name))
}
/// 实际 new 实现
#[inline(always)]
pub fn new_from_team_namer_unchecked(team_namer: &TeamNamer, name: &str) -> Self {
let mut val: [u8; 256] = team_namer.clone_vals();
2024-02-28 22:22:47 +08:00
let mut name_base = [0_u8; 128];
let mut name_prop = [0_u32; 8];
2024-02-28 23:33:59 +08:00
let skl_id = [0_u8; 40];
let skl_freq = [0_u8; 40];
2024-02-28 19:18:30 +08:00
2024-02-28 22:22:47 +08:00
let name_bytes = name.as_bytes();
2024-02-29 19:49:49 +08:00
let name_len = name_bytes.len();
for _ in 0..2 {
2024-04-25 23:07:44 +08:00
unsafe {
2024-05-03 23:31:43 +08:00
let mut s = 0_u8;
2024-04-25 23:07:44 +08:00
let mut k = 0;
for i in 0..256 {
2024-04-25 23:17:58 +08:00
s = s.wrapping_add(if k == 0 { 0 } else { *name_bytes.get_unchecked(k - 1) });
2024-04-28 21:25:58 +08:00
s = s.wrapping_add(*val.get_unchecked(i));
2024-04-25 23:07:44 +08:00
val.swap_unchecked(i, s as usize);
2024-05-04 00:27:17 +08:00
k = if k == name_len { 0 } else { k + 1 };
2024-04-25 23:07:44 +08:00
}
2024-02-29 19:49:49 +08:00
}
2024-02-28 22:22:47 +08:00
}
2024-03-02 00:08:56 +08:00
// simd 优化
#[cfg(feature = "simd")]
{
2024-04-28 20:34:39 +08:00
let mut simd_val = val;
2024-03-02 12:06:59 +08:00
let mut simd_val_b = [0_u8; 256];
2024-05-15 00:16:15 +08:00
let simd_181 = u8x32::splat(181);
let simd_160 = u8x32::splat(160);
let simd_63 = u8x32::splat(63);
2024-03-02 15:48:44 +08:00
2024-05-15 00:16:15 +08:00
for i in (0..256).step_by(32) {
2024-03-02 12:06:59 +08:00
// 一次性加载64个数字
2024-05-15 00:16:15 +08:00
let mut x = u8x32::from_slice(unsafe { simd_val.get_unchecked(i..) });
2024-03-03 17:13:44 +08:00
x = x * simd_181 + simd_160;
2024-03-02 12:06:59 +08:00
// 写入到 simd_val
2024-04-25 22:54:25 +08:00
unsafe {
x.copy_to_slice(simd_val.get_unchecked_mut(i..));
}
2024-03-03 17:12:29 +08:00
let y = x & simd_63;
2024-04-25 22:54:25 +08:00
unsafe {
y.copy_to_slice(simd_val_b.get_unchecked_mut(i..));
}
2024-03-02 00:08:56 +08:00
}
let mut mod_count = 0;
for i in 0..96 {
2024-04-25 22:54:25 +08:00
unsafe {
if simd_val.get_unchecked(i) > &88 && simd_val.get_unchecked(i) < &217 {
2024-04-25 23:17:58 +08:00
*name_base.get_unchecked_mut(mod_count as usize) = *simd_val_b.get_unchecked(i);
2024-04-25 22:54:25 +08:00
mod_count += 1;
}
2024-03-02 00:08:56 +08:00
}
2024-03-02 13:29:31 +08:00
if mod_count > 30 {
2024-03-02 00:08:56 +08:00
break;
}
}
2024-03-02 00:50:45 +08:00
if mod_count < 31 {
2024-03-02 00:08:56 +08:00
for i in 96..256 {
2024-04-25 23:07:44 +08:00
unsafe {
if simd_val.get_unchecked(i) > &88 && simd_val.get_unchecked(i) < &217 {
2024-04-25 23:17:58 +08:00
*name_base.get_unchecked_mut(mod_count as usize) = *simd_val_b.get_unchecked(i);
2024-04-25 23:07:44 +08:00
mod_count += 1;
}
2024-03-02 00:08:56 +08:00
}
2024-03-02 13:29:31 +08:00
if mod_count > 30 {
2024-03-02 00:08:56 +08:00
break;
}
}
}
}
#[cfg(not(feature = "simd"))]
{
let mut s = 0;
for i in 0..256 {
let m = ((val[i] as u32 * 181) + 160) % 256;
if m >= 89 && m < 217 {
name_base[s as usize] = (m & 63) as u8;
s += 1;
}
2024-02-28 22:22:47 +08:00
}
}
2024-02-28 19:18:30 +08:00
2024-02-28 23:33:59 +08:00
// 计算 name_prop
2024-04-25 23:07:44 +08:00
// let mut prop_name = name_base[0..32].to_vec();
// prop_name[0..10].sort_unstable();
// name_prop[0] = 154
// + prop_name[3] as u32
// + prop_name[4] as u32
// + prop_name[5] as u32
// + prop_name[6] as u32;
// name_prop[1] = median(prop_name[10], prop_name[11], prop_name[12]) as u32 + 36;
// name_prop[2] = median(prop_name[13], prop_name[14], prop_name[15]) as u32 + 36;
// name_prop[3] = median(prop_name[16], prop_name[17], prop_name[18]) as u32 + 36;
// name_prop[4] = median(prop_name[19], prop_name[20], prop_name[21]) as u32 + 36;
// name_prop[5] = median(prop_name[22], prop_name[23], prop_name[24]) as u32 + 36;
// name_prop[6] = median(prop_name[25], prop_name[26], prop_name[27]) as u32 + 36;
// name_prop[7] = median(prop_name[28], prop_name[29], prop_name[30]) as u32 + 36;
// 疯狂的 unsafe 优化(确信
unsafe {
let mut prop_name = [0_u8; 32];
prop_name.copy_from_slice(name_base.get_unchecked(0..32));
prop_name.get_unchecked_mut(0..10).sort_unstable();
*name_prop.get_unchecked_mut(0) = 154
+ *prop_name.get_unchecked(3) as u32
+ *prop_name.get_unchecked(4) as u32
+ *prop_name.get_unchecked(5) as u32
2024-04-26 21:57:15 +08:00
+ *prop_name.get_unchecked(6) as u32;
2024-04-28 20:34:39 +08:00
2024-04-26 21:57:15 +08:00
*name_prop.get_unchecked_mut(1) = median(
*prop_name.get_unchecked(10),
*prop_name.get_unchecked(11),
*prop_name.get_unchecked(12),
) as u32
+ 36;
*name_prop.get_unchecked_mut(2) = median(
*prop_name.get_unchecked(13),
*prop_name.get_unchecked(14),
*prop_name.get_unchecked(15),
) as u32
+ 36;
*name_prop.get_unchecked_mut(3) = median(
*prop_name.get_unchecked(16),
*prop_name.get_unchecked(17),
*prop_name.get_unchecked(18),
) as u32
+ 36;
*name_prop.get_unchecked_mut(4) = median(
*prop_name.get_unchecked(19),
*prop_name.get_unchecked(20),
*prop_name.get_unchecked(21),
) as u32
+ 36;
*name_prop.get_unchecked_mut(5) = median(
*prop_name.get_unchecked(22),
*prop_name.get_unchecked(23),
*prop_name.get_unchecked(24),
) as u32
+ 36;
*name_prop.get_unchecked_mut(6) = median(
*prop_name.get_unchecked(25),
*prop_name.get_unchecked(26),
*prop_name.get_unchecked(27),
) as u32
+ 36;
*name_prop.get_unchecked_mut(7) = median(
*prop_name.get_unchecked(28),
*prop_name.get_unchecked(29),
*prop_name.get_unchecked(30),
) as u32
+ 36;
2024-04-25 23:07:44 +08:00
}
2024-02-28 19:18:30 +08:00
2024-02-29 01:59:03 +08:00
Self {
2024-02-28 22:22:47 +08:00
name: name.to_string(),
2024-02-29 19:49:49 +08:00
team: team_namer.team.clone(),
2024-02-28 22:22:47 +08:00
val,
name_base,
name_prop,
skl_id,
skl_freq,
2024-02-29 01:59:03 +08:00
}
2024-02-28 22:22:47 +08:00
}
2024-02-28 19:18:30 +08:00
2024-05-03 19:07:08 +08:00
/// 更新当前的名字
#[inline(always)]
2024-05-25 12:16:03 +08:00
pub fn replace_name(&mut self, team_namer: &TeamNamer, name: &str) -> bool {
2024-05-03 19:07:08 +08:00
self.val = team_namer.clone_vals();
self.name = name.to_string();
2024-05-03 22:45:58 +08:00
2024-05-03 19:07:08 +08:00
let name_bytes = name.as_bytes();
let name_len = name_bytes.len();
2024-05-03 22:45:58 +08:00
2024-05-15 00:16:15 +08:00
unsafe {
let val_ptr = self.val.as_mut_ptr();
for _ in 0..2 {
let mut s = 0_u8;
2024-05-25 00:45:17 +08:00
let mut k = 0;
for i in 0..256 {
s = s.wrapping_add(if k == 0 { 0 } else { *name_bytes.get_unchecked(k - 1) });
s = s.wrapping_add(*self.val.get_unchecked(i));
std::ptr::swap(val_ptr.add(i), val_ptr.add(s as usize));
k = if k == name_len { 0 } else { k + 1 };
}
2024-05-03 19:07:08 +08:00
}
}
// simd!
#[cfg(feature = "simd")]
{
let mut simd_val = [0_u8; 256];
let mut simd_val_b = [0_u8; 256];
2024-05-15 00:16:15 +08:00
let simd_181 = u8x32::splat(181);
let simd_160 = u8x32::splat(160);
let simd_63 = u8x32::splat(63);
2024-05-03 19:07:08 +08:00
2024-05-15 00:16:15 +08:00
for i in (0..256).step_by(32) {
2024-05-03 19:07:08 +08:00
unsafe {
2024-05-15 00:16:15 +08:00
let mut x = u8x32::from_slice(self.val.get_unchecked(i..));
2024-05-03 19:07:08 +08:00
x = x * simd_181 + simd_160;
2024-05-15 00:16:15 +08:00
x.copy_to_slice(simd_val.get_unchecked_mut(i..));
2024-05-03 19:07:08 +08:00
let y = x & simd_63;
2024-05-15 00:16:15 +08:00
y.copy_to_slice(simd_val_b.get_unchecked_mut(i..));
2024-05-03 19:07:08 +08:00
}
}
let mut mod_count = 0;
for i in 0..96 {
unsafe {
2024-05-15 00:16:15 +08:00
if *simd_val.get_unchecked(i) > 88 && *simd_val.get_unchecked(i) < 217 {
2024-05-03 19:07:08 +08:00
*self.name_base.get_unchecked_mut(mod_count as usize) = *simd_val_b.get_unchecked(i);
mod_count += 1;
}
}
if mod_count > 30 {
break;
}
}
if mod_count < 31 {
for i in 96..256 {
unsafe {
if simd_val.get_unchecked(i) > &88 && simd_val.get_unchecked(i) < &217 {
*self.name_base.get_unchecked_mut(mod_count as usize) = *simd_val_b.get_unchecked(i);
mod_count += 1;
}
}
if mod_count > 30 {
break;
}
}
}
}
#[cfg(not(feature = "simd"))]
{
let mut s = 0;
for i in 0..256 {
let m = ((self.val[i] as u32 * 181) + 160) % 256;
if m >= 89 && m < 217 {
self.name_base[s as usize] = (m & 63) as u8;
s += 1;
}
}
}
// 计算 name_prop
unsafe {
2024-05-25 12:16:03 +08:00
let mut full = 0;
2024-05-03 19:07:08 +08:00
let mut prop_name = [0_u8; 32];
prop_name.copy_from_slice(self.name_base.get_unchecked(0..32));
2024-05-25 12:16:03 +08:00
// 加一些特殊检测
*self.name_prop.get_unchecked_mut(7) = median(
*prop_name.get_unchecked(28),
*prop_name.get_unchecked(29),
*prop_name.get_unchecked(30),
2024-05-03 19:07:08 +08:00
) as u32
+ 36;
2024-05-25 12:16:03 +08:00
full += self.name_prop.get_unchecked(7) - 36;
if full < 24 {
return false;
}
2024-05-03 19:07:08 +08:00
*self.name_prop.get_unchecked_mut(2) = median(
*prop_name.get_unchecked(13),
*prop_name.get_unchecked(14),
*prop_name.get_unchecked(15),
) as u32
+ 36;
*self.name_prop.get_unchecked_mut(3) = median(
*prop_name.get_unchecked(16),
*prop_name.get_unchecked(17),
*prop_name.get_unchecked(18),
) as u32
+ 36;
2024-05-25 12:16:03 +08:00
*self.name_prop.get_unchecked_mut(6) = median(
*prop_name.get_unchecked(25),
*prop_name.get_unchecked(26),
*prop_name.get_unchecked(27),
) as u32
+ 36;
full += self.name_prop.get_unchecked(2) + self.name_prop.get_unchecked(3) + self.name_prop.get_unchecked(6) - 108;
if full < 165 {
return false;
}
*self.name_prop.get_unchecked_mut(1) = median(
*prop_name.get_unchecked(10),
*prop_name.get_unchecked(11),
*prop_name.get_unchecked(12),
) as u32
+ 36;
2024-05-03 19:07:08 +08:00
*self.name_prop.get_unchecked_mut(4) = median(
*prop_name.get_unchecked(19),
*prop_name.get_unchecked(20),
*prop_name.get_unchecked(21),
) as u32
+ 36;
*self.name_prop.get_unchecked_mut(5) = median(
*prop_name.get_unchecked(22),
*prop_name.get_unchecked(23),
*prop_name.get_unchecked(24),
) as u32
+ 36;
2024-05-25 12:16:03 +08:00
full += self.name_prop.get_unchecked(1) + self.name_prop.get_unchecked(4) + self.name_prop.get_unchecked(5) - 108;
if full < 250 {
return false;
}
prop_name.get_unchecked_mut(0..10).sort_unstable();
*self.name_prop.get_unchecked_mut(0) = 154
+ *prop_name.get_unchecked(3) as u32
+ *prop_name.get_unchecked(4) as u32
+ *prop_name.get_unchecked(5) as u32
+ *prop_name.get_unchecked(6) as u32;
full += self.name_prop.get_unchecked(0) / 3 + 154;
if full < 380 {
println!("name_prop[0] < 380 {}", self.name);
return false;
}
2024-05-03 19:07:08 +08:00
}
2024-05-25 12:16:03 +08:00
true
2024-05-03 19:07:08 +08:00
}
2024-03-02 12:06:59 +08:00
#[inline(always)]
pub fn update_skill(&mut self) {
2024-05-25 00:45:17 +08:00
self.skl_id = [
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39,
];
2024-03-02 15:48:44 +08:00
2024-03-02 12:06:59 +08:00
#[cfg(feature = "simd")]
{
2024-05-25 12:16:03 +08:00
let mut simd_val = [0_u8; 256];
let mut simd_val_b = [0_u8; 256];
2024-05-15 00:16:15 +08:00
let simd_181 = u8x32::splat(181);
2024-05-25 12:16:03 +08:00
let simd_160 = u8x32::splat(160);
2024-05-15 00:16:15 +08:00
let simd_63 = u8x32::splat(63);
2024-03-02 16:49:48 +08:00
2024-05-15 00:16:15 +08:00
for i in (0..256).step_by(32) {
2024-04-25 23:17:58 +08:00
unsafe {
2024-05-25 12:16:03 +08:00
let mut x = u8x32::from_slice(self.val.get_unchecked(i..));
x = x * simd_181 + simd_160;
2024-04-25 23:17:58 +08:00
x.copy_to_slice(simd_val.get_unchecked_mut(i..));
2024-05-25 12:16:03 +08:00
let y = x & simd_63;
2024-04-25 23:17:58 +08:00
y.copy_to_slice(simd_val_b.get_unchecked_mut(i..));
}
2024-03-02 17:01:20 +08:00
}
2024-03-02 16:49:48 +08:00
2024-03-02 17:01:20 +08:00
let mut mod_count = 0;
for i in 0..256 {
2024-04-26 01:00:01 +08:00
unsafe {
2024-05-25 12:16:03 +08:00
if *simd_val.get_unchecked(i) > 88 && *simd_val.get_unchecked(i) < 217 {
2024-04-26 01:00:01 +08:00
*self.name_base.get_unchecked_mut(mod_count as usize) = *simd_val_b.get_unchecked(i);
mod_count += 1;
}
2024-03-02 17:01:20 +08:00
}
}
2024-05-25 12:16:03 +08:00
// let mut simd_val = self.val;
// let mut simd_val_b = self.val;
// let simd_181 = u8x32::splat(181);
// let simd_199 = u8x32::splat(199);
// let simd_128 = u8x32::splat(128);
// let simd_53 = u8x32::splat(53);
// let simd_63 = u8x32::splat(63);
// let simd_32 = u8x32::splat(32);
// for i in (0..256).step_by(32) {
// unsafe {
// let mut x = u8x32::from_slice(simd_val.get_unchecked(i..));
// let mut y = u8x32::from_slice(simd_val_b.get_unchecked(i..));
// x = (x * simd_181 + simd_199) & simd_128;
// y = (y * simd_53) & simd_63 ^ simd_32;
// x.copy_to_slice(simd_val.get_unchecked_mut(i..));
// y.copy_to_slice(simd_val_b.get_unchecked_mut(i..));
// }
// }
// let mut mod_count = 0;
// for i in 0..256 {
// unsafe {
// if simd_val.get_unchecked(i) != &0 {
// *self.name_base.get_unchecked_mut(mod_count as usize) = *simd_val_b.get_unchecked(i);
// mod_count += 1;
// }
// }
// }
2024-03-02 15:48:44 +08:00
// const int N = 256, M = 128, K = 64, skill_cnt = 40, max_len = 25;
2024-03-02 17:01:20 +08:00
let mut a: u8 = 0;
let mut b: u8 = 0;
2024-03-02 15:48:44 +08:00
let mut s: u8 = 0;
for _ in 0..2 {
for i in 0..40 {
2024-04-25 23:17:58 +08:00
let rnd = unsafe {
2024-03-02 17:01:20 +08:00
a += 1;
2024-04-25 23:17:58 +08:00
b = b.wrapping_add(*self.val.get_unchecked(a as usize));
self.val.swap_unchecked(a as usize, b as usize);
let u: u8 = *self.val.get_unchecked(
((*self.val.get_unchecked(a as usize) as u16 + *self.val.get_unchecked(b as usize) as u16) & 255)
as usize,
);
2024-03-02 17:01:20 +08:00
a += 1;
2024-04-25 23:17:58 +08:00
b = b.wrapping_add(*self.val.get_unchecked(a as usize));
self.val.swap_unchecked(a as usize, b as usize);
let t: u8 = *self.val.get_unchecked(
((*self.val.get_unchecked(a as usize) as u16 + *self.val.get_unchecked(b as usize) as u16) & 255)
as usize,
);
2024-03-02 15:48:44 +08:00
(((u as u32) << 8 | t as u32) % 40) as u8
};
2024-04-25 23:17:58 +08:00
unsafe {
2024-05-25 00:45:17 +08:00
s = (s as u16 + rnd as u16 + *self.skl_id.get_unchecked(i as usize) as u16) as u8 % 40;
self.skl_id.swap_unchecked(i as usize, s as usize);
2024-04-25 23:17:58 +08:00
}
2024-03-02 15:48:44 +08:00
}
}
let mut last = -1;
2024-04-28 20:34:39 +08:00
for (j, i) in (64..128).step_by(4).enumerate() {
2024-04-26 01:00:01 +08:00
let p = unsafe {
min(
2024-04-28 20:34:39 +08:00
min(*self.name_base.get_unchecked(i), *self.name_base.get_unchecked(i + 1)),
2024-04-26 01:00:01 +08:00
min(*self.name_base.get_unchecked(i + 2), *self.name_base.get_unchecked(i + 3)),
)
};
2024-05-03 23:31:43 +08:00
unsafe {
2024-05-25 00:45:17 +08:00
if p > 10 && *self.skl_id.get_unchecked(j) < 35 {
2024-05-03 23:31:43 +08:00
*self.skl_freq.get_unchecked_mut(j) = p - 10;
2024-05-25 00:45:17 +08:00
if *self.skl_id.get_unchecked(j) < 25 {
2024-05-03 23:31:43 +08:00
last = j as i32;
}
} else {
*self.skl_freq.get_unchecked_mut(j) = 0;
}
2024-03-02 15:48:44 +08:00
}
}
if last != -1 {
2024-05-03 23:31:43 +08:00
// self.skl_freq[last as usize] <<= 1;
unsafe {
*self.skl_freq.get_unchecked_mut(last as usize) <<= 1;
}
2024-03-02 15:48:44 +08:00
// *= 2
}
if (self.skl_freq[14] != 0) && (last != 14) {
2024-04-25 23:17:58 +08:00
self.skl_freq[14] += min(min(self.name_base[60], self.name_base[61]), self.skl_freq[14]);
2024-03-02 15:48:44 +08:00
}
if (self.skl_freq[15] != 0) && (last != 15) {
2024-04-25 23:17:58 +08:00
self.skl_freq[15] += min(min(self.name_base[62], self.name_base[63]), self.skl_freq[15]);
2024-03-02 15:48:44 +08:00
}
2024-03-02 12:06:59 +08:00
}
#[cfg(not(feature = "simd"))]
{
2024-03-02 17:01:20 +08:00
todo!("none simd 还没写呢")
2024-03-02 12:06:59 +08:00
}
}
2024-02-29 01:59:03 +08:00
#[inline(always)]
pub fn get_property(&self) -> f32 {
2024-05-03 22:45:58 +08:00
unsafe {
self.name_prop.get_unchecked(1..=7).iter().sum::<u32>() as f32 + (*self.name_prop.get_unchecked(0) as f32 / 3_f32)
}
2024-02-29 01:59:03 +08:00
}
2024-03-23 00:32:19 +08:00
pub fn get_info(&self) -> String {
let main = format!(
"name: {}, team: {} HP|{} 攻|{} 防|{} 速|{} 敏|{} 魔|{} 抗|{} 智|{} 八围:{}",
self.name,
self.team,
self.name_prop[0],
self.name_prop[1],
self.name_prop[2],
self.name_prop[3],
self.name_prop[4],
self.name_prop[5],
self.name_prop[6],
self.name_prop[7],
self.get_property()
);
let skills = {
let mut base = "".to_string();
let skill_names = [
2024-04-25 23:17:58 +08:00
"火球", "冰冻", "雷击", "地裂", "吸血", "投毒", "连击", "会心", "瘟疫", "命轮", "狂暴", "魅惑", "加速", "减速",
"诅咒", "治愈", "苏生", "净化", "铁壁", "蓄力", "聚气", "潜行", "血祭", "分身", "幻术", "防御", "守护", "反弹",
"护符", "护盾", "反击", "吞噬", "亡灵", "垂死", "隐匿", "", "", "", "", "",
2024-03-23 00:32:19 +08:00
];
// 后处理
let mut skills = [0; 40];
for i in 0..40 {
if self.skl_freq[i] != 0 {
skills[self.skl_id[i] as usize] = self.skl_freq[i];
}
}
for (i, v) in skills.iter().enumerate() {
if *v > 0 {
base.push_str(format!("{}: {}|", skill_names[i], v).as_str());
}
}
base
};
format!("{}|{}", main, skills)
}
2024-03-31 00:23:27 +08:00
2024-04-27 10:37:18 +08:00
pub fn get_info_csv(&self) -> String {
let main = format!(
"{},{},{},{},{},{},{},{},{},{},{}",
self.name,
self.team,
self.name_prop[0],
self.name_prop[1],
self.name_prop[2],
self.name_prop[3],
self.name_prop[4],
self.name_prop[5],
self.name_prop[6],
self.name_prop[7],
self.get_property()
);
let skills = {
let mut base = "".to_string();
let skill_names = [
"火球", "冰冻", "雷击", "地裂", "吸血", "投毒", "连击", "会心", "瘟疫", "命轮", "狂暴", "魅惑", "加速", "减速",
"诅咒", "治愈", "苏生", "净化", "铁壁", "蓄力", "聚气", "潜行", "血祭", "分身", "幻术", "防御", "守护", "反弹",
"护符", "护盾", "反击", "吞噬", "亡灵", "垂死", "隐匿", "", "", "", "", "",
];
// 后处理
let mut skills = [0; 40];
for i in 0..40 {
if self.skl_freq[i] != 0 {
skills[self.skl_id[i] as usize] = self.skl_freq[i];
}
}
for (i, v) in skills.iter().enumerate() {
if *v > 0 {
base.push_str(format!("{}-{},", skill_names[i], v).as_str());
}
}
base
};
format!("{},{}", main, skills)
}
2024-03-31 00:23:27 +08:00
pub fn get_fullname(&self) -> String {
if self.team.is_empty() {
self.name.clone()
} else {
format!("{}@{}", self.name, self.team)
}
}
2024-02-28 19:04:57 +08:00
}
2024-02-28 21:49:09 +08:00
2024-02-29 19:49:49 +08:00
#[cfg(test)]
mod test {
use super::*;
2024-02-28 21:49:09 +08:00
2024-02-29 19:49:49 +08:00
#[test]
2024-03-02 00:50:45 +08:00
fn new_test() {
let namer = Namer::new(&"x@x".to_string());
assert!(namer.is_some());
let namer = namer.unwrap();
assert_eq!(namer.name, "x");
assert_eq!(namer.team, "x");
}
2024-03-02 15:48:44 +08:00
2024-03-02 00:50:45 +08:00
#[test]
fn val_test() {
2024-02-29 19:49:49 +08:00
let team = TeamNamer::new_unchecked("x");
let namer = Namer::new_from_team_namer_unchecked(&team, "x");
2024-02-28 23:33:59 +08:00
2024-02-29 19:49:49 +08:00
let val_vec: Vec<u8> = vec![
2024-04-25 23:17:58 +08:00
225, 96, 49, 232, 20, 47, 115, 245, 234, 23, 111, 178, 231, 100, 118, 197, 42, 98, 137, 196, 209, 86, 114, 184, 167,
129, 164, 239, 205, 211, 82, 173, 189, 153, 198, 67, 4, 3, 90, 52, 128, 134, 176, 145, 85, 9, 250, 30, 63, 247, 240,
17, 215, 200, 78, 188, 132, 117, 10, 45, 162, 79, 123, 73, 109, 91, 57, 210, 22, 175, 107, 203, 103, 32, 83, 70, 242,
75, 220, 140, 148, 15, 138, 44, 228, 43, 105, 199, 99, 116, 97, 69, 80, 172, 230, 25, 224, 33, 31, 135, 235, 74, 193,
238, 233, 88, 216, 204, 24, 163, 141, 6, 201, 26, 38, 21, 186, 237, 101, 206, 212, 76, 144, 219, 149, 169, 202, 110,
41, 166, 139, 194, 168, 34, 142, 147, 187, 108, 223, 94, 5, 243, 226, 60, 40, 102, 51, 87, 61, 236, 46, 159, 64, 227,
113, 190, 81, 127, 65, 8, 183, 253, 150, 249, 229, 37, 156, 182, 180, 246, 124, 244, 174, 122, 89, 120, 160, 35, 143,
11, 14, 151, 133, 27, 177, 251, 221, 207, 58, 29, 131, 119, 171, 157, 93, 185, 48, 112, 192, 191, 66, 106, 39, 59,
92, 19, 1, 155, 254, 84, 222, 165, 54, 121, 13, 50, 36, 130, 95, 161, 213, 170, 28, 241, 71, 53, 68, 218, 0, 252, 16,
136, 179, 158, 248, 2, 154, 12, 125, 126, 255, 18, 146, 104, 77, 152, 208, 214, 72, 55, 195, 62, 7, 217, 56, 181,
2024-02-29 19:49:49 +08:00
];
assert_eq!(namer.val.to_vec(), val_vec);
2024-03-02 00:50:45 +08:00
}
#[test]
fn base_name_test() {
let team = TeamNamer::new_unchecked("x");
2024-03-02 17:01:20 +08:00
let mut namer = Namer::new_from_team_namer_unchecked(&team, "x");
2024-03-02 00:50:45 +08:00
let base_name_vec: Vec<u8> = vec![
2024-04-25 23:17:58 +08:00
53, 0, 40, 4, 58, 61, 37, 46, 56, 51, 21, 20, 27, 17, 15, 26, 13, 30, 52, 63, 36, 30, 57, 34, 22, 37, 35, 6, 12, 25,
50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2024-03-02 17:01:20 +08:00
];
let full_base_name_vec: Vec<u8> = vec![
2024-04-25 23:17:58 +08:00
53, 0, 40, 4, 58, 61, 37, 46, 56, 51, 21, 20, 27, 17, 15, 26, 13, 30, 52, 63, 36, 30, 57, 34, 22, 37, 35, 6, 12, 25,
50, 49, 59, 23, 49, 27, 51, 58, 39, 28, 60, 20, 31, 36, 41, 11, 7, 29, 24, 24, 61, 62, 57, 4, 28, 48, 55, 50, 38, 29,
10, 40, 42, 15, 23, 47, 42, 62, 47, 1, 60, 5, 43, 21, 1, 46, 45, 9, 9, 14, 38, 13, 56, 0, 31, 59, 39, 6, 35, 41, 55,
5, 34, 3, 7, 33, 33, 45, 16, 16, 32, 43, 18, 44, 22, 14, 17, 10, 11, 53, 18, 44, 19, 52, 2, 32, 12, 8, 2, 54, 26, 48,
8, 3, 63, 54, 19, 25,
2024-03-02 00:50:45 +08:00
];
2024-03-03 17:12:29 +08:00
assert_eq!(namer.name_base.to_vec(), base_name_vec);
namer.update_skill();
// update skill 之后才会是完整的 name
2024-03-02 17:01:20 +08:00
assert_eq!(namer.name_base.to_vec(), full_base_name_vec);
2024-02-29 19:49:49 +08:00
}
2024-03-02 00:50:45 +08:00
2024-03-02 15:48:44 +08:00
#[test]
fn skill_prop_test() {
let team = TeamNamer::new_unchecked("x");
let mut namer = Namer::new_from_team_namer_unchecked(&team, "x");
namer.update_skill();
2024-05-14 19:17:36 +08:00
let skill_freq_vec: Vec<u8> = vec![
2024-04-25 23:17:58 +08:00
13, 0, 0, 0, 0, 0, 0, 0, 6, 8, 0, 1, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,
2024-03-02 17:01:20 +08:00
];
2024-05-14 19:17:36 +08:00
assert_eq!(namer.skl_freq.to_vec(), skill_freq_vec);
2024-03-02 15:48:44 +08:00
}
2024-03-17 12:07:00 +08:00
#[test]
fn skill_id_test() {
let team = TeamNamer::new_unchecked("x");
let mut namer = Namer::new_from_team_namer_unchecked(&team, "x");
namer.update_skill();
let skill_id_vec: Vec<u8> = vec![
2024-04-25 23:17:58 +08:00
9, 13, 12, 38, 4, 27, 26, 15, 16, 32, 24, 5, 7, 21, 18, 10, 37, 2, 6, 20, 39, 1, 14, 3, 11, 29, 22, 33, 19, 0, 30,
31, 17, 28, 34, 35, 23, 8, 25, 36,
2024-03-17 12:07:00 +08:00
];
assert_eq!(namer.skl_id.to_vec(), skill_id_vec);
}
2024-03-02 00:50:45 +08:00
#[test]
fn prop_test() {
let team = TeamNamer::new_unchecked("x");
let namer = Namer::new_from_team_namer_unchecked(&team, "x");
2024-03-02 15:48:44 +08:00
let prop_vec: Vec<u32> = vec![344, 57, 53, 66, 72, 70, 71, 61];
2024-03-02 00:50:45 +08:00
assert_eq!(namer.name_prop.to_vec(), prop_vec);
2024-05-03 22:45:58 +08:00
assert_eq!(namer.get_property(), 564.6667_f32);
2024-03-02 00:50:45 +08:00
}
2024-03-31 00:23:27 +08:00
#[test]
fn shadow_test() {
let name = Namer::new_unchecked("一一七啺埀㴁?shadow");
let prop_vec: Vec<u32> = vec![240, 89, 69, 82, 65, 75, 49, 49];
2024-04-05 01:48:21 +08:00
2024-03-31 00:23:27 +08:00
assert_eq!(name.name_prop.to_vec(), prop_vec);
2024-05-03 22:45:58 +08:00
assert_eq!(name.get_property(), 558_f32);
2024-03-31 00:23:27 +08:00
}
2024-05-03 19:07:08 +08:00
#[test]
fn update_name_test() {
// 先创建一个正常的 namer
// 然后更新名字
let team = TeamNamer::new_unchecked("x");
let mut namer = Namer::new_from_team_namer_unchecked(&team, "x");
let update_name = "k";
namer.replace_name(&team, update_name);
let mut none_update_name = Namer::new_from_team_namer_unchecked(&team, update_name);
none_update_name.update_skill();
namer.update_skill();
assert_eq!(namer.name_base.to_vec(), none_update_name.name_base.to_vec());
assert_eq!(namer.name_prop.to_vec(), none_update_name.name_prop.to_vec());
assert_eq!(namer.val.to_vec(), none_update_name.val.to_vec());
assert_eq!(namer.skl_id.to_vec(), none_update_name.skl_id.to_vec());
assert_eq!(namer.skl_freq.to_vec(), none_update_name.skl_freq.to_vec());
}
2024-02-29 19:49:49 +08:00
}