Exemple #1
0
 public EquipStats GetEffectiveStats(RealmSynergy.SynergyValue synergy)
 {
     return((Item.SeriesId == synergy.GameSeries) ? SynergizedStats : NonSynergizedStats);
 }
Exemple #2
0
        public void Run()
        {
            // First run through and compute the effective stats of each item based
            // on the value of the item level consideration setting.
            DebugParallelForEach(mItems.Where(x => !x.Ignore),
                                 item =>
            {
                byte effective_level = item.Item.Level;
                switch (mSettings.LevelConsideration)
                {
                case AnalyzerSettings.ItemLevelConsideration.Current:
                    effective_level = item.Item.Level;
                    break;

                case AnalyzerSettings.ItemLevelConsideration.CurrentRankMaxLevel:
                    effective_level = item.Item.LevelMax;
                    break;

                case AnalyzerSettings.ItemLevelConsideration.FullyMaxed:
                    effective_level = StatCalculator.MaxLevel(
                        StatCalculator.Evolve(item.Item.BaseRarity, SchemaConstants.EvolutionLevel.PlusPlus));
                    break;
                }

                item.NonSynergizedStats = StatCalculator.ComputeStatsForLevel(item.Item.BaseRarity, item.BaseStats, item.MaxStats, effective_level);
                effective_level         = StatCalculator.EffectiveLevelWithSynergy(effective_level);
                item.SynergizedStats    = StatCalculator.ComputeStatsForLevel(item.Item.BaseRarity, item.BaseStats, item.MaxStats, effective_level);
            });

            RealmSynergy.SynergyValue[]      synergy_values  = RealmSynergy.Values.ToArray();
            AnalyzerSettings.DefensiveStat[] defensive_stats = Enum.GetValues(typeof(AnalyzerSettings.DefensiveStat)).Cast <AnalyzerSettings.DefensiveStat>().ToArray();
            AnalyzerSettings.OffensiveStat[] offensive_stats = Enum.GetValues(typeof(AnalyzerSettings.OffensiveStat)).Cast <AnalyzerSettings.OffensiveStat>().ToArray();

            List <AnalysisItem>[,] best_defensive_items = new List <AnalysisItem> [synergy_values.Length, defensive_stats.Length];
            List <AnalysisItem>[,] best_offensive_items = new List <AnalysisItem> [synergy_values.Length, offensive_stats.Length];

            // Sort the item list MxN different ways, once for each combination of (realm,stat)
            DebugParallelForEach(CartesianProduct(synergy_values, defensive_stats),
                                 x =>
            {
                RealmSynergy.SynergyValue synergy   = x.Key;
                AnalyzerSettings.DefensiveStat stat = x.Value;
                List <AnalysisItem> sorted_items    = new List <AnalysisItem>(mItems.Where(y => !y.Ignore));
                sorted_items.Sort((a, b) =>
                {
                    EquipStats a_stats = a.GetEffectiveStats(synergy);
                    EquipStats b_stats = b.GetEffectiveStats(synergy);
                    short a_value      = ChooseDefensiveStat(a_stats, stat);
                    short b_value      = ChooseDefensiveStat(b_stats, stat);
                    return(-a_value.CompareTo(b_value));
                });
                best_defensive_items[(int)synergy.Realm + 1, (int)stat] = sorted_items;
            });

            DebugParallelForEach(CartesianProduct(synergy_values, offensive_stats),
                                 x =>
            {
                RealmSynergy.SynergyValue synergy   = x.Key;
                AnalyzerSettings.OffensiveStat stat = x.Value;
                List <AnalysisItem> sorted_items    = new List <AnalysisItem>(mItems.Where(y => !y.Ignore));
                sorted_items.Sort((a, b) =>
                {
                    EquipStats a_stats = a.GetEffectiveStats(synergy);
                    EquipStats b_stats = b.GetEffectiveStats(synergy);
                    short a_value      = ChooseOffensiveStat(a_stats, stat);
                    short b_value      = ChooseOffensiveStat(b_stats, stat);
                    return(-a_value.CompareTo(b_value));
                });
                best_offensive_items[(int)synergy.Realm + 1, (int)stat] = sorted_items;
            });

            // Compute the top N items for each character.
            DebugParallelForEach(mBuddies.Where(x => x.Settings.Score),
                                 buddy =>
            {
                buddy.TopNDefense = new List <AnalysisItem> [synergy_values.Length, defensive_stats.Length];
                buddy.TopNOffense = new List <AnalysisItem> [synergy_values.Length, offensive_stats.Length];
                for (int x = 0; x < best_defensive_items.GetLength(0); ++x)
                {
                    for (int y = 0; y < best_defensive_items.GetLength(1); ++y)
                    {
                        List <AnalysisItem> best_items = best_defensive_items[x, y];
                        buddy.TopNDefense[x, y]        = best_items.Where(item => item.EnabledUsers.Contains(buddy)).Take(mTopN).ToList();
                    }
                }
                for (int x = 0; x < best_offensive_items.GetLength(0); ++x)
                {
                    for (int y = 0; y < best_offensive_items.GetLength(1); ++y)
                    {
                        List <AnalysisItem> best_items = best_offensive_items[x, y];
                        buddy.TopNOffense[x, y]        = best_items.Where(item => item.EnabledUsers.Contains(buddy)).Take(mTopN).ToList();
                    }
                }
            });

            // Finally, go through each item and assign it a score based on how many times it appears in someone's Top N list.
            DebugParallelForEach(mItems.Where(x => !x.Ignore),
                                 item =>
            {
                bool is_weapon = false;
                switch (item.Item.Type)
                {
                case SchemaConstants.ItemType.Weapon:
                    is_weapon = true;
                    break;

                case SchemaConstants.ItemType.Armor:
                    is_weapon = false;
                    break;

                default:
                    return;
                }

                // In the worst case the item appears 0 times in the top N for any character and any realm.  In the best
                // case it appears somewhere in the top N for every character who can use it, and in every single realm.
                // Furthermore, we weight appearances by their rank, so the max *score* is that value times the best
                // possible rank.
                int usable_by = item.EnabledUsers.Count;
                int max_denormalized_score = mTopN * usable_by * synergy_values.Length;
                int denormalized_score     = 0;
                foreach (AnalysisBuddy buddy in mBuddies.Where(b => b.Settings.Score))
                {
                    AnalyzerSettings.PartyMemberSettings buddy_settings = mSettings[buddy.Buddy.Name];
                    List <AnalysisItem>[,] rank_array = is_weapon ? buddy.TopNOffense : buddy.TopNDefense;
                    int stat_index = is_weapon ? (int)buddy_settings.OffensiveStat : (int)buddy_settings.DefensiveStat;

                    for (int realm = 0; realm < rank_array.GetLength(0); ++realm)
                    {
                        List <AnalysisItem> top_n_for_stat = rank_array[realm, stat_index];
                        int index = top_n_for_stat.IndexOf(item);
                        if (index == -1)
                        {
                            continue;
                        }
                        denormalized_score += top_n_for_stat.Count - index;
                    }
                }
                System.Diagnostics.Debug.Assert(denormalized_score <= max_denormalized_score);
                item.Result.IsValid = true;
                item.Result.Score   = (double)denormalized_score / (double)max_denormalized_score;
                item.Result.Score  *= 100.0;
            });
        }
Exemple #3
0
 public SynergyFormatter(RealmSynergy.SynergyValue Synergy)
 {
     mSynergy = Synergy;
 }
Exemple #4
0
        private GridEquipStats ComputeDisplayStats(DataEquipmentInformation equip)
        {
            ViewUpgradeModeComboIndex upgrade_type = (ViewUpgradeModeComboIndex)comboBoxUpgradeMode.SelectedIndex;

            RealmSynergy.SynergyValue synergy = RealmSynergy.Values.ElementAt(comboBoxSynergy.SelectedIndex);
            bool has_synergy = equip.SeriesId == synergy.GameSeries;

            DataCache.Items.Key cache_key = new DataCache.Items.Key {
                ItemId = equip.EquipmentId
            };
            DataCache.Items.Data cache_value;
            bool in_cache = FFRKProxy.Instance.Cache.Items.TryGetValue(cache_key, out cache_value);

            GridEquipStats result = new GridEquipStats();

            if (upgrade_type == ViewUpgradeModeComboIndex.CurrentUpgradeCurrentLevel)
            {
                result.Stats.Atk = (has_synergy) ? equip.SeriesAtk : equip.Atk;
                result.Stats.Mag = (has_synergy) ? equip.SeriesMag : equip.Mag;
                result.Stats.Acc = (has_synergy) ? equip.SeriesAcc : equip.Acc;
                result.Stats.Def = (has_synergy) ? equip.SeriesDef : equip.Def;
                result.Stats.Res = (has_synergy) ? equip.SeriesRes : equip.Res;
                result.Stats.Eva = (has_synergy) ? equip.SeriesEva : equip.Eva;
                result.Stats.Mnd = (has_synergy) ? equip.SeriesMnd : equip.Mnd;
                result.Level     = equip.Level;
                result.MaxLevel  = equip.LevelMax;
                if (equip.SeriesId == synergy.GameSeries)
                {
                    result.Level = StatCalculator.EffectiveLevelWithSynergy(result.Level);
                }
            }
            else
            {
                if (upgrade_type == ViewUpgradeModeComboIndex.CurrentUpgradeMaxLevel)
                {
                    result.MaxLevel = StatCalculator.MaxLevel(equip.Rarity);
                }
                else if (upgrade_type == ViewUpgradeModeComboIndex.MaxLevelThroughExistingCombine)
                {
                    // Valid candidates for combining items into this are only those items with matching
                    // equipment id and rarity LESS THAN OR EQUAL TO current item's rarity
                    int candidates = mEquipments.Count(x => x.EquipmentId == equip.EquipmentId && x.InstanceId != equip.InstanceId && x.Rarity <= equip.Rarity);
                    result.MaxLevel = StatCalculator.MaxLevel(StatCalculator.EvolveAsMuchAsPossible(equip.BaseRarity, equip.Rarity, candidates));
                }
                else
                {
                    result.MaxLevel = StatCalculator.MaxLevel(StatCalculator.Evolve(equip.BaseRarity, SchemaConstants.EvolutionLevel.PlusPlus));
                }
                result.Level = result.MaxLevel;
                if (has_synergy)
                {
                    result.Level = StatCalculator.EffectiveLevelWithSynergy(result.Level);
                }

                if (in_cache && cache_value.AreStatsValid)
                {
                    // Try to get the equipment stats from the database
                    result.Stats.Atk = StatCalculator.ComputeStatForLevel(equip.BaseRarity, cache_value.BaseStats.Atk, cache_value.MaxStats.Atk, result.Level);
                    result.Stats.Mag = StatCalculator.ComputeStatForLevel(equip.BaseRarity, cache_value.BaseStats.Mag, cache_value.MaxStats.Mag, result.Level);
                    result.Stats.Acc = StatCalculator.ComputeStatForLevel(equip.BaseRarity, cache_value.BaseStats.Acc, cache_value.MaxStats.Acc, result.Level);
                    result.Stats.Def = StatCalculator.ComputeStatForLevel(equip.BaseRarity, cache_value.BaseStats.Def, cache_value.MaxStats.Def, result.Level);
                    result.Stats.Res = StatCalculator.ComputeStatForLevel(equip.BaseRarity, cache_value.BaseStats.Res, cache_value.MaxStats.Res, result.Level);
                    result.Stats.Eva = StatCalculator.ComputeStatForLevel(equip.BaseRarity, cache_value.BaseStats.Eva, cache_value.MaxStats.Eva, result.Level);
                    result.Stats.Mnd = StatCalculator.ComputeStatForLevel(equip.BaseRarity, cache_value.BaseStats.Mnd, cache_value.MaxStats.Mnd, result.Level);
                }
                else
                {
                    // If they aren't there, fall back to trying to compute effective stats from the ifnormation in the JSON.  This will lead to some
                    // rounding error due to the fact that the values for Atk and SeriesAtk etc are all rounded, so the division will be less precise
                    // than doing it over the entire range of Max stats and base stats, but it's the best we can do in this case.
                    byte series_effective_level = StatCalculator.EffectiveLevelWithSynergy(equip.Level);
                    result.Stats.Atk = (result.MaxLevel == equip.Level) ? ((has_synergy) ? equip.SeriesAtk : equip.Atk) : StatCalculator.ComputeStatForLevel2(equip.Atk, equip.Level, equip.SeriesAtk, series_effective_level, result.Level);
                    result.Stats.Mag = (result.MaxLevel == equip.Level) ? ((has_synergy) ? equip.SeriesMag : equip.Mag) : StatCalculator.ComputeStatForLevel2(equip.Mag, equip.Level, equip.SeriesMag, series_effective_level, result.Level);
                    result.Stats.Acc = (result.MaxLevel == equip.Level) ? ((has_synergy) ? equip.SeriesAcc : equip.Acc) : StatCalculator.ComputeStatForLevel2(equip.Acc, equip.Level, equip.SeriesAcc, series_effective_level, result.Level);
                    result.Stats.Def = (result.MaxLevel == equip.Level) ? ((has_synergy) ? equip.SeriesDef : equip.Def) : StatCalculator.ComputeStatForLevel2(equip.Def, equip.Level, equip.SeriesDef, series_effective_level, result.Level);
                    result.Stats.Res = (result.MaxLevel == equip.Level) ? ((has_synergy) ? equip.SeriesRes : equip.Res) : StatCalculator.ComputeStatForLevel2(equip.Res, equip.Level, equip.SeriesRes, series_effective_level, result.Level);
                    result.Stats.Eva = (result.MaxLevel == equip.Level) ? ((has_synergy) ? equip.SeriesEva : equip.Eva) : StatCalculator.ComputeStatForLevel2(equip.Eva, equip.Level, equip.SeriesEva, series_effective_level, result.Level);
                    result.Stats.Mnd = (result.MaxLevel == equip.Level) ? ((has_synergy) ? equip.SeriesMnd : equip.Mnd) : StatCalculator.ComputeStatForLevel2(equip.Mnd, equip.Level, equip.SeriesMnd, series_effective_level, result.Level);
                }
            }

            if (equip.AugmentStat != null && equip.Augment > 0)
            {
                double bonus = (has_synergy) ? equip.Augment * 1.5 : (double)equip.Augment;

                System.Reflection.FieldInfo augmentField = typeof(EquipStats).GetField(equip.AugmentStat);
                short val = (short)augmentField.GetValue(result.Stats);
                augmentField.SetValue(result.Stats, (short)Math.Ceiling(val + bonus));
            }
            return(result);
        }
Exemple #5
0
 public SynergyColumnValue(RealmSynergy.SynergyValue Value)
 {
     mValue = Value;
 }
Exemple #6
0
        public void Execute(MySqlConnection connection, MySqlTransaction transaction)
        {
            SelectBuilder builder = new SelectBuilder();

            builder.Table = "dungeon_drops";
            builder.Columns.Add("*");
            builder.Parameters.Add(mItemTypes);
            builder.Parameters.Add(mRarities);
            builder.Parameters.Add(mSynergies);
            builder.Parameters.Add(mWorlds);
            builder.Parameters.Add(mDungeons);
            builder.Parameters.Add(mBattles);
            builder.Parameters.Add(mName);

            // Since histogram bars will come in on different rows we need a way to look up the item
            // so we can modify its histogram on the fly.
            var keyed_lookup = new Dictionary <KeyValuePair <uint, uint>, BasicItemDropStats>();

            string stmt = builder.ToString();

            using (MySqlCommand command = new MySqlCommand(stmt, connection))
            {
                builder.Bind(command);
                using (MySqlDataReader reader = command.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        uint battle_id = (uint)reader["battleid"];
                        uint item_id   = (uint)reader["itemid"];
                        var  key       = new KeyValuePair <uint, uint>(battle_id, item_id);

                        BasicItemDropStats stats = null;
                        if (!keyed_lookup.TryGetValue(key, out stats))
                        {
                            // This is a new entry.
                            RealmSynergy.SynergyValue synergy = null;
                            int series_ordinal = reader.GetOrdinal("item_series");
                            if (!reader.IsDBNull(series_ordinal))
                            {
                                uint series = (uint)reader["item_series"];
                                synergy = RealmSynergy.FromSeries(series);
                            }

                            stats = new BasicItemDropStats
                            {
                                BattleId              = battle_id,
                                ItemId                = item_id,
                                DungeonId             = (uint)reader["dungeon_id"],
                                WorldId               = (uint)reader["world_id"],
                                WorldName             = (string)reader["world_name"],
                                DungeonName           = (string)reader["dungeon_name"],
                                DungeonType           = (SchemaConstants.DungeonType)reader["dungeon_type"],
                                Rarity                = (SchemaConstants.Rarity)reader["item_rarity"],
                                Type                  = (SchemaConstants.ItemType)reader["item_type"],
                                TimesRun              = (uint)reader["times_run"],
                                TimesRunWithHistogram = (uint)reader["times_run_with_histogram"],
                                Synergy               = synergy,
                                BattleName            = (string)reader["battle_name"],
                                BattleStamina         = (ushort)reader["battle_stamina"],
                                ItemName              = (string)reader["item_name"],
                            };

                            keyed_lookup.Add(key, stats);
                        }

                        // Modify its histogram entry.
                        int  bucket       = (int)reader["histo_bucket"];
                        uint bucket_value = (uint)reader["histo_value"];

                        if (bucket < 0)
                        {
                            // The total drops is stored in bucket -1.  This should always be present.
                            stats.TotalDrops = bucket_value;
                        }
                        else if (bucket > 0)
                        {
                            // We should never have a bucket 0, because that would mean 0 of the item dropped,
                            // in which case why would it even be in the drop list?
                            System.Diagnostics.Debug.Assert(bucket != 0);

                            stats.Histogram[bucket] = bucket_value;
                        }
                    }
                }
            }

            if (mOnlyRepeatable)
            {
                mDropList = keyed_lookup.Values.Where(x => x.IsBattleRepeatable).ToList();
            }
            else
            {
                mDropList = keyed_lookup.Values.ToList();
            }

            foreach (BasicItemDropStats stats in mDropList)
            {
                // Post process the list.  None of the items will have a value set for Histogram[0] because that
                // means we didn't see anything.  So we have to compute this by subtracting all the events where
                // we did see something from all the events total.

                stats.Histogram[0] = stats.TimesRunWithHistogram;
                for (int i = 1; i < stats.Histogram.BucketCount; ++i)
                {
                    stats.Histogram[0] -= stats.Histogram[i];
                }
            }
        }