=========================================================== RiverWare support functions in Sim/SlotGUIUtils / 2-25-2013 =========================================================== New Slot utility functions in SlotGUIUtils to compare the values of slots which are intended to be potentially-modified copies of each other. This is used in the Scenario mechanism to determine whether a Scenario Slot has any changes relative to it's source Baseline Slot. bool slotsHaveEqualValues (const Slot*, const Slot*, Date_Time* firstDiffRet=NULL); bool slotsAreCongruent (const Slot*, const Slot*); bool seriesSlotsAreCongruent (const SeriesSlot* ss1, const SeriesSlot* ss2); [see first use in Scenario::recomputeInputChangeStatus()]. //------------------------------------------------------- // $Id: Sim/SlotGUIUtils.cpp 2013/02/25 20:19:24 philw $ //------------------------------------------------------- EXCERPT ... bool SlotGUIUtils::slotsHaveEqualValues (const Slot* slot1, const Slot* slot2, Date_Time* firstDiffRet /*=NULL*/) { // NOTE: Only ScalarSlots, TableSlots, SeriesSlots and AggSeriesSlots // are fully supported by this method. Subclasses of those Slots // (e.g. of TableSlot) are supported only with respect to the slot // base class values. if (slot2 == slot1) return (true); if (slot2 == NULL) return (false); if (slot1 == NULL) return (false); //------------------------------->> const bool areCong = slotsAreCongruent (slot1, slot2); if (!areCong) return (false); //------------------------->> const bool isScalarSlot = slot1->isA (Slot::ScalarSlotBit); const bool isTableSlot = slot1->isA (Slot::TableSlotBit); const bool isAggSeries = slot1->isA (Slot::AggSeriesSlotBit); const bool isSeriesSlot = slot1->isA (Slot::SeriesSlotBit); // ******************************* // *** ScalarSlot Comparison *** // ******************************* if (isScalarSlot) { const ScalarSlot* scSlot1 = dynamic_cast (slot1); const ScalarSlot* scSlot2 = dynamic_cast (slot2); if (!rwAssert (scSlot1 != NULL)) return (false); // not equal if (!rwAssert (scSlot2 != NULL)) return (false); // not equal const double val1 = scSlot1->getValue(); const double val2 = scSlot2->getValue(); return (isEqual (val1, val2)); //-------------------------->> } // ****************************** // *** TableSlot Comparison *** // ****************************** if (isTableSlot) { const TableSlot* ts1 = dynamic_cast (slot1); const TableSlot* ts2 = dynamic_cast (slot2); if (!rwAssert (ts1 != NULL)) return (false); if (!rwAssert (ts2 != NULL)) return (false); const int rowCnt = ts1->getNumRows(); const int colCnt = ts2->getNumColumns(); for (int col = 0; col < colCnt; ++col) { for (int row = 0; row < rowCnt; ++row) { const double val1 = ts1->getValue (row, col); const double val2 = ts2->getValue (row, col); if (!isEqual (val1, val2)) return (false); //-------------------------------------->> } } return (true); // table slots have equal values } // ********************************** // *** AggSeriesSlot Comparison *** // ********************************** if (isAggSeries) { // Note: Comprehensive congruency checks are not re-implemented here. // These have been checked above, e.g. step size and start dates. const AggSeriesSlot* aggS1 = dynamic_cast (slot1); const AggSeriesSlot* aggS2 = dynamic_cast (slot2); if (!rwAssert (aggS1 != NULL)) return (false); if (!rwAssert (aggS2 != NULL)) return (false); const int colCnt1 = aggS1->numSeriesSlots(); const int colCnt2 = aggS2->numSeriesSlots(); if (colCnt1 != colCnt2) return (false); //----------------------------------->> for (int col = 0; col < colCnt1; ++col) { // Note: TOO BAD this can't be called recursively for the SeriesSlot // columns of the AggSeriesSlot. The problem is that the first // SeriesSlot column IS the overall AggSeriesSlot, and cannot be // distinguished given just a SeriesSlot pointer. const SeriesSlot* colSlot1 = aggS1->getSeriesSlot (col); const SeriesSlot* colSlot2 = aggS2->getSeriesSlot (col); if (!rwAssert (colSlot1 != NULL)) return (false); if (!rwAssert (colSlot2 != NULL)) return (false); const int valCnt1 = colSlot1->numValues(); const int valCnt2 = colSlot2->numValues(); if (valCnt1 != valCnt2) return (false); //----------------------------------->> for (int valInx = 0; valInx < valCnt1; ++valInx) { double val1 (INVALIDVALUE); double val2 (INVALIDVALUE); colSlot1->getValueByIndex (valInx, val1); colSlot2->getValueByIndex (valInx, val2); if (!isEqual (val1, val2)) { if (firstDiffRet != NULL) { // Assign Return Date_Time for first value difference. errstat dateErr = colSlot1->getDate (valInx, firstDiffRet); dateErr; // (avoid compilation warning) } return (false); // AggSeriesSlot values not equal } } } return (true); // AggSeriesSlot values are equal } // ******************************* // *** SeriesSlot Comparison *** // ******************************* if (isSeriesSlot) // (and not an AggSeriesSlot, see above) { // Note: Comprehensive congruency checks are not re-implemented here. // These have been checked above, e.g. step size and start dates. const SeriesSlot* sslot1 = dynamic_cast (slot1); const SeriesSlot* sslot2 = dynamic_cast (slot2); if (!rwAssert (sslot1 != NULL)) return (false); if (!rwAssert (sslot2 != NULL)) return (false); const int valCnt1 = sslot1->numValues(); const int valCnt2 = sslot2->numValues(); if (valCnt1 != valCnt2) return (false); //----------------------------------->> for (int valInx = 0; valInx < valCnt1; ++valInx) { double val1 (INVALIDVALUE); double val2 (INVALIDVALUE); sslot1->getValueByIndex (valInx, val1); sslot2->getValueByIndex (valInx, val2); if (!isEqual (val1, val2)) { if (firstDiffRet != NULL) { // Assign Return Date_Time for first value difference. errstat dateErr = sslot1->getDate (valInx, firstDiffRet); dateErr; // (avoid compilation warning) } return (false); // SeriesSlot values not equal } } return (true); // SeriesSlot values are equal } rwAssert (("Slot type is not supported.", 0)); return (false); } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- bool SlotGUIUtils::slotsAreCongruent (const Slot* slot1, const Slot* slot2) { // NOTE: Only ScalarSlots, TableSlots, SeriesSlots and AggSeriesSlots // are currently supported by this method. if (slot2 == slot1) return (true); if (slot2 == NULL) return (false); if (slot1 == NULL) return (false); //------------------------------->> if (slot1->isA (Slot::ScalarSlotBit)) { return slot2->isA (Slot::ScalarSlotBit); } if (slot1->isA (Slot::TableSlotBit)) { if (!slot2->isA (Slot::TableSlotBit)) return (false); const TableSlot* tabSlot1 = dynamic_cast (slot1); const TableSlot* tabSlot2 = dynamic_cast (slot2); const int rows1 = tabSlot1 ? tabSlot1->getNumRows() : (-1); const int cols1 = tabSlot1 ? tabSlot1->getNumColumns() : (-1); const int rows2 = tabSlot2 ? tabSlot2->getNumRows() : (-1); const int cols2 = tabSlot2 ? tabSlot2->getNumColumns() : (-1); return ((rows1 == rows2) && (cols1 == cols2)); } if (slot1->isA (Slot::AggSeriesSlotBit)) { if (!slot2->isA (Slot::AggSeriesSlotBit)) return (false); const AggSeriesSlot* aggS1 = dynamic_cast (slot1); const AggSeriesSlot* aggS2 = dynamic_cast (slot2); if (aggS1 == NULL) return (false); if (aggS2 == NULL) return (false); const int cnt1 = aggS1->numSeriesSlots(); const int cnt2 = aggS2->numSeriesSlots(); if (cnt1 != cnt2) return (false); for (int inx = 0; inx < cnt1; ++inx) { const SeriesSlot* colSlot1 = aggS1->getSeriesSlot (inx); const SeriesSlot* colSlot2 = aggS2->getSeriesSlot (inx); const bool cong = seriesSlotsAreCongruent (colSlot1, colSlot2); if (!cong) return (false); } return (true); // congruent } if (slot1->isA (Slot::SeriesSlotBit)) { if (!slot2->isA (Slot::SeriesSlotBit)) return (false); const SeriesSlot* sslot1 = dynamic_cast (slot1); const SeriesSlot* sslot2 = dynamic_cast (slot2); const bool cong = seriesSlotsAreCongruent (sslot1, sslot2); return (cong); // congruent } // Other slot types (not fully supported), just do a slot type check. const int slotType1 = slot1->slotTypeBit(); const int slotType2 = slot2->slotTypeBit(); return (slotType1 == slotType2); // congruent } //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- bool SlotGUIUtils::seriesSlotsAreCongruent (const SeriesSlot* ss1, const SeriesSlot* ss2) { if (ss1 == ss2) return (true); if (ss1 == NULL) return (false); if (ss2 == NULL) return (false); if (ss1->numValues() != ss2->numValues()) return (false); if (ss1->getStep() != ss2->getStep()) return (false); const Date_Time* start1 = ss1->getStartDate(); const Date_Time* start2 = ss2->getStartDate(); if (start1 == NULL) return (false); if (start2 == NULL) return (false); if (*start1 != *start2) return (false); return (true); // congruent } //--- (end) ---