Пример #1
0
        /// <summary>
        /// Check a line for the SimC Addon version string, and set it on result if present
        /// </summary>
        private void TryApplySimcVersion(SimcParsedProfile result, string valueString)
        {
            var versionPrefix = "SimC Addon ";

            if (valueString.Length > versionPrefix.Length &&
                valueString.Substring(0, versionPrefix.Length) == versionPrefix)
            {
                var version = valueString[versionPrefix.Length..];
        public void SimcParsedProfile_Collections_Not_Null()
        {
            // Arrange
            var spp = new SimcParsedProfile();

            // Assert
            Assert.IsNotNull(spp.Soulbinds);
            Assert.IsNotNull(spp.Conduits);
            Assert.IsNotNull(spp.Professions);
            Assert.IsNotNull(spp.Items);
        }
Пример #3
0
        private void TryApplyClass(SimcParsedProfile profile, string classValue)
        {
            profile.Class = classValue;
            var classId = (classValue) switch
            {
                "priest" => Class.Priest,
                "paladin" => Class.Paladin,
                "monk" => Class.Monk,
                "shaman" => Class.Shaman,
                "druid" => Class.Druid,
                "rogue" => Class.Rogue,
                "mage" => Class.Mage,
                "deathknight" => Class.DeathKnight,
                "demonhunter" => Class.DemonHunter,
                "hunter" => Class.Hunter,
                "warlock" => Class.Warlock,
                "warrior" => Class.Warrior,
                _ => Class.None
            };

            profile.ClassId = (int)classId;
        }
Пример #4
0
        private void TryApplyRace(SimcParsedProfile profile, SimcParsedLine line)
        {
            // Set Race and RaceId
            profile.Race = line.Value.Trim();
            var raceId = (profile.Race.ToLower()) switch
            {
                "human" => Race.Human,
                "orc" => Race.Orc,
                "dwarf" => Race.Dwarf,
                "night_elf" => Race.NightElf,
                "undead" => Race.Undead,
                "tauren" => Race.Tauren,
                "gnome" => Race.Gnome,
                "troll" => Race.Troll,
                "goblin" => Race.Goblin,
                "blood_elf" => Race.BloodElf,
                "draenei" => Race.Draenei,
                "dark_iron_dwarf" => Race.DarkIronDwarf,
                "vulpera" => Race.Vulpera,
                "maghar_orc" => Race.MagharOrc,
                "mechagnome" => Race.Mechagnome,
                "worgen" => Race.Worgen,
                "pandaren" => Race.Pandaren,
                "pandaren_alliance" => Race.PandarenAlliance,
                "pandaren_horde" => Race.PandarenHorde,
                "nightborne" => Race.Nightborne,
                "highmountain_tauren" => Race.HighmountainTauren,
                "void_elf" => Race.VoidElf,
                "lightforged_draenei" => Race.LightforgedDraenei,
                "zandalari_troll" => Race.ZandalariTroll,
                "kul_tiran" => Race.KulTiran,
                _ => Race.NoRace,
            };

            profile.RaceId = (int)raceId;
        }
Пример #5
0
        public async Task InitOnce()
        {
            // Configure Logging
            Log.Logger = new LoggerConfiguration()
                         .MinimumLevel.Verbose()
                         .Enrich.FromLogContext()
                         .WriteTo.File("logs" + Path.DirectorySeparatorChar + "SimcProfileParser.log", rollingInterval: RollingInterval.Day)
                         .CreateLogger();

            // Load a data file
            var testFile         = @"RawData" + Path.DirectorySeparatorChar + "Hierophant.simc";
            var testFileContents = await File.ReadAllLinesAsync(testFile);

            var testFileString = new List <string>(testFileContents);

            // Create a new profile service
            using var loggerFactory = LoggerFactory.Create(builder => builder
                                                           .AddSerilog()
                                                           .AddFilter(level => level >= LogLevel.Trace));
            var logger     = loggerFactory.CreateLogger <SimcParserService>();
            var simcParser = new SimcParserService(logger);

            ParsedProfile = simcParser.ParseProfileAsync(testFileString);
        }
Пример #6
0
        private void TryApplySpecId(SimcParsedProfile profile)
        {
            var specId = Specialisation.SPEC_NONE;

            // from specialization_string in sc_const_data.cpp
            switch ((Class)profile.ClassId)
            {
            case Class.Priest:
                if (profile.Spec == "discipline")
                {
                    specId = Specialisation.PRIEST_DISCIPLINE;
                }
                if (profile.Spec == "holy")
                {
                    specId = Specialisation.PRIEST_HOLY;
                }
                if (profile.Spec == "shadow")
                {
                    specId = Specialisation.PRIEST_SHADOW;
                }
                break;

            case Class.Warrior:
                if (profile.Spec == "arms")
                {
                    specId = Specialisation.WARRIOR_ARMS;
                }
                if (profile.Spec == "fury")
                {
                    specId = Specialisation.WARRIOR_FURY;
                }
                if (profile.Spec == "protection")
                {
                    specId = Specialisation.WARRIOR_PROTECTION;
                }
                break;

            case Class.Paladin:
                if (profile.Spec == "holy")
                {
                    specId = Specialisation.PALADIN_HOLY;
                }
                if (profile.Spec == "protection")
                {
                    specId = Specialisation.PALADIN_PROTECTION;
                }
                if (profile.Spec == "retribution")
                {
                    specId = Specialisation.PALADIN_RETRIBUTION;
                }
                break;

            case Class.Hunter:
                if (profile.Spec == "beast_mastery")
                {
                    specId = Specialisation.HUNTER_BEAST_MASTERY;
                }
                if (profile.Spec == "marksmanship")
                {
                    specId = Specialisation.HUNTER_MARKSMANSHIP;
                }
                if (profile.Spec == "survival")
                {
                    specId = Specialisation.HUNTER_SURVIVAL;
                }
                break;

            case Class.Rogue:
                if (profile.Spec == "assassination")
                {
                    specId = Specialisation.ROGUE_ASSASSINATION;
                }
                if (profile.Spec == "outlaw")
                {
                    specId = Specialisation.ROGUE_OUTLAW;
                }
                if (profile.Spec == "subtlety")
                {
                    specId = Specialisation.ROGUE_SUBTLETY;
                }
                break;

            case Class.DeathKnight:
                if (profile.Spec == "blood")
                {
                    specId = Specialisation.DEATH_KNIGHT_BLOOD;
                }
                if (profile.Spec == "frost")
                {
                    specId = Specialisation.DEATH_KNIGHT_FROST;
                }
                if (profile.Spec == "unholy")
                {
                    specId = Specialisation.DEATH_KNIGHT_UNHOLY;
                }
                break;

            case Class.Shaman:
                if (profile.Spec == "elemental")
                {
                    specId = Specialisation.SHAMAN_ELEMENTAL;
                }
                if (profile.Spec == "enhancement")
                {
                    specId = Specialisation.SHAMAN_ENHANCEMENT;
                }
                if (profile.Spec == "restoration")
                {
                    specId = Specialisation.SHAMAN_RESTORATION;
                }
                break;

            case Class.Mage:
                if (profile.Spec == "arcane")
                {
                    specId = Specialisation.MAGE_ARCANE;
                }
                if (profile.Spec == "fire")
                {
                    specId = Specialisation.MAGE_FIRE;
                }
                if (profile.Spec == "frost")
                {
                    specId = Specialisation.MAGE_FROST;
                }
                break;

            case Class.Warlock:
                if (profile.Spec == "affliction")
                {
                    specId = Specialisation.WARLOCK_AFFLICTION;
                }
                if (profile.Spec == "demonology")
                {
                    specId = Specialisation.WARLOCK_DEMONOLOGY;
                }
                if (profile.Spec == "destruction")
                {
                    specId = Specialisation.WARLOCK_DESTRUCTION;
                }
                break;

            case Class.Monk:
                if (profile.Spec == "brewmaster")
                {
                    specId = Specialisation.MONK_BREWMASTER;
                }
                if (profile.Spec == "mistweaver")
                {
                    specId = Specialisation.MONK_MISTWEAVER;
                }
                if (profile.Spec == "windwalker")
                {
                    specId = Specialisation.MONK_WINDWALKER;
                }
                break;

            case Class.Druid:
                if (profile.Spec == "balance")
                {
                    specId = Specialisation.DRUID_BALANCE;
                }
                if (profile.Spec == "feral")
                {
                    specId = Specialisation.DRUID_FERAL;
                }
                if (profile.Spec == "guardian")
                {
                    specId = Specialisation.DRUID_GUARDIAN;
                }
                if (profile.Spec == "restoration")
                {
                    specId = Specialisation.DRUID_RESTORATION;
                }
                break;

            case Class.DemonHunter:
                if (profile.Spec == "havoc")
                {
                    specId = Specialisation.DEMON_HUNTER_HAVOC;
                }
                if (profile.Spec == "vengeance")
                {
                    specId = Specialisation.DEMON_HUNTER_VENGEANCE;
                }
                break;

            case Class.None:
            default:
                break;
            }

            profile.SpecId = (int)specId;
        }
Пример #7
0
        public SimcParsedProfile ParseProfileAsync(List <string> profileLines)
        {
            _logger?.LogInformation($"Parsing a profileString with {profileLines.Count} lines.");
            var runtime = Stopwatch.StartNew();

            var profile = new SimcParsedProfile();

            // Loop through each of the lines and parse them on their own merit.

            List <SimcParsedLine> validLines = new List <SimcParsedLine>();

            foreach (var rawLine in profileLines)
            {
                // Lines either start with the identifier=value combo or are commented, then identifier or comment.
                // e.g.: # shoulder=,id=173247,bonus_id=6716/1487/6977/6649/6647

                // TODO: pull the datetime/simc version from here
                var currentLine = rawLine;


                // Remove the comment #
                if (!string.IsNullOrEmpty(rawLine) && rawLine[0] == '#')
                {
                    currentLine = currentLine.Trim('#').Trim();
                }

                TryApplySimcVersion(profile, currentLine);
                TryApplyProfileDate(profile, currentLine);

                // Check if there is an identifier
                if (string.IsNullOrEmpty(rawLine) || !rawLine.Contains('='))
                {
                    continue;
                }

                _logger?.LogDebug($"New raw line: {currentLine}");

                var kvp         = currentLine.Split('=');
                var identifier  = kvp.FirstOrDefault();
                var valueString = string.Join("=", kvp.Skip(1)); // All but the identifier

                var parsedLine = new SimcParsedLine()
                {
                    RawLine    = rawLine,
                    CleanLine  = currentLine,
                    Identifier = identifier,
                    Value      = valueString
                };

                validLines.Add(parsedLine);
            }

            _logger?.LogInformation($"Found {validLines.Count} valid lines");

            if (validLines.Count == 0)
            {
                return(profile);
            }

            profile.ProfileLines = validLines;

            foreach (var line in validLines)
            {
                _logger?.LogTrace($"Processing line: {line.CleanLine} " +
                                  $"Identifier: ({line.Identifier}) Value: {line.Value}");

                switch (line.Identifier)
                {
                // Items
                case "head":
                case "neck":
                case "shoulder":
                case "back":
                case "chest":
                case "wrist":
                case "hands":
                case "waist":
                case "legs":
                case "feet":
                case "finger1":
                case "finger2":
                case "trinket1":
                case "trinket2":
                case "main_hand":
                case "off_hand":
                    _logger?.LogDebug($"Trying to parse item for slot: ({line.Identifier}) with values: {line.Value}");
                    TryApplyItem(profile, line);
                    break;

                // TODO: Add the remaining specs
                case "priest":
                case "paladin":
                case "monk":
                case "shaman":
                case "druid":
                case "rogue":
                case "mage":
                case "deathknight":
                case "demonhunter":
                case "hunter":
                case "warlock":
                case "warrior":
                    _logger?.LogDebug($"Setting player name for class ({line.Identifier}) with value: {line.Value}");
                    profile.Name = line.Value.Trim().Trim('"');
                    TryApplyClass(profile, line.Identifier.Trim());
                    break;

                case "level":
                    _logger?.LogDebug($"Trying to set level ({line.Identifier}) with value: {line.Value}");
                    TryApplyLevel(profile, line.Value.Trim());
                    break;

                case "race":
                    _logger?.LogDebug($"Trying to set race ({line.Identifier}) with value: {line.Value}");
                    TryApplyRace(profile, line);
                    break;

                case "region":
                    _logger?.LogDebug($"Trying to set region ({line.Identifier}) with value: {line.Value}");
                    profile.Region = line.Value.Trim();
                    break;

                case "server":
                    _logger?.LogDebug($"Trying to set server ({line.Identifier}) with value: {line.Value}");
                    profile.Server = line.Value.Trim();
                    break;

                case "role":
                    _logger?.LogDebug($"Trying to set role ({line.Identifier}) with value: {line.Value}");
                    profile.Role = line.Value.Trim();
                    break;

                case "professions":
                    _logger?.LogDebug($"Trying to parse profession ({line.Identifier}) with value: {line.Value}");
                    TryApplyProfessions(profile, line);
                    break;

                case "talents":
                    _logger?.LogDebug($"Trying to parse talents ({line.Identifier}) with value: {line.Value}");
                    TryApplyTalents(profile, line.Value);
                    break;

                case "spec":
                    _logger?.LogDebug($"Trying to set spec ({line.Identifier}) with value: {line.Value}");
                    profile.Spec = line.Value.Trim();
                    break;

                case "covenant":
                    _logger?.LogDebug($"Trying to parse covenant ({line.Identifier}) with value: {line.Value}");
                    profile.Covenant = line.Value.Trim();
                    break;

                case "soulbind":
                    _logger?.LogDebug($"Trying to parse soulbind ({line.Identifier}) with value: {line.Value}");
                    TryApplySoulbind(profile, line);
                    break;

                case "conduits_available":
                    _logger?.LogDebug($"Trying to parse conduits_available ({line.Identifier}) with value: {line.Value}");
                    TryApplyConduitData(profile, line.Value);
                    break;

                case "renown":
                    _logger?.LogDebug($"Trying to parse renown ({line.Identifier}) with value: {line.Value}");

                    if (int.TryParse(line.Value.Trim(), out int renown))
                    {
                        profile.Renown = renown;
                    }
                    else
                    {
                        _logger?.LogWarning($"Invalid renown value: {line.Value}");
                    }
                    break;

                default:
                    _logger?.LogWarning($"Unrecognised identifier found: {line.Identifier}");
                    break;
                }
            }

            // Call this last in case the class line is after the spec line.
            TryApplySpecId(profile);

            runtime.Stop();
            _logger?.LogInformation($"Done processing profile in {runtime.ElapsedMilliseconds}ms");

            return(profile);
        }