Files
Aaru.Server/DiscImageChef.Server/Controllers/StatsController.cs

575 lines
25 KiB
C#
Raw Normal View History

2019-11-02 01:40:41 +00:00
// /***************************************************************************
// The Disc Image Chef
// ----------------------------------------------------------------------------
//
// Filename : StatsController.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : DiscImageChef Server.
//
// --[ Description ] ----------------------------------------------------------
//
// Fetches statistics for Razor views.
//
// --[ License ] --------------------------------------------------------------
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2019 Natalia Portillo
// ****************************************************************************/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Xml;
using System.Xml.Serialization;
using DiscImageChef.CommonTypes.Interop;
using DiscImageChef.CommonTypes.Metadata;
using DiscImageChef.Server.Models;
using Highsoft.Web.Mvc.Charts;
2019-11-02 21:01:25 +00:00
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
2019-11-02 23:52:33 +00:00
using OperatingSystem = DiscImageChef.Server.Models.OperatingSystem;
2019-11-02 01:40:41 +00:00
using PlatformID = DiscImageChef.CommonTypes.Interop.PlatformID;
2019-11-02 23:52:33 +00:00
using Version = DiscImageChef.Server.Models.Version;
2019-11-02 01:40:41 +00:00
namespace DiscImageChef.Server.Controllers
{
2019-11-02 23:52:33 +00:00
/// <summary>Renders a page with statistics, list of media type, devices, etc</summary>
2019-11-02 01:40:41 +00:00
public class StatsController : Controller
{
2019-11-02 23:52:33 +00:00
readonly IWebHostEnvironment _environment;
readonly DicServerContext ctx;
List<DeviceItem> devices;
List<NameValueStats> operatingSystems;
List<MediaItem> realMedia;
List<NameValueStats> versions;
List<MediaItem> virtualMedia;
2019-11-02 21:01:25 +00:00
public StatsController(IWebHostEnvironment environment, DicServerContext context)
{
_environment = environment;
2019-11-02 23:52:33 +00:00
ctx = context;
2019-11-02 21:01:25 +00:00
}
2019-11-02 01:40:41 +00:00
public ActionResult Index()
{
ViewBag.Version = Assembly.GetExecutingAssembly().GetName().Version.ToString();
try
{
2019-11-02 23:52:33 +00:00
if(
System.IO.File.
Exists(Path.Combine(_environment.ContentRootPath ?? throw new InvalidOperationException(),
"Statistics", "Statistics.xml")))
2019-11-02 01:40:41 +00:00
try
{
2019-11-02 21:37:09 +00:00
var statistics = new Stats();
var xs = new XmlSerializer(statistics.GetType());
2019-11-02 23:52:33 +00:00
FileStream fs =
WaitForFile(Path.Combine(_environment.ContentRootPath ?? throw new InvalidOperationException(), "Statistics", "Statistics.xml"),
FileMode.Open, FileAccess.Read, FileShare.Read);
statistics = (Stats)xs.Deserialize(fs);
2019-11-02 01:40:41 +00:00
fs.Close();
StatsConverter.Convert(statistics);
2019-11-02 23:52:33 +00:00
System.IO.File.
Delete(Path.Combine(_environment.ContentRootPath ?? throw new InvalidOperationException(),
"Statistics", "Statistics.xml"));
2019-11-02 01:40:41 +00:00
}
2019-11-02 23:52:33 +00:00
catch(XmlException)
2019-11-02 01:40:41 +00:00
{
// Do nothing
}
2019-11-02 23:52:33 +00:00
if(ctx.OperatingSystems.Any())
2019-11-02 01:40:41 +00:00
{
operatingSystems = new List<NameValueStats>();
2019-11-02 23:52:33 +00:00
foreach(OperatingSystem nvs in ctx.OperatingSystems)
2019-11-02 01:40:41 +00:00
operatingSystems.Add(new NameValueStats
{
name =
2019-11-02 23:52:33 +00:00
$"{DetectOS.GetPlatformName((PlatformID)Enum.Parse(typeof(PlatformID), nvs.Name), nvs.Version)}{(string.IsNullOrEmpty(nvs.Version) ? "" : " ")}{nvs.Version}",
2019-11-02 01:40:41 +00:00
Value = nvs.Count
});
ViewBag.repOperatingSystems = operatingSystems.OrderBy(os => os.name).ToList();
2019-11-02 23:52:33 +00:00
List<PieSeriesData> windowsPieData = new List<PieSeriesData>();
decimal windowsCount = ctx.OperatingSystems.Where(o => o.Name == PlatformID.Win32NT.ToString()).
Sum(o => o.Count);
2019-11-02 01:40:41 +00:00
2019-11-02 23:52:33 +00:00
foreach(OperatingSystem version in
2019-11-02 01:40:41 +00:00
ctx.OperatingSystems.Where(o => o.Name == PlatformID.Win32NT.ToString()))
windowsPieData.Add(new PieSeriesData
{
Name =
$"{DetectOS.GetPlatformName(PlatformID.Win32NT, version.Version)}{(string.IsNullOrEmpty(version.Version) ? "" : " ")}{version.Version}",
2019-11-02 23:52:33 +00:00
Y = (double?)(version.Count / windowsCount)
2019-11-02 01:40:41 +00:00
});
ViewData["windowsPieData"] = windowsPieData;
}
2019-11-02 23:52:33 +00:00
if(ctx.Versions.Any())
2019-11-02 01:40:41 +00:00
{
versions = new List<NameValueStats>();
2019-11-02 23:52:33 +00:00
foreach(Version nvs in ctx.Versions)
2019-11-02 01:40:41 +00:00
versions.Add(new NameValueStats
{
2019-11-02 23:52:33 +00:00
name = nvs.Value == "previous" ? "Previous than 3.4.99.0" : nvs.Value, Value = nvs.Count
2019-11-02 01:40:41 +00:00
});
ViewBag.repVersions = versions.OrderBy(ver => ver.name).ToList();
decimal totalVersionCount = ctx.Versions.Sum(o => o.Count);
ViewData["versionsPieData"] = ctx.Versions.Select(version => new PieSeriesData
{
2019-11-02 23:52:33 +00:00
Name = version.Value == "previous" ? "Previous than 3.4.99.0" : version.Value,
Y = (double?)(version.Count / totalVersionCount), Sliced = version.Value == "previous",
Selected = version.Value == "previous"
2019-11-02 01:40:41 +00:00
}).ToList();
}
2019-11-02 23:52:33 +00:00
if(ctx.Commands.Any())
2019-11-02 01:40:41 +00:00
{
ViewBag.repCommands = ctx.Commands.OrderBy(c => c.Name).ToList();
decimal totalCommandCount = ctx.Commands.Sum(o => o.Count);
2019-11-02 23:52:33 +00:00
ViewData["commandsPieData"] = ctx.Commands.Select(command => new PieSeriesData
{
Name = command.Name, Y = (double?)(command.Count / totalCommandCount),
Sliced = command.Name == "analyze", Selected = command.Name == "analyze"
}).ToList();
2019-11-02 01:40:41 +00:00
}
2019-11-02 23:52:33 +00:00
if(ctx.Filters.Any())
2019-11-02 01:40:41 +00:00
{
ViewBag.repFilters = ctx.Filters.OrderBy(filter => filter.Name).ToList();
2019-11-02 23:52:33 +00:00
List<PieSeriesData> filtersPieData = new List<PieSeriesData>();
2019-11-02 01:40:41 +00:00
decimal totalFiltersCount = ctx.Filters.Sum(o => o.Count);
2019-11-02 23:52:33 +00:00
foreach(Filter filter in ctx.Filters.ToList())
2019-11-02 01:40:41 +00:00
filtersPieData.Add(new PieSeriesData
{
2019-11-02 23:52:33 +00:00
Name = filter.Name, Y = (double?)(filter.Count / totalFiltersCount),
Sliced = filter.Name == "No filter", Selected = filter.Name == "No filter"
2019-11-02 01:40:41 +00:00
});
ViewData["filtersPieData"] = filtersPieData;
}
2019-11-02 23:52:33 +00:00
if(ctx.MediaFormats.Any())
2019-11-02 01:40:41 +00:00
{
ViewBag.repMediaImages = ctx.MediaFormats.OrderBy(filter => filter.Name).ToList();
2019-11-02 23:52:33 +00:00
List<PieSeriesData> formatsPieData = new List<PieSeriesData>();
2019-11-02 01:40:41 +00:00
decimal totalFormatsCount = ctx.MediaFormats.Sum(o => o.Count);
2019-11-02 23:52:33 +00:00
decimal top10FormatCount = 0;
2019-11-02 01:40:41 +00:00
2019-11-02 23:52:33 +00:00
foreach(MediaFormat format in ctx.MediaFormats.OrderByDescending(o => o.Count).Take(10))
2019-11-02 01:40:41 +00:00
{
top10FormatCount += format.Count;
formatsPieData.Add(new PieSeriesData
{
2019-11-02 23:52:33 +00:00
Name = format.Name, Y = (double?)(format.Count / totalFormatsCount)
2019-11-02 01:40:41 +00:00
});
}
formatsPieData.Add(new PieSeriesData
{
2019-11-02 23:52:33 +00:00
Name = "Other", Y = (double?)((totalFormatsCount - top10FormatCount) / totalFormatsCount),
Sliced = true, Selected = true
2019-11-02 01:40:41 +00:00
});
ViewData["formatsPieData"] = formatsPieData;
}
2019-11-02 23:52:33 +00:00
if(ctx.Partitions.Any())
2019-11-02 01:40:41 +00:00
{
ViewBag.repPartitions = ctx.Partitions.OrderBy(filter => filter.Name).ToList();
2019-11-02 23:52:33 +00:00
List<PieSeriesData> partitionsPieData = new List<PieSeriesData>();
2019-11-02 01:40:41 +00:00
decimal totalPartitionsCount = ctx.Partitions.Sum(o => o.Count);
2019-11-02 23:52:33 +00:00
decimal top10PartitionCount = 0;
2019-11-02 01:40:41 +00:00
2019-11-02 23:52:33 +00:00
foreach(Partition partition in ctx.Partitions.OrderByDescending(o => o.Count).Take(10))
2019-11-02 01:40:41 +00:00
{
top10PartitionCount += partition.Count;
partitionsPieData.Add(new PieSeriesData
{
2019-11-02 23:52:33 +00:00
Name = partition.Name, Y = (double?)(partition.Count / totalPartitionsCount)
2019-11-02 01:40:41 +00:00
});
}
partitionsPieData.Add(new PieSeriesData
{
2019-11-02 23:52:33 +00:00
Name = "Other",
Y = (double?)((totalPartitionsCount - top10PartitionCount) / totalPartitionsCount),
Sliced = true, Selected = true
2019-11-02 01:40:41 +00:00
});
ViewData["partitionsPieData"] = partitionsPieData;
}
2019-11-02 23:52:33 +00:00
if(ctx.Filesystems.Any())
2019-11-02 01:40:41 +00:00
{
ViewBag.repFilesystems = ctx.Filesystems.OrderBy(filter => filter.Name).ToList();
2019-11-02 23:52:33 +00:00
List<PieSeriesData> filesystemsPieData = new List<PieSeriesData>();
2019-11-02 01:40:41 +00:00
decimal totalFilesystemsCount = ctx.Filesystems.Sum(o => o.Count);
2019-11-02 23:52:33 +00:00
decimal top10FilesystemCount = 0;
2019-11-02 01:40:41 +00:00
2019-11-02 23:52:33 +00:00
foreach(Filesystem filesystem in ctx.Filesystems.OrderByDescending(o => o.Count).Take(10))
2019-11-02 01:40:41 +00:00
{
top10FilesystemCount += filesystem.Count;
filesystemsPieData.Add(new PieSeriesData
{
2019-11-02 23:52:33 +00:00
Name = filesystem.Name, Y = (double?)(filesystem.Count / totalFilesystemsCount)
2019-11-02 01:40:41 +00:00
});
}
filesystemsPieData.Add(new PieSeriesData
{
2019-11-02 23:52:33 +00:00
Name = "Other",
Y = (double?)((totalFilesystemsCount - top10FilesystemCount) / totalFilesystemsCount),
Sliced = true, Selected = true
2019-11-02 01:40:41 +00:00
});
ViewData["filesystemsPieData"] = filesystemsPieData;
}
2019-11-02 23:52:33 +00:00
if(ctx.Medias.Any())
2019-11-02 01:40:41 +00:00
{
2019-11-02 23:52:33 +00:00
realMedia = new List<MediaItem>();
2019-11-02 01:40:41 +00:00
virtualMedia = new List<MediaItem>();
2019-11-02 23:52:33 +00:00
foreach(Media nvs in ctx.Medias)
2019-11-02 01:40:41 +00:00
try
{
2019-11-02 23:52:33 +00:00
MediaType.
MediaTypeToString((CommonTypes.MediaType)Enum.Parse(typeof(CommonTypes.MediaType), nvs.Type),
out string type, out string subtype);
if(nvs.Real)
realMedia.Add(new MediaItem
{
Type = type, SubType = subtype, Count = nvs.Count
});
else
virtualMedia.Add(new MediaItem
{
Type = type, SubType = subtype, Count = nvs.Count
});
2019-11-02 01:40:41 +00:00
}
catch
{
2019-11-02 23:52:33 +00:00
if(nvs.Real)
realMedia.Add(new MediaItem
{
Type = nvs.Type, SubType = null, Count = nvs.Count
});
else
virtualMedia.Add(new MediaItem
{
Type = nvs.Type, SubType = null, Count = nvs.Count
});
2019-11-02 01:40:41 +00:00
}
2019-11-02 23:52:33 +00:00
if(realMedia.Count > 0)
2019-11-02 01:40:41 +00:00
{
ViewBag.repRealMedia =
realMedia.OrderBy(media => media.Type).ThenBy(media => media.SubType).ToList();
2019-11-02 23:52:33 +00:00
List<PieSeriesData> realMediaPieData = new List<PieSeriesData>();
2019-11-02 01:40:41 +00:00
decimal totalRealMediaCount = realMedia.Sum(o => o.Count);
decimal top10RealMediaCount = 0;
2019-11-02 23:52:33 +00:00
foreach(MediaItem realMediaItem in realMedia.OrderByDescending(o => o.Count).Take(10))
2019-11-02 01:40:41 +00:00
{
top10RealMediaCount += realMediaItem.Count;
realMediaPieData.Add(new PieSeriesData
{
Name = $"{realMediaItem.Type} ({realMediaItem.SubType})",
2019-11-02 23:52:33 +00:00
Y = (double?)(realMediaItem.Count / totalRealMediaCount)
2019-11-02 01:40:41 +00:00
});
}
realMediaPieData.Add(new PieSeriesData
{
2019-11-02 23:52:33 +00:00
Name = "Other",
Y = (double?)((totalRealMediaCount - top10RealMediaCount) / totalRealMediaCount),
Sliced = true, Selected = true
2019-11-02 01:40:41 +00:00
});
ViewData["realMediaPieData"] = realMediaPieData;
}
2019-11-02 23:52:33 +00:00
if(virtualMedia.Count > 0)
2019-11-02 01:40:41 +00:00
{
ViewBag.repVirtualMedia =
virtualMedia.OrderBy(media => media.Type).ThenBy(media => media.SubType).ToList();
2019-11-02 23:52:33 +00:00
List<PieSeriesData> virtualMediaPieData = new List<PieSeriesData>();
2019-11-02 01:40:41 +00:00
decimal totalVirtualMediaCount = virtualMedia.Sum(o => o.Count);
decimal top10VirtualMediaCount = 0;
2019-11-02 23:52:33 +00:00
foreach(MediaItem virtualMediaItem in virtualMedia.OrderByDescending(o => o.Count).Take(10))
2019-11-02 01:40:41 +00:00
{
top10VirtualMediaCount += virtualMediaItem.Count;
virtualMediaPieData.Add(new PieSeriesData
{
2019-11-02 23:52:33 +00:00
Name = $"{virtualMediaItem.Type} ({virtualMediaItem.SubType})",
Y = (double?)(virtualMediaItem.Count / totalVirtualMediaCount)
2019-11-02 01:40:41 +00:00
});
}
virtualMediaPieData.Add(new PieSeriesData
{
Name = "Other",
2019-11-02 23:52:33 +00:00
Y = (double?)((totalVirtualMediaCount - top10VirtualMediaCount) /
totalVirtualMediaCount),
Sliced = true, Selected = true
2019-11-02 01:40:41 +00:00
});
ViewData["virtualMediaPieData"] = virtualMediaPieData;
}
}
2019-11-02 23:52:33 +00:00
if(ctx.DeviceStats.Any())
2019-11-02 01:40:41 +00:00
{
devices = new List<DeviceItem>();
2019-11-02 23:52:33 +00:00
foreach(DeviceStat device in ctx.DeviceStats.ToList())
2019-11-02 01:40:41 +00:00
{
string xmlFile;
2019-11-02 23:52:33 +00:00
if(!string.IsNullOrWhiteSpace(device.Manufacturer) &&
!string.IsNullOrWhiteSpace(device.Model) &&
!string.IsNullOrWhiteSpace(device.Revision))
2019-11-02 01:40:41 +00:00
xmlFile = device.Manufacturer + "_" + device.Model + "_" + device.Revision + ".xml";
2019-11-02 23:52:33 +00:00
else if(!string.IsNullOrWhiteSpace(device.Manufacturer) &&
!string.IsNullOrWhiteSpace(device.Model))
2019-11-02 01:40:41 +00:00
xmlFile = device.Manufacturer + "_" + device.Model + ".xml";
2019-11-02 23:52:33 +00:00
else if(!string.IsNullOrWhiteSpace(device.Model) &&
!string.IsNullOrWhiteSpace(device.Revision))
2019-11-02 21:37:09 +00:00
xmlFile = device.Model + "_" + device.Revision + ".xml";
2019-11-02 23:52:33 +00:00
else
xmlFile = device.Model + ".xml";
2019-11-02 01:40:41 +00:00
xmlFile = xmlFile.Replace('/', '_').Replace('\\', '_').Replace('?', '_');
2019-11-02 23:52:33 +00:00
if(System.IO.File.Exists(Path.Combine(_environment.ContentRootPath, "Reports", xmlFile)))
2019-11-02 01:40:41 +00:00
{
2019-11-02 21:37:09 +00:00
var deviceReport = new DeviceReport();
var xs = new XmlSerializer(deviceReport.GetType());
2019-11-02 23:52:33 +00:00
FileStream fs =
WaitForFile(Path.Combine(_environment.ContentRootPath ?? throw new InvalidOperationException(), "Reports", xmlFile),
FileMode.Open, FileAccess.Read, FileShare.Read);
deviceReport = (DeviceReport)xs.Deserialize(fs);
2019-11-02 01:40:41 +00:00
fs.Close();
2019-11-02 21:37:09 +00:00
var deviceReportV2 = new DeviceReportV2(deviceReport);
2019-11-02 01:40:41 +00:00
2019-11-02 21:01:25 +00:00
device.Report = ctx.Devices.Add(new Device(deviceReportV2)).Entity;
2019-11-02 01:40:41 +00:00
ctx.SaveChanges();
2019-11-02 23:52:33 +00:00
System.IO.File.
Delete(Path.Combine(_environment.ContentRootPath ?? throw new InvalidOperationException(),
"Reports", xmlFile));
2019-11-02 01:40:41 +00:00
}
devices.Add(new DeviceItem
{
2019-11-02 23:52:33 +00:00
Manufacturer = device.Manufacturer, Model = device.Model, Revision = device.Revision,
Bus = device.Bus,
ReportId = device.Report != null && device.Report.Id != 0 ? device.Report.Id : 0
2019-11-02 01:40:41 +00:00
});
}
2019-11-02 23:52:33 +00:00
ViewBag.repDevices = devices.OrderBy(device => device.Manufacturer).ThenBy(device => device.Model).
ThenBy(device => device.Revision).ThenBy(device => device.Bus).
ToList();
2019-11-02 01:40:41 +00:00
ViewData["devicesBusPieData"] = (from deviceBus in devices.Select(d => d.Bus).Distinct()
2019-11-02 23:52:33 +00:00
let deviceBusCount = devices.Count(d => d.Bus == deviceBus)
select new PieSeriesData
{
Name = deviceBus, Y = deviceBusCount / (double)devices.Count
}).ToList();
2019-11-02 01:40:41 +00:00
ViewData["devicesManufacturerPieData"] =
2019-11-02 23:52:33 +00:00
(from manufacturer in devices.Where(d => d.Manufacturer != null).
Select(d => d.Manufacturer.ToLowerInvariant()).Distinct()
let manufacturerCount = devices.Count(d => d.Manufacturer?.ToLowerInvariant() == manufacturer)
select new PieSeriesData
{
Name = manufacturer, Y = manufacturerCount / (double)devices.Count
}).ToList();
2019-11-02 01:40:41 +00:00
}
}
2019-11-02 23:52:33 +00:00
catch(Exception)
2019-11-02 01:40:41 +00:00
{
2019-11-02 23:52:33 +00:00
#if DEBUG
2019-11-02 01:40:41 +00:00
throw;
2019-11-02 23:52:33 +00:00
#endif
2019-11-02 01:40:41 +00:00
return Content("Could not read statistics");
}
return View();
}
2019-11-02 23:52:33 +00:00
static FileStream WaitForFile(string fullPath, FileMode mode, FileAccess access, FileShare share)
2019-11-02 01:40:41 +00:00
{
2019-11-02 23:52:33 +00:00
for(int numTries = 0; numTries < 100; numTries++)
2019-11-02 01:40:41 +00:00
{
FileStream fs = null;
2019-11-02 23:52:33 +00:00
2019-11-02 01:40:41 +00:00
try
{
fs = new FileStream(fullPath, mode, access, share);
2019-11-02 23:52:33 +00:00
2019-11-02 01:40:41 +00:00
return fs;
}
2019-11-02 23:52:33 +00:00
catch(IOException)
2019-11-02 01:40:41 +00:00
{
fs?.Dispose();
Thread.Sleep(50);
}
}
return null;
}
2019-11-03 03:20:04 +00:00
public IActionResult GetOsData()
{
var query = ctx.OperatingSystems.GroupBy(x => new
{
x.Name
}, x => x.Count).Select(g => new
{
g.Key.Name, Count = g.Sum()
});
string[][] result = new string[2][];
result[0] = query.Select(x => x.Name).ToArray();
result[1] = query.Select(x => x.Count.ToString()).ToArray();
for(int i = 0; i < result[0].Length; i++)
result[0][i] = DetectOS.GetPlatformName((PlatformID)Enum.Parse(typeof(PlatformID), result[0][i]));
return Json(result);
}
2019-11-03 03:36:49 +00:00
public IActionResult GetLinuxData()
2019-11-03 03:36:49 +00:00
{
string[][] result =
{
ctx.OperatingSystems.Where(o => o.Name == PlatformID.Linux.ToString()).OrderByDescending(o => o.Count).
Take(10).
Select(x =>
$"{DetectOS.GetPlatformName(PlatformID.Linux, x.Version)}{(string.IsNullOrEmpty(x.Version) ? "" : " ")}{x.Version}").
ToArray(),
ctx.OperatingSystems.Where(o => o.Name == PlatformID.Linux.ToString()).OrderByDescending(o => o.Count).
Take(10).Select(x => x.Count.ToString()).ToArray()
};
if(result[0].Length < 10)
return Json(result);
result[0][9] = "Other";
result[1][9] = (ctx.OperatingSystems.Where(o => o.Name == PlatformID.Linux.ToString()).Sum(o => o.Count) -
result[1].Take(9).Sum(long.Parse)).ToString();
return Json(result);
}
public IActionResult GetMacOsData()
2019-11-03 03:43:34 +00:00
{
string[][] result =
{
ctx.OperatingSystems.Where(o => o.Name == PlatformID.MacOSX.ToString()).OrderByDescending(o => o.Count).
Take(10).
Select(x =>
$"{DetectOS.GetPlatformName(PlatformID.MacOSX, x.Version)}{(string.IsNullOrEmpty(x.Version) ? "" : " ")}{x.Version}").
ToArray(),
ctx.OperatingSystems.Where(o => o.Name == PlatformID.MacOSX.ToString()).OrderByDescending(o => o.Count).
Take(10).Select(x => x.Count.ToString()).ToArray()
};
if(result[0].Length < 10)
return Json(result);
result[0][9] = "Other";
result[1][9] = (ctx.OperatingSystems.Where(o => o.Name == PlatformID.MacOSX.ToString()).Sum(o => o.Count) -
result[1].Take(9).Sum(long.Parse)).ToString();
return Json(result);
}
public IActionResult GetWindowsData()
{
string[][] result =
{
ctx.OperatingSystems.Where(o => o.Name == PlatformID.Win32NT.ToString()).
OrderByDescending(o => o.Count).Take(10).
Select(x =>
$"{DetectOS.GetPlatformName(PlatformID.Win32NT, x.Version)}{(string.IsNullOrEmpty(x.Version) ? "" : " ")}{x.Version}").
ToArray(),
ctx.OperatingSystems.Where(o => o.Name == PlatformID.Win32NT.ToString()).
OrderByDescending(o => o.Count).Take(10).Select(x => x.Count.ToString()).ToArray()
};
if(result[0].Length < 10)
return Json(result);
result[0][9] = "Other";
result[1][9] = (ctx.OperatingSystems.Where(o => o.Name == PlatformID.Win32NT.ToString()).Sum(o => o.Count) -
result[1].Take(9).Sum(long.Parse)).ToString();
return Json(result);
}
2019-11-02 01:40:41 +00:00
}
}