示例#1
0
        public void WriteJsonModel(IEnumerable <ILogSource> logSources, TextWriter writer)
        {
            var errors        = new List <string>();
            var jsonRotations = new List <JsonRotation>();

            var usedSkills = new Dictionary <uint, string>();

            foreach (var source in logSources)
            {
                IEnumerable <Rotation> rotations;
                try
                {
                    rotations = source.GetRotations();
                }
                catch (Exception e)
                {
                    errors.Add($"Failed to process {source.GetLogName()}: " + e.Message);
                    continue;
                }

                foreach (var rotation in rotations)
                {
                    var player = new PlayerData(rotation.PlayerName,
                                                GetTinyProfessionIconUrl(rotation.Profession, rotation.Specialization),
                                                source.GetLogName(), source.GetEncounterName());

                    foreach (var skillCast in rotation.Items.OfType <SkillCast>())
                    {
                        usedSkills[skillCast.SkillId] = skillCast.SkillName;
                    }

                    jsonRotations.Add(new JsonRotation(player, rotation.Items));
                }
            }

            var skillData = usedSkills
                            .Select(x => (Skill: (Id: x.Key, Name: x.Value), Data: apiData.GetSkillData((int)x.Key)))
                            .ToDictionary(
                x => x.Skill.Id,
                x => x.Data == null
                                                ? new { Name = x.Skill.Name, IconUrl = (string)null }
                                                : new { Name = x.Data.Name, IconUrl = x.Data.IconUrl }
                );

            writer.Write(JsonConvert.SerializeObject(new { Rotations = jsonRotations, SkillData = skillData, Errors = errors }));
        }
示例#2
0
        public override void WriteHtml(TextWriter writer)
        {
            foreach (var data in playerData)
            {
                var player = data.Player;

                // TODO: Proper alt for profession icon
                writer.WriteLine($@"
<div class='box content'>
	<article class='media'>
		<div class='media-left'>
			<figure class='image is-64x64'>
				<img src='{Theme.GetBigProfessionIconUrl(player)}' alt='Specialization icon'>
			</figure>"            );

                foreach (var badge in data.Badges)
                {
                    if (badge.Type == BadgeType.Specialization)
                    {
                        writer.WriteLine($"<span class='tag is-rounded player-trait-badge'>{badge.Text}</span>");
                    }
                }

                writer.WriteLine($@"
		</div>
		<div class='media-content'>
			<div class='content'>
				<p>
					<strong>{player.Name}</strong> <small>{player.AccountName.Substring(1)}</small> <small>(group {player.Subgroup})</small>
				</p>
				<p>"                );

                if (data.UtilitySkills != null && data.EliteSkills != null && data.HealingSkills != null)
                {
                    var skillMatrix = GetSkillMatrix(data);

                    for (int row = 0; row < skillMatrix.Length; row++)
                    {
                        foreach (var skillData in skillMatrix[row])
                        {
                            if (skillData == null)
                            {
                                writer.WriteLine(
                                    "<img class='player-skill-image' src='https://wiki.guildwars2.com/images/7/74/Skill.png' alt='Unknown skill' title='Unknown skill, unused or instant cast'>");
                            }
                            else
                            {
                                var encodedName = System.Web.HttpUtility.HtmlEncode(skillData.Name);
                                writer.WriteLine(
                                    $"<img class='player-skill-image' src='{skillData.IconUrl}' alt='{encodedName}' title='{encodedName}'>");
                            }
                        }

                        if (row != skillMatrix.Length - 1)
                        {
                            writer.WriteLine("<br>");
                        }
                    }
                }
                else
                {
                    writer.WriteLine(
                        $"No data on utility skills, perhaps API data was missing.");                         // TODO: Add reasons for missing data
                }

                writer.WriteLine($@"
                </p>
			</div>
			<div class='content is-hidden'>"            );

                // TODO: Tabs?
                if (data.Rotation != null)
                {
                    foreach (var rotationItem in data.Rotation.Items.OrderBy(x => x.ItemTime))
                    {
                        if (rotationItem is SkillCastItem skillCast)
                        {
                            var encodedName = HttpUtility.HtmlEncode(skillCast.Skill.Name);

                            var statusClass = skillCast.Type == SkillCastType.Cancel ? "cancel" :
                                              skillCast.Type == SkillCastType.Reset ? "interrupt" : "";

                            var skillData = gw2ApiData?.GetSkillData(skillCast.Skill);
                            if (skillData == null)
                            {
                                string title = $"No API data for skill {encodedName} ({skillCast.Skill.Id})";
                                writer.WriteLine(
                                    $"<img class='player-skill-image {statusClass}' src='https://wiki.guildwars2.com/images/7/74/Skill.png' alt='Unknown skill' title='{title}'>");
                            }
                            else
                            {
                                writer.WriteLine(
                                    $"<img class='player-skill-image {statusClass}' src='{skillData.IconUrl}' alt='{encodedName}' title='{encodedName}'>");
                            }
                        }
                        else if (rotationItem is WeaponSwapItem weaponSwap)
                        {
                            writer.WriteLine(
                                $"<img class='player-skill-image' src='https://wiki.guildwars2.com/images/c/ce/Weapon_Swap_Button.png' alt='Weapon Swap' title='Weapon Swap to ({weaponSwap.NewWeaponSet})'>");
                            writer.WriteLine($"<br>");
                        }
                    }
                }
                else
                {
                    writer.WriteLine("No rotation available.");
                }

                writer.WriteLine($@"
                </p>
			</div>
		</div>
		<div class='media-right'>
			<table class='table is-bordered'>
                <tr><th>Downs</th><td>{data.DownCount}</td></tr>
                <tr><th>Deaths</th><td>{data.DeathCount}</td></tr>
			</table>
		</div>
	</article>
</div>
");
            }
        }
示例#3
0
        public override void WriteHtml(TextWriter writer)
        {
            writer.WriteLine("<div id='squad-rotation'></div>");

            writer.WriteLine(@"
<script>
document.addEventListener('DOMContentLoaded', function() {
	var container = document.getElementById('squad-rotation');

	var groups = new vis.DataSet(["    );

            int playerIndex = 0;

            foreach (var data in playerData)
            {
                writer.WriteLine($@"{{id: {playerIndex++}, content: '{data.Player.Name}'}},");
            }

            writer.WriteLine(@"
	]);


	var items = new vis.DataSet(["    );

            // TODO: Optimize for HTML size

            playerIndex = 0;
            foreach (var data in playerData)
            {
                foreach (var rotationItem in data.Rotation.Items)
                {
                    if (rotationItem is SkillCastItem skillCast)
                    {
                        string className = skillCast.Type == SkillCastType.Cancel ? "className: 'cancel'" :
                                           skillCast.Type == SkillCastType.Reset ? "className: 'interrupt'" : "";

                        var htmlEncodedName = HttpUtility.HtmlEncode(skillCast.Skill.Name);

                        var imageClass = skillCast.Type == SkillCastType.Cancel ? "cancel" :
                                         skillCast.Type == SkillCastType.Reset ? "interrupt" : "";

                        string imageSrc;
                        string imageTitle;

                        var skillData = gw2ApiData?.GetSkillData(skillCast.Skill);
                        if (skillData == null)
                        {
                            if (skillCast.Skill.Id == SkillIds.ArcDpsDodge)
                            {
                                imageSrc   = "https://wiki.guildwars2.com/images/c/cc/Dodge_Instructor.png";
                                imageTitle = "Dodge";
                            }
                            else if (skillCast.Skill.Id == SkillIds.Revive)
                            {
                                imageSrc   = "https://wiki.guildwars2.com/images/3/3d/Downed_ally.png";
                                imageTitle = "Revive";
                            }
                            else
                            {
                                imageSrc   = "https://wiki.guildwars2.com/images/7/74/Skill.png";
                                imageTitle = $"No API data for skill {htmlEncodedName} ({skillCast.Skill.Id})";
                            }
                        }
                        else
                        {
                            imageSrc   = skillData.IconUrl;
                            imageTitle = htmlEncodedName;
                        }

                        string image = $"<img class='rotation-skill-image {imageClass}' src='{imageSrc}' alt='{imageTitle}' title='{imageTitle}'>";

                        image = HttpUtility.JavaScriptStringEncode(image);

                        writer.WriteLine(
                            $"{{group: {playerIndex}, content: '{image}', start: {skillCast.ItemTime}, end: {skillCast.CastEndTime}, {className}}},");
                    }
                    else if (rotationItem is WeaponSwapItem weaponSwap)
                    {
                        /* TODO: Looks ugly
                         * string image = $"<img class='rotation-skill-image' src='https://wiki.guildwars2.com/images/c/ce/Weapon_Swap_Button.png' alt='Weapon Swap' title='Weapon Swap to ({weaponSwap.NewWeaponSet})'>";
                         * image = HttpUtility.JavaScriptStringEncode(image);
                         * writer.WriteLine($"{{group: {playerIndex}, content: '{image}', start: {weaponSwap.ItemTime}, type: 'point'}},");
                         */
                    }
                    else if (rotationItem is TemporaryStatusItem temporaryStatus)
                    {
                        string name      = "";
                        string className = "";
                        switch (temporaryStatus.TemporaryStatus)
                        {
                        case TemporaryStatus.Downed:
                            name      = "Downed";
                            className = "downed";
                            break;

                        case TemporaryStatus.ContinuumSplit:
                            name      = "Continuum Split";
                            className = "csplit";
                            break;

                        default:
                            name = "Unknown status";
                            break;
                        }

                        writer.WriteLine(
                            $"{{group: {playerIndex}, content: '{name}', className: '{className}', type: 'background', start: {temporaryStatus.ItemTime}, end: {temporaryStatus.StatusEndTime}}},");
                    }
                }

                playerIndex++;
            }

            writer.WriteLine(@"
	]);

	var options = {
		format: {
			minorLabels: function(date,scale,step) {
				return Math.floor(new Date(date).getTime() / 1000) + 's';
			},
			majorLabels: function(date,scale,step) {
				return Math.floor(new Date(date).getTime() / 1000) + 's';
			},
		},
		stack: false,
		selectable: false,
		min: 0,
		//margin: {item: {horizontal: -1}},
		//start: 0, // setting start results in all items in initial window being moved down
		end: 20000,
		orientation: 'top',
	};

	var timeline = new vis.Timeline(container, items, groups, options);
});
</script>
");
            foreach (var data in playerData)
            {
                var player = data.Player;
            }
        }