nocriz的博客

苔花如米小,也学牡丹开。

呼吁广大选手积极参与开发下一代OIerDb

12/27 UPD: 下一代OIerDb前端项目在 https://github.com/OIerDb-ng/OIerDb

引言

OI巨神虞皓翔同学开发的下一代OIerDb项目现在在GitHub上开源,访问该项目的方法是前往OIerDb-ng/OIer中的oierdb-ng分支或点击此链接。新项目采用了浏览器前端存储的方式存储数据,在每次用户尝试询问时不需要访问服务器,但在数据更新或第一次访问时需要下载所有数据。

这个项目目前实现的逻辑和当前的OIerDb差不多,但新的项目的代码更加工程和正规,因此对于新人更友好,更适合进行扩展。新项目也处在还没有前端的开发的中间阶段,我感到因此这个项目可以从头就做的更好。这就需要更多选手参与进这件事情。由于我时间比较有限,我在此打一个广告呼吁广大对信息学竞赛感兴趣的朋友们积极参与开发OIerDb-ng,并发表一点我对新项目开发的一点看法。

数据存储结构以选手、获奖记录、学校分别同等对待

当前OIerDb数据存储结构有两个表,其中一个表为选手表,存储着形如(UID,姓名,拼音,年级,(获奖记录 1,获奖记录2,获奖记录3,…)…)的信息,另一表为学校表,存储着形如(省份,地市,学校名称,学校获奖统计,学校分数,…)的信息。

我感觉如果可以所有数据都在浏览器处理,可以在选手表和学校表之外另建一获奖记录表,存储形如(UID,姓名,学校,排名,分数,比赛,年级,奖项,…)的信息,而不直接存在选手表对应选手内。

这样有一点好处,就是可以处理以获奖记录为中心的询问:(显示NOIP2021中山东大学附属中学的获奖记录)。另外有可能可以使得每次数据更新时产生的diff更可控(?)

统一询问的逻辑,添加以获奖记录为中心询问的功能

感觉前端实现时,如果不同的表是分开的逻辑比较清晰,大概就是“给出一定的限定信息,查询某个表”。比如查询信息学竞赛选手,无论“限定信息”是如何给出的,大体逻辑还是要找到对应的选手。在当前的OIerDb上点击选手时,显示了选手的所有获奖记录,这个逻辑在获奖记录不和选手存储在一起时也非常简单:“询问所有当前点击的UID的获奖记录”。

对应的,对于获奖记录和学校也可以这么做。这么一来,就可以查询获奖记录了,如“查询济南市NOIP获奖记录”,“查询某年NOI获奖记录”,“查询某校全部NOI获奖记录”等等。查询学校也可以类似做,我们可以发现这么一来查询的能力是严格比当前的OIerDb优的,因为当前查询学校只能按照省份和地市选。

对应的,如果点击获奖记录的姓名栏,逻辑可同“询问所有当前点击的UID的获奖记录”一样,跳转到查询人,点击学校栏,可以直接查询对应学校。这样非常符合逻辑。

在数据更新时,充分利用数据更新差异较小的特性

据我观察OIerDb-ng的数据压缩之后只有不到2M,其实已经很小了。但是考虑到有些机器和情况网络连接确实较慢,除了想办法把服务器搞快之外也可以考虑采取一些措施使得“获取新数据”这一步传输远小于2M的量,如只传输一个“区别”文件再在客户端实现具体的“区别”。

感觉上如果希望服务器端静态实现的话,可以在生成数据时维护“当客户端数据的hash为某个版本时,应当执行什么操作”的文件。感觉逻辑上当数据差距不大,就说“将某个地方如何修改一下,再重新解释数据”,差距大时就说“直接重新解释如下的数据”。

结语

希望广大对信息学竞赛感兴趣的朋友们积极参与开发OIerDb-ng,想到更多使得项目变好的方法并开发出一个能用的用户界面,共同为信息学竞赛选手作出贡献。


评论

《 “呼吁广大选手积极参与开发下一代OIerDb” 》 有 7 条评论

  1. 我正在着手编写 OIerDb NG 的前端界面。

    演示:https://oier.baoshuo.dev
    源代码:https://github.com/renbaoshuo/OIerDb

    1. nocriz 的头像
      nocriz

      牛逼

  2. 前端的数据存储考虑一下用 WebAssembly编译后的sqLite加上浏览器提供的IndexedDB数据库存储?

  3. ghrk 的头像
    ghrk

    我发现有一些选手的记录存在问题,包括自己把年级填错了还有各种奇奇怪怪的原因,还有一些学校是一个学校结果每年报名名称不一样,导致选手的记录总是左右横跳,希望新增一个信息维护组,接受用户的debug,把这样的问题屏蔽掉(比如有一位同学存在两次初一的获奖记录,我私下去问是因为初二的他年级填成了初一)

  4. mashduihca 的头像
    mashduihca

    新版好像不能按城市搜索了?

  5. 不知道为什么发的评论不显示?

  6. 再写一遍罢:
    后端对学校,奖项,等等做离散化,只传编号
    而编号所对应的数据使用sql.js https://github.com/sql-js/sql.js 和 localStorage https://localforage.github.io/localForage 存储到前端
    地区传区号,对应的名称可以使用大公司的cdn获取

    对于信息发送,有更简单的地方:
    将json转化为普通的字符串,使用换行符和” | “分割,例如:`1 1 1 1 1 张三`
    使用fetch动态获取字符串,使得可以再http请求到一半的情况下就有数据使用
    对于传的数据不使用任何压缩(如果动态获取这个是非常重要的!)

回复 mashduihca 取消回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注