1use crate::{
4 config::{Mapped, MappedKey, Regularization, Scheme, ShortCodeConfig, 配置},
5 encoders::简码配置,
6 objectives::metric::指法标记,
7 错误,
8};
9use regex::Regex;
10use rustc_hash::FxHashMap;
11use serde::{Deserialize, Serialize};
12use std::{cmp::Reverse, collections::HashMap};
13
14pub const 最大词长: usize = 10;
16
17pub const 最大按键组合长度: usize = 4;
19
20#[derive(Debug, Serialize, Deserialize, Clone)]
22pub struct 原始可编码对象 {
23 pub name: String,
24 pub sequence: String,
25 pub frequency: u64,
26 #[serde(default = "原始可编码对象::默认级别")]
27 pub level: u64,
28}
29
30impl 原始可编码对象 {
31 const fn 默认级别() -> u64 {
32 u64::MAX
33 }
34}
35
36pub type 原始键位分布信息 = HashMap<char, 键位分布损失函数>;
37pub type 键位分布信息 = Vec<键位分布损失函数>;
38pub type 原始当量信息 = HashMap<String, f64>;
39pub type 当量信息 = Vec<f64>;
40
41#[derive(Debug, Clone, Serialize, Deserialize)]
43pub struct 键位分布损失函数 {
44 pub ideal: f64,
45 pub lt_penalty: f64,
46 pub gt_penalty: f64,
47}
48
49pub type 元素 = usize;
51
52pub type 元素序列 = Vec<元素>;
54
55pub type 编码 = u64;
57
58#[derive(Debug, Clone)]
60pub struct 可编码对象 {
61 pub 名称: String,
62 pub 词长: usize,
63 pub 元素序列: 元素序列,
64 pub 频率: u64,
65 pub 简码等级: u64,
66 pub 原始顺序: usize,
67}
68
69#[derive(Clone, Debug, Copy, Default)]
71pub struct 部分编码信息 {
72 pub 原始编码: 编码, pub 原始编码候选位置: u8, pub 实际编码: 编码, pub 选重标记: bool, pub 上一个实际编码: 编码, pub 上一个选重标记: bool, pub 有变化: bool, }
80
81impl 部分编码信息 {
82 #[inline(always)]
83 pub fn 更新(&mut self, 编码: 编码, 选重标记: bool) {
84 if self.实际编码 == 编码 && self.选重标记 == 选重标记 {
85 return;
86 }
87 self.有变化 = true;
88 self.上一个实际编码 = self.实际编码;
89 self.上一个选重标记 = self.选重标记;
90 self.实际编码 = 编码;
91 self.选重标记 = 选重标记;
92 }
93}
94
95#[derive(Clone, Debug)]
97pub struct 编码信息 {
98 pub 词长: usize,
99 pub 频率: u64,
100 pub 全码: 部分编码信息,
101 pub 简码: 部分编码信息,
102}
103
104impl 编码信息 {
105 pub fn new(词: &可编码对象) -> Self {
106 Self {
107 词长: 词.词长,
108 频率: 词.频率,
109 全码: 部分编码信息::default(),
110 简码: 部分编码信息::default(),
111 }
112 }
113}
114
115pub type 键 = u64;
117
118pub type 元素映射 = Vec<键>;
120
121pub type 指法向量 = [u8; 8];
123
124pub type 自动上屏 = Vec<bool>;
126
127#[derive(Debug, Serialize)]
129pub struct 码表项 {
130 pub name: String,
131 pub full: String,
132 pub full_rank: u8,
133 pub short: String,
134 pub short_rank: u8,
135}
136
137pub type 正则化 = FxHashMap<元素, Vec<(元素, f64)>>;
138
139#[derive(Debug, Clone)]
141pub struct 数据 {
142 pub 配置: 配置,
143 pub 词列表: Vec<可编码对象>,
144 pub 键位分布信息: 键位分布信息,
145 pub 当量信息: 当量信息,
146 pub 初始映射: 元素映射,
147 pub 正则化: 正则化,
148 pub 进制: u64,
149 pub 选择键: Vec<键>,
150 pub 键转数字: FxHashMap<char, 键>,
151 pub 数字转键: FxHashMap<键, char>,
152 pub 元素转数字: FxHashMap<String, 元素>,
153 pub 数字转元素: FxHashMap<元素, String>,
154}
155
156impl Mapped {
157 pub fn length(&self) -> usize {
158 match self {
159 Mapped::Basic(s) => s.len(),
160 Mapped::Advanced(v) => v.len(),
161 }
162 }
163
164 pub fn normalize(&self) -> Vec<MappedKey> {
165 match self {
166 Mapped::Advanced(vector) => vector.clone(),
167 Mapped::Basic(string) => string.chars().map(MappedKey::Ascii).collect(),
168 }
169 }
170}
171
172type 字母表信息 = (u64, Vec<键>, FxHashMap<char, 键>, FxHashMap<键, char>);
173type 映射信息 = (元素映射, FxHashMap<String, 元素>, FxHashMap<元素, String>);
174
175impl 数据 {
176 pub fn 新建(
177 配置: 配置,
178 原始词列表: Vec<原始可编码对象>,
179 原始键位分布信息: 原始键位分布信息,
180 原始当量信息: 原始当量信息,
181 ) -> Result<Self, 错误> {
182 let (进制, 选择键, 键转数字, 数字转键) = Self::预处理字母表(&配置)?;
183 let (初始映射, 元素转数字, 数字转元素) = Self::预处理映射(&配置, &键转数字, 进制)?;
184 let 最大码长 = 配置.encoder.max_length;
185 let 词列表 = Self::预处理词列表(原始词列表, 最大码长, &元素转数字)?;
186 let 组合长度 = 最大码长.min(最大按键组合长度);
187 let 编码空间大小 = 进制.pow(组合长度 as u32) as usize;
188 let 键位分布信息 = Self::预处理键位分布信息(&原始键位分布信息, 进制, &数字转键);
189 let 当量信息 = Self::预处理当量信息(&原始当量信息, 编码空间大小, 进制, &数字转键);
190 let 正则化 = if let Some(正则化配置) = 配置
191 .optimization
192 .clone()
193 .and_then(|x| Some(x.objective))
194 .and_then(|x| Some(x.regularization))
195 .flatten()
196 {
197 Self::预处理正则化(&正则化配置, &元素转数字)?
198 } else {
199 FxHashMap::default()
200 };
201 let repr = Self {
202 配置,
203 词列表,
204 键位分布信息,
205 当量信息,
206 初始映射,
207 元素转数字,
208 数字转元素,
209 键转数字,
210 数字转键,
211 进制,
212 选择键,
213 正则化,
214 };
215 Ok(repr)
216 }
217
218 pub fn 预处理字母表(config: &配置) -> Result<字母表信息, 错误> {
222 let mut 键转数字: FxHashMap<char, 键> = FxHashMap::default();
223 let mut 数字转键: FxHashMap<键, char> = FxHashMap::default();
224 let mut index = 1;
225 for key in config.form.alphabet.chars() {
226 if 键转数字.contains_key(&key) {
227 return Err("编码键有重复!".into());
228 };
229 键转数字.insert(key, index);
230 数字转键.insert(index, key);
231 index += 1;
232 }
233 let default_select_keys = vec!['_'];
234 let select_keys = config
235 .encoder
236 .select_keys
237 .as_ref()
238 .unwrap_or(&default_select_keys);
239 if select_keys.is_empty() {
240 return Err("选择键不能为空!".into());
241 }
242 let mut parsed_select_keys: Vec<键> = vec![];
243 for key in select_keys {
244 if 键转数字.contains_key(key) {
245 return Err("编码键有重复!".into());
246 };
247 键转数字.insert(*key, index);
248 数字转键.insert(index, *key);
249 parsed_select_keys.push(index);
250 index += 1;
251 }
252 let radix = index;
253 Ok((radix, parsed_select_keys, 键转数字, 数字转键))
254 }
255
256 pub fn 预处理映射(
258 配置: &配置,
259 键转数字: &FxHashMap<char, 键>,
260 进制: u64,
261 ) -> Result<映射信息, 错误> {
262 let mut 元素映射: 元素映射 = (0..进制).collect();
263 let mut 元素转数字: FxHashMap<String, 元素> = FxHashMap::default();
264 let mut 数字转元素: FxHashMap<元素, String> = FxHashMap::default();
265 for (键字符, 键) in 键转数字 {
266 元素转数字.insert(键字符.to_string(), *键 as usize);
267 数字转元素.insert(*键 as usize, 键字符.to_string());
268 }
269 for (元素, 映射值) in &配置.form.mapping {
270 let 映射值 = 映射值.normalize();
271 for (序号, 映射键) in 映射值.iter().enumerate() {
272 if let MappedKey::Ascii(x) = 映射键 {
273 if let Some(键) = 键转数字.get(x) {
274 let 元素名 = Self::序列化(元素, 序号);
275 元素转数字.insert(元素名.clone(), 元素映射.len());
276 数字转元素.insert(元素映射.len(), 元素名.clone());
277 元素映射.push(*键);
278 } else {
279 return Err(format!("元素 {元素} 的编码中的字符 {x} 并不在字母表中").into());
280 }
281 }
282 }
283 }
284 Ok((元素映射, 元素转数字, 数字转元素))
285 }
286
287 pub fn 预处理正则化(
288 正则化: &Regularization,
289 元素转数字: &FxHashMap<String, 元素>,
290 ) -> Result<FxHashMap<元素, Vec<(元素, f64)>>, 错误> {
291 let mut result = FxHashMap::default();
292 if let Some(列表) = &正则化.element_affinities {
293 for 规则 in 列表 {
294 let 元素名称 = Self::序列化(&规则.from.element, 规则.from.index);
295 let 元素 = 元素转数字
296 .get(&元素名称)
297 .ok_or(format!("元素 {元素名称} 不存在"))?;
298 let mut 亲和度列表 = Vec::new();
299 for 目标 in 规则.to.iter() {
300 let 目标元素名称 = Self::序列化(&目标.element.element, 目标.element.index);
301 let 目标元素 = 元素转数字
302 .get(&目标元素名称)
303 .ok_or(format!("目标元素 {目标元素名称} 不存在"))?;
304 亲和度列表.push((*目标元素, 目标.affinity));
305 }
306 result.insert(*元素, 亲和度列表);
307 }
308 }
309 if let Some(列表) = &正则化.key_affinities {
310 for 规则 in 列表 {
311 let 元素名称 = Self::序列化(&规则.from.element, 规则.from.index);
312 let 元素 = 元素转数字
313 .get(&元素名称)
314 .ok_or(format!("元素 {元素名称} 不存在"))?;
315 let mut 亲和度列表 = Vec::new();
316 for 目标 in 规则.to.iter() {
317 let 目标键位 = 元素转数字
318 .get(&目标.key.to_string())
319 .ok_or(format!("目标键位不存在"))?;
320 亲和度列表.push((*目标键位, 目标.affinity));
321 }
322 result.insert(*元素, 亲和度列表);
323 }
324 }
325 Ok(result)
326 }
327 pub fn 序列化(element: &String, index: usize) -> String {
328 if index == 0 {
329 element.to_string()
330 } else {
331 format!("{}.{}", element, index)
332 }
333 }
334
335 pub fn 预处理词列表(
337 raw_encodables: Vec<原始可编码对象>,
338 max_length: usize,
339 element_repr: &FxHashMap<String, 元素>,
340 ) -> Result<Vec<可编码对象>, 错误> {
341 let mut encodables = Vec::new();
342 for (index, assemble) in raw_encodables.into_iter().enumerate() {
343 let 原始可编码对象 {
344 name,
345 frequency,
346 level,
347 sequence,
348 } = assemble;
349 let raw_sequence: Vec<_> = sequence.split(' ').collect();
350 let mut sequence = 元素序列::new();
351 let length = raw_sequence.len();
352 if length > max_length {
353 return Err(format!(
354 "编码对象「{name}」包含的元素数量为 {length},超过了最大码长 {max_length}"
355 )
356 .into());
357 }
358 for element in raw_sequence {
359 if let Some(number) = element_repr.get(element) {
360 sequence.push(*number);
361 } else {
362 return Err(format!(
363 "编码对象「{name}」包含的元素「{element}」无法在键盘映射中找到"
364 )
365 .into());
366 }
367 }
368 encodables.push(可编码对象 {
369 名称: name.clone(),
370 词长: name.chars().count(),
371 元素序列: sequence,
372 频率: frequency,
373 简码等级: level,
374 原始顺序: index,
375 });
376 }
377
378 encodables.sort_by_key(|x| Reverse(x.频率));
379 Ok(encodables)
380 }
381
382 pub fn 生成码表(&self, buffer: &[编码信息]) -> Vec<码表项> {
383 let mut entries: Vec<(usize, 码表项)> = Vec::new();
384 let encodables = &self.词列表;
385 let recover = |code: 编码| {
386 Self::数字转编码(code, self.进制, &self.数字转键)
387 .iter()
388 .collect()
389 };
390 for (index, encodable) in encodables.iter().enumerate() {
391 let entry = 码表项 {
392 name: encodable.名称.clone(),
393 full: recover(buffer[index].全码.原始编码),
394 full_rank: buffer[index].全码.原始编码候选位置,
395 short: recover(buffer[index].简码.原始编码),
396 short_rank: buffer[index].简码.原始编码候选位置,
397 };
398 entries.push((encodable.原始顺序, entry));
399 }
400 entries.sort_by_key(|x| x.0);
401 entries.into_iter().map(|x| x.1).collect()
402 }
403
404 pub fn 更新配置(&self, candidate: &元素映射) -> 配置 {
406 let mut new_config = self.配置.clone();
407 let lookup = |element: &String| {
408 let number = *self.元素转数字.get(element).unwrap(); let current_mapped = &candidate[number];
410 *self.数字转键.get(current_mapped).unwrap() };
412 for (element, mapped) in &self.配置.form.mapping {
413 let new_element = element.clone();
414 let new_mapped = match mapped {
415 Mapped::Basic(string) => {
416 let mut all_codes = String::new();
417 for index in 0..string.len() {
418 let name = Self::序列化(element, index);
419 all_codes.push(lookup(&name));
420 }
421 Mapped::Basic(all_codes)
422 }
423 Mapped::Advanced(vector) => {
424 let all_codes: Vec<MappedKey> = vector
425 .iter()
426 .enumerate()
427 .map(|(index, mapped_key)| match mapped_key {
428 MappedKey::Ascii(_) => {
429 MappedKey::Ascii(lookup(&Self::序列化(element, index)))
430 }
431 other => other.clone(),
432 })
433 .collect();
434 Mapped::Advanced(all_codes)
435 }
436 };
437 new_config.form.mapping.insert(new_element, new_mapped);
438 }
439 new_config
440 }
441
442 pub fn 数字转编码(
444 code: 编码, 进制: u64, repr_key: &FxHashMap<键, char>
445 ) -> Vec<char> {
446 let mut chars = Vec::new();
447 let mut remainder = code;
448 while remainder > 0 {
449 let k = remainder % 进制;
450 remainder /= 进制;
451 if k == 0 {
452 continue;
453 }
454 let char = repr_key.get(&k).unwrap(); chars.push(*char);
456 }
457 chars
458 }
459
460 pub fn 预处理键位分布信息(
462 原始键位分布信息: &原始键位分布信息,
463 进制: u64,
464 数字转键: &FxHashMap<键, char>,
465 ) -> Vec<键位分布损失函数> {
466 let default_loss = 键位分布损失函数 {
467 ideal: 0.0,
468 lt_penalty: 0.0,
469 gt_penalty: 1.0,
470 };
471 let mut 键位分布信息: Vec<键位分布损失函数> = (0..进制)
472 .map(|键| {
473 if 键 == 0 {
475 default_loss.clone()
476 } else {
477 let 键名称 = 数字转键[&键];
478 原始键位分布信息
479 .get(&键名称)
480 .unwrap_or(&default_loss)
481 .clone()
482 }
483 })
484 .collect();
485 键位分布信息.iter_mut().for_each(|x| {
486 x.ideal /= 100.0;
487 });
488 键位分布信息
489 }
490
491 pub fn 预处理当量信息(
494 原始当量信息: &原始当量信息,
495 space: usize,
496 进制: u64,
497 数字转键: &FxHashMap<键, char>,
498 ) -> Vec<f64> {
499 let mut result: Vec<f64> = vec![0.0; space];
500 for (index, equivalence) in result.iter_mut().enumerate() {
501 let chars = Self::数字转编码(index as u64, 进制, 数字转键);
502 for correlation_length in [2, 3, 4] {
503 if chars.len() < correlation_length {
504 break;
505 }
506 for i in 0..=(chars.len() - correlation_length) {
508 let substr: String = chars[i..(i + correlation_length)].iter().collect();
509 *equivalence += 原始当量信息.get(&substr).unwrap_or(&0.0);
510 }
511 }
512 }
513 result
514 }
515
516 pub fn 预处理指法标记(&self) -> Vec<指法向量> {
521 let 指法标记 = 指法标记::new();
522 let mut result: Vec<指法向量> = Vec::with_capacity(self.get_space());
523 for code in 0..self.get_space() {
524 let chars = Self::数字转编码(code as u64, self.进制, &self.数字转键);
525 if chars.len() < 2 {
526 result.push(指法向量::default());
527 continue;
528 }
529 let mut 指法向量 = 指法向量::default();
530 for i in 0..(chars.len() - 1) {
531 let pair = (chars[i], chars[i + 1]);
532 if 指法标记.同手.contains(&pair) {
533 指法向量[0] += 1;
534 }
535 if 指法标记.同指大跨排.contains(&pair) {
536 指法向量[1] += 1;
537 }
538 if 指法标记.同指小跨排.contains(&pair) {
539 指法向量[2] += 1;
540 }
541 if 指法标记.小指干扰.contains(&pair) {
542 指法向量[3] += 1;
543 }
544 if 指法标记.错手.contains(&pair) {
545 指法向量[4] += 1;
546 }
547 }
548 for i in 0..(chars.len() - 2) {
549 let triple = (chars[i], chars[i + 1], chars[i + 2]);
550 if triple.0 == triple.1 && triple.1 == triple.2 {
551 指法向量[5] += 1;
552 }
553 }
554 result.push(指法向量);
555 }
556 result
557 }
558
559 pub fn 预处理自动上屏(&self) -> Result<Vec<bool>, 错误> {
562 let mut result: Vec<bool> = vec![];
563 let encoder = &self.配置.encoder;
564 let mut re: Option<Regex> = None;
565 if let Some(pattern) = &encoder.auto_select_pattern {
566 let re_or_error = Regex::new(pattern);
567 if let Ok(regex) = re_or_error {
568 re = Some(regex);
569 } else {
570 return Err(format!("正则表达式 {pattern} 无法解析").into());
571 }
572 }
573 for code in 0..self.get_space() {
574 let chars = Self::数字转编码(code as u64, self.进制, &self.数字转键);
575 let string: String = chars.iter().collect();
576 let is_matched = if let Some(re) = &re {
577 re.is_match(&string)
578 } else if let Some(length) = encoder.auto_select_length {
579 chars.len() >= length
580 } else {
581 true
582 };
583 let is_max_length = chars.len() == encoder.max_length;
584 result.push(is_matched || is_max_length);
585 }
586 Ok(result)
587 }
588
589 pub fn 预处理简码规则(
590 &self,
591 schemes: &Vec<Scheme>,
592 ) -> Result<Vec<简码配置>, 错误> {
593 let mut compiled_schemes = Vec::new();
594 for scheme in schemes {
595 let prefix = scheme.prefix;
596 let count = scheme.count.unwrap_or(1);
597 let select_keys = if let Some(keys) = &scheme.select_keys {
598 let mut transformed_keys = Vec::new();
599 for key in keys {
600 let transformed_key = self
601 .键转数字
602 .get(key)
603 .ok_or(format!("简码的选择键 {key} 不在全局选择键中"))?;
604 transformed_keys.push(*transformed_key);
605 }
606 transformed_keys
607 } else {
608 self.选择键.clone()
609 };
610 if count > select_keys.len() {
611 return Err("选重数量不能高于选择键数量".into());
612 }
613 compiled_schemes.push(简码配置 {
614 prefix,
615 select_keys: select_keys[..count].to_vec(),
616 });
617 }
618 Ok(compiled_schemes)
619 }
620
621 pub fn 预处理简码配置(
622 &self,
623 configs: Vec<ShortCodeConfig>,
624 ) -> Result<[Vec<简码配置>; 最大词长], 错误> {
625 let mut short_code: [Vec<简码配置>; 最大词长] = Default::default();
626 for config in configs {
627 match config {
628 ShortCodeConfig::Equal {
629 length_equal,
630 schemes,
631 } => {
632 short_code[length_equal - 1].extend(self.预处理简码规则(&schemes)?);
633 }
634 ShortCodeConfig::Range {
635 length_in_range: (from, to),
636 schemes,
637 } => {
638 for length in from..=to {
639 short_code[length - 1].extend(self.预处理简码规则(&schemes)?);
640 }
641 }
642 }
643 }
644 Ok(short_code)
645 }
646
647 pub fn get_space(&self) -> usize {
648 let max_length = self.配置.encoder.max_length.min(最大按键组合长度);
649 self.进制.pow(max_length as u32) as usize
650 }
651}