HarmonyOS应用实战-启示散页-05-随机抽答案要避免连续重复:把算法放进服务层

发布时间:2026/9/14 21:58:31

HarmonyOS应用实战-启示散页-05-随机抽答案要避免连续重复:把算法放进服务层 HarmonyOS应用实战-启示散页-05-随机抽答案要避免连续重复把算法放进服务层答案之书的核心体验是“提问后给一个答案”。如果连续两次抽到同一句用户会立刻觉得应用敷衍如果页面自己写随机算法动画页、快捷入口和未来的小组件入口又可能各抽各的。随机不是 UI 小细节它是产品体验规则应该放在服务层统一处理。这篇文章会把问题拆成四个可落地的点把抽取算法从页面移到 AnswerDrawService。用最近结果窗口降低连续重复概率。区分候选池、运行期状态和展示动画。给出小题库、空题库、过滤后无结果的兜底策略。1. 随机体验不等于 Math.randomMath.random()能给出随机下标但不能保证体验。题库只有十几条时连续重复很容易出现用户提问后看到同一句答案会把算法概率理解成产品问题。答案之书把抽取逻辑放进 Service让所有入口都使用同一套规则。interfaceDrawAnswerOptions{deckId:string;question?:string;excludeRecent?:boolean;}interfaceDrawAnswerResult{deckId:string;answer:Answer;drawnAt:number;question?:string;}抽取结果不是一段文本而是带题库、问题和时间的领域结果。这样后续收藏和历史才能拿到完整来源。2. 候选池先由 Service 准备页面不应该自己加载题库再筛答案。Service 先读取当前题库过滤空答案再决定是否允许抽取。空题库、损坏题库、当前题库不存在都在这里统一兜底。asyncdraw(options:DrawAnswerOptions):PromiseDrawAnswerResult{constdeck:Deck|nullawaitDeckRepository.loadDeck(options.deckId);if(!deck){thrownewError(当前题库不存在请重新选择题库);}constcandidates:Answer[]deck.answers.filter((item:Answer):booleanitem.text.trim().length0);if(candidates.length0){thrownewError(当前题库没有可抽取的答案);}returnthis.pickFromCandidates(deck.id,candidates,options.question);}候选池准备属于业务层。页面只关心成功展示或失败提示不应该处理题库损坏的细节。3. 最近窗口只影响选择不改题库避免连续重复不需要修改题库顺序也不需要给答案加权。答案之书维护一个运行期 recent 窗口抽取时优先排除最近出现过的答案如果题库太小导致排除后为空就退回全量候选。privatereadonlyrecentAnswerIds:string[][];privatereadonlyrecentLimit:number3;privatefilterRecent(candidates:Answer[]):Answer[]{constfiltered:Answer[]candidates.filter((item:Answer):boolean{return!this.recentAnswerIds.includes(item.id);});returnfiltered.length0?filtered:candidates;}recent 是运行期体验状态不是持久化数据。它影响下一次抽取但不改变用户题库内容。4. 选中后再更新 recentrecent 窗口要在抽取成功后更新不能在动画结束后才更新。否则用户快速连续点击时第二次抽取仍可能看到旧窗口。Service 返回结果前完成状态更新页面动画只负责表现。privateremember(answerId:string):void{this.recentAnswerIds.unshift(answerId);constunique:string[][];this.recentAnswerIds.forEach((id:string):void{if(!unique.includes(id)){unique.push(id);}});this.recentAnswerIds.splice(0,this.recentAnswerIds.length,...unique.slice(0,this.recentLimit));}这段代码把 recent 维护成去重队列。它不追求复杂概率只解决连续重复这个最刺眼的体验问题。5. 随机下标封装成可替换方法本地小应用不需要一上来引入复杂随机库但随机方法应该集中。未来如果要做权重、节日题库或测试可复现只改一个方法不需要翻页面代码。privatechooseIndex(total:number):number{returnMath.floor(Math.random()*total);}privatepickFromCandidates(deckId:string,candidates:Answer[],question?:string):DrawAnswerResult{constpool:Answer[]this.filterRecent(candidates);constanswer:Answerpool[this.chooseIndex(pool.length)];this.remember(answer.id);return{deckId,answer,question,drawnAt:Date.now()};}集中封装不是为了过度抽象而是为了让体验规则只有一个出口。6. DrawingPage 只处理状态机抽取页最容易把算法、动画和导航揉在一起。答案之书更稳的写法是页面进入 loading调用 Service 拿结果进入 revealing动画结束后进入 done。答案是什么由 Service 决定页面只负责让结果被看见。typeDrawingStateidle|drawing|revealing|done|error;StateprivatedrawingState:DrawingStateidle;StateprivatecurrentResult:DrawAnswerResult|nullnull;privateasyncstartDraw():Promisevoid{this.drawingStatedrawing;try{this.currentResultawaitAnswerDrawService.draw({deckId:this.deckId,question:this.question});this.drawingStaterevealing;}catch(err){this.drawingStateerror;}}状态机让页面逻辑可读也让失败态有入口。抽取失败不应该停在半段动画里。7. 收藏和历史使用同一个 DrawAnswerResult如果收藏只存文本历史又存 question后续就无法判断同一句答案来自哪个题库。抽取 Service 返回完整结果后收藏和历史都使用同一份来源信息能减少数据对不上的问题。awaitHistoryService.append({deckId:result.deckId,answerId:result.answer.id,answerText:result.answer.text,question:result.question,createdAt:result.drawnAt});抽取结果是后续功能的源头。源头字段完整收藏、历史、分享才不会各自补猜。8. 小题库要接受重复但不连续卡死如果题库只有两条答案强行不重复会很快无候选。Service 的策略应该是尽量避免最近重复但候选池为空时回退全量。这比一直重试随机更稳也不会出现死循环。constpool:Answer[]candidates.lengththis.recentLimit?this.filterRecent(candidates):candidates;constanswer:Answerpool[this.chooseIndex(pool.length)];体验规则要尊重数据规模。小题库允许重复但仍可以避免最常见的连续同一句。9. 验证与排障抽取验证不要只看“点一次有答案”。要连续抽 20 次观察重复分布切换题库后 recent 是否影响新题库空题库是否给出错误提示收藏和历史是否拿到同一个结果来源。验证点 1. 同一题库连续抽取不频繁出现相邻重复 2. 两条答案的小题库不会死循环 3. 当前题库不存在时页面进入 error 状态 4. 收藏记录包含 deckId、answerId、answerText 5. 历史记录 createdAt 使用抽取结果时间如果动画页偶发空白先看 Service 是否抛错后页面没有进入 error而不是先调整动画时间。验证清单清应用数据后从冷启动进入确认默认数据、页面状态和日志分支符合预期。对本文涉及的写路径准备正常、空值、重复、越界四类输入确认错误停在 Service 或 Repository。页面返回、重新进入、切换题库、收藏、历史或删除后确认对应刷新信号触发重新读取。修改资源或模块归属后重新构建确认 HAP、HAR、HSP 的依赖方向没有反转。涉及真机体验、备份恢复、发布素材的内容单独记录是否已经在设备或平台侧验证。常见问题与处理现象先看哪里处理方式连续抽到同一句recentAnswerIds 是否更新抽取成功后立即记入 recent小题库抽取卡住是否在 while 中强行排重排除后为空就回退全量候选收藏来源丢失是否只保存 answerText保存 DrawAnswerResult 中的 deckId 和 answerId切换题库后结果异常recent 是否跨题库污染recent 可按 deckId 分组或切换时清空小结随机抽取是产品规则不是页面按钮里的临时表达式。把候选池、recent 窗口、结果来源都放进服务层答案之书的核心体验才有一致性。
延伸阅读

更多相关文章

2026/9/14 21:57:29

如何快速恢复丢失的Ren‘Py游戏源码:终极反编译工具指南

如何快速恢复丢失的RenPy游戏源码:终极反编译工具指南 【免费下载链接】unrpyc A renpy script decompiler 项目地址: https://gitcode.com/gh_mirrors/un/unrpyc 你是否曾经遇到过RenPy游戏项目源码丢失的尴尬情况?或者需要分析已编译的游戏脚本…

2026/9/10 1:49:31

ADC药物研发热潮:技术突破与市场机遇

1. ADC药物赛道为何持续升温?抗体偶联药物(Antibody-Drug Conjugate,简称ADC)作为肿瘤靶向治疗的"生物导弹",近年来已成为全球医药研发最炙手可热的领域之一。根据Evaluate Pharma数据,2023年全球…

2026/9/14 9:25:43

信息素养大赛C++解题:从最大公约数看“必然事件”类数论问题

最近在准备信息素养大赛的同学,特别是C赛道的选手,常常会遇到一类题目:它不单纯考察语法,而是将编程逻辑与数学、概率等基础学科知识紧密结合,考察选手的综合素养。“必然事件”就是其中一道非常经典的题目&#xff0c…

2026/9/14 21:55:36

数据结构学习必备:C语言指针与内存管理核心技能

1. 为什么学数据结构前必须掌握C语言基础第一次接触数据结构课程的学生,经常会在指针操作和内存管理上栽跟头。上周刚有个大二学生找我调试代码,他的双向链表删除操作总是导致段错误,排查后发现是没处理好前驱节点的指针关系——这正是典型的…

2026/9/14 21:55:36

AI辅助论文写作工具实测:千笔与锐智AI如何提升研究生写作效率

研究生阶段写论文,最折磨人的往往不是研究本身,而是把研究变成一篇逻辑严密、表达精准的学术文章。尤其是第一次写小论文或者硕士大论文的时候,从选题到大纲,从文献综述到结论表述,每一步都像是在黑暗里摸石头。我自己…

2026/9/14 21:55:36

基于微信小程序的智能垃圾分类助手系统毕业设计项目源码

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

2026/9/14 21:50:35

手把手打造汽车360°全景影像:鱼眼相机标定与图像拼接实战

1. 项目整体设计与思路拆解1.1 到底什么是“上帝视角”“gods-eye-view”这个项目名听着唬人,说白了就是一套 360 环视俯视影像系统。车上装四路鱼眼摄像头,分别朝前、后、左、右看,然后通过图像处理把四路画面拼成一张从正上方俯视车辆的完整…

2026/9/14 2:17:50

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/14 0:03:22

KCF目标跟踪算法与OTB工程实现:毕业设计实战解析

简介:这是一份基于KCF核相关滤波算法、融合尺度池与抗遮挡处理的目标检测跟踪MATLAB完整源码,主要面向计算机相关专业准备毕业设计、课程设计或期末大作业的学生,也适合需要项目实战练习的初学者。源码在OTB数据集上完成验证,能够…

2026/9/14 0:03:22

语音情感识别实战:Keras实现LSTM、CNN、SVM与MLP多模型对比

简介:面向语音情感识别入门与进阶开发者,这份基于Keras的项目源码完整实现了LSTM、CNN、SVM、MLP四种模型,兼容Python3.8与Keras/TensorFlow2环境。压缩包内含49个文件,大小约70.31MB,主体包括Python脚本、yaml/json配…

2026/9/14 11:59:31

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/14 13:53:59

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/14 11:22:57

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码