recreate project
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
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)
|
||||
})
|
||||
|
||||
it('显影 0% 不保留词语,100% 保留全部候选词', () => {
|
||||
const hidden = selectKeywords(SOURCE, 0, 1)
|
||||
const revealed = selectKeywords(SOURCE, 100, 1)
|
||||
|
||||
expect(hidden.some((candidate) => candidate.selected)).toBe(false)
|
||||
expect(revealed.every((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('支持将体量压缩到 10% 或膨胀到 1000%', () => {
|
||||
const compressed = generateMosaic(SOURCE, [], {
|
||||
volume: 10,
|
||||
disorder: 0,
|
||||
seed: 42,
|
||||
})
|
||||
const expanded = generateMosaic(SOURCE, [], {
|
||||
volume: 1000,
|
||||
disorder: 0,
|
||||
seed: 42,
|
||||
})
|
||||
|
||||
expect(compressed.outputLength).toBe(Math.round(compressed.inputLength * 0.1))
|
||||
expect(expanded.outputLength).toBe(expanded.inputLength * 10)
|
||||
})
|
||||
|
||||
it('不生成可能跳出正常行框的 Unicode 组合符', () => {
|
||||
const outputs = Array.from({ length: 20 }, (_, seed) =>
|
||||
generateMosaic(SOURCE, [], {
|
||||
volume: 1000,
|
||||
disorder: 100,
|
||||
seed,
|
||||
}).output,
|
||||
).join('')
|
||||
|
||||
expect(outputs).not.toMatch(/\p{Mark}/u)
|
||||
})
|
||||
|
||||
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