feat: 初始化文字马赛克生成器
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
import { describe, expect, it } from 'bun:test'
|
||||
import {
|
||||
generateMosaic,
|
||||
selectKeywords,
|
||||
type KeywordCandidate,
|
||||
} from './mosaic'
|
||||
|
||||
const SOURCE =
|
||||
'我一直以为记忆会忠实地保存一切,后来才发现,每一次回想都在重新编造过去。'
|
||||
|
||||
function retain(
|
||||
candidates: KeywordCandidate[],
|
||||
words: string[],
|
||||
): KeywordCandidate[] {
|
||||
return candidates.map((candidate) => ({
|
||||
...candidate,
|
||||
selected: words.includes(candidate.text),
|
||||
}))
|
||||
}
|
||||
|
||||
describe('selectKeywords', () => {
|
||||
it('优先提供中文实词候选并排除常见停用词', () => {
|
||||
const candidates = selectKeywords(SOURCE, 14, 1)
|
||||
const words = candidates.map((candidate) => candidate.text)
|
||||
|
||||
expect(words).toContain('记忆')
|
||||
expect(words).toContain('保存')
|
||||
expect(words).toContain('回想')
|
||||
expect(words).toContain('编造')
|
||||
expect(words).not.toContain('一直')
|
||||
expect(words).not.toContain('后来')
|
||||
})
|
||||
|
||||
it('在有候选词时至少自动保留一个', () => {
|
||||
const candidates = selectKeywords('风穿过废弃车站', 5, 1)
|
||||
|
||||
expect(candidates.some((candidate) => candidate.selected)).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('generateMosaic', () => {
|
||||
it('保留指定词语并彻底替换原标点', () => {
|
||||
const candidates = retain(selectKeywords(SOURCE, 14, 1), [
|
||||
'记忆',
|
||||
'保存',
|
||||
'回想',
|
||||
'编造',
|
||||
'过去',
|
||||
])
|
||||
const result = generateMosaic(SOURCE, candidates, {
|
||||
volume: 100,
|
||||
disorder: 58,
|
||||
seed: 42,
|
||||
})
|
||||
|
||||
expect(result.output).toContain('记忆')
|
||||
expect(result.output).toContain('保存')
|
||||
expect(result.output).toContain('回想')
|
||||
expect(result.output).toContain('编造')
|
||||
expect(result.output).toContain('过去')
|
||||
expect(result.output).not.toMatch(/[,。!?;:“”‘’()【】、]/u)
|
||||
})
|
||||
|
||||
it('将总可见长度维持在设定体量附近', () => {
|
||||
const candidates = selectKeywords(SOURCE, 14, 1)
|
||||
const result = generateMosaic(SOURCE, candidates, {
|
||||
volume: 100,
|
||||
disorder: 58,
|
||||
seed: 42,
|
||||
})
|
||||
const ratio = result.outputLength / result.inputLength
|
||||
|
||||
expect(ratio).toBeGreaterThanOrEqual(0.97)
|
||||
expect(ratio).toBeLessThanOrEqual(1.03)
|
||||
})
|
||||
|
||||
it('相同种子可复现,不同种子会重新侵蚀', () => {
|
||||
const candidates = selectKeywords(SOURCE, 14, 1)
|
||||
const first = generateMosaic(SOURCE, candidates, {
|
||||
volume: 100,
|
||||
disorder: 58,
|
||||
seed: 42,
|
||||
})
|
||||
const repeated = generateMosaic(SOURCE, candidates, {
|
||||
volume: 100,
|
||||
disorder: 58,
|
||||
seed: 42,
|
||||
})
|
||||
const rerolled = generateMosaic(SOURCE, candidates, {
|
||||
volume: 100,
|
||||
disorder: 58,
|
||||
seed: 43,
|
||||
})
|
||||
|
||||
expect(repeated.output).toBe(first.output)
|
||||
expect(rerolled.output).not.toBe(first.output)
|
||||
})
|
||||
|
||||
it('保留换行但替换每一行中的隐藏内容', () => {
|
||||
const source = '记忆,在这里。\n过去,在那里。'
|
||||
const candidates = retain(selectKeywords(source, 20, 1), ['记忆', '过去'])
|
||||
const result = generateMosaic(source, candidates, {
|
||||
volume: 100,
|
||||
disorder: 30,
|
||||
seed: 7,
|
||||
})
|
||||
|
||||
expect(result.output.split('\n')).toHaveLength(2)
|
||||
expect(result.output).not.toMatch(/[,。]/u)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user