You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nmWTAI-Platform/Src/nmNum/nmSubWxs/nmReservoirPropertiesSessio...

322 lines
12 KiB
C++

#include "nmReservoirPropertiesSession.h"
#include "nmAttrRegistry.h"
#include "nmDataAttribute.h"
#include "rapidjson/document.h"
namespace
{
/** @brief 比较两个QVariant数值保留字符串和整数的精确语义。 */
bool sameValue(const QVariant& oLeft, const QVariant& oRight)
{
return oLeft == oRight;
}
template<typename T>
bool sameDataObject(const T& oLeft, const T& oRight)
{
rapidjson::Document oLeftDocument;
rapidjson::Document oRightDocument;
rapidjson::Value oLeftValue = oLeft.ToJsonValue(
oLeftDocument.GetAllocator());
rapidjson::Value oRightValue = oRight.ToJsonValue(
oRightDocument.GetAllocator());
return oLeftValue == oRightValue;
}
template<typename T>
bool sameDataVector(const QVector<T>& vecLeft, const QVector<T>& vecRight)
{
if(vecLeft.size() != vecRight.size()) {
return false;
}
for(int nIndex = 0; nIndex < vecLeft.size(); ++nIndex) {
if(!sameDataObject(vecLeft[nIndex], vecRight[nIndex])) {
return false;
}
}
return true;
}
/** @brief 比较两口井的平面位置。 */
bool sameWellPosition(nmDataWellBase& oLeft, nmDataWellBase& oRight)
{
return sameValue(oLeft.getX().getValue(), oRight.getX().getValue()) &&
sameValue(oLeft.getY().getValue(), oRight.getY().getValue());
}
}
nmReservoirPropertiesSession::nmReservoirPropertiesSession(
nmIReservoirPropertiesDataSource* pDataSource)
: m_pDataSource(pDataSource),
m_pAttrRegistry(new nmAttrRegistry),
m_bInitialized(false)
{
}
nmReservoirPropertiesSession::~nmReservoirPropertiesSession()
{
delete m_pAttrRegistry;
m_pAttrRegistry = nullptr;
m_pDataSource = nullptr;
}
bool nmReservoirPropertiesSession::initialize(QString& sError)
{
// 第一步:读取一次真实数据,作为取消和变更检测的基线。
if (m_pDataSource == nullptr ||
!m_pDataSource->loadSnapshot(m_oOriginalSnapshot, sError))
{
m_bInitialized = false;
return false;
}
// 第二步:复制出独立工作副本,后续界面修改只写入此对象。
m_oWorkingSnapshot = m_oOriginalSnapshot;
nmReservoirParameterCatalog::registerSnapshot(m_pAttrRegistry,
m_oWorkingSnapshot);
m_bInitialized = true;
sError.clear();
return true;
}
QList<nmReservoirPropertyObjectInfo> nmReservoirPropertiesSession::objectInfos(
nmReservoirPropertiesCategory eCategory)
{
if (!m_bInitialized)
{
return QList<nmReservoirPropertyObjectInfo>();
}
return nmReservoirParameterCatalog::createObjectInfos(eCategory,
m_oWorkingSnapshot);
}
QVariant nmReservoirPropertiesSession::value(const QString& sParameterId) const
{
if (!m_bInitialized || m_pAttrRegistry == nullptr)
{
return QVariant();
}
QStringList listIds;
listIds << sParameterId;
return m_pAttrRegistry->collect(listIds).value(sParameterId, QVariant());
}
bool nmReservoirPropertiesSession::setValue(const QString& sParameterId,
const QVariant& oValue)
{
if (!m_bInitialized || m_pAttrRegistry == nullptr ||
!m_pAttrRegistry->registeredNames().contains(sParameterId))
{
return false;
}
if (sameValue(value(sParameterId), oValue))
{
return true;
}
m_pAttrRegistry->setValue(sParameterId, oValue);
return true;
}
void nmReservoirPropertiesSession::setValues(
const QMap<QString, QVariant>& mapValues)
{
QMap<QString, QVariant>::const_iterator oIterator = mapValues.constBegin();
for (; oIterator != mapValues.constEnd(); ++oIterator)
{
setValue(oIterator.key(), oIterator.value());
}
}
QString nmReservoirPropertiesSession::enumCode(const QString& sParameterId) const
{
if (!m_bInitialized)
{
return QString();
}
return nmReservoirParameterCatalog::enumCode(m_oWorkingSnapshot,
sParameterId);
}
bool nmReservoirPropertiesSession::setEnumCode(const QString& sParameterId,
const QString& sCode)
{
if (!m_bInitialized)
{
return false;
}
if (enumCode(sParameterId) == sCode)
{
return true;
}
if (!nmReservoirParameterCatalog::setEnumCode(m_oWorkingSnapshot,
sParameterId,
sCode))
{
return false;
}
return true;
}
bool nmReservoirPropertiesSession::commit(QString& sError)
{
if (!m_bInitialized || m_pDataSource == nullptr)
{
sError = QObject::tr("The reservoir properties editing session is unavailable.");
return false;
}
// 第一步:几何变化优先级最高;其他正式输入只推进结果版本。
NM_PEBI_INPUT_CHANGE eInputChange = NM_PEBI_INPUT_UNCHANGED;
if (isGeometryChanged())
{
eInputChange = NM_PEBI_GRID_INPUT_CHANGED;
}
else if (isInputChanged())
{
eInputChange = NM_PEBI_RESULT_INPUT_CHANGED;
}
// 第二步:将完整工作副本一次性交给数据源;失败时继续保留当前编辑内容。
if (!m_pDataSource->commitSnapshot(m_oWorkingSnapshot,
eInputChange,
sError))
{
return false;
}
// 第三步:提交成功后更新基线,防止同一会话重复识别旧变更。
m_oOriginalSnapshot = m_oWorkingSnapshot;
sError.clear();
return true;
}
const nmReservoirPropertiesSnapshot&
nmReservoirPropertiesSession::workingSnapshot() const
{
return m_oWorkingSnapshot;
}
bool nmReservoirPropertiesSession::isInputChanged() const
{
// 完整结构化比较覆盖数值、枚举和批量导入,不依赖具体界面入口。
return m_oOriginalSnapshot.m_nSolverModelType !=
m_oWorkingSnapshot.m_nSolverModelType ||
!sameDataObject(m_oOriginalSnapshot.m_oReservoir,
m_oWorkingSnapshot.m_oReservoir) ||
!sameDataVector(m_oOriginalSnapshot.m_vecVerticalWells,
m_oWorkingSnapshot.m_vecVerticalWells) ||
!sameDataVector(m_oOriginalSnapshot.m_vecVerticalFracturedWells,
m_oWorkingSnapshot.m_vecVerticalFracturedWells) ||
!sameDataVector(m_oOriginalSnapshot.m_vecHorizontalFracturedWells,
m_oWorkingSnapshot.m_vecHorizontalFracturedWells) ||
!sameDataVector(m_oOriginalSnapshot.m_vecRegionMarks,
m_oWorkingSnapshot.m_vecRegionMarks) ||
!sameDataVector(m_oOriginalSnapshot.m_vecFaults,
m_oWorkingSnapshot.m_vecFaults) ||
!sameDataVector(m_oOriginalSnapshot.m_vecFractures,
m_oWorkingSnapshot.m_vecFractures) ||
!sameDataVector(m_oOriginalSnapshot.m_vecRegions,
m_oWorkingSnapshot.m_vecRegions);
}
bool nmReservoirPropertiesSession::isGeometryChanged() const
{
// 第一步:对象数量变化视为几何变化,虽然当前对话框本身不提供增删操作。
if (m_oOriginalSnapshot.m_vecVerticalWells.size() !=
m_oWorkingSnapshot.m_vecVerticalWells.size() ||
m_oOriginalSnapshot.m_vecVerticalFracturedWells.size() !=
m_oWorkingSnapshot.m_vecVerticalFracturedWells.size() ||
m_oOriginalSnapshot.m_vecHorizontalFracturedWells.size() !=
m_oWorkingSnapshot.m_vecHorizontalFracturedWells.size())
{
return true;
}
// 第二步:比较三类井的位置和井径。
for (int nIndex = 0; nIndex < m_oWorkingSnapshot.m_vecVerticalWells.size(); ++nIndex)
{
nmDataVerticalWell& oOriginal =
const_cast<nmDataVerticalWell&>(m_oOriginalSnapshot.m_vecVerticalWells[nIndex]);
nmDataVerticalWell& oWorking =
const_cast<nmDataVerticalWell&>(m_oWorkingSnapshot.m_vecVerticalWells[nIndex]);
if (!sameWellPosition(oOriginal, oWorking) ||
!sameValue(oOriginal.getRadius().getValue(),
oWorking.getRadius().getValue()))
{
return true;
}
}
for (int nIndex = 0; nIndex < m_oWorkingSnapshot.m_vecVerticalFracturedWells.size(); ++nIndex)
{
nmDataVerticalFracturedWell& oOriginal = const_cast<nmDataVerticalFracturedWell&>(
m_oOriginalSnapshot.m_vecVerticalFracturedWells[nIndex]);
nmDataVerticalFracturedWell& oWorking = const_cast<nmDataVerticalFracturedWell&>(
m_oWorkingSnapshot.m_vecVerticalFracturedWells[nIndex]);
if (!sameWellPosition(oOriginal, oWorking) ||
!sameValue(oOriginal.getFractureHalfLength().getValue(),
oWorking.getFractureHalfLength().getValue()) ||
!sameValue(oOriginal.getFractureAngle().getValue(),
oWorking.getFractureAngle().getValue()) ||
!sameValue(oOriginal.getWidth().getValue(),
oWorking.getWidth().getValue()) ||
!sameValue(oOriginal.getDfc().getValue(),
oWorking.getDfc().getValue()))
{
return true;
}
}
for (int nIndex = 0; nIndex < m_oWorkingSnapshot.m_vecHorizontalFracturedWells.size(); ++nIndex)
{
nmDataHorizontalFracturedWell& oOriginal =
const_cast<nmDataHorizontalFracturedWell&>(
m_oOriginalSnapshot.m_vecHorizontalFracturedWells[nIndex]);
nmDataHorizontalFracturedWell& oWorking =
const_cast<nmDataHorizontalFracturedWell&>(
m_oWorkingSnapshot.m_vecHorizontalFracturedWells[nIndex]);
if (!sameWellPosition(oOriginal, oWorking) ||
!sameValue(oOriginal.getWellLength().getValue(), oWorking.getWellLength().getValue()) ||
!sameValue(oOriginal.getDrainAngle().getValue(), oWorking.getDrainAngle().getValue()) ||
!sameValue(oOriginal.getNumberOfFractures().getValue(),
oWorking.getNumberOfFractures().getValue()) ||
!sameValue(oOriginal.getFractureHalfLength().getValue(),
oWorking.getFractureHalfLength().getValue()) ||
!sameValue(oOriginal.getFractureAngle().getValue(),
oWorking.getFractureAngle().getValue()) ||
!sameValue(oOriginal.getWidth().getValue(),
oWorking.getWidth().getValue()) ||
!sameValue(oOriginal.getDfc().getValue(),
oWorking.getDfc().getValue()))
{
return true;
}
}
// 第三步:断层和裂缝端点也直接参与网格,因此比较完整点坐标。
if (m_oOriginalSnapshot.m_vecFaults.size() != m_oWorkingSnapshot.m_vecFaults.size() ||
m_oOriginalSnapshot.m_vecFractures.size() != m_oWorkingSnapshot.m_vecFractures.size())
{
return true;
}
for (int nIndex = 0; nIndex < m_oWorkingSnapshot.m_vecFaults.size(); ++nIndex)
{
if (m_oOriginalSnapshot.m_vecFaults[nIndex].getFaultPoints() !=
m_oWorkingSnapshot.m_vecFaults[nIndex].getFaultPoints())
{
return true;
}
}
for (int nIndex = 0; nIndex < m_oWorkingSnapshot.m_vecFractures.size(); ++nIndex)
{
if (m_oOriginalSnapshot.m_vecFractures[nIndex].getFracturePoints() !=
m_oWorkingSnapshot.m_vecFractures[nIndex].getFracturePoints())
{
return true;
}
}
return false;
}