【Godot4.3】题目与答案解析合并器

免责申明
本文和工具截图中涉及题库和题目,均为本人自学使用,并未有商业和传播企图。如有侵害,联系删改。

概述

笔者本人医学专业从业人员,编程只是业余爱好。在自己的专业应考学习过程当中:

  • 有时候不太喜欢纸质题库的排版,比如题目与答案分开,甚至是分开在两本书上。
  • 想要翻录下来,转存到笔记软件中,作为自己积累的一个题库,而且方便随时查看、修改和扩充笔记。

这项工作,我从2024年头就开始实践,并且已经积累了一定的题目量。作为专业学习和考试的专用复习资料。

翻录操作

我的具体做法是:

  • 摊开书,翻页,手机拍照后转存PDF
  • 在WPS中进行扫描件识别,获取文本
  • 在VSCode中进行批量替换和初步处理
  • 复制到笔记软件(我用的是语雀),进行更详细的优化排版
  • 学习和补充笔记,手机随时查看记忆
  • 选择性打印为册子,方便查看

翻录环节一直是很顺畅和熟练的。但是,后续处理有时候比较麻烦。尤其是很多纸质题库是将题目和参考答案以及解析分开的。手动排版是个海量的工作。因此,需要编程实现题目与答案的合并。

之前的Python版本

2024年11月11日创建的Python版本,其原理是:

  • 把题目和答案都预处理为---分隔的形式
  • 各自拆分为字符串数组,检测题目总数和答案总数一致后,进行题目和答案解析的合并
# 读取文件内容
def read_file(path):with open(path, 'r',encoding="utf-8") as file:content = file.read()return content# 读取文件内容
def save_file(path,content):with open(path, 'w',encoding="utf-8") as file:content = file.write(content)# 获取题目和答案合并的结果
def get_result(qus_path,ans_path):result = ""qus = read_file(qus_path) # 问题ans = read_file(ans_path) # 答案# 用 --- 划分qus_arr = qus.split("---")ans_arr = ans.split("---")if len(qus_arr) == len(ans_arr): # 答案和题目数量一致# 遍历生成合并字符串for i in range(len(qus_arr)):q = qus_arr[i]a = ans_arr[i]result += f"""{q}
:::tips
{a}
:::"""return resultsave_file("result.md",get_result("qus.txt","ans.txt"))

这个版本的坏处的,必须依靠VSCode和工作目录,并且需要将题目和答案分别存储到固定名称的文件中。

而字符串处理的大部分操作还是需要手动在VSCode中进行。

创建Godot版本

为了更方便快捷的合并,编写了一个简单的Godot应用。

  • 用Godot创建合并器,以复制粘贴文本形式,而不是文件形式,处理起来会更灵活。
  • 而且代码和处理的灵活性也会进一步上升

初步界面设计

初期界面规划

初步实现

extends HSplitContainer
@onready var qus_txt: TextEdit = %qusTxt
@onready var ans_txt: TextEdit = %ansTxt
@onready var result_txt: TextEdit = %resultTxt# ================================= 按钮点击 =================================
# 整体添加分隔线
func _on_splits_btn_pressed() -> void:qus_txt.text = add_splits(qus_txt.text)ans_txt.text = add_splits(ans_txt.text)# 执行合并
func _on_join_btn_pressed() -> void:result_txt.text = do_joins_result(qus_txt.text,ans_txt.text)pass# ================================= 自定义方法 =================================
# 查找题目或答案序号,并添加 --- 分隔符
func add_splits(old_str:String) -> String:var regex = RegEx.new()regex.compile(r"\n\d\.")for result in regex.search_all(old_str):var res = result.get_string()old_str = old_str.replace(res,"\n --- %s" % res)return old_str# 执行合并
func do_joins_result(qus_str:String,ans_str:String) -> String:var result:PackedStringArray = []var qus_arr = qus_str.split("---",false)var ans_arr = ans_str.split("---",false)if qus_arr.size() == ans_arr.size(): # 题目数量与答案解析数量一致# 遍历生成合并字符串for i in range(qus_arr.size()):var qus = qus_arr[i]var ans = ans_arr[i]result.append(qus_ans_str(qus,ans))return "\n".join(result)# 根据模版字符串生成题目和答案解析的合并字符串
func qus_ans_str(qus:String,ans:String) -> String:var tmp = """%s
:::tips
%s
:::""" % [qus,ans]return tmp

已经实现基础的题目与答案解析合并功能,复制到语雀自动识别后,也是可以正常显示:

编写处理类

上面将处理逻辑编写为三个函数,混杂在主场景中,显得并不优秀。

好的办法是进一步编写类,来固定处理相似的逻辑。这样也就让逻辑和UI部分分离了。

新类设想

  • 新的类将自动处理输入的普通的题目和答案解析字符串,并维护题目和答案两个数组
  • 将可以编写简单的题库系统,顺序查看题目和答案

新类实现

# =========================================================
# 名称:QusAnsList
# 类型:GDSCript类
# 描述:解析和处理普通的题目和答案解析字符串,生成合并字符串的处理类
# Godot版本:v4.3.stable.steam [77dcf97d8]
# 创建时间:202521213:08:13
# 最后修改时间:202521221:38:46
# =========================================================
class_name QusAnsList
# 切分后的题目与答案集合
var qus_arr:PackedStringArray
var ans_arr:PackedStringArray# 原始字符串
var qus_str:String
var ans_str:String
# 添加分隔符后的字符串
var split_qus_str:String
var split_ans_str:String# 创建实例
func _init(qus_str:String,ans_str:String) -> void:self.qus_str = inline_opts(qus_str)self.ans_str = ans_str# 添加分隔线self.split_qus_str = add_lines(self.qus_str,true)self.split_ans_str = add_lines(ans_str)# 分割添加了分隔线的字符串,获得题目与答案集合splits()# ================================ 方法 ================================# 将ABCDE选项放置到一行
func inline_opts(old_str:String) -> String:var new_str = old_strfor opt in ["B","C","D","E"]:new_str = new_str.replace("\n%s." % opt,"%s%s." % ["\t".repeat(2),opt])return new_str# 查找题目或答案序号,并添加 --- 分隔符
# old_str 要添加分隔符的原始字符串
# ignore_first 是否忽略第一项,用于题目序号不是在第一行的情况
func add_lines(old_str:String,ignore_first:=false) -> String:# 创建对序号的正则匹配var regex = RegEx.new()regex.compile(r"\n\d+\.")# 遍历所有搜索到的序号,替换为 --- var results = regex.search_all(old_str)for i in range(results.size()):if ignore_first and i==0: # 忽略第一次continuevar res = results[i].get_string()old_str = old_str.replace(res,"\n---%s" % res)return old_str# 分割添加了分隔线的字符串获得题目与答案集合
func splits() -> void:qus_arr = split_qus_str.split("\n---\n",false)ans_arr = split_ans_str.split("\n---\n",false)# 检测题目与答案集合的数目是否相等
func is_qus_equal_ans_count() -> bool:return qus_arr.size() == ans_arr.size()# 获取执行合并的字符串
func get_joins_result() -> String:var result:PackedStringArray = []if qus_arr.size() == ans_arr.size(): # 题目数量与答案解析数量一致# 遍历生成合并字符串for i in range(qus_arr.size()):var qus = qus_arr[i]var ans = ans_arr[i]result.append(qus_ans_str(qus,ans))return "\n".join(result)# 根据模版字符串生成题目和答案解析的合并字符串
func qus_ans_str(qus:String,ans:String) -> String:var tmp = """%s
:::tips
%s
:::""" % [qus,ans]return tmp

基于新类,主场景的代码简化如下:

extends HSplitContainervar QAlist:QusAnsList
var current_index:int = 0@onready var qus_txt: TextEdit = %qusTxt
@onready var ans_txt: TextEdit = %ansTxt
@onready var result_txt: TextEdit = %resultTxt
@onready var tk_qus_txt: CodeEdit = %tkQusTxt
@onready var tk_ans_txt: CodeEdit = %tkAnsTxt# ================================= 按钮点击 =================================# 执行合并
func _on_join_btn_pressed() -> void:QAlist = QusAnsList.new(qus_txt.text,ans_txt.text)result_txt.text = QAlist.get_joins_result()# 题库显示第一题show_tk_qus_ans(0)# 题库显示指定的第几题
func show_tk_qus_ans(index:int) -> void:tk_qus_txt.text = QAlist.qus_arr[index]tk_ans_txt.text = QAlist.ans_arr[index]# 显示上一题
func _on_last_btn_pressed() -> void:current_index = clamp(current_index-1,0,QAlist.qus_arr.size()-1)show_tk_qus_ans(current_index)# 显示下一题
func _on_next_btn_pressed() -> void:current_index = clamp(current_index+1,0,QAlist.qus_arr.size()-1)show_tk_qus_ans(current_index)

程序效果

一键处理和合并题目与答案

  • 生成合并字符串并进行展示,可以复制到语雀中自动识别和排版

生成题库预览

  • 因为新类内部维护两个数组,存储题目和答案
  • 所以可以搭建简易的题库预览界面,来按顺序查看每一道题目

后续改进

界面分开

  • 将界面分为合并器和题库预览两部分,通过顶栏的按钮进行界面的切换

分开后的合并器主界面

分开后的题库预览界面,字号做了相应放大

题号列表

  • 只通过上一题,下一题查看题库并不方便,可以生成题号按钮,点击快速查看。

修改题库预览界面样式

  • 两边留白,让视野宽度略小于屏幕宽度,中心聚焦且看的不是太累。

刷题计时器

  • 设计一个简单的刷题计时器,可以重置、开始、暂停,用以记录刷题时间
  • 首先是编写一个函数获取累计时间的HH:MM:SS形式字符串
# 返回累计时间的时分秒的字符串形式 HH:MM:SS
func get_time_str(time:int) -> String:var dic = Time.get_time_dict_from_unix_time(time)return "%02d:%02d:%02d" % [dic["hour"],dic["minute"],dic["second"]]
# 返回累计时间的时分秒的字符串形式 HH小时MMSS秒
func get_time_str(time:int) -> String:var dic = Time.get_time_dict_from_unix_time(time)return "%02d小时%02d分%02d秒" % [dic["hour"],dic["minute"],dic["second"]]
  • 接着就是使用和控制Timer节点显示累计时间

UI美化

加载和保存题库

  • 题库文件是题目和答案用特殊解析字符串#================;所连接的纯文本文件

总结

  • 至此,意为着利用纯文本形式的题目和答案字符串,快速合并获得适用于语雀显示的格式将变得异常方便
  • 同时,可以以非常简便的方式创建刷题系统。只需要维护和保存一堆.txt文件即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/70556.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Lm studio本地部署DeepSeek

为什么用Lm studio Ollama官网下载过慢或失败(Lm默认下载源无法下载,但可以更换下载源)Ollama默认安装至C盘一部分Nivida显卡无法吃满显存资源一部分AMD显卡替换rocm文件后无法启动 Lm studio安装 官网下载:LM Studio - Discov…

基于Qlearning强化学习的2DoF机械臂运动控制系统matlab仿真

目录 1.算法仿真效果 2.算法涉及理论知识概要 2.1 2DoF机械臂运动学模型 2.2 Q-learning强化学习算法原理 3.MATLAB核心程序 4.完整算法代码文件获得 1.算法仿真效果 matlab2022a仿真结果如下(完整代码运行后无水印): 仿真操作步骤可参…

Unity贴图与模型相关知识

一、贴图 1.贴图的类型与形状 贴图类型 贴图形状 2.在Unity中可使用一张普通贴图来生成对应的法线贴图(但并不规范) 复制一张该贴图将复制后的贴图类型改为Normal Map 3.贴图的sRGB与Alpha sRGB:勾选此选项代表此贴图存储于Gamma空间中…

快速上手 Unstructured:安装、Docker部署及PDF文档解析示例

1. 核心概念 1.1 Unstructured简介 Unstructured 是一个强大的 Python 库,专注于从非结构化数据中提取和预处理文本信息,广泛应用于 PDF、Word 文档、HTML 等多种格式的文件处理。其核心功能包括分区、清理、暂存和分块,能够将复杂的非结构化文档转换为结构化输出,为后续…

pyecharts介绍

文章目录 介绍安装pyecharts基本使用全局配置选项 折线图相关配置地图模块使用柱状图使用 介绍 echarts虑是个由百度开源的数据可视化,凭借着良好的交互性,精巧的图表设计,得到了众多开发者的认可,而Pyhon是门富有表达力的语言&a…

Fisher信息矩阵与Hessian矩阵:区别与联系全解析

Fisher信息矩阵与Hessian矩阵:区别与联系全解析 在统计学和机器学习中,Fisher信息矩阵(FIM)和Hessian矩阵是两个经常出现的概念,它们都与“二阶信息”有关,常用来描述函数的曲率或参数的敏感性。你可能听说…

python与C系列语言的差异总结(1)

/ 表示浮点除法 // 表示整数除法 print(8/3)print(8//3)布尔型 False/True 首字母大写 整数的大小是没有限制的,会根据需要自动增长,仅受限于可用内存的大小。 m**n表示m的n次方 x 4.3 ** 2.4print(x)print(3.5e30 * 2.77e45)print(1000000001.0 *…

Python selenium 库

Selenium 是一个用于自动化 Web 浏览器操作的强大工具,广泛应用于 Web 应用程序测试、网页数据抓取和任务自动化等场景。 Selenium 为各种编程语言提供了 API,用作测试。 目前的官方 API 文档有 C#、JavaScript、Java、Python、Ruby。 安装 Selenium 和…

vllm部署LLM(qwen2.5,llama,deepseek)

目录 环境 qwen2.5-1.5b-instruct 模型下载 vllm 安装 验证安装 vllm 启动 查看当前模型列表 OpenAI Completions API(文本生成) OpenAI Chat Completions API(chat 对话) vllm 进程查看,kill llama3 deep…

Python NumPy库使用指南:从入门到精通

1. 引言 NumPy(Numerical Python)是 Python 中用于科学计算的核心库之一。它提供了强大的多维数组对象(ndarray),以及一系列高效的数学函数,能够轻松处理大规模的数值数据。NumPy 是许多其他科学计算库(如 Pandas、Matplotlib、Scikit-learn 等)的基础。 本文将详细介…

15.2 智能销售顾问系统技术架构解密:构建企业级知识驱动型对话引擎

智能销售顾问系统技术架构解密:构建企业级知识驱动型对话引擎 关键词:RAG 架构设计、销售知识库系统、LoRA 微调优化、多模态交互引擎、高并发服务部署 1. 系统技术架构全景解析 1.1 核心架构设计图 #mermaid-svg-UBkTgaR5lf5WfGMa {font-family:"trebuchet ms",…

用PyTorch从零构建 DeepSeek R1:模型架构和分步训练详解

DeepSeek R1 的完整训练流程核心在于,在其基础模型 DeepSeek V3 之上,运用了多种强化学习策略。 本文将从一个可本地运行的基础模型起步,并参照其技术报告,完全从零开始构建 DeepSeek R1,理论结合实践,逐步…

爬虫基础入门之爬取豆瓣电影Top250-Re正则的使用

网址:豆瓣电影 Top 250 本案例所需要的模块 requests (用于发送HTTP请求)re (用于字符串匹配和操作) 确定需要爬取的数据 : 电影的名称电影的年份电影的评分电影评论人数 一. 发送请求 模拟浏览器向服务器发送请求 准备工作 -分析页面: F12 or 右击点击检查 查看…

力扣hot100——岛屿数量 岛屿问题经典dfs总结

给你一个由 1(陆地)和 0(水)组成的的二维网格,请你计算网格中岛屿的数量。 岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。 此外,你可以假设该网格的四条边…

FPGA DSP:Vivado 中带有 DDS 的 FIR 滤波器

本文使用 DDS 生成三个信号,并在 Vivado 中实现低通滤波器。低通滤波器将滤除相关信号。 介绍 用DDS生成三个信号,并在Vivado中实现低通滤波器。低通滤波器将滤除较快的信号。 本文分为几个主要部分: 信号生成:展示如何使用DDS&am…

MessageAuthenticator

MessageAuthenticator https://coova.github.io/JRadius/ https://coova.github.io/JRadius/ import org.tinyradius.packet.RadiusPacket; import org.tinyradius.util.RadiusUtil; import java.nio.charset.StandardCharsets;public class RadiusAuthUtils {/*** 生成 RADI…

Spring Boot嵌入式服务器深度解析:从配置到调优的全方位指南

文章目录 引言一、嵌入式服务器核心原理1.1 架构设计特点1.2 主流服务器对比 二、嵌入式服务器配置实战2.1 基础配置模板2.2 HTTPS安全配置 三、高级调优策略3.1 线程池优化(Tomcat示例)3.2 响应压缩配置3.3 访问日志配置 四、服务器切换实战4.1 切换至U…

基于CentOS7安装kubesphere和Kubernetes并接入外部ES收集日志

一、修改所有节点主机名 主节点就修改成master hostnamectl set-hostname master 然后输入bash刷新当前主机名 工作节点1就修改成node1 hostnamectl set-hostname node1 然后输入bash刷新当前主机名 二、全部节点安装依赖并同步时间 yum -y install socat conntrack ebta…

探索与Cursor协作创建一个完整的前后端分离的项目的最佳实践

探索与Cursor协作创建一个完整的前后端分离的项目的最佳实践 Cursor简介 Cursor在目前代表了AI编程技术的顶峰。在一定程度上可以说是当今AI时代的最强生产力代表。为此,不惜重金开了年费会员来紧跟时代步伐。当然cline、roo code、trae等开源或者免费产品也在紧追不舍。 C…

支持向量机(SVM)在 NLP 中的使用场景

支持向量机(Support Vector Machine, SVM)是一种强大的监督学习算法,广泛应用于分类任务中。由于其出色的分类性能和高效的计算特点,SVM 已经成为自然语言处理(NLP)领域中的一种经典模型。SVM 在 NLP 中的应用非常广泛,尤其在文本分类任务中,表现出色。 本文将探讨 SV…