Projektdateien hinzufügen.

This commit is contained in:
Kevin Kandlbinder 2024-06-21 13:11:34 +02:00
parent 72ecb03642
commit 76fbb232a7
48 changed files with 3779 additions and 0 deletions

62
BusinessLogic/BaseData.cs Normal file
View file

@ -0,0 +1,62 @@

namespace WebEMSim
{
internal class BaseData
{
private static Team[] _teams = [
new Team("France", 2, "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c3/Flag_of_France.svg/320px-Flag_of_France.svg.png"),
new Team("Belgium", 3, "https://upload.wikimedia.org/wikipedia/commons/thumb/6/65/Flag_of_Belgium.svg/277px-Flag_of_Belgium.svg.png"),
new Team("England", 4, "https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Flag_of_England.svg/320px-Flag_of_England.svg.png"),
new Team("Portugal", 6, "https://upload.wikimedia.org/wikipedia/commons/thumb/5/5c/Flag_of_Portugal.svg/320px-Flag_of_Portugal.svg.png"),
new Team("Netherlands", 7, "https://upload.wikimedia.org/wikipedia/commons/thumb/2/20/Flag_of_the_Netherlands.svg/320px-Flag_of_the_Netherlands.svg.png"),
new Team("Spain", 8, "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9a/Flag_of_Spain.svg/320px-Flag_of_Spain.svg.png"),
new Team("Italy", 9, "https://upload.wikimedia.org/wikipedia/commons/thumb/0/03/Flag_of_Italy.svg/320px-Flag_of_Italy.svg.png"),
new Team("Croatia", 10, "https://upload.wikimedia.org/wikipedia/commons/thumb/1/1b/Flag_of_Croatia.svg/320px-Flag_of_Croatia.svg.png"),
new Team("Germany", 16, "https://upload.wikimedia.org/wikipedia/commons/thumb/b/ba/Flag_of_Germany.svg/320px-Flag_of_Germany.svg.png"),
new Team("Switzerland", 19, "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f3/Flag_of_Switzerland.svg/240px-Flag_of_Switzerland.svg.png"),
new Team("Denmark", 21, "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9c/Flag_of_Denmark.svg/318px-Flag_of_Denmark.svg.png"),
new Team("Ukraine", 22, "https://upload.wikimedia.org/wikipedia/commons/thumb/4/49/Flag_of_Ukraine.svg/320px-Flag_of_Ukraine.svg.png"),
new Team("Austria", 25, "https://upload.wikimedia.org/wikipedia/commons/thumb/4/41/Flag_of_Austria.svg/320px-Flag_of_Austria.svg.png"),
new Team("Hungary", 26, "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c1/Flag_of_Hungary.svg/320px-Flag_of_Hungary.svg.png"),
new Team("Poland", 28, "https://upload.wikimedia.org/wikipedia/commons/thumb/1/12/Flag_of_Poland.svg/320px-Flag_of_Poland.svg.png"),
new Team("Serbia", 33, "https://upload.wikimedia.org/wikipedia/commons/thumb/f/ff/Flag_of_Serbia.svg/320px-Flag_of_Serbia.svg.png"),
new Team("Czechia", 36, "https://upload.wikimedia.org/wikipedia/commons/thumb/c/cb/Flag_of_the_Czech_Republic.svg/320px-Flag_of_the_Czech_Republic.svg.png"),
new Team("Scotland", 39, "https://upload.wikimedia.org/wikipedia/commons/thumb/1/10/Flag_of_Scotland.svg/320px-Flag_of_Scotland.svg.png"),
new Team("Türkiye", 40, "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b4/Flag_of_Turkey.svg/320px-Flag_of_Turkey.svg.png"),
new Team("Romania", 46, "https://upload.wikimedia.org/wikipedia/commons/thumb/7/73/Flag_of_Romania.svg/320px-Flag_of_Romania.svg.png"),
new Team("Slovakia", 48, "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e6/Flag_of_Slovakia.svg/320px-Flag_of_Slovakia.svg.png"),
new Team("Slovenia", 57, "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f0/Flag_of_Slovenia.svg/320px-Flag_of_Slovenia.svg.png"),
new Team("Albania", 66, "https://upload.wikimedia.org/wikipedia/commons/thumb/3/36/Flag_of_Albania.svg/320px-Flag_of_Albania.svg.png"),
new Team("Georgia", 75, "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0f/Flag_of_Georgia.svg/320px-Flag_of_Georgia.svg.png"),
];
public static Team[] Teams { get => _teams.Select(team => new Team(team.Name, team.WorldRank, team.FlagUrl)).ToArray(); }
public static List<List<Team>> GetBuckets()
{
if (Teams.Length != 24)
{
throw new Exception("Invalid BaseData - Team count off.");
}
List<List<Team>> buckets = [];
int teamIterator = 0;
for (int bucketIdx = 0; bucketIdx < 4; bucketIdx++)
{
List<Team> bucket = [];
for (int bucketTeamIdx = 0; bucketTeamIdx < 6; bucketTeamIdx++)
{
bucket.Add(Teams[teamIterator]);
teamIterator++;
}
buckets.Add(bucket);
}
return buckets;
}
}
}

43
BusinessLogic/Group.cs Normal file
View file

@ -0,0 +1,43 @@

namespace WebEMSim
{
public class Group
{
private int _number;
private List<Team> _teams = [];
private Table _table;
public Group(int number)
{
_number = number;
_table = new Table(_teams);
}
public void AddTeam(Team team)
{
team.AssignGroup(_number);
_teams.Add(team);
_table.AddTeam(team);
}
public void PerformGroupPlayout()
{
List<Match> matches = Helpers.GenerateMatches(_teams);
foreach (Match match in matches)
{
match.Play();
}
}
public override string ToString()
{
return String.Format("Group {0} { {1} }", _number, _teams.ToArray().ToString());
}
public Table Table { get => _table; }
public char Letter { get => Helpers.NumberToLetter(_number); }
}
}

41
BusinessLogic/Helpers.cs Normal file
View file

@ -0,0 +1,41 @@

namespace WebEMSim
{
internal class Helpers
{
public static T GetRandomFromList<T>(List<T> list)
{
return list[Random.Shared.Next(list.Count)];
}
public static T GetRandomFromListAndRemove<T>(List<T> list)
{
T chosenOne = GetRandomFromList(list);
list.Remove(chosenOne);
return chosenOne;
}
public static List<Match> GenerateMatches(List<Team> teams)
{
List<Match> matches = [];
for (int teamAIdx = 0; teamAIdx < teams.Count - 1; teamAIdx++)
{
for (int teamBIdx = teamAIdx + 1; teamBIdx < teams.Count; teamBIdx++)
{
matches.Add(new Match(teams[teamAIdx], teams[teamBIdx]));
}
}
return matches.OrderBy(x => Random.Shared.Next()).ToList(); // why x ??
}
public static char NumberToLetter(int number)
{
return (char)(number+0x41);
}
}
}

101
BusinessLogic/Match.cs Normal file
View file

@ -0,0 +1,101 @@

namespace WebEMSim
{
public class Match
{
public enum MatchResult
{
TEAM_A_WIN = 0, TEAM_B_WIN = 1, DRAW = 2
}
private Team[] _teams = new Team[2];
private int[] _goals = new int[2];
private MatchResult _result;
public Match(Team team1, Team team2)
{
_teams[0] = team1;
_teams[1] = team2;
}
private void CommitStats()
{
for (int teamIdx = 0; teamIdx < _teams.Length; teamIdx++)
{
int goalsFor = _goals[teamIdx];
int goalsAgainst = _goals[1 - teamIdx];
int points = 0;
if(_result == (MatchResult)teamIdx) //vergleiche enum
{
points = 3;
}
if(_result == MatchResult.DRAW)
{
points = 1;
}
_teams[teamIdx].LogStats(points, goalsFor, goalsAgainst);
}
}
private void CalculateResult()
{
if (_goals[0] > _goals[1])
{
_result = MatchResult.TEAM_A_WIN;
return;
}
if (_goals[1] > _goals[0])
{
_result = MatchResult.TEAM_B_WIN;
return;
}
_result = MatchResult.DRAW;
}
public void Play()
{
for (int goalsIdx = 0; goalsIdx < _goals.Length; goalsIdx++)
{
_goals[goalsIdx] = Random.Shared.Next(6);
}
CalculateResult();
CommitStats();
}
private Team GetWinner()
{
if (_result == Match.MatchResult.TEAM_A_WIN)
{
return _teams[0];
}
if (_result == Match.MatchResult.TEAM_B_WIN)
{
return _teams[1];
}
Table drawResolver = new([_teams[0], _teams[1]]);
return drawResolver.GetTable()[0];
}
public MatchResult Result { get => _result; }
public Team Winner { get => GetWinner(); }
public Team TeamA { get => _teams[0]; }
public Team TeamB { get => _teams[1]; }
public int GoalsA { get => _goals[0]; }
public int GoalsB { get => _goals[1]; }
}
}

96
BusinessLogic/Table.cs Normal file
View file

@ -0,0 +1,96 @@

namespace WebEMSim
{
public class Table
{
private List<Team> _teams;
private Sorter _sorter = new Sorter();
public Dictionary<int, Team> Rankings { get => GetTable().Select((team, index) => new {team, index}).ToDictionary(x => x.index, x => x.team); }
public Table(List<Team> teams) {
_teams = new(teams);
}
public void AddTeam(Team team)
{
_teams.Add(team);
}
public List<Team> GetTable()
{
_teams.Sort(_sorter);
return _teams;
}
public List<Team> GetTruncatedTable(int cutoff)
{
List<Team> sortedTeams = new(GetTable());
sortedTeams.RemoveRange(cutoff, sortedTeams.Count - cutoff);
return sortedTeams;
}
/*public DataTable AsDataTable()
{
DataTable dataTable = new DataTable();
dataTable.Clear();
dataTable.Columns.Add("Name");
dataTable.Columns.Add("Wins");
dataTable.Columns.Add("Losses");
dataTable.Columns.Add("Draws");
dataTable.Columns.Add("For");
dataTable.Columns.Add("Against");
dataTable.Columns.Add("Goal Diff");
dataTable.Columns.Add("World Rank");
dataTable.Columns.Add("Points");
dataTable.Columns.Add("Group");
List<Team> teams = GetTable();
foreach (Team team in teams)
{
dataTable.Rows.Add([
team.Name,
team.Wins,
team.Losses,
team.Draws,
team.For,
team.Against,
team.GoalDelta,
team.WorldRank,
team.Points,
Helpers.NumberToLetter(team.Group)
]);
}
return dataTable;
}*/
private class Sorter : IComparer<Team>
{
public int Compare(Team? a, Team? b)
{
int rank = b.Points - a.Points;
if(rank == 0)
{
rank = b.GoalDelta - a.GoalDelta;
}
if(rank == 0)
{
rank = b.For - a.For;
}
return rank;
}
}
}
}

55
BusinessLogic/Team.cs Normal file
View file

@ -0,0 +1,55 @@

namespace WebEMSim
{
public class Team
{
private string _name;
private string _flagUrl;
private int _wins = 0;
private int _losses = 0;
private int _draws = 0;
private int _worldRank = 0;
private int _for = 0;
private int _against = 0;
private int _points = 0;
private int _group = -1;
public Team(string name, int worldRank, string flagUrl)
{
_name = name;
_worldRank = worldRank;
_flagUrl = flagUrl;
}
public void AssignGroup(int group)
{
_group = group;
}
public void LogStats(int points, int goalsFor, int goalsAgainst)
{
_points += points;
if (points == 3) { _wins += 1; }
if (points == 1) { _draws += 1; }
if (points == 0) { _losses += 1; }
_for += goalsFor;
_against += goalsAgainst;
}
public int For { get => _for; }
public int Points { get => _points; }
public int GoalDelta { get => _for - _against; }
public int Group { get => _group; }
public string Name { get => _name; }
public string FlagUrl { get => _flagUrl; }
public int Wins { get => _wins; }
public int Losses { get => _losses; }
public int Against { get => _against; }
public int Draws { get => _draws; }
public int WorldRank { get => _worldRank; }
}
}

222
BusinessLogic/Tournament.cs Normal file
View file

@ -0,0 +1,222 @@

namespace WebEMSim
{
public class Tournament
{
private readonly string _id;
private List<Group> _groups;
private Dictionary<string, Team> _ranks;
private Dictionary<string, Match> _matches;
private Table _overallTable = new([]);
private bool _hasPlayed = false;
public Tournament()
{
_id = System.Guid.NewGuid().ToString();
_ranks = new Dictionary<string, Team>();
_matches = new Dictionary<string, Match>();
_groups = [];
GenerateGroups();
}
public string ID { get => _id; }
public bool HasPlayed { get => _hasPlayed; }
public Dictionary<string, Match> Matches { get => _matches; }
private void GenerateGroups()
{
List<List<Team>> buckets = BaseData.GetBuckets();
for (int i = 0; i < 6; i++)
{
Group group = new(i);
foreach (var bucket in buckets)
{
Team chosenTeam = Helpers.GetRandomFromListAndRemove(bucket);
group.AddTeam(chosenTeam);
_overallTable.AddTeam(chosenTeam);
}
_groups.Add(group);
}
}
private string MakeRankString(char letter, int rank)
{
return String.Format("{0}{1}", rank, letter);
}
private void PerformGroupPhase(Table thirdPlaceTable)
{
foreach (var group in _groups)
{
group.PerformGroupPlayout();
List<Team> rankedTeams = group.Table.GetTable();
for (int rank = 0; rank < 2; rank++)
{
_ranks.Add(MakeRankString(group.Letter, rank + 1), rankedTeams[rank]);
}
thirdPlaceTable.AddTeam(rankedTeams[2]);
}
}
private void ChooseThirdPlaces(Table thirdPlaceTable)
{
List<Team> teams = thirdPlaceTable.GetTruncatedTable(4); // TODO: Check this
if (teams.Count != 4) throw new Exception("FUCK");
while(true)
{
teams = teams.OrderBy(x => Random.Shared.Next()).ToList();
int matchB = teams[0].Group;
int matchC = teams[1].Group;
int matchE = teams[2].Group;
int matchF = teams[3].Group;
if (!new List<int> { 0, 3, 4, 5 /* ADEF */ }.Contains(matchB))
{
continue;
}
if (!new List<int> { 3, 4, 5 /* DEF */ }.Contains(matchC))
{
continue;
}
if (!new List<int> { 0, 1, 2, 3 /* ABCD */ }.Contains(matchE))
{
continue;
}
if (!new List<int> { 0, 1, 2 /* ABC */ }.Contains(matchF))
{
continue;
}
break;
}
_ranks.Add("3ADEF", teams[0]);
_ranks.Add("3DEF", teams[1]);
_ranks.Add("3ABCD", teams[2]);
_ranks.Add("3ABC", teams[3]);
}
private Match DoMatch(string teamA, string teamB)
{
Team teamAObj = _ranks[teamA];
Team teamBObj = _ranks[teamB];
Match match = new(teamAObj, teamBObj);
match.Play();
return match;
}
public record PlayoutMatch(string teamA, string teamB, string result);
private void PlayoutGeneric(List<PlayoutMatch> playoutMatches)
{
foreach (var playoutMatch in playoutMatches)
{
Match match = DoMatch(playoutMatch.teamA, playoutMatch.teamB);
Team winner = match.Winner;
_ranks.Add(playoutMatch.result, winner);
_matches.Add(playoutMatch.result, match);
}
}
public List<PlayoutMatch> Playout16Matches = [
new PlayoutMatch("1B", "3ADEF", "W39"),
new PlayoutMatch("1A", "2C", "W37"),
new PlayoutMatch("1F", "3ABC", "W41"),
new PlayoutMatch("2D", "2E", "W42"),
new PlayoutMatch("1E", "3ABCD", "W43"),
new PlayoutMatch("1D", "2F", "W44"),
new PlayoutMatch("1C", "3DEF", "W40"),
new PlayoutMatch("2A", "2B", "W38"),
];
private void Playout16()
{
PlayoutGeneric(Playout16Matches);
}
public List<PlayoutMatch> Playout4Matches = [
new PlayoutMatch("W39", "W37", "W45"),
new PlayoutMatch("W41", "W42", "W46"),
new PlayoutMatch("W43", "W44", "W47"),
new PlayoutMatch("W40", "W38", "W48"),
];
private void Playout4()
{
PlayoutGeneric(Playout4Matches);
}
public List<PlayoutMatch> Playout2Matches = [
new PlayoutMatch("W45", "W46", "W49"),
new PlayoutMatch("W47", "W48", "W50"),
];
private void Playout2()
{
PlayoutGeneric(Playout2Matches);
}
public List<PlayoutMatch> PlayoutFinalMatches = [
new PlayoutMatch("W49", "W50", "WIN"),
];
private void PlayoutFinal()
{
PlayoutGeneric(PlayoutFinalMatches);
}
public Team GetTeamForRank(string rank)
{
return _ranks[rank];
}
public Match GetMatchForRank(string rank)
{
return _matches[rank];
}
public void PlayoutTournament()
{
Table thirdPlaceTable = new([]);
_hasPlayed = true;
PerformGroupPhase(thirdPlaceTable);
ChooseThirdPlaces(thirdPlaceTable);
Playout16();
Playout4();
Playout2();
PlayoutFinal();
}
public List<Group> Groups { get => _groups; }
public Table OverallTable { get => _overallTable; }
}
}