#include "GreyClusteringItemDelegate.h" #include "GreyClusteringSampleTable.h" #include "MultiLevelHeaderView.h" #include "CMind.h" #include "dbService/GradeInfoService.h" #include "dbService/EffectIndexInfoService.h" #include "dbService/SchemeInfoService.h" #include "dbService/MindWeightService.h" #include "dbService/EffectResultService.h" #include "algorithm/GreyClusterEvaluation.h" #include "ProjectManager.h" #include #include #include #include /** * example * QVector gcItems; gcItems << GreyClusteringItem { "火力", 0, 0, 9, 1, nullptr }; QSharedPointer sg = QSharedPointer(new GreyClusteringValue); sg->units = "m"; sg->weiget = 2; sg->greyRanges << GreyRange { "较差类", true, 85, true, 100 }; sg->greyRanges << GreyRange { "一般类", true, 100, true, 115 }; sg->greyRanges << GreyRange { "较好类", true, 115, true, 125 }; sg->leftExtension = 70; sg->rightExtension = 140; sg->oldValue = 0; sg->newValue = 0; gcItems << GreyClusteringItem { "火炮口径", 0, 1, 1, 2, sg }; gcItems << GreyClusteringItem { "初速", 1, 1, 3, 1, nullptr }; sg = QSharedPointer(new GreyClusteringValue); sg->units = "m"; sg->weiget = 4; sg->greyRanges << GreyRange { "较差类", true, 1600, true, 1300 }; sg->greyRanges << GreyRange { "一般类", true, 1600, true, 1900 }; sg->greyRanges << GreyRange { "较好类", true, 1600, true, 1900 }; sg->leftExtension = 500; sg->rightExtension = 220; sg->oldValue = 0; sg->newValue = 0; gcItems << GreyClusteringItem { "穿甲弹", 1, 2, 1, 1, sg }; sg = QSharedPointer(new GreyClusteringValue); sg->units = "m"; sg->weiget = 4; sg->greyRanges << GreyRange { "较差类", true, 1000, true, 1200 }; sg->greyRanges << GreyRange { "一般类", true, 1200, true, 1400 }; sg->greyRanges << GreyRange { "较好类", true, 1200, true, 1400 }; sg->leftExtension = 600; sg->rightExtension = 1700; sg->oldValue = 0; sg->newValue = 0; gcItems << GreyClusteringItem { "破甲弹", 2, 2, 1, 1, sg }; sg = QSharedPointer(new GreyClusteringValue); sg->units = "m"; sg->weiget = 4; sg->greyRanges << GreyRange { "较差类", true, 500, false, 650 }; sg->greyRanges << GreyRange { "一般类", true, 650, false, 800 }; sg->greyRanges << GreyRange { "较好类", true, 800, false, 1000 }; sg->leftExtension = 400; sg->rightExtension = 1100; sg->oldValue = 0; sg->newValue = 0; gcItems << GreyClusteringItem { "榴弹", 3, 2, 1, 1, sg }; sg = QSharedPointer(new GreyClusteringValue); sg->units = ""; sg->weiget = 5; sg->greyRanges << GreyRange { "较差类", true, 0.5, false, 0.65 }; sg->greyRanges << GreyRange { "一般类", true, 0.65, false, 0.75 }; sg->greyRanges << GreyRange { "较好类", true, 0.75, false, 0.9 }; sg->leftExtension = 0.45; sg->rightExtension = 0.95; sg->oldValue = 0; sg->newValue = 0; gcItems << GreyClusteringItem { "首发命中", 4, 1, 1, 2, sg }; sg = QSharedPointer(new GreyClusteringValue); sg->units = "m"; sg->weiget = 5; sg->greyRanges << GreyRange { "较差类", true, 800, false, 1200 }; sg->greyRanges << GreyRange { "一般类", true, 1200, false, 1600 }; sg->greyRanges << GreyRange { "较好类", true, 1600, false, 2200 }; sg->leftExtension = 500; sg->rightExtension = 2500; sg->oldValue = 0; sg->newValue = 0; gcItems << GreyClusteringItem { "直射距离", 5, 1, 1, 2, sg }; sg = QSharedPointer(new GreyClusteringValue); sg->units = "发"; sg->weiget = 3; sg->greyRanges << GreyRange { "较差类", true, 30, false, 40 }; sg->greyRanges << GreyRange { "一般类", true, 40, false, 50 }; sg->greyRanges << GreyRange { "较好类", true, 50, false, 65 }; sg->leftExtension = 28; sg->rightExtension = 70; sg->oldValue = 0; sg->newValue = 0; gcItems << GreyClusteringItem { "弹药基数", 6, 1, 1, 2, sg }; gcItems << GreyClusteringItem { "时间", 7, 1, 2, 1, nullptr }; sg = QSharedPointer(new GreyClusteringValue); sg->units = "s"; sg->weiget = 3; sg->greyRanges << GreyRange { "较差类", true, 11, false, 10 }; sg->greyRanges << GreyRange { "一般类", true, 10, false, 7 }; sg->greyRanges << GreyRange { "较好类", true, 7, false, 4 }; sg->leftExtension = 12; sg->rightExtension = 3; sg->oldValue = 0; sg->newValue = 0; gcItems << GreyClusteringItem { "静对静", 7, 2, 1, 1, sg }; sg = QSharedPointer(new GreyClusteringValue); sg->units = "s"; sg->weiget = 3; sg->greyRanges << GreyRange { "较差类", true, 14, false, 12 }; sg->greyRanges << GreyRange { "一般类", true, 12, false, 10 }; sg->greyRanges << GreyRange { "较好类", true, 10, false, 7 }; sg->leftExtension = 15; sg->rightExtension = 5; sg->oldValue = 0; sg->newValue = 0; gcItems << GreyClusteringItem { "静对动", 8, 2, 1, 1, sg }; GreyClusteringSampleTable gcst(gcItems, 3, 9); gcst.resize(1200, 800); gcst.refreshTableView(); gcst.show(); */ GreyClusteringSampleTable::GreyClusteringSampleTable(CMind *mind, int grayNumber, QWidget *parent) : QTableView(parent), m_mind(mind), m_nodeDepth(2), m_grayNumber(grayNumber) { m_model = new QStandardItemModel(); connect(m_model, &QStandardItemModel::itemChanged, this, &GreyClusteringSampleTable::itemChanged); this->setModel(m_model); init(); refreshData(); } void GreyClusteringSampleTable::refreshData() { loadData(); loadSchemeData(); initClusteringItems(); refreshTableView(); } void GreyClusteringSampleTable::refreshTableView() { m_isFillingData = true; m_model->clear(); if (m_greyClusterings.size() == 0) { m_isFillingData = false; return; } QStringList greyNames; // 灰数 for (auto &item : m_greyClusterings) { if (!item.value.isNull()) { for (const auto &s : item.value->greyRanges) { greyNames << s.name; } break; } } int colCount = m_nodeDepth + 6 + greyNames.size(); // 设置表头 { // if (m_tableHeaderInitialized == false) { // m_tableHeaderInitialized = true; MultiLevelHeaderView *hHeader = dynamic_cast(horizontalHeader()); if (hHeader == nullptr) { hHeader = new MultiLevelHeaderView(Qt::Horizontal, 2, colCount, this); hHeader->setSectionResizeMode(QHeaderView::Stretch); this->setHorizontalHeader(hHeader); hHeader->setCellSpan(0, 0, 2, m_nodeDepth); // 指标占位 for (int n = 0; n < 2 + greyNames.size(); ++n) { // 单位+权重+灰度级占位 hHeader->setCellSpan(0, m_nodeDepth + n, 2, 1); } hHeader->setCellSpan(0, m_nodeDepth + 2 + greyNames.size(), 1, 2); // 延拓值占位 hHeader->setCellSpan(1, m_nodeDepth + 2 + greyNames.size(), 1, 1); hHeader->setCellSpan(1, m_nodeDepth + 2 + greyNames.size() + 1, 1, 1); hHeader->setCellSpan(0, m_nodeDepth + 4 + greyNames.size(), 1, 2); // 实现值占位 hHeader->setCellSpan(1, m_nodeDepth + 4 + greyNames.size(), 1, 1); hHeader->setCellSpan(1, m_nodeDepth + 4 + greyNames.size() + 1, 1, 1); } // 一级 hHeader->setCellText(0, 0, QString("指标")); hHeader->setCellText(0, m_nodeDepth, QString("单位")); hHeader->setCellText(0, m_nodeDepth + 1, QString("权重")); for (int i = 0; i < greyNames.size(); ++i) { hHeader->setCellText(0, m_nodeDepth + 2 + i, greyNames.at(i)); } hHeader->setCellText(0, m_nodeDepth + 2 + greyNames.size(), QString("延拓值")); hHeader->setCellText(0, m_nodeDepth + 4 + greyNames.size(), QString("实现值")); // 二级 hHeader->setCellText(1, m_nodeDepth + 2 + greyNames.size(), "左"); hHeader->setCellText(1, m_nodeDepth + 3 + greyNames.size(), "右"); hHeader->setCellText(1, m_nodeDepth + 4 + greyNames.size(), "建设前"); hHeader->setCellText(1, m_nodeDepth + 5 + greyNames.size(), "建设后"); // } } m_model->setColumnCount(colCount); m_model->setRowCount(m_rowCount); for (const auto &item : m_greyClusterings) { // 第一步,设置指标名 auto s = new QStandardItem(item.indexName); s->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); s->setTextAlignment(Qt::AlignCenter); s->setToolTip(item.indexName); m_model->setItem(item.row, item.col, s); if (item.rowSpan > 1 || item.colSpan > 1) { this->setSpan(item.row, item.col, item.rowSpan, item.colSpan); } // 第二步,查看当前指标下是否附带值 if (!item.value.isNull()) { int offset = item.colSpan; m_model->setItem(item.row, item.col + offset, new QStandardItem(item.value->units)); // 单位 ++offset; m_model->setItem(item.row, item.col + offset, new QStandardItem(QString::number(item.value->weiget))); // 权重 ++offset; for (auto &range : item.value->greyRanges) { // 灰度级 QString r; r += range.leftClose ? "[" : "("; r += QString("%1, %2").arg(range.leftValue).arg(range.rightValue); r += range.rightClose ? "]" : ")"; m_model->setItem(item.row, item.col + offset, new QStandardItem(r)); ++offset; } m_model->setItem(item.row, item.col + offset, new QStandardItem(QString::number(item.value->leftExtension))); // 延拓值左 ++offset; m_model->setItem(item.row, item.col + offset, new QStandardItem(QString::number(item.value->rightExtension))); // 延拓值右 ++offset; QStandardItem *oldValue = new QStandardItem; if (m_schemeData.keys().contains("建设前")) { oldValue->setText(m_schemeData["建设前"][item.indexName]); } m_model->setItem(item.row, item.col + offset, oldValue); // 实现值前 ++offset; QStandardItem *newValue = new QStandardItem; if (m_schemeData.keys().contains("建设后")) { newValue->setText(m_schemeData["建设后"][item.indexName]); } m_model->setItem(item.row, item.col + offset, newValue); // 实现值后 ++offset; for (int c = item.colSpan; c < offset - 2; ++c) { m_model->item(item.row, item.col + c)->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); m_model->item(item.row, item.col + c)->setTextAlignment(Qt::AlignCenter); } for (int c = offset - 2; c < offset; ++c) { m_model->item(item.row, item.col + c)->setTextAlignment(Qt::AlignCenter); this->setItemDelegateForColumn(item.col + c, new GreyClusteringItemSpinDelegate(this)); } } } m_isFillingData = false; } void GreyClusteringSampleTable::itemChanged(QStandardItem *item) { if (m_isFillingData) { return; } if (horizontalHeader()->model()->rowCount() < 2 || horizontalHeader()->model()->columnCount() <= item->column()) { return; } QModelIndex hIndex = horizontalHeader()->model()->index(1, item->column()); QString hTitle = horizontalHeader()->model()->data(hIndex).toString(); QStringList valueStrList; for (int r = 0; r < m_model->rowCount(); ++r) { QString vTitle = m_model->item(r, 1)->text(); QString value = m_model->item(r, item->column())->text(); QString valueStr = vTitle + ":" + value; valueStrList.append(valueStr); } QString v = valueStrList.join(";"); SchemaEval scheme; scheme.engineerId = m_mind->root().projectId; scheme.name = hTitle; scheme.valueStr = v; scheme.type = 2; bool ret = SchemeInfoService().addUniqueGCEData(scheme); qDebug() << __FUNCTION__ << __LINE__ << ret << endl; } void GreyClusteringSampleTable::compute() { GCEMat mat; GCERangeMat ranges; QVector samples; int colCount = m_nodeDepth + 4 + m_grayNumber; for (int r = 0; r < m_rowCount; ++r) { samples << GCEmat { m_model->item(r, colCount)->text().toDouble(), m_model->item(r, colCount + 1)->text().toDouble() }; } mat = samples; // 指标 for (const auto &item : m_greyClusterings) { if (!item.value.isNull()) { QVector rg; QSet fullSet; fullSet << item.value->leftExtension; for (const auto &grange : item.value->greyRanges) { fullSet << grange.leftValue << grange.rightValue; } fullSet << item.value->rightExtension; QList full = fullSet.toList(); std::sort(full.begin(), full.end()); for (int i = 0; i < item.value->greyRanges.size(); ++i) { double left; double right; int lloc = full.indexOf(item.value->greyRanges.at(i).leftValue); int rloc = full.indexOf(item.value->greyRanges.at(i).rightValue); if (lloc == 0) { left = full[0]; } else { left = full[lloc - 1]; } if (rloc == full.size() - 1) { right = full.last(); } else { right = full[rloc + 1]; } rg << GCERange { i, left, item.value->greyRanges.at(i).leftValue, item.value->greyRanges.at(i).rightValue, right }; } ranges << rg; } } QScopedPointer gc(new GreyClusterEvaluation(mat, ranges)); MindWeightInfo info; bool ret = MindWeightService().queryWeightData(&info, m_mind->root().projectId, ProjectManager::EfficiencyIndex); if (ret == false) { return; } if (info.id < 0) { qDebug() << __FUNCTION__ << __LINE__ << "未找到指标权重数据" << endl; return; } QMap weightData; QStringList weightList = info.weight.split(";"); for (QString keyValueStr : weightList) { QStringList keyValue = keyValueStr.split(":"); if (keyValue.size() == 2) { weightData[keyValue.first()] = keyValue.last().toDouble(); } } QVector weights; QList indexList = m_mind->leaves(); for (int i = 0; i < indexList.size(); ++i) { weights.append(weightData[indexList[i].name]); } gc->evaluate(weights); gc->getBestIndex(); QVector rangeWeights = gc->getRangeWeights(); QVector rangeCvt = gc->getRangeCVT(); QList resultData; QList schemeIdList = { -2, -1 }; QList schemeNameList = { "建设前", "建设后" }; for (int scheme = 0; scheme < 2; ++scheme) { EffectResult overall; overall.projectId = m_mind->root().projectId; overall.schemeId = schemeIdList[scheme]; overall.schemeName = schemeNameList[scheme]; overall.algType = 1; overall.indexName = "综合"; QStringList strList; for (int v = 0; v < rangeWeights.size(); ++v) { if (scheme == 0) { strList.append(QString("%1").arg(rangeWeights[v].front_val)); } else { strList.append(QString("%1").arg(rangeWeights[v].back_val)); } } overall.value = strList.join(","); resultData.append(overall); for (int index = 0; index < indexList.size(); ++index) { EffectResult result; result.projectId = indexList[index].projectId; result.schemeId = schemeIdList[scheme]; result.schemeName = schemeNameList[scheme]; result.algType = 1; result.indexName = indexList[index].name; QStringList strList; for (int v = 0; v < rangeWeights.size(); ++v) { if (scheme == 0) { strList.append(QString("%1").arg(rangeCvt[index][v].front_val)); } else { strList.append(QString("%1").arg(rangeCvt[index][v].back_val)); } } result.value = strList.join(","); resultData.append(result); } } bool saveRet = EffectResultService().addDataList(resultData); qDebug() << __FUNCTION__ << __LINE__ << saveRet << endl; } void GreyClusteringSampleTable::init() { setAlternatingRowColors(false); horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); horizontalHeader()->setStyleSheet("QHeaderView::section{background:rgb(244,244,244);color: black;}"); verticalHeader()->setStyleSheet("QHeaderView::section{background:rgb(244,244,244);color: black;}"); verticalHeader()->setDefaultAlignment(Qt::AlignCenter); setSelectionMode(QAbstractItemView::SingleSelection); } void GreyClusteringSampleTable::loadData() { QList gradeInfoList; QMap grayLevelMaps; int projectId = m_mind->root().projectId; if (!GradeInfoService().QueryGradeByProjectIdAndType(&gradeInfoList, projectId, 1)) { QMessageBox::warning(this, "警告", "数据库访问失败"); } else { if (gradeInfoList.size() == 0) { for (int lvl = 0; lvl < m_grayNumber; ++lvl) { grayLevelMaps.insert(QString("级别 %1:").arg(lvl + 1), QString("E%1").arg(lvl + 1)); GradeInfo ginfo; ginfo.projectId = projectId; ginfo.gradeName = QString("级别 %1").arg(lvl + 1); ginfo.gradeValue = QString("灰类%1级").arg(lvl + 1); ginfo.type = 1; if (!GradeInfoService().AddGradeInfo(ginfo)) { QMessageBox::warning(this, "警告", "数据库访问失败"); } } } else { for (const auto &gi : gradeInfoList) { grayLevelMaps.insert(gi->gradeName, gi->gradeValue); if (grayLevelMaps.size() >= m_grayNumber) { break; } } // 缺少再补 for (int lvl = grayLevelMaps.size(); lvl < m_grayNumber; ++lvl) { grayLevelMaps.insert(QString("级别 %1:").arg(lvl + 1), QString("E%1").arg(lvl + 1)); GradeInfo ginfo; ginfo.projectId = projectId; ginfo.gradeName = QString("级别 %1").arg(lvl + 1); ginfo.gradeValue = QString("灰类%1级").arg(lvl + 1); ginfo.type = 1; if (!GradeInfoService().AddGradeInfo(ginfo)) { QMessageBox::warning(this, "警告", "数据库访问失败"); } } m_grayNames = grayLevelMaps.values(); } } qDeleteAll(gradeInfoList); } void GreyClusteringSampleTable::loadSchemeData() { m_schemeData.clear(); QList schemeList; bool ret = SchemeInfoService().QuerySchemeInfoByEngineerId(&schemeList, m_mind->root().projectId, 2); if (ret == false) { return; } for (SchemaEval *scheme : schemeList) { if (m_schemeData.keys().contains(scheme->name) == false) { m_schemeData[scheme->name] = QMap(); } QStringList valueStrList = scheme->valueStr.split(";"); for (QString valueStr : valueStrList) { QStringList keyValue = valueStr.split(":"); if (keyValue.size() == 2) { m_schemeData[scheme->name][keyValue.first()] = keyValue.last(); } } } } void GreyClusteringSampleTable::initClusteringItems() { // 脑图层级 < 2 时无效 if (m_mind->levels() < 2) { return; } m_greyClusterings.clear(); // 使用倒数第二层节点及其子节点 int row = 0; for (CNodeData n : m_mind->nodesInLevel(m_mind->levels() - 1)) { GreyClusteringItem parentItem = { n.name, row, 0, 1, 1, nullptr }; QList subNodes = m_mind->subNodes(n); parentItem.colSpan = subNodes.size() == 0 ? 2 : 1; // 没有子节点,占两列,否则占一列 parentItem.rowSpan = subNodes.size() == 0 ? 1 : subNodes.size(); // 没有子节点,占一行,否则占子节点数目行 if (subNodes.size() == 0) { // 没有子节点,需要录入值 GreyClusteringValue *sg = new GreyClusteringValue; sg->units = n.dimension; sg->weiget = 0; for (const auto &gname : m_grayNames) { sg->greyRanges << GreyRange { gname, true, 0, true, 0 }; } sg->leftExtension = 0; sg->rightExtension = 0; sg->oldValue = 0; sg->newValue = 0; parentItem.value.reset(sg); } m_greyClusterings.append(parentItem); int subRow = row; // 子节点 for (const CNodeData &sub : subNodes) { // 因为已有父节点,所以在第2列 GreyClusteringItem childItem = { sub.name, subRow, 1, 1, 1, nullptr }; GreyClusteringValue *sg = new GreyClusteringValue; sg->units = sub.dimension; sg->weiget = 0; for (const auto &gname : m_grayNames) { sg->greyRanges << GreyRange { gname, true, 0, true, 0 }; } sg->leftExtension = 0; sg->rightExtension = 0; sg->oldValue = 0; sg->newValue = 0; childItem.value.reset(sg); m_greyClusterings.append(childItem); subRow++; } row += parentItem.rowSpan; } m_rowCount = row; // 更新 QList effectIndexInfoList; int projectid = m_mind->root().projectId; if (!EffectIndexInfoService().QueryEffectIndexInfoByProjectId(&effectIndexInfoList, projectid)) { QMessageBox::warning(this, "警告", "数据库访问失败"); return; } if (effectIndexInfoList.size() > 0) { for (auto &item : m_greyClusterings) { if (item.value.isNull()) { continue; } for (const auto &effInfo : effectIndexInfoList) { if (effInfo->effectIndexName == item.indexName) { if (effInfo->effectIndexUnit.length() > 0) { // item.value->units = effInfo->effectIndexUnit; } item.value->leftExtension = effInfo->extendLeft.toDouble(); item.value->rightExtension = effInfo->extendRight.toDouble(); //[0:0],[0:0],[0:0] QStringList valueList; if (effInfo->effectIndexValue.length() > 0) { valueList = effInfo->effectIndexValue.split(","); } int align = qMin(valueList.size(), item.value->greyRanges.size()); for (int str = 0; str < align; str++) { //[0:0] QStringList lr = valueList.at(str).mid(1, valueList.at(str).size() - 2).split(":"); item.value->greyRanges[str].leftValue = lr.at(0).toDouble(); item.value->greyRanges[str].leftClose = valueList.at(str)[0] == "["; item.value->greyRanges[str].rightValue = lr.at(1).toDouble(); item.value->greyRanges[str].rightClose = valueList.at(str).right(1) == "]"; } } } } } qDeleteAll(effectIndexInfoList); }