1 //       _________ __                 __
2 //      /   _____//  |_____________ _/  |______     ____  __ __  ______
3 //      \_____  \\   __\_  __ \__  \\   __\__  \   / ___\|  |  \/  ___/
4 //      /        \|  |  |  | \// __ \|  |  / __ \_/ /_/  >  |  /\___ |
5 //     /_______  /|__|  |__|  (____  /__| (____  /\___  /|____//____  >
6 //             \/                  \/          \//_____/            \/
7 //  ______________________                           ______________________
8 //                        T H E   W A R   B E G I N S
9 //         Stratagus - A free fantasy real time strategy game engine
10 //
11 /**@name season_schedule.cpp - The season schedule source file. */
12 //
13 //      (c) Copyright 2018-2019 by Andrettin
14 //
15 //      This program is free software; you can redistribute it and/or modify
16 //      it under the terms of the GNU General Public License as published by
17 //      the Free Software Foundation; only version 2 of the License.
18 //
19 //      This program is distributed in the hope that it will be useful,
20 //      but WITHOUT ANY WARRANTY; without even the implied warranty of
21 //      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 //      GNU General Public License for more details.
23 //
24 //      You should have received a copy of the GNU General Public License
25 //      along with this program; if not, write to the Free Software
26 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 //      02111-1307, USA.
28 //
29 
30 //@{
31 
32 /*----------------------------------------------------------------------------
33 --  Includes
34 ----------------------------------------------------------------------------*/
35 
36 #include "stratagus.h"
37 
38 #include "time/season_schedule.h"
39 
40 #include "config.h"
41 #include "time/season.h"
42 
43 /*----------------------------------------------------------------------------
44 --  Variables
45 ----------------------------------------------------------------------------*/
46 
47 std::vector<CSeasonSchedule *> CSeasonSchedule::SeasonSchedules;
48 std::map<std::string, CSeasonSchedule *> CSeasonSchedule::SeasonSchedulesByIdent;
49 CSeasonSchedule *CSeasonSchedule::DefaultSeasonSchedule = nullptr;
50 
51 /*----------------------------------------------------------------------------
52 --  Functions
53 ----------------------------------------------------------------------------*/
54 
55 /**
56 **	@brief	Get a season schedule
57 **
58 **	@param	ident			The season schedule's string identifier
59 **	@param	should_find		Whether it is an error if the season schedule could not be found; this is true by default
60 **
61 **	@return	The season schedule if found, or null otherwise
62 */
GetSeasonSchedule(const std::string & ident,const bool should_find)63 CSeasonSchedule *CSeasonSchedule::GetSeasonSchedule(const std::string &ident, const bool should_find)
64 {
65 	std::map<std::string, CSeasonSchedule *>::const_iterator find_iterator = SeasonSchedulesByIdent.find(ident);
66 
67 	if (find_iterator != SeasonSchedulesByIdent.end()) {
68 		return find_iterator->second;
69 	}
70 
71 	if (should_find) {
72 		fprintf(stderr, "Invalid season schedule: \"%s\".\n", ident.c_str());
73 	}
74 
75 	return nullptr;
76 }
77 
78 /**
79 **	@brief	Get or add a season schedule
80 **
81 **	@param	ident	The season schedule's string identifier
82 **
83 **	@return	The season schedule if found, or a newly-created one otherwise
84 */
GetOrAddSeasonSchedule(const std::string & ident)85 CSeasonSchedule *CSeasonSchedule::GetOrAddSeasonSchedule(const std::string &ident)
86 {
87 	CSeasonSchedule *season_schedule = GetSeasonSchedule(ident, false);
88 
89 	if (!season_schedule) {
90 		season_schedule = new CSeasonSchedule;
91 		season_schedule->Ident = ident;
92 		SeasonSchedules.push_back(season_schedule);
93 		SeasonSchedulesByIdent[ident] = season_schedule;
94 	}
95 
96 	return season_schedule;
97 }
98 
99 /**
100 **	@brief	Remove the existing season schedules
101 */
ClearSeasonSchedules()102 void CSeasonSchedule::ClearSeasonSchedules()
103 {
104 	for (size_t i = 0; i < SeasonSchedules.size(); ++i) {
105 		delete SeasonSchedules[i];
106 	}
107 	SeasonSchedules.clear();
108 }
109 
110 /**
111 **	@brief	Destructor
112 */
~CSeasonSchedule()113 CSeasonSchedule::~CSeasonSchedule()
114 {
115 	for (size_t i = 0; i < this->ScheduledSeasons.size(); ++i) {
116 		delete this->ScheduledSeasons[i];
117 	}
118 }
119 
120 /**
121 **	@brief	Process data provided by a configuration file
122 **
123 **	@param	config_data	The configuration data
124 */
ProcessConfigData(const CConfigData * config_data)125 void CSeasonSchedule::ProcessConfigData(const CConfigData *config_data)
126 {
127 	for (size_t i = 0; i < config_data->Properties.size(); ++i) {
128 		std::string key = config_data->Properties[i].first;
129 		std::string value = config_data->Properties[i].second;
130 
131 		if (key == "name") {
132 			this->Name = value;
133 		} else if (key == "default_schedule") {
134 			const bool is_default_schedule = StringToBool(value);
135 			if (is_default_schedule) {
136 				CSeasonSchedule::DefaultSeasonSchedule = this;
137 			}
138 		} else if (key == "hours_per_day") {
139 			this->HoursPerDay = std::stoi(value);
140 		} else {
141 			fprintf(stderr, "Invalid season schedule property: \"%s\".\n", key.c_str());
142 		}
143 	}
144 
145 	for (const CConfigData *child_config_data : config_data->Children) {
146 		if (child_config_data->Tag == "scheduled_season") {
147 			CSeason *season = nullptr;
148 			unsigned hours = 0;
149 
150 			for (size_t j = 0; j < child_config_data->Properties.size(); ++j) {
151 				std::string key = child_config_data->Properties[j].first;
152 				std::string value = child_config_data->Properties[j].second;
153 
154 				if (key == "season") {
155 					value = FindAndReplaceString(value, "_", "-");
156 					season = CSeason::GetSeason(value);
157 				} else if (key == "days") {
158 					hours = std::stoi(value) * this->HoursPerDay;
159 				} else if (key == "hours") {
160 					hours = std::stoi(value);
161 				} else {
162 					fprintf(stderr, "Invalid scheduled season property: \"%s\".\n", key.c_str());
163 				}
164 			}
165 
166 			if (!season) {
167 				fprintf(stderr, "Scheduled season has no season.\n");
168 				continue;
169 			}
170 
171 			if (hours <= 0) {
172 				fprintf(stderr, "Scheduled season has no amount of time defined.\n");
173 				continue;
174 			}
175 
176 			CScheduledSeason *scheduled_season = new CScheduledSeason;
177 			scheduled_season->Season = season;
178 			scheduled_season->Hours = hours;
179 			scheduled_season->ID = this->ScheduledSeasons.size();
180 			scheduled_season->Schedule = this;
181 			this->ScheduledSeasons.push_back(scheduled_season);
182 			this->TotalHours += scheduled_season->Hours;
183 		} else {
184 			fprintf(stderr, "Invalid season schedule property: \"%s\".\n", child_config_data->Tag.c_str());
185 		}
186 	}
187 
188 	this->CalculateHourMultiplier();
189 }
190 
191 /**
192 **	@brief	Get the default total hours for a season schedule
193 **
194 **	@return	The default total hours
195 */
GetDefaultTotalHours() const196 unsigned long CSeasonSchedule::GetDefaultTotalHours() const
197 {
198 	return DEFAULT_DAYS_PER_YEAR * DEFAULT_HOURS_PER_DAY;
199 }
200 
201 /**
202 **	@brief	Get the default hour multiplier for a season schedule
203 **
204 **	@return	The default hour multiplier
205 */
GetDefaultHourMultiplier() const206 int CSeasonSchedule::GetDefaultHourMultiplier() const
207 {
208 	return DEFAULT_DAY_MULTIPLIER_PER_YEAR;
209 }
210 
211 //@}
212