From telecom@delta.eecs.nwu.edu Wed Nov 27 03:00:16 1991
Received: from delta.eecs.nwu.edu by gaak.LCS.MIT.EDU via TCP with SMTP
	id AA21231; Wed, 27 Nov 91 03:00:07 EST
Received: by delta.eecs.nwu.edu id AA21459
  (5.65c/IDA-1.4.4 for ptownson@gaak.lcs.mit.edu); Wed, 27 Nov 1991 01:59:48 -0600
Date: Wed, 27 Nov 1991 01:59:48 -0600
From: TELECOM Moderator <telecom@delta.eecs.nwu.edu>
Message-Id: <199111270759.AA21459@delta.eecs.nwu.edu>
To: ptownson@gaak.LCS.MIT.EDU
Subject: cost figuring program
Status: RO

>From telecom Mon Nov 25 11:15:33 1991
Received: by delta.eecs.nwu.edu id AA00056
  (5.65c/IDA-1.4.4 for \telecom); Mon, 25 Nov 1991 11:15:24 -0600
Received: from valhalla.ee.rochester.edu by delta.eecs.nwu.edu with SMTP id AA21221
  (5.65c/IDA-1.4.4 for <telecom@eecs.nwu.edu>); Mon, 25 Nov 1991 11:14:56 -0600
Received: from moscom.UUCP by valhalla.ee.rochester.edu with UUCP (4.1/2.5ee) id AA27251; Mon, 25 Nov 91 12:14:17 EST
Received: by moscom.com (4.1/SMI-4.1)
	id AA06031; Mon, 25 Nov 91 11:41:11 EST
Date: Mon, 25 Nov 91 11:41:11 EST
From: lb@moscom.com (Lawrence Beck)
Message-Id: <9111251641.AA06031@moscom.com>
To: telecom@eecs.nwu.edu
Subject: AT&T long distance calling plans
Cc: lb@moscom.com
Status: RO


To anybody interested in this:

The following program will determine the best combination of AT&T long distance
calling plans for you based on previous months' bills (you determine how many
months).   It was designed for Reach Out America/Reach Out New York
combinations, but can be modified to support other AT&T intrastate plans.

Let me know if I let any bugs slip through ...

Larry Beck (lb@moscom.com)




#ifndef lint
static char sccs_ident[] = "@(#)longdist.c	1.1 91/11/25 11:33:55 ";
#endif

/******************************************************************************
**
**	Source File:	longdist.c
**
**	Author:		Lawrence Beck	(lb@moscom.com)
**
**	Creation Date:	11/22/91
**
**	Description:	This file contains a program that calculates the best
**				combination of AT&T calling plans based on past phone
**				bills.  This program was designed to calculate the
**				cost of all direct-dialed long distance calls using all
**				combinations of Reach Out America and Reach Out New York
**				plans.  It prints a matrix of the total cost of all calls
**				using all combinations, and then prints the best
**				combination.
**
**				To use this program, one or more files containing a subset
**				of phone bill information must be specified on the
**				command line.  Each file should contain a month's worth of
**				billing information.  The information should be formatted
**				on separate lines as follows:
**
**				<State>	<Duration>	<Call Type>	<Cost>
**
**				<State> is the 2-letter uppercase state abbreviation.
**				<Duration> is the length of the call in minutes.
**				<Call Type> is DN, DE, or DD for Direct-Night, Direct-
**					Evening, and Direct-Day respectively.
**				<Cost> is the undiscounted cost of the call.
**
**				The rates for Reach Out America and Reach Out New York
**				are specified in two data structures.  They may be
**				modified to accomodate changes in the rate structure or
**				to accomodate a different intrastate calling plan.  If
**				a New York is not the home state, change HOME_STATE to the
**				appropriate 2-letter abbreviation for the desired state.
**
**	
******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define TRUE	1
#define FALSE	0

#define DD	0
#define DE	1
#define DN	2

#define NONE		0
#define BASIC		1
#define EVENING	2
#define _24HOUR	3

#define HOME_STATE	"NY"

char *plan[] = {
	"none",
	"basic",
	"evening",
	"24 hour"
};

struct rate_info {
	double
		initial_hour,
		additional_hours,
		evening_discount,
		day_discount,
		intrastate_discount;
};

struct rate_info interstate_info[] = {
	{	0.00, 0.00, 0.00, 0.00, 0.00 },
	{	7.15, 6.60, 1.00, 1.00, 0.95 },
	{	7.80, 6.60, 0.85, 1.00, 0.95 },
	{	8.70, 6.60, 0.75, 0.90, 0.95 }
};

struct rate_info intrastate_info[] = {
	{	0.00, 0.00, 0.00, 0.00, 0.00 },
	{	7.50, 7.20, 1.00, 1.00, 0.00 },
	{	8.20, 7.20, 0.85, 1.00, 0.00 },
	{	8.50, 7.20, 0.85, 0.95, 0.00 }
};

double
	compute_rates();

main(argc, argv)
int argc;
char **argv;
{
	int
		best_i,
		best_j,
		i,
		j;
	FILE
		*fp;
	double
		plan_totals[4][4],
		best_total=0.;

	/* initialize totals for all plan combinations */
	for(i=NONE; i<=_24HOUR; i++)
		for(j=NONE; j<=_24HOUR; j++)
			plan_totals[i][j] = 0.;

	/* process all command line arguments */
	while (argc > 1) {
		argc--;
		argv++;

		/* open the bill file */
		fp = fopen(*argv, "r");
		if (fp == NULL)
			continue;

		/* compute the total for all plan combinations */
		for(i=NONE; i<=_24HOUR; i++)
			for(j=NONE; j<=_24HOUR; j++) {
				(void)fseek(fp, 0L, 0);
				plan_totals[i][j] += compute_rates(fp, i, j);
			}

		/* close the file */
		(void)fclose(fp);
	}

	/* print the matrix of all plan combination totals (save the best one) */
	(void)printf("%20s%-20s\n", "", "interstate plans");
	(void)printf("%20s%-10s%-10s%-10s%-10s\n", "",
	       plan[0], plan[1], plan[2], plan[3]);
	for(i=NONE; i<=_24HOUR; i++) {
		(void)printf("%-12s%-8s", "intrastate", plan[i]);
		for(j=NONE; j<=_24HOUR; j++) {
			if (best_total == 0 || plan_totals[i][j] < best_total) {
				best_total = plan_totals[i][j];
				best_i = i;
				best_j = j;
			}
			(void)printf("%-10.2f", plan_totals[i][j]);
		}
		(void)printf("\n");
	}

	/* print the best plan combination */
	(void)printf("\nthe best plan combination for these bills is:\n");
	(void)printf("intrastate plan: %s\n", plan[best_i]);
	(void)printf("interstate plan: %s\n", plan[best_j]);

	return(EXIT_SUCCESS);
}

double
compute_rates(fp, intrastate_plan, interstate_plan)
FILE *fp;
int intrastate_plan;
int interstate_plan;
{
	int
		i,
		intrastate_duration[3],
		interstate_duration[3],
		period,
		duration;
	double
		intrastate_cost[3],
		interstate_cost[3],
		total_cost,
		cost;
	char
		input[80],
		state[3],
		calltype[3];

	/* initialize the durations and costs for all call types */
	for(i=0; i < 3; i++) {
		intrastate_duration[i] = 0;
		interstate_duration[i] = 0;
		intrastate_cost[i] = 0.;
		interstate_cost[i] = 0.;
	}

	/* read all lines from the bill file */
	while (fgets(input, sizeof(input), fp) != NULL) {

		/* extract the billing information from the input line */
		(void)sscanf(input, "%s %d %s %lf",
		             state, &duration, calltype, &cost);

		/* determine the period */
		if (strcmp(calltype, "DD") == 0)
			period = DD;
		else if (strcmp(calltype, "DE") == 0)
			period = DE;
		else if (strcmp(calltype, "DN") == 0)
			period = DN;
		else
			continue;

		/* if the call is intrastate ... */
		if (strcmp(state, HOME_STATE) == 0) {
			intrastate_cost[period] += cost;
			intrastate_duration[period] += duration;
		}
		/* else if the call is interstate ... */
		else {
			interstate_cost[period] += cost;
			interstate_duration[period] += duration;
		}
	}

	/* if using Reach Out America ... */
	if (interstate_plan != NONE) {

		/* calculate the night period cost */
		interstate_cost[DN] = interstate_info[interstate_plan].initial_hour;

		interstate_duration[DN] -= 60;
		if (interstate_duration[DN] > 0)
			interstate_cost[DN] +=
				interstate_info[interstate_plan].additional_hours *
				(double)interstate_duration[DN]/60.;

		/* calculate the other period costs */
		interstate_cost[DE] *=
			interstate_info[interstate_plan].evening_discount;
		interstate_cost[DD] *=
			interstate_info[interstate_plan].day_discount;

		/* apply intrastate discount, if no intrastate plan */
		if (intrastate_plan == NONE) {
			intrastate_cost[DD] *=
				interstate_info[interstate_plan].intrastate_discount;
			intrastate_cost[DE] *=
				interstate_info[interstate_plan].intrastate_discount;
			intrastate_cost[DN] *=
				interstate_info[interstate_plan].intrastate_discount;
		}
	}

	/* if using Reach Out <Your State> ... */
	if (intrastate_plan != NONE) {

		/* calculate the night period cost */
		intrastate_cost[DN] = intrastate_info[intrastate_plan].initial_hour;

		intrastate_duration[DN] -= 60;
		if (intrastate_duration[DN] > 0)
			intrastate_cost[DN] +=
				intrastate_info[intrastate_plan].additional_hours *
				(double)intrastate_duration[DN]/60.;

		/* calculate the other period costs */
		intrastate_cost[DE] *=
			intrastate_info[intrastate_plan].evening_discount;
		intrastate_cost[DD] *=
			intrastate_info[intrastate_plan].day_discount;
	}

	/* return the total cost */
	total_cost =	interstate_cost[DN] +
				interstate_cost[DE] +
				interstate_cost[DD] +
				intrastate_cost[DN] +
				intrastate_cost[DE] +
				intrastate_cost[DD];

	return(total_cost);
}


