diff --git a/company.nut b/company.nut index 4896dd2..bd2b7c3 100644 --- a/company.nut +++ b/company.nut @@ -15,6 +15,8 @@ class CompanyGoal { function AddMonitorElement(mon); function UpdateDelivered(mon); + function CheckFinished(); + function FinalizeGoal(); }; // Add an entry to the collection of monitored things. @@ -45,6 +47,19 @@ function CompanyGoal::UpdateDelivered(mon) this.delivered_amount += delivered; } +// Test whether the goal can be considered 'done'. +// @return Whether the goal is considered done. +function CompanyGoal::CheckFinished() +{ + return this.delivered_amount >= this.wanted_amount; +} + +// Goal is considered 'done', last chance to clean up before the goal is dropped +// (to make room for a new goal). +function CompanyGoal::FinalizeGoal() +{ + // Nothing to do (yet). +} class CompanyData { comp_id = null; @@ -63,6 +78,7 @@ class CompanyData { function AddMonitorElement(mon); function UpdateDelivered(mon); + function CheckAndFinishGoals(); }; // Find the number of active goals that are missing for this company. @@ -128,12 +144,28 @@ function CompanyData::AddMonitorElements(cmon) // Distribute the delivered amounts to the goals. // @param cmon Monitor results of all companies, 'comp_id' numbers to 'cargo_id' number to // 'ind' and/or 'town' to resource indices to amount. +// @return Whether a goal is considered to be 'done'. function CompanyData::UpdateDelivereds(cmon) { + local finished = false; if (this.comp_id in cmon) { foreach (num, goal in this.active_goals) { if (goal == null) continue; goal.UpdateDelivered(cmon[this.comp_id]); + if (goal.CheckFinished()) finished = true; + } + } + return finished; // One or more goals was considered 'done' +} + +// Test whether goals of the company are 'done', and if so, drop them. +function CompanyData::CheckAndFinishGoals() +{ + foreach (num, goal in this.active_goals) { + if (goal == null) continue; + if (goal.CheckFinished()) { + goal.FinalizeGoal(); + this.active_goals[num] = null; } } } diff --git a/main.nut b/main.nut index 8f2d1cf..694eb2e 100644 --- a/main.nut +++ b/main.nut @@ -219,7 +219,8 @@ function FMainClass::Start() // Main event loop. local companies_timeout = 0; - local goal_timeout = 0; + local new_goal_timeout = 0; + local finished_timeout = 0; local monitor_timeout = 0; local old_cmonitor = null; while (true) { @@ -244,7 +245,7 @@ function FMainClass::Start() } // Check for having to create new goals. - if (goal_timeout <= 0) { + if (new_goal_timeout <= 0) { local total_missing = 0; // Total number of missing goals. local best_cid = null; local cid_missing = 0; @@ -265,9 +266,9 @@ function FMainClass::Start() } if (total_missing > 1) { - goal_timeout = 1 * 74; // If more missing goals, wait only a short while. + new_goal_timeout = 1 * 74; // If more missing goals, wait only a short while. } else { - goal_timeout = 30 * 74; + new_goal_timeout = 30 * 74; } } @@ -287,9 +288,10 @@ function FMainClass::Start() this.FillMonitors(cmon); // Query the monitors. // Distribute the retrieved data. + local finished = false; foreach (cid, cdata in companies) { if (cdata == null) continue; - cdata.UpdateDelivereds(cmon); + if (cdata.UpdateDelivereds(cmon)) finished = true; } // Drop obsolete monitors. @@ -297,6 +299,17 @@ function FMainClass::Start() old_cmonitor = cmon; monitor_timeout = 15 * 74; // By default, check monitors every 15 days (other processes may force a check earlier). + if (finished) finished_timeout = 0; + } + + // Check for finished goals, and remove them if they exist. + if (finished_timeout <= 0) { + foreach (cid, cdata in companies) { + if (cdata == null) continue; + cdata.CheckAndFinishGoals(); + } + + finished_timeout = 30 * 74; // By default, check for finished goals every 30 days (may be forced by other processes). } // local lake_news = GSText(GSText.STR_LAKE_NEWS); @@ -306,15 +319,19 @@ function FMainClass::Start() // Sleep until the next event. local delay_time = 5000; if (delay_time > companies_timeout) delay_time = companies_timeout; - if (delay_time > goal_timeout) delay_time = goal_timeout; + if (delay_time > new_goal_timeout) delay_time = new_goal_timeout; if (delay_time > monitor_timeout) delay_time = monitor_timeout; + if (delay_time > finished_timeout) delay_time = finished_timeout; // XXX Perhaps check for company events? + GSLog.Info(""); + GSLog.Info("Sleeping for " + delay_time + " ticks."); if (delay_time > 0) this.Sleep(delay_time); companies_timeout -= delay_time; - goal_timeout -= delay_time; + new_goal_timeout -= delay_time; monitor_timeout -= delay_time; + finished_timeout -= delay_time; } }