Skip to content

Commit 85cc0ce

Browse files
committed
feat(ava/advisor): add async and condition type to advisor plugin
1 parent 3d32447 commit 85cc0ce

File tree

13 files changed

+139
-78
lines changed

13 files changed

+139
-78
lines changed

packages/ava/src/advisor/advise-pipeline/plugin/presets/chart-type-recommend/get-chart-Type.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,25 @@ import type {
66
BasicDataPropertyForAdvice,
77
RuleModule,
88
AdvisorOptions,
9+
AdvisorPipelineContext,
910
} from '../../../../types';
1011

1112
export const getChartTypeRecommendations = ({
1213
chartWIKI,
1314
dataProps,
1415
ruleBase,
1516
options,
17+
advisorContext,
1618
}: {
1719
dataProps: BasicDataPropertyForAdvice[];
1820
chartWIKI: Record<string, ChartKnowledge>;
1921
ruleBase: Record<string, RuleModule>;
2022
options?: AdvisorOptions;
23+
advisorContext?: Pick<AdvisorPipelineContext, 'extra'>;
2124
}) => {
2225
const chatTypes = Object.keys(chartWIKI);
2326
const list: ScoringResultForChartType[] = chatTypes.map((chartType) => {
24-
return scoreRules(chartType, chartWIKI, dataProps, ruleBase, options);
27+
return scoreRules(chartType, chartWIKI, dataProps, ruleBase, options, advisorContext);
2528
});
2629

2730
// filter and sorter

packages/ava/src/advisor/advise-pipeline/plugin/presets/chart-type-recommend/plugin-config.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@ export const chartTypeRecommendPlugin: AdvisorPluginType<ChartTypeRecommendInput
1212
stage: ['chartTypeRecommend'],
1313
execute(input: ChartTypeRecommendInput, context?: AdvisorPipelineContext): ChartTypeRecommendOutput {
1414
const { dataProps } = input;
15-
const { advisor, options } = context || {};
15+
const { advisor, options, extra } = context || {};
1616
const chartTypeRecommendations = getChartTypeRecommendations({
1717
dataProps,
1818
chartWIKI: advisor.ckb,
1919
ruleBase: advisor.ruleBase,
2020
options,
21+
advisorContext: { extra },
2122
});
2223
return { chartTypeRecommendations };
2324
},

packages/ava/src/advisor/advise-pipeline/plugin/presets/spec-generator/plugin-config.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export const specGeneratorPlugin: AdvisorPluginType<SpecGeneratorInput, SpecGene
2525
const { chartType } = chartTypeAdvice;
2626
const chartKnowledge = advisor.ckb[chartType];
2727
const chartTypeSpec =
28-
chartKnowledge?.toSpec(data, dataProps) ??
28+
chartKnowledge?.toSpec?.(data, dataProps) ??
2929
getChartTypeSpec({
3030
chartType,
3131
data,
@@ -35,7 +35,7 @@ export const specGeneratorPlugin: AdvisorPluginType<SpecGeneratorInput, SpecGene
3535

3636
// step 3: apply spec processors such as design rules, theme, color, to improve spec
3737
if (chartTypeSpec && refine) {
38-
const partEncSpec = applyDesignRules(chartType, dataProps, advisor.ruleBase, chartTypeSpec);
38+
const partEncSpec = applyDesignRules(chartType, dataProps, advisor.ruleBase, chartTypeSpec, context);
3939
deepMix(chartTypeSpec, partEncSpec);
4040
}
4141

packages/ava/src/advisor/advise-pipeline/plugin/presets/spec-generator/spec-processors/apply-design-rules.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,25 @@
1-
import { BasicDataPropertyForAdvice, RuleModule, Specification, DesignRuleModule } from '../../../../../types';
1+
import {
2+
BasicDataPropertyForAdvice,
3+
RuleModule,
4+
Specification,
5+
DesignRuleModule,
6+
AdvisorPipelineContext,
7+
} from '../../../../../types';
28
import { deepMix } from '../../../../../utils';
39

410
export function applyDesignRules(
511
chartType: string,
612
dataProps: BasicDataPropertyForAdvice[],
713
ruleBase: Record<string, RuleModule>,
8-
chartSpec: Specification
14+
chartSpec: Specification,
15+
advisorContext?: Pick<AdvisorPipelineContext, 'extra'>
916
) {
1017
const toCheckRules = Object.values(ruleBase).filter(
1118
(rule: RuleModule) =>
12-
rule.type === 'DESIGN' && rule.trigger({ dataProps, chartType }) && !ruleBase[rule.id].option?.off
19+
rule.type === 'DESIGN' && rule.trigger({ dataProps, chartType, advisorContext }) && !ruleBase[rule.id].option?.off
1320
);
1421
const encodingSpec = toCheckRules.reduce((lastSpec, rule: RuleModule) => {
15-
const relatedSpec = (rule as DesignRuleModule).optimizer(dataProps, chartSpec);
22+
const relatedSpec = (rule as DesignRuleModule).optimizer(dataProps, chartSpec, advisorContext);
1623
return deepMix(lastSpec, relatedSpec);
1724
}, {});
1825
return encodingSpec;

packages/ava/src/advisor/advise-pipeline/plugin/presets/visual-encoder/plugin-config.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import type { AdvisorPluginType, VisualEncoderInput } from '../../../../types';
1+
import type { AdvisorPluginType, VisualEncoderInput, VisualEncoderOutput } from '../../../../types';
22

3-
export const visualEncoderPlugin: AdvisorPluginType<VisualEncoderInput, VisualEncoderInput> = {
3+
export const visualEncoderPlugin: AdvisorPluginType<VisualEncoderInput, VisualEncoderOutput> = {
44
name: 'defaultVisualEncoder',
55
stage: ['encode'],
66
execute: (input) => {

packages/ava/src/advisor/advise-pipeline/score-calculator/compute-score.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Info, RuleModule } from '../../ruler';
22
import { DEFAULT_RULE_WEIGHTS } from '../../constants';
33

4-
import type { ScoringResultForRule } from '../../types';
4+
import type { AdvisorPipelineContext, ScoringResultForRule } from '../../types';
55
import type { ChartRuleModule } from '../../ruler/types';
66
import type { ChartId, ChartKnowledgeBase } from '../../../ckb';
77

@@ -13,20 +13,32 @@ export const computeScore = (
1313
ruleBase: Record<string, RuleModule>,
1414
ruleType: 'HARD' | 'SOFT',
1515
info: Info,
16-
log: ScoringResultForRule[]
16+
log: ScoringResultForRule[],
17+
advisorContext?: Pick<AdvisorPipelineContext, 'extra'>
1718
) => {
1819
// initial score is 1 for HARD rules and 0 for SOFT rules
1920
let computedScore = 1;
2021
Object.values(ruleBase)
2122
.filter((r: RuleModule) => {
2223
const weight = r.option?.weight || defaultWeights[r.id] || 1;
2324
const extra = r.option?.extra;
24-
return r.type === ruleType && r.trigger({ ...info, weight, ...extra, chartType, chartWIKI }) && !r.option?.off;
25+
return (
26+
r.type === ruleType &&
27+
r.trigger({ ...info, weight, ...extra, chartType, chartWIKI, advisorContext }) &&
28+
!r.option?.off
29+
);
2530
})
2631
.forEach((r: RuleModule) => {
2732
const weight = r.option?.weight || defaultWeights[r.id] || 1;
2833
const extra = r.option?.extra;
29-
const base = (r as ChartRuleModule).validator({ ...info, weight, ...extra, chartType, chartWIKI }) as number;
34+
const base = (r as ChartRuleModule).validator({
35+
...info,
36+
weight,
37+
...extra,
38+
chartType,
39+
chartWIKI,
40+
advisorContext,
41+
}) as number;
3042
const score = weight * base;
3143
computedScore *= score;
3244
log.push({ phase: 'ADVISE', ruleId: r.id, score, base, weight, ruleType });

packages/ava/src/advisor/advise-pipeline/score-calculator/score-rules.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
AdvisorOptions,
55
ScoringResultForChartType,
66
ScoringResultForRule,
7+
AdvisorPipelineContext,
78
} from '../../types';
89

910
import { computeScore } from './compute-score';
@@ -24,7 +25,8 @@ export function scoreRules(
2425
chartWIKI: ChartKnowledgeBase,
2526
dataProps: BasicDataPropertyForAdvice[],
2627
ruleBase: Record<string, RuleModule>,
27-
options?: AdvisorOptions
28+
options?: AdvisorOptions,
29+
advisorContext?: Pick<AdvisorPipelineContext, 'extra'>
2830
): ScoringResultForChartType {
2931
const purpose = options ? options.purpose : '';
3032
const preferences = options ? options.preferences : undefined;
@@ -34,15 +36,15 @@ export function scoreRules(
3436

3537
const info = { dataProps, chartType, purpose, preferences };
3638

37-
const hardScore = computeScore(chartType, chartWIKI, ruleBase, 'HARD', info, log);
39+
const hardScore = computeScore(chartType, chartWIKI, ruleBase, 'HARD', info, log, advisorContext);
3840

3941
// Hard-Rule pruning
4042
if (hardScore === 0) {
4143
const result: ScoringResultForChartType = { chartType, score: 0, log };
4244
return result;
4345
}
4446

45-
const softScore = computeScore(chartType, chartWIKI, ruleBase, 'SOFT', info, log);
47+
const softScore = computeScore(chartType, chartWIKI, ruleBase, 'SOFT', info, log, advisorContext);
4648

4749
const score = hardScore * softScore;
4850

packages/ava/src/advisor/advisor.ts

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
1+
import { forEach, size } from 'lodash';
2+
13
import { ckb } from '../ckb';
24

35
import { processRuleCfg } from './ruler';
46
import { dataToAdvices } from './advise-pipeline';
57
import { checkRules } from './lint-pipeline/check-rules';
68
import { BaseComponent } from './pipeline/component';
79
import { Pipeline } from './pipeline/pipeline';
8-
import { dataProcessorPlugin, specGeneratorPlugin, chartTypeRecommendPlugin } from './advise-pipeline/plugin';
10+
import {
11+
dataProcessorPlugin,
12+
specGeneratorPlugin,
13+
chartTypeRecommendPlugin,
14+
visualEncoderPlugin,
15+
} from './advise-pipeline/plugin';
916

1017
import type { ChartKnowledgeBase } from '../ckb';
1118
import type { RuleModule } from './ruler';
@@ -51,7 +58,7 @@ export class Advisor {
5158

5259
context: AdvisorPipelineContext;
5360

54-
plugins: AdvisorPluginType[];
61+
plugins: AdvisorPluginType[] = [];
5562

5663
pipeline: Pipeline;
5764

@@ -73,8 +80,10 @@ export class Advisor {
7380
this.context = { advisor: this, extra };
7481
this.initDefaultComponents();
7582
const defaultComponents = [this.dataAnalyzer, this.chartTypeRecommender, this.chartEncoder, this.specGenerator];
76-
this.plugins = plugins;
77-
this.pipeline = new Pipeline({ components: components ?? defaultComponents });
83+
this.registerPlugins(plugins);
84+
this.pipeline = new Pipeline<DataProcessorInput, SpecGeneratorOutput>({
85+
components: components ?? defaultComponents,
86+
});
7887
}
7988

8089
private initDefaultComponents() {
@@ -83,7 +92,7 @@ export class Advisor {
8392
plugins: [chartTypeRecommendPlugin],
8493
context: this.context,
8594
});
86-
// this.chartEncoder = new BaseComponent('chartEncode', { plugins: [visualEncoderPlugin], context: this.context });
95+
this.chartEncoder = new BaseComponent('chartEncode', { plugins: [visualEncoderPlugin], context: this.context });
8796
this.specGenerator = new BaseComponent('specGenerate', { plugins: [specGeneratorPlugin], context: this.context });
8897
}
8998

@@ -93,6 +102,11 @@ export class Advisor {
93102
return adviseResult.advices;
94103
}
95104

105+
adviseWithLog(params: AdviseParams): AdviseResult {
106+
const adviseResult = dataToAdvices({ adviseParams: params, ckb: this.ckb, ruleBase: this.ruleBase });
107+
return adviseResult;
108+
}
109+
96110
async adviseAsync(params: AdviseParams): Promise<Advice[]> {
97111
this.context = {
98112
...this.context,
@@ -103,10 +117,7 @@ export class Advisor {
103117
return adviseResult.advices;
104118
}
105119

106-
adviseWithLog(params: AdviseParams): AdviseResult {
107-
const adviseResult = dataToAdvices({ adviseParams: params, ckb: this.ckb, ruleBase: this.ruleBase });
108-
return adviseResult;
109-
}
120+
// todo 补充 adviseAsyncWithLog
110121

111122
lint(params: LintParams): Lint[] {
112123
const lintResult = checkRules(params, this.ruleBase, this.ckb);
@@ -118,18 +129,24 @@ export class Advisor {
118129
return lintResult;
119130
}
120131

121-
registerPlugins(plugins: AdvisorPluginType[]) {
132+
registerPlugins(plugins: AdvisorPluginType[] = []) {
122133
const stage2Components: Record<PipelineStageType, BaseComponent> = {
123134
dataAnalyze: this.dataAnalyzer,
124135
chartTypeRecommend: this.chartTypeRecommender,
125136
encode: this.chartEncoder,
126137
specGenerate: this.specGenerator,
127138
};
128139

129-
plugins.forEach((plugin) => {
140+
forEach(plugins, (plugin) => {
141+
this.plugins.push(plugin);
130142
if (typeof plugin.stage === 'string') {
131143
const pipelineComponent = stage2Components[plugin.stage];
132144
pipelineComponent.registerPlugin(plugin);
145+
return;
146+
}
147+
if (size(plugin.stage) === 1) {
148+
const pipelineComponent = stage2Components[plugin.stage[0]];
149+
pipelineComponent.registerPlugin(plugin);
133150
}
134151
});
135152
}

packages/ava/src/advisor/lint-pipeline/lintRules.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Info, RuleModule } from '../ruler';
22

33
import type { Specification } from '../../common/types';
4-
import type { ScoringResultForRule, Lint } from '../types';
4+
import type { ScoringResultForRule, Lint, AdvisorPipelineContext } from '../types';
55
import type { ChartRuleModule, DesignRuleModule } from '../ruler';
66
import type { ChartKnowledgeBase } from '../../ckb';
77

@@ -12,7 +12,8 @@ export function lintRules(
1212
log: ScoringResultForRule[],
1313
lints: Lint[],
1414
ckb: ChartKnowledgeBase,
15-
spec?: Specification
15+
spec?: Specification,
16+
advisorContext?: Pick<AdvisorPipelineContext, 'extra'>
1617
) {
1718
const judge = (type: 'HARD' | 'SOFT' | 'DESIGN') => {
1819
if (ruleTypeToLint === 'DESIGN') {
@@ -24,20 +25,28 @@ export function lintRules(
2425
Object.values(ruleBase)
2526
.filter((r: RuleModule) => {
2627
const { weight, extra } = r.option || {};
27-
return judge(r.type) && !r.option?.off && r.trigger({ ...info, weight, ...extra, chartWIKI: ckb });
28+
return (
29+
judge(r.type) && !r.option?.off && r.trigger({ ...info, weight, ...extra, chartWIKI: ckb, advisorContext })
30+
);
2831
})
2932
.forEach((r: RuleModule) => {
3033
const { type, id, docs } = r;
3134
let score: number;
3235
if (ruleTypeToLint === 'DESIGN') {
33-
const fix = (r as DesignRuleModule).optimizer(info.dataProps, spec);
36+
const fix = (r as DesignRuleModule).optimizer(info.dataProps, spec, advisorContext);
3437
// no fix -> means no violation
3538
score = Object.keys(fix).length === 0 ? 1 : 0;
3639
lints.push({ type, id, score, fix, docs });
3740
} else {
3841
const { weight, extra } = r.option || {};
3942
// no weight for linter's result
40-
score = (r as ChartRuleModule).validator({ ...info, weight, ...extra, chartWIKI: ckb }) as number;
43+
score = (r as ChartRuleModule).validator({
44+
...info,
45+
weight,
46+
...extra,
47+
chartWIKI: ckb,
48+
advisorContext,
49+
}) as number;
4150
lints.push({ type, id, score, docs });
4251
}
4352
log.push({ phase: 'LINT', ruleId: id, score, base: score, weight: 1, ruleType: type });

0 commit comments

Comments
 (0)