fix(nmNum): 区分流量记录身份与计算可用性

- 主井工作多相数据仅覆盖唯一且身份有效的 Gauge 记录
- 防止重复 Gauge Code 被重新标记为可用
- 包含井保留合法全零流量记录的 Code 和流动段索引
- 无非零产量的分相仍归一为关闭且不显示在下拉框中
- 仅在原 Flow Code 无效时自动回退其他记录
- 按当前已启用的非零产量相判断井是否可参与计算
feature/nmNum-multi-gauge-record
lh 23 hours ago
parent 62867a6b13
commit fa459f6ba7

@ -52,12 +52,28 @@ struct WellDataRow {
{
}
/** @brief 至少选择一个产量相时,该井才可作为主动井提交。 */
/** @brief 当前记录至少有一个已启用的非零产量相时,才可作为主动井提交。 */
bool canCalculate() const {
return m_bCanCalculate && !m_sWellCode.isEmpty() &&
!m_sFlowGaugeCode.isEmpty() &&
(m_bUseOilRate || m_bUseGasRate || m_bUseWaterRate) &&
m_nFlowSegmentIndex > 0;
if(!m_bCanCalculate || m_sWellCode.isEmpty() ||
m_sFlowGaugeCode.isEmpty() || m_nFlowSegmentIndex < 1) {
return false;
}
const nmFlowGaugeRecord* pRecord = nullptr;
int nMatchCount = 0;
for(int nIndex = 0; nIndex < m_vecFlowRecords.size(); ++nIndex) {
if(m_vecFlowRecords[nIndex].sGaugeCode == m_sFlowGaugeCode) {
pRecord = &m_vecFlowRecords[nIndex];
++nMatchCount;
}
}
return nMatchCount == 1 && pRecord != nullptr &&
pRecord->eStatus == NM_GaugeRecord_Usable &&
((m_bUseOilRate &&
nmHasNonZeroFlowRate(pRecord->vecOilPoints)) ||
(m_bUseGasRate &&
nmHasNonZeroFlowRate(pRecord->vecGasPoints)) ||
(m_bUseWaterRate &&
nmHasNonZeroFlowRate(pRecord->vecWaterPoints)));
}
};

@ -309,6 +309,7 @@ static bool applyCurrentMultiPhaseFlowData(
return false;
}
nmFlowGaugeRecord* pMatchedRecord = nullptr;
for(int nRecordIndex = 0;
nRecordIndex < vecRecords.size();
++nRecordIndex) {
@ -316,30 +317,37 @@ static bool applyCurrentMultiPhaseFlowData(
if(oRecord.sGaugeCode != sFlowGaugeCode) {
continue;
}
oRecord.vecOilPoints.clear();
oRecord.vecGasPoints.clear();
oRecord.vecWaterPoints.clear();
oRecord.vecOilPoints.reserve(nPointCount);
oRecord.vecGasPoints.reserve(nPointCount);
oRecord.vecWaterPoints.reserve(nPointCount);
for(int nPointIndex = 0;
nPointIndex < nPointCount;
++nPointIndex) {
const double dTime = vvecMultiPhaseData[0][nPointIndex];
oRecord.vecOilPoints.append(QPointF(
dTime, vvecMultiPhaseData[1][nPointIndex]));
oRecord.vecGasPoints.append(QPointF(
dTime, vvecMultiPhaseData[2][nPointIndex]));
oRecord.vecWaterPoints.append(QPointF(
dTime, vvecMultiPhaseData[3][nPointIndex]));
}
oRecord.bMultiPhase = true;
oRecord.eStatus = NM_GaugeRecord_Usable;
oRecord.nIndexF = nIndexF;
return true;
if(pMatchedRecord != nullptr) {
return false;
}
pMatchedRecord = &oRecord;
}
return false;
if(pMatchedRecord == nullptr ||
pMatchedRecord->eStatus == NM_GaugeRecord_InvalidIdentity) {
return false;
}
pMatchedRecord->vecOilPoints.clear();
pMatchedRecord->vecGasPoints.clear();
pMatchedRecord->vecWaterPoints.clear();
pMatchedRecord->vecOilPoints.reserve(nPointCount);
pMatchedRecord->vecGasPoints.reserve(nPointCount);
pMatchedRecord->vecWaterPoints.reserve(nPointCount);
for(int nPointIndex = 0;
nPointIndex < nPointCount;
++nPointIndex) {
const double dTime = vvecMultiPhaseData[0][nPointIndex];
pMatchedRecord->vecOilPoints.append(QPointF(
dTime, vvecMultiPhaseData[1][nPointIndex]));
pMatchedRecord->vecGasPoints.append(QPointF(
dTime, vvecMultiPhaseData[2][nPointIndex]));
pMatchedRecord->vecWaterPoints.append(QPointF(
dTime, vvecMultiPhaseData[3][nPointIndex]));
}
pMatchedRecord->bMultiPhase = true;
pMatchedRecord->eStatus = NM_GaugeRecord_Usable;
pMatchedRecord->nIndexF = nIndexF;
return true;
}
// 单相流量记录:只解析主块,并按井别把数据归入油、气或水相;忽略可能残留的 Ex2/Ex3。

@ -80,6 +80,29 @@ const nmFlowGaugeRecord* findFlowRecord(
return nullptr;
}
// 保留配置只要求 Code 唯一且记录可解析,不要求记录中存在非零产量。
const nmFlowGaugeRecord* findUniqueUsableFlowRecord(
const QVector<nmFlowGaugeRecord>& vecRecords,
const QString& sGaugeCode)
{
if(sGaugeCode.isEmpty()) {
return nullptr;
}
const nmFlowGaugeRecord* pMatchedRecord = nullptr;
for(int nIndex = 0; nIndex < vecRecords.size(); ++nIndex) {
if(vecRecords[nIndex].sGaugeCode != sGaugeCode) {
continue;
}
if(pMatchedRecord != nullptr) {
return nullptr;
}
pMatchedRecord = &vecRecords[nIndex];
}
return pMatchedRecord != nullptr &&
pMatchedRecord->eStatus == NM_GaugeRecord_Usable
? pMatchedRecord : nullptr;
}
nmFlowGaugeRecord* findMutableFlowRecord(
QVector<nmFlowGaugeRecord>& vecRecords,
const QString& sGaugeCode)
@ -398,10 +421,13 @@ void nmWxIncludeOtherWells::setupTable()
const bool bHadRequestedPhase = oWellRow.m_bUseOilRate ||
oWellRow.m_bUseGasRate || oWellRow.m_bUseWaterRate;
const bool bHadValidFlowSelection = findUniqueUsableFlowRecord(
oWellRow.m_vecFlowRecords,
oWellRow.m_sFlowGaugeCode) != nullptr;
normalizeFlowSelection(oWellRow);
// 新井默认启用三相;若框架当前选择失效,回退到第一条有产量记录。
// 用户已明确把三相都设为“无”时不自动恢复。
if(!oWellRow.canCalculate() && bHadRequestedPhase) {
if(!bHadValidFlowSelection && bHadRequestedPhase) {
for(int nRecordIndex = 0;
nRecordIndex < oWellRow.m_vecFlowRecords.size();
++nRecordIndex) {
@ -574,9 +600,9 @@ void nmWxIncludeOtherWells::addWellDataToTable(
void nmWxIncludeOtherWells::normalizeFlowSelection(WellDataRow& data) const
{
const nmFlowGaugeRecord* pRecord = findFlowRecord(
const nmFlowGaugeRecord* pRecord = findUniqueUsableFlowRecord(
data.m_vecFlowRecords, data.m_sFlowGaugeCode);
if(pRecord == nullptr || !nmIsSelectableFlowRecord(*pRecord)) {
if(pRecord == nullptr) {
data.m_sFlowGaugeCode.clear();
data.m_bUseOilRate = false;
data.m_bUseGasRate = false;
@ -594,11 +620,12 @@ void nmWxIncludeOtherWells::normalizeFlowSelection(WellDataRow& data) const
const int nSegmentCount = flowRecordSegmentCount(*pRecord);
if(nSegmentCount <= 0) {
data.m_sFlowGaugeCode.clear();
data.m_bUseOilRate = false;
data.m_bUseGasRate = false;
data.m_bUseWaterRate = false;
data.m_nFlowSegmentIndex = 0;
nmFlowGaugeRecord* pMutableRecord = findMutableFlowRecord(
data.m_vecFlowRecords, data.m_sFlowGaugeCode);
if(pMutableRecord != nullptr) {
pMutableRecord->nIndexF = 0;
}
return;
}
if(data.m_nFlowSegmentIndex < 1 ||
@ -711,7 +738,7 @@ void nmWxIncludeOtherWells::populateFlowSegmentCombo(
}
const bool bSignalsWereBlocked = pComboBox->blockSignals(true);
pComboBox->clear();
const nmFlowGaugeRecord* pRecord = findFlowRecord(
const nmFlowGaugeRecord* pRecord = findUniqueUsableFlowRecord(
data.m_vecFlowRecords, data.m_sFlowGaugeCode);
const int nSegmentCount = pRecord == nullptr
? 0 : flowRecordSegmentCount(*pRecord);

Loading…
Cancel
Save