From fcbe36e76c58e90e74dc0a02f56e772196bfbbb9 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 20 Aug 2004 07:01:26 +0000 Subject: [PATCH] (coll, fina, repa, shark, disloan): Fix calculation of regular and extended (beyond due date) loan time. At the due date, or after a last payment made at the due date, durations were zero in fina() and unpredictable elsewhere. With luck, debtors could abuse this to repay loans cheap (they couldn't gain cash, though), sharks to purchase loans cheap, and creditors to collect excessively. --- src/lib/commands/coll.c | 24 ++++++++++++------------ src/lib/commands/fina.c | 29 ++++++++++------------------- src/lib/commands/repa.c | 23 +++++++++-------------- src/lib/commands/shark.c | 24 ++++++++++++------------ src/lib/subs/disloan.c | 26 +++++++++++--------------- 5 files changed, 54 insertions(+), 72 deletions(-) diff --git a/src/lib/commands/coll.c b/src/lib/commands/coll.c index c744e240..941b2d51 100644 --- a/src/lib/commands/coll.c +++ b/src/lib/commands/coll.c @@ -57,8 +57,6 @@ coll(void) struct lonstr loan; struct sctstr sect; coord x, y; - long due; - long last; long rdur; long xdur; double rate; @@ -82,19 +80,21 @@ coll(void) /* If we got here, we check to see if it's been defaulted on. We already know it's owed to this player. */ (void)time(&now); - due = loan.l_duedate; - if (now <= due) { + /* + * split duration now - l_lastpay into regular (up to l_duedate) + * and extended (beyond l_duedate) + */ + rdur = loan.l_duedate - loan.l_lastpay; + xdur = now - loan.l_duedate; + if (rdur < 0) { + xdur += rdur; + rdur = 0; + } + if (xdur <= 0) { pr("There has been no default on loan %d\n", arg); return RET_FAIL; } - last = loan.l_lastpay; - if (last < due && due < now) { - rdur = due - last; - xdur = now - due; - } else if (due < last) { - rdur = 0; - xdur = now - last; - } + rate = loan.l_irate / (loan.l_ldur * 8.64e6); /* changed following to avoid overflow 3/27/89 bailey@math-cs.kent.edu diff --git a/src/lib/commands/fina.c b/src/lib/commands/fina.c index 93aaf01f..b80cce07 100644 --- a/src/lib/commands/fina.c +++ b/src/lib/commands/fina.c @@ -56,8 +56,6 @@ fina(void) int xdur; double rate; double amt; - time_t due; - time_t last; if (!opt_LOANS) { pr("Loans are not enabled.\n"); @@ -73,26 +71,19 @@ fina(void) while (nxtitem(&ni, (s_char *)&loan)) { if (loan.l_status != LS_SIGNED) continue; - due = loan.l_duedate; - last = loan.l_lastpay; - rdur = 0; - xdur = 0; - if (now < due) { - rdur = now - last; - xdur = 0; - } - if (last < due && due < now) { - rdur = due - last; - xdur = now - due; - } - if (due < last) { + /* + * split duration now - l_lastpay into regular (up to l_duedate) + * and extended (beyond l_duedate) + */ + rdur = loan.l_duedate - loan.l_lastpay; + xdur = now - loan.l_duedate; + if (rdur < 0) { + xdur += rdur; rdur = 0; - xdur = now - last; } - if (loan.l_ldur == 0) { - logerror("loan #%d has zero duration", ni.cur); + + if (CANT_HAPPEN(loan.l_ldur == 0)) continue; - } rate = loan.l_irate / (loan.l_ldur * 8640000.0); /* changed following to avoid overflow 3/27/89 bailey@math-cs.kent.edu diff --git a/src/lib/commands/repa.c b/src/lib/commands/repa.c index 24dfa342..c22a96b1 100644 --- a/src/lib/commands/repa.c +++ b/src/lib/commands/repa.c @@ -50,8 +50,6 @@ repa(void) int loan_num; long payment; long owe; - long due; - long last_payment; long normaltime; long doubletime; double rate_per_sec, amt; @@ -76,20 +74,17 @@ repa(void) return RET_FAIL; } (void)time(&now); - due = loan.l_duedate; - last_payment = loan.l_lastpay; - if (now < due) { - normaltime = now - last_payment; - doubletime = 0; - } - if (last_payment < due && due < now) { - normaltime = due - last_payment; - doubletime = now - due; - } - if (due < last_payment) { + /* + * split duration now - l_lastpay into regular (up to l_duedate) + * and extended (beyond l_duedate) + */ + normaltime = loan.l_duedate - loan.l_lastpay; + doubletime = now - loan.l_duedate; + if (normaltime < 0) { + doubletime += normaltime; normaltime = 0; - doubletime = now - last_payment; } + rate_per_sec = loan.l_irate / ((double)loan.l_ldur * SECS_PER_DAY * 100.0); diff --git a/src/lib/commands/shark.c b/src/lib/commands/shark.c index b9827a8f..9f0adf22 100644 --- a/src/lib/commands/shark.c +++ b/src/lib/commands/shark.c @@ -55,8 +55,6 @@ shark(void) struct lonstr loan; struct natstr *natp; struct natstr *oldie; - long due; - long last; long rdur; long xdur; double rate; @@ -85,19 +83,21 @@ shark(void) } /* If we got here, we check to see if it's been defaulted on. */ (void)time(&now); - due = loan.l_duedate; - if (now <= due) { + /* + * split duration now - l_lastpay into regular (up to l_duedate) + * and extended (beyond l_duedate) + */ + rdur = loan.l_duedate - loan.l_lastpay; + xdur = now - loan.l_duedate; + if (rdur < 0) { + xdur += rdur; + rdur = 0; + } + if (xdur <= 0) { pr("There has been no default on loan %d\n", arg); return RET_FAIL; } - last = loan.l_lastpay; - if (last < due && due < now) { - rdur = due - last; - xdur = now - due; - } else if (due < last) { - rdur = 0; - xdur = now - last; - } + rate = loan.l_irate / (loan.l_ldur * 8.64e6); owed = ((rdur * rate) + (xdur * rate * 2.0) + 1.0); diff --git a/src/lib/subs/disloan.c b/src/lib/subs/disloan.c index a0b95482..625de08c 100644 --- a/src/lib/subs/disloan.c +++ b/src/lib/subs/disloan.c @@ -54,8 +54,6 @@ int disloan(int n, register struct lonstr *loan) { time_t now; - time_t due; - time_t lastpaydate; time_t normaltime; time_t doubletime; time_t accept; @@ -85,20 +83,18 @@ disloan(int n, register struct lonstr *loan) pr("Loan must be accepted by %s", ctime(&accept)); return 1; } - due = loan->l_duedate; - lastpaydate = loan->l_lastpay; - if (now < due) { - normaltime = now - lastpaydate; - doubletime = 0; - } - if (lastpaydate < due && due < now) { - normaltime = due - lastpaydate; - doubletime = now - due; - } - if (due < lastpaydate) { + + /* + * split duration now - l_lastpay into regular (up to l_duedate) + * and extended (beyond l_duedate) + */ + normaltime = loan->l_duedate - loan->l_lastpay; + doubletime = now - loan->l_duedate; + if (normaltime < 0) { + doubletime += normaltime; normaltime = 0; - doubletime = now - lastpaydate; } + rate = ((double)loan->l_irate / 100.0) / (loan->l_ldur * SECS_PER_DAY); owe = ((double)loan->l_amtdue * (((double)normaltime * rate + 1.0) + @@ -107,7 +103,7 @@ disloan(int n, register struct lonstr *loan) pr("Amount due (if paid now) $%.2f", owe); if (doubletime == 0) { pr(" (if paid on due date) $%.2f\n", - loan->l_amtdue * ((due - lastpaydate) * rate + 1.0)); + loan->l_amtdue * ((loan->l_duedate - loan->l_lastpay) * rate + 1.0)); pr("Due date is %s", ctime(&loan->l_duedate)); } else pr(" ** In Arrears **\n");