Browse Source

CHART-13666 图表自动推荐

feature/big-screen
白岳 4 years ago
parent
commit
b981d8be03
  1. 25
      designer-base/src/main/java/com/fr/design/mainframe/chart/info/ChartInfo.java
  2. 17
      designer-base/src/main/java/com/fr/design/mainframe/chart/info/ChartInfoCollector.java
  3. 4
      designer-chart/src/main/java/com/fr/design/chart/AutoChartDialog.java
  4. 36
      designer-chart/src/main/java/com/fr/design/chart/AutoChartTypePane.java
  5. 7
      designer-chart/src/main/java/com/fr/design/chart/ChartDialog.java
  6. 46
      designer-chart/src/main/java/com/fr/design/chart/auto/AutoChartDataModel.java
  7. 17
      designer-chart/src/main/java/com/fr/design/chart/auto/AutoTypeCalculate.java
  8. 56
      designer-chart/src/main/java/com/fr/design/chart/auto/ColumnInfo.java
  9. 265
      designer-chart/src/main/java/com/fr/design/chart/auto/strategy/AbstractAutoTypeStrategy.java
  10. 22
      designer-chart/src/main/java/com/fr/design/chart/auto/strategy/AutoTypeStrategy.java
  11. 79
      designer-chart/src/main/java/com/fr/design/chart/auto/strategy/AvaType.java
  12. 106
      designer-chart/src/main/java/com/fr/design/chart/auto/strategy/imp/AvaStrategy.java
  13. 76
      designer-chart/src/main/java/com/fr/design/chart/auto/strategy/imp/BubbleChartStrategy.java
  14. 68
      designer-chart/src/main/java/com/fr/design/chart/auto/strategy/imp/SingleDimensionStrategy.java
  15. 45
      designer-chart/src/main/java/com/fr/design/chart/auto/strategy/imp/SingleTargetStrategy.java
  16. 66
      designer-chart/src/main/resources/com/fr/design/chart/auto/js/analyze.js
  17. 2729
      designer-chart/src/main/resources/com/fr/design/chart/auto/js/ava.js

25
designer-base/src/main/java/com/fr/design/mainframe/chart/info/ChartInfo.java

@ -54,6 +54,8 @@ public class ChartInfo extends AbstractPointInfo {
private static final String ATTR_OVER_CHART_TYPE_COUNT = "overChartTypeCount";
private static final String ATTR_IS_NEW = "isNew";
private static final String ATTR_IS_REUSE = "isReuse";
private static final String ATTR_AUTO_CHART_CREATE_TIME = "autoChartCreateTime";
private static final String ATTR_AUTO_CHART_ENSURE_TIME = "autoChartEnsureTime";
private static final int COMPLETE_DAY_COUNT = 3; // 判断图表是否可以上传的天数
@ -122,10 +124,10 @@ public class ChartInfo extends AbstractPointInfo {
}
public static ChartInfo newInstance(ChartProvider chartProvider) {
return newInstance(chartProvider, null, false, false);
return newInstance(chartProvider, null, false, false, false);
}
public static ChartInfo newInstance(ChartProvider chartProvider, String createTime, boolean isNew, boolean isReuse) {
public static ChartInfo newInstance(ChartProvider chartProvider, String createTime, boolean isNew, boolean isReuse, boolean isAutoChart) {
HashMap<String, String> chartConsumingMap = new HashMap<>();
String username = MarketConfig.getInstance().getBbsUsername();
@ -163,6 +165,13 @@ public class ChartInfo extends AbstractPointInfo {
chartConsumingMap.put(ATTR_OVER_CHART_TYPE_COUNT, "0");
chartConsumingMap.put(ATTR_IS_NEW, String.valueOf(isNew));
chartConsumingMap.put(ATTR_IS_REUSE, String.valueOf(isReuse));
if (isAutoChart) {
chartConsumingMap.put(ATTR_AUTO_CHART_CREATE_TIME, createTime);
chartConsumingMap.put(ATTR_AUTO_CHART_ENSURE_TIME, typeTime);
} else {
chartConsumingMap.put(ATTR_AUTO_CHART_CREATE_TIME, StringUtils.EMPTY);
chartConsumingMap.put(ATTR_AUTO_CHART_ENSURE_TIME, StringUtils.EMPTY);
}
ChartInfo chartInfo = new ChartInfo(chartId, templateId, book);
chartInfo.chartConsumingMap = chartConsumingMap;
@ -202,6 +211,9 @@ public class ChartInfo extends AbstractPointInfo {
writer.attr(ATTR_OVER_CHART_TYPE_COUNT, chartConsumingMap.get(ATTR_OVER_CHART_TYPE_COUNT));
writer.attr(ATTR_IS_NEW, chartConsumingMap.get(ATTR_IS_NEW));
writer.attr(ATTR_IS_REUSE, chartConsumingMap.get(ATTR_IS_REUSE));
writer.attr(ATTR_AUTO_CHART_CREATE_TIME, chartConsumingMap.get(ATTR_AUTO_CHART_CREATE_TIME));
writer.attr(ATTR_AUTO_CHART_ENSURE_TIME, chartConsumingMap.get(ATTR_AUTO_CHART_ENSURE_TIME));
writer.end();
chartConfigInfo.writeXML(writer);
@ -238,6 +250,8 @@ public class ChartInfo extends AbstractPointInfo {
chartConsumingMap.put(ATTR_OVER_CHART_TYPE_COUNT, reader.getAttrAsString(ATTR_OVER_CHART_TYPE_COUNT, "0"));
chartConsumingMap.put(ATTR_IS_NEW, reader.getAttrAsString(ATTR_IS_NEW, StringUtils.EMPTY));
chartConsumingMap.put(ATTR_IS_REUSE, reader.getAttrAsString(ATTR_IS_REUSE, StringUtils.EMPTY));
chartConsumingMap.put(ATTR_AUTO_CHART_CREATE_TIME, reader.getAttrAsString(ATTR_AUTO_CHART_CREATE_TIME, StringUtils.EMPTY));
chartConsumingMap.put(ATTR_AUTO_CHART_ENSURE_TIME, reader.getAttrAsString(ATTR_AUTO_CHART_ENSURE_TIME, StringUtils.EMPTY));
}
if (ChartConfigInfo.XML_TAG.equals(name)) {
this.chartConfigInfo = (ChartConfigInfo) reader.readXMLObject(new ChartConfigInfo());
@ -276,6 +290,10 @@ public class ChartInfo extends AbstractPointInfo {
}
public void updateChartType(ChartProvider chartProvider) {
updateChartType(chartProvider, false);
}
public void updateChartType(ChartProvider chartProvider, boolean isAutoChart) {
String typeTime = DateTime.now().toString("yyyy-MM-dd HH:mm:ss");
chartConsumingMap.put(ATTR_CHART_TYPE_TIME, typeTime);
@ -285,6 +303,9 @@ public class ChartInfo extends AbstractPointInfo {
String count = chartConsumingMap.get(ATTR_OVER_CHART_TYPE_COUNT);
count = StringUtils.isEmpty(count) ? "1" : String.valueOf(Integer.parseInt(count) + 1);
chartConsumingMap.put(ATTR_OVER_CHART_TYPE_COUNT, count);
if (isAutoChart) {
chartConsumingMap.put(ATTR_AUTO_CHART_ENSURE_TIME, typeTime);
}
resetChartConfigInfo(chartProvider);
}

17
designer-base/src/main/java/com/fr/design/mainframe/chart/info/ChartInfoCollector.java

@ -12,6 +12,7 @@ import com.fr.stable.StringUtils;
import com.fr.stable.xml.XMLPrintWriter;
import com.fr.stable.xml.XMLableReader;
import com.fr.third.joda.time.DateTime;
import java.util.HashMap;
import java.util.Map;
@ -49,18 +50,22 @@ public class ChartInfoCollector extends AbstractPointCollector<ChartInfo> {
}
public void collection(ChartProvider chartProvider, String createTime) {
collection(chartProvider, createTime, false);
collection(chartProvider, createTime, false, false);
}
public void collection(ChartProvider chartProvider, String createTime, boolean isReuse) {
collection(chartProvider, createTime, isReuse, false);
}
/**
* 新建图表保存状态
*/
public void collection(ChartProvider chartProvider, String createTime, boolean isReuse) {
public void collection(ChartProvider chartProvider, String createTime, boolean isReuse, boolean isAutoChart) {
String chartId = chartProvider.getChartUuid();
if (!shouldCollectInfo() || StringUtils.isEmpty(chartId)) {
return;
}
ChartInfo chartInfo = ChartInfo.newInstance(chartProvider, createTime, true, isReuse);
ChartInfo chartInfo = ChartInfo.newInstance(chartProvider, createTime, true, isReuse, isAutoChart);
chartInfoCacheMap.put(chartId, chartInfo);
}
@ -116,6 +121,10 @@ public class ChartInfoCollector extends AbstractPointCollector<ChartInfo> {
* 图表类型变化更新类型和类型确认时间
*/
public void updateChartTypeTime(ChartProvider chartProvider, String oldType) {
updateChartTypeTime(chartProvider, oldType, false);
}
public void updateChartTypeTime(ChartProvider chartProvider, String oldType, boolean isAutoChart) {
if (!shouldCollectInfo() || StringUtils.isEmpty(chartProvider.getChartUuid())) {
return;
}
@ -123,7 +132,7 @@ public class ChartInfoCollector extends AbstractPointCollector<ChartInfo> {
ChartInfo chartInfo = getOrCreateChartInfo(chartProvider, oldType);
//更新类型确认时间和类型
chartInfo.updateChartType(chartProvider);
chartInfo.updateChartType(chartProvider, isAutoChart);
//重置计数
chartInfo.resetIdleDayCount();

4
designer-chart/src/main/java/com/fr/design/chart/AutoChartDialog.java

@ -36,11 +36,11 @@ public class AutoChartDialog extends ChartDialog {
return autoChartTypePane;
}
protected ActionListener getActionListener() {
protected ActionListener getActionListener(final String createTime) {
return new ActionListener() {
public void actionPerformed(ActionEvent e) {
ChartCollection chartCollection = (ChartCollection) getChartCollection();
autoChartTypePane.update(chartCollection);
autoChartTypePane.update(chartCollection, createTime);
if (chartCollection.getChartCount() > 0) {
doOK();
} else {

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

@ -2,7 +2,6 @@ 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;
@ -15,6 +14,7 @@ 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.mainframe.chart.info.ChartInfoCollector;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.general.GeneralUtils;
import com.fr.log.FineLoggerFactory;
@ -225,8 +225,9 @@ public class AutoChartTypePane extends ChartWizardPane implements CallbackEvent
}
} catch (Exception e) {
if (!(e instanceof CancellationException)) {
connectionBar.close();
FineLoggerFactory.getLogger().error(e.getMessage(), e);
FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), e.getMessage(),
FineJOptionPane.showMessageDialog(AutoChartTypePane.this, e.getMessage(),
Toolkit.i18nText("Fine-Design_Basic_Error"), JOptionPane.ERROR_MESSAGE, UIManager.getIcon("OptionPane.errorIcon"));
}
} finally {
@ -243,16 +244,7 @@ public class AutoChartTypePane extends ChartWizardPane implements CallbackEvent
@Override
public void update(ChartCollection cc) {
if (chartViewList.getSelectedIndex() < 0) {
return;
}
AutoChartIcon chartIcon = (AutoChartIcon) chartViewList.getSelectedValue();
ChartProvider chartProvider = chartIcon.getChartCollection().getSelectedChartProvider(ChartProvider.class);
if (cc.getChartCount() > 0) {
cc.setSelectChart(chartProvider);
} else {
cc.addChart(chartProvider);
}
update(cc, null);
}
public void populate(String tableName, String[] dataFields) {
@ -264,6 +256,26 @@ public class AutoChartTypePane extends ChartWizardPane implements CallbackEvent
dataFieldBox.setSelectedValues(map);
}
public void update(ChartCollection cc, String createTime) {
if (chartViewList.getSelectedIndex() < 0) {
return;
}
AutoChartIcon chartIcon = (AutoChartIcon) chartViewList.getSelectedValue();
VanChart vanChart = chartIcon.getChartCollection().getSelectedChartProvider(VanChart.class);
if (cc.getChartCount() > 0) {
VanChart selectedChartProvider = cc.getSelectedChartProvider(VanChart.class);
if (selectedChartProvider.getChartUuid() != null) {
vanChart.setUuid(selectedChartProvider.getChartUuid());
}
cc.setSelectChart(vanChart);
ChartInfoCollector.getInstance().updateChartTypeTime(vanChart, null, true);
} else {
cc.addChart(vanChart);
//记录埋点
ChartInfoCollector.getInstance().collection(vanChart, createTime, false, true);
}
}
@Override
public void callback() {
this.repaint();

7
designer-chart/src/main/java/com/fr/design/chart/ChartDialog.java

@ -31,7 +31,6 @@ public class ChartDialog extends MiddleChartDialog {
private UIButton ok;
private UIButton cancel;
private ChartTypePane chartTypePane;
private String createTime;
public ChartDialog(Frame owner) {
super(owner);
@ -44,7 +43,7 @@ public class ChartDialog extends MiddleChartDialog {
}
private void initComponent() {
createTime = DateTime.now().toString("yyyy-MM-dd HH:mm:ss");
String createTime = DateTime.now().toString("yyyy-MM-dd HH:mm:ss");
this.setModal(true);
this.setLayout(new BorderLayout());
setTitle(getDialogTitle());
@ -61,7 +60,7 @@ public class ChartDialog extends MiddleChartDialog {
ok = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_OK"));
cancel = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Cancel"));
ok.addActionListener(getActionListener());
ok.addActionListener(getActionListener(createTime));
cancel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
doCancel();
@ -83,7 +82,7 @@ public class ChartDialog extends MiddleChartDialog {
return chartTypePane;
}
protected ActionListener getActionListener() {
protected ActionListener getActionListener(final String createTime) {
return new ActionListener() {
public void actionPerformed(ActionEvent e) {
chartTypePane.update((ChartCollection) cc, createTime);

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

@ -1,46 +0,0 @@
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);
}
}

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

@ -1,14 +1,15 @@
package com.fr.design.chart.auto;
import com.fr.chart.auto.ColumnInfo;
import com.fr.chart.auto.strategy.AutoTypeStrategy;
import com.fr.chart.auto.strategy.imp.AvaStrategy;
import com.fr.chart.auto.strategy.imp.BubbleChartStrategy;
import com.fr.chart.auto.strategy.imp.SingleDimensionStrategy;
import com.fr.chart.auto.strategy.imp.SingleTargetStrategy;
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;
@ -114,14 +115,14 @@ public class AutoTypeCalculate {
}
private static List<String> getColumnData(EmbeddedTableData tableData, String columnName) {
int colIndex = getColIndex(tableData, columnName);
List<String> columnData = new ArrayList<>();
int colIndex = getColIndex(tableData, columnName);
if (colIndex == DataModel.COLUMN_NAME_NOT_FOUND) {
return null;
return columnData;
}
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));

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

@ -1,56 +0,0 @@
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

@ -1,265 +0,0 @@
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

@ -1,22 +0,0 @@
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

@ -1,79 +0,0 @@
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

@ -1,106 +0,0 @@
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

@ -1,76 +0,0 @@
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

@ -1,68 +0,0 @@
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

@ -1,45 +0,0 @@
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

@ -1,66 +0,0 @@
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