Before Reading

You eat a bee!!! You eat a bee!!!谐音梗不好笑

后面不会再有这么巧的谐音梗了(

其实是说,在我们下面假设的情境中,怎么由A得B(由A得B.jpg

本系列整理了Existimer开发第0阶段的设计思路。这是本系列第二篇讨论,主要从数据结构的视角讨论了任务之间的关系。

Weichky/Existimer
1 更新于2025-12-19 09:12:25

情景假设

用户在复习考研数学。一开始在复习高数,于是创建了“高数”任务。随后进入线性代数复习,又创建了“线代”任务。显然,两者同属于考研数学这一分类。或者在复习高数之后,同时复习线代和概率论。

链表与树

天然的,我们能够想到用链表来描述这一结构。

每一节点除了自己的信息以外,还包括父节点和子节点的信息。这时就有两种可能的数据结构:

class Task {
    String name;
    String uuid;
    // and so on
    // ....
    bool hasChild;
    String parentUuid;
}

或者

class Task {
    String name;
    // ...
    bool hasChild;
    String parentUuid;
    String childUuid;
}

以及两者分别添加bool hasParent后的版本。区别在于一个是单向的,一个是双向的。

有向图

class Task {
    String uuid;
    String name;
    // ....
}

class TaskTransition {
    String fromUuid;
    String toUuid;
    int count;
}

大致是这种数据结构。

不分析了,没理由不用图。关键在于是DG还是DAG,至于更复杂的数据结构,不是这个阶段考虑的。有向图的有向是否必要?我们强调的是一种普遍的关系,而非一种传统的层级。展示顺序是否会破坏这种感觉?我们是否需要有向?这种结构的有向图,比起表示任务之间的关系,似乎更适合拿来做历史。

这并不矛盾。关键在于呈现给用户的是什么。开发者本人并不喜欢思维导图式的,或者知识图谱式的。虽然满满成就感,但是一次性信息量太大。青睐点云、泡泡、词云式的,感受直观的。问题这些元素也过与繁复,似乎只有传统的折叠展开式的。这种去中心的结构可以这样展示:不同Task具有不同颜色;可以把一个Task拖拽到另一个Task上,形成一个连接;基于连接自动算出最大联通,然后通过算法生成一个混色(保证好看,不能简单叠加,但也要体现出一个综合);根据UI放大的不同层级(或利用手势、点击),界面内显示的Task相应的混色或分色(具体方法还需论证。比如分离出液滴?像风车一样圆形展开?像饼状图、环形图一样?)。又产生了新的问题,不同比例下的Color Cluster是否应该有名字?这应当放到统计界面,还是选择任务界面?如果分开制作,选择界面怎么办,是否又要回归层级?(这很重要,人们往往快速开始行动,而后慢慢梳理和统计,选择界面必须足够干净迅速)

在实际使用中,用户往往并不会事先设计好任务之间的结构关系,而是在复习过程中不断跳转、回顾和重组。我们必须允许:

  • 用户开始时仅关心“我现在要做什么”
  • 用户事后才意识到任务之间的关联
  • 一些关联是有意为之(手动标记、拖拽建立关系)
  • 一些关联是无意累积(任务经常交替、同时出现)

因此,数据结构、界面展示与用户行为之间,必须留出弹性空间。


任务关系的数据结构

有向图 + 轻权重连接作为底层关系建模,同时在任务本体中保留最小元信息。

但是实际上呈现出的是无向图,只是方便区分、管理和统计。

Task 节点定义

class Task {
  String uuid;
  String name;
  String? color;       // 手动选择的颜色,也可为空
  String? description; // 可选说明
  DateTime createdAt;
}

每个任务就是一个独立的点,仅包含基础信息,例如 uuid、名称、颜色、创建时间等。

任务之间的“关系边”

关系通过单独的 TaskRelation 表表示,其中包含:

  • 两个任务的 uuid
  • 自动统计的 coOccurrenceCount(例如交替切换次数)
  • 综合权重 weight(可组合自动+手动)
  • 手动连接标记 manuallyLinked
  • 可选的语义标签 tag(如“数学复习组”、“线性相关”)

这种结构允许任意任务之间互相关联,既可以用作分析,也支持 UI 展示。

class TaskRelation {
  String fromUuid;
  String toUuid;

  int coOccurrenceCount; // 自动生成:两个任务在多次切换中共同出现的次数
  double weight;         // 可综合权重(手动增强 + 自动推测)

  bool manuallyLinked;   // 用户是否手动建立了连接(如拖拽)
  String? tag;           // 可选的标签(“数学复习”、“同一章”...)
}

有意 vs 无意关联的处理机制

用户与系统的“认识路径”往往不同步。有些连接是用户主动创造的(手动连接、显式分类),有些是被动形成的(长期使用中自然联想)。

自动关联(系统感知)

系统在后台持续记录任务切换历史,如 A → B、B → A。

  • 累加共同出现次数(co-occurrence)
  • 达到一定阈值后,形成弱连接
  • 用于推荐与聚类,不主动展示

手动关联(用户意图)

用户可以:

  • 拖拽任务建立连接
  • 为连接命名、加权
  • 删除/修改已有连接
  • 提升自动生成连接为“明确结构”

如何协调这两者?

  • 手动连接永远优先,系统不会覆盖。
  • 自动连接仅限于推荐、聚类分析或可视化展示。
  • 用户可以随时将“自动边”升级为“手动边”,使其参与结构可视。

开始页面(任务选择界面)设计原则

用户在执行前的目标是快速进入状态,而不是理解结构或编辑任务。应遵循以下三条原则:

  1. 极简启动:尽可能少的操作和认知负担
  2. 最小必要信息:当前任务、常用任务、推荐任务
  3. 延迟结构管理:不强迫分类、分组、关联,后期整理再处理

考虑的组织方式

  • 顶部展示当前正在进行的任务(若有)
  • 列出最近使用的任务(按时间排序)
  • 推荐任务区块:根据图结构推荐可能相关的任务(如最近频繁与当前任务一同使用)
  • 搜索栏:允许用户查找全部任务
  • 快速创建新任务按钮(颜色预设、默认空结构)

此界面以列表为主,避免展开式结构(如思维导图、嵌套层级),因为那会干扰用户进入任务状态。

这个方案强调三点:

  1. 结构与行为分离:任务的“结构”不应强加于“使用行为”之上,应该由使用中自然演化。
  2. 弱连接建模:通过无向边和轻权重的方式,保留用户操作自由度,也为后续图谱可视化与任务推荐打基础。
  3. 延迟结构化策略:结构的建立并非前置需求,而是一种“事后理解”的工具。

未来可以进一步考虑:

  • 自动聚类(基于图社区检测)并建议用户命名任务集
  • 用视觉元素展示结构(如点云、环图、聚类气泡)
  • 引入“颜色空间算法”让聚类任务形成自然、美观的视觉块
  • 在统计页提供“任务星系”、“学习路径回溯”等图谱式结构浏览器