home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1998 May / Pcwk5b98.iso / WEBSERVE / SAMBAR / DATA.1 / finance.c < prev    next >
C/C++ Source or Header  |  1997-04-27  |  14KB  |  642 lines

  1. /*
  2. ** FINANCE
  3. **
  4. **      HTTP Wrapper for the Financial Tools
  5. **
  6. **        Confidential Property of Tod Sambar
  7. **        (c) Copyright Tod Sambar 1996
  8. **        All rights reserved.
  9. **
  10. **
  11. ** Public Functions:
  12. **
  13. **        finance_init
  14. **
  15. **
  16. ** History:
  17. ** Chg#    Date    Description                                                Resp
  18. ** ----    -------    -------------------------------------------------------    ----
  19. **         6SEP96    Created                                                    sambar
  20. */
  21.  
  22. #include    <stdio.h>
  23. #include    <memory.h>
  24. #include    <string.h>
  25. #include    <stdlib.h>
  26. #include    <math.h>
  27. #include    <finance.h>
  28.  
  29. /*
  30. ** Finance RPC Commands
  31. */
  32. typedef struct finance__rpcs
  33. {
  34.     SA_CHAR        *name;
  35.     SA_INT        auth;
  36.     SA_VOID        *func;
  37.     SA_CHAR        *descr;
  38. } FINANCE__RPCS;
  39.  
  40. static FINANCE__RPCS     finance_rpcs [] =
  41. {
  42.     { "amorcalc",        SA_AUTHORIZATION_ALL,    (SA_VOID *)finance_amorcalc,
  43.       "Amortization schedule calculation." },
  44.     { "fvmdcalc",        SA_AUTHORIZATION_ALL,    (SA_VOID *)finance_fvmdcalc,
  45.       "Future value of monthly deposit calculator." },
  46.     { "fvpscalc",        SA_AUTHORIZATION_ALL,    (SA_VOID *)finance_fvpscalc,
  47.       "Future value of present sum calculator." },
  48.     { "mortcalc",        SA_AUTHORIZATION_ALL,    (SA_VOID *)finance_mortcalc,
  49.       "Mortgage calculator." },
  50.     { "ratecalc",        SA_AUTHORIZATION_ALL,    (SA_VOID *)finance_ratecalc,
  51.       "Interest rate calculator." }
  52. };
  53.  
  54. /*
  55. **  FINANCE_INIT
  56. **
  57. **    Initialize the Financial Tools calculators.
  58. **
  59. **  Parameters:
  60. **    sactx        Sambar Server context
  61. **
  62. **  Returns:
  63. **    SA_SUCCEED | SA_FAIL
  64. */
  65. SA_RETCODE SA_PUBLIC
  66. finance_init(sactx)
  67. SA_CTX        *sactx;
  68. {
  69.     int            i;
  70.  
  71.     /* Register the Finance RPCs with the application                    */
  72.     for (i = 0; i < sizeof(finance_rpcs) / sizeof(FINANCE__RPCS); i++)
  73.     {
  74.         if (sa_cmd_init(sactx, finance_rpcs[i].name, finance_rpcs[i].auth,
  75.             finance_rpcs[i].descr, (SA_RPCFUNC)finance_rpcs[i].func) 
  76.             != SA_SUCCEED)
  77.         {
  78.             sa_log(sactx, "Unable to initialize Finance RPCs");
  79.             return (SA_FAIL);
  80.         }
  81.     } 
  82.  
  83.     sa_log(sactx, "Finance Library Initialized");
  84.  
  85.     return (SA_SUCCEED);
  86. }
  87.  
  88. /*
  89. **  FINANCE_FVPSCALC
  90. **
  91. **    Future value of present sum calculator.
  92. **
  93. **  Parameters:
  94. **    sactx        Sambar Server context
  95. **    saconn        Sambar Server connection
  96. **    saparams    RPC Parameters
  97. **    infop        Error parameters
  98. **
  99. **  Returns:
  100. **    SA_SUCCEED | SA_FAIL
  101. */
  102. SA_RETCODE SA_PUBLIC
  103. finance_fvpscalc(sactx, saconn, saparams, infop)
  104. SA_CTX        *sactx;
  105. SA_CONN        *saconn;
  106. SA_PARAMS    *saparams;
  107. SA_INT        *infop;
  108. {
  109.     SA_INT        i;
  110.     SA_INT        periods;
  111.     SA_INT        numperiods;
  112.     SA_INT        datalen;
  113.     double        pressum;
  114.     double        rate;
  115.     double        tmp1;
  116.     double        tmp2;
  117.     double        fvps;
  118.     SA_CHAR        *data;
  119.     SA_CHAR        buffer[256];
  120.  
  121.     /* Get the present sum                                                */
  122.     if ((sa_param(sactx, saparams, "sum", &data, &datalen) != SA_SUCCEED) ||
  123.         (datalen == 0))
  124.     {
  125.         *infop = SA_E_INVALIDDATA;
  126.         return (SA_FAIL);
  127.     }
  128.  
  129.     pressum = atof(data);
  130.  
  131.     /* Get the annual interest rate                                     */
  132.     if ((sa_param(sactx, saparams, "rate", &data, &datalen) != SA_SUCCEED) ||
  133.         (datalen == 0))
  134.     {
  135.         *infop = SA_E_INVALIDDATA;
  136.         return (SA_FAIL);
  137.     }
  138.  
  139.     rate = atof(data);
  140.  
  141.     /* Get the number of periods per year                                */
  142.     if ((sa_param(sactx, saparams, "periods", &data, &datalen) != SA_SUCCEED) ||
  143.         (datalen == 0))
  144.     {
  145.         *infop = SA_E_INVALIDDATA;
  146.         return (SA_FAIL);
  147.     }
  148.  
  149.     periods = atoi(data);
  150.  
  151.     /* Get the number of periods to maturity                            */
  152.     if ((sa_param(sactx, saparams, "numperiods", &data, &datalen) 
  153.         != SA_SUCCEED) || (datalen == 0))
  154.     {
  155.         *infop = SA_E_INVALIDDATA;
  156.         return (SA_FAIL);
  157.     }
  158.  
  159.     numperiods = atoi(data);
  160.  
  161.     if ((pressum <= 0) || (rate <= 0) || (periods <= 0) || (numperiods <= 0))
  162.     {
  163.         *infop = SA_E_INVALIDDATA;
  164.         return (SA_FAIL);
  165.     }
  166.  
  167.     tmp1 = 1.0 + ((rate / (float)periods) / 100);
  168.     tmp2 = tmp1;
  169.     if (numperiods != 1)
  170.     {
  171.         for (i = 1; i < numperiods - 1; i++)
  172.         {
  173.             tmp1 = tmp1 * tmp2;
  174.         }
  175.     }
  176.  
  177.     fvps = pressum * tmp1;
  178.  
  179.     if (sa_send_macro(saconn, "FINANCE_FVPSCALC") != SA_SUCCEED)
  180.         return (SA_FAIL);
  181.  
  182.     sprintf(buffer, "$%11.2f\n", fvps);
  183.     if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
  184.         return (SA_FAIL);
  185.  
  186.     if (sa_send_macro(saconn, "FINANCE_FOOTER") != SA_SUCCEED)
  187.         return (SA_FAIL);
  188.  
  189.     return (SA_SUCCEED);
  190. }
  191.  
  192. /*
  193. **  FINANCE_AMORCALC
  194. **
  195. **    Amortization schedule calculator.
  196. **
  197. **  Parameters:
  198. **    sactx        Sambar Server context
  199. **    saconn        Sambar Server connection
  200. **    saparams    RPC Parameters
  201. **    infop        Error parameters
  202. **
  203. **  Returns:
  204. **    SA_SUCCEED | SA_FAIL
  205. */
  206. SA_RETCODE SA_PUBLIC
  207. finance_amorcalc(sactx, saconn, saparams, infop)
  208. SA_CTX        *sactx;
  209. SA_CONN        *saconn;
  210. SA_PARAMS    *saparams;
  211. SA_INT        *infop;
  212. {
  213.     SA_INT        i;
  214.     SA_INT        months;
  215.     SA_INT        start;
  216.     SA_INT        year;
  217.     SA_INT        datalen;
  218.     double        price;
  219.     double        rate;
  220.     double        payment;
  221.     double        tmp1;
  222.     double        tmp2;
  223.     double        at;
  224.     double        ay;
  225.     SA_CHAR        *data;
  226.     SA_CHAR        buffer[256];
  227.  
  228.     /* Get the principle amount                                         */
  229.     if ((sa_param(sactx, saparams, "price", &data, &datalen) != SA_SUCCEED) ||
  230.         (datalen == 0))
  231.     {
  232.         *infop = SA_E_INVALIDDATA;
  233.         return (SA_FAIL);
  234.     }
  235.  
  236.     price = atof(data);
  237.  
  238.     /* Get the number of months in the loan                             */
  239.     if ((sa_param(sactx, saparams, "months", &data, &datalen) != SA_SUCCEED)
  240.         || (datalen == 0))
  241.     {
  242.         *infop = SA_E_INVALIDDATA;
  243.         return (SA_FAIL);
  244.     }
  245.  
  246.     months = atoi(data);
  247.  
  248.     /* Get the interest rate                                             */
  249.     if ((sa_param(sactx, saparams, "rate", &data, &datalen) != SA_SUCCEED) ||
  250.         (datalen == 0))
  251.     {
  252.         *infop = SA_E_INVALIDDATA;
  253.         return (SA_FAIL);
  254.     }
  255.  
  256.     rate = atof(data);
  257.  
  258.     /* Get the starting month                                             */
  259.     if ((sa_param(sactx, saparams, "month", &data, &datalen) != SA_SUCCEED) || 
  260.         (datalen == 0))
  261.     {
  262.         *infop = SA_E_INVALIDDATA;
  263.         return (SA_FAIL);
  264.     }
  265.  
  266.     start = atoi(data);
  267.  
  268.     /* Get the starting year                                             */
  269.     if ((sa_param(sactx, saparams, "year", &data, &datalen) != SA_SUCCEED) || 
  270.         (datalen == 0))
  271.     {
  272.         *infop = SA_E_INVALIDDATA;
  273.         return (SA_FAIL);
  274.     }
  275.  
  276.     year = atoi(data);
  277.  
  278.     if ((price <= 0) || (months <= 0) || (rate <= 0) || (start <= 0) ||
  279.         (year <= 0))
  280.     {
  281.         *infop = SA_E_INVALIDDATA;
  282.         return (SA_FAIL);
  283.     }
  284.  
  285.     if (sa_send_macro(saconn, "FINANCE_AMORCALC") != SA_SUCCEED)
  286.         return (SA_FAIL);
  287.  
  288.     start--;
  289.     year--;
  290.  
  291.     tmp1 = rate / 1200.0;
  292.     tmp2 = 1.0 - (1.0 / pow((float)(tmp1+1), (float)months));
  293.     payment = price * tmp1 / tmp2;
  294.  
  295.     at = ay = 0.0;
  296.     for (i = 0; i < months; i++)
  297.     {
  298.         if (start >= 12)
  299.         {
  300.             year++;
  301.             at += ay;
  302.             sprintf(buffer, 
  303.                 "<I>Total Interest for paid during %d:</I> $%11.2f<BR>\n",
  304.                 year, ay);
  305.             if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
  306.                 return (SA_FAIL);
  307.  
  308.             ay = 0.0;
  309.             start = 0;
  310.         }
  311.  
  312.         ay = ay + (price * tmp1);
  313.         price = price - (payment - (price * tmp1));
  314.  
  315.         if (price > 0.0)
  316.             start++;
  317.         else
  318.             break;
  319.     }
  320.  
  321.     if (start > 0)
  322.     {
  323.         at += ay;
  324.         sprintf(buffer, "<I>Total Interest paid during %d:</I> $%11.2f<BR>\n",
  325.                 year, ay);
  326.         if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
  327.             return (SA_FAIL);
  328.     }
  329.  
  330.     sprintf(buffer, 
  331.         "<BR><B><I>Total Interest paid during loan:</B></I> $%11.2f<BR>\n",
  332.         at);
  333.     if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
  334.         return (SA_FAIL);
  335.  
  336.     if (sa_send_macro(saconn, "FINANCE_FOOTER") != SA_SUCCEED)
  337.         return (SA_FAIL);
  338.  
  339.     return (SA_SUCCEED);
  340. }
  341.  
  342. /*
  343. **  FINANCE_RATECALC
  344. **
  345. **    Interest rate calculator.
  346. **
  347. **  Parameters:
  348. **    sactx        Sambar Server context
  349. **    saconn        Sambar Server connection
  350. **    saparams    RPC Parameters
  351. **    infop        Error parameters
  352. **
  353. **  Returns:
  354. **    SA_SUCCEED | SA_FAIL
  355. */
  356. SA_RETCODE SA_PUBLIC
  357. finance_ratecalc(sactx, saconn, saparams, infop)
  358. SA_CTX        *sactx;
  359. SA_CONN        *saconn;
  360. SA_PARAMS    *saparams;
  361. SA_INT        *infop;
  362. {
  363.     SA_INT        i;
  364.     SA_INT        terms;
  365.     SA_INT        periods;
  366.     SA_INT        datalen;
  367.     double        price;
  368.     double        payment;
  369.     double        tmp1;
  370.     double        tmp2;
  371.     double        rate;
  372.     SA_CHAR        *data;
  373.     SA_CHAR        buffer[256];
  374.  
  375.     /* Get the principal value of the load                                 */
  376.     if ((sa_param(sactx, saparams, "price", &data, &datalen) != SA_SUCCEED) ||
  377.         (datalen == 0))
  378.     {
  379.         *infop = SA_E_INVALIDDATA;
  380.         return (SA_FAIL);
  381.     }
  382.  
  383.     price = atof(data);
  384.  
  385.     /* Get the number of terms per year                                 */
  386.     if ((sa_param(sactx, saparams, "terms", &data, &datalen) != SA_SUCCEED)
  387.         || (datalen == 0))
  388.     {
  389.         *infop = SA_E_INVALIDDATA;
  390.         return (SA_FAIL);
  391.     }
  392.  
  393.     terms = atoi(data);
  394.  
  395.     /* Get the number of periods of the load                             */
  396.     if ((sa_param(sactx, saparams, "periods", &data, &datalen) != SA_SUCCEED) ||
  397.         (datalen == 0))
  398.     {
  399.         *infop = SA_E_INVALIDDATA;
  400.         return (SA_FAIL);
  401.     }
  402.  
  403.     periods = atoi(data);
  404.  
  405.     /* Get the amount of each payment                                     */
  406.     if ((sa_param(sactx, saparams, "payment", &data, &datalen) != SA_SUCCEED) || 
  407.         (datalen == 0))
  408.     {
  409.         *infop = SA_E_INVALIDDATA;
  410.         return (SA_FAIL);
  411.     }
  412.  
  413.     payment = atof(data);
  414.  
  415.     if ((price <= 0) || (terms <= 0) || (periods <= 0) || (payment <= 0))
  416.     {
  417.         *infop = SA_E_INVALIDDATA;
  418.         return (SA_FAIL);
  419.     }
  420.  
  421.     tmp1 = 0.008;
  422.     i = 0;
  423.     while (i < 1000000)
  424.     {
  425.         tmp2 = payment / price * pow((float)(tmp1+1), (float)(periods-1)) /
  426.                 pow((float)(tmp1+1), (float)periods);
  427.         if (tmp1 - tmp2 < 0.000001 && tmp1 - tmp2 > -0.000001)
  428.             i = 1000000;
  429.         else
  430.             tmp1 = tmp2;
  431.  
  432.         i++;
  433.     }
  434.  
  435.     rate = tmp2 * terms * 100;
  436.  
  437.     if (sa_send_macro(saconn, "FINANCE_MORTCALC") != SA_SUCCEED)
  438.         return (SA_FAIL);
  439.  
  440.     sprintf(buffer, "%11.4f%%\n", rate);
  441.     if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
  442.         return (SA_FAIL);
  443.  
  444.     if (sa_send_macro(saconn, "FINANCE_FOOTER") != SA_SUCCEED)
  445.         return (SA_FAIL);
  446.  
  447.     return (SA_SUCCEED);
  448. }
  449.  
  450. /*
  451. **  FINANCE_MORTCALC
  452. **
  453. **    Mortgage calculator.
  454. **
  455. **  Parameters:
  456. **    sactx        Sambar Server context
  457. **    saconn        Sambar Server connection
  458. **    saparams    RPC Parameters
  459. **    infop        Error parameters
  460. **
  461. **  Returns:
  462. **    SA_SUCCEED | SA_FAIL
  463. */
  464. SA_RETCODE SA_PUBLIC
  465. finance_mortcalc(sactx, saconn, saparams, infop)
  466. SA_CTX        *sactx;
  467. SA_CONN        *saconn;
  468. SA_PARAMS    *saparams;
  469. SA_INT        *infop;
  470. {
  471.     SA_INT        years;
  472.     SA_INT        datalen;
  473.     double        price;
  474.     double        down;
  475.     double        rate;
  476.     double        tmp1;
  477.     double        mort;
  478.     SA_CHAR        *data;
  479.     SA_CHAR        buffer[256];
  480.  
  481.     /* Get the sale price of the house                                     */
  482.     if ((sa_param(sactx, saparams, "price", &data, &datalen) != SA_SUCCEED) ||
  483.         (datalen == 0))
  484.     {
  485.         *infop = SA_E_INVALIDDATA;
  486.         return (SA_FAIL);
  487.     }
  488.  
  489.     price = atof(data);
  490.  
  491.     /* Get the down payment amount                                         */
  492.     if ((sa_param(sactx, saparams, "down", &data, &datalen) != SA_SUCCEED)
  493.         || (datalen == 0))
  494.     {
  495.         *infop = SA_E_INVALIDDATA;
  496.         return (SA_FAIL);
  497.     }
  498.  
  499.     down = atof(data);
  500.  
  501.     /* Get the number of years to pay off the mortgage                     */
  502.     if ((sa_param(sactx, saparams, "years", &data, &datalen) != SA_SUCCEED) ||
  503.         (datalen == 0))
  504.     {
  505.         *infop = SA_E_INVALIDDATA;
  506.         return (SA_FAIL);
  507.     }
  508.  
  509.     years = atoi(data);
  510.  
  511.     /* Get the interest rate                                             */
  512.     if ((sa_param(sactx, saparams, "rate", &data, &datalen) != SA_SUCCEED) || 
  513.         (datalen == 0))
  514.     {
  515.         *infop = SA_E_INVALIDDATA;
  516.         return (SA_FAIL);
  517.     }
  518.  
  519.     rate = atof(data);
  520.  
  521.     if ((price <= 0) || (down <= 0) || (years <= 0) || (rate <= 0) ||
  522.         (down > price))
  523.     {
  524.         *infop = SA_E_INVALIDDATA;
  525.         return (SA_FAIL);
  526.     }
  527.  
  528.     tmp1 = rate / (12 * 100);
  529.     mort = (price - down) * (tmp1 / (1 - pow(1 + tmp1, - (years * 12))));
  530.  
  531.     if (sa_send_macro(saconn, "FINANCE_MORTCALC") != SA_SUCCEED)
  532.         return (SA_FAIL);
  533.  
  534.     sprintf(buffer, "$%11.2f\n", mort);
  535.     if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
  536.         return (SA_FAIL);
  537.  
  538.     if (sa_send_macro(saconn, "FINANCE_FOOTER") != SA_SUCCEED)
  539.         return (SA_FAIL);
  540.  
  541.     return (SA_SUCCEED);
  542. }
  543.  
  544. /*
  545. **  FINANCE_FVMDCALC
  546. **
  547. **    Future value of monthly deposit calculator.
  548. **
  549. **  Parameters:
  550. **    sactx        Sambar Server context
  551. **    saconn        Sambar Server connection
  552. **    saparams    RPC Parameters
  553. **    infop        Error parameters
  554. **
  555. **  Returns:
  556. **    SA_SUCCEED | SA_FAIL
  557. */
  558. SA_RETCODE SA_PUBLIC
  559. finance_fvmdcalc(sactx, saconn, saparams, infop)
  560. SA_CTX        *sactx;
  561. SA_CONN        *saconn;
  562. SA_PARAMS    *saparams;
  563. SA_INT        *infop;
  564. {
  565.     SA_INT        deposits;
  566.     SA_INT        months;
  567.     SA_INT        years;
  568.     SA_INT        datalen;
  569.     double        amount;
  570.     double        rate;
  571.     double        tmp1;
  572.     double        tmp2;
  573.     double        fvmd;
  574.     SA_CHAR        *data;
  575.     SA_CHAR        buffer[256];
  576.  
  577.     /* Get the regular amount of deposit                                */
  578.     if ((sa_param(sactx, saparams, "amount", &data, &datalen) != SA_SUCCEED) ||
  579.         (datalen == 0))
  580.     {
  581.         *infop = SA_E_INVALIDDATA;
  582.         return (SA_FAIL);
  583.     }
  584.  
  585.     amount = atof(data);
  586.  
  587.     /* Get the number of deposits per year                                 */
  588.     if ((sa_param(sactx, saparams, "deposits", &data, &datalen) 
  589.         != SA_SUCCEED) || (datalen == 0))
  590.     {
  591.         *infop = SA_E_INVALIDDATA;
  592.         return (SA_FAIL);
  593.     }
  594.  
  595.     deposits = atoi(data);
  596.  
  597.     /* Get the total months                                             */
  598.     if ((sa_param(sactx, saparams, "months", &data, &datalen) != SA_SUCCEED) ||
  599.         (datalen == 0))
  600.     {
  601.         *infop = SA_E_INVALIDDATA;
  602.         return (SA_FAIL);
  603.     }
  604.  
  605.     months = atoi(data);
  606.  
  607.     /* Get the nominal interest rate                                     */
  608.     if ((sa_param(sactx, saparams, "rate", &data, &datalen) != SA_SUCCEED) || 
  609.         (datalen == 0))
  610.     {
  611.         *infop = SA_E_INVALIDDATA;
  612.         return (SA_FAIL);
  613.     }
  614.  
  615.     rate = atof(data);
  616.  
  617.     if ((amount <= 0) || (rate <= 0) || (deposits <= 0) || (months <= 0))
  618.     {
  619.         *infop = SA_E_INVALIDDATA;
  620.         return (SA_FAIL);
  621.     }
  622.  
  623.     years = months / 12;
  624.     tmp1 = rate / (float)deposits / 100.0;
  625.     tmp2 = pow((float)(1+tmp1), (float)(deposits * years));
  626.     tmp2--;
  627.     tmp2 /= tmp1;
  628.     fvmd = amount * tmp2;
  629.  
  630.     if (sa_send_macro(saconn, "FINANCE_FVMDCALC") != SA_SUCCEED)
  631.         return (SA_FAIL);
  632.  
  633.     sprintf(buffer, "$%11.2f\n", fvmd);
  634.     if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
  635.         return (SA_FAIL);
  636.  
  637.     if (sa_send_macro(saconn, "FINANCE_FOOTER") != SA_SUCCEED)
  638.         return (SA_FAIL);
  639.  
  640.     return (SA_SUCCEED);
  641. }
  642.