ex-int-02-meet-the-teacher/MeetTheTeacher/Program.cs
2025-04-26 11:56:00 +02:00

179 lines
5.6 KiB
C#

using System.Text;
using MeetTheTeacher.Export;
using MeetTheTeacher.Import;
using MeetTheTeacher.Model;
using Spectre.Console;
Console.OutputEncoding = Encoding.UTF8;
Clear();
AnsiConsole.Markup("[orange3]Press any key to load HTL-Leonding teacher data[/] ");
Console.ReadKey();
// data loading
bool loadRealData = AskForDataToUse();
// wrapping IEnumerable in List, because we will iterate multiple times
var data = new List<Teacher>(LoadData(loadRealData));
var tableGenerator = new SpectreTableExporter();
tableGenerator.Export(data, string.Empty);
// fake loading
Clear();
await DisplayFakeProgress();
Clear();
AnsiConsole.Write(tableGenerator.Table);
PrintStatistics(data);
// user input
WriteRule("Sort Order");
var order = AskForSortOrder();
WriteRule("Export Format");
var format = AskForExportFormat();
WriteRule("File Name");
string fileName = AnsiConsole.Ask<string>("Which [blue]file name[/] should be used?");
// export
var exporter = new Exporter(order, format, new DefaultExporterProvider());
exporter.Export(fileName, data);
// done
WriteRule(string.Empty);
AnsiConsole.Write(new FigletText("All Done!").Centered().Color(Color.Green));
DrawDog();
return;
static void Clear()
{
Console.Clear();
AnsiConsole.Write(new FigletText("Teacher Data").Centered().Color(Color.Blue));
}
static void WriteRule(string text)
{
AnsiConsole.Write(new Rule($"[blue]{text}[/]").LeftJustified());
}
static IEnumerable<Teacher> LoadData(bool realData)
{
string generalDataFilePath = "Data/teachers.csv";
string businessCardDataFilePath = "Data/teachers-with-business-card.csv";
if (!File.Exists(generalDataFilePath))
{
AnsiConsole.MarkupLine($"[red]Error:[/] File '{generalDataFilePath}' not found");
return [];
}
ITeacherDataImporter importer = realData
? new TeacherDataCsvImporter(generalDataFilePath, businessCardDataFilePath)
: new TeacherDataFakeImporter();
return importer.LoadTeacherData();
}
static Task DisplayFakeProgress()
{
const double Increase = 4.5;
const double ReducedIncrease = Increase * 0.8D;
return AnsiConsole.Progress()
.StartAsync(async ctx =>
{
// we are actually already done, but want to fake some complex operation
// to have the user appreciate the hard work our application is doing :)
var task1 = ctx.AddTask("[green]Loading Data[/]");
var task2 = ctx.AddTask("[green]Processing Data[/]");
while (!ctx.IsFinished)
{
task1.Increment(Increase);
task2.Increment(ReducedIncrease);
await Task.Delay(TimeSpan.FromMilliseconds(125));
}
});
}
static void PrintStatistics(IReadOnlyCollection<Teacher> teachers)
{
var hasConsultingHours = 0;
var hasBusinessCard = 0;
foreach (var teacher in teachers)
{
if (teacher.ConsultingHour != null)
{
hasConsultingHours++;
}
if (teacher is TeacherWithBusinessCard)
{
hasBusinessCard++;
}
}
double total = teachers.Count;
var cPercentage = (int) (hasConsultingHours / total * 100);
int ncPercentage = 100 - cPercentage;
var bPercentage = (int) (hasBusinessCard / total * 100);
AnsiConsole.Write(new BarChart()
.Width(60)
.Label($"[blue underline]Statistics ({total:F0} teachers)[/]")
.CenterLabel()
.AddItem("Has consulting hour", cPercentage, Color.Green)
.AddItem("Has no consulting hour", ncPercentage, Color.Red)
.AddItem("Has business card", bPercentage, Color.Purple));
}
static SortOrder AskForSortOrder()
{
var options = new Dictionary<string, SortOrder>
{
["Name Asc."] = SortOrder.ByNameAsc,
["Name Desc."] = SortOrder.ByNameDesc,
["Hour Asc."] = SortOrder.ByHourAsc,
["Hour Desc."] = SortOrder.ByHourDesc,
["Room"] = SortOrder.Room
};
string order = AnsiConsole.Prompt(new SelectionPrompt<string>()
.Title("How do you wish to [blue]sort[/] the data?")
.PageSize(3)
.MoreChoicesText("[grey](Move up and down to reveal more options)[/]")
.AddChoices(options.Keys));
AnsiConsole.MarkupLine($"Selected: [green]{order}[/]");
return options[order];
}
static ExportFormat AskForExportFormat()
{
const string Csv = "Csv";
const string Html = "Html";
string dataToUse = AnsiConsole.Prompt(new SelectionPrompt<string>()
.Title("Do you want to load [blue]real[/] or [blue]sample[/] data?")
.AddChoices(Csv, Html));
AnsiConsole.MarkupLine($"Selected: [green]{dataToUse}[/]");
return dataToUse == Csv ? ExportFormat.Csv : ExportFormat.Html;
}
static bool AskForDataToUse()
{
const string Real = "Real";
string dataToUse = AnsiConsole.Prompt(new SelectionPrompt<string>()
.Title("Do you want to load [blue]real[/] or [blue]sample[/] data?")
.AddChoices(Real, "Sample"));
AnsiConsole.MarkupLine($"Selected: [green]{dataToUse}[/]");
return dataToUse == Real;
}
static void DrawDog()
{
var image = new CanvasImage("happy-dog.png");
image.MaxWidth(36);
AnsiConsole.Write(image);
}