package com.walker.etaa.extractor; import com.walker.etaa.AbstractQuestionExtractor; import com.walker.etaa.ExtractFailedException; import com.walker.etaa.ExtractNotEnoughException; import com.walker.etaa.ExtractStrategy; import com.walker.etaa.QuestionExtractOptions; import com.walker.etaa.QuestionType; import com.walker.etaa.util.AlgorithmUtils; import com.walker.infrastructure.utils.StringUtils; import java.util.List; /** * 基于平均分布的抽取规则实现。 * @author 时克英 * @date 2023-03-07 */ public abstract class SimpleQuestionExtractor extends AbstractQuestionExtractor { @Override protected List acquireGlobalList(QuestionExtractOptions option) throws ExtractFailedException { long existGlobalCount = this.acquireGlobalTotal(option.getOwnerId(), option.getDeptId(), option.getRootCatalog()); if(existGlobalCount <= 0){ throw new IllegalArgumentException("业务系统未找到任何'全局条件'试题数量:0"); } if(existGlobalCount < option.getExtractTotal()){ throw new ExtractNotEnoughException("抽取数量不足", null, existGlobalCount); } // int[] indexList = AlgorithmUtils.getAverageIndexArray((int)existGlobalCount, (int)option.getExtractTotal()); int[] indexList = this.getIndexList(option.getExtractStrategy(), (int)existGlobalCount, (int)option.getExtractTotal()); List hashCodeList = null; if(StringUtils.isEmpty(option.getRootCatalog())){ logger.debug("......only ownerId"); hashCodeList = AlgorithmUtils.getHashCode(option.getOwnerId(), indexList); return this.loadGlobalList(hashCodeList, null); } else { logger.debug("......root catalog"); hashCodeList = AlgorithmUtils.getHashCode(option.getOwnerId() + option.getRootCatalog(), indexList); return this.loadGlobalList(null, hashCodeList); } } protected int[] getIndexList(ExtractStrategy extractStrategy, int existDataCount, int requiredTotal){ int[] indexList = null; if(extractStrategy == ExtractStrategy.Average){ indexList = AlgorithmUtils.getAverageIndexArray(existDataCount, requiredTotal); } else if(extractStrategy == ExtractStrategy.Random){ indexList = AlgorithmUtils.getRandomIndexArray(existDataCount, requiredTotal); } else { throw new UnsupportedOperationException("不支持的抽取策略:" + extractStrategy); } return indexList; } /** * 获取全局配置条件下,返回的可用试题总数量。 * @param ownerId 归属id,如:顶级机构ID * @param deptId 暂未使用 * @param rootCatalog 题库根分类ID * @return */ protected abstract long acquireGlobalTotal(String ownerId, String deptId, String rootCatalog); /** * 加载试题集合。 * @param ownerHashCodeList 给定的只有归属索引集合 * @param rootCatalogHashCodeList 给定的归属、根分类索引集合 * @return * @date 2023-03-08 */ protected abstract List loadGlobalList(List ownerHashCodeList, List rootCatalogHashCodeList); @Override protected List acquireOptionItemList(QuestionExtractOptions option , QuestionExtractOptions.ExtractOptionItem item) throws ExtractFailedException { long existOptionCount = this.acquireOptionItemTotal(option.getOwnerId() , option.getRootCatalog(), item.getMajorCatalog(), item.getQuestionType()); if(existOptionCount <= 0){ throw new IllegalArgumentException("业务系统未找到任何'抽取规则明细'试题数量:0, item=" + item); } if(existOptionCount < item.getCount()){ throw new ExtractNotEnoughException("抽取数量不足," + item.toString(), null, existOptionCount); } // int[] indexList = AlgorithmUtils.getAverageIndexArray((int)existOptionCount, (int)item.getCount()); int[] indexList = this.getIndexList(option.getExtractStrategy(), (int)existOptionCount, (int)item.getCount()); List hashCodeList = null; StringBuilder prefix = new StringBuilder(option.getOwnerId()); prefix.append(option.getRootCatalog()); if(item.getQuestionType() == null){ logger.debug("......only catalog"); prefix.append(item.getMajorCatalog()); hashCodeList = AlgorithmUtils.getHashCode(prefix.toString(), indexList); return this.loadOptionList(hashCodeList, null); } else { logger.debug("......type"); prefix.append(item.getMajorCatalog()).append(item.getQuestionType().getIndex()); hashCodeList = AlgorithmUtils.getHashCode(prefix.toString(), indexList); return this.loadOptionList(null, hashCodeList); } } protected abstract long acquireOptionItemTotal(String owner , String rootCatalog, String catalog, QuestionType questionType); /** * 从业务数据中加载获取试题集合。 * @param catalogHashCodeList 二级分类HashCode集合 * @param typeHashCodeList 试题类型HashCode集合 * @return */ protected abstract List loadOptionList(List catalogHashCodeList, List typeHashCodeList); }