# ZenDAS

## 功能结构

* **项目管理**
  * 项目1（`project`）
    * **数据源管理（`datasource`）**
      * 数据源1
      * 数据源2
    * **分析管理（`solution`）**
      * 分析1
        * 数据（创建分析时从数据源生成）
        * **分析方案管理（`analysis`）**
          * 分析方案1
            * 数据过滤
            * **分析报告**
              * 报告区块1：分析方法1+参数+结果+备注
              * 报告区块2：分析方法2+参数+结果+备注
          * 分析方案2
      * 分析2
  * 项目2

## DataFrame

DataFrame 为用于分析的数据，通常使用一个对象来进行定义，主要包括如下属性：

| 属性名    | 类型       | 可选性 | 说明                                                     | 示例                                                         |
| --------- | ---------- | ------ | -------------------------------------------------------- | ------------------------------------------------------------ |
| `data`    | `any[][]`  | 必须   | 数据定义。使用而为数组来定义每行每列上的数据。           | `[[123, 520, 21, '21-01-03', '21-01-23', 15], [13, 20, 1, '21-01-03', '21-01-23', 10]]` |
| `columns` | `string[]` | 可选   | 列名定义                                                 | `['需求数', '功能点数', '人数', '开始时间', '结束时间', '天数']` |
| `index`   | `string[]` | 可选   | 行名定义                                                 | `['第一期', '第二期']`                                       |
| `dtypes`  | `string[]` | 可选   | 列数据类型定义。通过一个数组来依次定义每一列上的数据类型 | `['int', 'float', 'int', 'datetime', 'datetime', 'int']`     |
| `name`    | `string`   | 可选   | 数据表名称                                               | `'2022年上半年禅道迭代投入'`                                 |

其中**列数据类型**定义包括：

| 类型       | 说明                                                           |
| ---------- | -------------------------------------------------------------- |
| `int`      | 整形，可以直接用于计算                                         |
| `float`    | 浮点型，可以直接用于计算                                       |
| `string`   | 字符串，一般不用于计算，如果强制进行计算，会自动尝试转化为数值 |
| `datetime` | 日期时间                                                       |

下面为一个 DataFrame 示例：

```js
{
    columns: ['需求数', '功能点数', '人数', '开始时间', '结束时间', '天数'],
    dtypes:  ['int', 'float', 'int', 'datetime', 'datetime', 'int'],
    index:   ['第一期', '第二期', '第三期'],
    data: [
        [123, 520, 21, '21-01-03', '21-01-23', 5],
        [12, 20, 2, '21-02-03', '21-03-23', 10],
        [33, 50, 1, '21-03-03', '21-04-23', 15]
    ]
}
```

详细结构参考 pandas 和 danfojs：

- https://pandas.pydata.org/docs/reference/frame.html
- https://danfo.jsdata.org/getting-started#creating-a-dataframe-series

## 分析方法配置

ZenDAS 中所有可用的分析分析方法需要在 `lib/das/methods/` 中进行定义。

### 基本结构


每个分析方法配置包含内部名称、类型、参数设置和方法计算回调函数。使用一个对象和内部属性来进行定义，下面为一个示例：

```js
{
    /* 内部名称 */
    name: 'basicStatistic', // 需要在所有方法中具备唯一性

    /* 显示名称 */
    title: '基本量统计',      // 实际界面显示时，该名称可以在 lang 内进行覆盖

    /* 类型 */
    type: 'statistic',      // 可用类型包括：'statistic'（统计）、'graphic'（图表）、'analysis'（分析）

    /* 参数设置 */
    settings: [...],        // 定义使用此方法应该提供哪些设置参数，定义规则参加后续章节

    /* 计算回调函数 */
    func: function,         // 提供方法接受参数和数据并返回结果，定义规则参加后续章节

    /* 计算结果 */
    results: [...]
}
```

### 参数设置

方法的参数定义决定了方法最终的结果输出，根据参数的定义会在界面上显示合适的表单供用户设置和修改参数的值。方法的参数设置通过 `settings` 字段定义，使用一个数组来定义多个参数，每个参数使用一个对象来进行定义，该对象所有属性定义如下：

| 属性名         | 类型     | 可选性                         | 说明                                                         | 示例                                                         |
| -------------- | -------- | ------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
| `name`         | `string` | 必须                           | 参数内部名称。                                               | `'variables'`                                                |
| `type`         | `string` | 默认 `'string'`                | 参数类型。可用类型包括 `'bool'` `'string'` `'number'` `'enum'` `'column'` `'row'` `'cell'` `'range'` `'formula'` `'list'` | `'bool'`                                                     |
| `listType`     | `string` | 默认 `'string'`                | 列表类型。当 `type = 'list'` 时用于指定列表内元素值的类型，可用类型与 `type` 可用类型基本相同（不包括 `'list'`） | `'enum'`                                                     |
| `enumOptions`  | `array`  | 参数类型为枚举或枚举列表时必须 | 枚举选项列表。当参数类型为列表（`type = 'enum'`）或枚举列表（`type = 'list'` 且 `listType = 'enum'`）时用于指定枚举的选项列表；每个选项可用使用字符串或对象指定，当使用对象时可用分别指定选项的内部值（`value`）和显示名称（`label`）。 | `[{label: '苹果', value: 'apple'}, {label: '香蕉', value: 'banana'}]` |
| `stringMatch`  | `string` | 可选                           | 字符串匹配规则。当类型为字符串（`type = 'string'`）时可用使用此属性指定一个正则表达式约束用户填写的值必须匹配。 | `'ab+c'`                                                     |
| `stringLength`  | `number` `string` | 可选                           | 字符串最小长度，或者使用 `,` 分隔两个数值同时指定最小和最大长度 | `'10,100'`                                                     |
| `listLength`  | `number` `string` | 可选                           | 当类型为列表时（`type = 'list'`）时列表值最小数目，或者使用 `,` 分隔两个数值同时指定最小和最大数目 | `'10,100'`                                                     |
| `numberType`   | `string` | 可选                           | 数值类型。当类型为数值（`type = 'number'`）时，指定数值类型，包括：`'int'`（整数）、`'float'`（浮点数）| `'int'`                                                      |
| `numberRange`   | `string` | 可选                           | 数值范围，使用括号表示 | `'[0, 100)'` `'(0,)'`                                                      |
| `columnType`     | `string`   | 默认 `'any'`                   | 当类型为数值（`type = 'column'`）时，指定类数据类型，可以为 ` int`（整数）、`float`（浮点型）、`number`（整形和浮点型）、`string`（字符串）、`datetime`（日期时间）、`any`（任意类型），使用逗号分隔多个允许的类型   | `'number,datetime'`                                                      |
| `distinct`     | `string`   | 可选                   | 限定该参数的值必须与指定的参数值不一致，使用逗号分隔多个参数名。                                         | `'xaxis'`                                                      |
| `required`     | `bool`   | 默认 `false`                   | 参数是否必须提供值。                                         | `false`                                                      |
| `defaultValue` | `any`    | 可选                           | 参数默认值。                                                 | `''`                                                         |
| `label`        | `string` | 可选                           | 参数显示名称。                                               | `'统计量'`                                                   |
| `hint`         | `string` | 可选                           | 参数解释性或提示文本。                                       | `'指定需要从哪些维度进行统计'`                               |
| `ui` | `string` | 可选 | 指定表单 UI 控件类型，目前适合 `type = 'enum'` 或 `type = 'list'`，可以为如下值 `'picker'` （下拉选择）、`'radio'`（单选框）、`'checkbox'`（复选框） 、`'radio-list'`（单选框列表）、`'checkbox-list'`（复选框列表）| `'checkbox'` |
| `conditions` | `object` `object[]` | 可选 | 定义当前参数可用的条件，使用一个对象来定义，例如 `{var1: 'on', var2: 10}`，仅在参数 `var1` 值为 `'on'` 和 `var2` 参数值为 `10` 时可用，当需要定义多个组合条件满足任意条件可用使用数组来表示，例如 `[{var1: 'on', var2: 10}, {var2: 20}]` | `[{var1: 'on', var2: 10}, {var2: 20}]` |

其中各种 **参数类型** 定义如下：

| 参数类型  | 说明     | 参数表单控件                       | 示例数据                                   |
| --------- | -------- | ---------------------------------- | ------------------------------------------ |
| `bool`    | 布尔     | 复选框                             | `false`                                    |
| `string`  | 字符串   | 文本框                             | `'Hello'`                                  |
| `number`  | 数值     | 数值输入框                         | `123`                                      |
| `enum`    | 枚举     | 下拉选择框（单选）                 | `'apple'`                                  |
| `column`  | 数据列   | 列输入/选择框                      | `C1`（第1列）、 `功能点数`（通过列名引用） |
| `row`     | 数据行   | 行输入/选择框                      | `R1`（第1行）                              |
| `cell`    | 数据单元 | 单元格输入/选择框                  | `C1R1`（第1列第1行）                       |
| `range`   | 数据范围 | 范围输入/选择框                    | `C1R1:C3R3`（第1列第1行至第3列第3行）      |
| `formula` | 公式     | 公式输入框                         | `SUM(C1R1:C1R10)`                          |
| `list`    | 列表     | 根据列表元素类型不同显示不同的控件 | `['apple', 'banana']`                      |
| `color`   | 颜色     | 颜色值输入或选择控件               | `'red'`、`'#f1f1f1'`                       |

下面为一个参数定义示例：

```js
{
		/* 参数内部名称 */
    name: 'variables',

    /* 参数类型 */
    type: 'list', // 所有类型：'bool'、'string'、'number'、'list'、'enum'、'data_column'、'data_cell'、'data_range'

    /* 列表类型 */
    listType: 'column', // 仅当 type = 'list' 时可用，用于指定列表内部值类型

    /* 参数显示名称 */
    label: '统计变量',

    /* 参数解释性或提示文本 */
    hint: '指定需要进行统计的变量',

    /* 参数必填项 */
    required: true
}
```

### 计算回调函数

计算回调函数用于定义分析方法应该如何使用数据和参数来输出分析结果。该回调函数通常定义如下：

```php
function analysisFunc(dataframe, settings)
{
  	return analysisResult;
}
```

其中参数定义如下：

| 参数        | 类型     | 说明                        |
| ----------- | -------- | --------------------------- |
| `dataframe` | `object` | 参见 **DataFrame** 章节说明 |
| `settings`  | `object` | 参数 **参数设置** 章节说明  |

其中返回值为一个分析结果列表（`array`），详细定义参考 **分析报告** 章节说明。

### 分析方法结果

分析方法经过计算之后最终会返回分析方法报告，分析方法报告由一个或一个以上的分析方法结果组成。分析方法结果可以是表格，描述性文本或图表。分析方法结果定义由一个对象组成，通常包含如下属性：

| 属性名  | 类型     | 可选项 | 说明                                                         |
| ------- | -------- | ------ | ------------------------------------------------------------ |
| `title` | `string` | 可选   | 标题。例如 `'功能点数、需求数 散点图'`                       |
| `desc`  | `string` | 可选   | 描述性文本。                                                 |
| `type`  | `string` | 必须   | 结果类型。目前支持的类型包括：`'text'`（文本）、`'table'`（表格）、`'chart'`（图表）、`'image'`（图片）、`'error'`（发生了错误导致无法计算） |
| `data`  | `object` | 必须   | 结果数据。不同类型的结果，数据对象结构可能不一样。           |
| `css`  | `string` | 必须   | 注入到页面中的 CSS 样式代码           |
| `js`  | `string` | 必须   | 注入到页面中的 JavaScript 代码           |

其中 `data` 属性通常为一个对象，根据分析方法结果类型不同，`data` 对象拥有不同的结构。

**文本结果** 的 `data` 属性对象结构如下：

```js
{
    /* 文本内容 */
  	content: '这是文本性描述结果，可以包含换行',

    /* 文本类型 */
    type: 'html',  // 可以为 `text`（纯文本）、`html`（HTML 富文本）、`markdown`（Markdown 富文本）
}
```

**表格结果** 的 `data` 属性对象结构如下：

```js
{
    /* 表格外观主题 */
  	theme: 'simple', // 可以为 `simple`（简单，默认）、`bordered`（带完整边框）、`borderless`（无边框）


    /* 表格宽度 */
    width: 'auto',

    /* 表列头定义 */
    columns: [{label: '名称', width: 'auto', type: 'text'}, {label: '大小', width: '100px', align: 'right', type: 'number'}],

    /* 表数据定义 */
    data: [['正方形', 1000], ['三角形', 2000]]
}
```

**图表结果** 的 `data` 属性对象结构如下：

```js
{
    /* 图表类型 */
    type: 'scatter' // 可以为 `scatter`、`box`、`bar`、`line`、`radar`,

    /* 用于绘制图表的数据 */
    data: {...}     // 不同的图表类型，用于绘制的数据结构可能不同
}
```

**图片结果** 的 `data` 属性对象结构如下：

```js
{
    /* 图片地址 */
		src: 'http://example.com/image.png',

    /* 图片宽度（可选） */
    width: 1000,

    /* 图片高度（可选） */
    height: 500,
}
```

**错误结果** 的 `data` 属性对象结构如下：

```js
{
    /* 错误类型 */
		error: 'illegal',

    /* 错误消息 */
    message: '参数错误'
}
```

**CSS 和 JavaScript**

通过 `css` 和 `js` 可以为分析方法结果在页面呈现时向页面注入 CSS 和 JS 代码。在代码中可以通过如下特殊文本来引用当前分析方法和分析结果 ID：

* `{METHOD_ID}`：当前分析方法的 ID，例如 `202`；
* `{RESULT_ID}`：当前分析结果的 ID，例如 `4b3403665fea6`。
