]> git.mxchange.org Git - flightgear.git/blob - src/Traffic/SchedFlight.cxx
ATISEncoder: minor tweak
[flightgear.git] / src / Traffic / SchedFlight.cxx
1 /******************************************************************************
2  * SchedFlight.cxx
3  * Written by Durk Talsma, started May 5, 2004.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18  *
19  *
20  **************************************************************************/
21  
22 /* This a prototype version of a top-level flight plan manager for Flightgear.
23  * It parses the fgtraffic.txt file and determine for a specific time/date, 
24  * where each aircraft listed in this file is at the current time. 
25  * 
26  * I'm currently assuming the following simplifications:
27  * 1) The earth is a perfect sphere
28  * 2) Each aircraft flies a perfect great circle route.
29  * 3) Each aircraft flies at a constant speed (with infinite accelerations and
30  *    decelerations) 
31  * 4) Each aircraft leaves at exactly the departure time. 
32  * 5) Each aircraft arrives at exactly the specified arrival time. 
33  *
34  * TODO:
35  * - Check the code for known portability issues
36  *
37  *****************************************************************************/
38
39 #ifdef HAVE_CONFIG_H
40 #  include "config.h"
41 #endif
42
43 #include <stdlib.h>
44 #include <time.h>
45 #include <iostream>
46 #include <fstream>
47
48
49 #include <string>
50 #include <vector>
51
52 #include <simgear/compiler.h>
53 #include <simgear/props/props.hxx>
54 #include <simgear/structure/subsystem_mgr.hxx>
55 #include <simgear/timing/sg_time.hxx>
56 #include <simgear/xml/easyxml.hxx>
57
58 #include <AIModel/AIFlightPlan.hxx>
59 #include <AIModel/AIManager.hxx>
60 #include <Airports/airport.hxx>
61 #include <Main/fg_init.hxx>   // That's pretty ugly, but I need fgFindAirportID
62
63
64
65 #include <Main/globals.hxx>
66
67 #include "SchedFlight.hxx"
68
69 using std::string;
70
71 /******************************************************************************
72  * FGScheduledFlight stuff
73  *****************************************************************************/
74
75 FGScheduledFlight::FGScheduledFlight()
76 {
77     departureTime  = 0;
78     arrivalTime    = 0;
79     cruiseAltitude = 0;
80     repeatPeriod   = 0;
81     initialized = false;
82     available = true;
83     departurePort = NULL;
84     arrivalPort = NULL;
85 }
86   
87 FGScheduledFlight::FGScheduledFlight(const FGScheduledFlight &other)
88 {
89   callsign          = other.callsign;
90   fltRules          = other.fltRules;
91   departurePort     = other.departurePort;
92   depId             = other.depId;
93   arrId             = other.arrId;
94   departureTime     = other.departureTime;
95   cruiseAltitude    = other.cruiseAltitude;
96   arrivalPort       = other.arrivalPort;
97   arrivalTime       = other.arrivalTime;
98   repeatPeriod      = other.repeatPeriod;
99   initialized       = other.initialized;
100   requiredAircraft  = other.requiredAircraft;
101   available         = other.available;
102 }
103
104 FGScheduledFlight::FGScheduledFlight(const string& cs,
105                    const string& fr,
106                    const string& depPrt,
107                    const string& arrPrt,
108                    int cruiseAlt,
109                    const string& deptime,
110                    const string& arrtime,
111                    const string& rep,
112                    const string& reqAC)
113 {
114   callsign          = cs;
115   fltRules          = fr;
116   //departurePort.setId(depPrt);
117   //arrivalPort.setId(arrPrt);
118   depId = depPrt;
119   arrId = arrPrt;
120   //cerr << "Constructor: departure " << depId << ". arrival " << arrId << endl;
121   //departureTime     = processTimeString(deptime);
122   //arrivalTime       = processTimeString(arrtime);
123   cruiseAltitude    = cruiseAlt;
124   requiredAircraft  = reqAC;
125
126   // Process the repeat period string
127   if (rep.find("WEEK",0) != string::npos)
128     {
129       repeatPeriod = 7*24*60*60; // in seconds
130     }
131   else if (rep.find("Hr", 0) != string::npos)
132     {
133       repeatPeriod = 60*60*atoi(rep.substr(0,2).c_str());
134     }
135   else
136     {
137       repeatPeriod = 365*24*60*60;
138       SG_LOG( SG_AI, SG_ALERT, "Unknown repeat period in flight plan "
139                                     "of flight '" << cs << "': " << rep );
140     }
141
142   // What we still need to do is preprocess the departure and
143   // arrival times. 
144   departureTime = processTimeString(deptime);
145   arrivalTime   = processTimeString(arrtime);
146   //departureTime += rand() % 300; // Make sure departure times are not limited to 5 minute increments.
147   if (departureTime > arrivalTime)
148     {
149       departureTime -= repeatPeriod;
150     }
151   initialized = false;
152   available   = true;
153 }
154
155
156 FGScheduledFlight:: ~FGScheduledFlight()
157 {
158 }
159
160 time_t FGScheduledFlight::processTimeString(const string& theTime)
161 {
162   int weekday;
163   int timeOffsetInDays;
164   int targetHour;
165   int targetMinute;
166   int targetSecond;
167
168   tm targetTimeDate;
169   SGTime* currTimeDate = globals->get_time_params();
170  
171   string timeCopy = theTime;
172
173
174   // okay first split theTime string into
175   // weekday, hour, minute, second;
176   // Check if a week day is specified 
177   if (timeCopy.find("/",0) != string::npos)
178     {
179       weekday          = atoi(timeCopy.substr(0,1).c_str());
180       timeOffsetInDays = weekday - currTimeDate->getGmt()->tm_wday;
181       timeCopy = timeCopy.substr(2,timeCopy.length());
182     }
183   else 
184     {
185       timeOffsetInDays = 0;
186     }
187   // TODO: verify status of each token.
188   targetHour   = atoi(timeCopy.substr(0,2).c_str());
189   targetMinute = atoi(timeCopy.substr(3,5).c_str());
190   targetSecond = atoi(timeCopy.substr(6,8).c_str());
191   targetTimeDate.tm_year  = currTimeDate->getGmt()->tm_year;
192   targetTimeDate.tm_mon   = currTimeDate->getGmt()->tm_mon;
193   targetTimeDate.tm_mday  = currTimeDate->getGmt()->tm_mday;
194   targetTimeDate.tm_hour  = targetHour;
195   targetTimeDate.tm_min   = targetMinute;
196   targetTimeDate.tm_sec   = targetSecond;
197
198   time_t processedTime = sgTimeGetGMT(&targetTimeDate);
199   processedTime += timeOffsetInDays*24*60*60;
200   if (processedTime < currTimeDate->get_cur_time())
201     {
202       processedTime += repeatPeriod;
203     }
204   //tm *temp = currTimeDate->getGmt();
205   //char buffer[512];
206   //sgTimeFormatTime(&targetTimeDate, buffer);
207   //cout << "Scheduled Time " << buffer << endl; 
208   //cout << "Time :" << time(NULL) << " SGTime : " << sgTimeGetGMT(temp) << endl;
209   return processedTime;
210 }
211
212 void FGScheduledFlight::update()
213 {
214   departureTime += repeatPeriod;
215   arrivalTime  += repeatPeriod;
216 }
217
218 void FGScheduledFlight::adjustTime(time_t now)
219 {
220   //cerr << "1: Adjusting schedule please wait: " << now 
221   //   << " " << arrivalTime << " " << arrivalTime+repeatPeriod << endl;
222   // Make sure that the arrival time is in between 
223   // the current time and the next repeat period.
224   while ((arrivalTime < now) || (arrivalTime > now+repeatPeriod))
225     {
226       if (arrivalTime < now)
227         {
228           departureTime += repeatPeriod;
229           arrivalTime   += repeatPeriod;
230         }
231       else if (arrivalTime > now+repeatPeriod)
232         {
233           departureTime -= repeatPeriod;
234           arrivalTime   -= repeatPeriod;
235         }
236       //      cerr << "2: Adjusting schedule please wait: " << now 
237       //   << " " << arrivalTime << " " << arrivalTime+repeatPeriod << endl;
238     }
239 }
240
241
242 FGAirport *FGScheduledFlight::getDepartureAirport()
243 {
244   if (!(initialized))
245     {
246       initializeAirports();
247     }
248   if (initialized)
249     return departurePort;
250   else
251     return 0;
252 }
253 FGAirport * FGScheduledFlight::getArrivalAirport  ()
254 {
255    if (!(initialized))
256     {
257       initializeAirports();
258     }
259    if (initialized)
260      return arrivalPort;
261    else
262      return 0;
263 }
264
265 // Upon the first time of requesting airport information
266 // for this scheduled flight, these data need to be
267 // looked up in the main FlightGear database. 
268 // Missing or bogus Airport codes are currently ignored,
269 // but we should improve that. The best idea is probably to cancel
270 // this flight entirely by removing it from the schedule, if one
271 // of the airports cannot be found. 
272 bool FGScheduledFlight::initializeAirports()
273 {
274   //cerr << "Initializing using : " << depId << " " << arrId << endl;
275   departurePort = FGAirport::findByIdent(depId);
276   if(departurePort == NULL)
277     {
278       SG_LOG( SG_AI, SG_DEBUG, "Traffic manager could not find departure airport : " << depId);
279       return false;
280     }
281   arrivalPort = FGAirport::findByIdent(arrId);
282   if(arrivalPort == NULL)
283     {
284       SG_LOG( SG_AI, SG_DEBUG, "Traffic manager could not find arrival airport   : " << arrId);
285       return false;
286     }
287
288   //cerr << "Found : " << departurePort->getId() << endl;
289   //cerr << "Found : " << arrivalPort->getId() << endl;
290   initialized = true;
291   return true;
292 }
293
294
295 bool compareScheduledFlights(FGScheduledFlight *a, FGScheduledFlight *b) 
296
297   return (*a) < (*b); 
298 };