1pub mod config;
6pub mod contexts;
7pub mod encoders;
8pub mod interfaces;
9pub mod objectives;
10pub mod operators;
11pub mod optimizers;
12#[cfg(feature = "server")]
13pub mod server;
14
15use config::{安排, 广义码位};
16use objectives::metric::指法标记;
17use rustc_hash::FxHashMap;
18use serde::{Deserialize, Serialize};
19use std::cmp::Reverse;
20use std::io;
21use wasm_bindgen::JsError;
22
23use crate::config::条件;
24
25pub const 最大词长: usize = 10;
27
28pub const 最大按键组合长度: usize = 4;
30
31#[derive(Debug, Serialize, Deserialize, Clone)]
32pub struct 原始元素序列及条件列表 {
33 pub 元素序列: Vec<广义码位>,
34 pub 条件列表: Vec<条件>,
35}
36
37#[derive(Debug, Serialize, Deserialize, Clone)]
39pub struct 原始可编码对象 {
40 pub 词: String,
41 #[serde(default)]
43 pub 元素序列: Option<Vec<广义码位>>,
44 #[serde(default)]
46 pub 全部元素序列: Option<Vec<原始元素序列及条件列表>>,
47 pub 频率: u64,
48 #[serde(default = "原始可编码对象::默认级别")]
49 pub 简码长度: u64,
50}
51
52impl 原始可编码对象 {
53 const fn 默认级别() -> u64 {
54 u64::MAX
55 }
56}
57
58pub type 原始键位分布信息 = FxHashMap<char, 键位分布损失函数>;
59pub type 键位分布信息 = Vec<键位分布损失函数>;
60pub type 原始当量信息 = FxHashMap<String, f64>;
61pub type 当量信息 = Vec<f64>;
62
63#[derive(Debug, Clone, Serialize, Deserialize)]
65pub struct 键位分布损失函数 {
66 pub 理想值: f64,
67 pub 低于惩罚: f64,
68 pub 高于惩罚: f64,
69}
70
71pub type 元素 = usize;
73
74pub type 元素位 = usize;
76
77pub const 最大元素序列长度: usize = 8;
79
80pub const 最大元素数量: usize = 1024;
83
84pub type 元素序列 = [元素位; 最大元素序列长度];
86
87pub type 元素图 = FxHashMap<元素, Vec<元素>>;
89
90pub const 最大元素编码长度: usize = 4;
92
93pub type 编码 = u64;
95
96#[derive(Debug, Clone)]
98pub struct 可编码对象 {
99 pub 词: String,
100 pub 词长: usize,
101 pub 元素序列: 元素序列,
102 pub 全部元素序列: Vec<(元素序列, 位图)>,
103 pub 频率: u64,
104 pub 简码长度: u64,
105 pub 原始顺序: usize,
106}
107
108#[derive(Debug, Clone, PartialEq, Eq)]
110pub struct 位图 {
111 pub 位图: [u64; 16],
112}
113
114impl 位图 {
115 pub fn new() -> Self {
116 Self { 位图: [0; 16] }
117 }
118
119 pub fn 从条件列表创建(条件列表: &[条件], 棱镜: &棱镜) -> Self {
120 let mut bitmap = Self::new();
121 for 条件 in 条件列表 {
122 if let Some(&元素) = 棱镜.元素转数字.get(&条件.element) {
123 if let Some(&位图索引) = 棱镜.可选元素位图索引.get(&元素) {
124 bitmap.insert(位图索引);
125 } else {
126 eprintln!(
129 "警告:条件中的元素「{}」在棱镜中未找到,已忽略这个条件",
130 条件.element
131 );
132 }
133 }
134 }
135 bitmap
136 }
137
138 pub fn insert(&mut self, i: usize) {
139 let (block, bit) = (i / 64, i % 64);
140 self.位图[block] |= 1 << bit;
141 }
142
143 pub fn remove(&mut self, i: usize) {
144 let (block, bit) = (i / 64, i % 64);
145 self.位图[block] &= !(1 << bit);
146 }
147
148 pub fn subset(&self, other: &Self) -> bool {
149 for i in 0..16 {
150 if self.位图[i] & !other.位图[i] != 0 {
151 return false;
152 }
153 }
154 true
155 }
156
157 pub fn union(&self, other: &Self) -> Self {
158 let mut result = Self::new();
159 for i in 0..16 {
160 result.位图[i] = self.位图[i] | other.位图[i];
161 }
162 result
163 }
164
165 pub fn intersection(&self, other: &Self) -> Self {
166 let mut result = Self::new();
167 for i in 0..16 {
168 result.位图[i] = self.位图[i] & other.位图[i];
169 }
170 result
171 }
172}
173
174#[derive(Clone, Debug, Copy, Default)]
176pub struct 部分编码信息 {
177 pub 原始编码: 编码, pub 原始编码候选位置: u8, pub 实际编码: 编码, pub 选重标记: u8, pub 上一个实际编码: 编码, pub 上一个选重标记: u8, pub 有变化: bool, }
185
186impl 部分编码信息 {
187 #[inline(always)]
188 pub fn 更新(&mut self, 编码: 编码, 选重标记: u8) {
189 if self.实际编码 == 编码 && self.选重标记 == 选重标记 {
190 return;
191 }
192 self.有变化 = true;
193 self.上一个实际编码 = self.实际编码;
194 self.上一个选重标记 = self.选重标记;
195 self.实际编码 = 编码;
196 self.选重标记 = 选重标记;
197 }
198}
199
200#[derive(Clone, Debug)]
202pub struct 编码信息 {
203 pub 词长: usize,
204 pub 频率: u64,
205 pub 全码: 部分编码信息,
206 pub 简码: 部分编码信息,
207}
208
209impl 编码信息 {
210 pub fn new(词: &可编码对象) -> Self {
211 Self {
212 词长: 词.词长,
213 频率: 词.频率,
214 全码: 部分编码信息::default(),
215 简码: 部分编码信息::default(),
216 }
217 }
218}
219
220pub type 键 = u64;
222
223pub type 指法向量 = [u8; 8];
225
226pub type 自动上屏 = Vec<bool>;
228
229#[derive(Debug, Clone, Serialize, Default)]
231pub struct 码表项 {
232 pub 词: String,
233 pub 全码: String,
234 pub 全码排名: u8,
235 pub 简码: String,
236 pub 简码排名: u8,
237}
238
239impl 安排 {
240 pub fn normalize(&self) -> Vec<广义码位> {
241 match self {
242 安排::Advanced(vector) => vector.clone(),
243 安排::Basic(string) => string.chars().map(广义码位::Ascii).collect(),
244 _ => panic!("无法把归并或禁用表示成列表形式"),
245 }
246 }
247}
248
249pub fn 元素标准名称(element: &String, index: usize) -> String {
250 if index == 0 {
251 element.to_string()
252 } else {
253 format!("{element}.{index}")
254 }
255}
256
257#[derive(Debug, Clone)]
258pub struct 棱镜 {
259 pub 键转数字: FxHashMap<char, 键>,
260 pub 数字转键: FxHashMap<键, char>,
261 pub 元素转数字: FxHashMap<String, 元素>,
262 pub 数字转元素: FxHashMap<元素, String>,
263 pub 进制: u64,
264 pub 可选元素位图索引: FxHashMap<元素, usize>,
267}
268
269impl 棱镜 {
270 pub fn 元素总数(&self) -> usize {
271 self.元素转数字.len() + 1 }
273
274 pub fn 数字转编码(&self, code: 编码) -> Vec<char> {
276 let mut chars = Vec::new();
277 let mut remainder = code;
278 while remainder > 0 {
279 let k = remainder % self.进制;
280 remainder /= self.进制;
281 if k == 0 {
282 continue;
283 }
284 let char = self.数字转键.get(&k).unwrap(); chars.push(*char);
286 }
287 chars
288 }
289
290 pub fn 预处理元素序列(
291 &self,
292 词: &String,
293 原始元素序列: &[广义码位],
294 最大码长: usize,
295 ) -> Result<元素序列, 错误> {
296 let mut 元素序列 = 元素序列::default();
297 let 原始元素序列长度 = 原始元素序列.len();
298 if 原始元素序列长度 > 最大码长 {
299 return Err(format!(
300 "编码对象「{词}」包含的元素数量为 {原始元素序列长度},超过了最大码长 {最大码长}"
301 )
302 .into());
303 }
304 for (i, 码位) in 原始元素序列.iter().enumerate() {
305 let 元素位 = match 码位 {
306 广义码位::Reference { element, index } => {
307 if let Some(&元素) = self.元素转数字.get(element) {
308 元素 + index * self.元素总数()
309 } else {
310 return Err(format!(
311 "编码对象「{词}」包含的元素「{element}」无法在键盘映射中找到"
312 )
313 .into());
314 }
315 }
316 _ => 0,
317 };
318 元素序列[i] = 元素位;
319 }
320 return Ok(元素序列);
321 }
322
323 pub fn 预处理词列表(
324 &self,
325 原始词列表: Vec<原始可编码对象>,
326 最大码长: usize,
327 ) -> Result<Vec<可编码对象>, 错误> {
328 let mut 词列表 = vec![];
329 for (原始顺序, 原始可编码对象) in 原始词列表.into_iter().enumerate() {
330 let 原始可编码对象 {
331 词,
332 频率,
333 元素序列: 原始单一元素序列,
334 全部元素序列: 原始全部元素序列,
335 简码长度,
336 } = 原始可编码对象;
337 let 原始全部元素序列: Vec<原始元素序列及条件列表> = match (原始单一元素序列, 原始全部元素序列) {
338 (Some(seq), None) => vec![原始元素序列及条件列表 { 元素序列: seq, 条件列表: vec![] }],
339 (None, Some(list)) => list,
340 _ => panic!("编码对象「{词}」必须恰好提供「元素序列」或「全部元素序列」之一", 词 = 词),
341 };
342 let mut 全部元素序列 = vec![];
343 assert!(!原始全部元素序列.is_empty(), "编码对象「{词}」至少需要一个元素序列", 词 = 词);
344 assert!(原始全部元素序列.last().unwrap().条件列表.is_empty(), "编码对象「{词}」的最后一个元素序列必须没有任何条件", 词 = 词);
345 for 原始元素序列及条件列表 { 元素序列: 原始元素序列, 条件列表 } in 原始全部元素序列 {
346 let 元素序列 = self.预处理元素序列(&词, &原始元素序列, 最大码长)?;
347 let 位图 = 位图::从条件列表创建(&条件列表, self);
348 全部元素序列.push((元素序列, 位图));
349 }
350 let c = 可编码对象 {
351 词: 词.clone(),
352 词长: 词.chars().count(),
353 频率,
354 简码长度,
355 元素序列: 全部元素序列[0].0,
356 全部元素序列,
357 原始顺序,
358 };
359 词列表.push(c);
360 }
361 词列表.sort_by_key(|x| Reverse(x.频率));
362 Ok(词列表)
363 }
364
365 pub fn 预处理键位分布信息(
367 &self,
368 原始键位分布信息: &原始键位分布信息,
369 ) -> Vec<键位分布损失函数> {
370 let default_loss = 键位分布损失函数 {
371 理想值: 0.0,
372 低于惩罚: 0.0,
373 高于惩罚: 0.0,
374 };
375 let mut 键位分布信息: Vec<键位分布损失函数> = (0..self.进制)
376 .map(|键| {
377 if 键 == 0 {
379 default_loss.clone()
380 } else {
381 let 键名称 = self.数字转键[&键];
382 原始键位分布信息
383 .get(&键名称)
384 .unwrap_or(&default_loss)
385 .clone()
386 }
387 })
388 .collect();
389 键位分布信息.iter_mut().for_each(|x| {
390 x.理想值 /= 100.0;
391 });
392 键位分布信息
393 }
394
395 pub fn 预处理当量信息(
398 &self, 原始当量信息: &原始当量信息, space: usize
399 ) -> Vec<f64> {
400 let mut result: Vec<f64> = vec![0.0; space];
401 for (index, equivalence) in result.iter_mut().enumerate() {
402 let chars = self.数字转编码(index as u64);
403 for correlation_length in [2, 3, 4] {
404 if chars.len() < correlation_length {
405 break;
406 }
407 for i in 0..=(chars.len() - correlation_length) {
409 let substr: String = chars[i..(i + correlation_length)].iter().collect();
410 *equivalence += 原始当量信息.get(&substr).unwrap_or(&0.0);
411 }
412 }
413 }
414 result
415 }
416
417 pub fn 预处理指法标记(&self, 空间: usize) -> Vec<指法向量> {
422 let 指法标记 = 指法标记::new();
423 let mut result: Vec<指法向量> = Vec::with_capacity(空间);
424 for code in 0..空间 {
425 let chars = self.数字转编码(code as u64);
426 if chars.len() < 2 {
427 result.push(指法向量::default());
428 continue;
429 }
430 let mut 指法向量 = 指法向量::default();
431 for i in 0..(chars.len() - 1) {
432 let pair = (chars[i], chars[i + 1]);
433 if 指法标记.同手.contains(&pair) {
434 指法向量[0] += 1;
435 }
436 if 指法标记.同指大跨排.contains(&pair) {
437 指法向量[1] += 1;
438 }
439 if 指法标记.同指小跨排.contains(&pair) {
440 指法向量[2] += 1;
441 }
442 if 指法标记.小指干扰.contains(&pair) {
443 指法向量[3] += 1;
444 }
445 if 指法标记.错手.contains(&pair) {
446 指法向量[4] += 1;
447 }
448 }
449 for i in 0..(chars.len() - 2) {
450 let triple = (chars[i], chars[i + 1], chars[i + 2]);
451 if triple.0 == triple.1 && triple.1 == triple.2 {
452 指法向量[5] += 1;
453 }
454 }
455 result.push(指法向量);
456 }
457 result
458 }
459}
460
461#[derive(Debug, Clone)]
463pub struct 错误 {
464 pub message: String,
465}
466
467impl From<String> for 错误 {
468 fn from(value: String) -> Self {
469 Self { message: value }
470 }
471}
472
473impl From<&str> for 错误 {
474 fn from(value: &str) -> Self {
475 Self {
476 message: value.to_string(),
477 }
478 }
479}
480
481impl From<io::Error> for 错误 {
482 fn from(value: io::Error) -> Self {
483 Self {
484 message: value.to_string(),
485 }
486 }
487}
488
489impl From<serde_json::Error> for 错误 {
490 fn from(value: serde_json::Error) -> Self {
491 Self {
492 message: value.to_string(),
493 }
494 }
495}
496
497impl From<错误> for JsError {
498 fn from(value: 错误) -> Self {
499 JsError::new(&value.message)
500 }
501}
502
503#[cfg(target_arch = "wasm32")]
504pub fn formatted_local_now() -> String {
505 use js_sys::Date;
506 let date = Date::new_0();
507 let month = date.get_month() as u32 + 1; let day = date.get_date() as u32;
509 let hour = date.get_hours() as u32;
510 let minute = date.get_minutes() as u32;
511 let second = date.get_seconds() as u32;
512 format!(
513 "{:02}-{:02}+{:02}_{:02}_{:02}",
514 month, day, hour, minute, second
515 )
516}
517
518#[cfg(not(target_arch = "wasm32"))]
519pub fn formatted_local_now() -> String {
520 use chrono::Local;
521 Local::now().format("%m-%d+%H_%M_%S").to_string()
522}