[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[lmi-commits] [5546] Prepare to expunge 'SpecamtHistory'
From: |
Greg Chicares |
Subject: |
[lmi-commits] [5546] Prepare to expunge 'SpecamtHistory' |
Date: |
Mon, 20 Aug 2012 17:11:41 +0000 |
Revision: 5546
http://svn.sv.gnu.org/viewvc/?view=rev&root=lmi&revision=5546
Author: chicares
Date: 2012-08-20 17:11:40 +0000 (Mon, 20 Aug 2012)
Log Message:
-----------
Prepare to expunge 'SpecamtHistory'
Modified Paths:
--------------
lmi/trunk/input.hpp
lmi/trunk/input_realization.cpp
lmi/trunk/input_test.cpp
lmi/trunk/input_xml_io.cpp
Modified: lmi/trunk/input.hpp
===================================================================
--- lmi/trunk/input.hpp 2012-08-18 11:49:20 UTC (rev 5545)
+++ lmi/trunk/input.hpp 2012-08-20 17:11:40 UTC (rev 5546)
@@ -212,6 +212,12 @@
std::string RealizeAmountsPaidHistory ();
std::string RealizeSpecamtHistory ();
+ int must_overwrite_specamt_with_obsolete_history
+ (std::string specamt
+ ,std::string history
+ ,bool hide_errors = false
+ ) const;
+
void make_term_rider_consistent(bool aggressively = true);
boost::scoped_ptr<product_database> database_;
Modified: lmi/trunk/input_realization.cpp
===================================================================
--- lmi/trunk/input_realization.cpp 2012-08-18 11:49:20 UTC (rev 5545)
+++ lmi/trunk/input_realization.cpp 2012-08-20 17:11:40 UTC (rev 5546)
@@ -34,23 +34,24 @@
#include "database.hpp"
#include "dbnames.hpp"
#include "global_settings.hpp"
+#include "handle_exceptions.hpp"
#include "input_seq_helpers.hpp"
-#include "miscellany.hpp" // minmax<T>()
+#include "miscellany.hpp" // minmax<T>()
#include "round_to.hpp"
-#include "stl_extensions.hpp" // nonstd::is_sorted()
+#include "stl_extensions.hpp" // nonstd::is_sorted()
#include "value_cast.hpp"
#include <boost/bind.hpp>
#include <algorithm>
#include <sstream>
-#include <utility> // std::pair
+#include <utility> // std::pair
//============================================================================
// Realize sequence strings with only numeric values.
template<typename T>
std::string realize_sequence_string
- (Input & input
+ (Input const& input
,std::vector<T> & v
,datum_sequence const& sequence_string
,int index_origin = 0
@@ -73,7 +74,7 @@
// Realize sequence strings with only enumerative-string values.
template<typename T>
std::string realize_sequence_string
- (Input & input
+ (Input const& input
,std::vector<T> & v
,datum_sequence const& sequence_string
,detail::stringmap const& keyword_dictionary
@@ -106,7 +107,7 @@
// Realize sequence strings with both numeric and enumerative-string values.
template<typename Numeric, typename Enumerative>
std::string realize_sequence_string
- (Input & input
+ (Input const& input
,std::vector<Numeric> & vn
,std::vector<Enumerative> & ve
,datum_sequence const& sequence_string
@@ -905,6 +906,86 @@
);
}
+/// Determine whether specamt must be overwritten with history.
+///
+/// 'SpecifiedAmount' gives values for all policy years since issue,
+/// so 'SpecamtHistory' ought never to been created. Given that it did
+/// exist, it ought to have included only a subset of the values given
+/// by 'SpecifiedAmount'; but some extracts provide only a scalar for
+/// 'SpecifiedAmount', which must therefore be overwritten with the
+/// contents of the obsolete history entity. A warning is given if
+/// this backward-compatibility measure would lose any additional
+/// information given in 'SpecifiedAmount'--e.g., if a user saved an
+/// extract after modifying it to change future specamt without
+/// copying history into 'SpecifiedAmount'.
+///
+/// One of these four values is returned:
+/// 0 'SpecifiedAmount' already matches 'SpecamtHistory' through the
+/// inforce as-of date, so 'SpecamtHistory' can be discarded.
+/// 1 'SpecifiedAmount' matches 'SpecamtHistory' for future durations
+/// but not for historical durations, so 'SpecifiedAmount' should
+/// be overwritten with 'SpecamtHistory'.
+/// 2 Otherwise, they're inconsistent, so a warning is displayed. The
+/// warning may also be displayed when 'SpecifiedAmount' contains
+/// a keyword, in which case consistency is either difficult or
+/// impossible to determine.
+/// 3 An unexpected exception occurred in parsing an argument string;
+/// it's trapped, and passed to report_exception().
+/// As the function's name implies, it's used as though it returned a
+/// boolean, but returning an int facilitates unit testing, as does
+/// the last argument.
+
+int Input::must_overwrite_specamt_with_obsolete_history
+ (std::string specamt
+ ,std::string history
+ ,bool hide_errors
+ ) const
+{
+ std::vector<tnr_unrestricted_double> u;
+ std::vector<tnr_unrestricted_double> v;
+ try
+ {
+ realize_sequence_string(*this, u, numeric_sequence(specamt));
+ realize_sequence_string(*this, v, numeric_sequence(history));
+ }
+ catch(...)
+ {
+ report_exception();
+ return 3;
+ }
+
+ bool history_differs = false;
+ bool future_differs = false;
+ int const years_of_history = InforceYear.value() + (0 !=
InforceMonth.value());
+ for(int j = 0; j < years_of_history; ++j)
+ {
+ if(u[j] != v[j])
+ {
+ history_differs = true;
+ break;
+ }
+ }
+ for(int j = years_of_history; j < years_to_maturity(); ++j)
+ {
+ if(u[j] != v[j])
+ {
+ future_differs = true;
+ break;
+ }
+ }
+ if(history_differs && future_differs && !hide_errors)
+ {
+ warning()
+ << "Possible conflict between specified amount and history."
+ << " Merge them manually into the specified-amount field."
+ << "\nSpecified amount: " << specamt
+ << "\nHistory: " << history
+ << LMI_FLUSH
+ ;
+ }
+ return history_differs + (history_differs && future_differs);
+}
+
// TODO ?? More attention could be paid to term-rider rounding.
// This would be preferable:
//
Modified: lmi/trunk/input_test.cpp
===================================================================
--- lmi/trunk/input_test.cpp 2012-08-18 11:49:20 UTC (rev 5545)
+++ lmi/trunk/input_test.cpp 2012-08-20 17:11:40 UTC (rev 5546)
@@ -62,6 +62,7 @@
test_product_database();
test_input_class();
test_document_classes();
+ test_obsolete_history();
assay_speed();
}
@@ -69,6 +70,7 @@
static void test_product_database();
static void test_input_class();
static void test_document_classes();
+ static void test_obsolete_history();
static void assay_speed();
template<typename DocumentClass>
@@ -342,6 +344,52 @@
test_document_io<S>("sample.ill", "replica.ill", __FILE__, __LINE__,
false);
}
+void input_test::test_obsolete_history()
+{
+ Input z;
+ z.InforceYear = 0;
+ z.InforceMonth = 0;
+ // For new business, history is irrelevant.
+ BOOST_TEST(0 == z.must_overwrite_specamt_with_obsolete_history("0" ,
"1" , true));
+ // Year 0, month 1: one year of history.
+ z.InforceYear = 0;
+ z.InforceMonth = 1;
+ BOOST_TEST(2 == z.must_overwrite_specamt_with_obsolete_history("0" ,
"1" , true));
+ BOOST_TEST(0 == z.must_overwrite_specamt_with_obsolete_history("1" ,
"1" , true));
+ // Year 1, month 0: one year of history.
+ z.InforceYear = 1;
+ z.InforceMonth = 0;
+ BOOST_TEST(2 == z.must_overwrite_specamt_with_obsolete_history("0" ,
"1" , true));
+ BOOST_TEST(0 == z.must_overwrite_specamt_with_obsolete_history("1" ,
"1" , true));
+ BOOST_TEST(0 == z.must_overwrite_specamt_with_obsolete_history("1" ,
"1;2" , true));
+ BOOST_TEST(1 == z.must_overwrite_specamt_with_obsolete_history("1;2" ,
"2" , true));
+ // "History" after first year doesn't matter.
+ BOOST_TEST(0 == z.must_overwrite_specamt_with_obsolete_history("1;2" ,
"1" , true));
+ // Year 1, month 1: two years of history.
+ z.InforceYear = 1;
+ z.InforceMonth = 1;
+ BOOST_TEST(0 == z.must_overwrite_specamt_with_obsolete_history("1" ,
"1" , true));
+ // No conflict: history is a "subset" of specamt.
+ BOOST_TEST(0 == z.must_overwrite_specamt_with_obsolete_history("1;2" ,
"1;2;3" , true));
+ BOOST_TEST(2 == z.must_overwrite_specamt_with_obsolete_history("1;2" ,
"1" , true));
+ BOOST_TEST(1 == z.must_overwrite_specamt_with_obsolete_history("1;2" ,
"2" , true));
+ BOOST_TEST(2 == z.must_overwrite_specamt_with_obsolete_history("1" ,
"1;2" , true));
+ BOOST_TEST(2 == z.must_overwrite_specamt_with_obsolete_history("1;2" ,
"2;3" , true));
+ BOOST_TEST(0 == z.must_overwrite_specamt_with_obsolete_history("1;2;3",
"1;2;3" , true));
+ // Warn if a keyword is used--this one's meaning depends on context.
+ BOOST_TEST(2 == z.must_overwrite_specamt_with_obsolete_history("1;2" ,
"1;corridor" , true));
+ // Keyword may engender "obvious" false positives.
+ BOOST_TEST(2 == z.must_overwrite_specamt_with_obsolete_history("1;2" ,
"1;2;corridor", true));
+ // This would have been forbidden: history was numeric only.
+// BOOST_TEST(2 == z.must_overwrite_specamt_with_obsolete_history("X" ,
"1" , true));
+ BOOST_TEST(2 == z.must_overwrite_specamt_with_obsolete_history("1" ,
"X" , true));
+ // This case differs little from the preceding one, but has a different
+ // outcome. Reason: non-numeric substrings are interepreted as zero.
+ // This oddity doesn't matter, because specified amount by its nature
+ // must be positive, and zero is returned so that nothing is changed.
+ BOOST_TEST(0 == z.must_overwrite_specamt_with_obsolete_history("0" ,
"X" , true));
+}
+
void input_test::assay_speed()
{
Input raw_data;
Modified: lmi/trunk/input_xml_io.cpp
===================================================================
--- lmi/trunk/input_xml_io.cpp 2012-08-18 11:49:20 UTC (rev 5545)
+++ lmi/trunk/input_xml_io.cpp 2012-08-20 17:11:40 UTC (rev 5546)
@@ -35,11 +35,12 @@
#include "database.hpp"
#include "global_settings.hpp"
#include "map_lookup.hpp"
-#include "miscellany.hpp" // lmi_array_size()
+#include "miscellany.hpp" // lmi_array_size()
#include "oecumenic_enumerations.hpp"
-#include <algorithm> // std::min()
+#include <algorithm> // std::min()
#include <stdexcept>
+#include <utility> // std::pair
template class xml_serializable<Input>;
@@ -528,6 +529,49 @@
InforceCumulativeGptPremiumsPaid =
InforceCumulativeNoLapsePayments.value();
InforceCumulativeRopPayments =
InforceCumulativeNoLapsePayments.value();
}
+
+ if(file_version < 7 && !contains(residuary_names, "SpecamtHistory"))
+ {
+ // Merge obsolete 'SpecamtHistory' into 'SpecifiedAmount'.
+ //
+ // Prior to version 7, 'SpecamtHistory' and 'SpecifiedAmount'
+ // were distinct. Some version-0 files had the history entity,
+ // but others did not; if it's not present, then of course it
+ // cannot be merged.
+ //
+ // Function must_overwrite_specamt_with_obsolete_history(),
+ // called below, requires 'InforceYear' and 'InforceMonth',
+ // which some "deficient" extracts omit. DoTransmogrify()
+ // sets those members downstream, but the "obsolete history"
+ // function needs them now. This requires version 5, which
+ // introduced 'InforceAsOfDate'; no "deficient" extract
+ // should have an earlier version.
+ if(deficient_extract && EffectiveDate.value() !=
InforceAsOfDate.value())
+ {
+ LMI_ASSERT(4 < file_version);
+ std::pair<int,int> ym0 = years_and_months_since
+ (EffectiveDate .value()
+ ,InforceAsOfDate.value()
+ );
+ InforceYear = ym0.first;
+ InforceMonth = ym0.second;
+ }
+ // Requiring 'deficient_extract' here wouldn't be right,
+ // because an extract file that has been modified and saved
+ // is no longer detectably "deficient".
+ if(0 != InforceYear || 0 != InforceMonth)
+ {
+ if
+ (must_overwrite_specamt_with_obsolete_history
+ (SpecifiedAmount.value()
+ ,SpecamtHistory .value()
+ )
+ )
+ {
+ SpecifiedAmount = SpecamtHistory.value();
+ }
+ }
+ }
}
void Input::redintegrate_ad_terminum()
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [lmi-commits] [5546] Prepare to expunge 'SpecamtHistory',
Greg Chicares <=