private static void IncludeTranslations(PoEModData modtemplate)
        {
            IDictionary <string, StatLocalization> trlib = StatTranslator.Data;

            foreach (PoEModStat stat in modtemplate.stats)
            {
                string statkey = stat.id;
                if (!trlib.ContainsKey(statkey))
                {
                    continue;
                }
                StatLocalization sloc = trlib[statkey];
                foreach (LocalizationDefinition def in sloc.definitions)
                {
                    string text = def.text;
                    if (text.Length <= 10)          //omits league names as stats, not sure why they were there to begin with
                    {
                        continue;
                    }
                    text = text.Replace("{0} to {1}", "{0}");
                    if (text.Contains("{1}"))       //omits two flask charge when crit mods that aren't listed by trade searches anyway
                    {
                        continue;
                    }
                    if (def.format[0] != "ignore")
                    {
                        text = text.Replace("{0}", def.format[0]);
                    }
                    if (!text.Contains("Hinder"))   //don't replace "reduced" in the reminder text for hinder
                    {
                        text = text.Replace("reduced", "increased");
                    }
                    StatTemplates.Add(text);
                }
            }
        }
        //build mod data templates from mods.min.json and mod_types.min.json, also builds search templates for stats used by relevant mods
        //MUST BE DONE AFTER TRANSLATION DEFINITIONS ARE LOADED IN STATTRANSLATOR
        public static int LoadMods(string modsfile, string typesfile)
        {
            Dictionary <string, Dictionary <string, HashSet <string> > > typesdata = JsonSerializer.Deserialize <Dictionary <string, Dictionary <string, HashSet <string> > > >(File.ReadAllText(typesfile));

            AllMods      = JsonSerializer.Deserialize <Dictionary <string, PoEModData> >(File.ReadAllText(modsfile));
            CoreMods     = new Dictionary <string, PoEModData>();
            Enchantments = new Dictionary <string, PoEModData>();
            InitStatTemplates();
            foreach (string k in AllMods.Keys)
            {
                PoEModData d = AllMods[k];
                //translate once and save string as a property
                StatTranslator.FillTranslationData(d);
                //set type_tags field with a lookup
                d.type_tags = typesdata[d.type]["tags"];
                //set key field
                d.key = k;
                if (d.generation_type == ModLogic.Enchantment)
                {
                    Enchantments.Add(k, AllMods[k]);
                }
                //flag relevant mods to move to core dictionary, "misc" domain is for regular jewels
                if ((d.domain == "item" || d.domain == "abyss_jewel" || d.domain == "misc") && (d.generation_type == ModLogic.Prefix || d.generation_type == ModLogic.Suffix))
                {
                    CoreMods.Add(k, AllMods[k]);
                }
                //every mod worth translating into string templates to search by, doesn't include implicits because idk how to include them w/o also including a ton of useless unique item mods
                if ((d.domain == "item" || d.domain == "abyss_jewel" || d.domain == "misc" || d.domain == "crafted" || d.domain == "delve") && (d.generation_type == ModLogic.Prefix || d.generation_type == ModLogic.Suffix))
                {
                    IncludeTranslations(AllMods[k]);
                }
            }
            Debug.WriteLine(CoreMods.Count + " core, " + Enchantments.Count + " enchantment, " + AllMods.Count + " total mods loaded");
            Debug.WriteLine(StatTemplates.Count + " statlines loaded");
            return(CoreMods.Count);
        }
        //build mod data templates from mods.min.json and mod_types.min.json, also builds search templates for stats used by relevant mods
        //MUST BE DONE AFTER TRANSLATION DEFINITIONS ARE LOADED IN STATTRANSLATOR
        public static int LoadMods(string modsfile, string typesfile)
        {
            Dictionary <string, Dictionary <string, HashSet <string> > > typesdata = JsonSerializer.Deserialize <Dictionary <string, Dictionary <string, HashSet <string> > > >(File.ReadAllText(typesfile));

            AllMods      = JsonSerializer.Deserialize <Dictionary <string, PoEModData> >(File.ReadAllText(modsfile));
            CoreMods     = new Dictionary <string, PoEModData>();
            Enchantments = new Dictionary <string, PoEModData>();
            InitStatTemplates();
            afflictionmods.Clear();
            Dictionary <string, string> clusterreminders = new Dictionary <string, string>();

            using (StreamReader r = File.OpenText(@"Data\ClusterText.txt"))
            {
                string line;
                string name = null;
                string desc = null;
                while ((line = r.ReadLine()) != null)
                {
                    if (line.Length == 0 && name != null)
                    {
                        clusterreminders.Add(name, desc);
                        name = null;
                        desc = null;
                        continue;
                    }
                    if (name == null)
                    {
                        name = line;
                    }
                    else if (desc == null)
                    {
                        desc = line;
                    }
                    else
                    {
                        desc += "\n" + line;
                    }
                }
                if (name != null)
                {
                    clusterreminders.Add(name, desc);
                }
            }
            //Dictionary<string, List<PoEModWeight>> afflictiondict = new Dictionary<string, List<PoEModWeight>>();
            foreach (string k in AllMods.Keys)
            {
                PoEModData d = AllMods[k];
                //translate once and save string as a property
                StatTranslator.FillTranslationData(d);
                //set type_tags field with a lookup
                d.type_tags = typesdata[d.type]["tags"];
                //set key field
                d.key = k;
                if (d.generation_type == ModLogic.Enchantment)
                {
                    Enchantments.Add(k, AllMods[k]);
                }
                //flag relevant mods to move to core dictionary, "misc" domain is for regular jewels
                if ((d.domain == "item" || d.domain == "abyss_jewel" || d.domain == "misc" || d.domain == "affliction_jewel") && (d.generation_type == ModLogic.Prefix || d.generation_type == ModLogic.Suffix))
                {
                    CoreMods.Add(k, AllMods[k]);
                }
                //every mod worth translating into string templates to search by, doesn't include implicits because idk how to include them w/o also including a ton of useless unique item mods
                if ((d.domain == "item" || d.domain == "abyss_jewel" || d.domain == "misc" || d.domain == "affliction_jewel" || d.domain == "crafted" || d.domain == "delve") && (d.generation_type == ModLogic.Prefix || d.generation_type == ModLogic.Suffix))
                {
                    IncludeTranslations(AllMods[k]);
                }
                if ((d.domain == "affliction_jewel") && (d.generation_type == ModLogic.Prefix || d.generation_type == ModLogic.Suffix))
                {
                    int notableindex = d.full_translation.IndexOf("Skill is");
                    if (notableindex > 0 && !d.full_translation.Contains("Jewel Socket"))
                    {
                        string notablename = d.full_translation.Substring(notableindex + 9);
                        d.tooltip_reminder = clusterreminders[notablename];
                    }
                    //if (d.full_translation.Contains("also grant"))
                    //    Debug.WriteLine(d);
                    foreach (PoEModWeight w in d.spawn_weights)
                    {
                        if (w.tag.Contains("affliction"))
                        {
                            afflictionmods.Add(w.tag);
                            //if (d.full_translation.Contains("also grant"))
                            //    Debug.WriteLine(w.tag);
                            //if (notableindex > 0 && !d.full_translation.Contains("Jewel Socket"))
                            //{
                            //    if (!afflictiondict.ContainsKey(w.tag))
                            //        afflictiondict.Add(w.tag, new List<PoEModWeight>() { new PoEModWeight() { tag = k, weight = w.weight } });
                            //    else
                            //        afflictiondict[w.tag].Add(new PoEModWeight() { tag = k, weight = w.weight });
                            //}
                        }
                    }
                }
            }
            //using (StreamWriter w = File.CreateText("notables.csv"))
            //{
            //    foreach (string s in afflictiondict.Keys)
            //    {
            //        w.WriteLine(s);
            //        foreach (PoEModWeight mw in afflictiondict[s])
            //        {
            //            PoEModData mod = AllMods[mw.tag];
            //            w.WriteLine(mw.weight + ",\"" + mod.full_translation.Substring(mod.full_translation.IndexOf("Skill is") + 9) + "\",\"" + mod.tooltip_reminder + "\"");
            //        }
            //        w.WriteLine("");
            //    }
            //}
            Debug.WriteLine(CoreMods.Count + " core, " + Enchantments.Count + " enchantment, " + AllMods.Count + " total mods loaded");
            Debug.WriteLine(StatTemplates.Count + " statlines loaded");
            IList <string> mediumenchants = new List <string>()
            {
                "affliction_area_damage", "affliction_aura_effect", "affliction_brand_damage", "affliction_critical_chance", "affliction_curse_effect", "affliction_fire_damage_over_time_multiplier", "affliction_chaos_damage_over_time_multiplier", "affliction_physical_damage_over_time_multiplier", "affliction_cold_damage_over_time_multiplier", "affliction_damage_over_time_multiplier", "affliction_effect_of_non-damaging_ailments", "affliction_life_and_mana_recovery_from_flasks", "affliction_flask_duration", "affliction_damage_while_you_have_a_herald", "affliction_minion_damage_while_you_have_a_herald", "affliction_minion_life", "affliction_projectile_damage", "affliction_totem_damage", "affliction_trap_and_mine_damage", "affliction_warcry_buff_effect", "affliction_channelling_skill_damage"
            };
            IList <string> smallenchants = new List <string>()
            {
                "affliction_maximum_life", "affliction_chance_to_dodge_attacks", "affliction_cold_resistance", "affliction_chaos_resistance", "affliction_armour", "affliction_evasion", "affliction_fire_resistance", "affliction_maximum_mana", "affliction_maximum_energy_shield", "affliction_lightning_resistance", "affliction_chance_to_block"
            };
            IList <string> largeenchants = new List <string>()
            {
                "affliction_axe_and_sword_damage", "affliction_mace_and_staff_damage", "affliction_dagger_and_claw_damage", "affliction_bow_damage", "affliction_wand_damage", "affliction_damage_with_two_handed_melee_weapons", "affliction_attack_damage_while_dual_wielding_", "affliction_attack_damage_while_holding_a_shield", "affliction_attack_damage_", "affliction_spell_damage", "affliction_chaos_damage", "affliction_cold_damage", "affliction_elemental_damage", "affliction_fire_damage", "affliction_lightning_damage", "affliction_physical_damage", "affliction_minion_damage"
            };
            IList <PoEModWeight> afflictionmediumspawns = new List <PoEModWeight>
            {
                new PoEModWeight()
                {
                    tag = "expansion_jewel_medium", weight = 100
                },
                new PoEModWeight()
                {
                    tag = "default", weight = 0
                }
            };
            IList <PoEModWeight> afflictionsmallspawns = new List <PoEModWeight>
            {
                new PoEModWeight()
                {
                    tag = "expansion_jewel_small", weight = 100
                },
                new PoEModWeight()
                {
                    tag = "default", weight = 0
                }
            };
            IList <PoEModWeight> afflictionlargespawns = new List <PoEModWeight>
            {
                new PoEModWeight()
                {
                    tag = "expansion_jewel_large", weight = 100
                },
                new PoEModWeight()
                {
                    tag = "default", weight = 0
                }
            };
            IList <PoEModWeight> afflictionnospawns = new List <PoEModWeight>
            {
                new PoEModWeight()
                {
                    tag = "default", weight = 0
                }
            };

            foreach (string s in afflictionmods)
            {
                PoEModData afflictionmod = new PoEModData()
                {
                    adds_tags = new HashSet <string>()
                    {
                        s
                    },
                    domain             = "item",
                    generation_type    = "enchantment",
                    generation_weights = new List <PoEModWeight>(),
                    group           = "SmallPassiveGroup",
                    is_essence_only = false,
                    name            = s.Replace("affliction", "small passives grant: "),
                    required_level  = 1,
                    stats           = null,
                    type            = "SmallPassiveType",
                    key             = s,
                    type_tags       = new HashSet <string>()
                };
                if (mediumenchants.Contains(s))
                {
                    afflictionmod.spawn_weights = afflictionmediumspawns;
                }
                else if (smallenchants.Contains(s))
                {
                    afflictionmod.spawn_weights = afflictionsmallspawns;
                }
                else if (largeenchants.Contains(s))
                {
                    afflictionmod.spawn_weights = afflictionlargespawns;
                }
                else
                {
                    afflictionmod.spawn_weights = afflictionnospawns;
                }
                Enchantments.Add(s, afflictionmod);
                AllMods.Add(s, afflictionmod);
            }
            return(CoreMods.Count);
        }