1 // runwayprefs.cxx - class implementations corresponding to runwayprefs.hxx
2 // assignments by the AI code
4 // Written by Durk Talsma, started January 2005.
6 // Copyright (C) 2004 Durk Talsma.
8 // This program is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU General Public License as
10 // published by the Free Software Foundation; either version 2 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful, but
14 // WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // General Public License for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
29 //#include <algorithm>
31 #include <simgear/compiler.h>
33 //#include <plib/sg.h>
34 //#include <plib/ul.h>
36 //#include <Environment/environment_mgr.hxx>
37 //#include <Environment/environment.hxx>
38 //#include <simgear/misc/sg_path.hxx>
39 //#include <simgear/props/props.hxx>
40 //#include <simgear/structure/subsystem_mgr.hxx>
41 #include <simgear/debug/logstream.hxx>
42 #include <Main/globals.hxx>
43 //#include <Main/fg_props.hxx>
44 #include <Airports/runways.hxx>
46 #include "runwayprefs.hxx"
49 /******************************************************************************
51 ***************e*************************************************************/
52 void ScheduleTime::clear()
56 scheduleNames.clear();
60 ScheduleTime::ScheduleTime(const ScheduleTime &other)
63 timeVecConstIterator i;
64 for (i = other.start.begin(); i != other.start.end(); i++)
66 for (i = other.end.begin(); i != other.end.end(); i++)
68 stringVecConstIterator k;
69 for (k = other.scheduleNames.begin(); k != other.scheduleNames.end(); k++)
70 scheduleNames.push_back(*k);
73 //stringVec scheduleNames;
74 tailWind = other.tailWind;
75 crssWind = other.tailWind;
79 ScheduleTime & ScheduleTime::operator= (const ScheduleTime &other)
83 timeVecConstIterator i;
84 for (i = other.start.begin(); i != other.start.end(); i++)
86 for (i = other.end.begin(); i != other.end.end(); i++)
88 stringVecConstIterator k;
89 for (k = other.scheduleNames.begin(); k != other.scheduleNames.end(); k++)
90 scheduleNames.push_back(*k);
93 //stringVec scheduleNames;
94 tailWind = other.tailWind;
95 crssWind = other.tailWind;
98 string ScheduleTime::getName(time_t dayStart)
100 if ((start.size() != end.size()) || (start.size() != scheduleNames.size()))
102 SG_LOG( SG_GENERAL, SG_INFO, "Unable to parse schedule times" );
107 int nrItems = start.size();
108 //cerr << "Nr of items to process: " << nrItems << endl;
111 for (unsigned int i = 0; i < start.size(); i++)
114 if ((dayStart >= start[i]) && (dayStart <= end[i]))
115 return scheduleNames[i];
118 //couldn't find one so return 0;
119 //cerr << "Returning 0 " << endl;
123 /******************************************************************************
125 *****************************************************************************/
127 RunwayList::RunwayList(const RunwayList &other)
130 stringVecConstIterator i;
131 for (i = other.preferredRunways.begin(); i != other.preferredRunways.end(); i++)
132 preferredRunways.push_back(*i);
134 RunwayList& RunwayList::operator= (const RunwayList &other)
137 preferredRunways.clear();
138 stringVecConstIterator i;
139 for (i = other.preferredRunways.begin(); i != other.preferredRunways.end(); i++)
140 preferredRunways.push_back(*i);
143 void RunwayList::set(const string &tp, const string &lst)
145 //weekday = atoi(timeCopy.substr(0,1).c_str());
146 // timeOffsetInDays = weekday - currTimeDate->getGmt()->tm_wday;
147 // timeCopy = timeCopy.substr(2,timeCopy.length());
151 while (rwys.find(",") != string::npos)
153 rwy = rwys.substr(0, rwys.find(",",0));
154 //cerr << "adding runway [" << rwy << "] to the list " << endl;
155 preferredRunways.push_back(rwy);
156 rwys.erase(0, rwys.find(",",0)+1); // erase until after the first whitspace
157 while (rwys[0] == ' ')
158 rwys.erase(0, 1); // Erase any leading whitespaces.
159 //cerr << "Remaining runway list " << rwys;
161 preferredRunways.push_back(rwys);
165 void RunwayList::clear()
168 preferredRunways.clear();
170 /****************************************************************************
172 ***************************************************************************/
174 RunwayGroup::RunwayGroup(const RunwayGroup &other)
177 RunwayListVecConstIterator i;
178 for (i = other.rwyList.begin(); i != other.rwyList.end(); i++)
179 rwyList.push_back(*i);
180 choice[0] = other.choice[0];
181 choice[1] = other.choice[1];
182 nrActive = other.nrActive;
184 RunwayGroup& RunwayGroup:: operator= (const RunwayGroup &other)
188 RunwayListVecConstIterator i;
189 for (i = other.rwyList.begin(); i != other.rwyList.end(); i++)
190 rwyList.push_back(*i);
191 choice[0] = other.choice[0];
192 choice[1] = other.choice[1];
193 nrActive = other.nrActive;
197 void RunwayGroup::setActive(const string &aptId,
202 stringVec *currentlyActive)
206 int activeRwys = rwyList.size(); // get the number of runways active
208 // bool found = true;
215 int bestMatch = 0, bestChoice = 0;
219 // Now downward iterate across all the possible preferences
220 // starting by the least preferred choice working toward the most preferred choice
222 nrOfPreferences = rwyList[0].getRwyList()->size();
223 bool validSelection = true;
224 bool foundValidSelection = false;
225 for (int i = nrOfPreferences-1; i >= 0; i--)
230 // Test each runway listed in the preference to see if it's possible to use
231 // If one runway of the selection isn't allowed, we need to exclude this
232 // preference, however, we don't want to stop right there, because we also
233 // don't want to randomly swap runway preferences, unless there is a need to.
235 validSelection = true;
236 for (int j = 0; j < activeRwys; j++)
239 name = rwyList[j].getRwyList(i);
240 //cerr << "Name of Runway: " << name;
241 if (globals->get_runways()->search( aptId,
245 //cerr << "Succes" << endl;
246 hdgDiff = fabs(windHeading - rwy._heading);
247 //cerr << "Wind Heading: " << windHeading << "Runway Heading: " <<rwy._heading << endl;
248 //cerr << "Wind Speed : " << windSpeed << endl;
250 hdgDiff = 360 - hdgDiff;
251 //cerr << "Heading diff: " << hdgDiff << endl;
252 hdgDiff *= ((2*M_PI)/360.0); // convert to radians
253 crossWind = windSpeed * sin(hdgDiff);
254 tailWind = -windSpeed * cos(hdgDiff);
255 //cerr << ". Tailwind : " << tailWind;
256 //cerr << ". Crosswnd : " << crossWind;
257 if ((tailWind > maxTail) || (crossWind > maxCross))
259 //cerr << ". [Invalid] " << endl;
260 validSelection = false;
264 //cerr << ". [Valid] ";
267 SG_LOG( SG_GENERAL, SG_INFO, "Failed to find runway " << name << " at " << aptId );
274 //cerr << "Valid selection : " << i << endl;;
275 foundValidSelection = true;
276 for (stringVecIterator it = currentlyActive->begin();
277 it != currentlyActive->end(); it++)
282 if (match >= bestMatch) {
287 //cerr << "Preference " << i << " bestMatch " << bestMatch << " choice " << bestChoice << endl;
289 if (foundValidSelection)
291 //cerr << "Valid runay selection : " << bestChoice << endl;
292 nrActive = activeRwys;
296 // If this didn't work, due to heavy winds, try again
297 // but select only one landing and one takeoff runway.
300 for (int i = activeRwys-1; i; i--)
302 if (rwyList[i].getType() == string("landing"))
304 if (rwyList[i].getType() == string("takeoff"))
307 //cerr << "Choosing " << choice[0] << " for landing and " << choice[1] << "for takeoff" << endl;
308 nrOfPreferences = rwyList[0].getRwyList()->size();
309 for (int i = 0; i < nrOfPreferences; i++)
311 bool validSelection = true;
312 for (int j = 0; j < 2; j++)
314 //cerr << "I J " << i << " " << j << endl;
315 name = rwyList[choice[j]].getRwyList(i);
316 //cerr << "Name of Runway: " << name << endl;
317 if (globals->get_runways()->search( aptId,
321 //cerr << "Succes" << endl;
322 hdgDiff = fabs(windHeading - rwy._heading);
324 hdgDiff = 360 - hdgDiff;
325 hdgDiff *= ((2*M_PI)/360.0); // convert to radians
326 crossWind = windSpeed * sin(hdgDiff);
327 tailWind = -windSpeed * cos(hdgDiff);
328 if ((tailWind > maxTail) || (crossWind > maxCross))
329 validSelection = false;
331 SG_LOG( SG_GENERAL, SG_INFO, "Failed to find runway " << name << " at " << aptId );
338 //cerr << "Valid runay selection : " << i << endl;
349 void RunwayGroup::getActive(int i, string &name, string &type)
355 if (nrActive == (int)rwyList.size())
357 name = rwyList[i].getRwyList(active);
358 type = rwyList[i].getType();
362 name = rwyList[choice[i]].getRwyList(active);
363 type = rwyList[choice[i]].getType();
366 /*****************************************************************************
367 * FGRunway preference
368 ****************************************************************************/
369 FGRunwayPreference::FGRunwayPreference(FGAirport* ap) :
372 //cerr << "Running default Constructor" << endl;
376 FGRunwayPreference::FGRunwayPreference(const FGRunwayPreference &other)
378 initialized = other.initialized;
380 comTimes = other.comTimes; // Commercial Traffic;
381 genTimes = other.genTimes; // General Aviation;
382 milTimes = other.milTimes; // Military Traffic;
384 PreferenceListConstIterator i;
385 for (i = other.preferences.begin(); i != other.preferences.end(); i++)
386 preferences.push_back(*i);
389 FGRunwayPreference & FGRunwayPreference::operator= (const FGRunwayPreference &other)
391 initialized = other.initialized;
393 comTimes = other.comTimes; // Commercial Traffic;
394 genTimes = other.genTimes; // General Aviation;
395 milTimes = other.milTimes; // Military Traffic;
397 PreferenceListConstIterator i;
399 for (i = other.preferences.begin(); i != other.preferences.end(); i++)
400 preferences.push_back(*i);
404 ScheduleTime *FGRunwayPreference::getSchedule(const char *trafficType)
406 if (!(strcmp(trafficType, "com"))) {
409 if (!(strcmp(trafficType, "gen"))) {
412 if (!(strcmp(trafficType, "mil"))) {
418 RunwayGroup *FGRunwayPreference::getGroup(const string &groupName)
420 PreferenceListIterator i = preferences.begin();
421 if (preferences.begin() == preferences.end())
423 while (!(i == preferences.end() || i->getName() == groupName))
425 if (i != preferences.end())
431 string FGRunwayPreference::getId() {