using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
public class LedgerEntry{
public LedgerEntry(DateTime date, string desc, decimal chg){
Date = date;
Desc = desc;
Chg = chg;
}
public DateTime Date { get; }
public string Desc { get; }
public decimal Chg { get; }
}
public static class Ledger{
public static LedgerEntry CreateEntry(string date, string desc, int chng) => new LedgerEntry(DateTime.Parse(date, CultureInfo.InvariantCulture), desc, chng / 100.0m);
private static CultureInfo CreateCulture(string cur, string loc){
string curSymb = null;
int curNeg = 0;
string datPat = null;
if (cur != "USD" && cur != "EUR") throw new ArgumentException("Invalid currency");
if (loc != "nl-NL" && loc != "en-US") throw new ArgumentException("Invalid currency");
if (cur == "USD") {
if (loc == "en-US"){
curSymb = "$";
datPat = "MM/dd/yyyy";
}
else{
curSymb = "$";
curNeg = 12;
datPat = "dd/MM/yyyy";
}
}
else {
if (loc == "en-US"){
curSymb = "€";
datPat = "MM/dd/yyyy";
}
else {
curSymb = "€";
curNeg = 12;
datPat = "dd/MM/yyyy";
}
}
var culture = new CultureInfo(loc, false);
culture.NumberFormat.CurrencySymbol = curSymb;
culture.NumberFormat.CurrencyNegativePattern = curNeg;
culture.DateTimeFormat.ShortDatePattern = datPat;
return culture;
}
private static string PrintHead(string loc){
if (loc == "en-US") return "Date | Description | Change ";
else{
if (loc == "nl-NL") return "Datum | Omschrijving | Verandering ";
else throw new ArgumentException("Invalid locale");
}
}
private static string Date(IFormatProvider culture, DateTime date) => date.ToString("d", culture);
private static string Description(string desc){
if (desc.Length > 25) return $"{desc.Substring(0, 22)}...";
return desc;
}
private static string Change(IFormatProvider culture, decimal cgh) => cgh < 0.0m ? cgh.ToString("C", culture) : $"{cgh.ToString("C", culture)} ";
private static string PrintEntry(IFormatProvider culture, LedgerEntry entry) => $"{Date(culture, entry.Date)} | {Description(entry.Desc), -25} | {Change(culture, entry.Chg), 13}";
private static IEnumerable<LedgerEntry> sort(LedgerEntry[] entries) {
var neg = entries.Where(e => e.Chg < 0).OrderBy(x => $"{x.Date} @ {x.Desc} @ {x.Chg}");
var post = entries.Where(e => e.Chg >= 0).OrderBy(x => $"{x.Date} @ {x.Desc} @ {x.Chg}");
return new List<LedgerEntry>(neg.Concat(post));
}
public static string Format(string currency, string locale, LedgerEntry[] entries){
var culture = CreateCulture(currency, locale);
return sort(entries).Select(length => PrintEntry(culture, length)).
Aggregate(PrintHead(locale),(a,c) => $"{a}\n{c}");
}
}