home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World 2001 January
/
PCWorld_2001-01_cd.bin
/
Software
/
Topware
/
sambar
/
_SETUP.1
/
finance.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-06-05
|
16KB
|
688 lines
/*
** FINANCE
**
** HTTP Wrapper for the Financial Tools
**
** Confidential Property of Tod Sambar
** (c) Copyright Tod Sambar 1996
** All rights reserved.
**
**
** Public Functions:
**
** finance_init
**
**
** History:
** Chg# Date Description Resp
** ---- ------- ------------------------------------------------------- ----
** 6SEP96 Created sambar
*/
#include <stdio.h>
#include <memory.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <finance.h>
/*
** Finance RPC Commands
*/
typedef struct finance__rpcs
{
SA_CHAR *name;
SA_RPCPARAM *params;
SA_INT numparams;
SA_INT auth;
SA_VOID *func;
SA_CHAR *descr;
} FINANCE__RPCS;
static SA_RPCPARAM amorcalcp [] =
{
{ "price", 1, "The price of the property." },
{ "months", 1, "The number of month of sthe load." },
{ "rate", 1, "The rate of the loan." },
{ "month", 1, "The starting month of the loan." },
{ "year", 1, "The starting year of the loan." }
};
static SA_RPCPARAM fvmdcalcp [] =
{
{ "amount", 1, "The regular amount of deposit." },
{ "deposits", 1, "The number of deposits per year." },
{ "months", 1, "The total number of months." },
{ "rate", 1, "The normal interest rate." }
};
static SA_RPCPARAM fvpscalcp [] =
{
{ "sum", 1, "The present sum to be calculated." },
{ "rate", 1, "The annual interest rate." },
{ "periods", 1, "The number of periods per year." },
{ "periods", 1, "The number of periods to maturity." }
};
static SA_RPCPARAM mortcalcp [] =
{
{ "price", 1, "The sale price of the home." },
{ "down", 1, "The down payment amount." },
{ "years", 1, "The number of years to pay off the mortgage." },
{ "rate", 1, "The interest rate." }
};
static SA_RPCPARAM ratecalcp [] =
{
{ "price", 1, "The principal value of the loan." },
{ "terms", 1, "The number of terms per year." },
{ "periods", 1, "The number of periods of the loan." },
{ "payment", 1, "The amount of each payment." }
};
static FINANCE__RPCS finance_rpcs [] =
{
{ "amorcalc", amorcalcp, sizeof(amorcalcp) / sizeof(SA_RPCPARAM),
SA_AUTHORIZATION_ALL, (SA_VOID *)finance_amorcalc,
"Amortization schedule calculation." },
{ "fvmdcalc", fvmdcalcp, sizeof(fvmdcalcp) / sizeof(SA_RPCPARAM),
SA_AUTHORIZATION_ALL, (SA_VOID *)finance_fvmdcalc,
"Future value of monthly deposit calculator." },
{ "fvpscalc", fvpscalcp, sizeof(fvpscalcp) / sizeof(SA_RPCPARAM),
SA_AUTHORIZATION_ALL, (SA_VOID *)finance_fvpscalc,
"Future value of present sum calculator." },
{ "mortcalc", mortcalcp, sizeof(mortcalcp) / sizeof(SA_RPCPARAM),
SA_AUTHORIZATION_ALL, (SA_VOID *)finance_mortcalc,
"Mortgage calculator." },
{ "ratecalc", ratecalcp, sizeof(ratecalcp) / sizeof(SA_RPCPARAM),
SA_AUTHORIZATION_ALL, (SA_VOID *)finance_ratecalc,
"Interest rate calculator." }
};
/*
** FINANCE_INIT
**
** Initialize the Financial Tools calculators.
**
** Parameters:
** sactx Sambar Server context
**
** Returns:
** SA_SUCCEED | SA_FAIL
*/
SA_RETCODE SA_PUBLIC
finance_init(sactx)
SA_CTX *sactx;
{
int i;
/* Register the Finance RPCs with the application */
for (i = 0; i < sizeof(finance_rpcs) / sizeof(FINANCE__RPCS); i++)
{
if (sa_cmd_init(sactx, finance_rpcs[i].name,
finance_rpcs[i].params, finance_rpcs[i].numparams,
finance_rpcs[i].auth, finance_rpcs[i].descr,
(SA_RPCFUNC)finance_rpcs[i].func) != SA_SUCCEED)
{
sa_log(sactx, "Unable to initialize Finance RPCs");
return (SA_FAIL);
}
}
sa_log(sactx, "Finance Library Initialized");
return (SA_SUCCEED);
}
/*
** FINANCE_FVPSCALC
**
** Future value of present sum calculator.
**
** Parameters:
** sactx Sambar Server context
** saconn Sambar Server connection
** saparams RPC Parameters
** infop Error parameters
**
** Returns:
** SA_SUCCEED | SA_FAIL
*/
SA_RETCODE SA_PUBLIC
finance_fvpscalc(sactx, saconn, saparams, infop)
SA_CTX *sactx;
SA_CONN *saconn;
SA_PARAMS *saparams;
SA_INT *infop;
{
SA_INT i;
SA_INT periods;
SA_INT numperiods;
SA_INT datalen;
double pressum;
double rate;
double tmp1;
double tmp2;
double fvps;
SA_CHAR *data;
SA_CHAR buffer[256];
/* Get the present sum */
if ((sa_param(sactx, saparams, "sum", &data, &datalen) != SA_SUCCEED)
|| (datalen == 0) || (datalen > 32))
{
*infop = SA_E_INVALIDDATA;
return (SA_FAIL);
}
pressum = atof(data);
/* Get the annual interest rate */
if ((sa_param(sactx, saparams, "rate", &data, &datalen) != SA_SUCCEED)
|| (datalen == 0) || (datalen > 32))
{
*infop = SA_E_INVALIDDATA;
return (SA_FAIL);
}
rate = atof(data);
/* Get the number of periods per year */
if ((sa_param(sactx, saparams, "periods", &data, &datalen) != SA_SUCCEED)
|| (datalen == 0) || (datalen > 32))
{
*infop = SA_E_INVALIDDATA;
return (SA_FAIL);
}
periods = atoi(data);
/* Get the number of periods to maturity */
if ((sa_param(sactx, saparams, "numperiods", &data, &datalen) != SA_SUCCEED)
|| (datalen == 0) || (datalen > 32))
{
*infop = SA_E_INVALIDDATA;
return (SA_FAIL);
}
numperiods = atoi(data);
if ((pressum <= 0) || (rate <= 0) || (periods <= 0) || (numperiods <= 0))
{
*infop = SA_E_INVALIDDATA;
return (SA_FAIL);
}
tmp1 = 1.0 + ((rate / (float)periods) / 100);
tmp2 = tmp1;
if (numperiods != 1)
{
for (i = 1; i < numperiods - 1; i++)
{
tmp1 = tmp1 * tmp2;
}
}
fvps = pressum * tmp1;
if (sa_send_macro(saconn, "FINANCE_FVPSCALC") != SA_SUCCEED)
return (SA_FAIL);
sprintf(buffer, "$%11.2f\n", fvps);
if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
return (SA_FAIL);
if (sa_send_macro(saconn, "FINANCE_FOOTER") != SA_SUCCEED)
return (SA_FAIL);
return (SA_SUCCEED);
}
/*
** FINANCE_AMORCALC
**
** Amortization schedule calculator.
**
** Parameters:
** sactx Sambar Server context
** saconn Sambar Server connection
** saparams RPC Parameters
** infop Error parameters
**
** Returns:
** SA_SUCCEED | SA_FAIL
*/
SA_RETCODE SA_PUBLIC
finance_amorcalc(sactx, saconn, saparams, infop)
SA_CTX *sactx;
SA_CONN *saconn;
SA_PARAMS *saparams;
SA_INT *infop;
{
SA_INT i;
SA_INT months;
SA_INT start;
SA_INT year;
SA_INT datalen;
double price;
double rate;
double payment;
double tmp1;
double tmp2;
double at;
double ay;
SA_CHAR *data;
SA_CHAR buffer[256];
/* Get the principle amount */
if ((sa_param(sactx, saparams, "price", &data, &datalen) != SA_SUCCEED)
|| (datalen == 0) || (datalen > 32))
{
*infop = SA_E_INVALIDDATA;
return (SA_FAIL);
}
price = atof(data);
/* Get the number of months in the loan */
if ((sa_param(sactx, saparams, "months", &data, &datalen) != SA_SUCCEED)
|| (datalen == 0) || (datalen > 32))
{
*infop = SA_E_INVALIDDATA;
return (SA_FAIL);
}
months = atoi(data);
/* Get the interest rate */
if ((sa_param(sactx, saparams, "rate", &data, &datalen) != SA_SUCCEED)
|| (datalen == 0) || (datalen > 32))
{
*infop = SA_E_INVALIDDATA;
return (SA_FAIL);
}
rate = atof(data);
/* Get the starting month */
if ((sa_param(sactx, saparams, "month", &data, &datalen) != SA_SUCCEED)
|| (datalen == 0) || (datalen > 32))
{
*infop = SA_E_INVALIDDATA;
return (SA_FAIL);
}
start = atoi(data);
/* Get the starting year */
if ((sa_param(sactx, saparams, "year", &data, &datalen) != SA_SUCCEED)
|| (datalen == 0) || (datalen > 32))
{
*infop = SA_E_INVALIDDATA;
return (SA_FAIL);
}
year = atoi(data);
if ((price <= 0) || (months <= 0) || (rate <= 0) || (start <= 0) ||
(year <= 0))
{
*infop = SA_E_INVALIDDATA;
return (SA_FAIL);
}
if (sa_send_macro(saconn, "FINANCE_AMORCALC") != SA_SUCCEED)
return (SA_FAIL);
start--;
year--;
tmp1 = rate / 1200.0;
tmp2 = 1.0 - (1.0 / pow((float)(tmp1+1), (float)months));
payment = price * tmp1 / tmp2;
at = ay = 0.0;
for (i = 0; i < months; i++)
{
if (start >= 12)
{
year++;
at += ay;
sprintf(buffer,
"<I>Total Interest for paid during %ld:</I> $%11.2f<BR>\n",
year, ay);
if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
return (SA_FAIL);
ay = 0.0;
start = 0;
}
ay = ay + (price * tmp1);
price = price - (payment - (price * tmp1));
if (price > 0.0)
start++;
else
break;
}
if (start > 0)
{
at += ay;
sprintf(buffer, "<I>Total Interest paid during %ld:</I> $%11.2f<BR>\n",
year, ay);
if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
return (SA_FAIL);
}
sprintf(buffer,
"<BR><B><I>Total Interest paid during loan:</B></I> $%11.2f<BR>\n",
at);
if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
return (SA_FAIL);
if (sa_send_macro(saconn, "FINANCE_FOOTER") != SA_SUCCEED)
return (SA_FAIL);
return (SA_SUCCEED);
}
/*
** FINANCE_RATECALC
**
** Interest rate calculator.
**
** Parameters:
** sactx Sambar Server context
** saconn Sambar Server connection
** saparams RPC Parameters
** infop Error parameters
**
** Returns:
** SA_SUCCEED | SA_FAIL
*/
SA_RETCODE SA_PUBLIC
finance_ratecalc(sactx, saconn, saparams, infop)
SA_CTX *sactx;
SA_CONN *saconn;
SA_PARAMS *saparams;
SA_INT *infop;
{
SA_INT i;
SA_INT terms;
SA_INT periods;
SA_INT datalen;
double price;
double payment;
double tmp1;
double tmp2;
double rate;
SA_CHAR *data;
SA_CHAR buffer[256];
/* Get the principal value of the loan */
if ((sa_param(sactx, saparams, "price", &data, &datalen) != SA_SUCCEED)
|| (datalen == 0) || (datalen > 32))
{
*infop = SA_E_INVALIDDATA;
return (SA_FAIL);
}
price = atof(data);
/* Get the number of terms per year */
if ((sa_param(sactx, saparams, "terms", &data, &datalen) != SA_SUCCEED)
|| (datalen == 0) || (datalen > 32))
{
*infop = SA_E_INVALIDDATA;
return (SA_FAIL);
}
terms = atoi(data);
/* Get the number of periods of the load */
if ((sa_param(sactx, saparams, "periods", &data, &datalen) != SA_SUCCEED)
|| (datalen == 0) || (datalen > 32))
{
*infop = SA_E_INVALIDDATA;
return (SA_FAIL);
}
periods = atoi(data);
/* Get the amount of each payment */
if ((sa_param(sactx, saparams, "payment", &data, &datalen) != SA_SUCCEED)
|| (datalen == 0) || (datalen > 32))
{
*infop = SA_E_INVALIDDATA;
return (SA_FAIL);
}
payment = atof(data);
if ((price <= 0) || (terms <= 0) || (periods <= 0) || (payment <= 0))
{
*infop = SA_E_INVALIDDATA;
return (SA_FAIL);
}
tmp1 = 0.008;
i = 0;
while (i < 1000000)
{
tmp2 = payment / price * pow((float)(tmp1+1), (float)(periods-1)) /
pow((float)(tmp1+1), (float)periods);
if (tmp1 - tmp2 < 0.000001 && tmp1 - tmp2 > -0.000001)
i = 1000000;
else
tmp1 = tmp2;
i++;
}
rate = tmp2 * terms * 100;
if (sa_send_macro(saconn, "FINANCE_MORTCALC") != SA_SUCCEED)
return (SA_FAIL);
sprintf(buffer, "%11.4f%%\n", rate);
if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
return (SA_FAIL);
if (sa_send_macro(saconn, "FINANCE_FOOTER") != SA_SUCCEED)
return (SA_FAIL);
return (SA_SUCCEED);
}
/*
** FINANCE_MORTCALC
**
** Mortgage calculator.
**
** Parameters:
** sactx Sambar Server context
** saconn Sambar Server connection
** saparams RPC Parameters
** infop Error parameters
**
** Returns:
** SA_SUCCEED | SA_FAIL
*/
SA_RETCODE SA_PUBLIC
finance_mortcalc(sactx, saconn, saparams, infop)
SA_CTX *sactx;
SA_CONN *saconn;
SA_PARAMS *saparams;
SA_INT *infop;
{
SA_INT years;
SA_INT datalen;
double price;
double down;
double rate;
double tmp1;
double mort;
SA_CHAR *data;
SA_CHAR buffer[256];
/* Get the sale price of the house */
if ((sa_param(sactx, saparams, "price", &data, &datalen) != SA_SUCCEED)
|| (datalen == 0) || (datalen > 32))
{
*infop = SA_E_INVALIDDATA;
return (SA_FAIL);
}
price = atof(data);
/* Get the down payment amount */
if ((sa_param(sactx, saparams, "down", &data, &datalen) != SA_SUCCEED)
|| (datalen == 0) || (datalen > 32))
{
*infop = SA_E_INVALIDDATA;
return (SA_FAIL);
}
down = atof(data);
/* Get the number of years to pay off the mortgage */
if ((sa_param(sactx, saparams, "years", &data, &datalen) != SA_SUCCEED)
|| (datalen == 0) || (datalen > 32))
{
*infop = SA_E_INVALIDDATA;
return (SA_FAIL);
}
years = atoi(data);
/* Get the interest rate */
if ((sa_param(sactx, saparams, "rate", &data, &datalen) != SA_SUCCEED)
|| (datalen == 0) || (datalen > 32))
{
*infop = SA_E_INVALIDDATA;
return (SA_FAIL);
}
rate = atof(data);
if ((price <= 0) || (down <= 0) || (years <= 0) || (rate <= 0) ||
(down > price))
{
*infop = SA_E_INVALIDDATA;
return (SA_FAIL);
}
tmp1 = rate / (12 * 100);
mort = (price - down) * (tmp1 / (1 - pow(1 + tmp1, - (years * 12))));
if (sa_send_macro(saconn, "FINANCE_MORTCALC") != SA_SUCCEED)
return (SA_FAIL);
sprintf(buffer, "$%11.2f\n", mort);
if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
return (SA_FAIL);
if (sa_send_macro(saconn, "FINANCE_FOOTER") != SA_SUCCEED)
return (SA_FAIL);
return (SA_SUCCEED);
}
/*
** FINANCE_FVMDCALC
**
** Future value of monthly deposit calculator.
**
** Parameters:
** sactx Sambar Server context
** saconn Sambar Server connection
** saparams RPC Parameters
** infop Error parameters
**
** Returns:
** SA_SUCCEED | SA_FAIL
*/
SA_RETCODE SA_PUBLIC
finance_fvmdcalc(sactx, saconn, saparams, infop)
SA_CTX *sactx;
SA_CONN *saconn;
SA_PARAMS *saparams;
SA_INT *infop;
{
SA_INT deposits;
SA_INT months;
SA_INT years;
SA_INT datalen;
double amount;
double rate;
double tmp1;
double tmp2;
double fvmd;
SA_CHAR *data;
SA_CHAR buffer[256];
/* Get the regular amount of deposit */
if ((sa_param(sactx, saparams, "amount", &data, &datalen) != SA_SUCCEED)
|| (datalen == 0) || (datalen > 32))
{
*infop = SA_E_INVALIDDATA;
return (SA_FAIL);
}
amount = atof(data);
/* Get the number of deposits per year */
if ((sa_param(sactx, saparams, "deposits", &data, &datalen) != SA_SUCCEED)
|| (datalen == 0) || (datalen > 32))
{
*infop = SA_E_INVALIDDATA;
return (SA_FAIL);
}
deposits = atoi(data);
/* Get the total months */
if ((sa_param(sactx, saparams, "months", &data, &datalen) != SA_SUCCEED)
|| (datalen == 0) || (datalen > 32))
{
*infop = SA_E_INVALIDDATA;
return (SA_FAIL);
}
months = atoi(data);
/* Get the nominal interest rate */
if ((sa_param(sactx, saparams, "rate", &data, &datalen) != SA_SUCCEED)
|| (datalen == 0) || (datalen > 32))
{
*infop = SA_E_INVALIDDATA;
return (SA_FAIL);
}
rate = atof(data);
if ((amount <= 0) || (rate <= 0) || (deposits <= 0) || (months <= 0))
{
*infop = SA_E_INVALIDDATA;
return (SA_FAIL);
}
years = months / 12;
tmp1 = rate / (float)deposits / 100.0;
tmp2 = pow((float)(1+tmp1), (float)(deposits * years));
tmp2--;
tmp2 /= tmp1;
fvmd = amount * tmp2;
if (sa_send_macro(saconn, "FINANCE_FVMDCALC") != SA_SUCCEED)
return (SA_FAIL);
sprintf(buffer, "$%11.2f\n", fvmd);
if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
return (SA_FAIL);
if (sa_send_macro(saconn, "FINANCE_FOOTER") != SA_SUCCEED)
return (SA_FAIL);
return (SA_SUCCEED);
}