lmi
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lmi] Defect corrected: calendar date versus date of birth


From: Greg Chicares
Subject: [lmi] Defect corrected: calendar date versus date of birth
Date: Thu, 24 Jul 2008 15:57:03 +0000
User-agent: Thunderbird 2.0.0.14 (Windows/20080421)

We need to remove BasicValues::AssertAgeAndDobAreConsistent(),
which, as of 20080724T1212Z, is the last part of the insurance-
calculation code that uses obsolete class InputParms. It's not
actually needed because its logic is duplicated in class Input:
compare lines 686-699 here:

http://cvs.savannah.gnu.org/viewvc/lmi/lmi/ihs_basicval.cpp?annotate=1.82

to lines 1071-1093 here:

http://cvs.savannah.gnu.org/viewvc/lmi/lmi/input_harmonization.cpp?annotate=1.63

Except for the defect discussed on lines 1083-1088 in the latter
file, the latter (input) prevents the former (calculations) from
finding anything to complain about. We must resolve that defect
now so that class InputParms can be eradicated. In order to do so
confidently, we must follow Ruskin's advice to "substitute facts
for appearances, and demonstrations for impressions". Ostensibly
Input::DoTransmogrify() is wrong to use 'false' as the third
argument to add_years(), but we can proceed only with proof.

Consider this testcase:

File | New | Illustration
2008-02-29 case effective date
1960-02-29 date of birth
uncheck "Birthdate overrides issue age"
[issue age is 48]
OK

Illustration | Edit cell
change issue age to 47
Tab [to invoke validation]

What should be the outcome? InputParms::AlignAgeAndBirthdate()
says

        // If no DOB is supplied, a birthday is assumed to occur on the
        // issue date--as good an assumption as any, and the simplest.

on lines 418-419 here:

http://cvs.savannah.gnu.org/viewvc/lmi/lmi/inputs.cpp?annotate=1.26

That's not literally possible, because 1961-02-29 is invalid, but
the most tasteful succedaneum would seem to be the day preceding.
What we observe, however, is 1960-03-01, which is less tasteful
because it changes fractional age from 48.00 to 47.99, while the
fraction is zero in almost every other case. A one-year change in
age has elicited a one-day change in birthdate, which seems odd.
It is odder still that, at first glance, the code wouldn't appear
to be capable of producing such an outcome--and indeed it cannot
do so directly.

Apply the patch below [1] to a copy of HEAD as of 20080724T1212Z
or earlier, and run our testcase with that experimental build.
Observe:

DOB CHANGED
1960-02-29 formerly
1961-03-01 now
[file /lmi/src/lmi/input_harmonization.cpp, line 1100]

1961-03-01 DateOfBirth.value()
1961-03-01 DateOfBirth1
1961-02-28 DateOfBirth2
48 apparent_age
47 IssueAge.value()
[file /lmi/src/lmi/input_harmonization.cpp, line 1119]

DOB CHANGED
1961-03-01 formerly
1960-03-01 now
[file /lmi/src/lmi/input_harmonization.cpp, line 1100]

Thus:
  1961-02-28 is what date of birth should be, but...
  1961-03-01 is what it initially (and incorrectly) becomes
  1960-03-01 is what it later gets corrected to
The later correction occurs because Input::DoTransmogrify() is
called repeatedly by MvcModel::Reconcile(), as the documentation
states:

/// Reconcile() calls Harmonize() and Transmogrify() one or more
/// times, until neither changes any data member's value.

but giving a wrong answer the first time and relying on another
pass to correct it is not how we build maintainable programs. As
Einstein said, "a good joke should not be repeated too often".

Is HEAD correct in this respect as of 20080724T1545Z?

---------

[1] "the patch below"

Index: input_harmonization.cpp
===================================================================
RCS file: /sources/lmi/lmi/input_harmonization.cpp,v
retrieving revision 1.63
diff -U 3 -r1.63 input_harmonization.cpp
--- input_harmonization.cpp     6 Jul 2008 18:40:21 -0000       1.63
+++ input_harmonization.cpp     24 Jul 2008 13:48:31 -0000
@@ -1075,17 +1075,50 @@
         );
     if("No" == DeprecatedUseDOB)
         {
+        calendar_date const DateOfBirth1 = add_years
+            (DateOfBirth.value()
+            ,apparent_age - IssueAge.value()
+            ,false // Is 'false' always right? See note below.
+            );
+        calendar_date const DateOfBirth2 = add_years
+            (DateOfBirth.value()
+            ,apparent_age - IssueAge.value()
+            ,true
+            );
+
+calendar_date const old_dob = DateOfBirth.value();
         DateOfBirth = add_years
             (DateOfBirth.value()
             ,apparent_age - IssueAge.value()
             ,false // Is 'false' always right? See note below.
             );
+if(old_dob != DateOfBirth.value())
+  warning()
+    << "DOB CHANGED\n"
+    << old_dob.str() << " formerly\n"
+    << DateOfBirth.value().str() << " now\n"
+    << LMI_FLUSH
+    ;
+
 // TODO ?? Above, it appears that 'true' is always right. Inspect work
 // done in the 'skeleton' trunk around 2006-10 carefully to confirm
 // this; then correct the code above, and validate all other usage of
 // add_years(), paying special attention to the apparently-correct
 //   InputStatus::MakeAgesAndDatesConsistent()
 // code in 'inputstatus.cpp'.
+        if(DateOfBirth2 != DateOfBirth1)
+            {
+            warning()
+                << DateOfBirth.value().str() << " DateOfBirth.value()\n"
+                << DateOfBirth1.str() << " DateOfBirth1\n"
+                << DateOfBirth2.str() << " DateOfBirth2\n"
+                << apparent_age << " apparent_age\n"
+                << IssueAge.value() << " IssueAge.value()\n"
+                << minimum_birthdate(IssueAge.maximum(), 
EffectiveDate.value(), use_anb).str() << " min\n"
+                << maximum_birthdate(IssueAge.minimum(), 
EffectiveDate.value(), use_anb).str() << " max\n"
+                << LMI_FLUSH
+                ;
+            }
         }
     else
         {




reply via email to

[Prev in Thread] Current Thread [Next in Thread]