Skip to content
Open
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@
node_modules
bower_components
npm-debug.log

.fake
20 changes: 0 additions & 20 deletions jobs/Backend/Task/Currency.cs

This file was deleted.

23 changes: 0 additions & 23 deletions jobs/Backend/Task/ExchangeRate.cs

This file was deleted.

19 changes: 0 additions & 19 deletions jobs/Backend/Task/ExchangeRateProvider.cs

This file was deleted.

8 changes: 0 additions & 8 deletions jobs/Backend/Task/ExchangeRateUpdater.csproj

This file was deleted.

22 changes: 0 additions & 22 deletions jobs/Backend/Task/ExchangeRateUpdater.sln

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
namespace ExchangeRateUpdater.Common
{
/// <summary>
/// Provides static utility methods for parsing text-based data.
/// </summary>
public static class TextParsingUtils
{
/// <summary>
/// Analyzes a sample of data lines to automatically detect the most likely column delimiter.
/// </summary>
/// <param name="lines">The collection of all lines from the source file.</param>
/// <returns>The detected delimiter character, or ',' as a default fallback.</returns>
public static char DetectDelimiter(IEnumerable<string> lines)
{
var potentialDelimiters = new[] { '|', ',', ';', '\t' };
var sampleLines = lines.Where(l => !string.IsNullOrWhiteSpace(l)).Take(10).ToList();

if (sampleLines.Count < 2)
{
return ',';
}

var delimiterInfo = potentialDelimiters
.Select(d => new
{
Delimiter = d,
MostCommonGroup = sampleLines.GroupBy(l => l.Count(c => c == d))
.Where(g => g.Key > 0)
.OrderByDescending(g => g.Count())
.ThenByDescending(g => g.Key)
.Select(g => new { DelimiterCount = g.Key, LineCount = g.Count() })
.FirstOrDefault()
})
.Where(info => info.MostCommonGroup != null && info.MostCommonGroup.LineCount > 1)
.OrderByDescending(info => info.MostCommonGroup?.LineCount)
.ThenByDescending(info => info.MostCommonGroup?.DelimiterCount)
.FirstOrDefault();

return delimiterInfo?.Delimiter ?? ',';
}

/// <summary>
/// Finds the zero-based index of the header row in the data file.
/// </summary>
/// <param name="lines">The collection of all lines from the source file.</param>
/// <param name="delimiter">The delimiter character to look for in the header.</param>
/// <returns>The index of the header row, or -1 if not found.</returns>
public static int FindHeaderRowIndex(IReadOnlyList<string> lines, char delimiter)
{
for (int i = 0; i < lines.Count; i++)
{
if (lines[i].Contains(delimiter))
{
return i;
}
}
return -1;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace ExchangeRateUpdater.Core.Interfaces
{
/// <summary>
/// Interface for a client that interacts with the Czech National Bank API to fetch exchange rates.
/// </summary>
public interface ICnbApiClient
{
/// <summary>
/// Asynchronously retrieves the latest exchange rates from the Czech National Bank API.
/// </summary>
/// <returns>A task that represents the asynchronous operation, containing the latest exchange rates.</returns>
Task<string> GetLatestExchangeRatesAsync();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using ExchangeRateUpdater.Core.Models;
namespace ExchangeRateUpdater.Core.Interfaces
{
/// <summary>
/// Interface for a repository that retrieves exchange rates from the Czech National Bank (CNB) API.
/// </summary>
public interface ICnbExchangeRateRepository
{
/// <summary>
/// Asynchronously retrieves the latest exchange rates.
/// </summary>
/// <returns>A collection of <see cref="ExchangeRate"/> objects representing the latest exchange rates.</returns>
Task<IEnumerable<ExchangeRate>> GetExchangeRatesAsync();

/// <summary>
/// Asynchronously retrieves specific exchange rates for the given currencies.
/// </summary>
/// <param name="currencies"></param>
/// <returns></returns>
Task<IEnumerable<ExchangeRate>> GetSpecificExchangeRatesAsync(IEnumerable<Currency> currencies);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using ExchangeRateUpdater.Core.Models;

namespace ExchangeRateUpdater.Core.Interfaces
{
/// <summary>
/// Provides functionality to retrieve exchange rates for specified currencies.
/// </summary>
public interface IExchangeRateProvider
{
/// <summary>
/// Gets exchange rates for the specified currencies.
/// </summary>
/// <param name="currencies">Collection of currencies to get exchange rates for.</param>
/// <returns>Collection of exchange rates for the specified currencies.</returns>
Task<IEnumerable<ExchangeRate>> GetExchangeRatesAsync(IEnumerable<Currency> currencies);
}
}
77 changes: 77 additions & 0 deletions jobs/Backend/Task/ExchangeRateUpdater/src/Core/Models/Currency.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
namespace ExchangeRateUpdater.Core.Models
{
/// <summary>
/// Represents a currency.
/// </summary>
public class Currency
{
/// <summary>
/// Initializes a new instance of the <see cref="Currency"/> class.
/// </summary>
/// <param name="code">The three-letter ISO 4217 code of the currency.</param>
/// <exception cref="ArgumentException"></exception>
public Currency(string code)
{
if (string.IsNullOrWhiteSpace(code))
{
throw new ArgumentException("Currency code cannot be null or empty.", nameof(code));
}
Code = code.ToUpperInvariant();
}

/// <summary>
/// Three-letter ISO 4217 code of the currency.
/// </summary>
public string Code { get; }

/// <summary>
/// Overrides the ToString method to return the currency code.
/// </summary>
/// <returns>The currency code.</returns>
public override string ToString()
{
return Code;
}

/// <summary>
/// Determines whether the specified object is equal to the current currency.
/// </summary>
/// <param name="obj">The object to compare with the current currency.</param>
/// <returns>true if the specified object is equal to the current currency; otherwise, false.</returns>
public override bool Equals(object? obj)
{
return obj is Currency currency && Code == currency.Code;
}

/// <summary>
/// Generates a hash code for the current currency.
/// </summary>
/// <returns>A hash code for the current currency.</returns>
public override int GetHashCode()
{
return HashCode.Combine(Code);
}

/// <summary>
/// Overloaded equality operator to compare two Currency objects.
/// </summary>
/// <param name="left">The first Currency object to compare.</param>
/// <param name="right">The second Currency object to compare.</param>
/// <returns>true if both Currency objects are equal; otherwise, false.</returns>
public static bool operator ==(Currency? left, Currency? right)
{
return EqualityComparer<Currency>.Default.Equals(left, right);
}

/// <summary>
/// Overloaded inequality operator to compare two Currency objects.
/// </summary>
/// <param name="left">The first Currency object to compare.</param>
/// <param name="right">The second Currency object to compare.</param>
/// <returns>true if both Currency objects are not equal; otherwise, false.</returns>
public static bool operator !=(Currency? left, Currency? right)
{
return !(left == right);
}
}
}
Loading