CupEntrants.cs

Partial of ClubCareer, the soccer career simulator. Draws the eight persistent club entrants for a cup from the club catalog based on division tiers and a seeded RNG, and preserves already-started or legacy cup fields. Also has small helpers to look up the cup for a fixture and its team names/crests.

Rough Code
using System;
using System.Collections.Generic;
using System.Linq;

namespace Socer;

public sealed partial class ClubCareer
{
    // Fixture team numbers are local to a competition. Each cup owns its eight
    // persistent club identities instead of borrowing the current league slots.
    void DrawCupEntrants(CupTournament cup)
    {
        EnsureClubWorld();
        var selected=new List<int>{0};
        int regional=Division<=2?Division:Math.Max(1,Division-1);
        int stronger=Math.Min(5,Division+1);
        int[] tiers=cup.Id==FinalCupId?Enumerable.Repeat(5,7).ToArray():
            cup.Id=="county"?new[]{regional,regional,regional,regional,regional,Division,Division}:
            cup.Id=="league"?new[]{Division,Division,Division,Division,stronger,stronger,stronger}:
            new[]{Math.Max(1,Division-1),Division,Division,Division,stronger,stronger,stronger};
        var otherCupClubs=(Tournaments??new()).Where(t=>t!=cup).SelectMany(t=>t.ClubIds??Array.Empty<int>()).ToHashSet();
        var rng=new Random(unchecked((int)PlayerCatalog.Hash($"cup-clubs-{ClubSeed}-{Season}-{cup.Id}")));
        for(int index=0;index<tiers.Length;index++)
        {
            var candidates=ClubCatalog.All.Where(c=>c.Id!=0 && ClubDivision(c.Id)==tiers[index] && !selected.Contains(c.Id))
                .OrderBy(c=>otherCupClubs.Contains(c.Id)?1:0)
                .ThenBy(c=>LeagueClubIds.Contains(c.Id)?1:0)
                .ThenBy(c=>rng.Next());
            selected.Add(candidates.First().Id);
        }
        cup.ClubIds=selected.ToArray();cup.EntrantsRevision=1;cup.StrengthOffset=0;
        foreach(int id in selected.Skip(1))SquadForClub(id);
    }

    public void EnsureCupEntrants(CupTournament cup)
    {
        if(cup.ClubIds is {Length:8} && cup.ClubIds.Distinct().Count()==8 && cup.ClubIds.All(id=>id>=0 && id<ClubCatalog.All.Length))return;
        // Preserve the identity of an already drawn/played legacy cup and its
        // result; only unopened tournaments receive the new independent pool.
        if(cup.Started || cup.Finished || cup.Games.Any(f=>f.Played) || Pending?.Cup==true && Pending.CupId==cup.Id)
        {
            cup.ClubIds=(legacyLeagueClubs??LeagueClubIds).ToArray();cup.EntrantsRevision=1;cup.StrengthOffset=0;
        }
        else DrawCupEntrants(cup);
    }

    public CupTournament TournamentFor(ClubFixture fixture)=>Tournaments.FirstOrDefault(t=>t.Games.Contains(fixture));
    public string FixtureTeamName(ClubFixture fixture,int slot)=>TeamName(slot,TournamentFor(fixture));
    public string FixtureTeamCrest(ClubFixture fixture,int slot)=>TeamCrest(slot,TournamentFor(fixture));
}