同步: 最近刚来渠道, 方案将自己之前在其他当地发的文章搬运 (同步) 过来.

首发日期2024-03-04, 以下为原文内容.


(同步) 多渠道拼音输入法软件的开发

拼音输入法从上个世纪开展到现在, 现已开展了几十年了, 技能上现已非常成熟了. 换句话说, 便是实践上没多少技能含量, 随便来个人就能手搓一个.

(同步) 多渠道拼音输入法软件的开发

本文介绍一个简略的多渠道拼音输入法软件的规划和完成, 支撑 GNU/Linux (ibus) 渠道 (PC) 和 Android 渠道 (手机).

目录

  • 1 中文输入法简介
  • 2 全体架构规划
    • 2.1 数据
    • 2.2 拼音中心
    • 2.3 图形用户界面
    • 2.4 体系输入法接口与运用
  • 3 具体完成栗子
    • 3.1 架构规划
    • 3.2 拼音中心: 查表+急进学习战略
    • 3.3 PC 渠道的界面
    • 3.4 Android 渠道的界面
    • 3.5 GNU/Linux 运用 (ibus)
    • 3.6 Android 运用
    • 3.7 安全规划
    • 3.8 输入丈量
  • 4 总结与展望

1 中文输入法简介

  • 为什么需求输入法 ?

    省流: 由于汉字数量太多了.

    英文输入计算机非常简略, 由于英文字母只要 26 个, 完全能够在键盘上摆下 26 个按键, 然后按一个按键就输入对应的英文字母.

    可是, 现在 (现代汉语/简体中文) 常用的汉字就有 3000/5000/7000 个. 一组简略的丈量数据: 常用 3000 汉字占中文文本中呈现的所有汉字的 99%, 常用 5000 汉字占 99.9%, 常用 7000 汉字占 99.99%. 剩余还有几万个, 乃至更多的汉字, 可是很少见了.

    怎么输入几千个不同的汉字, 便是一个问题了. 因此发生了许多种不同的中文输入法.

  • 中文输入法有哪些 ?

    依据输入方式能够分为: 键盘输入 (包含实体键盘和屏幕接触键盘), 语音输入 (语音识别), 手写输入, 光学字符识别 (OCR) 等. 未来或许还有脑电波输入 (脑机接口).

    键盘输入有: 拼音输入法, 形码输入法 (比方 五笔), 音形结合 (拼音+形码) 等.

    尽管有许多种不同的输入法, 但现在拼音输入法仍然是运用最多的.

  • 拼音输入法有哪些 ?

    拼音输入法能够分为 全拼双拼.

    全拼便是输入完好的拼音 (比方 qiong), 也包含简拼 (便是省略一部分拼音).

    双拼便是每个拼音对应两个按键 (比方 qs). 双拼有多种不同的具体方案, 比方 自然码.

  • 拼音输入法有哪些首要挑战 ?

    省流: 重码 (同音字).

    常用汉字有几千个那么多, 可是拼音 (一般话, 不带腔调) 只要 400 多个. 所以必定存在一个拼音对应多个汉字的状况, 夸张的时分一个拼音对应 100 多个汉字.

    翻页查找需求的汉字必定很慢, 会大大降低输入效率.

    面对用户这个语焉不详的谜语人, 拼音输入法必须想方设法的去猜, 用户到底想输入什么 ? 然后把用户想输入的东西, 在候选项列表里面尽量往前放, 最好放在第一个.

2 全体架构规划

(同步) 多渠道拼音输入法软件的开发

作为一个支撑多渠道的拼音输入法, 全体上可分为渠道无关的部分, 和渠道相关的部分.

渠道无关的部分包含数据, 以及拼音中心. 在各个渠道上都是通用的.

渠道相关的部分包含图形用户界面, 以及体系输入法接口. 最终需求一个适应相应渠道的运用, 来把这些东西装进去.

2.1 数据

输入法中心所需的数据, 以及用户数据库 (学习功用).

比方拼音数据 (拼音和汉字的对应联络), 汉字频率数据, 词库, 言语大模型等. 具体取决于中心运用的方法.

这部分数据需求专门搜集, 整理, 准备.

2.2 拼音中心

完成拼音到汉字的转换 (这也是输入法的中心功用).

具体能够运用多种方法. 简略的比方查表, 杂乱的比方运用 AI 技能 (言语大模型) 等.

2.3 图形用户界面

不同的设备 (比方 PC, 手机) 需求不同的用户界面.

  • PC 渠道 (运用 键盘, 鼠标操作, 一般有 大屏显现器) 具体的设备形态包含: 台式机, 笔记本, 迷你主机 等.

    用户界面首要是候选框窗口, 需求跟随文本光标的方位移动.

  • 手机渠道: 用户界面首要是屏幕底部的接触键盘.

2.4 体系输入法接口与运用

不同的操作体系 (比方 GNU/Linux, Android, Windows) 具有各自不同的输入法接口, 以及运用格局.

  • GNU/Linux (PC) 渠道: 体系接口 (输入法结构) 有 ibus, fcitx 等.

    通常体系具有软件包办理器 (比方 pacman, apt, rpm 等). 各个软件由软件包办理器一致安装和升级, 并处理软件包之间的依赖联络.

  • Android (手机) 渠道: 体系接口是 Android 输入法结构.

    运用的格局是 apk, 编程言语一般是 JVM (比方 java 或 kotlin).

  • Windows (PC) 渠道: 体系接口是 TSF 输入法结构.

    运用格局是 .exe 可执行程序.

3 具体完成栗子

好, 上面把理论部分讲完了, 下面说一个具体的完成.

3.1 架构规划

技能选型的首要目标:

  • (1) 低成本, 快速开发.

    这里是指开发的低成本. 运转功用 (运转速度快, 内存占用小) 相对不重要. 用户体会相对不重要. 也便是说, 这个软件首要是为开发者而开发的.

  • (2) 跨渠道.

    所选技能应该能够支撑多个渠道, 尽量在不同的渠道之间多共享代码.

  • (3) 低门槛.

    所选技能应该简略学习, 简略入门, 简略上手, 具有大量的开发者.

没错, 说的便是 web 技能 ! 首要编程言语为 JavaScript.

(同步) 多渠道拼音输入法软件的开发

拼音中心运用 deno (fresh) 运转环境, 编程言语 TypeScript. deno 是一个相似 node 的 js 运转环境, 运用 rust 编写. 运用 deno 开发比运用 node 更简略, 所以挑选 deno. 数据库运用 deno-kv, 底层依据 sqlite.

用户界面运用 vue 结构开发, 经典的 web 技能: js + HTML + CSS. 尽管 PC 和手机的界面需求别离开发, 但由于都在一个 vue 项目中, 两个界面之间也共享了许多代码.

electronjs 是一个依据 chromium 浏览器的壳, 支撑 GNU/Linux 渠道, 担任把 vue 开发的界面显现出来. 艾刷 (librush) 模块担任与 ibus 输入法结构的接口.

Android 运用运用 WebView (背面仍是 chromium) 把 vue 界面显现出来. 一起担任体系输入法接口 (Android 输入法结构).

代码行数计算 (cloc): pmim-server 1936 行 (TypeScript), ui-vue 2396 行 (vue/js), pmim-ibus/electronjs 227 行 (js), librush 1222 行 (rust), pmim-apk 531 行 (kotlin). 代码总数 6312 行 (100%), 渠道无关部分 4332 行 (68.6%), 渠道相关部分 1980 行 (31.4%), GNU/Linux 渠道代码 1449 行 (23.0%), Android 渠道代码 531 行 (8.4%).

能够看到, 在这个架构之下, 大部分代码都是渠道无关的. 特别是 Android 渠道只需求很少的渠道支撑代码.

3.2 拼音中心: 查表+急进学习战略

相关文章:

拼音数据从 Unicode 数据库中提取. 词库运用了一个 6 万个词的很小的词库. 拼音切分部分, 完成了双拼 (自然码), 以及自定义双拼表. 拼音转汉字部分, 运用了最简略的查表法, 便是直接查词库.


急进的学习战略, 便是用户输入的东西 永远 优先于内置词库. 会在用户数据库存储用户输入内容的时刻和频率 (次数), 查询候选项时, 会依据最近运用时刻 (7 天内) 和频率排序.

用户数据库存储在本地, 关于更具体的安全分析请见 3.7 章节.

(同步) 多渠道拼音输入法软件的开发

比方, 第一次尝试输入 “贫民小水滴”, 由于词库中只要 “贫民”, 所以候选项如图所示.

(同步) 多渠道拼音输入法软件的开发

输入一次之后, 再次输入, 用户数据库中就有了这个词. 这便是简略的学习功用.

跟着运用时刻的增加, 用户数据的堆集, 输入法会变的越来越好用.

3.3 PC 渠道的界面

相关文章:

(同步) 多渠道拼音输入法软件的开发

候选框窗口如图所示. 候选框窗口需求跟随文本光标的方位移动, 并依照需求显现躲藏.

中间显现原始输入 (双拼), 上方显现对应的全拼. 下方显现候选项, 每页 10 个, 按 1 ~ 0 数字键输入对应的候选项. 右侧显现有候选项的页码, 总页数. 按 , . 键翻页. 空格键输入第一个候选项. Esc 键撤销输入.

由于这个界面是依据 vue 开发的, 对这个界面进行个性化修正应该是很简略的.

3.4 Android 渠道的界面

(同步) 多渠道拼音输入法软件的开发

这个界面担任卖萌. 点击上方的一行字切换不同的输入界面. 右上角的按钮用来封闭软键盘.

(同步) 多渠道拼音输入法软件的开发

英文键盘 (默许). 左上角 shift 键 (切换大小写), 右上角退格键 (backspace), 下方大大的空格键, 右下角回车键 (enter).

(同步) 多渠道拼音输入法软件的开发

英文键盘 (shift).

关于键盘布局的问题, 这个键盘布局被窝称为 abcd7109. 这其实是一种很复古的规划, 由于在 qwerty 键盘布局呈现之前, 打字机的键盘是依照英文字母的顺序排列的.

对应源代码 (pmim-ibus/ui-vue/src/im2/c/键盘/键盘布局.js):

// 定义键盘布局 (主键盘): abcd7109
export const 布局 = [
  // 第 1 行: 7
  [
    ["a", "A"],
    ["b", "B"],
    ["c", "C"],
    ["d", "D"],
    ["e", "E"],
    ["f", "F"],
    ["g", "G"],
  ],
  // 第 2 行: 10
  [
    ["h", "H"],
    ["i", "I"],
    ["j", "J"],
    ["k", "K"],
    ["l", "L"],
    ["m", "M"],
    ["n", "N"],
    ["o", "O"],
    ["p", "P"],
    ["q", "Q"],
  ],
  // 第 3 行: 9 + 1
  [
    ["r", "R"],
    ["s", "S"],
    ["t", "T"],
    ["u", "U"],
    ["v", "V"],
    ["w", "W"],
    ["x", "X"],
    ["y", "Y"],
    ["z", "Z"],
    [".", "/"],
  ],
  // 第 4 行: (2)
  [
    ["-", "_"],
    [",", ":"],
  ],
];

所以, 想要修正键盘布局是很简略的.


(同步) 多渠道拼音输入法软件的开发

拼音输入 (默许状况). 左上角的 shift 键换成了 “重输” 键, 按下会清空悉数拼音.

(同步) 多渠道拼音输入法软件的开发

拼音输入状况, 上方显现输入的拼音 (双拼) 和候选项.

(同步) 多渠道拼音输入法软件的开发

数字键盘.

(同步) 多渠道拼音输入法软件的开发

ASCII 符号键盘 (英文标点). 此处包含 ASCII 的悉数符号 (32 个, 空格除外), 对写代码友爱. 从此在手机上也能好好写代码啦 ~~

(同步) 多渠道拼音输入法软件的开发

中文标点以及一些符号.


此处 Android 软键盘界面的规划, 首要是为了简略. 各个键盘的职责分工清晰, 键盘之间的切换简略直接, 保持一致. 其他输入法各种键盘之间的杂乱跳转逻辑, 窝是受不了的, 一瞬间在这里点这个键, 一瞬间到那里点那个键, 一瞬间就绕晕了, 不知道自己在哪里 .. .

3.5 GNU/Linux 运用 (ibus)

相关文章:

此处挑选了 ibus 输入法结构.

为什么要挑选 ibus 呢 ? 由于窝运用 GNOME 桌面环境, GNOME 默许集成了 ibus, 所以运用起来比较便利. 而且, 尽管 ibus 的拼音输入法 (ibus-libpinyin) 窝感觉不太好用, 可是 ibus 本身多年来仍是很稳的, 基本上没出过大问题. 尽管还有 fcitx 输入法结构, 可是在 GNU/Linux 桌面环境的软件生态中, ibus 相对更普及一些. 乃至 fcitx 本身也挑选了兼容 ibus.

ibus 本身运用 C 和 python 开发, 可是运用 D-Bus 协议连接各个组件. 本输入法尽管运用了 ibus 输入法结构, 可是并没有对 ibus 有代码上的直接依赖, 而是挑选从 D-Bus 开始, 兼容 ibus 的协议 (艾刷 librush 模块).

在 web 运转环境的挑选上, 窝喜爱 chromium 浏览器内核, 所以排除了 tauri, 挑选了 electronjs. electronjs 更加成熟稳定, 有 vscode 这个大厂的产品做代表, 而且 electronjs 不必自己编译, 直接拿过来就能用, 比较便利. 在 GNU/Linux 体系上通常都有软件包办理器进行依赖办理, 这能够抵消 electronjs 的大部分缺陷.

专门为 electronjs 编写的代码只要 227 行 (js).

3.6 Android 运用

相关文章:

在 Android 体系就要运用 Android 输入法结构. Android 运用是运用 Android Studio 创建的一般运用, 运用 kotlin 编程言语.

在 Android 运用 WebView 显现网页是标准操作, 也便是运用体系自带的浏览器内核 (chromium). 在国产手机 (比方 MIUI) 上即便不 root, 也能够经过安装 Android System WebView 这个 apk 来更新体系 WebView 内核.

(同步) 多渠道拼音输入法软件的开发

留意版别号.

在 apk 中打包自带一个浏览器内核, 不是做不到, 可是太麻烦了, 而且比较体系 WebView 没有显着长处.


在 Android 运转 deno 运用了 proot. 这样能够让拼音中心运转起来.

运用 proot 并不是最好的方法, 可是能够承受, 功用并不差.

3.7 安全规划

相关文章:

此处的安全 (security), 是指信息安全, 网络安全, 黑客进犯这方面的.

事前声明, 肯定的安全是不或许完成的. 开发者能够做的, 是让一个软件合理的, 足够的安全, 不要呈现严峻安全漏洞罢了.

在此具体描述安全方面的规划, 是为了能够公开的对其进行检查. 如果发现这里有安全漏洞, 记住联络窝哦 ~~

  • (1) 用户数据库的存储. 用户数据库保存了一部分用户输入的内容, 这部分是敏感数据, 需求重点保护.

    用户数据库运用 deno-kv, 底层对应 sqlite 数据库. deno.com/kv

    • 在 GNU/Linux 渠道, 用户数据库文件的方位是:

      > ls -l ~/.config/pmim/pmim_user.db
      -rw-r--r-- 1 s2 s2 2977792  3月 3日 20:29 /home/s2/.config/pmim/pmim_user.db
      

      这位于用户的主目录中, 而用户主目录默许的权限是 700:

      > ls -ld ~
      drwx------ 1 s2 s2 1136  3月 4日 05:28 /home/s2/
      

      也便是说只要用户自己能够拜访. 所以, 在体系环境安全 (没有其他恶意软件悄悄读取这个数据库) 的前提下, 这个数据库文件是安全的.


    • 在 Android 渠道, 用户数据库文件的方位是: /sdcard/Android/data/io.github.fm_elpac.pmim_apk/files/pmim/pmim_user.db

      这个是 Android/data/包名 目录, 只要运用自己能够拜访, 其他运用无法拜访. 所以, 在体系环境安全 (比方没有 root) 的前提下, 这个数据库文件是安全的.

  • (2) 拼音中心 (pmim-server) 的 HTTP 接口. 用户界面经过 HTTP 接口 (REST) 对拼音中心进行恳求.

    拼音中心对 HTTP 接口 (API) 的调用运用 token 认证, 对应源代码 (pmim/server/routes/pmims_api/_middleware.ts):

    // /pmims_api/* header: x-token
    // 检查口令 (认证)
    export async function handler(
      req: Request,
      ctx: FreshContext<状况>,
    ) {
      // 首先尝试从 headers 中获取 token
      let token = req.headers.get(HH_TOKEN);
      // 其次从 cookie 中获取 token
      if (null == token) {
        token = getCookies(req.headers)["x_token"];
      }
      // 检查 token 是否正确
      if ((null == token) || (!检查口令(token))) {
        return new Response("HTTP 403", {
          status: 403,
        });
      }
      return await ctx.next();
    }
    

    检查口令运用定长时刻的比较函数, 这是为了对抗时刻侧信道的进犯, 对应源代码 (pmim/server/pmims/auth/token.ts):

    import { timingSafeEqual } from "$std/crypto/timing_safe_equal.ts";
    // 内存中保存的口令
    const etc = {
      口令: new Uint8Array(),
    };
    export function 检查口令(t: string): boolean {
      const d = new TextEncoder().encode(t);
      return timingSafeEqual(d, etc.口令);
    }
    

    token 运用真随机数据生成, 对应源代码 (pmim/server/pmims/auth/token.ts):

    async function 获取随机数据(): Promise<string> {
      // 64 Byte, 512bit 随机数据
      const a = new Uint8Array(64);
      crypto.getRandomValues(a);
      // base64(sha256())
      const h = await crypto.subtle.digest("SHA-256", a);
      return encodeBase64(h);
    }
    export function 口令文件途径(): string {
      const 目录 = Deno.env.get(ENV_XDG_RUNTIME_DIR)!;
      return join(目录, FP_TOKEN);
    }
    export async function 初始化口令() {
      const 口令文件 = 口令文件途径();
      logi(" token: " + 口令文件);
      const 口令 = await 获取随机数据();
      // 存储口令
      etc.口令 = new TextEncoder().encode(口令);
      await 建上级目录(口令文件);
      await Deno.writeTextFile(口令文件, 口令);
    }
    

    此处运用的是 Web Crypto API developer.mozilla.org/en-US/docs/….

    一起, 拼音中心只监听 127.0.0.1 IP 地址, 这意味着只要本机的程序能够连接. 对应源代码 (pmim/server/pmims/conf.ts):

    export const 监听地址 = "127.0.0.1";
    

    源代码 (pmim/server/fresh.config.ts):

    export default function getConfig() {
      return defineConfig({
        plugins: [tailwind()],
        server: {
          port: 获取端口(),
          hostname: 监听地址,
          onListen,
        },
      });
    }
    

    • 在 GNU/Linux 渠道, 口令文件的存储方位是:

      > ls -l $XDG_RUNTIME_DIR/pmim/server_token
      -rw-r--r-- 1 s2 s2 44  3月 3日 22:27 /run/user/1000/pmim/server_token
      

      XDG_RUNTIME_DIR 的默许权限是 700:

      > ls -ld $XDG_RUNTIME_DIR
      drwx------ 19 s2 s2 660  3月 4日 06:21 /run/user/1000/
      

      相同的, 只要用户自己能够拜访.

      electronjs 读取口令文件的源代码是 (pmim-ibus/electronjs/main.js):

      // 读取 deno/fresh server http token
      async function read_token() {
        const xrd = process.env["XDG_RUNTIME_DIR"];
        const 口令文件 = path.join(xrd, "pmim/server_token");
        logi(" read token: " + 口令文件);
        return await readFile(口令文件, { encoding: "utf8" });
      }
      

    • 在 Android 渠道, 口令文件的存储方位是: /sdcard/Android/data/io.github.fm_elpac.pmim_apk/files/pmim/server_token

      相同的, 只要运用自己能够拜访.

      WebView 中的页面读取口令文件的源代码是 (pmim-apk/p/app/src/main/java/io/github/fm_elpac/pmim_apk/im/ImView.kt):

      // 读取 pmim-server 的口令
      @JavascriptInterface
      fun pm_口令(): String {
        // /storage/emulated/0/Android/data/io.github.fm_elpac.pmim_apk/files/pmim/server_token
        val 外部文件目录 = p.getExternalFilesDir(null)!!
        val 口令文件 = File(外部文件目录, "pmim/server_token")
        println("ImView: 口令文件 " + 口令文件.getAbsolutePath())
        return 口令文件.readText()
      }
      

    上述这套机制完成了:

    • (1) 每次启动后都从头生成足够长的随机 token.
    • (2) 只要本机的运用 (127.0.0.1) 才或许恳求中心的 HTTP 接口.
    • (3) (GNU/Linux) 只要用户自己的运用 (能够读取口令文件) 才能够恳求中心的接口. 本机其他用户无法拜访.
    • (4) (Android) 只要运用自己才能够恳求中心的接口. 本机其他运用无法拜访.

  • (3) 艾刷与拼音中心之间的通讯 (仅适用于 GNU/Linux 渠道).

    艾刷与拼音中心之间运用 UNIX socket, 对应的文件途径是:

    > ls -l $XDG_RUNTIME_DIR/pmim/us
    srwxr-xr-x 1 s2 s2 0  3月 3日 22:27 /run/user/1000/pmim/us=
    

    相同的, 只要用户自己能够拜访.


未来, 还能够考虑运用 deno 权限, flatpak 沙箱 (sandbox) 等安全机制, 进一步增强运用的安全性 (比方完全制止网络拜访).

3.8 输入丈量

俗话说, 没有丈量就没有发言权. 拼音输入法运用 web 技能 (JavaScript) 开发, 功用会不会很差 ?

拼音中心完成了对输入的简略丈量功用. 本章节来答复这些问题.

输入丈量功用完成了对输入字数, 候选项序号, 中心的拼音切分和拼音转汉字的呼应时刻等的计算. 每分钟发生一条丈量数据.

丈量方法, 比方拼音中心的呼应时刻对应源代码 (pmim-ibus/ui-vue/src/输入/输入.js):

  // 调用接口进行拼音切分
  async _拼音切分(新) {
    // 输入丈量
    const d1 = new Date();
    const r1 = await pm_pin_yin(新);
    const d2 = new Date();
    this._mt_pin_yin.push(丈量时刻(d1, d2));
// 省略
// 丈量时刻 (Date) 回来 ms
function 丈量时刻(d1, d2) {
  return d2.getTime() - d1.getTime();
}

运用 js 内置的 Date 进行时刻丈量, 精度在毫秒等级.


输入丈量接口的原始数据相似这样 (有省略):

> curl -H x-token:(cat /run/user/1000/pmim/server_token) -X POST http://127.0.0.1:20200/pmims_api/m -d '{"d": "2024-03-03"}' | jq '.'
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 37051  100 37032  100    19   789k    414 --:--:-- --:--:-- --:--:--  804k
{
  "2024-03-03": {
    "分钟": 144,
    "计算": {
      "c.c": 1347,
      "c.c/m": 1,
      "c.c/M": 25,
      "c.n": 1347,
      "c.n/m": 1,
      "c.n/M": 25,
      "c.t": 2498,
      "c.t/m": 1,
      "c.t/M": 48,
      "c.t_M": 4,
      "c.t_m": 1,
      "i.c": 256,
      "i.c/m": 0,
      "i.c/M": 24,
      "i.c1": 74,
      "i.c1/m": 0,
      "i.c1/M": 12,
      "i.c1_M": 12,
      "i.c1_m": 0,
      "i.c1_n": 1279,
      "i.c1_n/m": 1,
      "i.c1_n/M": 24,
      "i.c_M": 13,
      "i.c_m": 0,
      "i.cn": 182,
      "i.cn/m": 0,
      "i.cn/M": 24,
      "i.cn_M": 13,
      "i.cn_m": 0,
      "i.cn_n": 141,
      "i.cn_n/m": 2,
      "i.cn_n/M": 11,
      "i.n": 1420,
      "i.n/m": 1,
      "i.n/M": 27,
      "i.n_M": 3,
      "i.n_m": 1,
      "t.c": 69075,
      "t.c/m": 13,
      "t.c/M": 1631,
      "t.c_M": 228,
      "t.c_m": 4,
      "t.c_n": 2613,
      "t.c_n/m": 1,
      "t.c_n/M": 50,
      "t.p": 96648,
      "t.p/m": 25,
      "t.p/M": 2021,
      "t.p_M": 112,
      "t.p_m": 3,
      "t.p_n": 5092,
      "t.p_n/m": 2,
      "t.p_n/M": 96
    },
    "均匀": {
      "c.n": 9.354166666666666,
      "c.c": 9.354166666666666,
      "c.t": 17.34722222222222,
      "i.n": 1.0541945063103193,
      "i.c": 0.18028169014084508,
      "i.c1": 0.05785770132916341,
      "i.cn": 1.2907801418439717,
      "t.p": 18.98036135113904,
      "t.c": 26.435132032146957
    },
    "数据": {
      "1326": {
        "c.c": 14,
        "c.n": 14,
        "c.t": 24,
        "c.t_M": 2,
        "c.t_m": 1,
        "i.c": 3,
        "i.c1": 0,
        "i.c1_M": 0,
        "i.c1_m": 0,
        "i.c1_n": 13,
        "i.c_M": 3,
        "i.c_m": 0,
        "i.cn": 3,
        "i.cn_M": 3,
        "i.cn_m": 0,
        "i.cn_n": 2,
        "i.n": 15,
        "i.n_M": 2,
        "i.n_m": 1,
        "t.c": 569,
        "t.c_M": 47,
        "t.c_m": 6,
        "t.c_n": 25,
        "t.p": 860,
        "t.p_M": 97,
        "t.p_m": 4,
        "t.p_n": 48
      },
      "1352": {
        "c.c": 2,
        "c.n": 2,
        "c.t": 2,
        "c.t_M": 1,
        "c.t_m": 1,
        "i.c": 0,
        "i.c1": 0,
        "i.c1_M": 0,
        "i.c1_m": 0,
        "i.c1_n": 2,
        "i.c_M": 0,
        "i.c_m": 0,
        "i.n": 2,
        "i.n_M": 1,
        "i.n_m": 1,
        "t.c": 32,
        "t.c_M": 21,
        "t.c_m": 11,
        "t.c_n": 2,
        "t.p": 129,
        "t.p_M": 58,
        "t.p_m": 11,
        "t.p_n": 4
      },

调用接口能够对某一天的丈量数据进行计算. 其间 分钟 是指多少分钟内有输入, 由于每分钟发生一条丈量数据, 如果这一分钟之内没有进行输入, 就没有对应的丈量数据. 计算 是对一天的所有数据进行分项累计. 均匀 是一天之内的均匀值. 数据 便是列出所有的原始丈量数据, 每分钟一条.

此处的计算分析功用很简略, 可是由于以 JSON 格局输出了原始丈量数据, 能够很简略的将数据导出, 然后运用更强大的工具 (比方 python) 进行计算分析.


窝这边最近几天的输入丈量数据如下表 (GNU/Linux 渠道, ibus):

日期 分钟 字数 拼音切分 拼音转汉字 候选项
2024-02-24 119 1284 22.7 38.1 0
2024-02-25 29 305 21.4 38.7 0.414
2024-02-26 46 448 20.7 33.8 0.121
2024-02-27 112 1798 20.1 33.6 0.264
2024-02-28 236 1887 19.5 26.8 0.112
2024-02-29 228 2647 20.1 24.6 0.075
2024-03-01 30 162 20.5 33.1 0.014
2024-03-02 25 273 18.3 24.5 0.084
2024-03-03 144 2498 19.0 26.5 0.181
2024-03-04* 132 2337 17.4 25.0 0.211

注:

  • 日期: 丈量数据对应的日期 (搜集悉数 24 小时).

  • 分钟: 在多少分钟内有输入 (每分钟发生一条丈量数据).

  • 字数: 输入的总字数.

  • 拼音切分 (ms): 中心进行一次拼音切分的均匀呼应时刻.

  • 拼音转汉字 (ms): 中心进行一次拼音转汉字 (查询候选项) 的均匀呼应时刻.

  • 候选项: 均匀候选项序号.

    输入时挑选的候选项的序号 (从 0 开始) 的均匀值.

  • *: 当天的数据并不完好.


很显着, 输入丈量功用是 2024-02-24 开发完成的, 所以并没有之前的数据. 这些是最近几天窝在真实运用场景之下取得的丈量数据, 比方写这篇文章.

拼音切分的均匀时刻基本稳定在大约 20 毫秒. 拼音转汉字后来进行了一点优化, 时刻有所下降, 现在稳定在大约 30 毫秒. 这个功用并不算好, 由于如果运用要达到 60fps 的帧率, 每一帧的时刻只要 16.6ms.

可是这是一个能够承受的功用. 由于一般人的击键速度难以超过每秒 10 次, 所以 100ms 以内的呼应时刻是能够承受的. 而且这是在一个功用并不算好的硬件上取得的结果, 窝运用的是 9 年前的寒酸笔记本 (CPU i5-6200U). 在更新的硬件上或许会取得更好的结果.

(同步) 多渠道拼音输入法软件的开发

这是窝随手做的一个击键速度测验 (英文), 最高击键速度每秒 9 次, 每分钟 314 次 (均匀 5.2 次/秒).


均匀候选项序号, 这个最理想的状况下是 0, 意味着每次输入的候选项都是第一项. 现在这个值大约在 0.1 ~ 0.2 之间, 也便是说大部分输入 (80%) 的候选项是第一项. 这说明输入法中心的功用并不算很差.

现在运用输入法的时刻并不长, 用户数据还没有足够的堆集. 后续跟着不断的运用, 这个值会逐步下降的.

(同步) 多渠道拼音输入法软件的开发

这是在一只几年前的旧手机上的运转状况, 内存和存储的占用都在可承受的范围内. 片面感触也能流畅运转.

4 总结与展望

(同步) 多渠道拼音输入法软件的开发

图片标题: 《拼 2024: 方圆之间, 刺破命运》

本文完成了一个简略的多渠道拼音输入法, 支撑 GNU/Linux (ibus) 渠道 (PC), 和 Android 渠道 (手机). 这个输入法的完好源代码只要几千行, 开发这个输入法也只用了十几天的时刻.

开发这个拼音输入法首要有两个目的:

  • (1) 自用. 现在这个拼音输入法现已覆盖了窝日常运用的所有设备, 包含一个笔记本 (ArchLinux), 以及 3 只手机 (Android 10, Android 11, Android 12). 从此, 窝就能够只运用自己的拼音输入法啦 ~

  • (2) 用于科普拼音输入法的作业原理.

本输入法依据 web 技能开发, 首要编程言语为 JavaScript, 具有低成本, 快速开发, 跨渠道, 低门槛等长处. 经过实践丈量, web 技能的功用并不差, 完全能够承受.

输入法需求处理用户输入的敏感数据, 在安全方面需求格外留意. 本文对本输入法的安全规划进行了具体描述.

这个输入法在技能上和功用上都非常简略 (粗陋), 拼音中心只运用了最简略的查表法. 可是是能够实践运用的, 比方写这篇文章.

对贫民来说, 廉价, 能用, 便是好.

后续在技能升级方面, 方案一步到位: 运用本地运转的言语大模型.


本文运用 CC-BY-SA 4.0 许可发布.