feat:データ集計処理実装完了

This commit is contained in:
xiaozhe.ma
2024-07-10 17:21:07 +09:00
parent c1d33e3ff0
commit bac7020c15
6 changed files with 509 additions and 337 deletions

View File

@@ -0,0 +1,121 @@
import { FieldForm,CalcFieldForm,FieldType, CalcFormat} from "../types/FieldLayout";
/**
* 集計操作子
*/
export enum Operator {
SUM = "SUM",
AVG = "AVG",
MAX = "MAX",
MIN = "MIN",
COUNT = "COUNT",
FIRST = "FIRST",
LAST = "LAST"
}
/**
* 集計関数
*/
export class Aggregator {
private data: string[];
private field: FieldForm;
constructor(data: string[], field: FieldForm) {
this.data = data;
this.field = field;
}
private toNumberArray(): number[] {
const numberArray = this.data.map(item => {
const num = Number(item);
if (isNaN(num)) {
throw new Error(`フィールド「${this.field.code} 」は数値に変換できないため、計算を実行できません。`);
}
return num;
});
return numberArray;
}
private sum(): number | null {
if (this.data.length === 0) return null;
const numberArray = this.toNumberArray();
return numberArray.reduce((acc, val) => acc + val, 0);
}
private avg(): number | null {
if (this.data.length === 0) return null;
const numberArray = this.toNumberArray();
const total = numberArray.reduce((acc, val) => acc + val, 0);
return total / numberArray.length;
}
private max(): number | string | null {
if (this.data.length === 0) return null;
if (this.field.type === FieldType.NUMBER ) {
const numberArray = this.toNumberArray();
return Math.max(...numberArray);
}
if(this.field.type===FieldType.CALC){
const calcField = this.field as CalcFieldForm;
if(calcField.format===CalcFormat.NUMBER || calcField.format===CalcFormat.NUMBER_DIGIT){
const numberArray = this.toNumberArray();
return Math.max(...numberArray);
}
}
return this.data.reduce((max, item) => (item > max ? item : max), this.data[0]);
}
private min(): number | string | null {
if (this.data.length === 0) return null;
if (this.field.type === FieldType.NUMBER ) {
const numberArray = this.toNumberArray();
return Math.min(...numberArray);
}
if(this.field.type===FieldType.CALC){
const calcField = this.field as CalcFieldForm;
if(calcField.format===CalcFormat.NUMBER || calcField.format===CalcFormat.NUMBER_DIGIT){
const numberArray = this.toNumberArray();
return Math.min(...numberArray);
}
}
if(this.data===null || this.data.length===0){
return null;
}
return this.data.reduce((min, item) => (item < min ? item : min), this.data[0]);
}
private count(): number {
return this.data.length;
}
private first(): string | null {
return this.data.length ? this.data[0] : null;
}
private last(): string | null {
return this.data.length ? this.data[this.data.length - 1] : null;
}
public calculate(operator: Operator): number | string | null {
switch (operator) {
case Operator.SUM:
return this.sum();
case Operator.AVG:
return this.avg();
case Operator.MAX:
return this.max();
case Operator.MIN:
return this.min();
case Operator.COUNT:
return this.count();
case Operator.FIRST:
return this.first();
case Operator.LAST:
return this.last();
default:
return null;
}
}
}