// DISCLAIMER: The SCN, Content, and Services are being provided to You AS IS. // To the fullest extent allowable by law, SAP does not guarantee or warrant any // features or qualities of the SCN, Content, or Services or give any undertaking // with regard to any other quality. Statements and explanations to SCN, Content // or Services in promotional material or on SCN and in the documentation are // made for explanatory purposes only; they are not meant to constitute any // guarantee or warranty of certain features. No warranty or undertaking shall be // implied by a User from any published SAP description of or advertisement // except to the extent SAP has expressly confirmed such warranty or undertaking // in writing. Warranties are validly given only with the express written // confirmation of SAPs management. // For a description of the Google visualizations used in this application, // see https://developers.google.com/chart/interactive/docs/ // Initialization var express = require('express'); var bodyParser = require('body-parser') var path = require('path'); var phantomProxy = require('phantom-proxy'); var fs = require('fs'); var util = require('util'); var app = express(); app.use(bodyParser.json()); var urlencodedParser = bodyParser.urlencoded({ extended: true }); var CR = String.fromCharCode(13); // Set the port number app.listen(65535); app.get("/", function(req, res) { res.send("Server Up and Running !"); }); app.get("/api/about", function(req, res) { logInfo("About"); res.send("Google Visualizations"); }); app.get("/api/formats", function(req, res) { logInfo("Start Format"); var format = {"formats": ["text/html", "image/png"]}; res.setHeader('Content-Type', 'application/json'); res.send(JSON.stringify(format)); logInfo("Stop Format"); }); app.get("/api/visualizations", function(req, res) { logInfo("Start Visualizations"); res.setHeader('Content-Type', 'application/json'); res.send(JSON.stringify(factory)); logInfo("Stop Visualizations"); }); app.get("/api/visualizations/:vizid/feeds", function(req, res) { logInfo("Start feeds"); var viz = factory.getViz(req.params.vizid); logInfo(" Viz ID => " + viz.name); var feedArray = []; if (!(viz.categoryAxisMin == 0 && viz.categoryAxisMax == 0)) { feedArray.push( { "id": "category-axis", "name": viz.categoryAxisName, "description": viz.categoryAxisDesc, "axis": "0", "type": "dimension", "min": ""+viz.categoryAxisMin+"", "max": ""+viz.categoryAxisMax+"" } ); } if (!(viz.regionColorMin == 0 && viz.regionColorMax == 0)) { feedArray.push( { "id": "region-color", "name": viz.regionColorName, "description": viz.regionColorDesc, "axis": "1", "type": "dimension", "min": ""+viz.regionColorMin+"", "max": ""+viz.regionColorMax+"" } ); } if (!(viz.primaryValueMin == 0 && viz.primaryValueMax == 0)) { feedArray.push( { "id": "primary-values", "name": viz.primaryValueName, "description": viz.primaryValueDesc, "type": "measure", "min": ""+viz.primaryValueMin+"", "max": ""+viz.primaryValueMax+"" } ); } var feeds = { "feeds": feedArray }; res.setHeader('Content-Type', 'application/json'); res.send(JSON.stringify(feeds)); logInfo("Stop feeds"); }); app.post("/api/visualizations/:vizid/render", function(req, res) { logInfo("Start Render"); var viz = factory.getViz(req.params.vizid); var html = viz.generate(req); var height = req.body.height; var width = req.body.width; var format = req.headers.accept; logInfo(" Viz ID => "+viz); // Bitmap generation if(format == "image/png") { var self = this; var randomnumber=Math.floor(Math.random()*101) var path = 'html_page_'+randomnumber+'.html'; fs.writeFileSync(path, html); phantomProxy.create(function(proxy) { proxy.page.open(path, function (result) { proxy.page.set('viewportSize', { width: width, height: height }); proxy.page.set('clipRect', { top: 0, left: 0, width: width, height: height }); proxy.page.waitForSelector("#chart", function (result){ proxy.page.renderBase64('PNG', function(result){ var bitmap = new Buffer(result, 'base64'); res.writeHead(200, {'Content-Type': 'image/png' }); res.end(bitmap, 'binary'); phantomProxy.end(); fs.unlinkSync(path); // Delete temp file }); }); }); }); } // HTML generation else { res.writeHead(200, {'Content-Type': 'text/html' }); res.end(html); } logInfo("Stop Render"); }); var VizFactory = function() { this.visualizations = []; this.getViz = function(id) { for (var index = 0 ; index < this.visualizations.length ; index++) { if (this.visualizations[index].id === id) return this.visualizations[index]; } }; }; var Visualization = function(id, name, catMin, catMax, regMin, regMax, valMin, valMax, catName, catDesc, regName, regDesc, valName, valDesc) { this.id = id; this.name = name; this.categoryAxisMin = catMin; this.categoryAxisMax = catMax; this.categoryAxisName = catName; this.categoryAxisDesc = catDesc; this.regionColorMin = regMin; this.regionColorMax = regMax; this.regionColorName = regName; this.regionColorDesc = regDesc; this.primaryValueMin = valMin; this.primaryValueMax = valMax; this.primaryValueName = valName; this.primaryValueDesc = valDesc; }; /******************* * Google Pie Chart * * 1: ID * 2: Name * 3: Category feeds min = 1 * 4: Category feeds max = 1 * 5: Region feeds min = 0 (optional) * 6: Region feeds max = 1 * 7: Value feeds min = 1 * 8: Value feeds max = 1 * 9: Category feeds name * 10: Category feeds description * 11: Region feeds name * 12: Region feeds description * 13: Value feeds name * 14: Value feeds description */ var vizPie = new Visualization("googlepie", "Google Pie", 1, 1, 0, 1, 1, 1, "Sectors Dimension", "Dimension on which the pie will be splitted", "Treillis Dimension", "Dimension to repeat the pies", "Measure", "Measure values"); vizPie.generate = function(req) { var w = req.body.width?req.body.width:800; var h = req.body.height?req.body.height:800; var hCell = h; var dimData = getData(req, getFeedings(req, "category-axis")[0].dataId); var regFeed = getFeedings(req, "region-color"); var mesData = getData(req, getFeedings(req, "primary-values")[0].dataId); var count0 = 1; var count1 = 1; var values = []; var value = []; if (regFeed) { if (regFeed.length === 1) { var regData0 = getData(req, regFeed[0].dataId); count0 = regData0.values.rawvalues.length; for (var j = 0 ; j < count0 ; j++) { value = []; var reg = regData0.values.rawvalues[j]; for (var i = 0 ; i < dimData.values.rawvalues.length ; i++) { var dim = dimData.values.rawvalues[i]; var mes = mesData.values.rawvalues[j][i]; if (mes == 1.7e+308) mes = 0; // 1.7e+308 = WebI overflow value.push([dim.toString(), mes]); } values.push(value); } } else { var regData0 = getData(req, regFeed[0].dataId); var regData1 = getData(req, regFeed[1].dataId); var regValues0 = distinct(regData0.values.rawvalues); var regValues1 = distinct(regData1.values.rawvalues); count0 = regValues0.length; count1 = regValues1.length; hCell = Math.floor(h/count1); var allData = {}; for (var i = 0 ; i < mesData.values.rawvalues.length ; i++) { if (!allData[regData0.values.rawvalues[i]]) allData[regData0.values.rawvalues[i]] = {}; allData[regData0.values.rawvalues[i]][regData1.values.rawvalues[i]] = mesData.values.rawvalues[i]; } for (var j = 0 ; j < count1 ; j++) { for (var i = 0 ; i < count0 ; i++) { var k = i + count0*j; value = []; if (allData[regValues0[i]] && allData[regValues0[i]][regValues1[j]]) { var m = allData[regValues0[i]][regValues1[j]]; for (var l = 0 ; l < dimData.values.rawvalues.length ; l++) { var dim = dimData.values.rawvalues[l]; var mes = m[l]; if (mes == 1.7e+308) mes = 0; value.push([dim.toString(), mes]); } } values.push(value); } } } } else { for (var i = 0 ; i < dimData.values.rawvalues.length ; i++) { var dim = dimData.values.rawvalues[i]; var mes = mesData.values.rawvalues[i]; if (mes == 1.7e+308) mes = 0; value.push([dim.toString(), mes]); } values.push(value); } var html = '' + CR + '' + CR + '
' + CR + ' ' + CR + ' ' + CR + ' ' + CR + ' ' + CR + '