Ejemplo n.º 1
0
void RiderSum::Line_Rider_Report (void)
{
	int riders, board, alight, run, runs, num, length, tot_len, period, num_periods;
	int max_riders, max_board, max_alight, max_runs, total, capacity, max_cap;
	double factor, max_fac, sum_time, tot_time, time, capfac, max_capfac;
	double vmt, vht, pmt, pht;
	Dtime low, high;

	Int_Map_Itr map_itr;
	Line_Data *line_ptr;
	Stop_Data *stop_ptr;
	Line_Stop_Itr stop_itr, next_itr;
	Line_Run_Itr run_itr;
	Veh_Type_Data *veh_type_ptr, *run_type_ptr;

	Show_Message ("Line Rider Profile -- Record");
	Set_Progress ();

	//---- print the report ----

	Header_Number (LINE_RIDERS);

	num_periods = sum_periods.Num_Periods ();
	if (num_periods == 0) num_periods = 1;

	num = (int) (line_map.size () * stop_map.size ());

	if (!Break_Check (num + 5)) {
		Print (1);
		Line_Rider_Header ();
	}

	//---- process each route ----

	for (map_itr = line_map.begin (); map_itr != line_map.end (); map_itr++) {
		Show_Progress ();

		if (select_routes && !route_range.In_Range (map_itr->first)) continue;

		line_ptr = &line_array [map_itr->second];

		if (select_modes && !select_mode [line_ptr->Mode ()]) continue;

		//---- check the link criteria ----

		if (!Link_Selection (line_ptr)) continue;

		//---- set the run flags ----

		if (!Run_Selection (line_ptr)) continue;

		//---- save the route ridership data ----
		
		veh_type_ptr = &veh_type_array [line_ptr->Type ()];

		for (period = 0; period < num_periods; period++) {
			if (period_flag [period] == 0) continue;

			if (!Break_Check ((int) line_ptr->size () + 15)) {
				Print (1);
				Line_Rider_Header ();
			}
			veh_type_ptr = &veh_type_array [line_ptr->Type ()];

			Print (1, "   Route    Mode     Type   Time Period  Name");

			Print (2, String ("%8d  %10.10s %4d  %12.12s") % line_ptr->Route () %
				Transit_Code ((Transit_Type) line_ptr->Mode ()) % veh_type_ptr->Type () % 
				sum_periods.Range_Format (period));

			if (!line_ptr->Name ().empty ()) {
				Print (0, String ("  %s") % line_ptr->Name ());
			}
			if (Notes_Name_Flag ()) {
				if (!line_ptr->Notes ().empty ()) {
					Print (0, String (" -- %s") % line_ptr->Notes ());
				}
			}
			Print (2, "    Stop  Length   TTime   Alight    Board   Riders  Runs  LoadFac Capacity CapFac");
			Print (1);

			time = tot_time = 0.0;
			max_alight = max_board = max_riders = max_runs = total = length = tot_len = max_cap = 0;
			max_fac = vmt = vht = pmt = pht = max_capfac = 0.0;

			sum_periods.Period_Range (period, low, high);

			for (stop_itr = line_ptr->begin (); stop_itr != line_ptr->end (); stop_itr++) {
				riders = board = alight = runs = capacity = 0;

				stop_ptr = &stop_array [stop_itr->Stop ()];

				next_itr = stop_itr + 1;

				if (next_itr != line_ptr->end ()) {
					length = next_itr->Length () - stop_itr->Length ();
				} else {
					length = 0;
				}
				sum_time = 0.0;
				num = 0;

				for (run=0, run_itr = stop_itr->begin (); run_itr != stop_itr->end (); run_itr++, run++) {
					if (run_flag [run] == 0) continue;
					if (run_period [run] != period) continue;

					board += run_itr->Board ();
					alight += run_itr->Alight ();
					riders += run_itr->Load ();
					runs++;

					if (line_ptr->run_types.size () > 0) {
						run_type_ptr = &veh_type_array [line_ptr->Run_Type (run)];
						capacity += run_type_ptr->Capacity ();
					} else {
						capacity += veh_type_ptr->Capacity ();
					}
					if (next_itr != line_ptr->end ()) {
						time = next_itr->at (run).Schedule ().Seconds () - run_itr->Schedule ().Seconds ();

						vmt += length;
						vht += time;
						pmt += length * run_itr->Load ();
						pht += time * run_itr->Load ();

						sum_time += time;
						num++;
					}
				}
				if (runs == 0) continue;
				if (capacity == 0) capacity = runs;

				factor = (double) riders / runs;
				capfac = DTOI (riders * 10.0 / capacity) / 10.0;

				if (next_itr == line_ptr->end ()) runs = 0;

				if (num > 0) {
					time = sum_time / num;
				} else {
					time = 0;
				}
				Print (1, String ("%8d %7.0lf %7.0lf %8d %8d %8d %5d %8.1lf %6d %8.1lf") % stop_ptr->Stop () % 
					UnRound (length) % time % alight % board % riders % runs % factor % capacity % capfac);

				if (Notes_Name_Flag ()) {
					if (!stop_ptr->Name ().empty ()) {
						Print (0, String ("  %s") % stop_ptr->Name ());
					}
					if (!stop_ptr->Notes ().empty ()) {
						Print (0, " -- ") << stop_ptr->Notes ();
					}
				}
				if (alight > max_alight) max_alight = alight;
				if (board > max_board) max_board = board;
				if (riders > max_riders) max_riders = riders;
				if (runs > max_runs) max_runs = runs;
				if (factor > max_fac) max_fac = factor;
				if (capacity > max_cap) max_cap = capacity;
				if (capfac > max_capfac) max_capfac = capfac;

				tot_len += length;
				tot_time += time;
				total += board;
			}
			if (max_runs == 0) continue;

			Print (2, String (" Maximum                 %8ld %8ld %8ld %5ld %8.1lf %6lf %8.1lf") %
				max_alight % max_board % max_riders % max_runs % max_fac % max_cap % max_capfac);

			Print (2, "Total Boardings = ") << total;

			if (total == 0 || tot_time == 0) continue;

			factor = UnRound (tot_len);
			vmt = UnRound (vmt) / 5280.0;
			vht = vht / 3600.0;
			pmt = UnRound (pmt) / 5280.0;
			pht = pht / 3600.0;


			Print (1, String ("Route Length = %.1lf miles, %.1lf minutes  Average Speed = %.1lf mph") %
				External_Units (factor, MILES) % (tot_time / 60.0) % External_Units ((factor / tot_time), MPH));
			Print (1, String ("Vehicle Miles = %.1lf  Vehicle Hours = %.1lf") % vmt % vht);
			Print (1, String ("Passenger Miles = %.1lf  Passenger Hours = %.1lf") %	pmt % pht);
			Print (1, String ("Passengers per Vehicle Mile = %.1lf  Passengers per Vehicle Hour = %.1lf") %	
				(pmt / vht) % (pht / vht));

			vmt = pmt / total;
			vht = pht * 60.0 / total;

			Print (1, String ("Average Trip Length = %.1lf miles, %.1lf minutes") % vmt % vht);
		}
	}
	End_Progress ();

	Header_Number (0);
}
Ejemplo n.º 2
0
bool Db_Base::Write_Field (Db_Field *fld, void *data, Field_Type type)
{
	if (data == 0) return (Status (NULL_POINTER));
	if (fld == 0) return (Status (NO_FIELD, false));
	if (!Record ().OK ()) return (Status (RECORD_SIZE));

	int lvalue = 0;
	unsigned uvalue = 0;
	double dvalue = 0.0;
	Dtime tvalue;
	String svalue;
	Field_Type fld_type;

	//---- convert the input data type to generic variables ----

	fld_type = fld->Type ();

	switch (fld_type) {
		default:
			return (Status (DB_ERROR));
			
		case DB_INTEGER:
			switch (type) {
				case DB_INTEGER:
					lvalue = *((int *) data);
					break;
				case DB_DOUBLE:
					dvalue = *((double *) data);
					if (dvalue > MAX_INTEGER) {
						lvalue = MAX_INTEGER;
					} else if (dvalue < -MAX_INTEGER) {
						lvalue = -MAX_INTEGER;
					} else {
						lvalue = DTOI (dvalue);
					}
					break;
				case DB_STRING:
					lvalue = ((String *) data)->Integer ();
					break;
				case DB_TIME:
					lvalue = (int) (*((Dtime *) data));
					break;
				default:
					return (Status (DB_ERROR));
			}
			break;

		case DB_UNSIGNED:
			switch (type) {
				case DB_INTEGER:
					uvalue = *((unsigned *) data);
					break;
				case DB_DOUBLE:
					dvalue = *((double *) data);
					if (dvalue > 2.0 * MAX_INTEGER) {
						uvalue = MAX_INTEGER;
						uvalue *= 2;
					} else if (dvalue < 0.0) {
						uvalue = 0;
					} else {
						uvalue = (unsigned) (dvalue + 0.5);
					}
					break;
				case DB_STRING:
					uvalue = ((String *) data)->Integer ();
					break;
				case DB_TIME:
					uvalue = (unsigned) (*((Dtime *) data));
					break;
				default:
					return (Status (DB_ERROR));
			}
			break;

		case DB_FIXED:
		case DB_DOUBLE:
			switch (type) {
				case DB_INTEGER:
					dvalue = (double) *((int *) data);
					break;
				case DB_DOUBLE:
					dvalue = *((double *) data);
					break;
				case DB_STRING:
					dvalue = ((String *) data)->Double ();
					break;
				case DB_TIME:
					dvalue = (double) *((Dtime *) data);
					break;
				default:
					return (Status (DB_ERROR));
			}
			break;
		
		case DB_STRING:
		case DB_CHAR:
			switch (type) {
				case DB_INTEGER:
					if (fld->Units () >= FACILITY_CODE) {
						External_Units (*((int *) data), fld->Units (), svalue);
					} else {
						svalue (*((int *) data));
					}
					break;
				case DB_DOUBLE:
					svalue (*((double *) data), fld->Decimal ());
					break;
				case DB_STRING:
					svalue = *((string *) data);
					break;
				case DB_TIME:
					svalue = ((Dtime *) data)->Time_String (fld->Units ());
					break;
				default:
					return (Status (DB_ERROR));
			}
			break;

		case DB_TIME:
			switch (type) {
				case DB_INTEGER:
					tvalue = *((int *) data);
					break;
				case DB_DOUBLE:
					tvalue = *((double *) data);
					break;
				case DB_STRING:
					tvalue = *((string *) data);
					break;
				case DB_TIME:
					tvalue = *((Dtime *) data);
					break;
				default:
					return (Status (DB_ERROR));
			}
			break;
	}

	//---- convert to external units ----

	if (fld->Units () != NO_UNITS) {
		if (fld_type == DB_INTEGER) {
			lvalue = (int) External_Units (lvalue, fld->Units ());
		} else if (fld_type == DB_UNSIGNED) {
			uvalue = (unsigned) External_Units ((int) uvalue, fld->Units ());
		} else if (fld_type == DB_DOUBLE || fld_type == DB_FIXED) {
			dvalue = External_Units (dvalue, fld->Units ());
		} else if ((fld_type == DB_STRING || fld_type == DB_CHAR) && fld->Units () < FACILITY_CODE) {
			return (Status (FIELD_UNITS));
		}
	}

	//---- place the data onto the data record -----

	Nested (fld->Nested ());

	char *field = Record_String ();

	bool asc_flag = false;
	bool justify = false;
	int len, position;
	int size = fld->Width ();
	int offset = fld->Offset ();

	switch (Record_Format ()) {
		case BINARY:
			field += offset;
			asc_flag = false;
			break;
		case FIXED_COLUMN:
			field += offset;
			memset (field, ' ', size);
			asc_flag = justify = true;
			break;
		case COMMA_DELIMITED:
		case SPACE_DELIMITED:
		case TAB_DELIMITED:
		case CSV_DELIMITED:
		default:		
			asc_flag = true;
			justify = false;
			break;
	}

	switch (fld_type) {
		default:
			return (Status (DB_ERROR));
			
		case DB_INTEGER:
			if (asc_flag) {
				svalue (lvalue);

				if (justify) {
					len = (int) svalue.size ();
					position = size - len;
					if (position < 0) {
						position = 0;
						len = size;
					}
					memcpy (field + position, svalue.c_str (), len);
				}
			} else if (size == sizeof (int)) {
				*((int *) field) = lvalue;
			} else if (size == sizeof (short)) {
				if (lvalue > 32767) lvalue = 32767;
				*((short *) field) = (short) lvalue;
			} else if (size == sizeof (char)) {
				if (lvalue > 127) lvalue = 127;
				*((char *) field) = (char) lvalue;
			} else {
				return (Status (FIELD_BYTES));
			}
			break;
			
		case DB_UNSIGNED:
			if (asc_flag) {
				svalue ((size_t) uvalue);

				if (justify) {
					len = (int) svalue.size ();
					position = size - len;
					if (position < 0) {
						position = 0;
						len = size;
					}
					memcpy (field + position, svalue.c_str (), len);
				}
			} else if (size == sizeof (int)) {
				*((unsigned int *) field) = (unsigned int) uvalue;
			} else if (size == sizeof (short)) {
				if (uvalue > 65535) uvalue = 65535;
				*((unsigned short *) field) = (unsigned short) uvalue;
			} else if (size == sizeof (char)) {
				if (uvalue > 255) uvalue = 255;
				*((unsigned char *) field) = (unsigned char) uvalue;
			} else {
				return (Status (FIELD_BYTES));
			}
			break;

		case DB_DOUBLE:
			if (asc_flag) {
				svalue (dvalue, fld->Decimal ());
				if (justify) {
					len = (int) svalue.size ();
					position = size - len;
					if (position < 0) {
						position = 0;
						len = size;
					}
					memcpy (field + position, svalue.c_str (), len);
				}
			} else if (size == sizeof (double)) {
				*((double *) field) = dvalue;
			} else if (size == sizeof (float)) {
				*((float *) field) = (float) dvalue;
			} else {
				return (Status (FIELD_BYTES));
			}
			break;

		case DB_FIXED:
			if (asc_flag) {
				svalue (dvalue, fld->Decimal ());

				if (justify) {
					len = (int) svalue.size ();
					position = size - len;
					if (position < 0) {
						position = 0;
						len = size;
					}
					memcpy (field + position, svalue.c_str (), len);
				}
			} else {
				if (dvalue < 0.0) {
					lvalue = (int) (dvalue * pow (10.0, fld->Decimal ()) - 0.5);
				} else {
					lvalue = (int) (dvalue * pow (10.0, fld->Decimal ()) + 0.5);
				}

				if (size == sizeof (int)) {
					*((int *) field) = lvalue;
				} else if (size == sizeof (short)) {
					*((short *) field) = (short) lvalue;
				} else if (size == sizeof (char)) {
					*((char *) field) = (char) lvalue;
				} else {
					return (Status (FIELD_BYTES));
				}
			}
			break;

		case DB_STRING:
			if (asc_flag) {
				if (justify) {
					len = (int) svalue.size ();
					if (len > size) len = size;
					memcpy (field, svalue.c_str (), len);
				}
			} else {
				memset (field, '\0', size);
				memcpy (field, svalue.c_str (), MIN ((int) svalue.size (), size));
			}
			break;
			
		case DB_CHAR:
			if (!asc_flag || justify) {
				memset (field, '\0', size);
				field [0] = svalue [0];
			}
			break;
			
		case DB_TIME:
			if (asc_flag) {
				svalue = tvalue.Time_String (fld->Units ());
				if (justify) {
					len = (int) svalue.size ();
					if (len > size) len = size;
					memcpy (field, svalue.c_str (), len);
				}
			} else if (size == sizeof (Dtime)) {
				*((Dtime *) field) = tvalue;
			} else if (size == sizeof (short)) {
				*((short *) field) = (short) tvalue;
			} else {
				return (Status (FIELD_BYTES));
			}
			break;
	}
	if (asc_flag && !justify) {
		if (Record_Format () == UNFORMATED) {
			return (Set_Field_Number (offset, svalue));
		} else {
			fld->Buffer (svalue);
		}
	}
	return (true);
}
Ejemplo n.º 3
0
void RiderSum::Group_Rider_Report (void)
{
	int n, run, runs, num, length, tot_len, period, num_periods, routes, index, stop, to, link;
	int max_riders, max_board, max_alight, max_runs, total;
	double factor, max_fac, sum_time, tot_time, time;
	double vmt, vht, pmt, pht;
	Dtime low, high;
	String label;
	bool flag;

	Int_Set *group;
	Int_Set_Itr itr;
	Int_Map_Itr map_itr, to_itr;
	Line_Data *line_ptr;
	Stop_Data *stop_ptr;
	Line_Stop_Itr stop_itr, next_itr;
	Line_Run_Itr run_itr;
	Int_Map stop_index;
	Int2_Map link_index;
	Int2_Map_Itr map2_itr;
	Int2_Key int2_key;
	Int2_Map_Stat map2_stat;
	Int_Map_Stat map_stat;
	Stop_Group_Data data, *data_ptr, *link_ptr;
	Stop_Group_Itr data_itr;

	Show_Message ("Line Group Profile -- Record");
	Set_Progress ();

	//---- print the report ----

	Header_Number (GROUP_RIDERS);

	num_periods = sum_periods.Num_Periods ();
	if (num_periods == 0) num_periods = 1;

	num = (int) (line_map.size () * stop_map.size ());

	if (!Break_Check (num + 5)) {
		Print (1);
		Group_Rider_Header ();
	}

	routes = 0;
	memset (&data, '\0', sizeof (data));
	
	for (n = line_equiv.First_Group (); n > 0; n = line_equiv.Next_Group ()) {

		group = line_equiv.Group_List (n);
		if (group == 0) continue;

		label = line_equiv.Group_Label (n);

		//---- process each time period ----

		for (period = 0; period < num_periods; period++) {

			//---- initialize stop data ----

			stop_index.clear ();
			link_index.clear ();
			stop_group_array.clear ();
			routes = 0;
			vmt = vht = pmt = pht = 0.0;

			//---- process each line in the line group ----

			for (itr = group->begin (); itr != group->end (); itr++) {

				map_itr = line_map.find (*itr);
				if (map_itr == line_map.end ()) continue;

				Show_Progress ();

				line_ptr = &line_array [map_itr->second];

				//---- set the run flags ----

				if (!Run_Selection (line_ptr)) continue;

				if (period_flag [period] == 0) continue;

				time = 0.0;
				total = length = 0;
				flag = false;

				sum_periods.Period_Range (period, low, high);

				for (stop_itr = line_ptr->begin (); stop_itr != line_ptr->end (); stop_itr++) {

					stop_ptr = &stop_array [stop_itr->Stop ()];
					stop = stop_ptr->Stop ();

					map_itr = stop_index.find (stop);

					next_itr = stop_itr + 1;

					if (next_itr != line_ptr->end ()) {
						stop_ptr = &stop_array [next_itr->Stop ()];

						to = stop_ptr->Stop ();
					} else {
						to = 0;
					}

					//---- create the link ----

					int2_key = Int2_Key (stop, to);

					map2_itr = link_index.find (int2_key);

					if (map2_itr == link_index.end ()) {
						if (to == 0 && map_itr != stop_index.end ()) {
							link = map_itr->second;
						} else {
							link = (int) stop_group_array.size ();

							link_index.insert (Int2_Map_Data (int2_key, link));

							data.stop = stop;
							data.to = to;
							stop_group_array.push_back (data);

							//---- check for a merge ----

							if (to != 0) {
								to_itr = stop_index.find (to);

								if (to_itr != stop_index.end ()) {
									index = (int) stop_group_array.size ();

									int2_key = Int2_Key (to, 0);

									map2_stat = link_index.insert (Int2_Map_Data (int2_key, index));

									if (map2_stat.second) {
										data.stop = to;
										data.to = 0;
										stop_group_array.push_back (data);
									}
								}
							}
						}
					} else {
						link = map2_itr->second;
					}
					link_ptr = &stop_group_array [link];

					//---- crete the stop index ----

					if (map_itr == stop_index.end ()) {
						map_stat = stop_index.insert (Int_Map_Data (stop, link));
						index = link;
					} else {
						index = map_itr->second;
					}
					data_ptr = &stop_group_array [index];

					if (next_itr != line_ptr->end ()) {
						length = next_itr->Length () - stop_itr->Length ();
					} else {
						length = 0;
					}
					sum_time = 0.0;
					num = runs = 0;

					for (run=0, run_itr = stop_itr->begin (); run_itr != stop_itr->end (); run_itr++, run++) {
						if (run_flag [run] == 0) continue;
						if (run_period [run] != period) continue;

						data_ptr->board += run_itr->Board ();
						data_ptr->alight += run_itr->Alight ();
						link_ptr->riders += run_itr->Load ();
						runs++;
						flag = true;

						if (next_itr != line_ptr->end ()) {
							link_ptr->runs++;
							time = next_itr->at (run).Schedule ().Seconds () - run_itr->Schedule ().Seconds ();
							sum_time += time;
							num++;

							vmt += length;
							vht += time;
							pmt += length * run_itr->Load ();
							pht += time * run_itr->Load ();
						}
					}
					if (runs == 0) continue;

					if (link_ptr->length == 0.0) {
						link_ptr->length = length;
					}
					if (num > 0) {
						time = sum_time / num;
					} else {
						time = 0;
					}
					if (link_ptr->time > 0) {
						link_ptr->time = (link_ptr->time + time) / 2.0;
					} else {
						link_ptr->time = time;
					}
				}
				if (flag) routes++;
			}

			//---- print the report ----

			if (!Break_Check ((int) stop_index.size () + 15)) {
				Print (1);
				Group_Rider_Header ();
			}
			Print (1, "Group   Time Period  Routes  Description");

			Print (2, String ("%5d  %12.12s  %6d  %s") % n %	sum_periods.Range_Format (period) %
				routes % label);

			Print (2, "    Stop  Length   TTime   Alight    Board   Riders  Runs  LoadFac");
			Print (1);

			tot_time = 0.0;
			max_alight = max_board = max_riders = max_runs = total = tot_len = 0;
			max_fac = 0.0;

			for (data_itr = stop_group_array.begin (); data_itr != stop_group_array.end (); data_itr++) {

				map_itr = stop_map.find (data_itr->stop);
					
				stop_ptr = &stop_array [map_itr->second];
				
				if (data_itr->runs > 0) {
					factor = DTOI (data_itr->riders * 10.0 / data_itr->runs) / 10.0;
				} else {
					factor = 0.0;
				}
				Print (1, String ("%8d %7.0lf %7.0lf %8d %8d %8d %5d %8.1lf") % data_itr->stop  % 
					UnRound (data_itr->length) % data_itr->time % data_itr->alight % data_itr->board % 
					data_itr->riders % data_itr->runs % factor);

				if (Notes_Name_Flag ()) {
					if (!stop_ptr->Name ().empty ()) {
						Print (0, String ("  %s") % stop_ptr->Name ());
					}
					if (!stop_ptr->Notes ().empty ()) {
						Print (0, " -- ") << stop_ptr->Notes ();
					}
				}
				if (data_itr->alight > max_alight) max_alight = data_itr->alight;
				if (data_itr->board > max_board) max_board = data_itr->board;
				if (data_itr->riders > max_riders) max_riders = data_itr->riders;
				if (data_itr->runs > max_runs) max_runs = data_itr->runs;
				if (factor > max_fac) max_fac = factor;

				tot_len += data_itr->length;
				tot_time += data_itr->time;
				total += data_itr->board;
			}
			if (max_runs == 0) continue;

			Print (2, String (" Maximum                 %8ld %8ld %8ld %5ld %8.1lf") %
				max_alight % max_board % max_riders % max_runs % max_fac);

			Print (2, "Total Boardings = ") << total;

			if (total == 0 || tot_time == 0) continue;

			factor = UnRound (tot_len);
			vmt = UnRound (vmt) / 5280.0;
			vht = vht / 3600.0;
			pmt = UnRound (pmt) / 5280.0;
			pht = pht / 3600.0;


			Print (1, String ("Route Length = %.1lf miles, %.1lf minutes  Average Speed = %.1lf mph") %
				External_Units (factor, MILES) % (tot_time / 60.0) % External_Units ((factor / tot_time), MPH));
			Print (1, String ("Vehicle Miles = %.1lf  Vehicle Hours = %.1lf") % vmt % vht);
			Print (1, String ("Passenger Miles = %.1lf  Passenger Hours = %.1lf") %	pmt % pht);
			Print (1, String ("Passengers per Vehicle Mile = %.1lf  Passengers per Vehicle Hour = %.1lf") %	
				(pmt / vht) % (pht / vht));

			vmt = pmt / total;
			vht = pht * 60.0 / total;

			Print (1, String ("Average Trip Length = %.1lf miles, %.1lf minutes") % vmt % vht);
		}
	}
	End_Progress ();

	Header_Number (0);
}
Ejemplo n.º 4
0
int Data_Service::Put_Link_Data (Link_File &file, Link_Data &data)
{
	if (file.Model_Format () == TPPLUS) {
		int a, b, count;
		double length;
		Dir_Data *dir_ptr;

		if (data.Length () == 0) return (0);

		count = 0;
		a = data.Anode ();
		b = data.Bnode ();
		length = UnRound (data.Length ());

		if (System_Data_Flag (NODE)) {
			a = node_array [a].Node ();
			b = node_array [b].Node ();
		}
		if (data.AB_Dir () >= 0) {
			file.Node_A (a);
			file.Node_B (b);
			file.Length (length);
			file.Type (data.Type ());

			dir_ptr = &dir_array [data.AB_Dir ()];

			file.Lanes_AB (dir_ptr->Lanes ());
			file.Speed_AB (UnRound (dir_ptr->Speed ()));
			file.Cap_AB (dir_ptr->Capacity ());

			if (file.Dbase_Format () == ARCVIEW) {
				Link_Shape (&data, 0, *((Arc_Link_File *) &file));
			}
			if (!file.Write_Record ()) {
				Error (String ("Writing %s") % file.File_Type ());
			}
			count++;
		}
		if (data.BA_Dir () >= 0) {
			file.Node_A (b);
			file.Node_B (a);
			file.Length (length);
			file.Type (data.Type ());

			dir_ptr = &dir_array [data.BA_Dir ()];

			file.Lanes_AB (dir_ptr->Lanes ());
			file.Speed_AB (UnRound (dir_ptr->Speed ()));
			file.Cap_AB (dir_ptr->Capacity ());

			if (file.Dbase_Format () == ARCVIEW) {
				Link_Shape (&data, 1, *((Arc_Link_File *) &file));
			}
			if (!file.Write_Record ()) {
				Error (String ("Writing %s") % file.File_Type ());
			}
			count++;
		}
		return (count);
	}
	Dir_Data *dir_ptr;

	if (data.Length () == 0) return (0);

	file.Link (data.Link ());
	file.Name (data.Name ());
	file.Node_A (node_array [data.Anode ()].Node ());
	file.Node_B (node_array [data.Bnode ()].Node ());
	file.Length (UnRound (data.Length ()));
	file.Setback_A (UnRound (data.Aoffset ()));
	file.Setback_B (UnRound (data.Boffset ()));
	file.Type (data.Type ());
	file.Divided (data.Divided ());
	file.Area_Type (data.Area_Type ());
	file.Use (data.Use ());
	file.Grade (UnRound (data.Grade ()));
	file.Notes (data.Notes ());

	if (data.AB_Dir () >= 0) {
		dir_ptr = &dir_array [data.AB_Dir ()];

		file.Lanes_AB (dir_ptr->Lanes ());
		file.Speed_AB (UnRound (dir_ptr->Speed ()));

		if (dir_ptr->Time0 () > 0) {
			file.Fspd_AB ((double) data.Length () / dir_ptr->Time0 ());
		} else {
			file.Fspd_AB (UnRound (dir_ptr->Speed ()));
		}
		if (file.Fspd_AB () > file.Speed_AB () && file.Speed_AB () > 0) {
			if ((file.Fspd_AB () - file.Speed_AB ()) > 0.5) {
				if (Metric_Flag ()) {
					Warning (String ("Link %d Free Flow Speed %.1lf > Maximum Speed %.1lf") % data.Link () % External_Units (file.Fspd_AB (), MPH) % 
						External_Units (file.Speed_AB (), MPH));
				} else {
					Warning (String ("Link %d Free Flow Speed %.1lf > Maximum Speed %.1lf") % data.Link () % External_Units (file.Fspd_AB (), MPH) % 
						External_Units (file.Speed_AB (), MPH));
				}
			}
			file.Fspd_AB (file.Speed_AB ());
		}
		file.Cap_AB (dir_ptr->Capacity ());
		file.Bearing_A (dir_ptr->In_Bearing ());
		file.Bearing_B (dir_ptr->Out_Bearing ());
	} else {
		file.Lanes_AB (0);
		file.Speed_AB (0);
		file.Fspd_AB (0);
		file.Cap_AB (0);
	}
	if (data.BA_Dir () >= 0) {
		dir_ptr = &dir_array [data.BA_Dir ()];

		file.Lanes_BA (dir_ptr->Lanes ());
		file.Speed_BA (UnRound (dir_ptr->Speed ()));

		if (dir_ptr->Time0 () > 0) {
			file.Fspd_BA ((double) data.Length () / dir_ptr->Time0 ());
		} else {
			file.Fspd_BA (UnRound (dir_ptr->Speed ()));
		}
		if (file.Fspd_BA () > file.Speed_BA () && file.Speed_BA () > 0) {
			if ((file.Fspd_BA () - file.Speed_BA ()) > 0.5) {
				if (Metric_Flag ()) {
					Warning (String ("Link %d Free Flow Speed %.1lf > Maximum Speed %.1lf") % data.Link () % External_Units (file.Fspd_BA (), MPH) % 
						External_Units (file.Speed_BA (), MPH));
				} else {
					Warning (String ("Link %d Free Flow Speed %.1lf > Maximum Speed %.1lf") % data.Link () % External_Units (file.Fspd_BA (), MPH) % 
						External_Units (file.Speed_BA (), MPH));
				}
			}
			file.Fspd_BA (file.Speed_BA ());
		}
		file.Cap_BA (dir_ptr->Capacity ());
		if (data.AB_Dir () < 0) {
			file.Bearing_B (compass.Flip (dir_ptr->In_Bearing ()));
			file.Bearing_A (compass.Flip (dir_ptr->Out_Bearing ()));
		}
	} else {
		file.Lanes_BA (0);
		file.Speed_BA (0);
		file.Fspd_BA (0);
		file.Cap_BA (0);
	}
	if (file.Dbase_Format () == ARCVIEW) {
		Link_Shape (&data, 0, *((Arc_Link_File *) &file));
	}
	if (!file.Write_Record ()) {
		Error (String ("Writing %s") % file.File_Type ());
	}
	return (1);
}