Esempio n. 1
0
        public void PerformAction(bool prompt)
        {
            try
            {
                Overwatch.Log("Cleanup Genealogy");

                Dictionary <IMiniSimDescription, IMiniSimDescription> duplicates = new Dictionary <IMiniSimDescription, IMiniSimDescription>();

                Dictionary <ulong, IMiniSimDescription> lookup = new Dictionary <ulong, IMiniSimDescription>();

                Dictionary <IMiniSimDescription, bool> urnstones = new Dictionary <IMiniSimDescription, bool>();

                foreach (SimDescription sim in SimDescription.GetHomelessSimDescriptionsFromUrnstones())
                {
                    if (urnstones.ContainsKey(sim))
                    {
                        continue;
                    }

                    urnstones.Add(sim, true);
                }

                Dictionary <IGenealogy, bool> allGenealogies = new Dictionary <IGenealogy, bool>();

                List <IGenealogy> geneList = new List <IGenealogy>();

                foreach (KeyValuePair <ulong, List <IMiniSimDescription> > ids in SimListing.AllSims <IMiniSimDescription>(null, true, false))
                {
                    List <IMiniSimDescription> list = ids.Value;

                    foreach (IMiniSimDescription miniSim in list)
                    {
                        if (miniSim.CASGenealogy == null)
                        {
                            continue;
                        }

                        if (allGenealogies.ContainsKey(miniSim.CASGenealogy))
                        {
                            continue;
                        }

                        allGenealogies.Add(miniSim.CASGenealogy, true);

                        geneList.Add(miniSim.CASGenealogy);
                    }

                    IMiniSimDescription choice = null;
                    if (list.Count == 1)
                    {
                        choice = list[0];
                    }
                    else if (list.Count > 1)
                    {
                        List <IMiniSimDescription> choices = new List <IMiniSimDescription>();

                        foreach (IMiniSimDescription miniSim in list)
                        {
                            SimDescription sim = miniSim as SimDescription;
                            if (sim == null)
                            {
                                continue;
                            }

                            if (sim.Household == Household.ActiveHousehold)
                            {
                                choices.Add(miniSim);
                            }
                        }

                        if (choices.Count >= 1)
                        {
                            choice = choices[0];

                            Overwatch.Log("Doppleganger Active-Inactive (" + list.Count + "): " + Relationships.GetFullName(choice));
                        }
                        else
                        {
                            choices.Clear();
                            foreach (IMiniSimDescription sim in list)
                            {
                                if (urnstones.ContainsKey(sim))
                                {
                                    choices.Add(sim);
                                }
                            }

                            if (choices.Count == 1)
                            {
                                choice = choices[0];

                                Overwatch.Log("Doppleganger Urnstone (" + list.Count + "): " + Relationships.GetFullName(choice));
                            }
                            else
                            {
                                choices.Clear();
                                foreach (IMiniSimDescription sim in list)
                                {
                                    Genealogy genealogy = sim.CASGenealogy as Genealogy;

                                    if ((genealogy != null) && (object.ReferenceEquals(sim, genealogy.mSim)))
                                    {
                                        choices.Add(sim);
                                    }
                                }

                                if (choices.Count == 1)
                                {
                                    choice = choices[0];

                                    Overwatch.Log("Doppleganger Personal Genealogy (" + list.Count + "): " + Relationships.GetFullName(choice));
                                }
                                else
                                {
                                    choices.Clear();

                                    MiniSimDescription miniSim = MiniSimDescription.Find(ids.Key);
                                    if ((miniSim != null) && (miniSim.Genealogy != null) && (miniSim.Genealogy.mSim != null))
                                    {
                                        foreach (IMiniSimDescription sim in list)
                                        {
                                            if (object.ReferenceEquals(sim, miniSim.Genealogy.mSim))
                                            {
                                                choices.Add(sim);
                                            }
                                        }
                                    }

                                    if (choices.Count == 1)
                                    {
                                        choice = choices[0];

                                        Overwatch.Log("Doppleganger MiniSim Genealogy (" + list.Count + "): " + Relationships.GetFullName(choice));
                                    }
                                    else
                                    {
                                        choices.Clear();

                                        int maxLinks = 0;

                                        foreach (IMiniSimDescription sim in list)
                                        {
                                            if (choice == null)
                                            {
                                                choice = sim;
                                            }
                                            else
                                            {
                                                int numLinks = 0;

                                                Genealogy gene = sim.CASGenealogy as Genealogy;
                                                if (gene != null)
                                                {
                                                    if (gene.mNaturalParents != null)
                                                    {
                                                        numLinks += gene.mNaturalParents.Count;
                                                    }

                                                    if (gene.mChildren != null)
                                                    {
                                                        numLinks += gene.mChildren.Count;
                                                    }

                                                    if (gene.mSiblings != null)
                                                    {
                                                        numLinks += gene.mSiblings.Count;
                                                    }

                                                    if (maxLinks < numLinks)
                                                    {
                                                        maxLinks = numLinks;

                                                        choice = sim;
                                                    }
                                                }
                                            }
                                        }

                                        Overwatch.Log("Doppleganger By Link Count (" + list.Count + "): " + Relationships.GetFullName(choice));
                                    }
                                }
                            }
                        }
                    }

                    if (choice != null)
                    {
                        lookup.Add(choice.SimDescriptionId, choice);

                        foreach (IMiniSimDescription sim in list)
                        {
                            if (object.ReferenceEquals(sim, choice))
                            {
                                continue;
                            }

                            duplicates.Add(sim, choice);

                            Genealogy genealogy = ReconcileGenealogy(choice.CASGenealogy as Genealogy, sim.CASGenealogy as Genealogy);
                            if (genealogy != null)
                            {
                                SetGenealogy(choice, genealogy);
                            }
                        }
                    }
                }

                int index = 0;
                while (index < geneList.Count)
                {
                    Genealogy genealogy = geneList[index] as Genealogy;
                    index++;

                    if (genealogy == null)
                    {
                        continue;
                    }

                    AddToList(geneList, allGenealogies, genealogy.mNaturalParents);
                    AddToList(geneList, allGenealogies, genealogy.mChildren);
                    AddToList(geneList, allGenealogies, genealogy.mSiblings);
                }

                Dictionary <string, List <Genealogy> > broken = new Dictionary <string, List <Genealogy> >();

                foreach (IGenealogy iGene in geneList)
                {
                    Genealogy gene = iGene as Genealogy;
                    if (gene == null)
                    {
                        continue;
                    }

                    if ((gene.mMiniSim == null) && (gene.mSim == null))
                    {
                        if (!string.IsNullOrEmpty(gene.Name))
                        {
                            List <Genealogy> genes;
                            if (!broken.TryGetValue(gene.Name, out genes))
                            {
                                genes = new List <Genealogy>();
                                broken.Add(gene.Name, genes);
                            }

                            genes.Add(gene);
                        }
                    }

                    MiniSimDescription miniSim = gene.mMiniSim as MiniSimDescription;
                    if (miniSim == null)
                    {
                        continue;
                    }

                    if ((MiniSimDescription.sMiniSims != null) && (!MiniSimDescription.sMiniSims.ContainsKey(miniSim.SimDescriptionId)))
                    {
                        MiniSimDescription.sMiniSims.Add(miniSim.SimDescriptionId, miniSim);

                        if (!lookup.ContainsKey(miniSim.SimDescriptionId))
                        {
                            lookup.Add(miniSim.SimDescriptionId, miniSim);
                        }

                        Overwatch.Log("Genealogy Minisim Added " + Relationships.GetFullName(miniSim));
                    }
                }

                CleanupMiniSimGenealogy(lookup, broken);

                foreach (IMiniSimDescription sim in lookup.Values)
                {
                    try
                    {
                        IMiniSimDescription lookupSim = Relationships.Find(sim.SimDescriptionId, lookup);

                        Genealogy genealogy = null;

                        if (lookupSim != null)
                        {
                            genealogy = lookupSim.CASGenealogy as Genealogy;

                            if ((genealogy != null) && (sim.CASGenealogy != null) && (!object.ReferenceEquals(genealogy, sim.CASGenealogy)))
                            {
                                sim.CASGenealogy = genealogy;

                                Overwatch.Log("Lookup Genealogy Replaced: " + Relationships.GetFullName(sim));
                            }
                        }

                        if (genealogy == null)
                        {
                            genealogy = sim.CASGenealogy as Genealogy;
                        }

                        if (genealogy == null)
                        {
                            MiniSimDescription miniSim = MiniSimDescription.Find(sim.SimDescriptionId);
                            if (miniSim != null)
                            {
                                genealogy = miniSim.mGenealogy;

                                if ((genealogy != null) && (sim.CASGenealogy != null) && (!object.ReferenceEquals(genealogy, sim.CASGenealogy)))
                                {
                                    sim.CASGenealogy = genealogy;

                                    Overwatch.Log("MiniSim Genealogy Replaced: " + Relationships.GetFullName(sim));
                                }
                            }
                        }

                        if (genealogy == null)
                        {
                            SimDescription trueSim = sim as SimDescription;
                            if (trueSim != null)
                            {
                                trueSim.Fixup();

                                genealogy = sim.CASGenealogy as Genealogy;
                                if (genealogy == null)
                                {
                                    Overwatch.Log("No SimDesc Genealogy: " + Relationships.GetFullName(sim));
                                }
                                else
                                {
                                    Overwatch.Log("Genealogy Fixup Performed: " + Relationships.GetFullName(sim));
                                }
                            }
                            else
                            {
                                MiniSimDescription miniSim = sim as MiniSimDescription;
                                if (miniSim != null)
                                {
                                    // This minisim may be part of a family tree, so must be uncorrupted
                                    genealogy = new Genealogy(miniSim.FullName);

                                    Overwatch.Log("MiniSim Genealogy Created: " + Relationships.GetFullName(sim));
                                }
                                else
                                {
                                    Overwatch.Log("No MiniSim Genealogy: " + Relationships.GetFullName(sim));
                                }
                            }
                        }

                        SetGenealogy(sim, genealogy);
                    }
                    catch (Exception e)
                    {
                        Common.Exception("Phase One: " + Relationships.GetFullName(sim), e);
                    }
                }

                foreach (IMiniSimDescription sim in lookup.Values)
                {
                    try
                    {
                        SimDescription trueSim = sim as SimDescription;
                        if (trueSim != null)
                        {
                            MiniSimDescription miniSim = MiniSimDescription.Find(trueSim.SimDescriptionId);
                            if (miniSim != null)
                            {
                                List <MiniRelationship> relationships = new List <MiniRelationship>(miniSim.MiniRelationships);
                                foreach (MiniRelationship relationship in relationships)
                                {
                                    IMiniSimDescription otherSim = MiniSimDescription.Find(relationship.GetOtherSimDescriptionId(sim));
                                    if (otherSim == null)
                                    {
                                        miniSim.mMiniRelationships.Remove(relationship);
                                    }
                                    else
                                    {
                                        Genealogy gene = otherSim.CASGenealogy as Genealogy;
                                        if (gene == null)
                                        {
                                            miniSim.mMiniRelationships.Remove(relationship);
                                        }
                                    }
                                }
                            }

                            Dictionary <ulong, bool> existingRelations = new Dictionary <ulong, bool>();

                            Dictionary <SimDescription, Relationship> oldRelations;
                            if (Relationship.sAllRelationships.TryGetValue(trueSim, out oldRelations))
                            {
                                Dictionary <SimDescription, Relationship> newRelations = new Dictionary <SimDescription, Relationship>();

                                foreach (KeyValuePair <SimDescription, Relationship> relation in new Dictionary <SimDescription, Relationship>(oldRelations))
                                {
                                    IMiniSimDescription townSim;
                                    if (lookup.TryGetValue(relation.Key.SimDescriptionId, out townSim))
                                    {
                                        if (!object.ReferenceEquals(townSim, relation.Key))
                                        {
                                            Overwatch.Log(Relationships.GetFullName(sim) + " Dropped bad relation for " + Relationships.GetFullName(relation.Key));

                                            Relationships.SafeRemoveRelationship(relation.Value);
                                            continue;
                                        }
                                    }

                                    if (existingRelations.ContainsKey(relation.Key.SimDescriptionId))
                                    {
                                        Overwatch.Log(Relationships.GetFullName(sim) + " Dropped duplicate relation for " + Relationships.GetFullName(relation.Key));

                                        Relationships.SafeRemoveRelationship(relation.Value);
                                        continue;
                                    }

                                    existingRelations.Add(relation.Key.SimDescriptionId, true);

                                    Relationships.RepairRelationship(relation.Value, Overwatch.Log);

                                    newRelations.Add(relation.Key, relation.Value);
                                }

                                Relationship.sAllRelationships[trueSim] = newRelations;
                            }

                            /*
                             * MiniSimDescription miniDesc = MiniSimDescription.Find(trueSim.SimDescriptionId);
                             * if (miniDesc != null)
                             * {
                             *  for (int i = miniDesc.mMiniRelationships.Count - 1; i >= 0; i--)
                             *  {
                             *      MiniRelationship relation = miniDesc.mMiniRelationships[i];
                             *
                             *      if (existingRelations.ContainsKey(relation.SimDescriptionId))
                             *      {
                             *          miniDesc.mMiniRelationships.RemoveAt(i);
                             *
                             *          Overwatch.Log(GetFullName(trueSim) + " Dropped duplicate mini relation");
                             *      }
                             *  }
                             * }
                             */

                            RepairMissingPartner(trueSim);

                            // Legacy repair for an issue with an earlier Phase of Overwatch
                            List <Relationship> relations = new List <Relationship>(Relationship.GetRelationships(trueSim));
                            foreach (Relationship relation in relations)
                            {
                                if ((relation.LTR.HasInteractionBit(LongTermRelationship.InteractionBits.Divorce)) ||
                                    (relation.LTR.HasInteractionBit(LongTermRelationship.InteractionBits.BreakUp)) ||
                                    (relation.LTR.HasInteractionBit(LongTermRelationship.InteractionBits.BreakEngagement)) ||
                                    (relation.LTR.HasInteractionBit(LongTermRelationship.InteractionBits.Marry)) ||
                                    (relation.LTR.HasInteractionBit(LongTermRelationship.InteractionBits.Propose)) ||
                                    (relation.LTR.HasInteractionBit(LongTermRelationship.InteractionBits.MakeCommitment)))
                                {
                                    relation.LTR.AddInteractionBit(LongTermRelationship.InteractionBits.HaveBeenPartners);
                                }
                            }
                        }

                        Genealogy genealogy = sim.CASGenealogy as Genealogy;
                        if (genealogy != null)
                        {
                            genealogy.ClearDerivedData();

                            new Relationships.RepairParents().Perform(sim, Overwatch.Log, lookup);
                            new Relationships.RepairChildren().Perform(sim, Overwatch.Log, lookup);
                            new Relationships.RepairSiblings().Perform(sim, Overwatch.Log, lookup);

                            RepairSpouse(sim, lookup);

                            if ((sim.IsMarried) && (genealogy.mPartnerType != PartnerType.Marriage))
                            {
                                genealogy.mPartnerType = PartnerType.Marriage;

                                if (genealogy.Spouse != null)
                                {
                                    genealogy.Spouse.mPartnerType = PartnerType.Marriage;
                                }

                                Overwatch.Log(Relationships.GetFullName(sim) + " PartnerType Corrected");
                            }
                        }

                        RepairMiniSim(trueSim);
                    }
                    catch (Exception e)
                    {
                        Common.Exception("Phase Two: " + Relationships.GetFullName(sim), e);
                    }
                }

                CleanupMiniSims(lookup);

                // Must be performed after repairing the genealogy as the mSim is wiped from the genealogy during deletion
                foreach (KeyValuePair <IMiniSimDescription, IMiniSimDescription> duplicate in duplicates)
                {
                    CustomAnnihilation(duplicate.Key as SimDescription, duplicate.Value as SimDescription);
                }
            }
            catch (Exception e)
            {
                Common.Exception(Name, e);
            }
        }
Esempio n. 2
0
        protected static void RepairSpouse(IMiniSimDescription simA, Dictionary <ulong, IMiniSimDescription> lookup)
        {
            SimDescription trueSimA = simA as SimDescription;

            IMiniSimDescription simB = null;

            Genealogy genealogy = simA.CASGenealogy as Genealogy;

            if (genealogy.Spouse != null)
            {
                simB = Relationships.GetSim(genealogy.Spouse, lookup);
            }

            if (trueSimA != null)
            {
                if ((simB == null) && (simA.IsMarried))
                {
                    simB = trueSimA.Partner;
                }

                if (simB == null)
                {
                    List <Relationship> relations = new List <Relationship>(Relationship.GetRelationships(trueSimA));
                    foreach (Relationship relation in relations)
                    {
                        if (relation.LTR.CurrentLTR == LongTermRelationshipTypes.Spouse)
                        {
                            simB = relation.GetOtherSimDescription(trueSimA);
                            if (simB != null)
                            {
                                simB = Relationships.Find(simB.SimDescriptionId, lookup);
                            }

                            if (simB is SimDescription)
                            {
                                break;
                            }
                        }
                    }
                }
            }

            SimDescription trueSimB = simB as SimDescription;

            if ((simA != null) && (simB != null))
            {
                Genealogy geneA = simA.CASGenealogy as Genealogy;
                Genealogy geneB = simB.CASGenealogy as Genealogy;

                if ((geneA != null) && (geneB != null))
                {
                    if (!object.ReferenceEquals(geneA.Spouse, geneB))
                    {
                        geneA.mSpouse = geneB;

                        Overwatch.Log("Missing Spouse Link Attached A");
                        Overwatch.Log("  " + Relationships.GetFullName(geneA) + " - " + Relationships.GetFullName(geneB));
                    }

                    if (!object.ReferenceEquals(geneB.Spouse, geneA))
                    {
                        geneB.mSpouse = geneA;

                        Overwatch.Log("Missing Spouse Link Attached B");
                        Overwatch.Log("  " + Relationships.GetFullName(geneB) + " - " + Relationships.GetFullName(geneA));
                    }
                }
            }

            if ((trueSimA != null) && (trueSimB != null))
            {
                if (!object.ReferenceEquals(trueSimA.Partner, trueSimB))
                {
                    // Don't call Partner, it requires genealogy
                    trueSimA.mPartner = trueSimB;

                    Overwatch.Log("Missing Partner Link Attached A");
                    Overwatch.Log("  " + Relationships.GetFullName(simA) + " - " + Relationships.GetFullName(simB));
                }

                if (!object.ReferenceEquals(trueSimB.Partner, trueSimA))
                {
                    // Don't call Partner, it requires genealogy
                    trueSimB.mPartner = trueSimA;

                    Overwatch.Log("Missing Partner Link Attached B");
                    Overwatch.Log("  " + Relationships.GetFullName(simB) + " - " + Relationships.GetFullName(simA));
                }
            }
        }