Skip to content

Instantly share code, notes, and snippets.

@edmondop
Created April 26, 2018 16:40
Show Gist options
  • Save edmondop/91e96cdfd18aabe12b20e96e19917138 to your computer and use it in GitHub Desktop.
Save edmondop/91e96cdfd18aabe12b20e96e19917138 to your computer and use it in GitHub Desktop.
chart-data-parser
import {ChartData} from "chart.js";
import {getDateOfISOWeek, getDateStringOfISOWeek, getWeekNumber} from "../../../commons/src";
import {addMonths, addWeeks, differenceInCalendarMonths, differenceInCalendarWeeks, isPast, isFuture, addDays} from 'date-fns';
import {range} from 'lodash';
export interface IAdvanceSummaryData{
Invoicer__c?: string;
paidBackOnTime: number;
paidBackLate: number;
notPaidBack: number;
toBePaidBackNotPostponed: number;
toBePaidBackPostponed: number;
}
interface IMonthlyDataIndex{
year: number;
month: number;
}
interface IWeeklyDataIndex{
year: number;
week: number;
}
export interface IMonthlyChartData extends IAdvanceSummaryData,IMonthlyDataIndex{
}
export interface IWeeklyChartData extends IAdvanceSummaryData,IWeeklyDataIndex{
}
export interface IChartDataResponse {
frequency: "MONTHLY" | "WEEKLY",
period: string,
data: IMonthlyChartData[] | IWeeklyChartData[]
}
interface IParsedData {
labels: string[];
paidBackOnTime: number[];
paidBackLate: number[];
notPaidBack: number[];
toBePaidBackNotPostponed: number[];
toBePaidBackPostponed: number[];
}
const monthsLabels = ["Gen", "Feb", "Mar", "Apr", "Mag", "Giu", "Lug", "Ago", "Set", "Ott", "Nov", "Dic"];
function addData(res:IParsedData, curr:IAdvanceSummaryData){
res.notPaidBack.push(curr.notPaidBack);
res.paidBackLate.push(curr.paidBackLate);
res.paidBackOnTime.push(curr.paidBackOnTime);
res.toBePaidBackPostponed.push(curr.toBePaidBackPostponed);
res.toBePaidBackNotPostponed.push(curr.toBePaidBackNotPostponed);
}
function buildDataSet(parsedData:IParsedData){
return {
labels: parsedData.labels,
datasets: [
{
label: 'Paid back on time',
backgroundColor: '#006600',
data: parsedData.paidBackOnTime
},
{
label: 'Paid back late',
backgroundColor: '#ff6e00',
data: parsedData.paidBackLate
},
{
label: 'Not paid back',
backgroundColor: '#660000',
data: parsedData.notPaidBack
},
{
label: 'To be paid back - non renegotiated',
backgroundColor: '#006600',
data: parsedData.toBePaidBackNotPostponed
},
{
label: 'To be paid back - renegotiated',
backgroundColor: '#ff6e00',
data: parsedData.toBePaidBackPostponed
}
]
};
}
function initialParsedData(){
return {
labels: [],
paidBackOnTime: [],
paidBackLate: [],
notPaidBack: [],
toBePaidBackNotPostponed: [],
toBePaidBackPostponed: []
};
}
function defaultEmptyDataSet(){
return {
labels: [],
datasets: [
{
label: 'Amount',
backgroundColor: '#006600',
data: []
}
]
}
}
function buildSlidingMonthlyWindow(period:string,data: IMonthlyChartData[]) {
let firstDate;
let lastDate;
if (period === 'ALL') {
firstDate = new Date(data[0].year!, data[0].month!);
lastDate = new Date(data[data.length - 1].year!, data[data.length - 1].month!);
} else {
firstDate = addMonths(new Date(), -period / 2);
lastDate = addMonths(new Date(), (+period / 2) + 1);
}
let firstMonth = firstDate.getMonth();
let firstYear = firstDate.getFullYear();
let difference = differenceInCalendarMonths(lastDate, firstDate);
let slidingWindow:Array<IMonthlyDataIndex> = range(0,difference).map( (item:number,index:number) =>
{
const yearIndex = Math.floor((firstMonth + index)/12);
return {
month : ((firstMonth + index) % 12) +1 ,
year : firstYear + yearIndex
}
});
console.log('Using monthly sliding window ' , slidingWindow);
return data.filter(d => slidingWindow.some(x => x.month === d.month && x.year === d.year))
}
function buildWeeklySlidingWindow(period: string,data: IWeeklyChartData[]){
let firstDate: Date;
let lastDate;
let firstWeek : number;
if (period === 'ALL') {
firstDate = getDateOfISOWeek(data[0].week!, data[0].year!);
lastDate = getDateOfISOWeek(data[data.length - 1].week!, data[data.length - 1].year!);
} else {
firstDate = addWeeks(new Date(), -period / 2);
lastDate = addWeeks(new Date(), (+period / 2) + 1);
}
firstWeek = getWeekNumber(firstDate);
let difference = differenceInCalendarWeeks(lastDate, firstDate);
let slidingWindow: Array<IWeeklyDataIndex> = range(0,difference).map( (item:number,index:number) =>
{
// TODO: 53
const yearIndex = Math.floor((firstWeek+ index)/52);
return {
week : (firstWeek + index) % 53 === 0 ? 53 : (firstWeek + index) % 53 ,
year : firstDate.getFullYear() + yearIndex
}
});
console.log('Using weekly sliding window' , slidingWindow , 'for data ' , data);
return data.filter(d => slidingWindow.some(x => x.week === d.week && x.year === d.year));
}
export function parseMonthlyChartData(data: IMonthlyChartData[], period: string): ChartData {
console.log('Parsing monthly data ' , data , ' for period ' , period);
if (data.length === 0) {
return defaultEmptyDataSet();
}
const initialData: IParsedData = initialParsedData();
const filteredData = buildSlidingMonthlyWindow(period,data);
const parsedData = filteredData.reduce((res: IParsedData, curr: IMonthlyChartData) => {
res.labels.push(`${monthsLabels[curr.month! - 1]} ${curr.year}`);
addData(res,curr);
return res;
}, initialData);
return buildDataSet(parsedData);
}
export function parseWeeklyChartData(data: IWeeklyChartData[], period: string): ChartData {
console.log('Parsing weekly data ' , data , ' for period ' , period);
if (data.length === 0) {
return defaultEmptyDataSet();
}
const initialData: IParsedData = initialParsedData();
const filteredData = buildWeeklySlidingWindow(period,data);
const parsedData = filteredData.reduce( (res: IParsedData, curr: IWeeklyChartData) => {
res.labels.push(`${getDateStringOfISOWeek(curr.week!, curr.year!)}`);
addData(res,curr);
return res;
}, initialData);
return buildDataSet(parsedData);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment