GreyClusteringSampleTable.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  1. #include "GreyClusteringItemDelegate.h"
  2. #include "GreyClusteringSampleTable.h"
  3. #include "MultiLevelHeaderView.h"
  4. #include "CMind.h"
  5. #include "dbService/GradeInfoService.h"
  6. #include "dbService/EffectIndexInfoService.h"
  7. #include "algorithm/GreyClusterEvaluation.h"
  8. #include "ProjectManager.h"
  9. #include <QHeaderView>
  10. #include <QDebug>
  11. #include <QMessageBox>
  12. #include <QtMath>
  13. /**
  14. * example
  15. * QVector<GreyClusteringItem> gcItems;
  16. gcItems << GreyClusteringItem { "火力", 0, 0, 9, 1, nullptr };
  17. QSharedPointer<GreyClusteringValue> sg = QSharedPointer<GreyClusteringValue>(new GreyClusteringValue);
  18. sg->units = "m";
  19. sg->weiget = 2;
  20. sg->greyRanges << GreyRange { "较差类", true, 85, true, 100 };
  21. sg->greyRanges << GreyRange { "一般类", true, 100, true, 115 };
  22. sg->greyRanges << GreyRange { "较好类", true, 115, true, 125 };
  23. sg->leftExtension = 70;
  24. sg->rightExtension = 140;
  25. sg->oldValue = 0;
  26. sg->newValue = 0;
  27. gcItems << GreyClusteringItem { "火炮口径", 0, 1, 1, 2, sg };
  28. gcItems << GreyClusteringItem { "初速", 1, 1, 3, 1, nullptr };
  29. sg = QSharedPointer<GreyClusteringValue>(new GreyClusteringValue);
  30. sg->units = "m";
  31. sg->weiget = 4;
  32. sg->greyRanges << GreyRange { "较差类", true, 1600, true, 1300 };
  33. sg->greyRanges << GreyRange { "一般类", true, 1600, true, 1900 };
  34. sg->greyRanges << GreyRange { "较好类", true, 1600, true, 1900 };
  35. sg->leftExtension = 500;
  36. sg->rightExtension = 220;
  37. sg->oldValue = 0;
  38. sg->newValue = 0;
  39. gcItems << GreyClusteringItem { "穿甲弹", 1, 2, 1, 1, sg };
  40. sg = QSharedPointer<GreyClusteringValue>(new GreyClusteringValue);
  41. sg->units = "m";
  42. sg->weiget = 4;
  43. sg->greyRanges << GreyRange { "较差类", true, 1000, true, 1200 };
  44. sg->greyRanges << GreyRange { "一般类", true, 1200, true, 1400 };
  45. sg->greyRanges << GreyRange { "较好类", true, 1200, true, 1400 };
  46. sg->leftExtension = 600;
  47. sg->rightExtension = 1700;
  48. sg->oldValue = 0;
  49. sg->newValue = 0;
  50. gcItems << GreyClusteringItem { "破甲弹", 2, 2, 1, 1, sg };
  51. sg = QSharedPointer<GreyClusteringValue>(new GreyClusteringValue);
  52. sg->units = "m";
  53. sg->weiget = 4;
  54. sg->greyRanges << GreyRange { "较差类", true, 500, false, 650 };
  55. sg->greyRanges << GreyRange { "一般类", true, 650, false, 800 };
  56. sg->greyRanges << GreyRange { "较好类", true, 800, false, 1000 };
  57. sg->leftExtension = 400;
  58. sg->rightExtension = 1100;
  59. sg->oldValue = 0;
  60. sg->newValue = 0;
  61. gcItems << GreyClusteringItem { "榴弹", 3, 2, 1, 1, sg };
  62. sg = QSharedPointer<GreyClusteringValue>(new GreyClusteringValue);
  63. sg->units = "";
  64. sg->weiget = 5;
  65. sg->greyRanges << GreyRange { "较差类", true, 0.5, false, 0.65 };
  66. sg->greyRanges << GreyRange { "一般类", true, 0.65, false, 0.75 };
  67. sg->greyRanges << GreyRange { "较好类", true, 0.75, false, 0.9 };
  68. sg->leftExtension = 0.45;
  69. sg->rightExtension = 0.95;
  70. sg->oldValue = 0;
  71. sg->newValue = 0;
  72. gcItems << GreyClusteringItem { "首发命中", 4, 1, 1, 2, sg };
  73. sg = QSharedPointer<GreyClusteringValue>(new GreyClusteringValue);
  74. sg->units = "m";
  75. sg->weiget = 5;
  76. sg->greyRanges << GreyRange { "较差类", true, 800, false, 1200 };
  77. sg->greyRanges << GreyRange { "一般类", true, 1200, false, 1600 };
  78. sg->greyRanges << GreyRange { "较好类", true, 1600, false, 2200 };
  79. sg->leftExtension = 500;
  80. sg->rightExtension = 2500;
  81. sg->oldValue = 0;
  82. sg->newValue = 0;
  83. gcItems << GreyClusteringItem { "直射距离", 5, 1, 1, 2, sg };
  84. sg = QSharedPointer<GreyClusteringValue>(new GreyClusteringValue);
  85. sg->units = "发";
  86. sg->weiget = 3;
  87. sg->greyRanges << GreyRange { "较差类", true, 30, false, 40 };
  88. sg->greyRanges << GreyRange { "一般类", true, 40, false, 50 };
  89. sg->greyRanges << GreyRange { "较好类", true, 50, false, 65 };
  90. sg->leftExtension = 28;
  91. sg->rightExtension = 70;
  92. sg->oldValue = 0;
  93. sg->newValue = 0;
  94. gcItems << GreyClusteringItem { "弹药基数", 6, 1, 1, 2, sg };
  95. gcItems << GreyClusteringItem { "时间", 7, 1, 2, 1, nullptr };
  96. sg = QSharedPointer<GreyClusteringValue>(new GreyClusteringValue);
  97. sg->units = "s";
  98. sg->weiget = 3;
  99. sg->greyRanges << GreyRange { "较差类", true, 11, false, 10 };
  100. sg->greyRanges << GreyRange { "一般类", true, 10, false, 7 };
  101. sg->greyRanges << GreyRange { "较好类", true, 7, false, 4 };
  102. sg->leftExtension = 12;
  103. sg->rightExtension = 3;
  104. sg->oldValue = 0;
  105. sg->newValue = 0;
  106. gcItems << GreyClusteringItem { "静对静", 7, 2, 1, 1, sg };
  107. sg = QSharedPointer<GreyClusteringValue>(new GreyClusteringValue);
  108. sg->units = "s";
  109. sg->weiget = 3;
  110. sg->greyRanges << GreyRange { "较差类", true, 14, false, 12 };
  111. sg->greyRanges << GreyRange { "一般类", true, 12, false, 10 };
  112. sg->greyRanges << GreyRange { "较好类", true, 10, false, 7 };
  113. sg->leftExtension = 15;
  114. sg->rightExtension = 5;
  115. sg->oldValue = 0;
  116. sg->newValue = 0;
  117. gcItems << GreyClusteringItem { "静对动", 8, 2, 1, 1, sg };
  118. GreyClusteringSampleTable gcst(gcItems, 3, 9);
  119. gcst.resize(1200, 800);
  120. gcst.refreshTableView();
  121. gcst.show();
  122. */
  123. GreyClusteringSampleTable::GreyClusteringSampleTable(CMind *mind, int grayNumber, QWidget *parent)
  124. : QTableView(parent), m_mind(mind), m_nodeDepth(2), m_grayNumber(grayNumber)
  125. {
  126. m_model = new QStandardItemModel();
  127. this->setModel(m_model);
  128. init();
  129. initClusteringItems();
  130. refreshTableView();
  131. }
  132. void GreyClusteringSampleTable::refreshTableView()
  133. {
  134. m_model->clear();
  135. if (m_greyClusterings.size() == 0) {
  136. return;
  137. }
  138. QStringList greyNames; // 灰数
  139. for (auto &item : m_greyClusterings) {
  140. if (!item.value.isNull()) {
  141. for (const auto &s : item.value->greyRanges) {
  142. greyNames << s.name;
  143. }
  144. break;
  145. }
  146. }
  147. int colCount = m_nodeDepth + 6 + greyNames.size();
  148. // 设置表头
  149. {
  150. auto hHeader = new MultiLevelHeaderView(Qt::Horizontal, 2, colCount, this);
  151. hHeader->setSectionResizeMode(QHeaderView::Stretch);
  152. hHeader->setCellSpan(0, 0, 2, m_nodeDepth); // 指标占位
  153. for (int n = 0; n < 2 + greyNames.size(); ++n) { // 单位+权重+灰度级占位
  154. hHeader->setCellSpan(0, m_nodeDepth + n, 2, 1);
  155. }
  156. hHeader->setCellSpan(0, m_nodeDepth + 2 + greyNames.size(), 1, 2); // 延拓值占位
  157. hHeader->setCellSpan(1, m_nodeDepth + 2 + greyNames.size(), 1, 1);
  158. hHeader->setCellSpan(1, m_nodeDepth + 2 + greyNames.size() + 1, 1, 1);
  159. hHeader->setCellSpan(0, m_nodeDepth + 4 + greyNames.size(), 1, 2); // 实现值占位
  160. hHeader->setCellSpan(1, m_nodeDepth + 4 + greyNames.size(), 1, 1);
  161. hHeader->setCellSpan(1, m_nodeDepth + 4 + greyNames.size() + 1, 1, 1);
  162. // 一级
  163. hHeader->setCellText(0, 0, QString("指标"));
  164. hHeader->setCellText(0, m_nodeDepth, QString("单位"));
  165. hHeader->setCellText(0, m_nodeDepth + 1, QString("权重"));
  166. for (int i = 0; i < greyNames.size(); ++i) {
  167. hHeader->setCellText(0, m_nodeDepth + 2 + i, greyNames.at(i));
  168. }
  169. hHeader->setCellText(0, m_nodeDepth + 2 + greyNames.size(), QString("延拓值"));
  170. hHeader->setCellText(0, m_nodeDepth + 4 + greyNames.size(), QString("实现值"));
  171. // 二级
  172. hHeader->setCellText(1, m_nodeDepth + 2 + greyNames.size(), "左");
  173. hHeader->setCellText(1, m_nodeDepth + 3 + greyNames.size(), "右");
  174. hHeader->setCellText(1, m_nodeDepth + 4 + greyNames.size(), "建设前");
  175. hHeader->setCellText(1, m_nodeDepth + 5 + greyNames.size(), "建设后");
  176. this->setHorizontalHeader(hHeader);
  177. }
  178. m_model->setColumnCount(colCount);
  179. m_model->setRowCount(m_rowCount);
  180. for (const auto &item : m_greyClusterings) {
  181. // 第一步,设置指标名
  182. auto s = new QStandardItem(item.indexName);
  183. s->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
  184. s->setTextAlignment(Qt::AlignCenter);
  185. s->setToolTip(item.indexName);
  186. m_model->setItem(item.row, item.col, s);
  187. if (item.rowSpan > 1 || item.colSpan > 1) {
  188. this->setSpan(item.row, item.col, item.rowSpan, item.colSpan);
  189. }
  190. // 第二步,查看当前指标下是否附带值
  191. if (!item.value.isNull()) {
  192. int offset = item.colSpan;
  193. m_model->setItem(item.row, item.col + offset, new QStandardItem(item.value->units)); // 单位
  194. ++offset;
  195. m_model->setItem(item.row, item.col + offset,
  196. new QStandardItem(QString::number(item.value->weiget))); // 权重
  197. ++offset;
  198. for (auto &range : item.value->greyRanges) { // 灰度级
  199. QString r;
  200. r += range.leftClose ? "[" : "(";
  201. r += QString("%1, %2").arg(range.leftValue).arg(range.rightValue);
  202. r += range.rightClose ? "]" : ")";
  203. m_model->setItem(item.row, item.col + offset, new QStandardItem(r));
  204. ++offset;
  205. }
  206. m_model->setItem(item.row, item.col + offset,
  207. new QStandardItem(QString::number(item.value->leftExtension))); // 延拓值左
  208. ++offset;
  209. m_model->setItem(item.row, item.col + offset,
  210. new QStandardItem(QString::number(item.value->rightExtension))); // 延拓值右
  211. ++offset;
  212. m_model->setItem(item.row, item.col + offset,
  213. new QStandardItem(QString::number(item.value->oldValue))); // 实现值前
  214. ++offset;
  215. m_model->setItem(item.row, item.col + offset,
  216. new QStandardItem(QString::number(item.value->newValue))); // 实现值后
  217. ++offset;
  218. for (int c = item.colSpan; c < offset - 2; ++c) {
  219. m_model->item(item.row, item.col + c)->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
  220. m_model->item(item.row, item.col + c)->setTextAlignment(Qt::AlignCenter);
  221. }
  222. for (int c = offset - 2; c < offset; ++c) {
  223. m_model->item(item.row, item.col + c)->setTextAlignment(Qt::AlignCenter);
  224. this->setItemDelegateForColumn(item.col + c, new GreyClusteringItemSpinDelegate(this));
  225. }
  226. }
  227. }
  228. }
  229. void GreyClusteringSampleTable::compute()
  230. {
  231. GCEMat mat;
  232. GCERangeMat ranges;
  233. QVector<GCEmat> samples;
  234. int colCount = m_nodeDepth + 4 + m_grayNumber;
  235. for (int r = 0; r < m_rowCount; ++r) {
  236. samples << GCEmat { m_model->item(r, colCount)->text().toDouble(),
  237. m_model->item(r, colCount + 1)->text().toDouble() };
  238. }
  239. mat = samples;
  240. // 指标
  241. for (const auto &item : m_greyClusterings) {
  242. if (!item.value.isNull()) {
  243. QVector<GCERange> rg;
  244. QSet<double> fullSet;
  245. fullSet << item.value->leftExtension;
  246. for (const auto &grange : item.value->greyRanges) {
  247. fullSet << grange.leftValue << grange.rightValue;
  248. }
  249. fullSet << item.value->rightExtension;
  250. QList<double> full = fullSet.toList();
  251. std::sort(full.begin(), full.end());
  252. for (int i = 0; i < item.value->greyRanges.size(); ++i) {
  253. double left;
  254. double right;
  255. int lloc = full.indexOf(item.value->greyRanges.at(i).leftValue);
  256. int rloc = full.indexOf(item.value->greyRanges.at(i).rightValue);
  257. if (lloc == 0) {
  258. left = full[0];
  259. } else {
  260. left = full[lloc - 1];
  261. }
  262. if (rloc == full.size() - 1) {
  263. right = full.last();
  264. } else {
  265. right = full[rloc + 1];
  266. }
  267. rg << GCERange { i, left, item.value->greyRanges.at(i).leftValue,
  268. item.value->greyRanges.at(i).rightValue, right };
  269. }
  270. ranges << rg;
  271. }
  272. }
  273. QScopedPointer<GreyClusterEvaluation> gc(new GreyClusterEvaluation(mat, ranges));
  274. gc->evaluate({ 0.2, 0.15, 0.05, 0.4, 0.2 });
  275. BestIndex index = gc->getBestIndex();
  276. qDebug() << index.front_index << index.back_index;
  277. }
  278. void GreyClusteringSampleTable::init()
  279. {
  280. setAlternatingRowColors(false);
  281. horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
  282. horizontalHeader()->setStyleSheet("QHeaderView::section{background:rgb(244,244,244);color: black;}");
  283. verticalHeader()->setStyleSheet("QHeaderView::section{background:rgb(244,244,244);color: black;}");
  284. verticalHeader()->setDefaultAlignment(Qt::AlignCenter);
  285. setSelectionMode(QAbstractItemView::SingleSelection);
  286. QList<GradeInfo *> gradeInfoList;
  287. QMap<QString, QString> grayLevelMaps;
  288. int projectId = m_mind->root().projectId;
  289. if (!GradeInfoService().QueryGradeByProjectIdAndType(&gradeInfoList, projectId, 1)) {
  290. QMessageBox::warning(this, "警告", "数据库访问失败");
  291. } else {
  292. if (gradeInfoList.size() == 0) {
  293. for (int lvl = 0; lvl < m_grayNumber; ++lvl) {
  294. grayLevelMaps.insert(QString("级别 %1:").arg(lvl + 1), QString("E%1").arg(lvl + 1));
  295. GradeInfo ginfo;
  296. ginfo.projectId = projectId;
  297. ginfo.gradeName = QString("级别 %1").arg(lvl + 1);
  298. ginfo.gradeValue = QString("灰类%1级").arg(lvl + 1);
  299. ginfo.type = 1;
  300. if (!GradeInfoService().AddGradeInfo(ginfo)) {
  301. QMessageBox::warning(this, "警告", "数据库访问失败");
  302. }
  303. }
  304. } else {
  305. for (const auto &gi : gradeInfoList) {
  306. grayLevelMaps.insert(gi->gradeName, gi->gradeValue);
  307. if (grayLevelMaps.size() >= m_grayNumber) {
  308. break;
  309. }
  310. }
  311. // 缺少再补
  312. for (int lvl = grayLevelMaps.size(); lvl < m_grayNumber; ++lvl) {
  313. grayLevelMaps.insert(QString("级别 %1:").arg(lvl + 1), QString("E%1").arg(lvl + 1));
  314. GradeInfo ginfo;
  315. ginfo.projectId = projectId;
  316. ginfo.gradeName = QString("级别 %1").arg(lvl + 1);
  317. ginfo.gradeValue = QString("灰类%1级").arg(lvl + 1);
  318. ginfo.type = 1;
  319. if (!GradeInfoService().AddGradeInfo(ginfo)) {
  320. QMessageBox::warning(this, "警告", "数据库访问失败");
  321. }
  322. }
  323. m_grayNames = grayLevelMaps.values();
  324. }
  325. }
  326. qDeleteAll(gradeInfoList);
  327. }
  328. void GreyClusteringSampleTable::initClusteringItems()
  329. {
  330. // 脑图层级 < 2 时无效
  331. if (m_mind->levels() < 2) {
  332. return;
  333. }
  334. m_greyClusterings.clear();
  335. // 使用倒数第二层节点及其子节点
  336. int row = 0;
  337. for (CNodeData n : m_mind->nodesInLevel(m_mind->levels() - 1)) {
  338. GreyClusteringItem parentItem = { n.name, row, 0, 1, 1, nullptr };
  339. QList<CNodeData> subNodes = m_mind->subNodes(n);
  340. parentItem.colSpan = subNodes.size() == 0 ? 2 : 1; // 没有子节点,占两列,否则占一列
  341. parentItem.rowSpan = subNodes.size() == 0 ? 1 : subNodes.size(); // 没有子节点,占一行,否则占子节点数目行
  342. if (subNodes.size() == 0) { // 没有子节点,需要录入值
  343. GreyClusteringValue *sg = new GreyClusteringValue;
  344. sg->units = "";
  345. sg->weiget = 0;
  346. for (const auto &gname : m_grayNames) {
  347. sg->greyRanges << GreyRange { gname, true, 0, true, 0 };
  348. }
  349. sg->leftExtension = 0;
  350. sg->rightExtension = 0;
  351. sg->oldValue = 0;
  352. sg->newValue = 0;
  353. parentItem.value.reset(sg);
  354. }
  355. m_greyClusterings.append(parentItem);
  356. int subRow = row;
  357. // 子节点
  358. for (const CNodeData &sub : subNodes) {
  359. // 因为已有父节点,所以在第2列
  360. GreyClusteringItem childItem = { sub.name, subRow, 1, 1, 1, nullptr };
  361. GreyClusteringValue *sg = new GreyClusteringValue;
  362. sg->units = "";
  363. sg->weiget = 0;
  364. for (const auto &gname : m_grayNames) {
  365. sg->greyRanges << GreyRange { gname, true, 0, true, 0 };
  366. }
  367. sg->leftExtension = 0;
  368. sg->rightExtension = 0;
  369. sg->oldValue = 0;
  370. sg->newValue = 0;
  371. childItem.value.reset(sg);
  372. m_greyClusterings.append(childItem);
  373. subRow++;
  374. }
  375. row += parentItem.rowSpan;
  376. }
  377. m_rowCount = row;
  378. // 更新
  379. QList<EffectIndexInfo *> effectIndexInfoList;
  380. int projectid = m_mind->root().projectId;
  381. if (!EffectIndexInfoService().QueryEffectIndexInfoByProjectId(&effectIndexInfoList, projectid)) {
  382. QMessageBox::warning(this, "警告", "数据库访问失败");
  383. return;
  384. }
  385. if (effectIndexInfoList.size() > 0) {
  386. for (auto &item : m_greyClusterings) {
  387. if (item.value.isNull()) {
  388. continue;
  389. }
  390. for (const auto &effInfo : effectIndexInfoList) {
  391. if (effInfo->effectIndexName == item.indexName) {
  392. item.value->units = effInfo->effectIndexUnit;
  393. item.value->leftExtension = effInfo->extendLeft.toDouble();
  394. item.value->rightExtension = effInfo->extendRight.toDouble();
  395. //[0:0],[0:0],[0:0]
  396. QStringList valueList;
  397. if (effInfo->effectIndexValue.length() > 0) {
  398. valueList = effInfo->effectIndexValue.split(",");
  399. }
  400. int align = qMin(valueList.size(), item.value->greyRanges.size());
  401. for (int str = 0; str < align; str++) {
  402. //[0:0]
  403. QStringList lr = valueList.at(str).mid(1, valueList.at(str).size() - 2).split(":");
  404. item.value->greyRanges[str].leftValue = lr.at(0).toDouble();
  405. item.value->greyRanges[str].rightValue = lr.at(1).toDouble();
  406. }
  407. }
  408. }
  409. }
  410. }
  411. qDeleteAll(effectIndexInfoList);
  412. if (projectid == kDemoProjId1) {
  413. QVector<double> left = { 2, 35, 2, 90, 2.5, 35, 70, 2.5, 35, 30, 2.5, 70, 25, 2, 50, 1, 45, 8, 60, 1 };
  414. QVector<double> right = { 4, 20, 3, 40, 0.5, 55, 90, 1.2, 55, 70, 1.2, 90, 60, 6, 20, 3, 75, 25, 25, 3 };
  415. int sn = 0;
  416. for (auto &item : m_greyClusterings) {
  417. if (item.value.isNull()) {
  418. continue;
  419. }
  420. if (sn < left.size()) {
  421. item.value->oldValue = left.at(sn);
  422. item.value->newValue = right.at(sn);
  423. }
  424. sn++;
  425. }
  426. }
  427. }