From 78cf5ca682bf9c8f7ff05c945061c82fd3dcfdb2 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Fri, 29 Jan 2016 00:26:47 +0000 Subject: [PATCH] Add setting for linkgraph times to be in non daylength scaled days. Savegame format change for link graph jobs. Change link graph scheduler to support more than one operation per day, on _date_fract ticks other than SPAWN_JOIN_TICK. --- src/lang/english.txt | 2 ++ src/linkgraph/flowmapper.cpp | 2 +- src/linkgraph/linkgraphjob.cpp | 12 +++++++++- src/linkgraph/linkgraphjob.h | 19 +++++++++++---- src/linkgraph/linkgraphschedule.cpp | 36 ++++++++++++++++++++--------- src/saveload/extended_ver_sl.cpp | 1 + src/saveload/extended_ver_sl.h | 1 + src/saveload/linkgraph_sl.cpp | 13 ++++++++++- src/settings_gui.cpp | 1 + src/settings_type.h | 1 + src/table/settings.ini | 9 ++++++++ 11 files changed, 78 insertions(+), 19 deletions(-) diff --git a/src/lang/english.txt b/src/lang/english.txt index 6d4585e387..68c019fb89 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -1714,6 +1714,8 @@ STR_CONFIG_SETTING_LINKGRAPH_INTERVAL :Update distribu STR_CONFIG_SETTING_LINKGRAPH_INTERVAL_HELPTEXT :Time between subsequent recalculations of the link graph. Each recalculation calculates the plans for one component of the graph. That means that a value X for this setting does not mean the whole graph will be updated every X days. Only some component will. The shorter you set it the more CPU time will be necessary to calculate it. The longer you set it the longer it will take until the cargo distribution starts on new routes. STR_CONFIG_SETTING_LINKGRAPH_TIME :Take {STRING2}{NBSP}day{P 0:2 "" s} for recalculation of distribution graph STR_CONFIG_SETTING_LINKGRAPH_TIME_HELPTEXT :Time taken for each recalculation of a link graph component. When a recalculation is started, a thread is spawned which is allowed to run for this number of days. The shorter you set this the more likely it is that the thread is not finished when it's supposed to. Then the game stops until it is ("lag"). The longer you set it the longer it takes for the distribution to be updated when routes change. +STR_CONFIG_SETTING_LINKGRAPH_NOT_DAYLENGTH_SCALED :Do not scale the linkgraph days by the day length factor: {STRING2} +STR_CONFIG_SETTING_LINKGRAPH_NOT_DAYLENGTH_SCALED_HELPTEXT :When enabled, the linkgraph recalculation interval and time are in units of unscaled, original days, instead of day-length scaled calendar days. STR_CONFIG_SETTING_DISTRIBUTION_MANUAL :manual STR_CONFIG_SETTING_DISTRIBUTION_ASYMMETRIC :asymmetric STR_CONFIG_SETTING_DISTRIBUTION_SYMMETRIC :symmetric diff --git a/src/linkgraph/flowmapper.cpp b/src/linkgraph/flowmapper.cpp index 4b974a809e..04e8fd776f 100644 --- a/src/linkgraph/flowmapper.cpp +++ b/src/linkgraph/flowmapper.cpp @@ -54,7 +54,7 @@ void FlowMapper::Run(LinkGraphJob &job) const /* Scale by time the graph has been running without being compressed. Add 1 to avoid * division by 0 if spawn date == last compression date. This matches * LinkGraph::Monthly(). */ - uint runtime = job.JoinDate() - job.Settings().recalc_time - job.LastCompression() + 1; + uint runtime = (job.StartDateTicks() / DAY_TICKS) - job.LastCompression() + 1; for (FlowStatMap::iterator i = flows.begin(); i != flows.end(); ++i) { i->second.ScaleToMonthly(runtime); } diff --git a/src/linkgraph/linkgraphjob.cpp b/src/linkgraph/linkgraphjob.cpp index eb95b93be4..368d42ae81 100644 --- a/src/linkgraph/linkgraphjob.cpp +++ b/src/linkgraph/linkgraphjob.cpp @@ -28,6 +28,15 @@ INSTANTIATE_POOL_METHODS(LinkGraphJob) */ /* static */ Path *Path::invalid_path = new Path(INVALID_NODE, true); +static DateTicks GetLinkGraphJobJoinDateTicks() +{ + DateTicks ticks = _settings_game.linkgraph.recalc_time * DAY_TICKS; + if (_settings_game.linkgraph.recalc_not_scaled_by_daylength) { + ticks /= _settings_game.economy.day_length_factor; + } + return ticks + (_date * DAY_TICKS) + _date_fract; +} + /** * Create a link graph job from a link graph. The link graph will be copied so * that the calculations don't interfer with the normal operations on the @@ -40,7 +49,8 @@ LinkGraphJob::LinkGraphJob(const LinkGraph &orig) : link_graph(orig), settings(_settings_game.linkgraph), thread(NULL), - join_date(_date + _settings_game.linkgraph.recalc_time), + join_date_ticks(GetLinkGraphJobJoinDateTicks()), + start_date_ticks((_date * DAY_TICKS) + _date_fract), job_completed(false) { } diff --git a/src/linkgraph/linkgraphjob.h b/src/linkgraph/linkgraphjob.h index 3c6039019d..b4f53e1884 100644 --- a/src/linkgraph/linkgraphjob.h +++ b/src/linkgraph/linkgraphjob.h @@ -54,13 +54,15 @@ private: typedef SmallMatrix EdgeAnnotationMatrix; friend const SaveLoad *GetLinkGraphJobDesc(); + friend void GetLinkGraphJobDayLengthScaleAfterLoad(LinkGraphJob *lgj); friend class LinkGraphSchedule; protected: const LinkGraph link_graph; ///< Link graph to by analyzed. Is copied when job is started and mustn't be modified later. const LinkGraphSettings settings; ///< Copy of _settings_game.linkgraph at spawn time. ThreadObject *thread; ///< Thread the job is running in or NULL if it's running in the main thread. - Date join_date; ///< Date when the job is to be joined. + DateTicks join_date_ticks; ///< Date when the job is to be joined. + DateTicks start_date_ticks; ///< Date when the job was started. NodeAnnotationVector nodes; ///< Extra node data necessary for link graph calculation. EdgeAnnotationMatrix edges; ///< Extra edge data necessary for link graph calculation. bool job_completed; ///< Is the job still running. This is accessed by multiple threads and is permitted to be spuriously incorrect. @@ -268,7 +270,7 @@ public: * settings have to be brutally const-casted in order to populate them. */ LinkGraphJob() : settings(_settings_game.linkgraph), thread(NULL), - join_date(INVALID_DATE), job_completed(false) {} + join_date_ticks(INVALID_DATE), start_date_ticks(INVALID_DATE), job_completed(false) {} LinkGraphJob(const LinkGraph &orig); ~LinkGraphJob(); @@ -279,21 +281,28 @@ public: /** * Check if job is supposed to be finished. + * @param tick_offset Optional number of ticks to add to the current date * @return True if job should be finished by now, false if not. */ - inline bool IsFinished() const { return this->join_date <= _date; } + inline bool IsFinished(int tick_offset = 0) const { return this->join_date_ticks <= (_date * DAY_TICKS) + _date_fract + tick_offset; } /** * Get the date when the job should be finished. * @return Join date. */ - inline Date JoinDate() const { return join_date; } + inline DateTicks JoinDateTicks() const { return join_date_ticks; } + + /** + * Get the date when the job was started. + * @return Start date. + */ + inline DateTicks StartDateTicks() const { return start_date_ticks; } /** * Change the join date on date cheating. * @param interval Number of days to add. */ - inline void ShiftJoinDate(int interval) { this->join_date += interval; } + inline void ShiftJoinDate(int interval) { this->join_date_ticks += interval * DAY_TICKS; } /** * Get the link graph settings for this component. diff --git a/src/linkgraph/linkgraphschedule.cpp b/src/linkgraph/linkgraphschedule.cpp index f8b461e2a9..57b5290a43 100644 --- a/src/linkgraph/linkgraphschedule.cpp +++ b/src/linkgraph/linkgraphschedule.cpp @@ -56,7 +56,7 @@ void LinkGraphSchedule::SpawnNext() bool LinkGraphSchedule::IsJoinWithUnfinishedJobDue() const { for (JobList::const_iterator it = this->running.begin(); it != this->running.end(); ++it) { - if (!((*it)->IsFinished())) { + if (!((*it)->IsFinished(1))) { /* job is not due to be joined yet */ return false; } @@ -187,13 +187,19 @@ void StateGameLoop_LinkGraphPauseControl() if (!LinkGraphSchedule::instance.IsJoinWithUnfinishedJobDue()) { DoCommandP(0, PM_PAUSED_LINK_GRAPH, 0, CMD_PAUSE); } - } else if (_pause_mode == PM_UNPAUSED && _tick_skip_counter == 0 && - _date_fract == LinkGraphSchedule::SPAWN_JOIN_TICK - 1) { - if (_date % _settings_game.linkgraph.recalc_interval == _settings_game.linkgraph.recalc_interval / 2) { - /* perform check one _date_fract tick before we would join */ - if (LinkGraphSchedule::instance.IsJoinWithUnfinishedJobDue()) { - DoCommandP(0, PM_PAUSED_LINK_GRAPH, 1, CMD_PAUSE); - } + } else if (_pause_mode == PM_UNPAUSED && _tick_skip_counter == 0) { + if (!_settings_game.linkgraph.recalc_not_scaled_by_daylength || _settings_game.economy.day_length_factor == 1) { + if (_date_fract != LinkGraphSchedule::SPAWN_JOIN_TICK - 1) return; + if (_date % _settings_game.linkgraph.recalc_interval != _settings_game.linkgraph.recalc_interval / 2) return; + } else { + int date_ticks = ((_date * DAY_TICKS) + _date_fract - (LinkGraphSchedule::SPAWN_JOIN_TICK - 1)); + int interval = (_settings_game.linkgraph.recalc_interval * DAY_TICKS / _settings_game.economy.day_length_factor); + if (date_ticks % interval != interval / 2) return; + } + + /* perform check one _date_fract tick before we would join */ + if (LinkGraphSchedule::instance.IsJoinWithUnfinishedJobDue()) { + DoCommandP(0, PM_PAUSED_LINK_GRAPH, 1, CMD_PAUSE); } } } @@ -204,11 +210,19 @@ void StateGameLoop_LinkGraphPauseControl() */ void OnTick_LinkGraph() { - if (_date_fract != LinkGraphSchedule::SPAWN_JOIN_TICK) return; - Date offset = _date % _settings_game.linkgraph.recalc_interval; + int offset; + int interval; + if (!_settings_game.linkgraph.recalc_not_scaled_by_daylength || _settings_game.economy.day_length_factor == 1) { + if (_date_fract != LinkGraphSchedule::SPAWN_JOIN_TICK) return; + interval = _settings_game.linkgraph.recalc_interval; + offset = _date % interval; + } else { + interval = (_settings_game.linkgraph.recalc_interval * DAY_TICKS / _settings_game.economy.day_length_factor); + offset = ((_date * DAY_TICKS) + _date_fract - LinkGraphSchedule::SPAWN_JOIN_TICK) % interval; + } if (offset == 0) { LinkGraphSchedule::instance.SpawnNext(); - } else if (offset == _settings_game.linkgraph.recalc_interval / 2) { + } else if (offset == interval / 2) { LinkGraphSchedule::instance.JoinNext(); } } diff --git a/src/saveload/extended_ver_sl.cpp b/src/saveload/extended_ver_sl.cpp index ae79de923a..a1242a2d5c 100644 --- a/src/saveload/extended_ver_sl.cpp +++ b/src/saveload/extended_ver_sl.cpp @@ -67,6 +67,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = { { XSLFI_EXTRA_LARGE_MAP, XSCF_NULL, 0, 1, "extra_large_map", NULL, NULL, NULL }, { XSLFI_REVERSE_AT_WAYPOINT, XSCF_NULL, 1, 1, "reverse_at_waypoint", NULL, NULL, NULL }, { XSLFI_VEH_LIFETIME_PROFIT, XSCF_NULL, 1, 1, "veh_lifetime_profit", NULL, NULL, NULL }, + { XSLFI_LINKGRAPH_DAY_SCALE, XSCF_NULL, 1, 1, "linkgraph_day_scale", NULL, NULL, NULL }, { XSLFI_NULL, XSCF_NULL, 0, 0, NULL, NULL, NULL, NULL },// This is the end marker }; diff --git a/src/saveload/extended_ver_sl.h b/src/saveload/extended_ver_sl.h index 9dd206f471..080e5d8667 100644 --- a/src/saveload/extended_ver_sl.h +++ b/src/saveload/extended_ver_sl.h @@ -41,6 +41,7 @@ enum SlXvFeatureIndex { XSLFI_EXTRA_LARGE_MAP, ///< Extra large map XSLFI_REVERSE_AT_WAYPOINT, ///< Reverse at waypoint orders XSLFI_VEH_LIFETIME_PROFIT, ///< Vehicle lifetime profit patch + XSLFI_LINKGRAPH_DAY_SCALE, ///< Linkgraph job duration & interval may be in non-scaled days XSLFI_RIFF_HEADER_60_BIT, ///< Size field in RIFF chunk header is 60 bit XSLFI_HEIGHT_8_BIT, ///< Map tile height is 8 bit instead of 4 bit, but savegame version may be before this became true in trunk diff --git a/src/saveload/linkgraph_sl.cpp b/src/saveload/linkgraph_sl.cpp index a65f4fc8a5..1076b1fcef 100644 --- a/src/saveload/linkgraph_sl.cpp +++ b/src/saveload/linkgraph_sl.cpp @@ -40,6 +40,13 @@ const SaveLoad *GetLinkGraphDesc() return link_graph_desc; } +void GetLinkGraphJobDayLengthScaleAfterLoad(LinkGraphJob *lgj) +{ + lgj->join_date_ticks *= DAY_TICKS; + lgj->join_date_ticks += LinkGraphSchedule::SPAWN_JOIN_TICK; + lgj->start_date_ticks = lgj->join_date_ticks - (lgj->Settings().recalc_time * DAY_TICKS); +} + /** * Get a SaveLoad array for a link graph job. The settings struct is derived from * the global settings saveload array. The exact entries are calculated when the function @@ -75,7 +82,8 @@ const SaveLoad *GetLinkGraphJobDesc() } const SaveLoad job_desc[] = { - SLE_VAR(LinkGraphJob, join_date, SLE_INT32), + SLE_VAR(LinkGraphJob, join_date_ticks, SLE_INT32), + SLE_CONDVAR_X(LinkGraphJob, start_date_ticks, SLE_INT32, 0, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_LINKGRAPH_DAY_SCALE)), SLE_VAR(LinkGraphJob, link_graph.index, SLE_UINT16), SLE_END() }; @@ -208,6 +216,9 @@ static void Load_LGRJ() } LinkGraphJob *lgj = new (index) LinkGraphJob(); SlObject(lgj, GetLinkGraphJobDesc()); + if (SlXvIsFeatureMissing(XSLFI_LINKGRAPH_DAY_SCALE)) { + GetLinkGraphJobDayLengthScaleAfterLoad(lgj); + } LinkGraph &lg = const_cast(lgj->Graph()); SlObject(&lg, GetLinkGraphDesc()); lg.Init(_num_nodes); diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index dd94a07b4b..13a327b9c5 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -1782,6 +1782,7 @@ static SettingsContainer &GetSettingsTree() cdist->Add(new SettingEntry("linkgraph.demand_distance")); cdist->Add(new SettingEntry("linkgraph.demand_size")); cdist->Add(new SettingEntry("linkgraph.short_path_saturation")); + cdist->Add(new SettingEntry("linkgraph.recalc_not_scaled_by_daylength")); } SettingsPage *treedist = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_TREES)); { diff --git a/src/settings_type.h b/src/settings_type.h index 489763d335..66635d73cd 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -550,6 +550,7 @@ struct EconomySettings { struct LinkGraphSettings { uint16 recalc_time; ///< time (in days) for recalculating each link graph component. uint16 recalc_interval; ///< time (in days) between subsequent checks for link graphs to be calculated. + bool recalc_not_scaled_by_daylength; ///< whether the time should be in daylength-scaled days (false) or unscaled days (true) DistributionTypeByte distribution_pax; ///< distribution type for passengers DistributionTypeByte distribution_mail; ///< distribution type for mail DistributionTypeByte distribution_armoured; ///< distribution type for armoured cargo class diff --git a/src/table/settings.ini b/src/table/settings.ini index 41e4c8a516..62a0ddcd03 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -743,6 +743,15 @@ str = STR_CONFIG_SETTING_LINKGRAPH_TIME strval = STR_JUST_COMMA strhelp = STR_CONFIG_SETTING_LINKGRAPH_TIME_HELPTEXT +[SDT_BOOL] +base = GameSettings +var = linkgraph.recalc_not_scaled_by_daylength +def = false +str = STR_CONFIG_SETTING_LINKGRAPH_NOT_DAYLENGTH_SCALED +strhelp = STR_CONFIG_SETTING_LINKGRAPH_NOT_DAYLENGTH_SCALED_HELPTEXT +extver = SlXvFeatureTest(XSLFTO_AND, XSLFI_LINKGRAPH_DAY_SCALE) +patxname = ""linkgraph_day_scale.linkgraph.recalc_not_scaled_by_daylength"" + [SDT_VAR] base = GameSettings var = linkgraph.distribution_pax