private void ManageAllocation(Entity nation, ResearchResult turn, TechTeam researcher, ResearchFrame target) { ProgressFrame liveFrame = nation.Status.Frames.FirstOrDefault(x => x.IdTag == target.IdTag); if (liveFrame != null) { // Should this check for Active/Accessible frames, or leave that to the assignment routines? Tuple <ProgressFrame, List <String> > outcome = ProcessTeam(researcher, liveFrame, BonusCalculator.CalculateEffectiveBonus(nation, researcher, target), // Get Admiral/Event Bonuses calculated for us BonusCalculator.MatchPreference(researcher, target)); // And double check the skill match turn.UpdateFrames.Add(researcher, outcome.Item1); // Commit our now updated frame to the results if (researcher.IncrementXP(target.Tree)) // Next we process xp gain and see if the team has levelled up { turn.LevelledUpTeams.Add(researcher); // If yes, make sure we mark that down } } else { throw new ArgumentException("An invalid frame was provided"); } }
/// <summary> /// Total up the three relevant sources of bonuses. /// </summary> /// <param name="parent"></param> /// <param name="researcher"></param> /// <param name="frame"></param> /// <returns></returns> public static int CalculateEffectiveBonus(Entity parent, TechTeam researcher, ResearchFrame frame) { int bonus = parent.Status.AdmiralBonuses.Where(x => x.TreeTarget == frame.Tree)?.Sum(x => x.BonusValue) ?? 0; bonus += parent.Status.AdmiralBonuses.Where(x => frame.PartContained.Contains(x.PartTarget))?.Sum(x => x.BonusValue) ?? 0; bonus += parent.Status.EventBonuses.Where(x => x.FrameTag == frame.IdTag)?.Sum(x => x.BonusForAllLines) ?? 0; return(bonus); }
public static void Translate(Vote vote, string raw) { Dictionary <TechTeam, ResearchFrame> parsedVote = new Dictionary <TechTeam, ResearchFrame>(); /* Assumes Federation will be first Entity listed, and the tech tree used by the Federation the first tech tree listed. * Otherwise the Entity needs to be passed in or defined in a static member somewhere, and the Entity needs to store the * tech tree it is using. */ TechTree usedTree = Master.MasterTreeList[0]; Entity votedOn = Master.MasterEntityList[0]; using (var sr = new System.IO.StringReader(raw)) { string line; while ((line = sr.ReadLine()) != null) { if (line.Contains(":")) { string[] split = line.Split(':'); int start = split[0].LastIndexOf(']') + 1; string team = split[0].Substring(start, split[0].Length - start); string newProject; if (split[1].Contains("->")) { string[] projects = split[1].Split(new[] { "->" }, StringSplitOptions.None); newProject = projects[1]; } else { newProject = split[1]; } team.Trim(); newProject.Trim(); TechTeam techTeam = votedOn.Teams.Find(tt => tt.IdTag == team); ResearchFrame frame = usedTree.Find(newProject); if (techTeam != null && frame != null) { parsedVote.Add(techTeam, frame); } } else if (line.Contains("[BOOST]")) { int start = line.LastIndexOf(']') + 1; string[] teams = line.Substring(start, line.Length - start).Split(','); foreach (String team in teams) { team.Trim(); TechTeam techTeam = votedOn.Teams.Find(tt => tt.IdTag == team); if (techTeam != null) { techTeam.AssignedBoosts += 1; } } } } } }
/// <summary> /// Run the check to see if this matches the research preferences. /// </summary> /// <param name="researcher">TechTeam being checked</param> /// <param name="frame">Frame being researched</param> /// <returns></returns> public static bool MatchPreference(TechTeam researcher, ResearchFrame frame) { if (researcher.PreferredSkill1 == frame.Tree || researcher.PreferredSkill2 == frame.Tree) { return(true); } else { return(false); } }
private Tuple <ProgressFrame, List <String> > ProcessTeam(TechTeam team, ProgressFrame frame, int bonus, bool matchesSkill) { List <String> rewards = new List <String>(); int minProgress = bonus + team.SkillLevel * (matchesSkill ? 2 : 1); int overflow = 0; SortedDictionary <int, Queue <int> > remaining = new SortedDictionary <int, Queue <int> >(); List <ComponentProgressLine> back = new List <ComponentProgressLine>(); for (int i = 0; i < frame.Lines.Count; ++i) { if (frame.Lines[i].WasCompleteInPreviousTurn) { continue; } int diff = frame.Lines[i].Advance(minProgress); if (diff >= 0) { overflow += diff; rewards.Add(frame.Lines[i].Line.Reward); } else { if (remaining.ContainsKey(diff)) { remaining[diff].Enqueue(i); } else { var q = new Queue <int>(); q.Enqueue(i); remaining.Add(diff, q); } } } AssignOverflow(frame, remaining, rewards, overflow); Random rand = new Random(); int inspirationAndBoost = 1; if (team.AssignedBoosts > 0) { inspirationAndBoost += 1; team.AssignedBoosts -= 1; } for (int j = 0; j < inspirationAndBoost; ++j) { int total = 0; foreach (var kv in remaining) { total += kv.Value.Count; } int r = rand.Next(total - 1); foreach (var kv in remaining) { if (kv.Value.Count < r) { r -= kv.Value.Count; } else { int i = kv.Value.Dequeue(); if (r > 0) { kv.Value.Enqueue(i); --r; } else { int diff = frame.Lines[i].Advance(5); if (diff >= 0) { rewards.Add(frame.Lines[i].Line.Reward); AssignOverflow(frame, remaining, rewards, diff); } else { if (remaining.ContainsKey(diff)) { remaining[diff].Enqueue(i); } else { var q = new Queue <int>(); q.Enqueue(i); remaining.Add(diff, q); } } break; } } } } return(new Tuple <ProgressFrame, List <String> >(frame, rewards)); }