import { Controller } from "../index";
import { getAvibleNfixingWids, getNfixingAndFixedWids } from "../../utils/text";
import {
  normalNFixFrame,
  paragraphNormalBreakFrame,
  paragraphNormalBreakFrame2,
  paragraphNormalBreakFrame3,
  paragraphNormalBreakFrame4,
  paragraphNormalBreakFrame5,
  paragraphNormalBreakFrame6,
  paragraphNormalBreakFrame7,
  paragraphNormalBreakFrame8,
  paragraphNormalBreakFrame9,
  paragraphNormalBreakFrame10,
  paragraphNormalBreakFrame11,
  paragraphForceBreakFrame,
  paragraphForceBreakFrame2,
  paragraphForceBreakFrame3,
  paragraphForceBreakFrame4,
  paragraphForceBreakFrame5,
  paragraphForceBreakFrame6,
} from "./mock/nfixBreakParagraph.data";

describe("nfixBreakParagraph", () => {
  it("breaking：正常成段1，和原先内容一致", async () => {
    const controller = new Controller();
    controller.setLivingMode(true);
    controller.injectSpeakersGetter(() => []);
    controller.injectSpeakersSetter(() => {});
    controller.on("paragraphChangeSpecific", event => {
      event.addParagraphPids.forEach(() => {
        // console.log('------- event', controller.getParagraph(pid));
      });
    });

    controller.processParagraphFrames(normalNFixFrame);

    // expect：unfix的 lastPid下标，应该为 normalNFixFrame 的 尾部pid
    expect(controller.getUnfixPid()).toEqual(`${normalNFixFrame[normalNFixFrame.length - 1].pi}`);

    // 触发强制成段
    controller.processParagraphFrames(paragraphNormalBreakFrame);

    // expect：根据数据测试，unfix的 lastPid下标，应该为 paragraphForceBreakFrame 的 尾部pid
    expect(controller.getUnfixPid()).toBeUndefined();

    // expect：根据数据测试，sc 50，由 pi：1
    expect(controller.getPidByWid("50")).toEqual("1");

    // expect：根据数据测试，验证word归属sc正确
    expect(controller.getLatestSid()).toEqual("1");
    expect(controller.getFirstWordBySid("1")?.wid).toEqual("10");
    expect(controller.getWord("50").sentenceId).toEqual("1");
    expect(controller.getWord("60").sentenceId).toEqual("1");

    const allWids: any[] = [];
    const nFixWids: any[] = [];
    const fixedWids: any[] = [];
    paragraphNormalBreakFrame.forEach(({ pi, sc, partial }) => {
      // expect：对应段落数据，没有丢词
      const pg = controller.getParagraph(pi);
      expect(pg.wids).toMatchObject(sc.map(word => `${word.id}`));
      // expect：验证 段落数据，按预期分段
      expect(pg.isUnfix).toEqual(partial);

      sc.forEach(({ pt, id }) => {
        if (pt) {
          nFixWids.push(id);
        } else {
          fixedWids.push(id);
        }
        allWids.push(id);
      });
    });

    const wordsMap = getNfixingAndFixedWids(controller, allWids);
    // expect：验证 工具方法，n字fix的标没问题
    expect(wordsMap.nfixingWids).toMatchObject(nFixWids);
    // expect：根据数据测试，验证 工具方法，n字fix的标没问题
    expect(wordsMap.nfixingWids).toMatchObject([]);
    // expect：验证 工具方法，非n字fix的标没问题
    expect(wordsMap.fixedWids).toMatchObject(fixedWids);

    await new Promise(r => setTimeout(r, 2000));
  });

  it("breaking：正常成段2，多了一个词", async () => {
    const controller = new Controller();
    controller.setLivingMode(true);
    controller.injectSpeakersGetter(() => []);
    controller.injectSpeakersSetter(() => {});
    controller.on("paragraphChangeSpecific", event => {
      event.addParagraphPids.forEach(() => {
        // console.log('------- event', controller.getParagraph(pid));
      });
    });

    controller.processParagraphFrames(normalNFixFrame);

    // expect：unfix的 lastPid下标，应该为 normalNFixFrame 的 尾部pid
    expect(controller.getUnfixPid()).toEqual(`${normalNFixFrame[normalNFixFrame.length - 1].pi}`);

    // 触发强制成段
    controller.processParagraphFrames(paragraphNormalBreakFrame2);

    // expect：根据数据测试，unfix的 lastPid下标，应该为 paragraphForceBreakFrame 的 尾部pid
    expect(controller.getUnfixPid()).toBeUndefined();

    // expect：根据数据测试，sc 50，由 pi：1
    expect(controller.getPidByWid("50")).toEqual("1");

    // expect：根据数据测试，sc 70，由 pi：1
    expect(controller.getPidByWid("70")).toEqual("1");

    // expect：根据数据测试，验证word归属sc正确
    expect(controller.getLatestSid()).toEqual("1");
    expect(controller.getFirstWordBySid("1")?.wid).toEqual("10");
    expect(controller.getWord("50").sentenceId).toEqual("1");
    expect(controller.getWord("60").sentenceId).toEqual("1");
    expect(controller.getWord("70").sentenceId).toEqual("1");

    const allWids: any[] = [];
    const nFixWids: any[] = [];
    const fixedWids: any[] = [];
    paragraphNormalBreakFrame2.forEach(({ pi, sc, partial }) => {
      // expect：对应段落数据，没有丢词
      const pg = controller.getParagraph(pi);
      expect(pg.wids).toMatchObject(sc.map(word => `${word.id}`));
      // expect：验证 段落数据，按预期分段
      expect(pg.isUnfix).toEqual(partial);

      sc.forEach(({ pt, id }) => {
        if (pt) {
          nFixWids.push(id);
        } else {
          fixedWids.push(id);
        }
        allWids.push(id);
      });
    });

    const wordsMap = getNfixingAndFixedWids(controller, allWids);
    // expect：验证 工具方法，n字fix的标没问题
    expect(wordsMap.nfixingWids).toMatchObject(nFixWids);
    // expect：根据数据测试，验证 工具方法，n字fix的标没问题
    expect(wordsMap.nfixingWids).toMatchObject([]);
    // expect：验证 工具方法，非n字fix的标没问题
    expect(wordsMap.fixedWids).toMatchObject(fixedWids);

    await new Promise(r => setTimeout(r, 2000));
  });

  it("breaking：正常成段3，词的所属句子发生变化", async () => {
    const controller = new Controller();
    controller.setLivingMode(true);
    controller.injectSpeakersGetter(() => []);
    controller.injectSpeakersSetter(() => {});
    controller.on("paragraphChangeSpecific", event => {
      event.addParagraphPids.forEach(() => {
        // console.log('------- event', controller.getParagraph(pid));
      });
    });

    controller.processParagraphFrames(normalNFixFrame);

    // expect：unfix的 lastPid下标，应该为 normalNFixFrame 的 尾部pid
    expect(controller.getUnfixPid()).toEqual(`${normalNFixFrame[normalNFixFrame.length - 1].pi}`);

    // 触发强制成段
    controller.processParagraphFrames(paragraphNormalBreakFrame3);

    // expect：根据数据测试，unfix的 lastPid下标，应该为 paragraphForceBreakFrame 的 尾部pid
    expect(controller.getUnfixPid()).toBeUndefined();

    // expect：根据数据测试，sc 50，由 pi：1
    expect(controller.getPidByWid("50")).toEqual("1");

    // expect：根据数据测试，sc 70，由 pi：1
    expect(controller.getPidByWid("60")).toEqual("1");

    // expect：根据数据测试，验证word归属sc正确
    expect(controller.getLatestSid()).toEqual("2");
    expect(controller.getFirstWordBySid("2")?.wid).toEqual("50");
    expect(controller.getWord("40").sentenceId).toEqual("1");
    expect(controller.getWord("50").sentenceId).toEqual("2");
    expect(controller.getWord("60").sentenceId).toEqual("2");

    const allWids: any[] = [];
    const nFixWids: any[] = [];
    const fixedWids: any[] = [];
    paragraphNormalBreakFrame3.forEach(({ pi, sc, partial }) => {
      // expect：对应段落数据，没有丢词
      const pg = controller.getParagraph(pi);
      expect(pg.wids).toMatchObject(sc.map(word => `${word.id}`));
      // expect：验证 段落数据，按预期分段
      expect(pg.isUnfix).toEqual(partial);

      sc.forEach(({ pt, id }) => {
        if (pt) {
          nFixWids.push(id);
        } else {
          fixedWids.push(id);
        }
        allWids.push(id);
      });
    });

    const wordsMap = getNfixingAndFixedWids(controller, allWids);
    // expect：验证 工具方法，n字fix的标没问题
    expect(wordsMap.nfixingWids).toMatchObject(nFixWids);
    // expect：根据数据测试，验证 工具方法，n字fix的标没问题
    expect(wordsMap.nfixingWids).toMatchObject([]);
    // expect：验证 工具方法，非n字fix的标没问题
    expect(wordsMap.fixedWids).toMatchObject(fixedWids);

    await new Promise(r => setTimeout(r, 2000));
  });

  it("breaking：正常成段4，词的所属句子发生变化，同时新增了词", async () => {
    const controller = new Controller();
    controller.setLivingMode(true);
    controller.injectSpeakersGetter(() => []);
    controller.injectSpeakersSetter(() => {});
    controller.on("paragraphChangeSpecific", event => {
      event.addParagraphPids.forEach(() => {
        // console.log('------- event', controller.getParagraph(pid));
      });
    });

    controller.processParagraphFrames(normalNFixFrame);

    // expect：unfix的 lastPid下标，应该为 normalNFixFrame 的 尾部pid
    expect(controller.getUnfixPid()).toEqual(`${normalNFixFrame[normalNFixFrame.length - 1].pi}`);

    // 触发强制成段
    controller.processParagraphFrames(paragraphNormalBreakFrame4);

    // expect：根据数据测试，unfix的 lastPid下标，应该为 paragraphForceBreakFrame 的 尾部pid
    expect(controller.getUnfixPid()).toBeUndefined();

    // expect：根据数据测试，sc 50，由 pi：1，强制成段到了 pi：2
    expect(controller.getPidByWid("50")).toEqual("1");

    // expect：根据数据测试，sc 70，由 pi：1，强制成段到了 pi：2
    expect(controller.getPidByWid("70")).toEqual("1");

    // expect：根据数据测试，验证word归属sc正确
    expect(controller.getLatestSid()).toEqual("2");
    expect(controller.getFirstWordBySid("2")?.wid).toEqual("50");
    expect(controller.getWord("40").sentenceId).toEqual("1");
    expect(controller.getWord("50").sentenceId).toEqual("2");
    expect(controller.getWord("60").sentenceId).toEqual("2");
    expect(controller.getWord("70").sentenceId).toEqual("2");

    const allWids: any[] = [];
    const nFixWids: any[] = [];
    const fixedWids: any[] = [];
    paragraphNormalBreakFrame4.forEach(({ pi, sc, partial }) => {
      // expect：对应段落数据，没有丢词
      const pg = controller.getParagraph(pi);
      expect(pg.wids).toMatchObject(sc.map(word => `${word.id}`));
      // expect：验证 段落数据，按预期分段
      expect(pg.isUnfix).toEqual(partial);

      sc.forEach(({ pt, id }) => {
        if (pt) {
          nFixWids.push(id);
        } else {
          fixedWids.push(id);
        }
        allWids.push(id);
      });
    });

    const wordsMap = getNfixingAndFixedWids(controller, allWids);
    // expect：验证 工具方法，n字fix的标没问题
    expect(wordsMap.nfixingWids).toMatchObject(nFixWids);
    // expect：根据数据测试，验证 工具方法，n字fix的标没问题
    expect(wordsMap.nfixingWids).toMatchObject([]);
    // expect：验证 工具方法，非n字fix的标没问题
    expect(wordsMap.fixedWids).toMatchObject(fixedWids);

    await new Promise(r => setTimeout(r, 2000));
  });

  it("breaking：正常成段5，多了新段落", async () => {
    const controller = new Controller();
    controller.setLivingMode(true);
    controller.injectSpeakersGetter(() => []);
    controller.injectSpeakersSetter(() => {});
    controller.on("paragraphChangeSpecific", event => {
      event.addParagraphPids.forEach(() => {
        // console.log('------- event', controller.getParagraph(pid));
      });
    });

    controller.processParagraphFrames(normalNFixFrame);

    // expect：unfix的 lastPid下标，应该为 normalNFixFrame 的 尾部pid
    expect(controller.getUnfixPid()).toEqual(`${normalNFixFrame[normalNFixFrame.length - 1].pi}`);

    // 触发强制成段
    controller.processParagraphFrames(paragraphNormalBreakFrame5);

    // expect：根据数据测试，unfix的 lastPid下标，应该为 paragraphForceBreakFrame 的 尾部pid
    expect(controller.getUnfixPid()).toEqual("2");

    // expect：根据数据测试，sc 50，由 pi：1
    expect(controller.getPidByWid("50")).toEqual("1");

    // expect：根据数据测试，新段落， pi：2
    expect(controller.getPidByWid("70")).toEqual("2");

    // expect：根据数据测试，验证word归属sc正确
    expect(controller.getLatestSid()).toEqual("2");
    expect(controller.getFirstWordBySid("1")?.wid).toEqual("10");
    expect(controller.getFirstWordBySid("2")?.wid).toEqual("70");
    expect(controller.getWord("40").sentenceId).toEqual("1");
    expect(controller.getWord("50").sentenceId).toEqual("1");
    expect(controller.getWord("60").sentenceId).toEqual("1");
    expect(controller.getWord("70").sentenceId).toEqual("2");

    const allWids: any[] = [];
    const nFixWids: any[] = [];
    const fixedWids: any[] = [];
    paragraphNormalBreakFrame5.forEach(({ pi, sc, partial }) => {
      // expect：对应段落数据，没有丢词
      const pg = controller.getParagraph(pi);
      expect(pg.wids).toMatchObject(sc.map(word => `${word.id}`));
      // expect：验证 段落数据，按预期分段
      expect(pg.isUnfix).toEqual(partial);

      sc.forEach(({ pt, id }) => {
        if (pt) {
          nFixWids.push(id);
        } else {
          fixedWids.push(id);
        }
        allWids.push(id);
      });
    });

    const wordsMap = getNfixingAndFixedWids(controller, allWids);
    // expect：验证 工具方法，n字fix的标没问题
    expect(wordsMap.nfixingWids).toMatchObject(nFixWids);
    // expect：根据数据测试，验证 工具方法，n字fix的标没问题
    expect(wordsMap.nfixingWids).toMatchObject([70]);
    // expect：验证 工具方法，非n字fix的标没问题
    expect(wordsMap.fixedWids).toMatchObject(fixedWids);

    await new Promise(r => setTimeout(r, 2000));
  });

  it("breaking：正常成段6，多了新段落，老段落，也多了新词", async () => {
    const controller = new Controller();
    controller.setLivingMode(true);
    controller.injectSpeakersGetter(() => []);
    controller.injectSpeakersSetter(() => {});
    controller.on("paragraphChangeSpecific", event => {
      event.addParagraphPids.forEach(() => {
        // console.log('------- event', controller.getParagraph(pid));
      });
    });

    controller.processParagraphFrames(normalNFixFrame);

    // expect：unfix的 lastPid下标，应该为 normalNFixFrame 的 尾部pid
    expect(controller.getUnfixPid()).toEqual(`${normalNFixFrame[normalNFixFrame.length - 1].pi}`);

    // 触发强制成段
    controller.processParagraphFrames(paragraphNormalBreakFrame6);

    // expect：根据数据测试，unfix的 lastPid下标，应该为 paragraphForceBreakFrame 的 尾部pid
    expect(controller.getUnfixPid()).toEqual("2");

    // expect：根据数据测试，sc 50，由 pi：1
    expect(controller.getPidByWid("50")).toEqual("1");

    // expect：根据数据测试，新段落， pi：1
    expect(controller.getPidByWid("70")).toEqual("1");
    // expect：根据数据测试，新段落， pi：2
    expect(controller.getPidByWid("80")).toEqual("2");

    // expect：根据数据测试，验证word归属sc正确
    expect(controller.getLatestSid()).toEqual("2");
    expect(controller.getFirstWordBySid("1")?.wid).toEqual("10");
    expect(controller.getFirstWordBySid("2")?.wid).toEqual("80");
    expect(controller.getWord("40").sentenceId).toEqual("1");
    expect(controller.getWord("50").sentenceId).toEqual("1");
    expect(controller.getWord("60").sentenceId).toEqual("1");
    expect(controller.getWord("70").sentenceId).toEqual("1");
    expect(controller.getWord("80").sentenceId).toEqual("2");

    const allWids: any[] = [];
    const nFixWids: any[] = [];
    const fixedWids: any[] = [];
    paragraphNormalBreakFrame6.forEach(({ pi, sc, partial }) => {
      // expect：对应段落数据，没有丢词
      const pg = controller.getParagraph(pi);
      expect(pg.wids).toMatchObject(sc.map(word => `${word.id}`));
      // expect：验证 段落数据，按预期分段
      expect(pg.isUnfix).toEqual(partial);

      sc.forEach(({ pt, id }) => {
        if (pt) {
          nFixWids.push(id);
        } else {
          fixedWids.push(id);
        }
        allWids.push(id);
      });
    });

    const wordsMap = getNfixingAndFixedWids(controller, allWids);
    // expect：验证 工具方法，n字fix的标没问题
    expect(wordsMap.nfixingWids).toMatchObject(nFixWids);
    // expect：根据数据测试，验证 工具方法，n字fix的标没问题
    expect(wordsMap.nfixingWids).toMatchObject([80]);
    // expect：验证 工具方法，非n字fix的标没问题
    expect(wordsMap.fixedWids).toMatchObject(fixedWids);

    await new Promise(r => setTimeout(r, 2000));
  });

  it("breaking：正常成段7，多了新段落，老段落，也多了新词，且sc也是新的", async () => {
    const controller = new Controller();
    controller.setLivingMode(true);
    controller.injectSpeakersGetter(() => []);
    controller.injectSpeakersSetter(() => {});
    controller.on("paragraphChangeSpecific", event => {
      event.addParagraphPids.forEach(() => {
        // console.log('------- event', controller.getParagraph(pid));
      });
    });

    controller.processParagraphFrames(normalNFixFrame);

    // expect：unfix的 lastPid下标，应该为 normalNFixFrame 的 尾部pid
    expect(controller.getUnfixPid()).toEqual(`${normalNFixFrame[normalNFixFrame.length - 1].pi}`);

    // 触发强制成段
    controller.processParagraphFrames(paragraphNormalBreakFrame7);

    // expect：根据数据测试，unfix的 lastPid下标，应该为 paragraphForceBreakFrame 的 尾部pid
    expect(controller.getUnfixPid()).toEqual("2");

    // expect：根据数据测试，sc 50，由 pi：1
    expect(controller.getPidByWid("50")).toEqual("1");

    // expect：根据数据测试，新段落， pi：1
    expect(controller.getPidByWid("70")).toEqual("1");
    // expect：根据数据测试，新段落， pi：2
    expect(controller.getPidByWid("80")).toEqual("2");

    // expect：根据数据测试，验证word归属sc正确
    expect(controller.getLatestSid()).toEqual("3");
    expect(controller.getFirstWordBySid("1")?.wid).toEqual("10");
    expect(controller.getFirstWordBySid("2")?.wid).toEqual("70");
    expect(controller.getFirstWordBySid("3")?.wid).toEqual("80");
    expect(controller.getWord("40").sentenceId).toEqual("1");
    expect(controller.getWord("50").sentenceId).toEqual("1");
    expect(controller.getWord("60").sentenceId).toEqual("1");
    expect(controller.getWord("70").sentenceId).toEqual("2");
    expect(controller.getWord("80").sentenceId).toEqual("3");

    const allWids: any[] = [];
    const nFixWids: any[] = [];
    const fixedWids: any[] = [];
    paragraphNormalBreakFrame7.forEach(({ pi, sc, partial }) => {
      // expect：对应段落数据，没有丢词
      const pg = controller.getParagraph(pi);
      expect(pg.wids).toMatchObject(sc.map(word => `${word.id}`));
      // expect：验证 段落数据，按预期分段
      expect(pg.isUnfix).toEqual(partial);

      sc.forEach(({ pt, id }) => {
        if (pt) {
          nFixWids.push(id);
        } else {
          fixedWids.push(id);
        }
        allWids.push(id);
      });
    });

    const wordsMap = getNfixingAndFixedWids(controller, allWids);
    // expect：验证 工具方法，n字fix的标没问题
    expect(wordsMap.nfixingWids).toMatchObject(nFixWids);
    // expect：根据数据测试，验证 工具方法，n字fix的标没问题
    expect(wordsMap.nfixingWids).toMatchObject([80]);
    // expect：验证 工具方法，非n字fix的标没问题
    expect(wordsMap.fixedWids).toMatchObject(fixedWids);

    await new Promise(r => setTimeout(r, 2000));
  });

  it("breaking：正常成段8，多了 新段落，老段落，也多了新词，且sc也是新的，部分老词sc也有更新", async () => {
    const controller = new Controller();
    controller.setLivingMode(true);
    controller.injectSpeakersGetter(() => []);
    controller.injectSpeakersSetter(() => {});
    controller.on("paragraphChangeSpecific", event => {
      event.addParagraphPids.forEach(() => {
        // console.log('------- event', controller.getParagraph(pid));
      });
    });

    controller.processParagraphFrames(normalNFixFrame);

    // expect：unfix的 lastPid下标，应该为 normalNFixFrame 的 尾部pid
    expect(controller.getUnfixPid()).toEqual(`${normalNFixFrame[normalNFixFrame.length - 1].pi}`);

    // 触发强制成段
    controller.processParagraphFrames(paragraphNormalBreakFrame8);

    // expect：根据数据测试，unfix的 lastPid下标，应该为 paragraphForceBreakFrame 的 尾部pid
    expect(controller.getUnfixPid()).toEqual("2");

    // expect：根据数据测试，sc 50，由 pi：1
    expect(controller.getPidByWid("50")).toEqual("1");

    // expect：根据数据测试，新段落， pi：1
    expect(controller.getPidByWid("70")).toEqual("1");
    // expect：根据数据测试，新段落， pi：2
    expect(controller.getPidByWid("80")).toEqual("2");

    // expect：根据数据测试，验证word归属sc正确
    expect(controller.getLatestSid()).toEqual("3");
    expect(controller.getFirstWordBySid("1")?.wid).toEqual("10");
    expect(controller.getFirstWordBySid("2")?.wid).toEqual("50");
    expect(controller.getFirstWordBySid("3")?.wid).toEqual("80");
    expect(controller.getWord("40").sentenceId).toEqual("1");
    expect(controller.getWord("50").sentenceId).toEqual("2");
    expect(controller.getWord("60").sentenceId).toEqual("2");
    expect(controller.getWord("70").sentenceId).toEqual("2");
    expect(controller.getWord("80").sentenceId).toEqual("3");

    const allWids: any[] = [];
    const nFixWids: any[] = [];
    const fixedWids: any[] = [];
    paragraphNormalBreakFrame8.forEach(({ pi, sc, partial }) => {
      // expect：对应段落数据，没有丢词
      const pg = controller.getParagraph(pi);
      expect(pg.wids).toMatchObject(sc.map(word => `${word.id}`));
      // expect：验证 段落数据，按预期分段
      expect(pg.isUnfix).toEqual(partial);

      sc.forEach(({ pt, id }) => {
        if (pt) {
          nFixWids.push(id);
        } else {
          fixedWids.push(id);
        }
        allWids.push(id);
      });
    });

    const wordsMap = getNfixingAndFixedWids(controller, allWids);
    // expect：验证 工具方法，n字fix的标没问题
    expect(wordsMap.nfixingWids).toMatchObject(nFixWids);
    // expect：根据数据测试，验证 工具方法，n字fix的标没问题
    expect(wordsMap.nfixingWids).toMatchObject([80]);
    // expect：验证 工具方法，非n字fix的标没问题
    expect(wordsMap.fixedWids).toMatchObject(fixedWids);

    await new Promise(r => setTimeout(r, 2000));
  });

  it("breaking：正常成段9，多了 新段落，老段落，部分老词sc有更新", async () => {
    const controller = new Controller();
    controller.setLivingMode(true);
    controller.injectSpeakersGetter(() => []);
    controller.injectSpeakersSetter(() => {});
    controller.on("paragraphChangeSpecific", event => {
      event.addParagraphPids.forEach(() => {
        // console.log('------- event', controller.getParagraph(pid));
      });
    });

    controller.processParagraphFrames(normalNFixFrame);

    // expect：unfix的 lastPid下标，应该为 normalNFixFrame 的 尾部pid
    expect(controller.getUnfixPid()).toEqual(`${normalNFixFrame[normalNFixFrame.length - 1].pi}`);

    // 触发强制成段
    controller.processParagraphFrames(paragraphNormalBreakFrame9);

    // expect：根据数据测试，unfix的 lastPid下标，应该为 paragraphForceBreakFrame 的 尾部pid
    expect(controller.getUnfixPid()).toEqual("2");

    // expect：根据数据测试，sc 50，由 pi：1
    expect(controller.getPidByWid("50")).toEqual("1");

    // expect：根据数据测试，新段落， pi：1
    expect(controller.getPidByWid("70")).toEqual("2");

    // expect：根据数据测试，验证word归属sc正确
    expect(controller.getLatestSid()).toEqual("3");
    expect(controller.getFirstWordBySid("1")?.wid).toEqual("10");
    expect(controller.getFirstWordBySid("2")?.wid).toEqual("50");
    expect(controller.getWord("40").sentenceId).toEqual("1");
    expect(controller.getWord("50").sentenceId).toEqual("2");
    expect(controller.getWord("60").sentenceId).toEqual("2");
    expect(controller.getWord("70").sentenceId).toEqual("3");

    const allWids: any[] = [];
    const nFixWids: any[] = [];
    const fixedWids: any[] = [];
    paragraphNormalBreakFrame9.forEach(({ pi, sc, partial }) => {
      // expect：对应段落数据，没有丢词
      const pg = controller.getParagraph(pi);
      expect(pg.wids).toMatchObject(sc.map(word => `${word.id}`));
      // expect：验证 段落数据，按预期分段
      expect(pg.isUnfix).toEqual(partial);

      sc.forEach(({ pt, id }) => {
        if (pt) {
          nFixWids.push(id);
        } else {
          fixedWids.push(id);
        }
        allWids.push(id);
      });
    });

    const wordsMap = getNfixingAndFixedWids(controller, allWids);
    // expect：验证 工具方法，n字fix的标没问题
    expect(wordsMap.nfixingWids).toMatchObject(nFixWids);
    // expect：根据数据测试，验证 工具方法，n字fix的标没问题
    expect(wordsMap.nfixingWids).toMatchObject([70]);
    // expect：验证 工具方法，非n字fix的标没问题
    expect(wordsMap.fixedWids).toMatchObject(fixedWids);

    await new Promise(r => setTimeout(r, 2000));
  });

  it("breaking：正常成段10，多了 新段落，但新段落的词不带n字fix标", async () => {
    const controller = new Controller();
    controller.setLivingMode(true);
    controller.injectSpeakersGetter(() => []);
    controller.injectSpeakersSetter(() => {});
    controller.on("paragraphChangeSpecific", event => {
      event.addParagraphPids.forEach(() => {
        // console.log('------- event', controller.getParagraph(pid));
      });
    });

    controller.processParagraphFrames(normalNFixFrame);

    // expect：unfix的 lastPid下标，应该为 normalNFixFrame 的 尾部pid
    expect(controller.getUnfixPid()).toEqual(`${normalNFixFrame[normalNFixFrame.length - 1].pi}`);

    // 触发强制成段
    controller.processParagraphFrames(paragraphNormalBreakFrame10);

    // expect：根据数据测试，unfix的 lastPid下标，应该为 paragraphForceBreakFrame 的 尾部pid
    expect(controller.getUnfixPid()).toEqual("2");

    // expect：根据数据测试，sc 50，由 pi：1
    expect(controller.getPidByWid("50")).toEqual("1");

    // expect：根据数据测试，新段落， pi：2
    expect(controller.getPidByWid("70")).toEqual("2");

    // expect：根据数据测试，验证word归属sc正确
    expect(controller.getLatestSid()).toEqual("2");
    expect(controller.getFirstWordBySid("1")?.wid).toEqual("10");
    expect(controller.getFirstWordBySid("2")?.wid).toEqual("70");
    expect(controller.getWord("40").sentenceId).toEqual("1");
    expect(controller.getWord("50").sentenceId).toEqual("1");
    expect(controller.getWord("60").sentenceId).toEqual("1");
    expect(controller.getWord("70").sentenceId).toEqual("2");

    const allWids: any[] = [];
    const nFixWids: any[] = [];
    const fixedWids: any[] = [];
    paragraphNormalBreakFrame10.forEach(({ pi, sc, partial }) => {
      // expect：对应段落数据，没有丢词
      const pg = controller.getParagraph(pi);
      expect(pg.wids).toMatchObject(sc.map(word => `${word.id}`));
      // expect：验证 段落数据，按预期分段
      expect(pg.isUnfix).toEqual(partial);

      sc.forEach(({ pt, id }) => {
        if (pt) {
          nFixWids.push(id);
        } else {
          fixedWids.push(id);
        }
        allWids.push(id);
      });
    });

    const wordsMap = getNfixingAndFixedWids(controller, allWids);
    // expect：验证 工具方法，n字fix的标没问题
    expect(wordsMap.nfixingWids).toMatchObject(nFixWids);
    // expect：根据数据测试，验证 工具方法，n字fix的标没问题
    expect(wordsMap.nfixingWids).toMatchObject([]);
    // expect：验证 工具方法，非n字fix的标没问题
    expect(wordsMap.fixedWids).toMatchObject(fixedWids);

    await new Promise(r => setTimeout(r, 2000));
  });

  it("breaking：正常成段11，多了 新段落，但新段落的词，部分带n字fix标，部分不带", async () => {
    const controller = new Controller();
    controller.setLivingMode(true);
    controller.injectSpeakersGetter(() => []);
    controller.injectSpeakersSetter(() => {});
    controller.on("paragraphChangeSpecific", event => {
      event.addParagraphPids.forEach(() => {
        // console.log('------- event', controller.getParagraph(pid));
      });
    });

    controller.processParagraphFrames(normalNFixFrame);

    // expect：unfix的 lastPid下标，应该为 normalNFixFrame 的 尾部pid
    expect(controller.getUnfixPid()).toEqual(`${normalNFixFrame[normalNFixFrame.length - 1].pi}`);

    // 触发强制成段
    controller.processParagraphFrames(paragraphNormalBreakFrame11);

    // expect：根据数据测试，unfix的 lastPid下标，应该为 paragraphForceBreakFrame 的 尾部pid
    expect(controller.getUnfixPid()).toEqual("2");

    // expect：根据数据测试，sc 50，由 pi：1
    expect(controller.getPidByWid("50")).toEqual("1");

    // expect：根据数据测试，新段落， pi：2
    expect(controller.getPidByWid("70")).toEqual("2");
    // expect：根据数据测试，新段落， pi：2
    expect(controller.getPidByWid("80")).toEqual("2");

    // expect：根据数据测试，验证word归属sc正确
    expect(controller.getLatestSid()).toEqual("3");
    expect(controller.getFirstWordBySid("1")?.wid).toEqual("10");
    expect(controller.getFirstWordBySid("2")?.wid).toEqual("70");
    expect(controller.getFirstWordBySid("3")?.wid).toEqual("80");
    expect(controller.getWord("40").sentenceId).toEqual("1");
    expect(controller.getWord("50").sentenceId).toEqual("1");
    expect(controller.getWord("60").sentenceId).toEqual("1");
    expect(controller.getWord("70").sentenceId).toEqual("2");
    expect(controller.getWord("80").sentenceId).toEqual("3");

    const allWids: any[] = [];
    const nFixWids: any[] = [];
    const fixedWids: any[] = [];
    paragraphNormalBreakFrame11.forEach(({ pi, sc, partial }) => {
      // expect：对应段落数据，没有丢词
      const pg = controller.getParagraph(pi);
      expect(pg.wids).toMatchObject(sc.map(word => `${word.id}`));
      // expect：验证 段落数据，按预期分段
      expect(pg.isUnfix).toEqual(partial);

      sc.forEach(({ pt, id }) => {
        if (pt) {
          nFixWids.push(id);
        } else {
          fixedWids.push(id);
        }
        allWids.push(id);
      });
    });

    const wordsMap = getNfixingAndFixedWids(controller, allWids);
    // expect：验证 工具方法，n字fix的标没问题
    expect(wordsMap.nfixingWids).toMatchObject(nFixWids);
    // expect：根据数据测试，验证 工具方法，n字fix的标没问题
    expect(wordsMap.nfixingWids).toMatchObject([80]);
    // expect：验证 工具方法，非n字fix的标没问题
    expect(wordsMap.fixedWids).toMatchObject(fixedWids);

    await new Promise(r => setTimeout(r, 2000));
  });

  it("breaking：强制成段1：部分句子挪到pg:2，pt标签不动", async () => {
    const controller = new Controller();
    controller.setLivingMode(true);
    controller.injectSpeakersGetter(() => []);
    controller.injectSpeakersSetter(() => {});
    controller.on("paragraphChangeSpecific", event => {
      event.addParagraphPids.forEach(() => {
        // console.log('------- event', controller.getParagraph(pid));
      });
    });

    controller.processParagraphFrames(normalNFixFrame);

    // expect：unfix的 lastPid下标，应该为 normalNFixFrame 的 尾部pid
    expect(controller.getUnfixPid()).toEqual(`${normalNFixFrame[normalNFixFrame.length - 1].pi}`);

    // 触发强制成段
    controller.processParagraphFrames(paragraphForceBreakFrame);

    // expect：根据数据测试，unfix的 lastPid下标，应该为 paragraphForceBreakFrame 的 尾部pid
    expect(controller.getUnfixPid()).toEqual(
      `${paragraphForceBreakFrame[paragraphForceBreakFrame.length - 1].pi}`
    );

    // expect：根据数据测试，sc 50，由 pi：1，强制成段到了 pi：2
    expect(controller.getPidByWid("50")).toEqual("2");

    // expect：根据数据测试，验证word归属sc正确
    expect(controller.getLatestSid()).toEqual("2");
    expect(controller.getFirstWordBySid("2")?.wid).toEqual("50");
    expect(controller.getWord("40").sentenceId).toEqual("1");
    expect(controller.getWord("50").sentenceId).toEqual("2");
    expect(controller.getWord("60").sentenceId).toEqual("2");

    const allWids: any[] = [];
    const nFixWids: any[] = [];
    const fixedWids: any[] = [];
    paragraphForceBreakFrame.forEach(({ pi, sc, partial }) => {
      // expect：对应段落数据，没有丢词
      const pg = controller.getParagraph(pi);
      expect(pg.wids).toMatchObject(sc.map(word => `${word.id}`));
      // expect：验证 段落数据，按预期分段
      expect(pg.isUnfix).toEqual(partial);

      sc.forEach(({ pt, id }) => {
        if (pt) {
          nFixWids.push(id);
        } else {
          fixedWids.push(id);
        }
        allWids.push(id);
      });
    });

    const wordsMap = getNfixingAndFixedWids(controller, allWids);
    // expect：验证 工具方法，n字fix的标没问题
    expect(wordsMap.nfixingWids).toMatchObject(nFixWids);
    // expect：根据数据测试，验证 工具方法，n字fix的标没问题
    expect(wordsMap.nfixingWids).toMatchObject([50, 60]);
    // expect：验证 工具方法，非n字fix的标没问题
    expect(wordsMap.fixedWids).toMatchObject(fixedWids);

    await new Promise(r => setTimeout(r, 2000));
  });

  it("breaking：强制成段2：部分句子挪到pg:2，pt要跟着句子走（pt标签部分动，部分不动，但sc不变）", async () => {
    const controller = new Controller();
    controller.setLivingMode(true);
    controller.injectSpeakersGetter(() => []);
    controller.injectSpeakersSetter(() => {});
    controller.on("paragraphChangeSpecific", event => {
      event.addParagraphPids.forEach(() => {
        // console.log('------- event', controller.getParagraph(pid));
      });
    });

    controller.processParagraphFrames(normalNFixFrame);

    // expect：unfix的 lastPid下标，应该为 normalNFixFrame 的 尾部pid
    expect(controller.getUnfixPid()).toEqual(`${normalNFixFrame[normalNFixFrame.length - 1].pi}`);

    // 触发强制成段
    controller.processParagraphFrames(paragraphForceBreakFrame2);

    // expect：根据数据测试，unfix的 lastPid下标，应该为 paragraphForceBreakFrame 的 尾部pid
    expect(controller.getUnfixPid()).toEqual(
      `${paragraphForceBreakFrame2[paragraphForceBreakFrame2.length - 1].pi}`
    );

    // expect：根据数据测试，sc 50，由 pi：1，强制成段到了 pi：2
    expect(controller.getPidByWid("50")).toEqual("2");

    // expect：根据数据测试，验证word归属sc正确
    expect(controller.getLatestSid()).toEqual("2");
    expect(controller.getFirstWordBySid("2")?.wid).toEqual("50");
    expect(controller.getWord("40").sentenceId).toEqual("1");
    expect(controller.getWord("50").sentenceId).toEqual("2");
    expect(controller.getWord("60").sentenceId).toEqual("2");

    const allWids: any[] = [];
    const nFixWids: any[] = [];
    const fixedWids: any[] = [];
    paragraphForceBreakFrame2.forEach(({ pi, sc, partial }) => {
      // expect：对应段落数据，没有丢词
      const pg = controller.getParagraph(pi);
      expect(pg.wids).toMatchObject(sc.map(word => `${word.id}`));
      // expect：验证 段落数据，按预期分段
      expect(pg.isUnfix).toEqual(partial);

      sc.forEach(({ pt, id }) => {
        if (pt) {
          nFixWids.push(id);
        } else {
          fixedWids.push(id);
        }
        allWids.push(id);
      });
    });

    const wordsMap = getNfixingAndFixedWids(controller, allWids);

    // expect：验证 工具方法，n字fix的标没问题
    expect(wordsMap.nfixingWids).not.toMatchObject(nFixWids);

    const wordsNfixMap = getAvibleNfixingWids(controller, allWids);
    // expect：根据数据测试，验证 工具方法，n字fix的标没问题，因为句子没变，所有50的pt标去除失败（pt理论上跟着sc走）
    expect(wordsNfixMap.nfixingWids).toMatchObject([50, 60]);
    // expect：根据数据测试，验证 工具方法，n字fix的标没问题，因为句子没变，所有50的pt标去除失败（pt理论上跟着sc走）
    expect(wordsMap.nfixingWids).toMatchObject([50, 60]);
    // expect：验证 工具方法，非n字fix的标没问题
    expect(wordsMap.fixedWids).not.toMatchObject(fixedWids);

    await new Promise(r => setTimeout(r, 2000));
  });

  it("breaking：强制成段3：部分句子挪到pg:2，pt要跟着句子走（pt标签部分动，部分不动，但sc不变）", async () => {
    const controller = new Controller();
    controller.setLivingMode(true);
    controller.injectSpeakersGetter(() => []);
    controller.injectSpeakersSetter(() => {});
    controller.on("paragraphChangeSpecific", event => {
      event.addParagraphPids.forEach(() => {
        // console.log('------- event', controller.getParagraph(pid));
      });
    });

    controller.processParagraphFrames(normalNFixFrame);

    // expect：unfix的 lastPid下标，应该为 normalNFixFrame 的 尾部pid
    expect(controller.getUnfixPid()).toEqual(`${normalNFixFrame[normalNFixFrame.length - 1].pi}`);

    // 触发强制成段
    controller.processParagraphFrames(paragraphForceBreakFrame3);

    // expect：根据数据测试，unfix的 lastPid下标，应该为 paragraphForceBreakFrame 的 尾部pid
    expect(controller.getUnfixPid()).toEqual(
      `${paragraphForceBreakFrame3[paragraphForceBreakFrame3.length - 1].pi}`
    );

    // expect：根据数据测试，sc 50，由 pi：1，强制成段到了 pi：2
    expect(controller.getPidByWid("50")).toEqual("2");

    // expect：根据数据测试，验证word归属sc正确
    expect(controller.getLatestSid()).toEqual("3");
    expect(controller.getFirstWordBySid("2")?.wid).toEqual("50");
    expect(controller.getFirstWordBySid("3")?.wid).toEqual("70");
    expect(controller.getWord("40").sentenceId).toEqual("1");
    expect(controller.getWord("50").sentenceId).toEqual("2");
    expect(controller.getWord("60").sentenceId).toEqual("2");
    expect(controller.getWord("70").sentenceId).toEqual("3");

    const allWids: any[] = [];
    const nFixWids: any[] = [];
    const fixedWids: any[] = [];
    paragraphForceBreakFrame3.forEach(({ pi, sc, partial }) => {
      // expect：对应段落数据，没有丢词
      const pg = controller.getParagraph(pi);
      expect(pg.wids).toMatchObject(sc.map(word => `${word.id}`));
      // expect：验证 段落数据，按预期分段
      expect(pg.isUnfix).toEqual(partial);

      sc.forEach(({ pt, id }) => {
        if (pt) {
          nFixWids.push(id);
        } else {
          fixedWids.push(id);
        }
        allWids.push(id);
      });
    });

    const wordsMap = getNfixingAndFixedWids(controller, allWids);
    // expect：验证 工具方法，n字fix的标没问题
    expect(wordsMap.nfixingWids).not.toMatchObject(nFixWids);
    const wordsNfixMap = getAvibleNfixingWids(controller, allWids);
    // expect：根据数据测试，验证 工具方法，n字fix的标没问题，因为句子没变，所有50的pt标去除失败（pt理论上跟着sc走）
    expect(wordsNfixMap.nfixingWids).toMatchObject([50, 60, 70]);
    // expect：根据数据测试，验证 工具方法，n字fix的标没问题，因为句子没变，所有50的pt标去除失败（pt理论上跟着sc走）
    expect(wordsMap.nfixingWids).toMatchObject([50, 60, 70]);
    // expect：验证 工具方法，非n字fix的标没问题
    expect(wordsMap.fixedWids).not.toMatchObject(fixedWids);

    await new Promise(r => setTimeout(r, 2000));
  });

  it("breaking：强制成段4：部分句子挪到pg:2，原句子无pt，新增word带pt", async () => {
    const controller = new Controller();
    controller.setLivingMode(true);
    controller.injectSpeakersGetter(() => []);
    controller.injectSpeakersSetter(() => {});
    controller.on("paragraphChangeSpecific", event => {
      event.addParagraphPids.forEach(() => {
        // console.log('------- event', controller.getParagraph(pid));
      });
    });

    controller.processParagraphFrames(normalNFixFrame);

    // expect：unfix的 lastPid下标，应该为 normalNFixFrame 的 尾部pid
    expect(controller.getUnfixPid()).toEqual(`${normalNFixFrame[normalNFixFrame.length - 1].pi}`);

    // 触发强制成段
    controller.processParagraphFrames(paragraphForceBreakFrame4);

    // expect：根据数据测试，unfix的 lastPid下标，应该为 paragraphForceBreakFrame 的 尾部pid
    expect(controller.getUnfixPid()).toEqual(
      `${paragraphForceBreakFrame4[paragraphForceBreakFrame4.length - 1].pi}`
    );

    // expect：根据数据测试，sc 50，由 pi：1，强制成段到了 pi：2
    expect(controller.getPidByWid("50")).toEqual("2");

    // expect：根据数据测试，验证word归属sc正确
    expect(controller.getLatestSid()).toEqual("3");
    expect(controller.getFirstWordBySid("2")?.wid).toEqual("50");
    expect(controller.getFirstWordBySid("3")?.wid).toEqual("70");
    expect(controller.getWord("40").sentenceId).toEqual("1");
    expect(controller.getWord("50").sentenceId).toEqual("2");
    expect(controller.getWord("60").sentenceId).toEqual("2");
    expect(controller.getWord("70").sentenceId).toEqual("3");

    const allWids: any[] = [];
    const nFixWids: any[] = [];
    const fixedWids: any[] = [];
    paragraphForceBreakFrame4.forEach(({ pi, sc, partial }) => {
      // expect：对应段落数据，没有丢词
      const pg = controller.getParagraph(pi);
      expect(pg.wids).toMatchObject(sc.map(word => `${word.id}`));
      // expect：验证 段落数据，按预期分段
      expect(pg.isUnfix).toEqual(partial);

      sc.forEach(({ pt, id }) => {
        if (pt) {
          nFixWids.push(id);
        } else {
          fixedWids.push(id);
        }
        allWids.push(id);
      });
    });

    const wordsMap = getNfixingAndFixedWids(controller, allWids);
    // expect：验证 工具方法，n字fix的标没问题
    expect(wordsMap.nfixingWids).toMatchObject(nFixWids);

    const wordsNfixMap = getAvibleNfixingWids(controller, allWids);
    // expect：根据数据测试，验证 工具方法，n字fix的标没问题
    expect(wordsNfixMap.nfixingWids).toMatchObject([70]);
    // expect：根据数据测试，验证 工具方法，n字fix的标没问题
    expect(wordsMap.nfixingWids).toMatchObject([70]);
    // expect：验证 工具方法，非n字fix的标没问题
    expect(wordsMap.fixedWids).toMatchObject(fixedWids);

    await new Promise(r => setTimeout(r, 2000));
  });

  it("breaking：强制成段5：部分句子挪到pg:2，且分成两句，pt标签变化", async () => {
    const controller = new Controller();
    controller.setLivingMode(true);
    controller.injectSpeakersGetter(() => []);
    controller.injectSpeakersSetter(() => {});
    controller.on("paragraphChangeSpecific", event => {
      event.addParagraphPids.forEach(() => {
        // console.log('------- event', controller.getParagraph(pid));
      });
    });

    controller.processParagraphFrames(normalNFixFrame);

    // expect：unfix的 lastPid下标，应该为 normalNFixFrame 的 尾部pid
    expect(controller.getUnfixPid()).toEqual(`${normalNFixFrame[normalNFixFrame.length - 1].pi}`);

    // 触发强制成段
    controller.processParagraphFrames(paragraphForceBreakFrame5);

    // expect：根据数据测试，unfix的 lastPid下标，应该为 paragraphForceBreakFrame 的 尾部pid
    expect(controller.getUnfixPid()).toEqual(
      `${paragraphForceBreakFrame5[paragraphForceBreakFrame5.length - 1].pi}`
    );

    // expect：根据数据测试，sc 50，由 pi：1，强制成段到了 pi：2
    expect(controller.getPidByWid("50")).toEqual("2");

    expect(controller.getLatestSid()).toEqual("3");
    expect(controller.getFirstWordBySid("2")?.wid).toEqual("50");
    expect(controller.getFirstWordBySid("3")?.wid).toEqual("60");
    expect(controller.getWord("40").sentenceId).toEqual("1");
    expect(controller.getWord("50").sentenceId).toEqual("2");
    expect(controller.getWord("60").sentenceId).toEqual("3");

    const allWids: any[] = [];
    const nFixWids: any[] = [];
    const fixedWids: any[] = [];
    paragraphForceBreakFrame5.forEach(({ pi, sc, partial }) => {
      // expect：对应段落数据，没有丢词
      const pg = controller.getParagraph(pi);
      expect(pg.wids).toMatchObject(sc.map(word => `${word.id}`));
      // expect：验证 段落数据，按预期分段
      expect(pg.isUnfix).toEqual(partial);

      sc.forEach(({ pt, id }) => {
        if (pt) {
          nFixWids.push(id);
        } else {
          fixedWids.push(id);
        }
        allWids.push(id);
      });
    });

    const wordsMap = getNfixingAndFixedWids(controller, allWids);
    // expect：验证 工具方法，n字fix的标没问题
    expect(wordsMap.nfixingWids).toMatchObject(nFixWids);
    const wordsNfixMap = getAvibleNfixingWids(controller, allWids);
    // expect：根据数据测试，验证 工具方法，n字fix的标没问题，因为句子没变，所有50的pt标去除失败（pt理论上跟着sc走）
    expect(wordsNfixMap.nfixingWids).toMatchObject([60]);
    // expect：根据数据测试，验证 工具方法，n字fix的标没问题，因为句子没变，所有50的pt标去除失败（pt理论上跟着sc走）
    expect(wordsMap.nfixingWids).toMatchObject([60]);
    // expect：验证 工具方法，非n字fix的标没问题
    expect(wordsMap.fixedWids).toMatchObject(fixedWids);

    await new Promise(r => setTimeout(r, 2000));
  });

  it("breaking：强制成段6：部分句子挪到pg:2，且分成两句，pt标签变化，且有新增word", async () => {
    const controller = new Controller();
    controller.setLivingMode(true);
    controller.injectSpeakersGetter(() => []);
    controller.injectSpeakersSetter(() => {});
    controller.on("paragraphChangeSpecific", event => {
      event.addParagraphPids.forEach(() => {
        // console.log('------- event', controller.getParagraph(pid));
      });
    });

    controller.processParagraphFrames(normalNFixFrame);

    // expect：unfix的 lastPid下标，应该为 normalNFixFrame 的 尾部pid
    expect(controller.getUnfixPid()).toEqual(`${normalNFixFrame[normalNFixFrame.length - 1].pi}`);

    // 触发强制成段
    controller.processParagraphFrames(paragraphForceBreakFrame6);

    // expect：根据数据测试，unfix的 lastPid下标，应该为 paragraphForceBreakFrame 的 尾部pid
    expect(controller.getUnfixPid()).toEqual(
      `${paragraphForceBreakFrame6[paragraphForceBreakFrame6.length - 1].pi}`
    );

    // expect：根据数据测试，sc 50，由 pi：1，强制成段到了 pi：2
    expect(controller.getPidByWid("50")).toEqual("2");
    expect(controller.getLatestSid()).toEqual("3");
    expect(controller.getFirstWordBySid("2")?.wid).toEqual("50");
    expect(controller.getFirstWordBySid("3")?.wid).toEqual("60");
    expect(controller.getWord("40").sentenceId).toEqual("1");
    expect(controller.getWord("50").sentenceId).toEqual("2");
    expect(controller.getWord("60").sentenceId).toEqual("3");
    expect(controller.getWord("70").sentenceId).toEqual("3");

    const allWids: any[] = [];
    const nFixWids: any[] = [];
    const fixedWids: any[] = [];
    paragraphForceBreakFrame6.forEach(({ pi, sc, partial }) => {
      // expect：对应段落数据，没有丢词
      const pg = controller.getParagraph(pi);
      expect(pg.wids).toMatchObject(sc.map(word => `${word.id}`));
      // expect：验证 段落数据，按预期分段
      expect(pg.isUnfix).toEqual(partial);

      sc.forEach(({ pt, id }) => {
        if (pt) {
          nFixWids.push(id);
        } else {
          fixedWids.push(id);
        }
        allWids.push(id);
      });
    });

    const wordsMap = getNfixingAndFixedWids(controller, allWids);
    // expect：验证 工具方法，n字fix的标没问题
    expect(wordsMap.nfixingWids).toMatchObject(nFixWids);
    const wordsNfixMap = getAvibleNfixingWids(controller, allWids);
    // expect：根据数据测试，验证 工具方法，n字fix的标没问题，因为句子没变，所有50的pt标去除失败（pt理论上跟着sc走）
    expect(wordsNfixMap.nfixingWids).toMatchObject([60, 70]);
    // expect：根据数据测试，验证 工具方法，n字fix的标没问题，因为句子没变，所有50的pt标去除失败（pt理论上跟着sc走）
    expect(wordsMap.nfixingWids).toMatchObject([60, 70]);
    // expect：验证 工具方法，非n字fix的标没问题
    expect(wordsMap.fixedWids).toMatchObject(fixedWids);

    await new Promise(r => setTimeout(r, 2000));
  });
});
