“mitao”
2026-02-11 504880873eeea15bcbe7d5a79608ccc4abacb0d2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
package com.estate.expert.admin.service.impl;
 
import com.estate.expert.admin.domain.common.IDtoBase;
import com.estate.expert.admin.domain.standard.expert.Expert;
import com.estate.expert.admin.domain.standard.expert.matrix.CompareMatrix;
import com.estate.expert.admin.domain.standard.expert.matrix.MembershipMatrix;
import com.estate.expert.admin.domain.standard.expert.matrix.MembershipMatrixRowDto;
import com.estate.expert.admin.domain.standard.expert.matrix.WeightMatrixRow;
import com.estate.expert.admin.domain.standard.hierachy.HierarchyData;
import com.estate.expert.admin.domain.user.User;
import com.estate.expert.admin.enums.BizResultCode;
import com.estate.expert.admin.io.processor.impl.matrix.CompareMatrixProcessor;
import com.estate.expert.admin.io.processor.impl.matrix.MembershipMatrixProcessor;
import com.estate.expert.admin.service.common.CrudServiceBaseImpl;
import com.estate.expert.admin.service.expert.ExpertService;
import com.estate.expert.admin.utils.Tuple;
import com.estate.expert.admin.utils.tree.TreeNode;
import com.estate.expert.admin.utils.tree.TreeRoot;
import com.estate.expert.admin.utils.tree.helper.TreeHelper;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.CollectionUtils;
 
import javax.lang.model.type.NullType;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
 
/**
 * 专家服务实现
 */
public abstract class ExpertServiceImpl<T extends Expert, D extends IDtoBase>
        extends CrudServiceBaseImpl<T, D> implements ExpertService<T, D> {
 
    @Override
    public void editWeightMap(Integer expertId, String hierarchyPath, Float weight) {
        var expert = get(expertId);
        BizResultCode.BIZ_EXPERT_NOT_EXIST.check(expert == null);
        if(expert.getWeightMap() == null)
            expert.setWeightMap(new TreeMap<>());
        expert.getWeightMap().put(hierarchyPath, weight);
        save(expert);
    }
 
    @Override
    public void editWeightMatrixRow(Integer expertId, WeightMatrixRow row) {
        var expert = get(expertId);
        BizResultCode.BIZ_EXPERT_NOT_EXIST.check(expert == null);
 
        if(expert.getWeightMap() == null)
            expert.setWeightMap(new TreeMap<>());
 
        expert.getWeightMap().put(row.getHierarchyPath(), row.getWeight());
        save(expert);
    }
 
    @Override
    public void editWeightMatrixRows(Integer expertId, List<WeightMatrixRow> rows) {
        var expert = get(expertId);
        BizResultCode.BIZ_EXPERT_NOT_EXIST.check(expert == null);
 
        if(expert.getWeightMap() == null)
            expert.setWeightMap(new TreeMap<>());
 
        rows.forEach(row -> expert.getWeightMap().put(row.getHierarchyPath(), row.getWeight()));
 
        save(expert);
    }
 
    @Override
    public Map<String, Tuple<String, Float>> weightMap(Integer expertId, String hierarchyPath) {
        var res = new TreeMap<String, Tuple<String, Float>>();
        var expert = get(expertId);
        BizResultCode.BIZ_EXPERT_NOT_EXIST.check(expert == null);
 
        var hierarchyTree = getHierarchyTree(expertId);
        var weightMap = expert.getWeightMap();
        var node = hierarchyTree.get(hierarchyPath);
        BizResultCode.HIERARCHY_NODE_NOT_FOUND.check(node == null);
        node.getChildren().forEach((key, value) -> {
            Float weight = value.getData().getWeight();
            if(weightMap != null && weightMap.containsKey(value.getPath()))
            {
                weight = weightMap.get(value.getPath());
            }
            res.put(value.getPath(), new Tuple<>(value.getName(), weight));
        });
        return res;
    }
 
    @Override
    public List<WeightMatrixRow> weightMatrix(Integer expertId, String hierarchyPath) {
        var expert = get(expertId);
        BizResultCode.BIZ_EXPERT_NOT_EXIST.check(expert == null);
 
        var weightMatrix = new ArrayList<WeightMatrixRow>();
 
        var hierarchyTree = getHierarchyTree(expertId);
        var weightMap = expert.getWeightMap();
        var node = hierarchyTree.get(hierarchyPath);
        BizResultCode.HIERARCHY_NODE_NOT_FOUND.check(node == null);
        node.getChildren().forEach((key, value) -> {
            Float weight = value.getData().getWeight();
            if(weightMap != null && weightMap.containsKey(value.getPath()))
            {
                weight = weightMap.get(value.getPath());
            }
 
            weightMatrix.add(WeightMatrixRow.builder()
                            .name(value.getName())
                            .hierarchyPath(value.getPath())
                            .weight(weight)
                    .build());
        });
        return weightMatrix;
    }
 
    @Override
    public MembershipMatrix getMembershipMatrix(Integer expertId) {
        var expert = get(expertId);
        BizResultCode.BIZ_EXPERT_NOT_EXIST.check(expert == null);
        return expert.getMembershipMatrix();
    }
 
    @Override
    public void editMembershipMatrix(Integer expertId, float[][][][][] data) {
        MembershipMatrixProcessor.validate(data);
 
        var expert = get(expertId);
        BizResultCode.BIZ_EXPERT_NOT_EXIST.check(expert == null);
 
        var oldMatrix = expert.getMembershipMatrix();
        if(oldMatrix != null)
            oldMatrix.setData(data);
        else
            expert.setMembershipMatrix(new MembershipMatrix(null, data));
        save(expert);
    }
 
    @Override
    public void editMembershipMatrixRow(Integer expertId, MembershipMatrixRowDto row) {
        MembershipMatrixProcessor.validateRow(row);
 
        var expert = get(expertId);
        BizResultCode.BIZ_EXPERT_NOT_EXIST.check(expert == null);
 
        var matrix = expert.getMembershipMatrix();
        BizResultCode.MEMBERSHIP_MATRIX_NOT_EXIST.check(matrix == null);
 
        var data = matrix.getData();
        data[row.getP1()][row.getP2()][row.getP3()][row.getP4()] =
            new float[]{row.getV0(), row.getV1(), row.getV2(), row.getV3(), row.getV4()};
        save(expert);
    }
 
    @Override
    public List<MembershipMatrixRowDto> listMembershipMatrixRows(Integer expertId, Integer p1, Integer p2, Integer p3, Integer p4) {
        var matrix = getMembershipMatrix(expertId);
        return matrix.listRows(p1, p2, p3, p4);
    }
 
    @Override
    public void importMembershipMatrix(Integer expertId, InputStream inputStream) {
        MembershipMatrix matrix = null;
        try {
            matrix = new MembershipMatrixProcessor().loadFromWorkbook(inputStream);
            editMembershipMatrix(expertId, matrix.getData());
        } catch (IOException e) {
            e.printStackTrace();
            BizResultCode.MEMBERSHIP_MATRIX_LOAD_ERROR.check(true);
        }
        BizResultCode.MEMBERSHIP_MATRIX_LOAD_ERROR.check(matrix == null);
    }
 
    @Override
    public CompareMatrix getFuzzyMatrix(Integer expertId, String hierarchyPath) {
        var hierarchyTree = getHierarchyTree(expertId);
        var node = hierarchyTree.get(hierarchyPath);
        BizResultCode.HIERARCHY_NODE_NOT_FOUND.check(node == null);
 
        var children = node.getChildren();
        BizResultCode.COMPARE_MATRIX_EMPTY.check(children == null || children.isEmpty());
 
        var indexCols = children.values().stream().map(TreeNode::getName).toArray(String[]::new);
        return getFuzzyMatrix(expertId, hierarchyPath, indexCols);
    }
 
    @Override
    public CompareMatrix getFuzzyMatrix(Integer expertId, String hierarchyPath, String[] indexCols) {
        var expert = get(expertId);
        BizResultCode.BIZ_EXPERT_NOT_EXIST.check(expert == null);
        BizResultCode.INDEX_COLS_EMPTY.check(indexCols == null || indexCols.length == 0);
 
        if(expert.getCompareMatrixMap() == null)
            return new CompareMatrix(indexCols);
 
        var compareMatrix = expert.getCompareMatrixMap().get(hierarchyPath);
        if(compareMatrix == null)
            return new CompareMatrix(indexCols);
 
        return compareMatrix.subMatrix(indexCols);
    }
 
    @Override
    public void editFuzzyMatrix(Integer expertId, String hierarchyPath, CompareMatrix matrix) {
        // 校验矩阵
        CompareMatrixProcessor.validate(matrix);
 
        var expert = get(expertId);
        BizResultCode.BIZ_EXPERT_NOT_EXIST.check(expert == null);
 
        var compareMatrixMap = expert.getCompareMatrixMap();
        if(compareMatrixMap == null) {
            compareMatrixMap = new TreeMap<>();
            expert.setCompareMatrixMap(compareMatrixMap);
        }
        compareMatrixMap.put(hierarchyPath, matrix);
        save(expert);
    }
 
    @Override
    public TreeNode<NullType> getNullModelTree(Integer expertId) {
        var expert = get(expertId);
        BizResultCode.BIZ_EXPERT_NOT_EXIST.check(expert == null);
        var modelTree = getModelTree(expert.getModel());
        return TreeHelper.<HierarchyData, NullType> convertTree(modelTree.root(), (node, newNode) -> null);
    }
 
//    public abstract TreeRoot<HierarchyData> getModelTree(Model model);
 
    @Override
    public TreeRoot<HierarchyData> getHierarchyTree(Integer expertId) {
        var expert = get(expertId);
        BizResultCode.BIZ_EXPERT_NOT_EXIST.check(expert == null);
 
        // 首先获得模型中的树结构
        var modelTree = getModelTree(expert.getModel());
 
        var scoreMatrix = expert.getWeightMap();
        // 然后根据专家的评分表,更新树的评分
        if(scoreMatrix != null) {
            TreeHelper.travel(modelTree.root(), (node) -> {
                var score = scoreMatrix.get(node.getPath());
                if (score != null) {
                    node.getData().setScore(score);
                }
            });
        }
        return modelTree;
    }
 
    //////      初始化专家      //////
    @Override
    public T add(User creator, T entity) {
        BizResultCode.EXPERT_FUNCTIONS_MUST_ENABLE.check(CollectionUtils.isEmpty(entity.getExpertFuncs()));
        BizResultCode.EXPERT_MODEL_NOT_EXIST.check(entity.getModel() == null || !existModel(entity.getModel().getId()));
        if(entity.getMembershipMatrix() == null)
            entity.setMembershipMatrix(loadDefaultMembershipMatrix());
        return super.add(creator, entity);
    }
 
    @Override
    public T edit(T entity) {
        BizResultCode.EXPERT_FUNCTIONS_MUST_ENABLE.check(CollectionUtils.isEmpty(entity.getExpertFuncs()));
        return super.edit(entity);
    }
 
    private MembershipMatrix loadDefaultMembershipMatrix() {
        try {
            var res = new ClassPathResource("data/membership_matrix.xlsx");
            return new MembershipMatrixProcessor().loadFromWorkbook(res.getInputStream());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
 
    protected abstract boolean existModel(Integer modelId);
 
}