new(basic.gblib): New CHART keyword..

This commit is contained in:
Rodrigo Rodriguez 2022-06-03 15:09:24 -03:00
parent b500a366b0
commit 3c65ae23e2
5 changed files with 338 additions and 1619 deletions

1792
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -69,6 +69,7 @@
"azure-arm-sql": "5.7.0",
"azure-arm-website": "5.7.0",
"azure-search-client": "3.1.5",
"billboard.js": "^3.4.1",
"bluebird": "3.7.2",
"body-parser": "1.19.0",
"botbuilder": "4.11.0",

View file

@ -0,0 +1,68 @@
/*****************************************************************************\
| ( )_ _ |
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' v `\ /'_`\ |
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__, \| (˅) |( (_) ) |
| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' |
| | | ( )_) | |
| (_) \___/' |
| |
| General Bots Copyright (c) Pragmatismo.io. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| According to our dual licensing model, this program can be used either |
| under the terms of the GNU Affero General Public License, version 3, |
| or under a proprietary license. |
| |
| The texts of the GNU Affero General Public License with an additional |
| permission and of our proprietary license can be found at and |
| in the LICENSE file you have received along with this program. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. |
| |
| "General Bots" is a registered trademark of Pragmatismo.io. |
| The licensing of the program under the AGPLv3 does not imply a |
| trademark license. Therefore any rights, title and interest in |
| our trademarks remain entirely with us. |
| |
\*****************************************************************************/
'use strict';
const urlJoin = require('url-join');
const DateDiff = require('date-diff');
const puppeteer = require('puppeteer');
const Path = require('path');
import bb from "billboard.js";
export class ChartServices {
/**
* Generate chart image screenshot
* @param {object} options billboard.js generation option object
* @param {string} path screenshot image full path with file name
*/
public static async screenshot(args, path) {
const browser = await puppeteer.launch({ headless: false });
const page = await browser.newPage();
// load billboard.js assets from CDN.
await page.addStyleTag({ url: "https://cdn.jsdelivr.net/npm/billboard.js/dist/theme/datalab.min.css" });
await page.addScriptTag({ url: "https://cdn.jsdelivr.net/npm/billboard.js/dist/billboard.pkgd.min.js" });
await page.evaluate(`bb.generate(${JSON.stringify(args)});`);
const content = await page.$(".bb");
await content.screenshot({
path,
omitBackground: true
});
await page.close();
await browser.close();
}
}

View file

@ -34,6 +34,7 @@
import { GBDialogStep, GBLog, GBMinInstance } from 'botlib';
import { GBConfigService } from '../../core.gbapp/services/GBConfigService';
import { ChartServices } from './ChartServices';
const urlJoin = require('url-join');
import { GBServer } from '../../../src/app';
import { GBDeployer } from '../../core.gbapp/services/GBDeployer';
@ -47,7 +48,7 @@ import * as fs from 'fs';
const DateDiff = require('date-diff');
const puppeteer = require('puppeteer');
const Path = require('path');
const c3ChartMaker = require('c3-chart-maker');
import bb, {area, bar, zoom} from "billboard.js";
/**
* Base services of conversation to be called by BASIC which
@ -125,6 +126,11 @@ export class DialogKeywords {
/**
*
*
* Data = [10, 20, 30]
* Legends = "Steve;Yui;Carlos"
* img = CHART "pie", data, legends
*
* https://c3js.org/examples.html
*
@ -132,56 +138,45 @@ export class DialogKeywords {
* @param legends
* @see https://www.npmjs.com/package/plot
*/
public async getChart(data, legends)
{
const chartDefinition = {
"size": {
public async chart(step, type, data, legends) {
const columns = [[]];
const legends_ = legends.split(';');
for (let i = 0; i < legends_.length; i++) {
columns[i] = [legends_[i]];
columns[i] = columns[i].concat(data);
}
const definition = {
size: {
"height": 600,
"width": 1200
},
"series": {
"x": "Date",
"Close": "Close",
"Volume": "Volume"
data: {
columns: columns,
type: type
},
"data": {
"x": "x",
"type": "line",
"axes": {
"Volume": "y2"
},
"types": {
"Volume": "bar"
}
},
"axis": {
"x": {
"type": "timeseries",
"tick": {
"format": "%Y-%m-%d"
}
},
"y": {
"label": {
"text": "Close",
"position": "outer-middle"
}
},
"y2": {
"show": true,
"label": {
"text": "Signal",
"position": "outer-middle"
}
}
},
"transition": {
"duration": 0
bar: {
width: 200
}
};
const outputFilePath = "output.png";
await c3ChartMaker(data, chartDefinition, outputFilePath);
const gbaiName = `${this.min.botId}.gbai`;
const localName = Path.join('work', gbaiName, 'cache', `img${GBAdminService.getRndReadableIdentifier()}.jpg`);
await ChartServices.screenshot(definition, localName);
const url = urlJoin(
GBServer.globals.publicAddress,
this.min.botId,
'cache',
Path.basename(localName)
);
GBLog.info(`BASIC: Visualization: Chart generated at ${url}.`);
return url;
}
/**

View file

@ -389,6 +389,10 @@ export class GBVMService extends GBService {
return `sys().createABotFarmUsing (${$3})`;
});
code = code.replace(/(chart)(\s)(.*)/gi, ($0, $1, $2, $3) => {
return `chart (step, ${$3})\n`;
});
code = code.replace(/(transfer to)(\s)(.*)/gi, ($0, $1, $2, $3) => {
return `transferTo (step, ${$3})\n`;
});
@ -646,6 +650,9 @@ export class GBVMService extends GBService {
code = code.replace(/("[^"]*"|'[^']*')|\btransferTo\b/gi, ($0, $1) => {
return $1 === undefined ? 'this.transferTo' : $1;
});
code = code.replace(/("[^"]*"|'[^']*')|\bchart\b/gi, ($0, $1) => {
return $1 === undefined ? 'this.chart' : $1;
});
code = code.replace(/("[^"]*"|'[^']*')|\bcreateDeal\b/gi, ($0, $1) => {
return $1 === undefined ? 'this.createDeal' : $1;
});