public Highcharts GuildHybridXpsOverTime(int bossFightId, int difficultyId, int guildId, string guildName, string bossFightName) { var graphTitle = string.Format("{0} vs {1}: Raid performance over time", guildName.Replace("'", "\\\'"), bossFightName); var stats = _recordsRepository.GetGuildStatsOverTimeHybrid(bossFightId, difficultyId, guildId); if (!stats.Any()) { return(null); } #region Build chart series var dpsSeries = new Series() { Name = "Damage" }; var dpsDataList = new List <object[]>(); var hpsSeries = new Series() { Name = "Healing", PlotOptionsSpline = new PlotOptionsSpline() { Visible = false } }; var hpsDataList = new List <object[]>(); var apsSeries = new Series() { Name = "Absorption", PlotOptionsSpline = new PlotOptionsSpline() { Visible = false } }; var apsDataList = new List <object[]>(); var durationSeries = new Series() { Name = "Encounter duration", YAxis = "1", PlotOptionsSpline = new PlotOptionsSpline() { Color = Color.FromArgb(255, 124, 181, 236), } }; var durationDataList = new List <object[]>(); foreach (var stat in stats) { dpsDataList.Add(new object[] { stat.Date, stat.AverageDps }); hpsDataList.Add(new object[] { stat.Date, stat.AverageHps }); apsDataList.Add(new object[] { stat.Date, stat.AverageAps }); durationDataList.Add(new object[] { stat.Date, new DateTime().Add(stat.Duration) }); } dpsSeries.Data = new Data(dpsDataList.ToArray()); hpsSeries.Data = new Data(hpsDataList.ToArray()); apsSeries.Data = new Data(apsDataList.ToArray()); durationSeries.Data = new Data(durationDataList.ToArray()); var chartSeries = new Series[] { dpsSeries, hpsSeries, apsSeries, durationSeries }; #endregion #region Build Y-Axes var yAxes = new List <YAxis>(); // Standard Y yAxes.Add( new YAxis { Title = new YAxisTitle { Text = "Per second", Style = ChartColors.WhiteTextStyle }, TickColor = Color.White, LineColor = Color.White, Labels = new YAxisLabels { Style = ChartColors.WhiteTextStyle } }); yAxes.Add( new YAxis { Title = new YAxisTitle { Text = "Encounter duration", Style = ChartColors.WhiteTextStyle }, Type = AxisTypes.Datetime, DateTimeLabelFormats = new DateTimeLabel { Hour = "%Mm %Ss", Minute = "%Mm %Ss", Second = "%Mm %Ss" }, TickColor = Color.White, LineColor = Color.White, Labels = new YAxisLabels { Style = ChartColors.WhiteTextStyle }, Opposite = true, }); #endregion var chart = new Highcharts(string.Format("bf{0}d{1}g{2}hybrid", bossFightId, difficultyId, guildId)) .InitChart(new Chart { DefaultSeriesType = ChartTypes.Spline, ZoomType = ZoomTypes.Xy, Height = 400, BackgroundColor = new BackColorOrGradient(new Gradient { LinearGradient = new[] { 0, 0, 0, 400 }, Stops = new object[, ] { { 0, Color.FromArgb(13, 255, 255, 255) }, { 1, Color.FromArgb(13, 255, 255, 255) } } }), Style = ChartColors.WhiteTextStyle }) .SetCredits(ChartDefaults.Credits) .SetOptions(new GlobalOptions { Colors = ChartColors.ColorArrayBlackBg(), Global = new Global { UseUTC = false } }) .SetTitle(new Title { Text = graphTitle, Style = ChartColors.WhiteTextStyle }) .SetXAxis(new XAxis { Type = AxisTypes.Datetime, DateTimeLabelFormats = new DateTimeLabel { Month = "%e %b", Year = "%e %b", Day = "%e %b", Week = "%e %b" }, LineColor = Color.White, TickColor = Color.White, Labels = new XAxisLabels { Style = ChartColors.WhiteTextStyle }, }) //.SetYAxis(new YAxis //{ // Title = new YAxisTitle { Text = "Per second", Style = ChartColors.WhiteTextStyle }, // TickColor = Color.White, // LineColor = Color.White, // Labels = new YAxisLabels { Style = ChartColors.WhiteTextStyle } //}) .SetYAxis(yAxes.ToArray()) // Combined tooltip // There's an if/else if/else statement in there to format the tooltips differently depending on the series name // The DPS chart has a tooltip that will convert the value to thousands / millions / billions etc. // Eg 1500000DPS will be 1.50M DPS .SetTooltip(new Tooltip() { Formatter = @"function() { var text = ''; if(this.series.name == 'Encounter duration') { text = '<b>' + this.series.name +'</b><br/>' + Highcharts.dateFormat('%Mm %Ss',new Date(this.y)); } else if (this.series.name == 'Healing') { text = '<b>' + this.y + '</b> HPS'; } else if (this.series.name == 'Absorption') { text = '<b>' + this.y + '</b> APS'; } else { var ret = '', multi, axis = this.series.yAxis, numericSymbols = ['k', 'M', 'B', 'T', 'P', 'E'], i = numericSymbols.length; while (i-- && ret === '') { multi = Math.pow(1000, i); if (axis.tickInterval >= multi && numericSymbols[i] !== null) { ret = '<b>' + Highcharts.numberFormat(this.y / multi / 1000, 2) + numericSymbols[i] + '</b> DPS'; } } return ret; } return text; }" }) // Tooltip for XPS //.SetTooltip(new Tooltip() { ValueSuffix = " per second" }) // Tooltip for Duration //.SetTooltip(new Tooltip { Formatter = @"function() { return '<b>' + this.series.name +'</b><br/>' + // Highcharts.dateFormat('%Mm %Ss',new Date(this.y)); }" }) .SetSeries(chartSeries) .SetExporting(new Exporting { Enabled = false }) .SetLegend(new Legend() { ItemStyle = ChartColors.WhiteTextStyle, ItemHoverStyle = "color: '#bbb'" }) ; return(chart); }