1pub mod config;
6pub mod contexts;
7pub mod encoders;
8pub mod interfaces;
9pub mod objectives;
10pub mod operators;
11pub mod optimizers;
12pub mod server;
13
14use config::{安排, 广义码位};
15use objectives::metric::指法标记;
16use rustc_hash::FxHashMap;
17use serde::{Deserialize, Serialize};
18use std::cmp::Reverse;
19use std::io;
20use wasm_bindgen::JsError;
21
22pub const 最大词长: usize = 10;
24
25pub const 最大按键组合长度: usize = 4;
27
28#[derive(Debug, Serialize, Deserialize, Clone)]
30pub struct 原始可编码对象 {
31 pub 词: String,
32 pub 元素序列: String,
33 pub 频率: u64,
34 #[serde(default = "原始可编码对象::默认级别")]
35 pub 简码长度: u64,
36}
37
38impl 原始可编码对象 {
39 const fn 默认级别() -> u64 {
40 u64::MAX
41 }
42}
43
44pub type 原始键位分布信息 = FxHashMap<char, 键位分布损失函数>;
45pub type 键位分布信息 = Vec<键位分布损失函数>;
46pub type 原始当量信息 = FxHashMap<String, f64>;
47pub type 当量信息 = Vec<f64>;
48
49#[derive(Debug, Clone, Serialize, Deserialize)]
51pub struct 键位分布损失函数 {
52 pub 理想值: f64,
53 pub 低于惩罚: f64,
54 pub 高于惩罚: f64,
55}
56
57pub type 元素 = usize;
59
60pub type 元素序列 = Vec<(元素, usize)>;
62
63pub type 元素图 = FxHashMap<元素, Vec<元素>>;
65
66pub const 最大元素编码长度: usize = 4;
68
69pub type 编码 = u64;
71
72#[derive(Debug, Clone)]
74pub struct 可编码对象 {
75 pub 词: String,
76 pub 词长: usize,
77 pub 元素序列: 元素序列,
78 pub 频率: u64,
79 pub 简码长度: u64,
80 pub 原始顺序: usize,
81}
82
83#[derive(Clone, Debug, Copy, Default)]
85pub struct 部分编码信息 {
86 pub 原始编码: 编码, pub 原始编码候选位置: u8, pub 实际编码: 编码, pub 选重标记: bool, pub 上一个实际编码: 编码, pub 上一个选重标记: bool, pub 有变化: bool, }
94
95impl 部分编码信息 {
96 #[inline(always)]
97 pub fn 更新(&mut self, 编码: 编码, 选重标记: bool) {
98 if self.实际编码 == 编码 && self.选重标记 == 选重标记 {
99 return;
100 }
101 self.有变化 = true;
102 self.上一个实际编码 = self.实际编码;
103 self.上一个选重标记 = self.选重标记;
104 self.实际编码 = 编码;
105 self.选重标记 = 选重标记;
106 }
107}
108
109#[derive(Clone, Debug)]
111pub struct 编码信息 {
112 pub 词长: usize,
113 pub 频率: u64,
114 pub 全码: 部分编码信息,
115 pub 简码: 部分编码信息,
116}
117
118impl 编码信息 {
119 pub fn new(词: &可编码对象) -> Self {
120 Self {
121 词长: 词.词长,
122 频率: 词.频率,
123 全码: 部分编码信息::default(),
124 简码: 部分编码信息::default(),
125 }
126 }
127}
128
129pub type 键 = u64;
131
132pub type 指法向量 = [u8; 8];
134
135pub type 自动上屏 = Vec<bool>;
137
138#[derive(Debug, Clone, Serialize, Default)]
140pub struct 码表项 {
141 pub 词: String,
142 pub 全码: String,
143 pub 全码排名: u8,
144 pub 简码: String,
145 pub 简码排名: u8,
146}
147
148impl 安排 {
149 pub fn normalize(&self) -> Vec<广义码位> {
150 match self {
151 安排::Advanced(vector) => vector.clone(),
152 安排::Basic(string) => string.chars().map(广义码位::Ascii).collect(),
153 _ => panic!("无法把归并或禁用表示成列表形式"),
154 }
155 }
156}
157
158pub fn 元素标准名称(element: &String, index: usize) -> String {
159 if index == 0 {
160 element.to_string()
161 } else {
162 format!("{element}.{index}")
163 }
164}
165
166#[derive(Debug, Clone)]
167pub struct 棱镜 {
168 pub 键转数字: FxHashMap<char, 键>,
169 pub 数字转键: FxHashMap<键, char>,
170 pub 元素转数字: FxHashMap<String, 元素>,
171 pub 数字转元素: FxHashMap<元素, String>,
172 pub 进制: u64,
173}
174
175impl 棱镜 {
176 pub fn 数字转编码(&self, code: 编码) -> Vec<char> {
178 let mut chars = Vec::new();
179 let mut remainder = code;
180 while remainder > 0 {
181 let k = remainder % self.进制;
182 remainder /= self.进制;
183 if k == 0 {
184 continue;
185 }
186 let char = self.数字转键.get(&k).unwrap(); chars.push(*char);
188 }
189 chars
190 }
191
192 pub fn 预处理词列表(
193 &self,
194 原始词列表: Vec<原始可编码对象>,
195 最大码长: usize,
196 ) -> Result<Vec<可编码对象>, 错误> {
197 let mut 词列表 = Vec::new();
198 for (原始顺序, 原始可编码对象) in 原始词列表.into_iter().enumerate() {
199 let 原始可编码对象 {
200 词: name,
201 频率: frequency,
202 元素序列: sequence,
203 简码长度: level,
204 } = 原始可编码对象;
205 let 原始元素序列: Vec<_> = sequence.split(' ').collect();
206 let mut 元素序列 = 元素序列::new();
207 let length = 原始元素序列.len();
208 if length > 最大码长 {
209 return Err(format!(
210 "编码对象「{name}」包含的元素数量为 {length},超过了最大码长 {最大码长}"
211 )
212 .into());
213 }
214 for 原始元素 in 原始元素序列 {
215 let (元素, 位置) = if 原始元素.contains(".") {
216 let parts: Vec<&str> = 原始元素.split('.').collect();
217 if parts.len() != 2 {
218 return Err(format!(
219 "编码对象「{name}」包含的元素「{原始元素}」格式不正确"
220 )
221 .into());
222 }
223 let 元素名称 = parts[0];
224 let index: usize = match parts[1].parse() {
225 Ok(v) => v,
226 Err(_) => {
227 return Err(format!(
228 "编码对象「{name}」包含的元素「{原始元素}」格式不正确"
229 )
230 .into());
231 }
232 };
233 if let Some(元素) = self.元素转数字.get(元素名称) {
234 元素序列.push((*元素, index));
235 } else {
236 return Err(format!(
237 "编码对象「{name}」包含的元素「{原始元素}」无法在键盘映射中找到"
238 )
239 .into());
240 }
241 continue;
242 } else {
243 let 元素名称 = 原始元素;
244 if let Some(元素) = self.元素转数字.get(元素名称) {
245 (*元素, 0)
246 } else {
247 return Err(format!(
248 "编码对象「{name}」包含的元素「{原始元素}」无法在键盘映射中找到"
249 )
250 .into());
251 }
252 };
253 元素序列.push((元素, 位置));
254 }
255 词列表.push(可编码对象 {
256 词: name.clone(),
257 词长: name.chars().count(),
258 频率: frequency,
259 简码长度: level,
260 元素序列,
261 原始顺序,
262 });
263 }
264 词列表.sort_by_key(|x| Reverse(x.频率));
265 Ok(词列表)
266 }
267
268 pub fn 预处理键位分布信息(
270 &self,
271 原始键位分布信息: &原始键位分布信息,
272 ) -> Vec<键位分布损失函数> {
273 let default_loss = 键位分布损失函数 {
274 理想值: 0.0,
275 低于惩罚: 0.0,
276 高于惩罚: 0.0,
277 };
278 let mut 键位分布信息: Vec<键位分布损失函数> = (0..self.进制)
279 .map(|键| {
280 if 键 == 0 {
282 default_loss.clone()
283 } else {
284 let 键名称 = self.数字转键[&键];
285 原始键位分布信息
286 .get(&键名称)
287 .unwrap_or(&default_loss)
288 .clone()
289 }
290 })
291 .collect();
292 键位分布信息.iter_mut().for_each(|x| {
293 x.理想值 /= 100.0;
294 });
295 键位分布信息
296 }
297
298 pub fn 预处理当量信息(
301 &self, 原始当量信息: &原始当量信息, space: usize
302 ) -> Vec<f64> {
303 let mut result: Vec<f64> = vec![0.0; space];
304 for (index, equivalence) in result.iter_mut().enumerate() {
305 let chars = self.数字转编码(index as u64);
306 for correlation_length in [2, 3, 4] {
307 if chars.len() < correlation_length {
308 break;
309 }
310 for i in 0..=(chars.len() - correlation_length) {
312 let substr: String = chars[i..(i + correlation_length)].iter().collect();
313 *equivalence += 原始当量信息.get(&substr).unwrap_or(&0.0);
314 }
315 }
316 }
317 result
318 }
319
320 pub fn 预处理指法标记(&self, 空间: usize) -> Vec<指法向量> {
325 let 指法标记 = 指法标记::new();
326 let mut result: Vec<指法向量> = Vec::with_capacity(空间);
327 for code in 0..空间 {
328 let chars = self.数字转编码(code as u64);
329 if chars.len() < 2 {
330 result.push(指法向量::default());
331 continue;
332 }
333 let mut 指法向量 = 指法向量::default();
334 for i in 0..(chars.len() - 1) {
335 let pair = (chars[i], chars[i + 1]);
336 if 指法标记.同手.contains(&pair) {
337 指法向量[0] += 1;
338 }
339 if 指法标记.同指大跨排.contains(&pair) {
340 指法向量[1] += 1;
341 }
342 if 指法标记.同指小跨排.contains(&pair) {
343 指法向量[2] += 1;
344 }
345 if 指法标记.小指干扰.contains(&pair) {
346 指法向量[3] += 1;
347 }
348 if 指法标记.错手.contains(&pair) {
349 指法向量[4] += 1;
350 }
351 }
352 for i in 0..(chars.len() - 2) {
353 let triple = (chars[i], chars[i + 1], chars[i + 2]);
354 if triple.0 == triple.1 && triple.1 == triple.2 {
355 指法向量[5] += 1;
356 }
357 }
358 result.push(指法向量);
359 }
360 result
361 }
362}
363
364#[derive(Debug, Clone)]
366pub struct 错误 {
367 pub message: String,
368}
369
370impl From<String> for 错误 {
371 fn from(value: String) -> Self {
372 Self { message: value }
373 }
374}
375
376impl From<&str> for 错误 {
377 fn from(value: &str) -> Self {
378 Self {
379 message: value.to_string(),
380 }
381 }
382}
383
384impl From<io::Error> for 错误 {
385 fn from(value: io::Error) -> Self {
386 Self {
387 message: value.to_string(),
388 }
389 }
390}
391
392impl From<serde_json::Error> for 错误 {
393 fn from(value: serde_json::Error) -> Self {
394 Self {
395 message: value.to_string(),
396 }
397 }
398}
399
400impl From<错误> for JsError {
401 fn from(value: 错误) -> Self {
402 JsError::new(&value.message)
403 }
404}