DQA: A Software Tool for Analyzing

Data Quality in Data Manufacturing Systems

June 1993 TDQM-93-10

Sung Jun Pak

Alicia Pando

Total Data Quality Management (TDQM) Research Program

Room E53-320, Sloan School of Management

Massachusetts Institute of Technlogy

Cambridge, MA 02139 USA

Tel: 617-253-2656

Fax: 617-253-3321










© 1993 Sung Pak and Alicia Pando

Acknowledgments Work reported herein has been supported, in part, by MIT's Total Data Quality Management (TDQM) Research Program, MIT's International Financial Services Research Center (IFSRC), Fujitsu Personal Systems, Inc. and Bull-HN.

DQA: A Software Tool for Analyzing

Data Quality in Data Manufacturing Systems

1. Introduction

ABSTRACT DQA (Data Quality Analyzer) is a software tool capable of designing and analyzing data manufacturing systems. It is based on functional specifications developed by Professor Don Ballou, Professor Harold Pazer, and G.T. Tayi of the State University of New York in Albany and Professor Richard Wang of the M.I.T. The business community's interest in improving data processing systems has grown as the costs of faulty data skyrocket. This software tool is aimed at reengineering data manufacturing systems to enhance quality and value of information. By hand, sketching and analyzing data manufacturing systems are extremely tedious, and modifying systems is difficult. DQA can complete the same tasks in a fraction of the time, and systems can easily be reengineered and reanalyzed.

Because information has become a valuable commodity in certain industries, companies have begun making efforts to improve the quality of their data and to determine the costs of erroneous data. The quality of the data is not only defined by its accuracy, completeness, and consistency, but also by its timeliness. Looking at data-producing systems makes it possible to determine which processes are affecting the quality of the data. Data Quality Analyzer (DQA) is a software tool that allows users to model and analyze data manufacturing systems. Systems can easily be modified and examined to determine whether reengineering can improve the data products of the system. At the present, DQA can be run under DOS. Systems can be drawn with polygons representing processing functions. Vectors representing data units are used to connect those blocks, showing the path of data units. A command in the DQA menu computes the data quality and cost of system outputs.

1.1. Background -- The BWPT Data Manufacturing Model

The model developed by Ballou, Wang, Pazer and Tayi, hereafter referred to as BWPT model, was designed to help analyzing and reengineering of data manufacturing systems for improvement information quality. The model tracks the quality, cost, and timeliness of data units through a system. Quality encompasses all attributes that measure the integrity of data excluding timeliness. Cost is tracked to evaluate the increase in cost associated with the improvement of data quality. Timeliness is based partially on the currency of the data, whose value is determined by a customer when a data product is received. Hence, timeliness is not computed until a data product is delivered.

A data unit can undergo three different types of operations in a system: processing, quality improvement, and storage. Processing operations include arithmetic functions as well as processes such as sorting. These operations have cost, quality improvement (degradation), and processing time parameters associated with them. Data units pass through a series of operations before getting delivered to a customer.

1.2. Goals of Paper

The goal of this paper is to document the fundamental concepts of BWPT model and to describe and demonstrate the development and usage of the software tool, DQA. The software facilitates the following capacities and attributes:

(1) Computing results as specified by the BWPT model.

(2) Allowing systems to be drawn and modified easily.

(3) Saving and retrieving models of data manufacturing systems from files.

(4) Providing user friendly environment to minimize users' effort and time.

1.3 Overview of Paper

The focus of this paper is to document the design and implementation of DQA. Chapter 2 summarizes the data manufacturing model created by BWPT. It is essential to understand this material before reading ahead. Chapter 3 outlines the development of the software tool. Finally, Chapter 4 leads the reader through a sample run of DQA.

2. Data Manufacturing Model

The development of the software tool DQA is based on a paper written by Professor Richard Wang at M.I.T. Sloan School and Professors Donald Ballou, Harold Pazer, and G.T. Tayi oat the State University of New York in Albany dealing with the reengineering of data manufacturing systems to enhance information quality. The term data manufacturing refers to a fixed set of data units which experience predefined processing activities to produce data products for internal or external customers, or both. The purpose of the work is to provide a framework for analyzing data manufacturing systems allowing customers to receive the greatest possible value from the data produced by the systems. The data units in the model can experience collection, processing, storage and quality control operations. The cost, timeliness, and quality of the data are computed each time a data unit undergoes an operation.

The timeliness of a data unit is determined by its currency and by its volatility. Currency relates the age of a primitive data unit used to produce a data product. Volatility indicates how long a unit remains valid. The volatility is measured by its shelf life -- the amount of time it is valid. Volatility is determined by the user of the data outputs (customers). A data unit's currency is measured by the delivery time to the customer, the time the data unit was obtained (input time), and how old the data is when it was received as input (age). The equation relating the three parameters is

Currency = Delivery Time - Input Time + Age. (1)

With the currency and volatility parameters determined, the timeliness is given by

Timeliness = max {(1 - currency/volatility)s, 0}. (2)

The timeliness is always between zero and one, and s can be any customer-determined positive integer or fraction. Since the currency cannot be measured until the delivery time is determined, the timeliness of data products cannot be computed until the data products are delivered to customers.

The timeliness of the output of a processing block that is defined by an arithmetic operation can be determined by

where and y = f(x1, x2,..., xn). (3)

Equation two is the weighted average of the timeliness of all the inputs to the function y. As previously stated, the timeliness properties of data cannot be calculated until data products are delivered to customers.

In order to measure the integrity of data products being delivered to customers, the quality of data units is computed after any operation is performed. The data quality, DC of the output, y, of a processing block is given by the following formula:

where (4)

and the xi's are the inputs to the function, y. DC is always between zero and one.

Most functions have a probability of producing erroneous outputs. To account for this possibility, a measure of processing correctness, PE, is introduced. If DC is quality of the output of some function, then the DQ(y) represents the degradation associated with processing. The overall quality for y is then given by

. (5)

A customer may put more value on the currency of a data product than on the quality of the data. For this reason, the value of the product to the consumer must be determined. Given that a data product has an intrinsic value, VI, the value is given by

VA = VI (1-w(DQ)a - (1-w)Tb). (6)

VI, W, a, and b are customer determined.

The cost of data units must be tracked so that the increase in value can be compared to the increase in cost. Reengineering a system could indeed increase the value of the output but the cost increase may be so high that other alternatives must be found.

The framework created by BWPT allows data units to undergo three different operations: processing, quality improvement, and storage. In the model, the processing operation is represented by a process block. These blocks may represent arithmetic functions, but they may also represent functions such a sorting. Blocks can also represent delays if there is a lag in getting a data unit to its next activity. Quality blocks can only receive one input at a time. Storage and quality blocks do not affect the timeliness of data units. Storage blocks do not affect the qualities of data units either, but data units do incorporate costs when they enter a storage block.

The figure below illustrates a sample system. The primitive data units, DU1, DU2, and DU3, originate from vendor blocks and have not entered any of the operational blocks in the data manufacturing system. The quality block, QB1, only takes only one input, DU1. The outputs of the storage block retain their input names since no process is performed.

Figure 2.1. Sample Model

The above system can be represented by the matrix in Table 2.1, called a data manufacturing analysis matrix. An 'x' in a cell indicated that the data unit associated with the row is an input to the block associated with the column.

The marked cells also have a five dimensional vector associated with them. The five components of this vector are:

p: This specifies the predecessor block by symbol. For example, the predecessor of

DU4 is QB1, or column 3.

t1: This represents the time when the data unit is available for the activity. For

example, the value for t1 for the vector associated with (DU2, PB1) is that

time when DU2 is ready for the processing block PB1. In the special case when

p is a vendor block (VB.1), t1 = Input Time as appears in the expression for

currency.

t2: This is the time when the processing begins. Processing cannot start until all

data units needed for that block are available. Also, processing may begin at a

scheduled time tsch. Thus, t2 = max {max{t1's}, tsch}.

DQi: This is the quality of the incoming data unit for a particular activity. It is, of

course, the same as DQ of the output of the predecessor block. The term "data

quality" is used as a place holder for whatever dimension or dimensions of data

quality are of concern to management (with the exception, of course, of

timeliness).

Costi: This represents the cost of the incoming data unit. In essence Costi is the

accumulated cost of all previous activities that a data unit has experienced. If

a data unit is passed onto more than one activity, Costi for that unit is

determined in some pro rated fashion. (This implies that total cost is

preserved.)

Table 2.1. Data Manufacturing Analysis Matrix
PB1
SB1
QB1
CB1
DU1
X
DU2
X
X
DU3
X
X
DU4
X
DU5
X

Using the BWPT data manufacturing model, one can reengineer a system and determine the integrity and cost of the outputs. The data manufacturer can use the model to attempt to optimize the total value of the data being delivered to customers.

3. Development of the DQA Software

DQA is designed to allow quick and easy modeling of information flow using the BWPT Data Manufacturing Model. Using a sample system from the BWPT paper, a spreadsheet was first developed to calculate the outputs of the system. While the spreadsheet was quicker manual computation, it did not allow easy modification or deletion of system elements. In addition, entirely new spreadsheets had to be created for different systems. DQA quickly determines the outputs of any system, and it allows users to easily reengineer their systems and view the new outcomes.

DQA was created using C programming language and HALO™ Professional Graphics Kernel System for a DOS operating system. Figure 3.1 outlines the program architecture of DQA. The first step in the development of DQA was to create a computational engine. This module required the initial data unit and block information as inputs and determined the time, quality, and cost attributes of the outcoming data units. Once the computational engine was completed, HALO™ was used to create the graphic user interface (GUI). Finally, a module was developed to act as a link between the computational engine and the GUI. This module simply converted information from the models drawn in the GUI to data that corresponded to those inputs needed by the computational engine to calculate the results. The following section will describe the three developmental stages of DQA in more detail.

Figure 3.1. DQA Architecture


3.1. The Computational Engine: calculate

When given the proper inputs, calculate will compute the outputs of any system modeled using BWPT Data Manufacturing Model. The values calculate needs as inputs are the attributes of primitive data units and the parameters of process, storage, and quality blocks. The computational engine assumes that activities and data units are arranged in a two-dimensional array in the same way they are arranged in a data manufacturing analysis matrix. The characteristics of each cell are arranged in arrays corresponding to the data manufacturing analysis matrix. Before the graphic interface was developed, calculate was tested using data that had been stored in files.

The flow chart in Figure 3.2 outlines the calculate program. Columns are scanned until one associated with a block ready to be processed is found. Initially, all data units coming from vendor blocks will be ready to enter the next activity. Therefore, the vendor blocks are marked as "ready" to be processed and each cell having a vendor block as a predecessor is marked as "ready" to be processed. Of course, a column will only be marked "ready" if all the cells in that column are marked "ready," indicating that all of an activity's inputs have undergone all the preprocessing needed when they reach the activity. When a column is marked "ready," the program determines the type of the block, and computes the outputs of that block using the algorithms given in chapter two. The column is then marked "done."

The program calculate is being called from the program link, which acts as an interface between calculate and the GUI. When a block is processed, calculate returns to link, where all the columns are scanned to determined if they have all been marked "done." The calculate function continues to be called until all the columns are "done."

Figure 3.2. Flowchart for calculate


3.2. Graphic User Interface

The graphic user interface was created using HALO™ Professional Graphics Kernel System. The HALO environment consists of the HALO device drivers, font and text characteristics, drawing styles and modes, and the coordinate system.[8]. The two device drivers supported by DQA are the VGA display device and a virtual raster graphics (VRI) device. The former of the two was chosen because it is the standard display device most commonly used by PC's. VRI allows images to be larger than the display device. It uses a combination of external and internal memory to store images. Dot text was chosen as the default font. It was not as elaborate as the stroke text offered by HALO, but it was simpler to implement. DQA's graphics were drawn in pixels. A pixel is a single point on a graphics display surface. A pixel's location can be described in coordinates. HALO offers three different types of coordinates: world, and normalized, device. Device coordinates correspond to the resolution of the display driver. DQA uses device coordinates. The resolution used was 640 x 480. This indicates that the upper left coordinate is (0,0) and the lower right coordinate is (639, 479).Normalized and world coordinates are device independent. The world coordinate system allows the range of coordinates to be set and maps these coordinates to the device coordinates of the hardware. Normalized coordinates always identify the upper left corner to be (0, 0) and the lower right coordinate to be (1, 1). The coordinates of the VRI were allowed to reach (1000, 1000). Using a VRI device layer, the display device allowed data manufacturing systems larger than the display device range to be drawn. Arrow icons were placed on the screen to allow the user to shift the displayed image to view different parts of VRI.

When DQA is called, the code initially executed is located in main. This module calls several initialization routines, including Initwindow, which draws the initial screen. Main then monitors the location of the mouse. Different modules are called if mouse cursor is in a specific area and the proper button on the mouse is depressed. The following sections will discuss in more detail the various modules called by main.

3.2.1. Drawing the Initial Window

The module Initwindow draws the initial working screen. Figure 3.3 shows a copy of the working screen. HALO commands for creating boxes and text were used to draw the graphics. The Menu consists of the top row of boxes. These commands can be used by clicking on the boxes once with the left button of the mouse. The window immediately below those commands is the Message Window. This window is used to communicate with the user and to ask for inputs. The large box below the message window is the View Window. Diagrams are to be drawn in this window. On the left side of the View Window is the Block Window, which contains figures representing the vendor, process, storage, quality, and customer blocks.

3.2.2. Drawing Boxes and Vectors in the View Window

Operational blocks can be drawn in the view window by clicking on the desired figure in the Block Window once with the left button of the mouse and dragging the mouse to the desired position in the view window. Any attempt to draw a figure outside the view window will lead to an error message in the message window that informs the user that a block can only be drawn inside the view window. If the block is drawn on top of a previously drawn block or vector, error messages will also appear in the message window. Figure 3.4 shows an example of an error message displayed when one of these situations is encountered.

In order to draw the vectors connecting the blocks, one must click in the block from which the vector is originating with the right button of the mouse, and drag the mouse to the destination block. The destination block must always be ahead of the originating block. When a vector is drawn, the user will be required to enter the name of the vector. The name of the vector will be drawn at the center of the vector. It will appear on top of the vector if the vector is downward sloping, and below it if it is upward sloping. If a user tries to draw a vector from a spot which is not a block or to a spot which is not in a block, an error message will appear in the message window. An error message will also appear if a vector is drawn to a block which is behind the originating block.

3.2.3. Calculating the Outputs of a System

When a system has been drawn on the view screen, the output of the system can be computed by clicking the left button of the mouse in the "RUN" box on the Menu. Several statements will appear in the Message Window prompting the user to enter the parameters of the primitive vectors. The output will appear in the view window.

Figure 3.3. Initial Screen

Figure 3.4. Sample Error Message


3.2.4. Menu Commands

Any of the Menu commands can be accessed by pressing the left button of the mouse in the desired box. The SAVE command displays a message asking for the name of the file to be saved. It creates two separate files, file.v and file.b. This action is transparent to the user. The coordinates and names of the vectors are saved in file.v, while the coordinates and parameters of the blocks are stored in file.b. When loading a file, the user should only use the name file. Coordinates and parameters from file.b and file.v are loaded, and the figures are drawn on the screen. The LOAD command will always ask the user whether the current model should be saved. This eliminates any unintentional deletion of the current model while another file is being loaded.

The PRINT command in the Menu allows the user to print a screen dump, the computed results, or the graphical representation of the system. The print module was implemented using printer drivers provided by HALO™. The VIEW command switches the output in the View Window between the computed results and the graphical representation of the system. The NEW command clears the screen, allowing the user to draw and analyze a new system.

4. Sample Session

In this section, the basic features of DQA are illustrated with the use of a sample model. First the system is drawn on the DQA View Window. Outputs are then calculated by using the RUN command from the Menu. The PRINT command from the Menu was used to provide illustrations of the DQA working window so that the reader could get a clear picture of what DQA looks like.

In order to use the DQA software application tool, one must be within the DOS operating system. The program will be loaded when "do" is typed at the prompt in the directory in which DQA has been loaded.

4.1. Sample Data Manufacturing System

Figure 4.1 represents the data manufacturing system that will be simulated using DQA. Table 4.1 gives a listing of the attributes of the data units exiting the vendors. Table 4.2 shows the characteristics associated with each of the process, quality, and storage blocks. The outputs of the manufacturing system will be associated with those data units entering the customers.

Instead of using equation (4) from chapter 3 to compute the output quality of process and quality blocks, the substitutions in Tables 4.1 and 4.2 were made. These substitutions were made by the authors of BWPT model for simplicity and generalization. (See Table 4.3a and 4.3b)

Figure 4.1. Sample Data Manufacturing System


TABLE 4.1. Primitive Data Attributes
DU1
DU2
DU3
DU4
DU5
QUALITY
.9
.5
.7
.9
.8
COST
10
10
20
30
20
TIME
0
0
5
10
10

4.2. DQA Sample Session

The DQA program will now be used to simulate the system pictured in Figure 4.1. This section contains actual outputs from the sample run. The first step in modeling the system is to draw it and input all the necessary data using DQA. The program will request the required data when the system is drawn. Once this step is computed, the "RUN" command from the DQA Menu is used to calculate and display the output.

TABLE 4.2. Operational Block Attributes
QUALITY
COST
TIME
PB1
1
20
3
PB2
2
30
4
PB3
.5
30
6
PB4
1
10
2
PB5
.5
70
4
PB6
2
100
10
SB1
*
5/input
1
QB1
.5
20
6
QB2
.25
40
8
QB3
.25
50
10

Table 4.3. (a) Substitution Equations for Process Blocks

Process Cost Time Quality Function Delay

PB1 20 3 0

PB2 30 4 0

PB3 30 6 0

PB4 10 2 0

PB5 70 4 2

PB6 100 10 1


Table 4.3. (b) Substitution Equations for Quality Blocks

Quality Block Cost Time Quality Function Delay

QB1 20 6 0

QB2 40 8 0

QB3 50 10 0

4.2.1. Drawing the Model

When a block is drawn in the view window, DQA will prompt the user for the name of the block. The user is also prompted to enter the associated parameters (time, cost, quality, and delay) of blocks. Once the necessary blocks are drawn, the monitor window looks like Figure 4.2.

When the vectors are drawn, the model looks like Figure 4.3. By allowing easy drawing of blocks and vectors, DQA makes modeling of data manufacturing systems extremely easy. The model can be subsequently modified to correct errors or to reconfigure the system. The model can be saved using the SAVE menu for easy retrieval for future use.

Figure 4.2. Sample Model with Only Blocks Drawn

4.2.2.  Calculating the Outputs

Once the model has been drawn and the appropriate parameters have been entered, information on the data units being delivered to the customer blocks can be obtained by simply pressing the left button on the "RUN" command in the menu (See figure 4.2). DQA will prompt the user for the attributes of primitive data units prior to producing the output. The output for the sample model is shown below in Table 4.4.

4.3. Moving Around the Screen

The size of the view window is not restricted by the size of the monitor screen. If a user is drawing a model which is larger than monitor screen, it is possible to move the part of the window showing on the monitor by using the arrow keys in the left bottom corner of the screen (See Figure 4.1). Figure 4.4 show s the finished model from section 4.2 when the view has been shifted down.

4.4. Moving and Deleting Blocks and Vectors

Repositioning a block is extremely easy. To move a block, the user must press the right mouse button down in the item and then move the mouse to its new location. Error messages will appear if the block is moved outside the view window or on top of existing items. When a block is moved, all the data unit vectors attached to it will also be readjusted. If the newly moved vectors cross over any existing blocks, DQA will not allow the block to be relocated. The vectors and the blocks retain their names and attributes when they are moved. Vectors cannot be moved. If a user wants to redraw a vector, it must first be deleted then redrawn.

In order to delete a vector or a block, or to change the system parameters (i.e., name) the left button of the mouse must be double-clicked in the item. DQA will prompt whether the user wishes deletion or change of parameters. If a vector is to be deleted, the mouse does not have to be directly on top of the line. The mouse simply has to be within five pixels of the mouse. When a block is deleted, all the vectors associated with that block are also deleted. All the information associated with deleted items is also erased. If parameters are to be changed, DQA will prompt the user for new parameters.

Figure 4.3. Finished Model as it appears in DQA

5. Concluding Remarks

In this paper, DQA was presented as a software tool to model and analyze data manufacturing systems. With DQA, it is possible to effortlessly reengineer existing systems to enhance information quality. Users can modify their systems until the optimal system is obtained. Since DQA tracks the cost of data units, users can also determine whether systems are cost effective.

The most difficult aspect of this project was the software development. Although DQA meets all the original goals, we have gained insights for future improvement. The program could also be modified to use world coordinates, which will allow for clearer printouts. Porting the program over to other widely used platforms such as Microsoft Windows®, Macintosh®, and UNIX will be useful for users of those platforms.

Table 4.4. The Data Manufacturing Analysis Matrix for the illustrative example
PB1 PB2PB3 PB4PB5 PB6SB1 QB1QB2 QB3CB1 CB2CB3
parameters
time
3
4
6
2
4
10
1
6
8
10
cost
20
30
30
10
70
100
5
20
40
50
quality
1
2
0.5
1
0.5
2
1
0.5
0.25
0.25
delay
0
2
1
DU1p SB1 VB1
t1
1
0
t2
18
0
DQI
0.9
0.9
CostI
15
10
DU2p VB1
t1
0
t2
0
DQI
0.5
CostI
10
DU3p VB2
t1
5
t2
6
DQI
0.7
CostI
20
DU4p VB3
t1
10
t2
31
DQI
0.9
CostI
30
DU5p VB3
t1
10
t2
17
DQI
0.8
CostI
20
DU6p QB1 SB1 QB1
t1
6
7
5
t2
6
7
6
DQI
0.75
0.75
0.75
CostI
15
20
15
DU7p PB2
t1
9
t2
9
DQI
0.725
CostI
55
DU8
p
QB2
SB1
QB2
t1
17
18
17
t2
17
18
17
DQI
0.931
0.9312
0.9312
CostI
47.5
52.5
47.5
DU9
p
PB2
t1
21
t2
21
DQI
.7493
CostI
97.5
DU10
p
QB3
QB3
t1
31
31
t2
31
31
DQI
0.9373
0.9373
CostI
73.75
73.75
PB1
PB2
PB3
PB4
PB5
PB6
SB1
QB1
QB2
QB3
CB1
CB2
CB3
DU11
p
PB4
t1
20
t2
31
DQI
0.9153
CostI
77.6
DU12
p
PB3
t1
13
t2
13
DQI
0.866
CostI
50
DU13
p
PB6
PB6
PB6
t1
41
41
41
t2
42
42
42
DQI
0.842
0.842
0.842
CostI
93.75
93.75
93.75
DU14
p
PB5
PB5
t1
35
35
t2
37
37
DQI
0.9681
0.9681
CostI
71.876
71.876

Figure 4.4. View of Sample Model When it Has Been Shifted

Appendix 1: Source Files

Main.c

#include <stdio.h>

#include <stdlib.h>

#include <malloc.h>

#include <stddef.h>

#include <string.h>

#include <stdlib.h>

#include <conio.h>

#include <ctype.h>

#include <math.h>

#include <float.h>

#include "halodevc.h" /* Contains halo function prototypes */

#include "our.h" /* Contains symbobic constant definitions */

/*******************************************************/

/* Following external variables stores various device */

/* and model information */

/*******************************************************/

int xmax, ymax; /* Maximum screen device range */

int maxcolor; /* Maximum screen color */

int vri_id; /* VRI device handle */

int dev_id; /* Screen device handle */

int pattr[64]; /* Printer attributes */

int model_status; /* Status of the current model */

char *model_name; /* Name of the current model */

int current_x, /* Current position on VRI */

current_y;

int Mouse_x, /* Current position of the mouse */

Mouse_y,

Mouse_st; /* Current status of the mouse */

/*****************************************************/

/* Following arrays contain the display coordinates */

/* of various objects drawn on the screen. */

/*****************************************************/

int view[4], /* Viewing window */

up[4], /* Up arrow */

down[4], /* Down arrow */

left[4], /* Left arrow */

right[4]; /* Right arrow */

int box1[4], /* Process block icon */

box2[4], /* Storage block icon */

box3[4], /* Vendor block icon */

box4[4], /* Quality block icon */

box5[4], /* Customer block icon */

textbox[4]; /* Message block icon */

int menu0[4], /* 'NEW' menu box */

menu1[4], /* 'LOAD' menu box */

menu2[4], /* 'SAVE' menu box */

menu3[4], /* 'QUIT' menu box */

menu4[4], /* 'PRINT' menu box */

menu5[4], /* 'RUN' menu box */

menu6[4]; /* 'VIEW' menu box */

/********************************************************************/

/* Following external variable captures the model in the */

/* 'Data Manufacturing Analysis Matrix' form used by the */

/* computational engine. */

/********************************************************************/

/* Following variables capture the attributes of the vectors */

int p_config[MAX_ROW][MAX_COL], /* Predecessor block */

time1[MAX_ROW][MAX_COL], /* Time of availability */

time2[MAX_ROW][MAX_COL]; /* Time when process begins */

float quality[MAX_ROW][MAX_COL], /* Data quality of data unit*/

cost[MAX_ROW][MAX_COL]; /* Cost of data unit */

/* Following is used to mark the status by the computational engine */

int status[MAX_ROW][MAX_COL]; /* Status */

/* Following variables capture the parameters of the blocks */

int blk_type[MAX_COL], /* Block type */

blk_time[MAX_COL], /* Time parameter */

delay_param[MAX_COL]; /* Delay parameter */

float blk_quality[MAX_COL], /* Quality parameter */

blk_cost[MAX_COL]; /* Cost parameter */

/* Follwing variables are used by the computational engine */

int no_out[MAX_COL], /* Number of outputs */

col_stat[MAX_COL], /* Status */

comp_out[MAX_COL], /* Number of computed output */

col_time[MAX_COL]; /* Time of completion */

int row_count, /* Number of vectors */

col_count; /* Number of blocks */

/****************************************************************/

/* Declaration of Structures. */

/* These structure capture the information of a model in a */

/* graphical format. */

/* struct block: Captures the information about a block */

/* struct vector: Captures the information about a vector */

/****************************************************************/

struct block{

int x1; /* x coordinate in VRI */

int y1; /* y coordinate in VRI */

int time; /* time parameter */

int block_no; /* block type */

int cost; /* cost parameter */

int delay; /* delay time parameter */

float quality; /* quality parameter */

char *blk_name; /* block name */

struct block *next; /* pointer to the next block */

};

struct vector{

int fromx; /* x coordinate of the originating block */

int fromy; /* y coordinate of the originating block */

int tox; /* x coordinate of the target block */

int toy; /* y coordinate of the target block */

int subscript; /* vector number */

char *name; /* vector name */

struct vector *next; /* pointer to the next vector */

};

struct block *first_blk; /* Pointer to the first block */

struct block *new; /* Pointer to the current block */

struct vector *first_vect; /* Pointer to the first vector */

struct vector *vector; /* Pointer to the current vector */

/************************/

/* Function prototypes */

/************************/

void main(void);

void initialize(void);

void initscreen(void);

void MakeDisplayActive(void);

void StartCursor(void);

void CloseDisplay(void);

void CloseVRI(void);

int MoveVRItoDisplay(void);

int chk_button(void);

int haloerr(char *);

int Makeblock(void);

char *challoc(void);

struct block *check_in_block(struct block *, int *, int *, int *, int *);

struct block *talloc(void);

struct vector *talloc2(void);

/***********************************************************************

* MAIN *

***********************************************************************/

void

main()

{

int ExitFlag, tempflag, /* Loopcontrol variables */

dbl_click, tempMx, tempMy,

vri_x, vri_y,

stat, mode;

struct block *from_blk; /* used mark originating block for a vector */

model_status = CONFIG; /* set model status to config */

model_name = challoc(); /* allocate memory for model name */

*model_name = '\0'; /* set model name to null */

first_blk = talloc(); /* allocate memory for the first_block */

new = first_blk; /* set current block to first_block */

first_blk->next = NULL; /* set next block to NULL */

new->blk_name = '\0'; /* set current block name to null */

first_vect = talloc2(); /* allocate memory for the first vector */

vector = first_vect; /* set current vector to the first vector */

first_vect->next = NULL; /* set next vector to NULL */

vector->name = '\0'; /* set current block name to null */

initialize(); /* initialize display, VRI, mouse, and printer */

MakeDisplayActive (); /* set the dispaly as active device */

initscreen(); /* draw the screen */

current_x = 0; /* Set the cuurent VRI offsets to zero */

current_y = 0;

MoveVRItoDisplay (); /* Move part of VRI to the view window */

MakeDisplayActive ();

StartCursor (); /* Start the mouse cursor */

/*-------------

Main Loop

--------------*/

MakeDisplayActive ();

showbcursor();

ExitFlag = FALSE;

while(!ExitFlag)

{

/*-----------------------------------

Read the locator device (mouse);

if no mouse activity loop.

-------------------------------------*/

readlocator(&Mouse_x, &Mouse_y, &Mouse_st);

haloerr("READLOCATOR");

if ( (Mouse_st & 128) == 0)

continue;

movbcurabs(&Mouse_x, &Mouse_y);

/*---------------------------------------------

If mouse is in the blocks menu create a block

----------------------------------------------*/

if ((Mouse_x > box1[0])&&(Mouse_x < box1[2])

&&(Mouse_y > box1[1])&&(Mouse_y < box5[3])

&&((Mouse_st &4) != 4))

{

Makeblock();

continue;

}

/*----------------------------------------------

Is mouse in viewing window?

----------------------------------------------*/

if ((Mouse_x > view[0])&&(Mouse_x < view[2])

&&(Mouse_y > view[1])&&(Mouse_y <view[3])

&&((Mouse_st & 1) != 1) && ((Mouse_st & 4) != 4))

{

while ((Mouse_x > view[0])&&(Mouse_x < view[2])

&&(Mouse_y > view[1])&&(Mouse_y < view[3])

&&((Mouse_st & 1) != 1) && ((Mouse_st & 4) != 4))

{

readlocator(&Mouse_x, &Mouse_y, &Mouse_st);

movbcurabs(&Mouse_x, &Mouse_y);

continue;

}

/*-----------------------------------

is the right mouse button pressed?

-------------------------------------*/

if((Mouse_st & 1) == 1)

{

vri_x = Mouse_x - view[0] + current_x;

vri_y = Mouse_y - view[1] + current_y;

/*-------------------------

is mouse in a block?

--------------------------*/

mode = 0;

from_blk = check_in_block(first_blk, &stat, &vri_x, &vri_y, &mode);

/*----------------------------------------------------

if 'yes' and the mouse is not in a customer block

create a vector

------------------------------------------------------*/

if (stat == TRUE)

{

if(from_blk->block_no == 'c')

{

printf("\a"); /* sound alarm */

continue;

}

connect(from_blk);

}

}

/* --------------------------------------------------------------

if left button pressed, then if single click move the block

and the attached vectors, is double click change or delete

----------------------------------------------------------------*/

if((Mouse_st & 4) == 4)

{

readlocator(&Mouse_x, &Mouse_y, &Mouse_st);

while((Mouse_st & 128) == 0)

readlocator(&Mouse_x, &Mouse_y, &Mouse_st);

tempMx = Mouse_x, tempMy = Mouse_y;

if(((Mouse_st & 4) != 4) && Mouse_x == tempMx && Mouse_y == tempMy)

{

while(Mouse_x == tempMx && Mouse_y == tempMy)

{

readlocator(&Mouse_x, &Mouse_y, &Mouse_st);

if((Mouse_st & 4) == 4)

{

dbl_click = TRUE;

tempflag = 1;

break;

}

}

if (tempflag != 1)

{

tempflag = 0;

continue;

}

}

else if((Mouse_st & 4) == 4)

dbl_click = FALSE;

/*----------------------------------------

single click moveblock and vectors

------------------------------------------*/

if(dbl_click == FALSE)

{

vri_x = Mouse_x - view[0] + current_x;

vri_y = Mouse_y - view[1] + current_y;

mode = 0;

from_blk = check_in_block(first_blk, &stat, &vri_x, &vri_y, &mode);

if (from_blk == NULL)

continue;

if (stat == 1)

{

movblock(from_blk);

}

}

/* -----------------------------------------

double click delete or change

--------------------------------------------*/

else if(dbl_click == TRUE)

{

/*modify();*/

}

}

}

/*-----------------------------------

If locator is in icon area,

-------------------------------------*/

if ( ( ((Mouse_x < (ICONSPACE * 2)) /* mouse in iconspace */

&& (Mouse_y > (ymax - (ICONSPACE *2))))

|| ( (Mouse_y < menu0[3]) /* mouse in menu bar */

&& ((Mouse_x > menu0[0])&&(Mouse_x < menu6[2])))

&&((Mouse_st & 4) != 4)))

/*-------------------------------

Check for button clicks

and take approporiate actions

---------------------------------*/

ExitFlag = chk_button(); /* True will be returned if quit was selected */

MakeDisplayActive ();

showbcursor();

}

free(model_name);

free(first_blk);

free(first_vect);

Mouse_st = 0; /* Deallocate Mouse driver buffer */

setlocator("",&Mouse_st);

CloseVRI ();

CloseDisplay ();

exit(0);

}

Initialize.c

#include "our.h"

void initialize(void);

void initscreen(void);

int haloerr(char *);

/*********************************************************************

* INITIALIZE() *

* *

* This subroutine initializes the Display driver, the VRI driver, *

* & the printer driver, inquires information about the devices, *

* and performs some calculations for fast text placement. *

* *

**********************************************************************/

void

initialize()

{

extern int dev_id, maxcolor, xmax, ymax, vri_id;

extern int pattr[64]; /* Printer attribute array */

int mode; /* Graphics mode */

int zero = 0; /* Zero'd value */

int MousePort; /* Communications port */

int lcv; /* Loop control variable */

int vri_xmax, vri_ymax;

int mattr[64]; /* Memory attribute array */

/*----------------------------------------

Initialize the screen graphics device

------------------------------------------*/

setdev(GRAPHICS_DEVICE);

haloerr("SCREEN SETDEV");

inqadev ( &dev_id );

/*----------------------

Set graphics mode

-----------------------*/

mode = GRAPHICS_MODE;

initgraphics(&mode);

haloerr("SCREEN INITGRAPHICS");

/*-------------------------------------------------------------------

Obtain screen characteristics. maxcolor will always be white.

-------------------------------------------------------------------*/

inqcrange(&maxcolor);

inqdrange(&xmax,&ymax);

/*----------------------------------

Initialize the VRI graphics device

-----------------------------------*/

setdev(VRI_DRIVER);

haloerr("VRI SETDEV");

inqadev (&vri_id);

/*-------------------------------------------------------------------

Initialize memory attribute array to zero.

-------------------------------------------------------------------*/

for (lcv = 0; lcv < 64; lcv++)

{

mattr[lcv] = 0;

}

/*-------------------------------------------------------------------

As a default, MATTR 0 and 1 are set to -1. This means that HALO

will use as much Extended (Up to eight megabytes) and EMS memory as

it can before chaining out to a disk file.

-------------------------------------------------------------------*/

mattr[0] = EMS_MAXPAGE;

mattr[1] = INT_MAXPAGE;

vri_xmax = VRI_X;

vri_ymax = VRI_Y;

/*---------------------------------

Set VRI characteristics

----------------------------------*/

setdrange(&vri_xmax,&vri_ymax);

setcrange(&maxcolor);

setmattr(mattr);

/*------------------------------------------------------------------

Set graphics mode and initialize graphics.

-------------------------------------------------------------------*/

mode = 0;

initgraphics(&mode);

haloerr("VRI INITGRAPHICS");

/*-------------------------------------------------------------------

Initialize current drawing and fill color. maxcolor = white

-------------------------------------------------------------------*/

setcolor(&maxcolor);

setadev(&dev_id);

/*-------------------------------------------------------------------

Initialize and load the locator driver.

-------------------------------------------------------------------*/

MousePort = 1;

setlocator(MOUSE_DRIVER, &MousePort);

haloerr("SETLOCATOR");

/*--------------------------------------------------------------------

initialize the printer and set printer attributes.

--------------------------------------------------------------------*/

setprn(PRINTER_DRIVER);

for (lcv = 0; lcv < 64; lcv++)

{

pattr[lcv] = -1;

}

pattr[0] = 1200;

pattr[1] = 750;

pattr[2] = 0;

pattr[3] = 0;

pattr[4] = 0;

pattr[5] = 0;

pattr[6] = 0;

pattr[7] = 2;

pattr[8] = 0;

pattr[9] = 0;

pattr[10] = 0;

pattr[11] = 0;

pattr[16] = 2;

setpattr(pattr);

return;

}

/*****************************************************************/

/* This function will draw the menu bar, arrows, viewing and */

/* text windows, etc. */

/*****************************************************************/

void initscreen()

{

extern int view[4], up[4], down[4],left[4], right[4]; /* Right arrow */

extern int box1[4],box2[4], box3[4],box4[4], box5[4],

textbox[4];

extern int menu0[4];

extern int menu1[4];

extern int menu2[4];

extern int menu3[4];

extern int menu4[4];

extern int menu5[4];

extern int menu6[4];

extern int xmax, ymax;

int x1, y1, x2, y2;

int x, y, width; /* Graphics cursor position */

int i, j; /* Counter Variables */

int line = 2, fil = 2, height = 10; /* Text Parameters */

int path = 1;

float aspect = 1.0;

char font[] = "AHD104.FNT";

char string0[] = "NEW"; /* Menu names */

char string1[] = "LOAD";

char string2[] = "SAVE";

char string3[] = "QUIT";

char string4[] = "PRINT";

char string5[] = "RUN";

char string6[] = "VIEW";

int boxheight, boxwidth, offset, n;

int ytemp, xtemp, shiftx = -15, shifty = -15;

/*------------------------------------------------

following arrays contain relative coordinates

of the vertices for drawing the blocks.

-------------------------------------------------*/

int pblockx[] = {0, 30, 0, -30, 0};

int pblocky[] = {0, 0, 30, 0, -30};

int sblockx[] = {0, 30, 0, -30, 0};

int sblocky[] = {0, 0, 30, 0, -30};

int qblockx[] = {0, 30, 0, -15, -15, 0};

int qblocky[] = {0, 0, 30, 0, -15, -15};

int vblockx[] = {0, 20, 10, -10, -20, 0};

int vblocky[] = {0, 0, 15, 15, 0, -30};

int cblockx[] = {0, 10, 20, 0, -20, -10};

int cblocky[] = {0, -15, 0, 30, 0, -15};

/*--------------------------------------------------------

following arrays contain the vertices of the arrows

used to scroll the image.

---------------------------------------------------------*/

int uparrayx[] = { 7, -5, 0, -5, 0, -5, 7 };

int uparrayy[] = { 7, 0, 7, 0, -7, 0, -7 };

int leftarrayx[] = { 7, 0, 7, 0, -7, 0 , -7 };

int leftarrayy[] = { -7, 5, 0, 5, 0, 5, -7 };

int downarrayx[] = { -7, 5, 0, 5, 0, 5, -7 };

int downarrayy[] = { -7, 0, -7, 0, 7, 0, 7 };

int rightarrayx[] = { -7, 0, -7, 0, 7, 0, 7 };

int rightarrayy[] = { 7, -5, 0, -5, 0, -5, 7 };

int scanarrayx[] = { 6, 0, 6, 0, -6, 0 , -6 };

int scanarrayy[] = { -6, 4, 0, 4, 0, 4, -6 };

int tx, ty; /* Beginning point for polyln functions */

int Wx1, Wy1, /* Temporary variables for window use */

Wx2, Wy2;

int linewidth; /* Current line width */

int num_pts; /* Number of verticies in array */

inqdrange(&xmax,&ymax); /* Device range */

/**********************************************************************

* Draw Arrows *

***********************************************************************/

/*-------

Up

--------*/

up[0] = 0; /* Up icon */

up[1] = ymax - (ICONSPACE * 2);

up[2] = ICONSPACE;

up[3] = ymax - ICONSPACE;

box ( &up[0], &up[1], &up[2], &up[3] );

tx = 11; /* Draw up arrow in box */

ty = ymax - 38;

movabs ( &tx, &ty );

num_pts = 7;

polylnrel ( uparrayx, uparrayy, &num_pts );

/*---------

Left

----------*/

left[0] = 0; /* Left icon */

left[1] = ymax - 21;

left[2] = 21;

left[3] = ymax;

box ( &left[0], &left[1], &left[2], &left[3]);

tx = 3; /* Draw left arrow in box */

ty = ymax - 11;

movabs ( &tx, &ty );

num_pts = 7;

polylnrel ( leftarrayx, leftarrayy, &num_pts );

/*---------

Right

----------*/

right[0] = ICONSPACE; /* Right icon */

right[1] = ymax - (ICONSPACE * 2);

right[2] = ICONSPACE * 2;

right[3] = ymax - (ICONSPACE);

box ( &right[0], &right[1], &right[2], &right[3] );

tx = 38; /* Draw right arrow in box */

ty = ymax - 31;

movabs ( &tx, &ty );

num_pts = 7;

polylnrel ( rightarrayx, rightarrayy, &num_pts );

/*---------

Down

----------*/

down[0] = ICONSPACE; /* Down icon */

down[1] = ymax - ICONSPACE;

down[2] = ICONSPACE * 2;

down[3] = ymax;

box ( &down[0], &down[1], &down[2], &down[3] );

tx = 31; /* Draw down arrow in box */

ty = ymax - 4;

movabs ( &tx, &ty );

num_pts = 7;

polylnrel ( downarrayx, downarrayy, &num_pts );

/***************************************************************************

* Build Menu Bar *

****************************************************************************/

menu0[0] = 19, menu0[1] = 0, menu0[2] = 99, menu0[3] = 20;

menu1[0] = 109, menu1[1] = 0, menu1[2] = 189, menu1[3] = 20;

menu2[0] = 199, menu2[1] = 0, menu2[2] = 279, menu2[3] = 20;

menu3[0] = 289, menu3[1] = 0, menu3[2] = 369, menu3[3] = 20;

menu4[0] = 379, menu4[1] = 0, menu4[2] = 459, menu4[3] = 20;

menu5[0] = 469, menu5[1] = 0, menu5[2] = 549, menu5[3] = 20;

menu6[0] = 559, menu6[1] = 0, menu6[2] = 639, menu6[3] = 20;

box(&menu0[0],&menu0[1],&menu0[2],&menu0[3]);

box(&menu1[0],&menu1[1],&menu1[2],&menu1[3]);

box(&menu2[0],&menu2[1],&menu2[2],&menu2[3]);

box(&menu3[0],&menu3[1],&menu3[2],&menu3[3]);

box(&menu4[0],&menu4[1],&menu4[2],&menu4[3]);

box(&menu5[0],&menu5[1],&menu5[2],&menu5[3]);

box(&menu6[0],&menu6[1],&menu6[2],&menu6[3]);

x = menu0[0] + 20, y = 15;

movtcurabs(&x, &y);

btext(string0);

deltcur();

x = menu1[0] + 20, y = 15;

movtcurabs(&x, &y);

btext(string1);

deltcur();

x = menu2[0] +20, y = 15;

movtcurabs(&x, &y);

btext(string2);

deltcur();

x = menu3[0] + 20, y = 15;

movtcurabs(&x, &y);

btext(string3);

deltcur();

x = menu4[0] + 20, y = 15;

movtcurabs(&x, &y);

btext(string4);

deltcur();

x = menu5[0] + 20, y = 15;

movtcurabs(&x, &y);

btext(string5);

deltcur();

x = menu6[0] + 20, y = 15;

movtcurabs(&x, &y);

btext(string6);

deltcur();

/***************************************************************************

* Toolbox Window *

****************************************************************************/

x1 = 0, y1 = 29, x2 = 50, y2 = ymax - 50;

box(&x1, &y1, &x2, &y2);

/***** Determine Block Positions *****/

boxheight = y2 - y1;

boxwidth = x2 -x1;

offset = boxheight/5;

/***** Process Block *****/

ytemp = y1 + offset/2;

xtemp = 25;

movabs(&xtemp, &ytemp);

movrel(&shiftx, &shifty);

n = 5;

polylnrel(pblockx, pblocky,&n);

x1 = xtemp - 7;

y1 = ytemp + 5;

movtcurabs(&x1, &y1);

btext("PB");

deltcur();

x1 = xtemp - 15;

y1 = ytemp -15;

x2 = x1 + 30;

y2 = y1 + 30;

box1[0] = x1, box1[1] = y1, box1[2] = x2, box1[3] = y2;

/***** Storage Block *****/

width = 3;

setlnwidth(&width);

ytemp = ytemp + offset;

movabs(&xtemp, &ytemp);

movrel(&shiftx, &shifty);

n = 5;

polylnrel(sblockx, sblocky,&n);

x1 = xtemp - 7;

y1 = ytemp + 5;

movtcurabs(&x1, &y1);

btext("SB");

deltcur();

width = 1;

setlnwidth(&width);

x1 = xtemp - 15;

y1 = ytemp -15;

x2 = x1 + 30;

y2 = y1 + 30;

box2[0] = x1, box2[1] = y1, box2[2] = x2, box2[3] = y2;

/***** Vendor Block *****/

ytemp = ytemp + offset;

movabs(&xtemp, &ytemp);

movrel(&shiftx, &shifty);

n = 6;

polylnrel(vblockx, vblocky,&n);

x1 = xtemp - 7;

y1 = ytemp + 5;

movtcurabs(&x1, &y1);

btext("VB");

deltcur();

x1 = xtemp - 15;

y1 = ytemp -15;

x2 = x1 + 30;

y2 = y1 + 30;

box3[0] = x1, box3[1] = y1, box3[2] = x2, box3[3] = y2;

/***** Quality Block *****/

ytemp = ytemp + offset;

movabs(&xtemp, &ytemp);

movrel(&shiftx, &shifty);

n = 6;

polylnrel(qblockx, qblocky,&n);

x1 = xtemp - 7;

y1 = ytemp + 5;

movtcurabs(&x1, &y1);

btext("QB");

deltcur();

x1 = xtemp - 15;

y1 = ytemp -15;

x2 = x1 + 30;

y2 = y1 + 30;

box4[0] = x1, box4[1] = y1, box4[2] = x2, box4[3] = y2;

/***** Customer Block *****/

ytemp = ytemp + offset;

movabs(&xtemp, &ytemp);

shifty = 0;

movrel(&shiftx, &shifty);

n = 6;

polylnrel(cblockx, cblocky,&n);

x1 = xtemp - 7;

y1 = ytemp + 5;

movtcurabs(&x1, &y1);

btext("CB");

deltcur();

x1 = xtemp - 15;

y1 = ytemp -15;

x2 = x1 + 30;

y2 = y1 + 30;

box5[0] = x1, box5[1] = y1, box5[2] = x2, box5[3] = y2;

/***************************************************************************

* Message Window *

****************************************************************************/

x1 = 80, y1 = 29, x2 = xmax, y2 = 99;

movabs(&x1, &y1);

box(&x1, &y1, &x2, &y2);

textbox[0] = x1, textbox[1] = y1, textbox[2] = x2, textbox[3] = y2;

/***************************************************************************

* Viewing (working) Window *

****************************************************************************/

x1 = 80, y1 = 109, x2 = xmax -1, y2 = ymax -1;

linewidth = WINDOW_BORDER;

setlnwidth( &linewidth);

box(&x1, &y1, &x2, &y2);

view[0] = x1 - 1 + WINDOW_BORDER, view[1] = y1 - 1 + WINDOW_BORDER;

view[2] = x2 - 2, view[3] = y2 - 2;

linewidth = 1;

setlnwidth ( &linewidth);

}

Graphic_Functions.c

#include <stdio.h>

#include <malloc.h>

#include "our.h"

int MoveVRItoDisplay(void);

int MoveFast(void);

void MakeVRIActive(void);

void MakeDisplayActive(void);

void StartCursor(void);

void CloseDisplay(void);

void CloseVRI(void);

int haloerr(char *);

void myscanf(char *);

/**********************************************************************

* MoveVRItoDisplay() *

* *

* This function moves an area of the VRI to the current display. *

* Depending on the video architecture of your display adapter, the *

* data is either moved directly ( Movefast() ) or manipulated and *

* then moved ( MoveVRItoDisplay() ). Note the process for *

* normalizing the data, switching devices, repacking the data and *

* moving the image to the screen. *

* *

***********************************************************************/

int MoveVRItoDisplay()

{

extern int current_x, current_y, vri_id, dev_id, maxcolor, view[4];

int NumPixels; /* Number of pixels to move */

int NormLineLen, /* Length of nomalized line of data */

DevPackedLineLen, /* Length of packed line under screen */

VRIPackedLineLen, /* Length of packed line under VRI */

PackedLineLen; /* Final packed line length */

int DevCurrentLine, /* Current screen line */

VRICurrentLine; /* Current VRI line */

int x_extent; /* VRI extent for MOVEFROM */

int replace = 1; /* Method of MOVETO replacement */

void *NormBuffer, /* Pointer to Normalized buffer */

*PackedBuffer; /* Pointer to packed buffer */

/*------------------------------------------------------------------

If the color range is 1 or 255, then the compaction of the video

buffers are the same. Data from one device may be moved to the

other without any expansion and recompression of the data.

However if the color range is 3 or 15, the data must be normalized

and repacked for the video architecture. The code below handles

both cases.

-------------------------------------------------------------------*/

if ( ( maxcolor == 1 ) && ( maxcolor == 1 ) )

{

return ( MoveFast () );

}

else if ( ( maxcolor == 255 ) && ( maxcolor == 255 ) )

{

return ( MoveFast () );

}

else {

NumPixels = (view[2] - view[0]) + 1;

NormLineLen = NumPixels + 6;

/*------------------------------------------------------------------

Determine the necessary lengths for each architecture.

-------------------------------------------------------------------*/

MakeDisplayActive ();

inqpflen ( &DevPackedLineLen, &NumPixels );

DevPackedLineLen += 6;

MakeVRIActive ();

inqpflen ( &VRIPackedLineLen, &NumPixels );

VRIPackedLineLen += 6;

if ( DevPackedLineLen >= VRIPackedLineLen )

PackedLineLen = DevPackedLineLen;

else

PackedLineLen = VRIPackedLineLen;

/* Allocate buffers */

if ( ( NormBuffer = malloc ( NormLineLen ) ) == NULL )

return ( -1 );

if ( ( PackedBuffer = malloc ( PackedLineLen ) ) == NULL ) {

free ( NormBuffer );

return ( -1 );

}

/*------------------------------------------------------------------

Transfer the data one line at a time.

-------------------------------------------------------------------*/

x_extent = current_x + NumPixels - 1;

for ( DevCurrentLine = view[1], VRICurrentLine = current_y;

DevCurrentLine <= view[3];

DevCurrentLine++, VRICurrentLine++ )

{

MakeVRIActive ();

movefrom ( &current_x, &VRICurrentLine, &x_extent, &VRICurrentLine, PackedBuffer );

ptnorm ( NormBuffer, PackedBuffer, &NumPixels );

MakeDisplayActive ();

pfnorm ( PackedBuffer, NormBuffer, &NumPixels );

moveto ( &view[0], &DevCurrentLine, PackedBuffer, &replace );

}

free ( NormBuffer );

free ( PackedBuffer );

return ( 0 );

}

}

/**********************************************************************

* MoveFast() *

* *

* This function moves an area of the VRI to the current display. *

* Depending on the video architecture of your display adapter, the *

* data is either moved directly ( Movefast() ) or manipulated and *

* then moved ( MoveVRItoDisplay() ). Note the process for *

* normalizing the data, switching devices, repacking the data and *

* moving the image to the screen. *

* *

***********************************************************************/

int MoveFast(void)

{

extern int current_x, current_y, view[4], dev_id, vri_id;

int NumPixels; /* Number of pixels to move */

int PackedLineLen; /* Final packed line length */

int DevCurrentLine, /* Current screen line */

VRICurrentLine; /* Current VRI line */

int x_extent; /* VRI extent for MOVEFROM */

int replace = 1; /* Method of MOVETO replacement */

void *PackedBuffer; /* Pointer to packed buffer */

/*---------------------------------------------------------------------

Inquire and calculate lengths for MOVEFROM function.

-----------------------------------------------------------------------*/

NumPixels = (view[2] - view[0]) + 1;

MakeVRIActive ();

inqpflen ( &PackedLineLen, &NumPixels );

PackedLineLen += 6;

/* Allocate buffer */

if ( ( PackedBuffer = malloc ( PackedLineLen ) ) == NULL ) {

return ( -1 );

}

/*------------------------------------------------------------------

Transfer the data one line at a time.

-------------------------------------------------------------------*/

x_extent = current_x + NumPixels - 1;

for ( DevCurrentLine = view[1], VRICurrentLine = current_y;

DevCurrentLine <= view[3];

DevCurrentLine++, VRICurrentLine++ ) {

MakeVRIActive ();

movefrom ( &current_x, &VRICurrentLine, &x_extent, &VRICurrentLine, PackedBuffer );

MakeDisplayActive ();

moveto ( &view[0], &DevCurrentLine, PackedBuffer, &replace );

}

free ( PackedBuffer );

return ( 0 );

}

/**********************************************************************

* MakeVRIActive() *

* *

* This function switches the active device to the VRI *

* *

***********************************************************************/

void MakeVRIActive()

{

extern int vri_id;

setadev( &vri_id );

return;

}

/**********************************************************************

* MakeDisplayActive() *

* *

* This function switches the active device to the screen display *

* *

***********************************************************************/

void MakeDisplayActive()

{

extern int dev_id;

setadev( &dev_id );

return;

}

/**********************************************************************

* CloseDispaly() *

* *

* This function closes the active screen device. *

* *

***********************************************************************/

void CloseDisplay()

{

extern int dev_id;

MakeDisplayActive ();

closegraphics ( );

closedev (&dev_id);

return;

}

/**********************************************************************

* CloseVRI() *

* *

* This function closes the active VRI. *

* *

***********************************************************************/

void CloseVRI()

{

extern int vri_id;

MakeVRIActive ();

closegraphics ( );

closedev ( &vri_id );

return;

}

/**********************************************************************

* StartCursor() *

* *

* This function initializes and positions the cursor on the *

* screen display. The cursor used is an arrow. *

* *

***********************************************************************/

void StartCursor ()

{

extern xmax, ymax, maxcolor;

static unsigned char CursorMask[26] = {

0xff, 0x80,

0xff, 0x80,

0xff, 0x80,

0xff, 0x80,

0xfe, 0x00,

0xff, 0x00,

0xff, 0x80,

0xf7, 0xc0,

0xf3, 0xe0,

0x01, 0xf0,

0x00, 0xf8,

0x00, 0x7c,

0x00, 0x3c };

static unsigned char Cursor[26] = {

0x00, 0x00,

0x7f, 0x00,

0x7f, 0x00,

0x78, 0x00,

0x7c, 0x00,

0x6e, 0x00,

0x67, 0x00,

0x63, 0x80,

0x01, 0xc0,

0x00, 0xe0,

0x00, 0x70,

0x00, 0x38,

0x00, 0x00 };

int width, /* Width of cursor */

height; /* Height of cursor */

int one = 1; /* Hot spot for cursor */

int CurX, CurY; /* Position of cursor */

width = 14;

height = 13;

defbcursor ( CursorMask, Cursor, &width, &height, &one, &one, &maxcolor );

haloerr("DEFBCURSOR");

CurX = xmax / 2;

CurY = ymax / 2;

orglocator( &CurX, &CurY );

haloerr("ORGLOCATOR");

movbcurabs( &CurX, &CurY );

haloerr("MOVBCURABS");

showbcursor ( );

haloerr("SHOWBCURSOR");

return;

}

/**********************************************************************

* HALOERR() *

* *

* This subroutine inquires the error condition of any implemented *

* HALO function. The string passed to it contains the name of *

* the function and will be displayed along with the error value *

* if an error occurs. *

* *

* Extensive use of INQERR is recommended throughout your program. *

* *

**********************************************************************/

int

haloerr(char *errstring)

{

int func,err = 0;

inqerr(&func,&err);

if (err != 0)

{

closegraphics();

printf("Error in %s : %d \n",errstring,err);

getch();

exit(1);

}

return(0);

}

File_Fun.c

#include <stdio.h>

#include "our.h"

void new_simulation(void);

void save(void);

void load(void);

void drawscreen(void);

struct block *talloc(void);

struct vector *talloc2(void);

char *challoc(void);

void myscanf(char *);

struct block{

int x1;

int y1;

int time;

int block_no;

int cost;

int delay;

float quality;

char *blk_name;

struct block *next;

};

struct vector{

int fromx;

int fromy;

int tox;

int toy;

int subscript;

char *name;

struct vector *next;

};

/**********************************************************************/

/* New_simulation clears VRI & view window and frees the block & */

/* vector structures for starting a new model. */

/**********************************************************************/

void new_simulation(void)

{

extern int textbox[4], current_x, current_y, maxcolor, vri_id, dev_id;

extern struct block *first_blk;

extern struct vector *first_vect;

extern struct vector *vector;

extern struct block *new;

int xfillarray[] = {0, VRI_X, VRI_X, 0, 0};

int yfillarray[] = {0, 0, VRI_Y, VRI_Y, 0};

struct block *tmp_blk;

struct block *tmp_blk2;

struct vector *tmp_vect;

struct vector *tmp_vect2;

int bcur_x, bcur_y, counter;

int black = 0, no_pts = 5, exitflag = FALSE;

char *resp;

char reschar;

char string1[] = "Save current model? (y, or n) :";

char blankline[] = " ";

resp = challoc();

/*--------------------------------------------------------------------

Following loop asks the user if he/she wants to save the current

model. If 'y' then save is called.

----------------------------------------------------------------------*/

while(exitflag == FALSE)

{

bcur_x = textbox[0] + 20;

bcur_y = textbox[1] + 20;

movtcurabs(&bcur_x, &bcur_y);

btext(string1);

myscanf(resp);

deltcur();

movtcurabs(&bcur_x, &bcur_y);

btext(blankline);

deltcur();

if(*resp == 'y')

{

save();

break;

}

else if(*resp == 'n')

break;

else

continue;

}

/*--------------------------------------------------------------------

This loop frees the memory allocated for blocks in the current

model.

---------------------------------------------------------------------*/

while(first_blk->next != NULL)

{

new = first_blk->next;

free(first_blk->blk_name);

free(first_blk);

first_blk = new;

}

/*--------------------------------------------------------------------

This loop frees the memory allocated for vectors in the current

model.

---------------------------------------------------------------------*/

while(first_vect->next != NULL)

{

vector = first_vect->next;

free(first_vect->name);

free(first_vect);

first_vect = vector;

}

new = first_blk; /* sets the current block to the first block */

vector = first_vect; /* sets the current vector to the first vector */

current_x = 0; /* sets the VRI offsets to zero */

current_y = 0;

/*-------------------------------------------------------------------

following clears the VRI and the viewing window.

--------------------------------------------------------------------*/

setadev(&vri_id);

setcolor(&black);

movabs(&xfillarray[0], &yfillarray[0]);

polyfabs(xfillarray, yfillarray, &no_pts, &black);

setcolor(&maxcolor);

setadev(&dev_id);

MoveVRItoDisplay();

free(resp);

}

/*********************************************************************/

/* save() prompts the user for a name of the model to be saved, */

/* then creates two files. "name".b for saving block info, and */

/* "name".v for saving vector info. */

/*********************************************************************/

void save(void)

{

extern int textbox[4];

extern struct block *first_blk;

extern struct vector *first_vect;

extern struct block *new;

extern struct vector *vector;

extern int model_status;

struct block *blk;

struct vector *vec;

int x, y;

int z;

char save_str[] = {"Save as: "};

char blank[] = {" "};

char tempname[] = {"temp.b"};

char tempname1[] = {"temp.v"};

char *filename;

char *filename1;

FILE *fp;

FILE *fp1;

filename = challoc();

filename1 = challoc();

/*------------------------------------------------

promts the user for a name unless saving

temporarily to display results.

-------------------------------------------------*/

if(model_status == CONFIG)

{

x = textbox[0] + 20;

y = textbox[1] + 20;

movtcurabs(&x, &y);

btext(save_str);

myscanf(filename);

strcpy(filename1, filename);

movtcurabs(&x, &y);

btext(blank);

deltcur();

/*-------------------------------------------------

Create the two files necessary for saving

--------------------------------------------------*/

z = strlen(filename);

filename[z] = '.';

filename[z+1] = 'b';

filename[z+2] = '\0';

filename1[z] = '.';

filename1[z+1] = 'v';

filename1[z+2] = '\0';

filename;

fp = fopen(filename, "w");

fp1 = fopen(filename1, "w");

}

else if(model_status == RESULTS)

{

fp = fopen(tempname, "w");

fp1 = fopen(tempname, "w");

}

/*------------------------------------------------------

Save the information.

------------------------------------------------------*/

for(blk = first_blk; blk->next != new->next; blk = blk->next)

{

fprintf(fp, "%d %d %d %d %d %f %s\n", blk->x1, blk->y1, blk->time, blk->block_no, blk->cost, blk->quality, blk->blk_name);

}

for(vec = first_vect; vec->next != vector->next; vec = vec->next)

{

fprintf(fp1, "%d %d %d %d %d %s\n", vec->fromx, vec->fromy, vec->tox, vec->toy, vec->subscript, vec->name);

}

fcloseall();

free(filename);

free(filename1);

}

/******************************************************************/

/* load() asks for a name of the model to be retrived, then */

/* from the files creates necessary structures. */

/******************************************************************/

void load()

{

extern int textbox[4];

extern struct block *first_blk;

extern struct vector *first_vect;

extern struct block *new;

extern struct vector *vector;

struct block *blk;

struct vector *vec;

int x, y;

int z, i, vcount, bcount;

char load_str[] = {"Load file:"};

char blank[] = {" "};

char *file;

char *file1;

FILE *lp;

FILE *lp1;

/*----------------------------------------------------------

Ask for the name of the model to be retrieved

----------------------------------------------------------*/

file = challoc();

file1 = challoc();

x = textbox[0] + 20;

y = textbox[1] + 20;

movtcurabs(&x, &y);

btext(load_str);

myscanf(file);

strcpy(file1, file);

movtcurabs(&x, &y);

btext(blank);

z = strlen(file);

file[z] = '.';

file[z+1] = 'b';

file[z+2] = '\0';

file1[z] = '.';

file1[z+1] = 'v';

file1[z+2] = '\0';

lp = fopen(file, "r");

lp1 = fopen(file1, "r");

deltcur();

/*---------------------------------------------------------------

Scan the information from the files and create approporiate

structures to capture the model.

----------------------------------------------------------------*/

for(bcount = 0; (i = fgetc(lp)) != EOF;)

{

if(i == '\n')

{

bcount++;

}

}

for(vcount = 0; (i = fgetc(lp1)) != EOF;)

{

if(i == '\n')

vcount++;

}

fcloseall();

lp = fopen(file, "r");

lp1 = fopen(file1, "r");

for(i = 1, blk = first_blk; i <= bcount; i++)

{

blk->blk_name = challoc();

fscanf(lp, "%d %d %d %d %d %f %s\n", &blk->x1, &blk->y1, &blk->time, &blk->block_no, &blk->cost, &blk->quality, blk->blk_name);

blk->next = talloc();

blk = blk->next;

}

new = blk;

new->next = NULL;

new->blk_name = '\0';

for(i = 1, vec = first_vect; i <= vcount; i++)

{

vec->name = challoc();

fscanf(lp1, "%d %d %d %d %d %s\n", &vec->fromx, &vec->fromy, &vec->tox, &vec->toy, &vec->subscript, vec->name);

vec->next = talloc2();

vec = vec->next;

}

vector = vec;

vector->next = NULL;

vector->name = '\0';

free(file);

free(file1);

fcloseall();

}

/**************************************************************/

/* drawscreen() draws the configuration in vri and display */

/* using the structures loaded through load() */

/**************************************************************/

void

drawscreen(void)

{

extern struct block *first_blk;

extern struct vector *first_vect;

extern struct block *new;

extern struct vector *vector;

INT x, y;

struct block *tmp_blk;

struct vector *tmp_vect;

for(tmp_blk = first_blk; tmp_blk->next != new->next; tmp_blk = tmp_blk->next)

{

drawblock2(tmp_blk, tmp_blk->block_no, tmp_blk->x1, tmp_blk->y1);

}

new = tmp_blk;

for(tmp_vect = first_vect; tmp_vect->next != vector->next; tmp_vect = tmp_vect->next)

{

drawvector(tmp_vect);

}

vector = tmp_vect;

}

Create_Block.c

#include<stdio.h>

#include"our.h"

struct block{

int x1;

int y1;

int time;

int block_no;

int cost;

int delay;

float quality;

char *blk_name;

struct block *next;

};

struct vector{

int fromx;

int fromy;

int tox;

int toy;

int subscript;

char *name;

struct vector *next;

};

struct block *check_in_block(struct block *,int *, int *,int *, int *);

struct vector *check_on_vec(struct vector *, int *,int, int, int);

int check_connect(struct vector *);

/*********************************************************************/

/* This function serves two purposes. When called with fourth */

/* parameter(mode) set to one, it is used to see if a block */

/* trying to be drawn will lie on top of another block. If that is */

/* the case, function returns the structure of the block that is */

/* already there and a status of one. When called with the mode */

/* set to zero, if see if the coordinates x, y are in a block. The */

/* function also returns the structure of the block and status of */

/* one. If no block interferes, the function returns NULL and */

/* status is set to zero. */

/*********************************************************************/

struct block *check_in_block(struct block *a_block,int *status, int *x,int *y, int *mode)

{

extern struct block *new;

int a1, a2, b1, b2;

/*------------------------------------------------

made it to the current (empty) block? then return

NULL and set status = 0;

---------------------------------------------------*/

if(a_block->next == NULL)

{

*status = 0;

return(NULL);

}

else

{

/*------------------------------------------------

if checking to see if block will overlap, must

add or subtract 30.

_________________________________________________*/

if(*mode == 1)

{

a1 = a_block->x1 - 30;

a2 = a_block->x1 + 30;

b1 = a_block->y1 - 30;

b2 = a_block->y1 + 30;

}

/*--------------------------------------------------

if checking to see if a point( coordinates) lies

in a block add or subtract 15.

--------------------------------------------------*/

else if(*mode == 0)

{

a1 = a_block->x1 - 15;

a2 = a_block->x1 + 15;

b1 = a_block->y1 - 15;

b2 = a_block->y1 + 15;

}

/*--------------------------------------------------

if a block interferes return block and set status

to one.

---------------------------------------------------*/

if((*x >= a1 && *x <= a2) && (*y >= b1 && *y <= b2))

{

*x = a_block->x1;

*y = a_block->y1;

*status = 1;

return(a_block);

}

/*----------------------------------------------------

else call check_in_block recursevely with the next

block as first argument.

----------------------------------------------------*/

else return(check_in_block(a_block->next, status, x, y, mode));

}

}

/*********************************************************************/

/* This function if similar to check_in_box, however, its checks */

/* wheter a block is being drawn on top of vector or a point (x, y) */

/* lies on a vector . When called with mode 1, it check if a block */

/* lies on top of a vector by setting the offset to 15. When */

/* called with mode 0, it checks if a point lies on a vector by */

/* setting offset to 2. Status of 1 indicates an interference. */

/*********************************************************************/

struct vector

*check_on_vec(struct vector *vec, int *stat,int x,int y, int mode)

{

int x1, x2, y3;

float y2, y1, slope;

int offset;

if(mode == 0)

offset = 2;

else

offset = 15;

/*---------------------------------------

made if to the current (last and empty)?

then retrun NULL and set status to 0.

------------------------------------------*/

if(vec->next == NULL)

{

*stat = 0;

return(NULL);

}

else if(vec->next != NULL)

{

x1 = vec->fromx + 15;

x2 = vec->tox - 15;

y1 = vec->fromy;

y2 = vec->toy;

slope = (y2 -y1)/(x2 - x1);

x2 = vec->fromx + 16;

y2 = y1 + ((x2 - x1) * slope);

y3 = y2;

while(x2 <= (vec->tox - 16))

{

if((x2 >= (x - offset) && x2 <= (x + offset)) && (y3 >= (y - offset) && y3 <= (y + offset)))

{

*stat = 1;

return(vec);

}

else

{

x2 = x2 + 1;

y2 = y1 + ((x2 - x1) * slope);

y3 = y2;

}

}

/*---------------------

check next vector

---------------------*/

return(check_on_vec(vec->next, stat, x, y, mode));

}

}

int check_connect(struct vector *a_vector)

{

extern int view[4];

extern struct block *first_blk;

int x, y, x1, x2, y3, stat, mode;

float slope, y1, y2;

x1 = a_vector->fromx + 15;

x2 = a_vector->tox - 15;

y1 = a_vector->fromy;

y2 = a_vector->toy;

slope = (y2 - y1)/(x2 - x1);

x2 = a_vector->fromx + 16;

y2 = y1 + ((x2 - x1) * slope);

y3 = y2;

mode = 0;

while(x2 <= (a_vector->tox - 16))

{

check_in_block(first_blk, &stat, &x2, &y3, &mode);

if(stat == 1)

{

return(1);

}

x2 = x2 + 1;

y2 = y1 + ((x2 - x1) * slope);

y3 = y2;

}

return(0);

}

Check_Model.c

#include<stdio.h>

#include"our.h"

struct block{

int x1;

int y1;

int time;

int block_no;

int cost;

int delay;

float quality;

char *blk_name;

struct block *next;

};

struct vector{

int fromx;

int fromy;

int tox;

int toy;

int subscript;

char *name;

struct vector *next;

};

struct block *check_in_block(struct block *,int *, int *,int *, int *);

struct vector *check_on_vec(struct vector *, int *,int, int, int);

int check_connect(struct vector *);

/*********************************************************************/

/* This function serves two purposes. When called with fourth */

/* parameter(mode) set to one, it is used to see if a block */

/* trying to be drawn will lie on top of another block. If that is */

/* the case, function returns the structure of the block that is */

/* already there and a status of one. When called with the mode */

/* set to zero, if see if the coordinates x, y are in a block. The */

/* function also returns the structure of the block and status of */

/* one. If no block interferes, the function returns NULL and */

/* status is set to zero. */

/*********************************************************************/

struct block *check_in_block(struct block *a_block,int *status, int *x,int *y, int *mode)

{

extern struct block *new;

int a1, a2, b1, b2;

/*------------------------------------------------

made it to the current (empty) block? then return

NULL and set status = 0;

---------------------------------------------------*/

if(a_block->next == NULL)

{

*status = 0;

return(NULL);

}

else

{

/*------------------------------------------------

if checking to see if block will overlap, must

add or subtract 30.

_________________________________________________*/

if(*mode == 1)

{

a1 = a_block->x1 - 30;

a2 = a_block->x1 + 30;

b1 = a_block->y1 - 30;

b2 = a_block->y1 + 30;

}

/*--------------------------------------------------

if checking to see if a point( coordinates) lies

in a block add or subtract 15.

--------------------------------------------------*/

else if(*mode == 0)

{

a1 = a_block->x1 - 15;

a2 = a_block->x1 + 15;

b1 = a_block->y1 - 15;

b2 = a_block->y1 + 15;

}

/*--------------------------------------------------

if a block interferes return block and set status

to one.

---------------------------------------------------*/

if((*x >= a1 && *x <= a2) && (*y >= b1 && *y <= b2))

{

*x = a_block->x1;

*y = a_block->y1;

*status = 1;

return(a_block);

}

/*----------------------------------------------------

else call check_in_block recursevely with the next

block as first argument.

----------------------------------------------------*/

else return(check_in_block(a_block->next, status, x, y, mode));

}

}

/*********************************************************************/

/* This function if similar to check_in_box, however, its checks */

/* wheter a block is being drawn on top of vector or a point (x, y) */

/* lies on a vector . When called with mode 1, it check if a block */

/* lies on top of a vector by setting the offset to 15. When */

/* called with mode 0, it checks if a point lies on a vector by */

/* setting offset to 2. Status of 1 indicates an interference. */

/*********************************************************************/

struct vector

*check_on_vec(struct vector *vec, int *stat,int x,int y, int mode)

{

int x1, x2, y3;

float y2, y1, slope;

int offset;

if(mode == 0)

offset = 2;

else

offset = 15;

/*---------------------------------------

made if to the current (last and empty)?

then retrun NULL and set status to 0.

------------------------------------------*/

if(vec->next == NULL)

{

*stat = 0;

return(NULL);

}

else if(vec->next != NULL)

{

x1 = vec->fromx + 15;

x2 = vec->tox - 15;

y1 = vec->fromy;

y2 = vec->toy;

slope = (y2 -y1)/(x2 - x1);

x2 = vec->fromx + 16;

y2 = y1 + ((x2 - x1) * slope);

y3 = y2;

while(x2 <= (vec->tox - 16))

{

if((x2 >= (x - offset) && x2 <= (x + offset)) && (y3 >= (y - offset) && y3 <= (y + offset)))

{

*stat = 1;

return(vec);

}

else

{

x2 = x2 + 1;

y2 = y1 + ((x2 - x1) * slope);

y3 = y2;

}

}

/*---------------------

check next vector

---------------------*/

return(check_on_vec(vec->next, stat, x, y, mode));

}

}

int check_connect(struct vector *a_vector)

{

extern int view[4];

extern struct block *first_blk;

int x, y, x1, x2, y3, stat, mode;

float slope, y1, y2;

x1 = a_vector->fromx + 15;

x2 = a_vector->tox - 15;

y1 = a_vector->fromy;

y2 = a_vector->toy;

slope = (y2 - y1)/(x2 - x1);

x2 = a_vector->fromx + 16;

y2 = y1 + ((x2 - x1) * slope);

y3 = y2;

mode = 0;

while(x2 <= (a_vector->tox - 16))

{

check_in_block(first_blk, &stat, &x2, &y3, &mode);

if(stat == 1)

{

return(1);

}

x2 = x2 + 1;

y2 = y1 + ((x2 - x1) * slope);

y3 = y2;

}

return(0);

}

View_Results.c

#include <stdio.h>

#include "our.h"

FILE *fpout;

void viewresults(void);

void new_simulation(void);

void clear_textbox(void);

char *challoc(void);

void

viewresults()

{

extern int view[4];

extern int maxcolor, dev_id, vri_id;

extern int current_x, current_y;

extern row_count, col_count;

int x = 10, y = 10,r,c;

int flag = FALSE;

char *ch;

FILE *fpout;

fpout = fopen("results.out", "r");

ch = challoc();

clear_textbox();

new_simulation();

setadev(&vri_id);

movtcurabs(&x, &y);

while(flag == FALSE)

{

*ch = fgetc(fpout);

if(*ch == EOF)

break;

else

{

if(*ch == '\n')

{

y = y + 10;

movtcurabs(&x, &y);

}

else

btext(ch);

}

}

setadev(&dev_id);

free(ch);

current_x = 0;

current_y = 0;

MoveVRItoDisplay();

}

Shift_Image.c

#include "our.h"

void ShiftUp ();

void ShiftDown ();

void ShiftRight();

void ShiftLeft();

void CheckWindow();

int MoveVRItoDisplay ();

/**********************************************************************

* ShiftUp() *

* *

* This function adjusts the location of the current Y position, *

* checks if the shift is within VRI range, and performs the copy to *

* the screen. *

* *

***********************************************************************/

void ShiftUp ()

{

extern int view[4], current_y, current_y, dev_id, vri_id;

if (current_y != 0)

{

current_y -= DELTAY;

CheckWindow ();

MoveVRItoDisplay ();

}

return;

}

/**********************************************************************

* ShiftDown() *

* *

* This function adjusts the location of the current Y position, *

* checks if the shift is within VRI range, and performs the copy to *

* the screen. *

* *

***********************************************************************/

void ShiftDown ()

{

extern int view[4], current_x, current_y, dev_id, vri_id;

int ysize;

int scr_height;

ysize = VRI_Y - 1; /* VRI Y size */

scr_height = (view[3] - view[1]);

if ( current_y != (ysize - scr_height) )

{

current_y += DELTAY;

CheckWindow ();

MoveVRItoDisplay ();

}

return;

}

/**********************************************************************

* ShiftRight() *

* *

* This function adjusts the location of the current X position, *

* checks if the shift is within VRI range, and performs the copy to *

* the screen. *

* *

***********************************************************************/

void ShiftRight()

{

extern int view[4], current_x, current_y, dev_id, vri_id;

int xsize;

int scr_width;

xsize = VRI_X - 1; /* VRI X size */

scr_width = (view[2] - view[0]);

if ( current_x != (xsize - scr_width) )

{

current_x += DELTAX;

CheckWindow();

MoveVRItoDisplay();

}

return;

}

/**********************************************************************

* ShiftLeft() *

* *

* This function adjusts the location of the current X position, *

* checks if the shift is within VRI range, and performs the copy to *

* the screen. *

* *

***********************************************************************/

void

ShiftLeft()

{

extern int view[4], current_x, current_y, dev_id, vri_id;

if ( current_x != 0 )

{

current_x -= DELTAX;

CheckWindow();

MoveVRItoDisplay();

}

return;

}

/**********************************************************************

* CheckWindow() *

* *

* This function determines if the requested shift is within the *

* VRI bounds. If it is not, it adjusts the variables accordingly. *

* *

***********************************************************************/

void CheckWindow()

{

extern int view[4], current_x, current_y;

int xsize, ysize; /* VRI range */

int scr_width; /* Viewing window width */

int scr_height; /* Viewing window height */

xsize = VRI_X - 1; /* VRI X size */

ysize = VRI_Y - 1; /* VRI Y size */

scr_width = (view[2] - view[0]);

scr_height = (view[3] - view[1]);

/* Check VRI extents */

if ( current_x < 0 )

current_x = 0;

if ( current_x > (xsize - scr_width) )

current_x = xsize - scr_width;

if ( current_y < 0 )

current_y = 0;

if ( current_y > (ysize - scr_height) )

current_y = ysize - scr_height;

return;

}

Print.c

#include <stdio.h>

#include "our.h"

char *challoc(void);

void myscanf(char *);

void myprint(char *);

void clear_textbox(void);

struct block{

int x1;

int y1;

int time;

int block_no;

int cost;

int delay;

float quality;

char *blk_name;

struct block *next;

};

struct vector{

int fromx;

int fromy;

int tox;

int toy;

int subscript;

char *name;

struct vector *next;

};

void

print()

{

extern int textbox[4];

extern int vri_id, dev_id;

extern int xmax, ymax;

extern int pattr[64];

extern int model_status;

extern struct block *first_blk;

extern struct block *new;

struct block *temp_blk;

int btext_x, btext_y, x, y;

int print_x1, print_y1, print_x2, print_y2;

char string1[] = {"Which of the following do you wish to print?"};

char string2[] = {" 1) The model configuration. "};

char string3[] = {" 1) Simulation results. "};

char string4[] = {" 2) Screen dump. "};

char string5[] = {"Enter your choice:"};

char errorstring[] = {"That is not a valid choice!"};

char *response;

response = challoc();

btext_x = textbox[0] + 20;

btext_y = textbox[1] + 20;

movtcurabs(&btext_x, &btext_y);

btext(string1);

btext_y = btext_y + 10;

movtcurabs(&btext_x, &btext_y);

if(model_status == RESULTS)

{

btext(string3);

btext_y = btext_y + 10;

movtcurabs(&btext_x, &btext_y);

}

else if(model_status == CONFIG)

{

btext(string2);

btext_y = btext_y + 10;

movtcurabs(&btext_x, &btext_y);

}

btext(string4);

btext_y = btext_y + 10;

movtcurabs(&btext_x, &btext_y);

btext(string5);

myscanf(response);

clear_textbox();

if(*response == '1')

{

setadev(&vri_id);

print_x1 = 0, print_y1 = 0;

print_x2 = 0, print_y2 = 0;

for(temp_blk = first_blk; temp_blk->next != new->next; temp_blk = temp_blk->next)

if(temp_blk->x1 > print_x2)

print_x2 = temp_blk->x1;

else if(temp_blk->y1 > print_y2)

print_y2 = temp_blk->y1;

else

continue;

print_x2 = print_x2 + 40;

print_y2 = print_y2 + 40;

setclip(&print_x1, &print_y1, &print_x2, &print_y2);

pattr[2] = 1;

setpattr(pattr);

box(&print_x1, &print_y1, &print_x2, &print_y2);

gprint();

pattr[2] = 0;

setpattr(pattr);

setadev(&dev_id);

}

else if(*response == '2')

{

print_x1 = 0, print_y1 = 0, print_x2 = xmax, print_y2 = ymax;

setclip(&print_x1, &print_y1, &print_x2, &print_y2);

gprint();

}

else

{

myprint(errorstring);

}

free(response);

}

Move_Block.c

#include <stdio.h>

#include "our.h"

#include<float.h>

#define TO 0

#define FROM 1

struct block *check_in_block(struct block *, int *, int *, int *, int *);

void vri_to_dev(int *, int *);

void check_on_vec(struct vector *, int *, int, int, int);

struct vector *talloc2(void);

void myprint(char *);

void myscanf(char *);

char *challoc(void);

void drawvector(struct vector *);

void drawblock2(struct block *, int , int , int );

void drawblock3(struct block *, int , int *, int *, int , int , int );

struct block *talloc();

struct vector *talloc2(void);

struct block{

int x1;

int y1;

int time;

int block_no;

int cost;

int delay;

float quality;

char *blk_name;

struct block *next;

};

struct vector{

int fromx;

int fromy;

int tox;

int toy;

int subscript;

char *name;

struct vector *next;

};

/*******************************************************/

/* This function moves a block and associated */

/* vectors to a new location on the diplay */

/*******************************************************/

void movblock(struct block *a_block)

{

extern int Mouse_x, Mouse_y, Mouse_st, textbox[4], view[4];

extern struct vector *first_vect;

extern struct block *first_blk;

extern struct vector *vector;

extern int vri_id, dev_id;

extern view[4];

int flag = 1, x, y,Mx, My, same_vector, cindex, tmousex, tmousey, stat, i;

int x1, y1, x2, y2, lcv, lcv2, dummy1, dummy2, status, exitflag, iflag;

int vtempx2, vtempx1, vtempy1, vtempy2, index = 0, maxcolor, pflag;

int mode, mode_no;

char *vtempname;

int vec_x1[10], vec_x2[10], vec_y1[10], vec_y2[10], vec_st[10];

struct block *to;

struct vector *tempvector;

struct vector *tempvector2;

struct block *tempblock;

struct vector *tempvec;

char *name_string;

char *vec_name[10];

tempblock = talloc();

tempvec = talloc2();

for(lcv = 0, tempvector = first_vect; tempvector != vector; tempvector = tempvector->next)

{

if(tempvector->tox == a_block->x1 && tempvector->toy == a_block->y1)

{

vec_x1[lcv] = tempvector->fromx;

vec_y1[lcv] = tempvector->fromy;

vec_x2[lcv] = tempvector->tox;

vec_y2[lcv] = tempvector->toy;

vec_st[lcv] = TO;

vec_name[lcv] = tempvector->name;

lcv++;

}

else if(tempvector->fromx == a_block->x1 && tempvector->fromy == a_block->y1)

{

vec_x1[lcv] = tempvector->fromx;

vec_y1[lcv] = tempvector->fromy;

vec_x2[lcv] = tempvector->tox;

vec_y2[lcv] = tempvector->toy;

vec_st[lcv] = FROM;

vec_name[lcv] = tempvector->name;

lcv++;

}

}

while(flag == 1)

{

hidebcursor();

readlocator(&Mouse_x, &Mouse_y, &Mouse_st);

Mx = (((Mouse_x - view[0])/60)*60) + view[0] + 25;

My = Mouse_y;

dev_to_vri(&Mx, &My);

dummy1 = Mx, dummy2 = My;

mode = 1;

to = check_in_block(first_blk, &stat, &dummy1, &dummy2, &mode);

tempvector2 = first_vect;

exitflag = 0;

while(exitflag == 0)

{

if(tempvector == NULL)

break;

mode_no = 1;

tempvector = check_on_vec(tempvector2, &status, Mx, My, mode_no);

if(status == 1)

{

iflag = 1;

for(i = 0; i <= lcv; i++)

{

if(tempvector->fromx == vec_x1[i] && tempvector->fromy == vec_y1[i]

&& tempvector->tox == vec_x2[i] && tempvector->toy == vec_y2[i])

{

tempvector2 = tempvector->next;

iflag = 0;

exitflag = 0;

break;

}

}

if(iflag == 1)

exitflag = 1;

}

}

vri_to_dev(&Mx, &My);

x1 = Mx -15;

y1 = My - 15;

x2 = Mx + 15;

y2 = My + 15;

rbox(&x1,&y1,&x2,&y2);

if ((Mouse_st & 4) == 4 && (Mouse_st & 128))

{

movbcurabs(&Mouse_x, &Mouse_y);

delbox();

for(lcv2 = 0; lcv2 < lcv; lcv2++)

delln();

hidebcursor();

Mx = (((Mouse_x - view[0])/60)*60) + view[0] + 25;

My = Mouse_y;

x1 = Mx -15;

y1 = My - 15;

x2 = Mx + 15;

y2 = My + 15;

for(lcv2 = 0;lcv2 < lcv; lcv2++)

{

if(vec_st[lcv2] == TO)

{

vtempx1 = Mx;

vtempy1 = My;

vtempx2 = vec_x1[lcv2];

vtempy2 = vec_y1[lcv2];

vtempname = vec_name[lcv2];

vri_to_dev(&vtempx2, &vtempy2);

}

else if(vec_st[lcv2] == FROM)

{

vtempx1 = vec_x2[lcv2];

vtempy1 = vec_y2[lcv2];

vtempx2 = Mx;

vtempy2 = My;

vtempname = vec_name[lcv2];

vri_to_dev(&vtempx1, &vtempy1);

}

movabs(&vtempx1, &vtempy1);

rlnabs(&vtempx2, &vtempy2);

}

rbox(&x1,&y1, &x2, &y2);

continue;

}

else if ((Mouse_st & 4) == 4)

{

continue;

}

/* if mouse let go check an draw */

else if(((Mouse_st & 4) != 4) && (stat == 0) && (status == 0))

{

pflag = 0;

dev_to_vri(&Mx, &My);

for(i = 0; i <= lcv; i++)

{

if(vec_st[i] == FROM)

if(Mx >= vec_x2[i])

{

pflag = 1;

break;

}

if(vec_st[i] == TO)

if(Mx <= vec_x1[i])

{

pflag = 1;

break;

}

}

if(pflag == 1)

{

for(lcv2 = 0; lcv2 < lcv; lcv2++)

delln();

delbox();

break;

}

flag = 0;

for(lcv2 = 0; lcv2 < lcv; lcv2++)

delln();

delbox();

tempblock->x1 = a_block->x1;

tempblock->y1 = a_block->y1;

tempblock->block_no = a_block->block_no;

x1 = a_block->x1;

y1 = a_block->y1;

tempblock->blk_name = " ";

setcolor(&index);

setadev(&vri_id);

setcolor(&index);

setadev(&dev_id);

/* erases old block */

drawblock2(tempblock, tempblock->block_no, x1, y1);

inqcrange(&maxcolor);

setcolor(&maxcolor);

setadev(&vri_id);

setcolor(&maxcolor);

setadev(&dev_id);

a_block->x1 = Mx;

a_block->y1 = My;

/* draws the block on a new position */

drawblock2(a_block, a_block->block_no, Mx, My);

/* erase old vectors */

for(i = 0;i < lcv; i++)

{

setcolor(&index);

setadev(&vri_id);

setcolor(&index);

setadev(&dev_id);

tempvec->fromx = vec_x1[i];

tempvec->fromy = vec_y1[i];

tempvec->tox = vec_x2[i];

tempvec->toy = vec_y2[i];

tempvec->name = " ";

drawvector(tempvec);

setcolor(&maxcolor);

setadev(&vri_id);

setcolor(&maxcolor);

setadev(&dev_id);

deltcur();

}

/* draw new vectors */

for(i = 0, tempvector = first_vect; tempvector != vector; tempvector = tempvector->next)

{

if((vec_x1[i] == tempvector->fromx) && (vec_y1[i] == tempvector->fromy) &&

(vec_x2[i] == tempvector->tox) && (vec_y2[i] == tempvector->toy))

{

if(vec_st[i] == TO)

{

tempvector->tox = Mx;

tempvector->toy = My;

drawvector(tempvector);

i++;

}

else if(vec_st[i] == FROM)

{

tempvector->fromx = Mx;

tempvector->fromy = My;

drawvector(tempvector);

i++;

}

}

}

flag = 0;

break;

}

else if(((Mouse_st & 4) != 4) && ((stat == 1) || (status == 1) || (Mx < view[0]) || (My < view[1])))

{

for(lcv2 = 0; lcv2 < lcv; lcv2++)

delln();

delbox();

break;

}

movbcurabs(&Mx, &My);

}

}

void drawvector(struct vector *a_vector)

{

int ix1, ix2, iy1, iy2, shiftx, shifty;

float x1, x2, y1, y2, cent_x, cent_y, slope;

char *name;

x1 = a_vector->fromx + 15.0;

x2 = a_vector->tox - 15.0;

y1 = a_vector->fromy;

y2 = a_vector->toy;

ix1= x1;

ix2 = x2;

iy1 = y1;

iy2= y2;

cent_x = (x1 + x2)/2.0;

cent_y = (y1 + y2)/2.0;

slope = (y2 - y1)/(x2 - x1);

if(slope == 0.0 || slope > 0.0)

{

shiftx = cent_x;

shifty = cent_y - 2.0;

}

else

{

shiftx = cent_x;

shifty = cent_y +10;

}

vri_to_dev(&shiftx, &shifty);

movtcurabs(&shiftx, &shifty);

name = a_vector->name;

btext(name);

deltcur();

setadev(&vri_id);

dev_to_vri(&shiftx, &shifty);

movtcurabs(&shiftx, &shifty);

name = a_vector->name;

btext(name);

deltcur();

setadev(&dev_id);

vri_to_dev(&ix1, &iy1);

vri_to_dev(&ix2, &iy2);

movabs(&ix1, &iy1);

lnabs(&ix2,&iy2);

setadev(&vri_id);

dev_to_vri(&ix1, &iy1);

dev_to_vri(&ix2, &iy2);

movabs(&ix1, &iy1);

lnabs(&ix2,&iy2);

setadev(&dev_id);

}

void

drawblock2(struct block *a_block, int blk_type, int x, int y)

{

int n, width;

int pblockx[] = {0, 30, 0, -30, 0};

int pblocky[] = {0, 0, 30, 0, -30};

int sblockx[] = {0, 30, 0, -30, 0};

int sblocky[] = {0, 0, 30, 0, -30};

int qblockx[] = {0, 30, 0, -15, -15, 0};

int qblocky[] = {0, 0, 30, 0, -15, -15};

int vblockx[] = {0, 20, 10, -10, -20, 0};

int vblocky[] = {0, 0, 15, 15, 0, -30};

int cblockx[] = {0, 10, 20, 0, -20, -10};

int cblocky[] = {0, -15, 0, 30, 0, -15};

if(blk_type == 'p')

{ n = 5;

drawblock3(a_block,blk_type, pblockx, pblocky, n, x, y);

}

else if(blk_type == 's')

{n = 5;

width = 3;

setlnwidth(&width);

drawblock3(a_block,blk_type, sblockx, sblocky, n, x, y);

width = 1;

setlnwidth(&width);

}

else if(blk_type == 'v')

{ n = 6;

drawblock3(a_block, blk_type, vblockx, vblocky, n, x, y);

}

else if(blk_type == 'q')

{ n = 6;

drawblock3(a_block, blk_type, qblockx, qblocky, n, x, y);

}

else if(blk_type == 'c')

{ n = 6;

drawblock3(a_block, blk_type, cblockx, cblocky, n, x, y);

}

}

void

drawblock3(struct block *a_block,int blk_type, int *xcoords, int *ycoords, int n, int x, int y)

{

extern int current_x, current_y;

int shiftx, shifty,temp1, temp2,tshift;

shiftx = -15;

if(blk_type == 'v')

tshift = -12;

else tshift = -10;

if(blk_type == 'c')

shifty = 0;

else shifty = -15;

vri_to_dev(&x, &y);

movabs(&x, &y);

movrel(&shiftx, &shifty);

hidebcursor();

polylnrel(xcoords, ycoords,&n);

temp1 = x + tshift;

temp2 = y + 4;

movtcurabs(&temp1, &temp2);

hidebcursor();

btext(a_block->blk_name);

deltcur();

setadev(&vri_id);

x = x - view[0] + current_x;

y = y - view[1] + current_y;

movabs(&x, &y);

movrel(&shiftx, &shifty);

polylnrel(xcoords, ycoords,&n);

dev_to_vri(&temp1, &temp2);

movtcurabs(&temp1, &temp2);

btext(a_block->blk_name);

deltcur();

setadev(&dev_id);

}

Check_Button.c

#include <stdio.h>

#include "our.h"

int chk_button();

void ShiftLeft();

void ShiftUp ();

void ShiftDown ();

void ShiftRight();

void new_simulation(void);

void print(void);

void viewresults(void);

void calc(void);

void load(void);

void save(void);

struct block{

int x1; /* x coordinate in VRI */

int y1; /* y coordinate in VRI */

int time; /* time parameter */

int block_no; /* block type */

int cost; /* cost parameter */

int delay; /* delay time parameter */

float quality; /* quality parameter */

char *blk_name; /* block name */

struct block *next; /* pointer to the next block */

};

struct vector{

int fromx; /* x coordinate of the originating block */

int fromy; /* y coordinate of the originating block */

int tox; /* x coordinate of the target block */

int toy; /* y coordinate of the target block */

int subscript; /* vector number */

char *name; /* vector name */

struct vector *next; /* pointer to the next vector */

};

/**********************************************************************

* CHK_BUTTON *

* *

* This function checks which icon has been selected, performs *

* the appropriate shift and returns the exit condition. If the *

* cursor is in the quit menu box and the left button is pressed, *

* the exit value is returned as TRUE. *

* *

**********************************************************************/

int chk_button()

{

extern int view[4], up[4], down[4], left[4], right[4];

extern int menu0[4], menu1[4], menu2[4], menu3[4], menu4[4], menu5[4], menu6[4];

extern int textbox[4], Mouse_x, Mouse_y, Mouse_st, current_x, current_y;

extern int dev_id, vri_id, model_status;

extern struct block *first_blk;

extern struct vector *first_vect;

extern xmax, ymax;

int column1; /* arrow columns */

int column2;

column1 = up[0];

column2 = right[0];

while ( (( ((Mouse_x < (ICONSPACE * 2)) /* mouse in arrow space */

&& (Mouse_y > (ymax - (ICONSPACE *2))))

|| ( (Mouse_y < menu0[3]) /* in menu bar */

&& ((Mouse_x > menu0[0])&&(Mouse_x < menu6[2]))))

&&((Mouse_st & 4) != 4)))

{

readlocator(&Mouse_x, &Mouse_y, &Mouse_st);

movbcurabs(&Mouse_x, &Mouse_y);

continue;

}

/*--------------------------------------------------------------------

Is the cursor in the first arrow column? If so, identify whicharrow

and check for button press.

--------------------------------------------------------------------*/

if (((Mouse_x > column1) && (Mouse_x < column2)) && ((Mouse_st & 4) == 4) )

{

if ( (Mouse_y > up[1]) && (Mouse_y < up[3]) ) /* Shift up */

{

if ((Mouse_st & 4) == 4)

{

ShiftUp ();

return(FALSE);

}

}

else if ( (Mouse_y > left[1]) && (Mouse_y < left[3]) )

/* Shift left */

{

if ((Mouse_st & 4) == 4)

{

ShiftLeft();

return(FALSE);

}

}

}

/*----------------------------------------------------------------------------

ELSE Is the cursor in the second arrowcolumn? If so, identify which arrow

and check for button press.

-------------------------------------------------------------------------*/

else if(((Mouse_x > column2) && (Mouse_x < right[2]))&&((Mouse_st & 4) == 4))

{

if ( (Mouse_y > right[1]) && (Mouse_y < right[3]) ) /* Shift Right*/

{

if ((Mouse_st & 4) == 4)

{

ShiftRight ();

return(FALSE);

}

}

else if ( (Mouse_y > down[1]) && (Mouse_y < down[3]) ) /* Shift Down */

{

if ((Mouse_st & 4) == 4)

{

ShiftDown ();

return(FALSE);

}

}

}

/*---------------------------------------------------------------------

Is the mouse in menu bar? if it is take approporiate action(s).

----------------------------------------------------------------------*/

else if ((Mouse_y < menu0[3]) &&((Mouse_st & 4) == 4))

{

/*------------------

'NEW' menu

---------------------*/

if ((Mouse_x > menu0[0]) && (Mouse_x < menu0[2]))

{ if ((Mouse_st & 4) == 4)

{

if(first_blk->next == NULL && first_vect->next == NULL)

return(FALSE);

else

{

new_simulation();

model_status = CONFIG;

return(FALSE);

}

}

}

/*------------------

'LOAD' menu

---------------------*/

else if ((Mouse_x > menu1[0]) && (Mouse_x < menu1[2]))

{ if ((Mouse_st & 4) == 4)

{

if(model_status == RESULTS)

{

printf("\a");

return(FALSE);

}

else if(first_blk->next != NULL || first_vect->next != NULL)

new_simulation();

load();

drawscreen();

return(FALSE);

}

}

/*------------------

'SAVE' menu

---------------------*/

else if ((Mouse_x > menu2[0]) && (Mouse_x < menu2[2]))

{ if ((Mouse_st & 4) == 4)

{

if(model_status == RESULTS)

{

printf("\a");

return(FALSE);

}

else if(first_blk->next == NULL && first_vect->next == NULL)

return(FALSE);

else

{

save();

return(FALSE);

}

}

}

/*------------------

'QUIT' menu

---------------------*/

else if ((Mouse_x > menu3[0]) && (Mouse_x < menu3[2]))

{ if ((Mouse_st & 4) == 4)

{

if(first_blk->next != NULL && first_vect->next != NULL)

new_simulation();

return(TRUE);

}

}

/*------------------

'PRINT' menu

---------------------*/

else if ((Mouse_x > menu4[0]) && (Mouse_x < menu4[2]))

{ if ((Mouse_st & 4) == 4)

{

print();

return(FALSE);

}

}

/*------------------

'RUN' menu

---------------------*/

else if ((Mouse_x > menu5[0]) && (Mouse_x < menu5[2]))

{ if ((Mouse_st & 4) == 4)

{

calc();

model_status = RESULTS;

save();

viewresults();

return(FALSE);

}

}

/*------------------

'VIEW' menu

---------------------*/

else if ((Mouse_x > menu6[0]) && (Mouse_x < menu6[2]))

{ if ((Mouse_st & 4) == 4)

{

return(FALSE);

}

}

}

return(FALSE);

}

Calculate.c

#include <stdio.h>

#include "our.h"

struct block{

int x1;

int y1;

int time;

int block_no;

int cost;

int delay;

float quality;

char *blk_name;

struct block *next;

};

struct vector{

int fromx;

int fromy;

int tox;

int toy;

int subscript;

char *name;

struct vector *next;

};

int calculate(void);

void myscanf(char *);

char *challoc(void);

void clear_textbox(void);

/******************************************************************/

/* calc() converts the structures information to the Data */

/* Manufacturing Analysis Matrix form as defined by Ballou-Wang- */

/* Pazer model. It also sets other auxillary variables that */

/* calculate() requires for computing the results. Once all */

/* the preprocessing is done, it call calculate iteratively */

/* computation is finished. */

/******************************************************************/

void

calc(void)

{

/*----------------------------------------------------------------

following external variables captures the model configuration

and its characteristics in a DMS Matrix form.

-----------------------------------------------------------------*

extern int p_config[MAX_ROW][MAX_COL], status[MAX_ROW][MAX_COL];

extern int time1[MAX_ROW][MAX_COL], time2[MAX_ROW][MAX_COL];

extern int blk_type[MAX_COL], blk_time[MAX_COL];

extern int no_out[MAX_COL],delay_param[MAX_ROW];

extern int col_stat[MAX_COL], col_time[MAX_COL], comp_out[MAX_COL];

extern float quality[MAX_ROW][MAX_COL], cost[MAX_ROW][MAX_COL];

extern float blk_quality[MAX_COL], blk_cost[MAX_COL];

extern int row_count, col_count;

extern int textbox[4];

/*-------------------------------------

following pointers mark the first

and last blocks and vectors

-------------------------------------*/

extern struct block *first_blk;

extern struct block *new;

extern struct vector *first_vect;

extern struct vector *vector;

/*----------------------------------

following are temporary pointers

used in conversion process from

structures to a matrix

------------------------------------*

struct block *current_blk;

struct block *cur_blk2;

struct vector *current_vector;

struct vector *sub_vector;

struct vector *tempvector;

struct block *tempblock;

int x, y, a, b, c, r, col, row, flag,no_of_vendors = 0, tag = 1;

char *stringv;

char *tempchar;

char string1[] = {"Enter the time unit for initial vector "};

char string2[] = {"Enter the quality unit for initial vector "};

char string3[] = {"Enter the cost unit for initial vector "};

char string4[] = {"Enter the delay element for final vector "};

char stringx[] = {" :"};

char blank[] = {" "};

FILE *fpout;

tempchar = challoc();

fpout = fopen("results.out", "w");

current_blk = first_blk;

cur_blk2 = first_blk;

current_vector = first_vect;

/*****************************************/

/* Initializing arrays. */

/*****************************************/

for(r = 1; r <= MAX_ROW; r++)

delay_param[r] = -1;

for(c = 1; c <= MAX_COL; c++)

{

blk_type[c] = '\0';

blk_time[c] = 0;

blk_cost[c] = 0.0;

blk_quality[c] = 0.0;

for(r =0; r <MAX_ROW; r++)

{

quality[r][c] = 0.0;

p_config[r][c] = 0;

status[r][c] = 0;

time1[r][c] = 0;

time2[r][c] = 0;

cost[r][c] = 0.0;

}

}

/*-----------------------------------------

loading block parameters into

arrays

------------------------------------------*

for(c = 1;current_blk->next != NULL;c++)

{

blk_time[c] = current_blk->time;

blk_cost[c] = current_blk->cost;

blk_quality[c] = current_blk->quality;

blk_type[c] = current_blk->block_no;

if (blk_type[c] == 'v')

no_of_vendors = no_of_vendors + 1;

current_blk = current_blk->next;

}

col_count = c - 1;

for(c = 1, tempblock = first_blk; c <= col_count; c++, tempblock = tempblock->next)

{

for(no_out[c] = 0, tempvector = first_vect; tempvector != vector; tempvector = tempvector->next)

{

if(tempvector->fromx == tempblock->x1 && tempvector->fromy == tempblock->y1)

no_out[c]++;

}

}

/********************************************************************/

/* this loop loads vector configuration into matrix form and */

/* asks the user to input the attributes of primitive vectors. */

/********************************************************************/

for(r = 1; current_vector->next != NULL; current_vector = current_vector->next)

{

current_blk = first_blk;

/*-------------------------------------------------------

loading vector configuration into arrays.

--------------------------------------------------------*/

for(c=1;current_blk->next != NULL; c++, current_blk = current_blk->next)

{

if(current_vector->fromx==current_blk->x1 && current_vector->fromy == current_blk->y1)

{

if(current_blk->block_no == 'v')

{

current_vector->subscript = r;

r++;

}

if(current_blk->block_no != 'v')

for(sub_vector = first_vect;sub_vector != current_vector->next;sub_vector = sub_vector->next)

{

if(sub_vector == current_vector)

{

current_vector->subscript = r;

r++;

break;

}

else if(strcmp(current_vector->name, sub_vector->name) == 0)

{

current_vector->subscript = sub_vector->subscript;

break;

}

}

cur_blk2 = first_blk;

/*--------------------------------------------------------------

following loope prompts the user for attributes of

primitive (vendor) vectors.

---------------------------------------------------------------*/

for(col=1;cur_blk2->next != NULL; col++, cur_blk2 = cur_blk2->next)

{

if(current_vector->tox == cur_blk2->x1 &&

current_vector->toy == cur_blk2->y1)

{

p_config[current_vector->subscript][col] = c;

if(current_blk->block_no == 'v')

{

stringv = current_vector->name;

status[current_vector->subscript][col] = 2;

x = textbox[0] + 20;

y = textbox[1] + 20;

movtcurabs(&x, &y);

btext(string1);

btext(stringv);

btext(stringx);

myscanf(tempchar);

time1[current_vector->subscript][col] = atof(tempchar);

x = textbox[0] + 20;

y = textbox[1] + 20;

movtcurabs(&x, &y);

btext(blank);

x = textbox[0] + 20;

y = textbox[1] + 20;

movtcurabs(&x, &y);

btext(string2);

btext(stringv);

btext(stringx);

myscanf(tempchar);

quality[current_vector->subscript][col] = atof(tempchar);

deltcur();

x = textbox[0] + 20;

y = textbox[1] + 20;

movtcurabs(&x, &y);

btext(blank);

x = textbox[0] + 20;

y = textbox[1] + 20;

movtcurabs(&x, &y);

btext(string3);

btext(stringv);

btext(stringx);

myscanf(tempchar);

cost[current_vector->subscript][col] = atof(tempchar);

x = textbox[0] + 20;

y = textbox[1] + 20;

movtcurabs(&x, &y);

btext(blank);

}

else

{

status[current_vector->subscript][col] = 1;

}

}

else

{

continue;

}

}

}

else continue;

}

}

deltcur();

row_count = r - 1;

/*----------------------------------------------------------

asks the user to input any delay elements of the

final vectors.

-----------------------------------------------------------*/

for(tempblock = first_blk; tempblock != new; tempblock = tempblock->next)

{ if(tempblock->block_no == 'c')

{ for(tempvector = first_vect; tempvector != vector; tempvector = tempvector->next)

{ if(tempvector->tox == tempblock->x1 && tempvector->toy == tempblock->y1)

{ if(delay_param[tempvector->subscript] == -1)

{ x = textbox[0] + 20;

y = textbox[1] + 20;

stringv = tempvector->name;

movtcurabs(&x, &y);

btext(string4);

btext(stringv);

btext(stringx);

myscanf(tempchar);

delay_param[tempvector->subscript] = atoi(tempchar);

deltcur();

if(y > textbox[1] + 50)

{

clear_textbox();

y = textbox[1] + 10;

}

y = y + 10;

}

}

}

}

}

for(c = 1; c <= col_count; c++)

{

comp_out[c] = 0;

col_stat[c] = 0;

}

/**************************************************************/

/* Following calls calculate iteratively until all of the */

/* columns (blocks) are processed. */

/**************************************************************/

calculate();

for(c = 1; c <= col_count; c++)

{

if(c == col_count)

if(col_stat[c] == 3)

break;

if(col_stat[c] != 3)

calculate();

}

for(r = 1; r <= row_count;r++)

for(c = 1, current_blk = first_blk; c <= col_count; c++, current_blk = current_blk->next)

if(current_blk->block_no == 'c' && status[r][c] != 0)

time2[r][c] = time2[r][c] + delay_param[r];

/******************************************************/

/* prints the results onto a file. */

/******************************************************/

for(r = 1; r <= row_count;r++)

{

for(c = 1; c <= col_count; c++)

fprintf(fpout, "%5d ", p_config[r][c]);

fprintf(fpout, "\n");

for(c = 1; c <= col_count; c++)

fprintf(fpout, "%5d ", time1[r][c]);

fprintf(fpout, "\n");

for(c = 1; c <= col_count; c++)

fprintf(fpout, "%5d ", time2[r][c]);

fprintf(fpout, "\n");

for(c = 1; c <= col_count; c++)

fprintf(fpout,"%5.2f ", quality[r][c]);

fprintf(fpout, "\n");

for(c = 1; c <= col_count; c++)

fprintf(fpout,"%5.2f ", cost[r][c]);

fprintf(fpout, "\n");

}

free(tempchar);

}

/*******************************************************************/

/* Following funtion is the heart of the computational engine. */

/* calculte() processes blocks that have inputs that are ready */

/* for processing and passes the outputs as the inputs of the */

/* next block. It marks the status of the blocks as each */

/* block is processed. */

/*******************************************************************/

int calculate(void)

{

extern int p_config[MAX_ROW][MAX_COL], status[MAX_ROW][MAX_COL];

extern int time1[MAX_ROW][MAX_COL], time2[MAX_ROW][MAX_COL];

extern int blk_type[MAX_COL], blk_time[MAX_COL];

extern int row_count, col_count;

extern int no_out[30];

extern int col_stat[30], col_time[30], comp_out[30];

extern float quality[MAX_ROW][MAX_COL], cost[MAX_ROW][MAX_COL];

extern float blk_quality[MAX_COL], blk_cost[MAX_COL] ;

float tot_qual, av_in_q, q_out, tot_in_c, c_out;

int c;

int r, x, y, col, row, s_row;

int st_count, tot_stat, in_count;

int max_t1s, t_out;

/*********************************************************************/

/*** checks columns to see if ready and puts maximum of t1's as t2 ***/

/*********************************************************************/

for(c = 1; c <= col_count; c++)

{

if(blk_type[c] == 'v')

{

col_stat[c] = 3;

continue;

}

if(col_stat[c] != 3) /* if column has not yet been processd */

{

/*----------------------------------------------------------

computes the approporiate time2's (time when inputs are

ready to be processed, and puts them in the matrix

__________________________________________________________*/

for(r = 1, tot_stat = 0, st_count = 0, max_t1s = 0; r <= row_count; r++)

{

tot_stat = tot_stat + status[r][c];

if(blk_type[c] == 's')

{

st_count = 1;

if(status[r][c] == 2)

{

col_stat[c] = 2;

time2[r][c] = time1[r][c];

}

}

else if(status[r][c] != 0) /*** is this an active cell? ***/

{

st_count = st_count + 1;

if(time1[r][c] > max_t1s)

max_t1s = time1[r][c];

}

}

if(tot_stat/st_count == 2 && blk_type[c] != 's')

{

col_stat[c] = 2;

col_time[c] = max_t1s;

for(r = 1; r <= row_count; r++) /** set t2 to greatest t1 **/

{

if(status[r][c] != 0)

{

if(blk_type[c] == 's' || blk_type[c] == 'c') /** if sb then set t2 **/

{

time2[r][c] = time1[r][c]; /** equal to t1 **/

}

else

time2[r][c] = max_t1s; /** otherwise t2 = max(t1) **/

}

}

}

}

}

/********************************************/

/* Process the blocks with all inputs ready */

/********************************************/

for(c = 1; c <= col_count; c++)

{

if(col_stat[c] == 2)

{

switch (blk_type[c])

{

/**** Process Block Case ****/

case 'p':

tot_qual = 0;

t_out = blk_time[c] + col_time[c];

for(r = 1, in_count = 0, tot_in_c = blk_cost[c]; r <= row_count; r++)

if(status[r][c] != 0)

{

in_count = in_count + 1;

tot_in_c = tot_in_c + cost[r][c];

tot_qual = tot_qual + quality[r][c];

}

av_in_q = tot_qual / in_count;

c_out = tot_in_c / no_out[c];

q_out = pow(av_in_q, blk_quality[c]);

col_stat[c] = 3;

break;

/**** Quality Block Case ****/

case 'q':

t_out = blk_time[c] + col_time[c];

for(r = 1; r <= row_count; r++)

if(status[r][c] == 2)

{

c_out = (cost[r][c] + blk_cost[c])/no_out[c];

q_out = 1 - ((1 - quality[r][c]) * blk_quality[c]);

}

col_stat[c] = 3;

break;

/**** Customer Block Case ****/

case 'c':

col_stat[c] = 3;

break;

/**** Storage Block Case ****/

case 's':

for(r = 1; r <= row_count; r++)

if(status[r][c] == 2)

{

q_out = quality[r][c];

t_out = blk_time[c] + time2[r][c];

c_out = cost[r][c] + blk_cost[c];

s_row = r;

status[r][c] = 3;

comp_out[c]++;

if(comp_out[c] == no_out[c])

col_stat[c] = 3;

else

col_stat[c] = 1;

}

break;

}

/*******************************************/

/* Update cells with processed information */

/*******************************************/

for(col = 1; col <= col_count; col++)

{

if(blk_type[c] == 's' && p_config[s_row][col] == c)

{

time1[s_row][col] = t_out;

quality[s_row][col] = q_out;

cost[s_row][col] = c_out;

status[s_row][col] = 2;

}

else

for(row = 1; row <= row_count; row++)

if(blk_type[c] != 's' && p_config[row][col] == c)

{

time1[row][col] = t_out;

quality[row][col] = q_out;

cost[row][col] = c_out;

status[row][col] = 2;

}

}

}

}

}

Other Files

#include <stdio.h>

#include "our.h"

void myscanf(char *);

int mygetch(int, int);

void myprint(char *);

void vri_to_dev(short *, short *);

void dev_to_vri(short *, short *);

void clear_textbox(void);

struct block *talloc(void);

struct vector *talloc2(void);

char *challoc(void);

struct block{

int x1;

int y1;

int time;

int block_no;

int cost;

int delay;

float quality;

char *blk_name;

struct block *next;

};

struct vector{

int fromx;

int fromy;

int tox;

int toy;

int subscript;

char *name;

struct vector *next;

};

/*----------------------------------------------

myscanf function had to be rewritten to

accomodate halo fast text printing and to

suppress DOS defualt printing.

Takes user input and puts in a string.

----------------------------------------------*/

void

myscanf(char *string)

{

int c, temp, x, y;

int dummy;

temp = 0;

for(dummy = 0; temp == 0; dummy++)

{

*(string+dummy) = mygetch(x,y);

/*-------------------------------------

if character from mygetch is newline

return to caller

--------------------------------------*/

if(*(string+dummy) == 13)

{

*(string+dummy) = '\0';

temp = 1;

}

/*-------------------------------------

if character form mygetch is backspace

then erase previous character.

---------------------------------------*/

else if(*(string+dummy) == 8)

{

if(dummy != 0)

{

inqtcur(&x, &y, &c);

x = x - 8;

movtcurabs(&x, &y);

btext(" ");

movtcurabs(&x, &y);

dummy = dummy - 2;

}

else

{

printf("\a");

dummy = dummy - 1;

}

}

}

}

/*--------------------------------------------

mygetch reads from the keyboard and

echos a fast text character in the message

window.

---------------------------------------------*/

int

mygetch(int x, int y)

{

int c,clr;

char *ch;

c = getch();

*ch = c;

*(ch+1) = '\0';

if((*ch == 13) || (*ch == 8))

return(*ch);

else

{

inqtcur(&x, &y, &clr);

movtcurabs(&x, &y);

btext(ch);

return(*ch);

}

}

/*-------------------------------------

prints the string passed to it in the

message window and waits for keystroke

to continue. Used for error messages

---------------------------------------*/

void

myprint(char *string)

{

extern short textbox[4];

short x, y;

char ret_inst[] = "press any key to continue.";

char blankline[] = " ";

deltcur();

printf("\a");

x = textbox[0] + 20;

y = textbox[1] + 20;

movtcurabs(&x, &y);

btext(string);

y = y + 10;

movtcurabs(&x, &y);

btext(ret_inst);

deltcur();

getch();

y = y - 10;

movtcurabs(&x, &y);

btext(blankline);

y = y + 10;

movtcurabs(&x, &y);

btext(blankline);

deltcur();

return;

}

/*--------------------------------------

changes vri coordinate pair x, y into

dev coordinates.

--------------------------------------*/

void

vri_to_dev(int *x, int *y)

{

extern int view[4], current_x, current_y;

*x = *x + view[0] - current_x;

*y = *y + view[1] - current_y;

}

/*--------------------------------------

changes dev coordinate pair x, y into

vri coordinates.

--------------------------------------*/

void

dev_to_vri(int *x, int *y)

{

extern int view[4], current_x, current_y;

*x = *x - view[0] + current_x;

*y = *y - view[1] + current_y;

}

/*-------------------------------------

clears the message window

--------------------------------------*/

void

clear_textbox()

{

extern int textbox[4];

int btext_x, btext_y;

int lcv;

char blankline[] = {" "};

btext_x = textbox[0] + 20;

btext_y = textbox[1] + 20;

for(lcv = 1; lcv <= 5; lcv ++, btext_y = btext_y + 10)

{

movtcurabs(&btext_x, &btext_y);

btext(blankline);

}

deltcur();

}

/*--------------------------------------

allocates memory for strings.

i.e. vector, block names.

---------------------------------------*/

char *challoc(void)

{

return (char *) malloc(10);

}

/*----------------------------------------

allocates memory for block structure

----------------------------------------*/

struct block *talloc(void)

{

return (struct block *) malloc(sizeof(struct block));

}

/*------------------------------------

allocates memory for block vector

-------------------------------------*/

struct vector *talloc2(void)

{

return (struct vector *) malloc(sizeof(struct vector));

}