<commit_before>/*
 * Copyright (c) 2015 IBM Corporation and others.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * You may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.brunel.build.d3.diagrams;

import org.brunel.action.Param;
import org.brunel.build.d3.D3Interaction;
import org.brunel.build.d3.D3LabelBuilder;
import org.brunel.build.d3.element.D3ElementBuilder;
import org.brunel.build.d3.element.ElementDetails;
import org.brunel.build.info.ElementStructure;
import org.brunel.build.util.ScriptWriter;
import org.brunel.data.Data;
import org.brunel.data.Dataset;
import org.brunel.model.VisSingle;
import org.brunel.model.VisTypes;
import org.brunel.model.VisTypes.Diagram;
import org.brunel.model.VisTypes.Element;

import java.util.ArrayList;
import java.util.List;

public abstract class D3Diagram {
	public static D3Diagram make(ElementStructure structure, D3Interaction interaction, ScriptWriter out) {
		VisSingle vis = structure.vis;
		Dataset data = structure.data;
		if (vis.tDiagram == null) return null;
		if (vis.tDiagram == Diagram.bubble) return new Bubble(structure, data, interaction, out);
		if (vis.tDiagram == Diagram.chord) return new Chord(structure, data, interaction, out);
		if (vis.tDiagram == Diagram.cloud) return new Cloud(structure, data, interaction, out);
		if (vis.tDiagram == Diagram.tree) return new Tree(structure, data, interaction, out);
		if (vis.tDiagram == Diagram.parallel) return new ParallelCoordinates(structure, data, interaction, out);
		if (vis.tDiagram == Diagram.gridded) return new Grid(structure, data, interaction, out);
		if (vis.tDiagram == Diagram.table) return new Table(structure, data, interaction, out);
		if (vis.tDiagram == Diagram.treemap) return new Treemap(structure, data, interaction, out);
		if (vis.tDiagram == Diagram.network)
			return new Network(structure, data, interaction, out);
		if (vis.tDiagram == Diagram.map) {
			if (vis.tDiagramParameters.length == 1 && vis.tDiagramParameters[0].asString().equals("labels"))
				return new GeoMapLabels(structure, data, interaction, out);
			else
				return new GeoMap(structure, data, structure.geo, interaction, out);
		}
		throw new IllegalStateException("Unknown diagram: " + vis.tDiagram);
	}

	final ScriptWriter out;
	final Param size;
	final Element element;
	final VisSingle vis;
	final D3LabelBuilder labelBuilder;
	final D3Interaction interaction;
	final String[] position;
	final ElementStructure structure;
	private boolean isHierarchy;

	D3Diagram(ElementStructure structure, Dataset data, D3Interaction interaction, ScriptWriter out) {
		this.structure = structure;
		this.vis = structure.vis;
		this.out = out;
		this.size = vis.fSize.isEmpty() ? null : vis.fSize.get(0);
		this.position = vis.positionFields();
		this.element = vis.tElement;
		this.interaction = interaction;
		this.labelBuilder = new D3LabelBuilder(vis, out, data);

	}

	public String getRowKeyFunction() {
		return vis.tDiagram.isHierarchical ? "nodeKey" : "function(d) { return d.key }";
	}

	public String getStyleClasses() {
		// Define the classes for this group; note that we flag hierarchies specially also
		String classes = "diagram " + vis.tDiagram.name();
		return "'" + (isHierarchy ? classes + " hierarchy" : classes) + "'";
	}

	public boolean needsDiagramExtras() {
		// By default, no extras needed
		return false;
	}

	public boolean needsDiagramLabels() {
		// By default, no labels needed
		return false;
	}

	public void preBuildDefinitions() {
		// By default, do nothing
	}

	public void writeBuildCommands() {
		// By default, do nothing
	}

	public abstract ElementDetails initializeDiagram();

	public abstract void writeDefinition(ElementDetails details);

	public void writeDiagramEnter() {
		// By default, nothing is needed
	}

	public void writePerChartDefinitions() {
		if (vis.tDiagram.isHierarchical) {
			out.add("var tree, expandState = [], collapseState = {};").at(50).comment("collapse state maps node IDs to true/false");
		}
	}

	public void writePreDefinition(ElementDetails details) {
		// By Default, do nothing
	}

	void addAestheticsAndTooltips(ElementDetails details) {
		D3ElementBuilder.writeAesthetics(details, true, vis, out, labelBuilder);
	}

	void makeHierarchicalTree(boolean definedHierarchy) {
		Integer prune = findPruneParameter(vis.tDiagramParameters);
		String pruneValue;
		if (prune == null) pruneValue = null;
		else if (prune < 1) {
			if (vis.coords == VisTypes.Coordinates.polar)
				pruneValue = "geom.inner_width * geom.inner_height / 1000";
			else if (vis.coords == VisTypes.Coordinates.transposed)
				pruneValue = "geom.inner_width / 10";
			else
				pruneValue = "geom.inner_height / 10";
		} else {
			pruneValue = prune.toString();
		}

		String[] positionFields = vis.positionFields();

		if (positionFields.length != 0 || vis.fKeys.isEmpty()) {
			// Positions have been defined using fields, so we create a hierarchy by treating them as categories
			// and nesting categories of one field within the field at the next level up.
			String fieldsList = positionFields.length == 0 ? "" : quoted(positionFields);
			String sizeParam = size == null ? null : Data.quote(size.asField());
			out.add("var first = (!tree)");
			if (definedHierarchy) {
				// Already defined so set the value on a new line
				out.endStatement();
			} else {
				// not defined, so add to definition list
				out.add(", ");
			}
			out.add("hierarchy = BrunelData.diagram_Hierarchical.makeByNestingFields(processed, "
					+ sizeParam + ", " + fieldsList + ")")
					.endStatement();
		} else {<commit_msg>Fix for trailing comma generation in JS<commit_after>/*
 * Copyright (c) 2015 IBM Corporation and others.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * You may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.brunel.build.d3.diagrams;

import org.brunel.action.Param;
import org.brunel.build.d3.D3Interaction;
import org.brunel.build.d3.D3LabelBuilder;
import org.brunel.build.d3.element.D3ElementBuilder;
import org.brunel.build.d3.element.ElementDetails;
import org.brunel.build.info.ElementStructure;
import org.brunel.build.util.ScriptWriter;
import org.brunel.data.Data;
import org.brunel.data.Dataset;
import org.brunel.model.VisSingle;
import org.brunel.model.VisTypes;
import org.brunel.model.VisTypes.Diagram;
import org.brunel.model.VisTypes.Element;

import java.util.ArrayList;
import java.util.List;

public abstract class D3Diagram {
	public static D3Diagram make(ElementStructure structure, D3Interaction interaction, ScriptWriter out) {
		VisSingle vis = structure.vis;
		Dataset data = structure.data;
		if (vis.tDiagram == null) return null;
		if (vis.tDiagram == Diagram.bubble) return new Bubble(structure, data, interaction, out);
		if (vis.tDiagram == Diagram.chord) return new Chord(structure, data, interaction, out);
		if (vis.tDiagram == Diagram.cloud) return new Cloud(structure, data, interaction, out);
		if (vis.tDiagram == Diagram.tree) return new Tree(structure, data, interaction, out);
		if (vis.tDiagram == Diagram.parallel) return new ParallelCoordinates(structure, data, interaction, out);
		if (vis.tDiagram == Diagram.gridded) return new Grid(structure, data, interaction, out);
		if (vis.tDiagram == Diagram.table) return new Table(structure, data, interaction, out);
		if (vis.tDiagram == Diagram.treemap) return new Treemap(structure, data, interaction, out);
		if (vis.tDiagram == Diagram.network)
			return new Network(structure, data, interaction, out);
		if (vis.tDiagram == Diagram.map) {
			if (vis.tDiagramParameters.length == 1 && vis.tDiagramParameters[0].asString().equals("labels"))
				return new GeoMapLabels(structure, data, interaction, out);
			else
				return new GeoMap(structure, data, structure.geo, interaction, out);
		}
		throw new IllegalStateException("Unknown diagram: " + vis.tDiagram);
	}

	final ScriptWriter out;
	final Param size;
	final Element element;
	final VisSingle vis;
	final D3LabelBuilder labelBuilder;
	final D3Interaction interaction;
	final String[] position;
	final ElementStructure structure;
	private boolean isHierarchy;

	D3Diagram(ElementStructure structure, Dataset data, D3Interaction interaction, ScriptWriter out) {
		this.structure = structure;
		this.vis = structure.vis;
		this.out = out;
		this.size = vis.fSize.isEmpty() ? null : vis.fSize.get(0);
		this.position = vis.positionFields();
		this.element = vis.tElement;
		this.interaction = interaction;
		this.labelBuilder = new D3LabelBuilder(vis, out, data);

	}

	public String getRowKeyFunction() {
		return vis.tDiagram.isHierarchical ? "nodeKey" : "function(d) { return d.key }";
	}

	public String getStyleClasses() {
		// Define the classes for this group; note that we flag hierarchies specially also
		String classes = "diagram " + vis.tDiagram.name();
		return "'" + (isHierarchy ? classes + " hierarchy" : classes) + "'";
	}

	public boolean needsDiagramExtras() {
		// By default, no extras needed
		return false;
	}

	public boolean needsDiagramLabels() {
		// By default, no labels needed
		return false;
	}

	public void preBuildDefinitions() {
		// By default, do nothing
	}

	public void writeBuildCommands() {
		// By default, do nothing
	}

	public abstract ElementDetails initializeDiagram();

	public abstract void writeDefinition(ElementDetails details);

	public void writeDiagramEnter() {
		// By default, nothing is needed
	}

	public void writePerChartDefinitions() {
		if (vis.tDiagram.isHierarchical) {
			out.add("var tree, expandState = [], collapseState = {};").at(50).comment("collapse state maps node IDs to true/false");
		}
	}

	public void writePreDefinition(ElementDetails details) {
		// By Default, do nothing
	}

	void addAestheticsAndTooltips(ElementDetails details) {
		D3ElementBuilder.writeAesthetics(details, true, vis, out, labelBuilder);
	}

	void makeHierarchicalTree(boolean definedHierarchy) {
		Integer prune = findPruneParameter(vis.tDiagramParameters);
		String pruneValue;
		if (prune == null) pruneValue = null;
		else if (prune < 1) {
			if (vis.coords == VisTypes.Coordinates.polar)
				pruneValue = "geom.inner_width * geom.inner_height / 1000";
			else if (vis.coords == VisTypes.Coordinates.transposed)
				pruneValue = "geom.inner_width / 10";
			else
				pruneValue = "geom.inner_height / 10";
		} else {
			pruneValue = prune.toString();
		}

		String[] positionFields = vis.positionFields();

		if (positionFields.length != 0 || vis.fKeys.isEmpty()) {
			// Positions have been defined using fields, so we create a hierarchy by treating them as categories
			// and nesting categories of one field within the field at the next level up.
			String fieldsList = positionFields.length == 0 ? "" : ", " + quoted(positionFields);
			String sizeParam = size == null ? null : Data.quote(size.asField());
			out.add("var first = (!tree)");
			if (definedHierarchy) {
				// Already defined so set the value on a new line
				out.endStatement();
			} else {
				// not defined, so add to definition list
				out.add(", ");
			}
			out.add("hierarchy = BrunelData.diagram_Hierarchical.makeByNestingFields(processed, "
					+ sizeParam  + fieldsList + ")")
					.endStatement();
		} else {
{'fraction_non_alphanumeric': 0.11069805865344899, 'fraction_numerical': 0.006774060305658819, 'mean_word_length': 4.3189806678383125, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, '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': '2402958', 'n_tokens_mistral': 3997, 'n_tokens_neox': 3669, 'n_words': 1084}