Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update sample apps #2

Merged
merged 2 commits into from
May 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 16 additions & 9 deletions MelonChart.sln
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{3D03FD67-99F
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MelonChart", "src\MelonChart\MelonChart.csproj", "{8C61EBBC-B2B6-4C3D-A7AA-2D9569EAE8DC}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sample", "sample", "{ACA1464B-2D70-4B57-B6A6-2E399931AC0A}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{8CF3DBA1-84DB-4274-86EA-3BB54B7262C0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MelonChart.ConsoleApp", "sample\MelonChart.ConsoleApp\MelonChart.ConsoleApp.csproj", "{FA517387-3495-4649-81D3-AF51A9A683B8}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MelonChart.Tests", "test\MelonChart.Tests\MelonChart.Tests.csproj", "{48FBE532-F50C-4CE5-A61D-86B5921B9ACE}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{8CF3DBA1-84DB-4274-86EA-3BB54B7262C0}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{ACA1464B-2D70-4B57-B6A6-2E399931AC0A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MelonChart.Tests", "test\MelonChart.Tests\MelonChart.Tests.csproj", "{48FBE532-F50C-4CE5-A61D-86B5921B9ACE}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MelonChart.ConsoleApp", "samples\MelonChart.ConsoleApp\MelonChart.ConsoleApp.csproj", "{FA517387-3495-4649-81D3-AF51A9A683B8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MelonChart.WebApp", "samples\MelonChart.WebApp\MelonChart.WebApp.csproj", "{1515CA58-4FAF-4F89-898C-599E55694F84}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand All @@ -25,22 +27,27 @@ Global
{8C61EBBC-B2B6-4C3D-A7AA-2D9569EAE8DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8C61EBBC-B2B6-4C3D-A7AA-2D9569EAE8DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8C61EBBC-B2B6-4C3D-A7AA-2D9569EAE8DC}.Release|Any CPU.Build.0 = Release|Any CPU
{FA517387-3495-4649-81D3-AF51A9A683B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FA517387-3495-4649-81D3-AF51A9A683B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FA517387-3495-4649-81D3-AF51A9A683B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FA517387-3495-4649-81D3-AF51A9A683B8}.Release|Any CPU.Build.0 = Release|Any CPU
{48FBE532-F50C-4CE5-A61D-86B5921B9ACE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{48FBE532-F50C-4CE5-A61D-86B5921B9ACE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{48FBE532-F50C-4CE5-A61D-86B5921B9ACE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{48FBE532-F50C-4CE5-A61D-86B5921B9ACE}.Release|Any CPU.Build.0 = Release|Any CPU
{FA517387-3495-4649-81D3-AF51A9A683B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FA517387-3495-4649-81D3-AF51A9A683B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FA517387-3495-4649-81D3-AF51A9A683B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FA517387-3495-4649-81D3-AF51A9A683B8}.Release|Any CPU.Build.0 = Release|Any CPU
{1515CA58-4FAF-4F89-898C-599E55694F84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1515CA58-4FAF-4F89-898C-599E55694F84}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1515CA58-4FAF-4F89-898C-599E55694F84}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1515CA58-4FAF-4F89-898C-599E55694F84}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{8C61EBBC-B2B6-4C3D-A7AA-2D9569EAE8DC} = {3D03FD67-99F7-4245-83C4-230456C5D9F5}
{FA517387-3495-4649-81D3-AF51A9A683B8} = {ACA1464B-2D70-4B57-B6A6-2E399931AC0A}
{48FBE532-F50C-4CE5-A61D-86B5921B9ACE} = {8CF3DBA1-84DB-4274-86EA-3BB54B7262C0}
{FA517387-3495-4649-81D3-AF51A9A683B8} = {ACA1464B-2D70-4B57-B6A6-2E399931AC0A}
{1515CA58-4FAF-4F89-898C-599E55694F84} = {ACA1464B-2D70-4B57-B6A6-2E399931AC0A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {34032734-030B-4982-8F04-9138EFCDF681}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,57 +1,57 @@
namespace MelonChart.ConsoleApp.Options;
/// <summary>
/// This represents the options entity for arguments.
/// </summary>
public class ArgumentOptions
{
/// <summary>
/// Gets or sets the <see cref="ChartTypes"/> value.
/// </summary>
public ChartTypes ChartType { get; set; } = ChartTypes.Top100;
/// <summary>
/// Gets or sets the value indicating whether to display help or not.
/// </summary>
public bool Help { get; set; } = false;
/// <summary>
/// Parses the arguments and returns the <see cref="ArgumentOptions"/> instance.
/// </summary>
/// <param name="args">List of arguments.</param>
/// <returns>Returns the <see cref="ArgumentOptions"/> instance.</returns>
public static ArgumentOptions Parse(string[] args)
{
var options = new ArgumentOptions();
if (args.Length == 0)
{
return options;
}
for (var i = 0; i < args.Length; i++)
{
var arg = args[i];
switch (arg)
{
case "-c":
case "-t":
case "--chart":
case "--type":
case "--chart-type":
options.ChartType = i < args.Length - 1
? Enum.TryParse<ChartTypes>(args[++i], ignoreCase: true, out var result)
? result
: throw new ArgumentException("Invalid chart type. It should be 'Top100', 'Hot100', 'Daily100', 'Weekly100' or 'Monthly100'.")
: throw new ArgumentException("Invalid chart type. It should be 'Top100', 'Hot100', 'Daily100', 'Weekly100' or 'Monthly100'.");
break;
case "-h":
case "--help":
options.Help = true;
break;
}
}
return options;
}
}
namespace MelonChart.ConsoleApp.Options;

/// <summary>
/// This represents the options entity for arguments.
/// </summary>
public class ArgumentOptions
{
/// <summary>
/// Gets or sets the <see cref="ChartTypes"/> value.
/// </summary>
public ChartTypes ChartType { get; set; } = ChartTypes.Top100;

/// <summary>
/// Gets or sets the value indicating whether to display help or not.
/// </summary>
public bool Help { get; set; } = false;

/// <summary>
/// Parses the arguments and returns the <see cref="ArgumentOptions"/> instance.
/// </summary>
/// <param name="args">List of arguments.</param>
/// <returns>Returns the <see cref="ArgumentOptions"/> instance.</returns>
public static ArgumentOptions Parse(string[] args)
{
var options = new ArgumentOptions();
if (args.Length == 0)
{
return options;
}

for (var i = 0; i < args.Length; i++)
{
var arg = args[i];
switch (arg)
{
case "-c":
case "-t":
case "--chart":
case "--type":
case "--chart-type":
options.ChartType = i < args.Length - 1
? Enum.TryParse<ChartTypes>(args[++i], ignoreCase: true, out var result)
? result
: throw new ArgumentException("Invalid chart type. It should be 'Top100', 'Hot100', 'Daily100', 'Weekly100' or 'Monthly100'.")
: throw new ArgumentException("Invalid chart type. It should be 'Top100', 'Hot100', 'Daily100', 'Weekly100' or 'Monthly100'.");
break;

case "-h":
case "--help":
options.Help = true;
break;
}
}

return options;
}
}
Original file line number Diff line number Diff line change
@@ -1,80 +1,84 @@
using MelonChart.Abstractions;
using MelonChart.ConsoleApp.Options;
using MelonChart.Models;

namespace MelonChart.ConsoleApp.Services;

/// <summary>
/// This represents the service entity for Melon chart.
/// </summary>
/// <param name="charts">List of <see cref="IChart"/> instances.</param>
public class MelonChartService(IEnumerable<IChart> charts) : IMelonChartService
{
private readonly IEnumerable<IChart> _charts = charts ?? throw new ArgumentNullException(nameof(charts));

/// <inheritdoc />
public async Task RunAsync(string[] args)
{
var options = ArgumentOptions.Parse(args);
if (options.Help)
{
this.DisplayHelp();
return;
}

try
{
var chart = this._charts.SingleOrDefault(p => p.ChartType.Equals(options.ChartType));
if (chart is null)
{
throw new ArgumentException("Invalid chart type. It should be 'Top100', 'Hot100', 'Daily100', 'Weekly100' or 'Monthly100'.");
}

var collection = await chart.GetChartAsync().ConfigureAwait(false);
this.DisplayDetails(collection);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
this.DisplayHelp();
}
}

private void DisplayDetails(ChartItemCollection collection)
{
Console.WriteLine($"Chart Type: {collection.ChartType}");
if (string.IsNullOrWhiteSpace(collection.DateLastUpdated) == false)
{
Console.WriteLine($"Date: {collection.DateLastUpdated}");
}
if (string.IsNullOrWhiteSpace(collection.TimeLastUpdated) == false)
{
Console.WriteLine($"Time: {collection.TimeLastUpdated}");
}
if (string.IsNullOrWhiteSpace(collection.PeriodFrom) == false && string.IsNullOrWhiteSpace(collection.PeriodTo) == false)
{
Console.WriteLine($"Week: {collection.PeriodFrom} - {collection.PeriodTo}");
}
if (string.IsNullOrWhiteSpace(collection.Year) == false && string.IsNullOrWhiteSpace(collection.Month) == false)
{
Console.WriteLine($"Month: {collection.Year}-{collection.Month}");
}
Console.WriteLine();

var items = collection.Items;

Console.WriteLine("Rank\tTitle\tArtist\tAlbum");
Console.WriteLine("----\t-----\t------\t-----");
foreach (var item in items)
{
Console.WriteLine($"{item.Rank}\t{item.Title}\t{item.Artist}\t{item.Album}");
}
}

private void DisplayHelp()
{
Console.WriteLine("Usage:");
Console.WriteLine(" -c, -t, --chart, --type, --chart-type <chart-type> Chart type - 'Top100', 'Hot100', 'Daily100', 'Weekly100' or 'Monthly100'.");
Console.WriteLine(" -h, --help Display help");
}
}
using MelonChart.Abstractions;
using MelonChart.ConsoleApp.Options;
using MelonChart.Models;

namespace MelonChart.ConsoleApp.Services;

/// <summary>
/// This represents the service entity for Melon chart.
/// </summary>
/// <param name="charts">List of <see cref="IChart"/> instances.</param>
public class MelonChartService(IEnumerable<IChart> charts) : IMelonChartService
{
private readonly IEnumerable<IChart> _charts = charts ?? throw new ArgumentNullException(nameof(charts));

/// <inheritdoc />
public async Task RunAsync(string[] args)
{
var options = ArgumentOptions.Parse(args);
if (options.Help)
{
this.DisplayHelp();
return;
}

try
{
var chart = this._charts.SingleOrDefault(p => p.ChartType.Equals(options.ChartType));
if (chart is null)
{
throw new ArgumentException("Invalid chart type. It should be 'Top100', 'Hot100', 'Daily100', 'Weekly100' or 'Monthly100'.");
}

var collection = await chart.GetChartAsync().ConfigureAwait(false);
this.DisplayDetails(collection);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
this.DisplayHelp();
}
}

private void DisplayDetails(ChartItemCollection collection)
{
Console.WriteLine($"Chart Type: {collection.ChartType}");
switch (collection.ChartType)
{
case ChartTypes.Top100:
case ChartTypes.Hot100:
default:
Console.WriteLine($"Date/Time: {collection.DateLastUpdated} {collection.TimeLastUpdated}");
break;

case ChartTypes.Daily100:
Console.WriteLine($"Date: {collection.DateLastUpdated}");
break;

case ChartTypes.Weekly100:
Console.WriteLine($"Week: {collection.PeriodFrom} - {collection.PeriodTo}");
break;

case ChartTypes.Monthly100:
Console.WriteLine($"Month: {collection.Year}-{collection.Month}");
break;
}
Console.WriteLine();

var items = collection.Items;

Console.WriteLine("Rank\tTitle\tArtist\tAlbum");
Console.WriteLine("----\t-----\t------\t-----");
foreach (var item in items)
{
Console.WriteLine($"{item.Rank}\t{item.Title}\t{item.Artist}\t{item.Album}");
}
}

private void DisplayHelp()
{
Console.WriteLine("Usage:");
Console.WriteLine(" -c, -t, --chart, --type, --chart-type <chart-type> Chart type - 'Top100', 'Hot100', 'Daily100', 'Weekly100' or 'Monthly100'.");
Console.WriteLine(" -h, --help Display help");
}
}
20 changes: 20 additions & 0 deletions samples/MelonChart.WebApp/Components/App.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="/" />
<link rel="stylesheet" href="bootstrap/bootstrap.min.css" />
<link rel="stylesheet" href="app.css" />
<link rel="stylesheet" href="MelonChart.WebApp.styles.css" />
<link rel="icon" type="image/png" href="favicon.png" />
<HeadOutlet @rendermode="new InteractiveServerRenderMode(prerender:false)" />
</head>

<body>
<Routes @rendermode="new InteractiveServerRenderMode(prerender:false)" />
<script src="_framework/blazor.web.js"></script>
</body>

</html>
19 changes: 19 additions & 0 deletions samples/MelonChart.WebApp/Components/Layout/MainLayout.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
@inherits LayoutComponentBase

<div class="page">
<div class="sidebar">
<NavMenu />
</div>

<main>
<article class="content px-4">
@Body
</article>
</main>
</div>

<div id="blazor-error-ui">
An unhandled error has occurred.
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
</div>
Loading