Files
qctool/modules/tools.js
hbk01 ff726aeec8 + L014-1 相关物质取消测试状态
+ L014-1 相关物质使用表格展示结果
+ 干燥失重将读写存储的操作解耦合
+ 干燥失重将保存功能使用方法删除
2023-01-07 00:28:14 +08:00

226 lines
6.4 KiB
JavaScript

import Decimal from './decimal.mjs'
class IO {
/**
* 传入一个组名,返回一个 IO 对象,后续仅对该组内的数据进行读写
* @param {string} scope 组名
*/
constructor(scope) {
this.scope = scope
}
/**
* 读取一条数据
* @param {string} id 数据的唯一标识符
* @returns 该标识符所代表的数据
*/
read(id) {
let key = `${this.scope}/${id}`
return localStorage.getItem(key)
}
/**
* 写入一条数据
* @param {string} id 数据的唯一标识符
* @param {*} data 该标识符所代表的数据
*/
write(id, data) {
let key = `${this.scope}/${id}`
localStorage.setItem(key, data)
}
/**
* 删除一条数据
* @param {string} id 数据的唯一标识符
*/
remove(id) {
let key = `${this.scope}/${id}`
localStorage.removeItem(key)
}
/**
* 列出已存储的所有数据的唯一标识符
* @returns 当前组内所存储的所有数据的唯一标识符
*/
listKeys() {
let keys = []
for (const key in localStorage) {
if (Object.hasOwnProperty.call(localStorage, key) &&
key.startsWith(this.scope)) {
let i = key.indexOf('/') + 1
keys.push(key.slice(i))
}
}
return keys
}
/**
* 确定是否需要收集 value
* @param {*} value 当前值
* @param {boolean} collectEmptyValue 是否收集空值
* @returns
*/
#checkValue = (value, collectEmptyValue) => {
return collectEmptyValue || !(value === null || value === undefined || value == '')
}
/**
* 检查 input 类型,若不是用户输入的内容(如 button 等),则不收集该 input 的数据
* @param {*} type input 类型
* @returns 是否需要收集该 input 的数据
*/
#checkType = (type) => {
let allows = [
// 已列出所有的 input 类型,将不收集数据的类型注释掉即可
// 'button',
'checkbox',
'color',
'date',
'datetime-local',
'email',
// 'file',
// 'hidden',
// 'image',
'month',
'number',
// 'password',
'radio',
'range',
// 'reset',
'search',
// 'submit',
'tel',
'text',
'time',
'url',
'week'
]
return allows.indexOf(type) != -1
}
/**
* 从 input 控件收集用户填入的数据
* @param {HTMLCollection | HTMLInputElement} inputs 需要收集数据的 input 标签
* @param {boolean} collectEmptyValue 是否需要收集空值
* @returns 收集的数据
*/
collectData(inputs, collectEmptyValue = true) {
if (inputs.length == 0) return
let result = {
timestamp: Date.now()
}
let safeKey = (key) => {
return key.replaceAll('-', '_')
}
for (let input of inputs) {
if (this.#checkType(input.type)) {
// 需要分类型进行收集数据
switch (input.type) {
case 'checkbox':
result[safeKey(input.name)] = input.checked
break
case 'radio':
if (input.checked) {
result[safeKey(input.name)] = input.value
}
break
default:
if (this.#checkValue(input.value, collectEmptyValue)) {
result[safeKey(input.name)] = input.value
}
break
}
}
}
return result
}
/**
* 将 data 中的值自动填入到对应的 input 中
* @param {Object} data 需要填入的数据
* @param {HTMLCollection | HTMLInputElement} inputs 需要填入数据到哪些 input
*/
exportData(data, inputs) {
let reSafeKey = (key) => {
return key.replaceAll('-', '_')
}
for (let item in data) {
for (let input of inputs) {
if (reSafeKey(input.name) == item) {
switch (input.type) {
case 'checkbox':
input.checked = data[item]
break
case 'radio':
if (input.value == data[item]) input.checked = true
break
default:
input.value = data[item]
break
}
}
}
}
}
}
class Formula {
static AVERAGE(...array) {
let sum = new Decimal(0)
array.forEach((item) => sum = sum.plus(item))
return sum.dividedBy(array.length)
}
// 计算相对标准偏差
// Markdown 公式:$RSD = \frac{SD}{\overline{x}}*100\%$
// @see Formula.STDEV()
static RSD(...array) {
let stdev = this.STDEV(...array)
let average = () => {
let sum = new Decimal(0)
array.forEach(value => sum = sum.plus(new Decimal(value)))
return sum.dividedBy(array.length)
}
let rsd = stdev.dividedBy(average()).times(100)
return rsd.toPrecision(5)
}
// 计算标准偏差
// Markdown 公式:$SD = \sqrt{\frac{\sum_{i=1}^{n}(x_i - \overline{x})^2}{n-1}}$
static STDEV(...array) {
// 计算所有数值的和
let sum = new Decimal(0)
array.forEach(value => sum = sum.plus(new Decimal(value)))
// 计算所有数值的平均值
let average = sum.dividedBy(array.length)
// 计算 ((每个数值减去平均值)的二次方)的和,即公式中分子的结果
let sumEach = new Decimal(0)
array.forEach(value => {
let v = new Decimal(value)
let temp = v.minus(average).toPower(2)
sumEach = sumEach.plus(temp)
})
// 以上结果除以 n-1 并开根号即得
let x = sumEach.dividedBy(array.length - 1).squareRoot()
return x
}
}
class Deviation {
static AbsoluteDeviation(num, nums) {
// TODO: implement this method
}
}
export { IO, Formula, Deviation }