白岳
5 years ago
14 changed files with 3777 additions and 5 deletions
@ -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); |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
||||
} |
@ -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); |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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()); |
||||
} |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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()); |
||||
} |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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); |
||||
} |
Loading…
Reference in new issue