/// <summary> /// Calculates employment ratio for type of resident /// </summary> /// <param name="type"></param> /// <returns></returns> public float Get_Employment_Ratio(Building.Resident type) { if (Required_Workers[type] == 0) { return(0.0f); } return((float)Residents[type][CURRENT] / (float)Required_Workers[type]); }
/// <summary> /// /// </summary> /// <param name="delta_time">Seconds since last update</param> public void Process(float delta_time) { Resources.Clear(); Cash_Flow = 0.0f; Dictionary <Building.Resident, float> resident_happiness_temp = new Dictionary <Building.Resident, float>(); Dictionary <Building.Resident, int> required_workers_temp = new Dictionary <Building.Resident, int>(); foreach (Building.Resident resident_type in Enum.GetValues(typeof(Building.Resident))) { Residents[resident_type][CURRENT] = 0; Residents[resident_type][MAX] = 0; resident_happiness_temp[resident_type] = 0.0f; required_workers_temp.Add(resident_type, 0); } Dictionary <string, float[]> resource_stats_temp = new Dictionary <string, float[]>(); float income = 0.0f; float expenditures = 0.0f; float food_current = 0.0f; float food_max = 0.0f; float food_produced = 0.0f; float food_consumed = 0.0f; List <int> food_storage_cheched = new List <int>(); List <string> food_types = new List <string>(); foreach (KeyValuePair <string, Dictionary <string, float> > resource in resource_data) { if (resource.Value.ContainsKey("food")) { food_types.Add(resource.Key); } } System.Diagnostics.Stopwatch stopwatch = System.Diagnostics.Stopwatch.StartNew(); Time += (Game.Instance.Speed * delta_time); foreach (Building building in buildings) { //Process if (Game.Instance.Is_Paused) { building.Render_Alerts(); } else { building.Process(Game.Instance.Speed * (delta_time + (stopwatch.ElapsedMilliseconds / 1000.0f))); } //Storage if (building.Is_Built) { if (building.Attribute("storehouse") != 0.0f) { foreach (KeyValuePair <string, float[]> resource in building.Storage) { if (!Resources.ContainsKey(resource.Key)) { Resources.Add(resource.Key, resource.Value[CURRENT]); } else { Resources[resource.Key] += resource.Value[CURRENT]; } } } //Resident count foreach (Building.Resident resident_type in Enum.GetValues(typeof(Building.Resident))) { if (building.Population_Type == resident_type) { Residents[resident_type][CURRENT] += building.Population; Residents[resident_type][MAX] += building.Population_Max; resident_happiness_temp[resident_type] += (building.Population_Happiness * building.Population); break; } } //Worker count foreach (KeyValuePair <Building.Resident, int[]> worker_type in building.Workers) { required_workers_temp[worker_type.Key] += worker_type.Value[MAX]; } if (building.Changeable_Workers_PC.Count != 0) { if (building.Changeable_Workers_PC[2] == 0) { required_workers_temp[Building.Resident.PEASANT] += building.Changeable_Workers_PC[MAX]; } else { required_workers_temp[Building.Resident.CITIZEN] += building.Changeable_Workers_PC[MAX]; } } if (building.Changeable_Workers_CN.Count != 0) { if (building.Changeable_Workers_CN[2] == 0) { required_workers_temp[Building.Resident.CITIZEN] += building.Changeable_Workers_CN[MAX]; } else { required_workers_temp[Building.Resident.NOBLE] += building.Changeable_Workers_CN[MAX]; } } } //Cash flow Cash_Flow -= building.Current_Upkeep; expenditures -= building.Current_Upkeep; Cash_Flow += building.Get_Statistic("income"); income += building.Get_Statistic("income"); //Food foreach (string food in food_types) { food_current += building.Resource_Amount(food); if (building.Storage.ContainsKey(food) && !food_storage_cheched.Contains(building.Id)) { food_max += building.Storage[food][MAX]; food_storage_cheched.Add(building.Id); } } food_produced += building.Get_Statistic("food_produced"); food_consumed += building.Get_Statistic("food_consumed"); //Resources foreach (KeyValuePair <string, float> stat in building.Statistics) { if (stat.Key.StartsWith("produced_")) { string resource_name = stat.Key.Substring(9); float[] data = new float[3] { 0.0f, 0.0f, stat.Value }; if (!resource_stats_temp.ContainsKey(resource_name)) { resource_stats_temp.Add(resource_name, data); } else { resource_stats_temp[resource_name][0] += data[0]; resource_stats_temp[resource_name][1] += data[1]; resource_stats_temp[resource_name][2] += data[2]; } } else if (stat.Key.StartsWith("consumed_")) { string resource_name = stat.Key.Substring(9); float[] data = new float[3] { 0, 0, -1.0f * stat.Value }; if (!resource_stats_temp.ContainsKey(resource_name)) { resource_stats_temp.Add(resource_name, data); } else { resource_stats_temp[resource_name][0] += data[0]; resource_stats_temp[resource_name][1] += data[1]; resource_stats_temp[resource_name][2] += data[2]; } } } foreach (KeyValuePair <string, float[]> resource in building.Storage) { float[] data = new float[3] { resource.Value[CURRENT], resource.Value[MAX], 0.0f }; if (!resource_stats_temp.ContainsKey(resource.Key)) { resource_stats_temp.Add(resource.Key, data); } else { resource_stats_temp[resource.Key][0] += data[0]; resource_stats_temp[resource.Key][1] += data[1]; resource_stats_temp[resource.Key][2] += data[2]; } } } //Redistribute workers foreach (KeyValuePair <Building.Resident, int> temp_data in required_workers_temp) { Required_Workers[temp_data.Key] = temp_data.Value; } Dictionary <Building.Resident, int> available_workers = new Dictionary <Building.Resident, int>(); Dictionary <Building.Resident, float> worker_ratios = new Dictionary <Building.Resident, float>(); foreach (KeyValuePair <Building.Resident, int[]> resident in Residents) { available_workers.Add(resident.Key, resident.Value[CURRENT]); if (Required_Workers[resident.Key] == 0) { worker_ratios.Add(resident.Key, 0.0f); } else { worker_ratios.Add(resident.Key, resident.Value[CURRENT] / (float)Required_Workers[resident.Key]); if (worker_ratios[resident.Key] > 1.0f) { worker_ratios[resident.Key] = 1.0f; } } } foreach (Building building in buildings) { if (building.Is_Built && (building.Workers.Count != 0 || building.Changeable_Workers_PC.Count != 0 || building.Changeable_Workers_CN.Count != 0)) { foreach (KeyValuePair <Building.Resident, int[]> worker_data in building.Workers) { worker_data.Value[CURRENT] = (int)(worker_ratios[worker_data.Key] * worker_data.Value[MAX]); available_workers[worker_data.Key] -= worker_data.Value[CURRENT]; } if (building.Changeable_Workers_PC.Count != 0) { Building.Resident type = Building.Resident.PEASANT; if (building.Changeable_Workers_PC[2] == 1) { type = Building.Resident.CITIZEN; } building.Changeable_Workers_PC[CURRENT] = (int)(worker_ratios[type] * building.Changeable_Workers_PC[MAX]); available_workers[type] -= building.Changeable_Workers_PC[CURRENT]; } if (building.Changeable_Workers_CN.Count != 0) { Building.Resident type = Building.Resident.CITIZEN; if (building.Changeable_Workers_CN[2] == 1) { type = Building.Resident.NOBLE; } building.Changeable_Workers_CN[CURRENT] = (int)(worker_ratios[type] * building.Changeable_Workers_CN[MAX]); available_workers[type] -= building.Changeable_Workers_CN[CURRENT]; } } } //Average happiness foreach (Building.Resident resident_type in Enum.GetValues(typeof(Building.Resident))) { if (Residents[resident_type][CURRENT] == 0) { resident_happiness_temp[resident_type] = 0; } else { resident_happiness_temp[resident_type] /= Residents[resident_type][CURRENT]; } } //Try to store resources foreach (KeyValuePair <Building, Dictionary <string, float> > store_data in resources_on_queue) { foreach (KeyValuePair <string, float> resource_data in store_data.Value) { float over_flow = Store_Resources(resource_data.Key, resource_data.Value); store_data.Key.Add(resource_data.Key, over_flow); } } resources_on_queue.Clear(); //Delete foreach (Building b in buildings_to_be_deleted) { buildings.Remove(b); } buildings_to_be_deleted.Clear(); //Update menu foreach (KeyValuePair <Building.Resident, float> pair in resident_happiness_temp) { Resident_Happiness[pair.Key] = pair.Value; } MenuManager.Instance.Set_Time(Time); Update_Resource_Menu(); MenuManager.Instance.Set_Resident_Info( Residents[Building.Resident.PEASANT][CURRENT], Residents[Building.Resident.PEASANT][MAX], Mathf.RoundToInt(Resident_Happiness[Building.Resident.PEASANT] * 100.0f), Required_Workers[Building.Resident.PEASANT], Mathf.RoundToInt(100.0f * Get_Employment_Ratio(Building.Resident.PEASANT)), Residents[Building.Resident.CITIZEN][CURRENT], Residents[Building.Resident.CITIZEN][MAX], Mathf.RoundToInt(Resident_Happiness[Building.Resident.CITIZEN] * 100.0f), Required_Workers[Building.Resident.CITIZEN], Mathf.RoundToInt(100.0f * Get_Employment_Ratio(Building.Resident.CITIZEN)), Residents[Building.Resident.NOBLE][CURRENT], Residents[Building.Resident.NOBLE][MAX], Mathf.RoundToInt(Resident_Happiness[Building.Resident.NOBLE] * 100.0f), Required_Workers[Building.Resident.NOBLE], Mathf.RoundToInt(100.0f * Get_Employment_Ratio(Building.Resident.NOBLE)) ); //Update statistics StatisticsManager.Instance.Cash = Cash; StatisticsManager.Instance.Income = income; StatisticsManager.Instance.Expenditures = expenditures; StatisticsManager.Instance.Food_Current = food_current; StatisticsManager.Instance.Food_Max = food_max; StatisticsManager.Instance.Food_Produced = food_produced; StatisticsManager.Instance.Food_Consumed = food_consumed; Resource_Stats.Clear(); foreach (KeyValuePair <string, float[]> resource_data_temp in resource_stats_temp) { Resource_Stats.Add(resource_data_temp.Key, resource_data_temp.Value); } }