mirror of
https://github.com/fumiama/emozi.git
synced 2026-06-05 00:32:48 +08:00
259 lines
7.5 KiB
Go
259 lines
7.5 KiB
Go
package emozi
|
||
|
||
import (
|
||
base14 "github.com/fumiama/go-base16384"
|
||
)
|
||
|
||
type 声母枚举 uint8
|
||
|
||
// String 国际音标
|
||
func (sm 声母枚举) String() string {
|
||
a := sm * 3
|
||
b := a + [...]声母枚举{1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 2, 3, 1, 2, 3, 1, 1, 2, 3, 1, 1, 1, 1, 1}[sm]
|
||
s := []rune("p pʰ m f t tʰ n l k kʰ x tɕ tɕʰɕ ʈʂ ʈʂʰʂ ɻ ts tsʰs j w ɥ 0 ")[a:b]
|
||
return string(s)
|
||
}
|
||
|
||
const (
|
||
声母b 声母枚举 = iota
|
||
声母p
|
||
声母m
|
||
声母f
|
||
声母d
|
||
声母t
|
||
声母n
|
||
声母l
|
||
声母g
|
||
声母k
|
||
声母h
|
||
声母j
|
||
声母q
|
||
声母x
|
||
声母zh
|
||
声母ch
|
||
声母sh
|
||
声母r
|
||
声母z
|
||
声母c
|
||
声母s
|
||
声母yi
|
||
声母w
|
||
声母yu
|
||
声母0
|
||
)
|
||
|
||
// 声母 可以有多个颜文字与之对应 但有时系统可能无法显示
|
||
var 声母 = [...][]string{
|
||
// b: 鼻笔八
|
||
{"👃", "🖊️", "🎱"},
|
||
// p: 跑跑跑票票牌牌
|
||
{"🏃", "🏃♀️", "🏃♂️", "🎫", "🎟️", "🃏", "🎴"},
|
||
// m: 马马猫猫猫猫锚面面门麦米木蜜帽帽帽麦
|
||
{"🐴", "🐎", "🐱", "🐈", "🐈⬛", "😺", "⚓️", "🍜", "🍝", "🚪", "🌾", "🍚", "🪵", "🍯", "🎩", "👒", "🧢", "🎙️"},
|
||
// f: 斧肺
|
||
{"🪓", "🫁"},
|
||
// d: 刀豆蛋灯灯洞
|
||
{"🔪", "🫘", "🥚", "💡", "🪔", "🕳️"},
|
||
// t: 腿糖兔兔桶桃
|
||
{"🦵", "🍬", "🐰", "🐇", "🪣", "🍑"},
|
||
// n: 奶鸟牛
|
||
{"🥛", "🐦", "🐮"},
|
||
// l: 鹿鹿冷龙龙莲
|
||
{"🦌", "🫎", "🥶", "🐲", "🐉", "🪷"},
|
||
// g: 瓜鼓龟狗勾跪跪跪
|
||
{"🍉", "🥁", "🐢", "🐶", "🪝", "🧎", "🧎♀️", "🧎♂️"},
|
||
// k: 哭裤
|
||
{"😭", "👖"},
|
||
// h: 花花花花花花花花火虎虎猴猴
|
||
{"🌹", "🌼", "💐", "🌷", "🌸", "🌺", "🥀", "🪻", "🔥", "🐯", "🐅", "🐒", "🐵"},
|
||
// j: 加减酒酒鸡鸡剑姜镜脚
|
||
{"➕", "➖", "🍷", "🍺", "🐔", "🐓", "🗡️", "🫚", "🪞", "🦶"},
|
||
// q: 茄钱钱钱钱钱棋
|
||
{"🍆", "💰", "💴", "💵", "💶", "💸", "♟️"},
|
||
// x: 下下虾虾虾雪星星星星熊象蟹
|
||
{"👇", "⬇️", "🦐", "🍤", "🦞", "❄️", "🌟", "✨", "⭐️", "💫", "🐻", "🐘", "🦀️"},
|
||
// zh: 猪猪针针
|
||
{"🐽", "🐷", "🪡", "💉"},
|
||
// ch: 茶茶车车车车床床除虫
|
||
{"🍵", "☕️", "🚗", "🚘", "🚙", "🛻", "🛏️", "🛌", "➗", "🐛"},
|
||
// sh: 水水书书书书书书上上上石山山山树树树蛇鼠鼠鼠珊18
|
||
{"💦", "💧", "📖", "📕", "📗", "📘", "📙", "📚", "⬆️", "☝️", "👆", "🪨", "⛰️", "🏔️", "🗻", "🌲", "🌳", "🌴", "🐍", "🐭", "🐀", "🐁", "🪸", "🔞"},
|
||
// r: 肉日日日
|
||
{"🥩", "🌞", "☀️", "🌅"},
|
||
// z: 左左左 c: 错错错错 s: 锁伞伞伞伞蒜
|
||
{"👈", "⬅️", "⬅"}, {"❌", "🙅", "🙅♀️", "🙅♂️"}, {"🔒", "🌂", "☔️", "⛱️", "☂️", "🧄"},
|
||
// yi: 羊羊牙药盐 w: 袜雾网碗 yu: 雨鱼鱼 0: 两种椅子
|
||
{"🐑", "🐐", "🦷", "💊", "🧂"}, {"🧦", "🌫️", "🕸️", "🥣"}, {"🐟", "🌧️", "🐠"}, {"🪑", "💺"},
|
||
}
|
||
|
||
func 低阶逆初始化(表 [][]string, 倍数 int) map[rune][]string {
|
||
m := make(map[rune][]string, len(表)*倍数)
|
||
for _, lst := range 表 {
|
||
for _, s := range lst {
|
||
k := []rune(s)[0]
|
||
m[k] = append(m[k], s)
|
||
}
|
||
}
|
||
return m
|
||
}
|
||
|
||
// 低阶逆声母 rune声母到声母的逆映射
|
||
var 低阶逆声母 = 低阶逆初始化(声母[:], 32)
|
||
|
||
func 逆初始化[T ~uint8](表 [][]string, 倍数 int) map[string]T {
|
||
m := make(map[string]T, len(表)*倍数)
|
||
for i, lst := range 表 {
|
||
for _, s := range lst {
|
||
m[s] = T(i)
|
||
}
|
||
}
|
||
return m
|
||
}
|
||
|
||
// 逆声母 声母到枚举的逆映射
|
||
var 逆声母 = 逆初始化[声母枚举](声母[:], 32)
|
||
|
||
type 韵母枚举 uint8
|
||
|
||
// String 国际音标
|
||
func (ym 韵母枚举) String() string {
|
||
return [...]string{
|
||
"ä", "ɔ", "ɤ", "i", "ɿ", "u", "y", "ɐɚ̯", "aɪ̯", "u̯aɪ̯", "eɪ̯", "u̯eɪ̯", "ɑʊ̯", "i̯ɑʊ̯",
|
||
"oʊ̯", "i̯oʊ̯", "i̯ä", "u̯ä", "u̯o", "i̯ɛ", "y̯ɛ", "an", "i̯ɛn", "u̯an", "y̯ɛn", "ən", "u̯ən",
|
||
"in", "yn", "ɑŋ", "i̯ɑŋ", "u̯ɑŋ", "ɤŋ", "iŋ", "u̯əŋ", "ʊŋ", "i̯ʊŋ",
|
||
}[ym]
|
||
}
|
||
|
||
const (
|
||
韵母a 韵母枚举 = iota
|
||
韵母o
|
||
韵母e
|
||
韵母yi
|
||
韵母ri
|
||
韵母wu
|
||
韵母yu
|
||
韵母er
|
||
韵母ai
|
||
韵母uai
|
||
韵母ei
|
||
韵母ui
|
||
韵母ao
|
||
韵母iao
|
||
韵母ou
|
||
韵母iu
|
||
韵母ia
|
||
韵母ua
|
||
韵母uo
|
||
韵母ie
|
||
韵母yue
|
||
韵母an
|
||
韵母ian
|
||
韵母uan
|
||
韵母yuan
|
||
韵母en
|
||
韵母un
|
||
韵母in
|
||
韵母yun
|
||
韵母ang
|
||
韵母iang
|
||
韵母uang
|
||
韵母eng
|
||
韵母ing
|
||
韵母ueng
|
||
韵母ong
|
||
韵母iong
|
||
)
|
||
|
||
// 韵母 仅由一种意象表示
|
||
var 韵母 = [...][]string{
|
||
{"😧", "🤔️"}, {"😲"}, {"😋"}, {"👔", "👗", "👕", "👚"}, {"🌞", "☀️", "🌅"},
|
||
{"🈚", "🌫️"}, {"🐟", "🌧️"}, {"👂"},
|
||
{"💟", "❤️", "💗", "💓", "🫶", "💕", "💖", "💘", "💙", "💚", "💛", "💜", "💝", "💞", "🧡"}, {"🥢"}, {"😩"}, {"🐢"},
|
||
{"🐱", "🐈", "🐈⬛", "😺"}, {"💊"}, {"🤮", "🤢"}, {"👉", "➡️"},
|
||
{"🦷"}, {"🧦"}, {"🌀"}, {"👴", "✌️"}, {"🌙", "🌕", "🌛", "🌝"}, {"🔐"}, {"🚬"}, {"🥣", "🍚"},
|
||
{"🔘", "⭕️"}, {"😐"}, {"😘", "💋"}, {"🎵"}, {"☁"}, {"👍"}, {"🐑"},
|
||
{"🥅", "🕸️"}, {"💡", "🪔"}, {"🦅"}, {"🐝"}, {"🌈"}, {"😳"}, // jiong 囧
|
||
}
|
||
|
||
// 低阶逆韵母 rune韵母到韵母的逆映射
|
||
var 低阶逆韵母 = 低阶逆初始化(韵母[:], 8)
|
||
|
||
// 逆韵母 韵母到枚举的逆映射
|
||
var 逆韵母 = 逆初始化[韵母枚举](韵母[:], 8)
|
||
|
||
type 声调枚举 uint8
|
||
|
||
// String 返回传统调名
|
||
func (t 声调枚举) String() string {
|
||
return [...]string{
|
||
"阴平", "阳平", "上声", "去声", "轻声",
|
||
}[t]
|
||
}
|
||
|
||
const (
|
||
阴平 声调枚举 = iota
|
||
阳平
|
||
上声
|
||
去声
|
||
轻声
|
||
)
|
||
|
||
var 声调 = [...][]string{{"🍉"}, {"🧗", "🧗♀️", "🧗♂️", "🦎"}, {"🐴", "🐎"}, {"😨"}, {"😯"}}
|
||
|
||
// 低阶逆声调 rune声调到声调的逆映射
|
||
var 低阶逆声调 = 低阶逆初始化(声调[:], 4)
|
||
|
||
// 逆声调 声调到枚举的逆映射
|
||
var 逆声调 = 逆初始化[声调枚举](声调[:], 4)
|
||
|
||
// 校验表 用 校验表长度 个unicode控制字符做校验和验证此序列是由本程序生成而非手写的
|
||
//
|
||
// 具体做法是先对后面的文本做crc32然后取 校验表长度^校验字节数 的模
|
||
var 校验表 = func() []rune {
|
||
x, err := base14.UTF16BE2UTF8(base14.StringToBytes("\x20\x0b\x20\x0c\x20\x0d\x20\x0e\x20\x0f\x20\x2a\x20\x2b\x20\x2c\x20\x2d\x20\x2e\x20\x60\x20\x61\x20\x62\x20\x63\x20\x64\x20\x65\x20\x66\x20\x68\x20\x69\x20\x6a\x20\x6b\x20\x6c\x20\x6d\x20\x6e\x20\x6f"))
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
return []rune(base14.BytesToString(x))
|
||
}()
|
||
|
||
// 校验表长度 25
|
||
var 校验表长度 = len(校验表)
|
||
|
||
// 校验字节数 默认为 3, 不得大于 3
|
||
const 校验字节数 = 3
|
||
|
||
// 校验模 校验表长度^校验字节数
|
||
var 校验模 = uint32(0)
|
||
|
||
// 校验倍数 校验表长度乘方表
|
||
var 校验倍数 = func() []uint32 {
|
||
tab := make([]uint32, 校验字节数)
|
||
tab[0] = 1
|
||
for i := 1; i < 校验字节数; i++ {
|
||
tab[i] = tab[i-1] * uint32(校验表长度)
|
||
}
|
||
校验模 = tab[校验字节数-1] * uint32(校验表长度)
|
||
return tab
|
||
}()
|
||
|
||
// 逆校验表 还原校验和用
|
||
var 逆校验表 = func() map[rune]uint8 {
|
||
m := make(map[rune]uint8, 64)
|
||
for i, c := range 校验表 {
|
||
m[c] = uint8(i)
|
||
}
|
||
return m
|
||
}()
|
||
|
||
// 逆部首后备 部首后备逆查表 一对多
|
||
var 逆部首后备 = func() map[string][]rune {
|
||
m := make(map[string][]rune, len(部首后备)*4)
|
||
for r, e := range 部首后备 {
|
||
if 无此字符(m[e], r) {
|
||
m[e] = append(m[e], r)
|
||
}
|
||
}
|
||
return m
|
||
}()
|