<commit_before>/// @author vtloc
/// @date 2014Jan09
/// @author GradualStudent
/// @date 2015jan06
/// This module's purpose is to transform 
/// 
var _ = require('lodash');
var xmlBuilder = require('xmlbuilder');
var fs = require('fs');
var _chartSpecs = require('./charts');


function OfficeChart(chartInfo) {

	if (chartInfo instanceof OfficeChart) {
		return chartInfo;
	}

	return {

		chartSpec: null, // Javascript object that represents the XML tree for the PowerPoint chart

		toXML: function () {
			return xmlBuilder.create(this.chartSpec, {
				version: '1.0',
				encoding: 'UTF-8',
				standalone: true
			}).end({
				pretty: true,
				indent: '  ',
				newline: '\n'
			});
		},

		toJSON: function () {
			return this.chartSpec;
		},

		getClass: function () {
			return "OfficeChart";
		},

		///
		/// @brief Create XML representation of chart object
		/// @param[chartInfo] object
		///  {
		///			title: 'eSurvey chart',
		///			data:  [ // array of series
		///				{
		///					name: 'Income',
		///					labels: ['2005', '2006', '2007', '2008', '2009'],
		///					values: [23.5, 26.2, 30.1, 29.5, 24.6],
		///         color: 'ff0000'
		///				}
		///			],
		///     overlap:  "0",
		///     gapWidth: "150"
		///
		/// 	}

		initialize: function (chartInfo) {

			if (chartInfo.getClass && chartInfo.getClass() == 'OfficeChart') {
				return chartInfo;
			}

			// overlap ["50"] is handled as an option within the chartbase
			// gapWidth ["150"] is handled as an option within the chartbase
			// valAxisCrossAtMaxCategory [true|false] is handled as an option within the chart base
			// catAxisReverseOrder [true|false] is handled as an option within the chart base

			this.chartSpec = OfficeChart.getChartBase(chartInfo); // get foundation XML for the chart type

			// Below are methods for handling options with more complex XML to mix in
			this.setData(chartInfo['data']);
			this.setTitle(chartInfo.title || chartInfo.name);
			this.setValAxisTitle(chartInfo.valAxisTitle);
			this.setCatAxisTitle(chartInfo.catAxisTitle);
			this.setValAxisNumFmt(chartInfo.valAxisNumFmt);
			this.setValAxisScale(chartInfo.valAxisMinValue, chartInfo.valAxisMaxValue);
			this.setTextSize(chartInfo.fontSize);
			this.mergeChartXml(chartInfo.xml);
			this.setValAxisMajorGridlines(chartInfo.valAxisMajorGridlines);
			this.setValAxisMinorGridlines(chartInfo.valAxisMinorGridlines);

			return this;
		},

		setTextSize: function (textSize) {
			if (textSize !== undefined) {
				var textRef = this._text(textSize);
				_.merge(this.chartSpec['c:chartSpace'], textRef);
			}
		},

		setTitle: function (title) {
			if (title !== undefined) {
				var titleRef = this._title(chartInfo.title || chartInfo.name);
				_.merge(this.chartSpec['c:chartSpace']['c:chart'], titleRef)
			}
		},

		setValAxisTitle: function (title) {
			if (title) {
				var titleRef = this._title(title);
				_.merge(this.chartSpec['c:chartSpace']['c:chart']['c:plotArea']['c:valAx'], titleRef);
			}
		},

		setCatAxisTitle: function (title) {
			if (title) {
				var titleRef = this._title(title);
				_.merge(this.chartSpec['c:chartSpace']['c:chart']['c:plotArea']['c:catAx'], titleRef);
			}
		},

		setValAxisNumFmt: function (format) {
			if (format !== undefined) {
				var numFmtRef = this._numFmt(format);
				_.merge(this.chartSpec['c:chartSpace']['c:chart']['c:plotArea']['c:valAx'], numFmtRef)
			}
		},

		setValAxisScale: function (min, max) {
			if (min !== undefined || max !== undefined) {
				var scalingRef = this._scaling(min, max);
				_.merge(this.chartSpec['c:chartSpace']['c:chart']['c:plotArea']['c:valAx'], scalingRef);
			}
		},

		mergeChartXml: function (xml) {
			if (xml !== undefined) {
				_.merge(this.chartSpec['c:chartSpace'], xml);
			}
		},

		setValAxisMajorGridlines: function (boolean) {
			if (boolean) {
				this.chartSpec['c:chartSpace']['c:chart']['c:plotArea']['c:valAx']['c:majorGridlines'] = {};
			}
		},
		setValAxisMinorGridlines: function (boolean) {
			if (boolean) {
				this.chartSpec['c:chartSpace']['c:chart']['c:plotArea']['c:valAx']['c:minorGridlines'] = {};
			}
		},


		setData: function (data) {

			if (data) {
				this.data = data;

				// Mix in data series
				var seriesDataRef;
				if (this.chartSpec['c:chartSpace']['c:chart']['c:plotArea']['c:barChart']) {
					seriesDataRef = this.chartSpec['c:chartSpace']['c:chart']['c:plotArea']['c:barChart']['#list'];
				} else if (this.chartSpec['c:chartSpace']['c:chart']['c:plotArea']['c:pieChart']) {
					seriesDataRef = this.chartSpec['c:chartSpace']['c:chart']['c:plotArea']['c:pieChart']['#list'];
				} else throw new Error("Can't add data to chart that is not initialized or not a recognized type")

				// the barChart/pieChart objects has other attributes too, so we push the series data on, not replace it
				if (chartInfo['data']) {
					var seriesData = this.getSeriesRef(chartInfo['data']);
					for (var i = 0; i < seriesData.length; i++) {
						seriesDataRef.push(seriesData[i])
					}
				}
			}
			return this;
		},


		///
		/// @brief Transform an array of string into an office's compliance structure
		///
		/// @param[in] region String
		///		The reference cell of the string, for example: $A$1
		/// @param[in] stringArr
		///		An array of string, for example: ['foo', 'bar']
		///
		_strRef: function (region, stringArr) {
			var obj = {
				'c:strRef': {
					'c:f': region,
					'c:strCache': function () {
						var result = {};<commit_msg>Added missing support for line chart<commit_after>/// @author vtloc
/// @date 2014Jan09
/// @author GradualStudent
/// @date 2015jan06
/// This module's purpose is to transform
///
var _ = require('lodash');
var xmlBuilder = require('xmlbuilder');
var fs = require('fs');
var _chartSpecs = require('./charts');


function OfficeChart(chartInfo) {

	if (chartInfo instanceof OfficeChart) {
		return chartInfo;
	}

	return {

		chartSpec: null, // Javascript object that represents the XML tree for the PowerPoint chart

		toXML: function () {
			return xmlBuilder.create(this.chartSpec, {
				version: '1.0',
				encoding: 'UTF-8',
				standalone: true
			}).end({
				pretty: true,
				indent: '  ',
				newline: '\n'
			});
		},

		toJSON: function () {
			return this.chartSpec;
		},

		getClass: function () {
			return "OfficeChart";
		},

		///
		/// @brief Create XML representation of chart object
		/// @param[chartInfo] object
		///  {
		///			title: 'eSurvey chart',
		///			data:  [ // array of series
		///				{
		///					name: 'Income',
		///					labels: ['2005', '2006', '2007', '2008', '2009'],
		///					values: [23.5, 26.2, 30.1, 29.5, 24.6],
		///         color: 'ff0000'
		///				}
		///			],
		///     overlap:  "0",
		///     gapWidth: "150"
		///
		/// 	}

		initialize: function (chartInfo) {

			if (chartInfo.getClass && chartInfo.getClass() == 'OfficeChart') {
				return chartInfo;
			}

			// overlap ["50"] is handled as an option within the chartbase
			// gapWidth ["150"] is handled as an option within the chartbase
			// valAxisCrossAtMaxCategory [true|false] is handled as an option within the chart base
			// catAxisReverseOrder [true|false] is handled as an option within the chart base

			this.chartSpec = OfficeChart.getChartBase(chartInfo); // get foundation XML for the chart type

			// Below are methods for handling options with more complex XML to mix in
			this.setData(chartInfo['data']);
			this.setTitle(chartInfo.title || chartInfo.name);
			this.setValAxisTitle(chartInfo.valAxisTitle);
			this.setCatAxisTitle(chartInfo.catAxisTitle);
			this.setValAxisNumFmt(chartInfo.valAxisNumFmt);
			this.setValAxisScale(chartInfo.valAxisMinValue, chartInfo.valAxisMaxValue);
			this.setTextSize(chartInfo.fontSize);
			this.mergeChartXml(chartInfo.xml);
			this.setValAxisMajorGridlines(chartInfo.valAxisMajorGridlines);
			this.setValAxisMinorGridlines(chartInfo.valAxisMinorGridlines);

			return this;
		},

		setTextSize: function (textSize) {
			if (textSize !== undefined) {
				var textRef = this._text(textSize);
				_.merge(this.chartSpec['c:chartSpace'], textRef);
			}
		},

		setTitle: function (title) {
			if (title !== undefined) {
				var titleRef = this._title(chartInfo.title || chartInfo.name);
				_.merge(this.chartSpec['c:chartSpace']['c:chart'], titleRef)
			}
		},

		setValAxisTitle: function (title) {
			if (title) {
				var titleRef = this._title(title);
				_.merge(this.chartSpec['c:chartSpace']['c:chart']['c:plotArea']['c:valAx'], titleRef);
			}
		},

		setCatAxisTitle: function (title) {
			if (title) {
				var titleRef = this._title(title);
				_.merge(this.chartSpec['c:chartSpace']['c:chart']['c:plotArea']['c:catAx'], titleRef);
			}
		},

		setValAxisNumFmt: function (format) {
			if (format !== undefined) {
				var numFmtRef = this._numFmt(format);
				_.merge(this.chartSpec['c:chartSpace']['c:chart']['c:plotArea']['c:valAx'], numFmtRef)
			}
		},

		setValAxisScale: function (min, max) {
			if (min !== undefined || max !== undefined) {
				var scalingRef = this._scaling(min, max);
				_.merge(this.chartSpec['c:chartSpace']['c:chart']['c:plotArea']['c:valAx'], scalingRef);
			}
		},

		mergeChartXml: function (xml) {
			if (xml !== undefined) {
				_.merge(this.chartSpec['c:chartSpace'], xml);
			}
		},

		setValAxisMajorGridlines: function (boolean) {
			if (boolean) {
				this.chartSpec['c:chartSpace']['c:chart']['c:plotArea']['c:valAx']['c:majorGridlines'] = {};
			}
		},
		setValAxisMinorGridlines: function (boolean) {
			if (boolean) {
				this.chartSpec['c:chartSpace']['c:chart']['c:plotArea']['c:valAx']['c:minorGridlines'] = {};
			}
		},


		setData: function (data) {

			if (data) {
				this.data = data;

				// Mix in data series
				var seriesDataRef;
				
				if (this.chartSpec['c:chartSpace']['c:chart']['c:plotArea']['c:barChart']) {
					seriesDataRef = this.chartSpec['c:chartSpace']['c:chart']['c:plotArea']['c:barChart']['#list'];
				} else if (this.chartSpec['c:chartSpace']['c:chart']['c:plotArea']['c:pieChart']) {
					seriesDataRef = this.chartSpec['c:chartSpace']['c:chart']['c:plotArea']['c:pieChart']['#list'];
				} else if (this.chartSpec['c:chartSpace']['c:chart']['c:plotArea']['c:doughnutChart']) {
          seriesDataRef = this.chartSpec['c:chartSpace']['c:chart']['c:plotArea']['c:doughnutChart']['#list'];
      	} else if (this.chartSpec['c:chartSpace']['c:chart']['c:plotArea']['c:lineChart']) {
          seriesDataRef = this.chartSpec['c:chartSpace']['c:chart']['c:plotArea']['c:lineChart']['#list'];
        } else {
					throw new Error("Can't add data to chart that is not initialized or not a recognized type");
				}

				// the barChart/pieChart objects has other attributes too, so we push the series data on, not replace it
				if (chartInfo['data']) {
					var seriesData = this.getSeriesRef(chartInfo['data']);
					for (var i = 0; i < seriesData.length; i++) {
						seriesDataRef.push(seriesData[i])
					}
				}
			}
			return this;
		},


		///
		/// @brief Transform an array of string into an office's compliance structure
		///
		/// @param[in] region String
		///		The reference cell of the string, for example: $A$1
		/// @param[in] stringArr
		///		An array of string, for example: ['foo', 'bar']
		///
		_strRef: function (region, stringArr) {
			var obj = {
				'c:strRef': {
					'c:f': region,
					'c:strCache': function () {
						var result = {};
{'fraction_non_alphanumeric': 0.17335205828140085, 'fraction_numerical': 0.01141051522864917, 'mean_word_length': 3.4317386231038505, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 14}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5351455', 'n_tokens_mistral': 4507, 'n_tokens_neox': 3721, 'n_words': 817}