Browse Source

CHART-13666 自动类型推荐匹配

feature/big-screen
白岳 4 years ago
parent
commit
d8233ad43e
  1. 2
      designer-chart/src/main/java/com/fr/design/chart/AutoChartIcon.java
  2. 78
      designer-chart/src/main/java/com/fr/design/chart/AutoChartTypePane.java
  3. 46
      designer-chart/src/main/java/com/fr/design/chart/auto/AutoChartDataModel.java
  4. 142
      designer-chart/src/main/java/com/fr/design/chart/auto/AutoTypeCalculate.java
  5. 56
      designer-chart/src/main/java/com/fr/design/chart/auto/ColumnInfo.java
  6. 265
      designer-chart/src/main/java/com/fr/design/chart/auto/strategy/AbstractAutoTypeStrategy.java
  7. 22
      designer-chart/src/main/java/com/fr/design/chart/auto/strategy/AutoTypeStrategy.java
  8. 79
      designer-chart/src/main/java/com/fr/design/chart/auto/strategy/AvaType.java
  9. 106
      designer-chart/src/main/java/com/fr/design/chart/auto/strategy/imp/AvaStrategy.java
  10. 76
      designer-chart/src/main/java/com/fr/design/chart/auto/strategy/imp/BubbleChartStrategy.java
  11. 68
      designer-chart/src/main/java/com/fr/design/chart/auto/strategy/imp/SingleDimensionStrategy.java
  12. 45
      designer-chart/src/main/java/com/fr/design/chart/auto/strategy/imp/SingleTargetStrategy.java
  13. 66
      designer-chart/src/main/resources/com/fr/design/chart/auto/js/analyze.js
  14. 2729
      designer-chart/src/main/resources/com/fr/design/chart/auto/js/ava.js

2
designer-chart/src/main/java/com/fr/design/chart/AutoChartIcon.java

@ -66,7 +66,7 @@ public class AutoChartIcon implements Icon {
public void paintIcon(Component c, Graphics g, int x, int y) {
BaseChartPainter painter = chartCollection.createResultChartPainterWithOutDealFormula(Calculator.createCalculator(),
WebChartIDInfo.createEmptyDesignerInfo(), getIconWidth(), getIconHeight());
WebChartIDInfo.createAutoTypeInfo(), getIconWidth(), getIconHeight());
int resolution = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().getJTemplateResolution();

78
designer-chart/src/main/java/com/fr/design/chart/AutoChartTypePane.java

@ -3,27 +3,41 @@ package com.fr.design.chart;
import com.fr.base.chart.chartdata.CallbackEvent;
import com.fr.chart.chartattr.ChartCollection;
import com.fr.chartx.attr.ChartProvider;
import com.fr.design.chart.auto.AutoTypeCalculate;
import com.fr.design.data.DesignTableDataManager;
import com.fr.design.data.datapane.TableDataComboBox;
import com.fr.design.data.tabledata.wrapper.TableDataWrapper;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.icombocheckbox.UIComboCheckBox;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.iprogressbar.AutoProgressBar;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.general.GeneralUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.plugin.chart.vanchart.VanChart;
import javax.swing.BorderFactory;
import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.ListCellRenderer;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.plaf.SplitPaneUI;
import javax.swing.plaf.basic.BasicSplitPaneUI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CancellationException;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
@ -46,6 +60,9 @@ public class AutoChartTypePane extends ChartWizardPane implements CallbackEvent
private TableDataComboBox tableNameComboBox;
private UIComboCheckBox dataFieldBox;
private AutoProgressBar connectionBar;
private SwingWorker worker;
public AutoChartTypePane() {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
initButtonGroup();
@ -62,10 +79,15 @@ public class AutoChartTypePane extends ChartWizardPane implements CallbackEvent
chartViewList.setCellRenderer(iconCellRenderer);
JScrollPane subListPane = new JScrollPane(chartViewList);
subListPane.setBorder(BorderFactory.createTitledBorder(Toolkit.i18nText("Fine-Design_Chart_Recommended_Chart")));
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, false, contentPane, subListPane);
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true, contentPane, subListPane);
SplitPaneUI ui = splitPane.getUI();
if (ui instanceof BasicSplitPaneUI) {
((BasicSplitPaneUI) ui).getDivider().setBorder(null);
}
splitPane.setDividerLocation(60);
splitPane.setBorder(BorderFactory.createTitledBorder(Toolkit.i18nText("Fine-Design_Chart_M_Popup_Auto_Chart_Type")));
this.add(splitPane);
}
@ -94,7 +116,7 @@ public class AutoChartTypePane extends ChartWizardPane implements CallbackEvent
JPanel tableDataPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane();
panel.add(tableDataPane);
tableDataPane.add(new UILabel(Toolkit.i18nText("Fine-Design_Chart_Table_Data") + ":"));
tableNameComboBox.setPreferredSize(new Dimension(96, 20));
tableNameComboBox.setPreferredSize(new Dimension(126, 20));
tableDataPane.add(tableNameComboBox);
JPanel areaNamePane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane();
@ -102,6 +124,7 @@ public class AutoChartTypePane extends ChartWizardPane implements CallbackEvent
areaNamePane.add(new UILabel(Toolkit.i18nText("Fine-Design_Chart_Data_Field") + ":"));
areaNamePane.add(dataFieldBox);
panel.add(refreshButton);
panel.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0));
return panel;
}
@ -154,6 +177,7 @@ public class AutoChartTypePane extends ChartWizardPane implements CallbackEvent
refreshButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
refreshButton.setEnabled(false);
calculateAutoChart();
}
});
@ -161,7 +185,55 @@ public class AutoChartTypePane extends ChartWizardPane implements CallbackEvent
}
private void calculateAutoChart() {
connectionBar = new AutoProgressBar(this, Toolkit.i18nText("Fine-Design_Chart_Generate_Recommended_Chart"), "", 0, 100) {
public void doMonitorCanceled() {
refreshButton.setEnabled(true);
worker.cancel(true);
}
};
setWorker();
worker.execute();
}
private void setWorker() {
worker = new SwingWorker<List<VanChart>, Void>() {
protected List<VanChart> doInBackground() {
connectionBar.start();
chartResultModel.clear();
List<String> columnList = new ArrayList<>();
Object[] selectedValues = dataFieldBox.getSelectedValues();
for (Object value : selectedValues) {
columnList.add(GeneralUtils.objectToString(value));
}
List<VanChart> vanChartList = AutoTypeCalculate.calculateType(tableNameComboBox.getSelectedItem().getTableDataName(), columnList);
connectionBar.close();
return vanChartList;
}
public void done() {
try {
List<VanChart> vanChartList = get();
if (vanChartList != null && !vanChartList.isEmpty()) {
for (VanChart vanChart : vanChartList) {
ChartCollection chartCollection = new ChartCollection(vanChart);
AutoChartIcon autoChartIcon = new AutoChartIcon(chartCollection);
autoChartIcon.registerCallBackEvent(AutoChartTypePane.this);
chartResultModel.addElement(autoChartIcon);
}
chartViewList.setSelectedIndex(0);
}
} catch (Exception e) {
if (!(e instanceof CancellationException)) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), e.getMessage(),
Toolkit.i18nText("Fine-Design_Basic_Error"), JOptionPane.ERROR_MESSAGE, UIManager.getIcon("OptionPane.errorIcon"));
}
} finally {
refreshButton.setEnabled(true);
}
}
};
}
@Override

46
designer-chart/src/main/java/com/fr/design/chart/auto/AutoChartDataModel.java

@ -0,0 +1,46 @@
package com.fr.design.chart.auto;
import com.fr.data.AbstractDataModel;
import com.fr.general.data.DataModel;
import java.util.List;
/**
* @author Bjorn
* @version 10.0
* Created by Bjorn on 2020-06-16
*/
public class AutoChartDataModel extends AbstractDataModel {
public List<ColumnInfo> columnInfoList;
public AutoChartDataModel(List<ColumnInfo> columnInfos) {
this.columnInfoList = columnInfos;
}
@Override
public int getColumnCount() {
return columnInfoList.size();
}
@Override
public String getColumnName(int index) {
if (index >= columnInfoList.size()) {
return null;
}
return columnInfoList.get(index).getColumnName();
}
@Override
public int getRowCount() {
return columnInfoList.get(0).getValues().size();
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
if (columnIndex == DataModel.COLUMN_NAME_NOT_FOUND || columnIndex >= columnInfoList.size()) {
return null;
}
return columnInfoList.get(columnIndex).getValues().get(rowIndex);
}
}

142
designer-chart/src/main/java/com/fr/design/chart/auto/AutoTypeCalculate.java

@ -0,0 +1,142 @@
package com.fr.design.chart.auto;
import com.fr.data.TableDataSource;
import com.fr.data.TableDataSourceTailor;
import com.fr.data.impl.EmbeddedTableData;
import com.fr.data.impl.NameTableData;
import com.fr.design.chart.auto.strategy.AutoTypeStrategy;
import com.fr.design.chart.auto.strategy.imp.AvaStrategy;
import com.fr.design.chart.auto.strategy.imp.BubbleChartStrategy;
import com.fr.design.chart.auto.strategy.imp.SingleDimensionStrategy;
import com.fr.design.chart.auto.strategy.imp.SingleTargetStrategy;
import com.fr.design.data.DesignTableDataManager;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.general.ComparatorUtils;
import com.fr.general.GeneralUtils;
import com.fr.general.data.DataModel;
import com.fr.log.FineLoggerFactory;
import com.fr.plugin.chart.vanchart.VanChart;
import com.fr.script.Calculator;
import com.fr.stable.StringUtils;
import java.util.ArrayList;
import java.util.List;
/**
* @author Bjorn
* @version 10.0
* Created by Bjorn on 2020-05-08
*/
public class AutoTypeCalculate {
public static List<VanChart> calculateType(String tableName, List<String> columns) {
List<ColumnInfo> columnValue = calculateField(tableName, columns);
if (columnValue.isEmpty()) {
return new ArrayList<>();
}
List<ColumnInfo> dimensions = new ArrayList<>();
List<ColumnInfo> targets = new ArrayList<>();
for (ColumnInfo field : columnValue) {
if (isTarget(field.getValues())) {
targets.add(field);
} else {
dimensions.add(field);
}
}
AutoTypeStrategy autoTypeStrategy = chooseStrategy(dimensions.size(), targets.size());
return autoTypeStrategy.rankChart(tableName, dimensions, targets);
}
private static AutoTypeStrategy chooseStrategy(int dimensionSize, int targetSize) {
if (dimensionSize == 0) {
//没有维度,并且只有一个指标,使用单指标匹配逻辑,大于1个指标,使用气泡图(散点图)匹配逻辑
if (targetSize == 1) {
return new SingleTargetStrategy();
} else {
return new BubbleChartStrategy();
}
} else if (dimensionSize == 1) {
//1个维度,并且没有指标,使用单维度匹配,2~3个指标,使用气泡图(散点图)匹配逻辑,其余使用ava匹配
if (targetSize == 0) {
return new SingleDimensionStrategy();
} else if (targetSize == 2 || targetSize == 3) {
return new BubbleChartStrategy();
} else {
return new AvaStrategy();
}
} else {
//大与1个维度,并且没有指标,使用单维度匹配(循环),否则使用ava匹配
if (targetSize == 0) {
return new SingleDimensionStrategy();
} else {
return new AvaStrategy();
}
}
}
private static boolean isTarget(List<String> values) {
for (String value : values) {
if (StringUtils.isEmpty(value)) {
continue;
}
Number number = GeneralUtils.string2Number(value);
if (number == null) {
return false;
}
}
return true;
}
private static List<ColumnInfo> calculateField(String tableName, List<String> columns) {
NameTableData nameTableData = new NameTableData(tableName);
TableDataSource dataSource = TableDataSourceTailor.extractTableData(HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().getTarget());
Calculator calculator = Calculator.createCalculator();
calculator.setAttribute(TableDataSource.KEY, dataSource);
nameTableData.createTableData(calculator);
EmbeddedTableData tableData;
try {
tableData = DesignTableDataManager.previewTableDataNeedInputParameters(dataSource, nameTableData, Integer.MAX_VALUE, false);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
return new ArrayList<>();
}
List<ColumnInfo> originalData = new ArrayList<>();
for (String column : columns) {
List<String> columnData = getColumnData(tableData, column);
if (columnData != null && !columnData.isEmpty()) {
originalData.add(new ColumnInfo(column, columnData));
}
}
return originalData;
}
private static List<String> getColumnData(EmbeddedTableData tableData, String columnName) {
int colIndex = getColIndex(tableData, columnName);
if (colIndex == DataModel.COLUMN_NAME_NOT_FOUND) {
return null;
}
int size = tableData.getRowCount();
List<String> columnData = new ArrayList<>();
for (int i = 0; i < size; i++) {
Object valueAt = tableData.getValueAt(i, colIndex);
columnData.add(GeneralUtils.objectToString(valueAt));
}
return columnData;
}
private static int getColIndex(EmbeddedTableData tableData, String columnName) {
int colIndex = 0;
for (int count = tableData.getColumnCount(); colIndex < count; ++colIndex) {
if (ComparatorUtils.tableDataColumnNameEquals(tableData.getColumnName(colIndex), columnName)) {
return colIndex;
}
}
return DataModel.COLUMN_NAME_NOT_FOUND;
}
}

56
designer-chart/src/main/java/com/fr/design/chart/auto/ColumnInfo.java

@ -0,0 +1,56 @@
package com.fr.design.chart.auto;
import com.fr.data.util.function.DataFunction;
import java.util.ArrayList;
import java.util.List;
/**
* @author Bjorn
* @version 10.0
* Created by Bjorn on 2020-06-16
*/
public class ColumnInfo {
private String columnName;
private List<String> values;
private DataFunction function;
private List<Object> resultValues = new ArrayList<>();
public ColumnInfo(String columnName, List<String> values) {
this.columnName = columnName;
this.values = values;
}
public String getColumnName() {
return columnName;
}
public void setColumnName(String columnName) {
this.columnName = columnName;
}
public List<String> getValues() {
return values;
}
public void setValues(List<String> values) {
this.values = values;
}
public DataFunction getFunction() {
return function;
}
public void setFunction(DataFunction function) {
this.function = function;
}
public List<Object> getResultValues() {
return resultValues;
}
public void setResultValues(List<Object> resultValues) {
this.resultValues = resultValues;
}
}

265
designer-chart/src/main/java/com/fr/design/chart/auto/strategy/AbstractAutoTypeStrategy.java

@ -0,0 +1,265 @@
package com.fr.design.chart.auto.strategy;
import com.fr.base.chart.chartdata.TopDefinitionProvider;
import com.fr.chart.chartdata.BubbleTableDefinition;
import com.fr.chart.chartdata.ChartDataUtils;
import com.fr.chart.chartdata.ChartSummaryColumn;
import com.fr.chart.chartdata.MoreNameCDDefinition;
import com.fr.chart.chartdata.OneValueCDDefinition;
import com.fr.data.impl.NameTableData;
import com.fr.data.util.function.DataFunction;
import com.fr.design.chart.auto.ColumnInfo;
import com.fr.general.GeneralUtils;
import com.fr.general.data.DataModel;
import com.fr.graph.g2d.canvas.CanvasPainter;
import com.fr.json.JSONArray;
import com.fr.json.JSONObject;
import com.fr.locale.InterProviderFactory;
import com.fr.log.FineLoggerFactory;
import com.fr.plugin.chart.vanchart.VanChart;
import com.fr.stable.StringUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* @author Bjorn
* @version 10.0
* Created by Bjorn on 2020-06-17
*/
public abstract class AbstractAutoTypeStrategy implements AutoTypeStrategy {
private static CanvasPainter engine;
public static final String NONE = InterProviderFactory.getProvider().getLocText("Fine-Engine_Chart_Use_None");
public static final int MAX_COUNT = 3;
//对维度和指标进行计算
protected void calculateColumn(List<ColumnInfo> dimensions, List<ColumnInfo> targets) {
//<key,<functionFieldId,valueList>> 需要聚合计算的数据数组。eg:{a-x-:{fieldId3:[1,4],fieldId4:[5,8]},a-y-:{fieldId3:[3],fieldId4:[7]}}。
Map<String, Map<String, List<Object>>> targetFieldMap = new HashMap<>();
//关键字段可能有数据字典属性,需要拿到数据字典的映射值<key,<keyFieldId, (actualValue, displayValue)>>。eg:{a-x-:{fieldId1:(a,a1),fieldId1:(x,x1)},a-y-:{fieldId1:(a,a1),fieldId1:(y,y1)}}
Map<String, Map<String, String>> dimensionFieldMap = new LinkedHashMap<>();
int size = dimensions.get(0).getValues().size();
for (int rowIndex = 0; rowIndex < size; rowIndex++) {
String key = StringUtils.EMPTY;
Map<String, String> keyValueMap = new HashMap<>();
//处理维度字段
for (ColumnInfo field : dimensions) {
String columnName = field.getColumnName();
String result = field.getValues().get(rowIndex);
List<Object> resultList = new ArrayList<>();
key += (result + "-");
resultList.add(result);
keyValueMap.put(columnName, result);
}
if (!dimensionFieldMap.containsKey(key)) {
dimensionFieldMap.put(key, keyValueMap);
}
//处理指标字段
for (ColumnInfo field : targets) {
String result = field.getValues().get(rowIndex);
Map<String, List<Object>> map = targetFieldMap.get(key);
if (map == null) {
map = new HashMap<>();
targetFieldMap.put(key, map);
}
String columnName = field.getColumnName();
List<Object> list = map.get(columnName);
if (list == null) {
list = new ArrayList<>();
map.put(columnName, list);
}
list.add(result);
}
}
calculateAndFill(dimensionFieldMap, targetFieldMap, dimensions, targets);
}
private void calculateAndFill(Map<String, Map<String, String>> dimensionFieldMap,
Map<String, Map<String, List<Object>>> targetFieldMap,
List<ColumnInfo> dimensions, List<ColumnInfo> targets) {
for (String key : dimensionFieldMap.keySet()) {
Map<String, List<Object>> targetValues = targetFieldMap.get(key);
//对需要计算的字段使用dataFunction进行计算
for (ColumnInfo field : targets) {
DataFunction dataFunction = field.getFunction();
dataFunction.reset();
List<Object> valueList = targetValues.get(field.getColumnName());
field.getResultValues().add(ChartDataUtils.calculateByFunction(dataFunction, valueList));
}
Map<String, String> keyValue = dimensionFieldMap.get(key);
for (ColumnInfo field : dimensions) {
String result = keyValue.get(field.getColumnName());
field.getResultValues().add(result);
}
}
}
protected List<RankChart> analyzeByAva(List<ColumnInfo> dimensions, List<ColumnInfo> targets) {
List<RankChart> rankChartList = new ArrayList<>();
CanvasPainter engine = createEngine();
if (engine == null) {
return rankChartList;
}
JSONArray jsonArray = new JSONArray();
int size = dimensions.isEmpty() ? targets.get(0).getResultValues().size() : dimensions.get(0).getResultValues().size();
for (int i = 0; i < size; i++) {
JSONObject jsonObject = new JSONObject();
for (ColumnInfo columnInfo : dimensions) {
jsonObject.put(columnInfo.getColumnName(), GeneralUtils.objectToString(columnInfo.getResultValues().get(i)));
}
for (ColumnInfo columnInfo : targets) {
jsonObject.put(columnInfo.getColumnName(), GeneralUtils.objectToNumber(columnInfo.getResultValues().get(i)));
}
jsonArray.add(jsonObject);
}
String result = StringUtils.EMPTY;
try {
result = (String) engine.executeFunction("analyzeData", jsonArray.toString());
} catch (Exception ex) {
FineLoggerFactory.getLogger().error(ex.getMessage(), ex);
}
JSONArray resultArray = new JSONArray(result);
for (int i = 0; i < resultArray.length(); i++) {
JSONObject jsonObject = resultArray.getJSONObject(i);
AvaType type = AvaType.parse(GeneralUtils.objectToString(jsonObject.get("type")));
double score = GeneralUtils.objectToNumber(jsonObject.get("score")).doubleValue();
if (type == null || score <= 0) {
continue;
}
RankChart rankChart = new RankChart();
rankChart.setVanChart(type.getVanChart());
rankChart.setGrade(score);
rankChart.setMainCategory(GeneralUtils.objectToString(jsonObject.get("category")));
rankChartList.add(rankChart);
if (rankChartList.size() >= MAX_COUNT) {
break;
}
}
return rankChartList;
}
protected List<VanChart> selectHighRankChart(List<RankChart> rankChartList) {
Collections.sort(rankChartList);
List<VanChart> vanChartList = new ArrayList<>();
int size = Math.min(rankChartList.size(), MAX_COUNT);
for (int i = 0; i < size; i++) {
vanChartList.add(rankChartList.get(i).getVanChart());
}
return vanChartList;
}
private synchronized static CanvasPainter createEngine() {
if (engine != null) {
return engine;
}
CanvasPainter.Builder builder = null;
try {
builder = CanvasPainter.newDefaultBuilder()
.loadAndExecute("/com/fr/design/chart/auto/js/analyze.js")
.loadAndExecute("/com/fr/design/chart/auto/js/ava.js");
} catch (Exception ex) {
FineLoggerFactory.getLogger().error(ex.getMessage(), ex);
} finally {
if (builder != null) {
engine = builder.build();
}
}
return engine;
}
protected TopDefinitionProvider createOneValueCDDefinition(String tableName, DataModel dataModel, String categoryName,
String seriesName, String valueName, DataFunction dataFunction) {
OneValueCDDefinition oneValueCDDefinition = new OneValueCDDefinition();
oneValueCDDefinition.setTableData(new NameTableData(tableName));
oneValueCDDefinition.setDataModel(dataModel);
oneValueCDDefinition.setCategoryName(categoryName);
oneValueCDDefinition.setSeriesColumnName(seriesName);
oneValueCDDefinition.setValueColumnName(valueName);
oneValueCDDefinition.setDataFunction(dataFunction);
return oneValueCDDefinition;
}
protected TopDefinitionProvider createMoreNameCDDefinition(String tableName, DataModel dataModel,
String categoryName, String seriesName, DataFunction dataFunction) {
ChartSummaryColumn chartSummaryColumn = new ChartSummaryColumn();
chartSummaryColumn.setCustomName(seriesName);
chartSummaryColumn.setName(seriesName);
chartSummaryColumn.setFunction(dataFunction);
MoreNameCDDefinition moreNameCDDefinition = new MoreNameCDDefinition();
moreNameCDDefinition.setTableData(new NameTableData(tableName));
moreNameCDDefinition.setDataModel(dataModel);
moreNameCDDefinition.setCategoryName(categoryName);
moreNameCDDefinition.setChartSummaryColumn(new ChartSummaryColumn[]{chartSummaryColumn});
return moreNameCDDefinition;
}
protected TopDefinitionProvider createBubbleTableDefinition(String tableName, DataModel dataModel,
String seriesName, String x, String y, String value) {
BubbleTableDefinition bubbleTableDefinition = new BubbleTableDefinition();
bubbleTableDefinition.setTableData(new NameTableData(tableName));
bubbleTableDefinition.setDataModel(dataModel);
bubbleTableDefinition.setSeriesName(seriesName);
bubbleTableDefinition.setBubbleX(x);
bubbleTableDefinition.setBubbleY(y);
bubbleTableDefinition.setBubbleSize(value);
return bubbleTableDefinition;
}
public class RankChart implements Comparable<RankChart> {
private double grade;
private VanChart vanChart;
private String mainCategory;
public double getGrade() {
return grade;
}
public void setGrade(double grade) {
this.grade = grade;
}
public VanChart getVanChart() {
return vanChart;
}
public void setVanChart(VanChart vanChart) {
this.vanChart = vanChart;
}
public String getMainCategory() {
return mainCategory;
}
public void setMainCategory(String mainCategory) {
this.mainCategory = mainCategory;
}
public int compareTo(RankChart compare) {
//分数越高,排名越前
return compare.getGrade() - grade >= 0 ? 1 : -1;
}
}
}

22
designer-chart/src/main/java/com/fr/design/chart/auto/strategy/AutoTypeStrategy.java

@ -0,0 +1,22 @@
package com.fr.design.chart.auto.strategy;
import com.fr.design.chart.auto.ColumnInfo;
import com.fr.plugin.chart.vanchart.VanChart;
import java.util.List;
/**
* @author Bjorn
* @version 10.0
* Created by Bjorn on 2020-06-16
*/
public interface AutoTypeStrategy {
/**
* 计算排名匹配度最高的图表
*
* @param dimensions 维度
* @param targets 指标
*/
public List<VanChart> rankChart(String tableName, List<ColumnInfo> dimensions, List<ColumnInfo> targets);
}

79
designer-chart/src/main/java/com/fr/design/chart/auto/strategy/AvaType.java

@ -0,0 +1,79 @@
package com.fr.design.chart.auto.strategy;
import com.fr.chart.charttypes.ChartTypeManager;
import com.fr.log.FineLoggerFactory;
import com.fr.plugin.chart.PiePlot4VanChart;
import com.fr.plugin.chart.area.VanChartAreaPlot;
import com.fr.plugin.chart.bubble.VanChartBubblePlot;
import com.fr.plugin.chart.column.VanChartColumnPlot;
import com.fr.plugin.chart.line.VanChartLinePlot;
import com.fr.plugin.chart.radar.VanChartRadarPlot;
import com.fr.plugin.chart.scatter.VanChartScatterPlot;
import com.fr.plugin.chart.vanchart.VanChart;
import com.fr.stable.StringUtils;
/**
* @author Bjorn
* @version 10.0
* Created by Bjorn on 2020-06-18
*/
public enum AvaType {
//柱形图,堆积柱形图,百分比堆积柱形图
COLUMN_CHART(VanChartColumnPlot.VAN_CHART_COLUMN_PLOT_ID, 0),
STACKED_COLUMN_CHART(VanChartColumnPlot.VAN_CHART_COLUMN_PLOT_ID, 1),
PERCENT_STACKED_COLUMN_CHART(VanChartColumnPlot.VAN_CHART_COLUMN_PLOT_ID, 2),
//条形图,堆积条形图,百分比堆积条形图
BAR_CHART(VanChartColumnPlot.VAN_CHART_BAR_PLOT_ID, 0),
STACKED_BAR_CHART(VanChartColumnPlot.VAN_CHART_BAR_PLOT_ID, 1),
PERCENT_STACKED_BAR_CHART(VanChartColumnPlot.VAN_CHART_BAR_PLOT_ID, 2),
//雷达图
RADAR_CHART(VanChartRadarPlot.VAN_CHART_RADAR_PLOT, 0),
//饼图
PIE_CHART(PiePlot4VanChart.VAN_CHART_PIE_PLOT, 0),
//折线图
LINE_CHART(VanChartLinePlot.VAN_CHART_LINE_PLOT, 0),
//面积图
AREA_CHART(VanChartAreaPlot.VAN_CHART_AREA_PLOT_ID, 0),
STACKED_AREA_CHART(VanChartAreaPlot.VAN_CHART_AREA_PLOT_ID, 1),
PERCENT_STACKED_AREA_CHART(VanChartAreaPlot.VAN_CHART_AREA_PLOT_ID, 2),
//散点图
SCATTER_PLOT(VanChartScatterPlot.VAN_CHART_SCATTER_PLOT_ID, 0),
//气泡图
BUBBLE_CHART(VanChartBubblePlot.VAN_CHART_BUBBLE_PLOT_ID, 0);
private VanChart vanChart;
AvaType(String vanChartType, int vanChartIndex) {
vanChart = (VanChart) ChartTypeManager.getInstance().
getCharts(vanChartType)[vanChartIndex];
}
public VanChart getVanChart() {
VanChart vanChart = null;
try {
vanChart = (VanChart) this.vanChart.clone();
} catch (Exception ex) {
FineLoggerFactory.getLogger().error(ex.getMessage(), ex);
}
return vanChart;
}
public static AvaType parse(String typeName) {
for (AvaType type : AvaType.values()) {
if (StringUtils.equalsIgnoreCase(type.toString(), typeName)) {
return type;
}
}
return null;
}
}

106
designer-chart/src/main/java/com/fr/design/chart/auto/strategy/imp/AvaStrategy.java

@ -0,0 +1,106 @@
package com.fr.design.chart.auto.strategy.imp;
import com.fr.base.chart.chartdata.TopDefinitionProvider;
import com.fr.data.util.function.SumFunction;
import com.fr.design.chart.auto.AutoChartDataModel;
import com.fr.design.chart.auto.ColumnInfo;
import com.fr.design.chart.auto.strategy.AbstractAutoTypeStrategy;
import com.fr.general.data.DataModel;
import com.fr.plugin.chart.area.VanChartAreaPlot;
import com.fr.plugin.chart.line.VanChartLinePlot;
import com.fr.plugin.chart.radar.VanChartRadarPlot;
import com.fr.plugin.chart.vanchart.VanChart;
import com.fr.stable.StringUtils;
import java.util.ArrayList;
import java.util.List;
/**
* @author Bjorn
* @version 10.0
* Created by Bjorn on 2020-06-16
* 使用ava来匹配的策略
*/
public class AvaStrategy extends AbstractAutoTypeStrategy {
public List<VanChart> rankChart(String tableName, List<ColumnInfo> dimensions, List<ColumnInfo> targets) {
List<RankChart> rankChartList = new ArrayList<>();
for (ColumnInfo columnInfo : targets) {
columnInfo.setFunction(new SumFunction());
}
if (dimensions.size() == 1) {
//一个维度+一个指标匹配
for (ColumnInfo target : targets) {
List<ColumnInfo> newTargets = new ArrayList<>();
newTargets.add(target);
rankChartList.addAll(rankChartByAva(tableName, dimensions, newTargets));
//ava匹配之后,初始化图表和分数
}
} else {
//两个维度+一个指标匹配
int size = dimensions.size();
for (int i = 0; i < size; i++) {
for (int j = i + 1; j < size; j++) {
for (ColumnInfo target : targets) {
List<ColumnInfo> newDimensions = new ArrayList<>();
newDimensions.add(dimensions.get(i));
newDimensions.add(dimensions.get(j));
List<ColumnInfo> newTargets = new ArrayList<>();
newTargets.add(target);
rankChartList.addAll(rankChartByAva(tableName, newDimensions, newTargets));
}
}
}
}
return selectHighRankChart(rankChartList);
}
private List<RankChart> rankChartByAva(String tableName, List<ColumnInfo> dimensions, List<ColumnInfo> targets) {
for (ColumnInfo columnInfo : dimensions) {
columnInfo.setResultValues(new ArrayList<>());
}
for (ColumnInfo columnInfo : targets) {
columnInfo.setResultValues(new ArrayList<>());
}
calculateColumn(dimensions, targets);
//调用ava
List<RankChart> rankChartList = analyzeByAva(dimensions, targets);
List<ColumnInfo> modelList = new ArrayList<>();
modelList.addAll(dimensions);
modelList.addAll(targets);
AutoChartDataModel dataModel = new AutoChartDataModel(modelList);
for (RankChart rankChart : rankChartList) {
VanChart vanChart = rankChart.getVanChart();
String plotID = vanChart.getPlot().getPlotID();
vanChart.setFilterDefinition(creatDefinition(plotID, rankChart.getMainCategory(), tableName, dataModel, dimensions, targets));
}
return rankChartList;
}
private TopDefinitionProvider creatDefinition(String plotId, String category, String tableName, DataModel dataModel,
List<ColumnInfo> dimensions, List<ColumnInfo> targets) {
String categoryName;
String seriesName;
switch (plotId) {
case VanChartLinePlot.VAN_CHART_LINE_PLOT:
case VanChartAreaPlot.VAN_CHART_AREA_PLOT_ID:
case VanChartRadarPlot.VAN_CHART_RADAR_PLOT:
if (dimensions.size() == 1) {
return createMoreNameCDDefinition(tableName, dataModel, dimensions.get(0).getColumnName(), targets.get(0).getColumnName(), new SumFunction());
} else {
categoryName = category;
seriesName = StringUtils.equals(dimensions.get(0).getColumnName(), categoryName) ?
dimensions.get(1).getColumnName() : dimensions.get(0).getColumnName();
return createOneValueCDDefinition(tableName, dataModel, categoryName, seriesName, targets.get(0).getColumnName(), new SumFunction());
}
default:
categoryName = dimensions.size() > 1 ? dimensions.get(0).getColumnName() : NONE;
seriesName = dimensions.size() > 1 ? dimensions.get(1).getColumnName() : dimensions.get(0).getColumnName();
return createOneValueCDDefinition(tableName, dataModel, categoryName, seriesName, targets.get(0).getColumnName(), new SumFunction());
}
}
}

76
designer-chart/src/main/java/com/fr/design/chart/auto/strategy/imp/BubbleChartStrategy.java

@ -0,0 +1,76 @@
package com.fr.design.chart.auto.strategy.imp;
import com.fr.base.chart.chartdata.TopDefinitionProvider;
import com.fr.design.chart.auto.AutoChartDataModel;
import com.fr.design.chart.auto.ColumnInfo;
import com.fr.design.chart.auto.strategy.AbstractAutoTypeStrategy;
import com.fr.plugin.chart.vanchart.VanChart;
import com.fr.stable.StringUtils;
import java.util.ArrayList;
import java.util.List;
/**
* @author Bjorn
* @version 10.0
* Created by Bjorn on 2020-06-16
* 匹配气泡图和散点图的策略
*/
public class BubbleChartStrategy extends AbstractAutoTypeStrategy {
@Override
public List<VanChart> rankChart(String tableName, List<ColumnInfo> dimensions, List<ColumnInfo> targets) {
List<RankChart> rankChartList = new ArrayList<>();
for (ColumnInfo columnInfo : dimensions) {
List<Object> resultValues = columnInfo.getResultValues();
for (String str : columnInfo.getValues()) {
resultValues.add(str);
}
}
for (ColumnInfo columnInfo : targets) {
List<Object> resultValues = columnInfo.getResultValues();
for (String str : columnInfo.getValues()) {
resultValues.add(str);
}
}
int size = targets.size();
//散点图
if (size == 2) {
rankChartList.addAll(rankChartByAva(tableName, dimensions, targets));
} else {
//气泡图
for (int i = 0; i < size; i++) {
for (int j = i + 1; j < size; j++) {
for (int k = j + 1; k < size; k++) {
List<ColumnInfo> newTargets = new ArrayList<>();
newTargets.add(targets.get(i));
newTargets.add(targets.get(j));
newTargets.add(targets.get(k));
rankChartList.addAll(rankChartByAva(tableName, dimensions, newTargets));
}
}
}
}
return selectHighRankChart(rankChartList);
}
private List<RankChart> rankChartByAva(String tableName, List<ColumnInfo> dimensions, List<ColumnInfo> targets) {
//调用ava
List<RankChart> rankChartList = analyzeByAva(dimensions, targets);
List<ColumnInfo> modelList = new ArrayList<>();
modelList.addAll(dimensions);
modelList.addAll(targets);
AutoChartDataModel dataModel = new AutoChartDataModel(modelList);
String series = dimensions.size() == 0 ? NONE : dimensions.get(0).getColumnName();
String value = targets.size() == 2 ? StringUtils.EMPTY : targets.get(2).getColumnName();
TopDefinitionProvider bubbleTableDefinition = createBubbleTableDefinition(tableName, dataModel, series,
targets.get(0).getColumnName(), targets.get(1).getColumnName(), value);
for (RankChart rankChart : rankChartList) {
VanChart vanChart = rankChart.getVanChart();
vanChart.setFilterDefinition(bubbleTableDefinition);
}
return rankChartList;
}
}

68
designer-chart/src/main/java/com/fr/design/chart/auto/strategy/imp/SingleDimensionStrategy.java

@ -0,0 +1,68 @@
package com.fr.design.chart.auto.strategy.imp;
import com.fr.base.chart.chartdata.TopDefinitionProvider;
import com.fr.data.util.function.CountFunction;
import com.fr.design.chart.auto.AutoChartDataModel;
import com.fr.design.chart.auto.ColumnInfo;
import com.fr.design.chart.auto.strategy.AbstractAutoTypeStrategy;
import com.fr.general.data.DataModel;
import com.fr.plugin.chart.area.VanChartAreaPlot;
import com.fr.plugin.chart.line.VanChartLinePlot;
import com.fr.plugin.chart.radar.VanChartRadarPlot;
import com.fr.plugin.chart.vanchart.VanChart;
import java.util.ArrayList;
import java.util.List;
/**
* @author Bjorn
* @version 10.0
* Created by Bjorn on 2020-06-16
* 匹配无指标的策略
*/
public class SingleDimensionStrategy extends AbstractAutoTypeStrategy {
@Override
public List<VanChart> rankChart(String tableName, List<ColumnInfo> dimensions, List<ColumnInfo> targets) {
List<RankChart> rankChartList = new ArrayList<>();
for (ColumnInfo columnInfo : dimensions) {
ColumnInfo target = new ColumnInfo(columnInfo.getColumnName(), columnInfo.getValues());
target.setFunction(new CountFunction());
target.setColumnName("value");
List<ColumnInfo> newDimension = new ArrayList<>();
List<ColumnInfo> newTarget = new ArrayList<>();
newDimension.add(columnInfo);
newTarget.add(target);
rankChartList.addAll(rankChartByAva(tableName, newDimension, newTarget));
}
return selectHighRankChart(rankChartList);
}
private List<RankChart> rankChartByAva(String tableName, List<ColumnInfo> dimensions, List<ColumnInfo> targets) {
calculateColumn(dimensions, targets);
//调用ava
List<RankChart> rankChartList = analyzeByAva(dimensions, targets);
AutoChartDataModel dataModel = new AutoChartDataModel(dimensions);
for (RankChart rankChart : rankChartList) {
VanChart vanChart = rankChart.getVanChart();
String plotID = vanChart.getPlot().getPlotID();
vanChart.setFilterDefinition(creatDefinition(plotID, tableName, dataModel, dimensions));
}
return rankChartList;
}
private TopDefinitionProvider creatDefinition(String plotId, String tableName, DataModel dataModel,
List<ColumnInfo> dimensions) {
switch (plotId) {
case VanChartLinePlot.VAN_CHART_LINE_PLOT:
case VanChartAreaPlot.VAN_CHART_AREA_PLOT_ID:
case VanChartRadarPlot.VAN_CHART_RADAR_PLOT:
return createMoreNameCDDefinition(tableName, dataModel, dimensions.get(0).getColumnName(), dimensions.get(0).getColumnName(), new CountFunction());
default:
return createOneValueCDDefinition(tableName, dataModel, NONE, dimensions.get(0).getColumnName(), dimensions.get(0).getColumnName(), new CountFunction());
}
}
}

45
designer-chart/src/main/java/com/fr/design/chart/auto/strategy/imp/SingleTargetStrategy.java

@ -0,0 +1,45 @@
package com.fr.design.chart.auto.strategy.imp;
import com.fr.data.util.function.NoneFunction;
import com.fr.design.chart.auto.AutoChartDataModel;
import com.fr.design.chart.auto.ColumnInfo;
import com.fr.design.chart.auto.strategy.AbstractAutoTypeStrategy;
import com.fr.design.chart.auto.strategy.AvaType;
import com.fr.plugin.chart.attr.axis.VanChartAxis;
import com.fr.plugin.chart.attr.axis.VanChartValueAxis;
import com.fr.plugin.chart.column.VanChartColumnPlot;
import com.fr.plugin.chart.vanchart.VanChart;
import java.util.ArrayList;
import java.util.List;
/**
* @author Bjorn
* @version 10.0
* Created by Bjorn on 2020-06-16
* 匹配无维度的策略
*/
public class SingleTargetStrategy extends AbstractAutoTypeStrategy {
@Override
public List<VanChart> rankChart(String tableName, List<ColumnInfo> dimensions, List<ColumnInfo> targets) {
//只有一个指标,匹配直方图
VanChart vanChart = AvaType.COLUMN_CHART.getVanChart();
List<ColumnInfo> allColumn = new ArrayList<>(dimensions);
allColumn.addAll(targets);
AutoChartDataModel dataModel = new AutoChartDataModel(allColumn);
String columnName = targets.get(0).getColumnName();
vanChart.setFilterDefinition(createMoreNameCDDefinition(tableName, dataModel, columnName, columnName, new NoneFunction()));
VanChartColumnPlot plot = vanChart.getPlot();
List<VanChartAxis> xAxisList = plot.getXAxisList();
VanChartAxis vanChartAxis = xAxisList.get(0);
VanChartValueAxis axis = new VanChartValueAxis(vanChartAxis.getAxisName(), vanChartAxis.getPosition());
xAxisList.set(0, axis);
List<VanChart> vanChartList = new ArrayList<>();
vanChartList.add(vanChart);
return vanChartList;
}
}

66
designer-chart/src/main/resources/com/fr/design/chart/auto/js/analyze.js

@ -0,0 +1,66 @@
var document = {
body: {
style: {}
},
documentElement: {
style: {}
},
head: {
prepend: function () {
}
},
addEventListener: function () {
},
createDocumentFragment: function () {
return {
appendChild: function () {
return {};
}
};
},
createElement: function () {
return {
getContext: function () {
return undefined;
},
setAttribute: function () {
},
getElementsByTagName: function () {
return [];
},
appendChild: function () {
return {};
}
}
}
};
function analyzeData(data) {
data = JSON.parse(data);
var result = window.analyze(data);
for (i = 0; i < result.length; i++) {
var type = result[i].type;
if(type == "line_chart" || type == "area_chart"
|| type == "stacked_area_chart" || type == "percent_stacked_area_chart"){
result[i].category = result[i].channels.x;
}
}
return JSON.stringify(result);
}

2729
designer-chart/src/main/resources/com/fr/design/chart/auto/js/ava.js

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save