static void Main()
        {
            var random = new Random();

            var skiers           = new List <Skier>();
            var sexes            = new List <Sex>();
            var countries        = new List <Country>();
            var races            = new List <Race>();
            var venues           = new List <Venue>();
            var raceTypes        = new List <RaceType>();
            var startLists       = new List <StartList>();
            var startPositions   = new List <StartPosition>();
            var raceStates       = new List <RaceState>();
            var seasons          = new List <Season>();
            var seasonPlans      = new List <SeasonPlan>();
            var raceDataList     = new List <RaceData>();
            var timeMeasurements = new List <TimeMeasurement>();

            var skiersJson = JObject.Parse(File.ReadAllText("Resources/data.json")).Children().Children().Children();
            var racesJson  = JObject.Parse(File.ReadAllText("Resources/races.json")).Children().Children().Children();

            var raceDescriptionArr = new string[]
            {
                "Sondre Norheim was the champion of the first downhill skiing competition, reportedly held " +
                "in Oslo, Norway in 1868. Two to three decades later, the sport spread to the rest of " +
                "Europe and the U.S. The first slalom ski competition occurred in Mürren, Switzerland in 1922.",
                "Norwegian legend Sondre Norheim first began the trend of skis with curved sides, bindings " +
                "with stiff heel bands made of willow, and the slalom turn style.",
                "Skiing was an integral part of transportation in colder countries for thousands of years. " +
                "In the late 19th century skiing converted from a method of transportation to a competitive " +
                "and recreational sport.",
                "The Norwegian army held skill competitions involving skiing down slopes, around trees and obstacles " +
                "while shooting. The birth of modern alpine skiing is often dated to the 1850s.",
                "The ancient origins of skiing can be traced back to prehistoric times in Russia, Finland, Sweden " +
                "and Norway where varying sizes and shapes of wooden planks were preserved in peat bogs. " +
                "Skis were first invented to cross wetlands and marshes in the winter when they froze over."
            };

            raceStates.Add(new RaceState()
            {
                Id    = raceStates.Count,
                Label = "Abgeschlossen"
            });
            raceStates.Add(new RaceState()
            {
                Id    = raceStates.Count,
                Label = "Disqualifiziert"
            });
            raceStates.Add(new RaceState()
            {
                Id    = raceStates.Count,
                Label = "NichtAbgeschlossen"
            });
            raceStates.Add(new RaceState()
            {
                Id    = raceStates.Count,
                Label = "Laufend"
            });
            raceStates.Add(new RaceState()
            {
                Id    = raceStates.Count,
                Label = "Startbereit"
            });

            sexes.Add(new Sex()
            {
                Id    = 0,
                Label = "Weiblich"
            });
            sexes.Add(new Sex()
            {
                Id    = 1,
                Label = "Männlich"
            });

            foreach (var currentSkier in skiersJson)
            {
                var currentCountryLabel = currentSkier.Value <string>("country");
                if (!countries.Any(c => c.Name == currentCountryLabel))
                {
                    countries.Add(new Country()
                    {
                        Id   = countries.Count,
                        Name = currentCountryLabel
                    });
                }
            }

            foreach (var currentRace in racesJson)
            {
                var currentPlace        = currentRace.Value <JObject>("place");
                var currentCountryLabel = currentPlace.Value <string>("country");

                var currentVenueLabel = currentPlace.Value <string>("place");
                if (!venues.Any(v => v.Name == currentVenueLabel))
                {
                    venues.Add(new Venue()
                    {
                        Id        = venues.Count,
                        CountryId = countries.FirstOrDefault(c => c.Name == currentCountryLabel).Id,
                        Name      = currentVenueLabel
                    });
                }

                var currentRaceType = currentRace.Value <string>("discipline");

                //localize english to german
                if (currentRaceType == "Giant Slalom")
                {
                    currentRaceType = "Riesentorlauf";
                }

                bool raceTypeIsNeeded = currentRaceType == "Slalom" || currentRaceType == "Riesentorlauf";

                if (currentRaceType != null && raceTypeIsNeeded)
                {
                    foreach (var genderSpecificRace in sexes)
                    {
                        int nextRaceId = races.Count;

                        if (!raceTypes.Any(rt => rt.Label == currentRaceType))
                        {
                            raceTypes.Add(new RaceType()
                            {
                                Id    = raceTypes.Count,
                                Label = currentRaceType
                            });
                        }

                        int firstStartListId = startLists.Count;
                        startLists.Add(new StartList()
                        {
                            Id = firstStartListId
                        });

                        races.Add(new Race()
                        {
                            Id                   = nextRaceId,
                            Date                 = DateTime.Parse(currentRace.Value <string>("date")).AddYears(2),
                            Description          = raceDescriptionArr[random.Next(0, raceDescriptionArr.Length)],
                            NumberOfSensors      = random.Next(4, 7),
                            FirstStartListId     = firstStartListId,
                            SecondStartListId    = 0,
                            RaceTypeId           = raceTypes.FirstOrDefault(rt => rt.Label == currentRaceType).Id,
                            VenueId              = venues.FirstOrDefault(v => v.Name == currentVenueLabel).Id,
                            GenderSpecificRaceId = genderSpecificRace.Id
                        });
                    }
                }
            }

            foreach (var currentSkier in skiersJson)
            {
                var currentSexLabel = currentSkier.Value <string>("gender");

                //localize english to german
                if (currentSexLabel == "Female")
                {
                    currentSexLabel = "Weiblich";
                }
                else if (currentSexLabel == "Male")
                {
                    currentSexLabel = "Männlich";
                }

                var currentCountryLabel = currentSkier.Value <string>("country");

                var dobString = currentSkier.Value <string>("birthDate");
                if (!dobString.Contains('-'))
                {
                    dobString = "01-01-" + dobString;
                }

                skiers.Add(new Skier()
                {
                    Id          = skiers.Count,
                    FirstName   = currentSkier.Value <string>("firstName"),
                    LastName    = currentSkier.Value <string>("lastName"),
                    DateOfBirth = DateTime.Parse(dobString),
                    ImageUrl    = currentSkier.Value <string>("avatarUrl"),
                    SexId       = sexes.FirstOrDefault(sex => sex.Label == currentSexLabel).Id,
                    CountryId   = countries.FirstOrDefault(c => c.Name == currentCountryLabel).Id
                });
            }

            int startPositionId = 0;

            foreach (var currentRace in races)
            {
                int positionCounter         = 1;
                int participatingSkierCount = random.Next(11) + 45;

                var setOfPossibleSkiers = skiers.Where(s => s.SexId == currentRace.GenderSpecificRaceId);
                foreach (var participatingSkier in setOfPossibleSkiers.OrderBy(s => random.Next()).Take(participatingSkierCount))
                {
                    startPositions.Add(new StartPosition()
                    {
                        Id          = startPositionId++,
                        StartListId = currentRace.FirstStartListId,
                        SkierId     = participatingSkier.Id,
                        Position    = positionCounter++
                    });
                }
            }

            races.Select(r => r.Date.Year)
            .Distinct()
            .ToList()
            .ForEach(y => seasons.Add(new Season()
            {
                Id        = seasons.Count,
                Name      = $"Jährliche Saison {y}",
                StartDate = new DateTime(y, 1, 1),
                EndDate   = new DateTime(y, 12, 31)
            }));

            int seasonPlanIdCounter = 0;

            foreach (var currentSeason in seasons)
            {
                foreach (var currentVenue in venues)
                {
                    seasonPlans.Add(new SeasonPlan()
                    {
                        Id       = seasonPlanIdCounter++,
                        SeasonId = currentSeason.Id,
                        VenueId  = currentVenue.Id
                    });
                }
            }

            foreach (var currentStartPosition in startPositions)
            {
                SimulateTimeMeasurement(random, races, raceStates, raceDataList, timeMeasurements, currentStartPosition);
            }

            //generate second startlist out of performance of first one
            var newlyCreatedStartPositions = new List <StartPosition>();
            var newStartLists   = new List <StartList>();
            var nextStartListId = startLists.Max(sl => sl.Id) + 1;

            foreach (var currentStartList in startLists)
            {
                var relevantTimeMeasurements = timeMeasurements
                                               .Where(tm => raceDataList
                                                      .Where(rd => rd.StartListId == currentStartList.Id)
                                                      .Any(rd => rd.Id == tm.RaceDataId))
                                               .ToList();

                var reverseRankedSkiers = startPositions
                                          .Where(sp => sp.StartListId == currentStartList.Id)
                                          .Select(sp => skiers.First(s => s.Id == sp.SkierId))
                                          .OrderByDescending(
                    s => relevantTimeMeasurements
                    .Where(
                        tm => tm.RaceDataId == raceDataList.First(rd => rd.SkierId == s.Id &&
                                                                  rd.StartListId == currentStartList.Id)
                        .Id)
                    .Max(tm => tm.Measurement))
                                          .ToList();

                newStartLists.Add(new StartList {
                    Id = nextStartListId
                });

                var currentRace = races.First(r => r.FirstStartListId == currentStartList.Id);
                currentRace.SecondStartListId = nextStartListId;

                Console.WriteLine(newStartLists.Count);

                int startPosition = 1;
                foreach (var skier in reverseRankedSkiers)
                {
                    var newStartPosition = new StartPosition()
                    {
                        Id          = startPositions.Max(sp => sp.Id) + 1,
                        Position    = startPosition++,
                        SkierId     = skier.Id,
                        StartListId = nextStartListId
                    };

                    startPositions.Add(newStartPosition);
                    newlyCreatedStartPositions.Add(newStartPosition);
                }

                nextStartListId++;
            }
            startLists.AddRange(newStartLists);

            //create time measurements for second run
            foreach (var newlyCreatedStartPosition in newlyCreatedStartPositions)
            {
                SimulateTimeMeasurement(random, races, raceStates, raceDataList, timeMeasurements, newlyCreatedStartPosition);
            }

            AddToInsertScript(startLists);
            AddToInsertScript(raceTypes);
            AddToInsertScript(sexes);
            AddToInsertScript(countries);
            AddToInsertScript(skiers);
            AddToInsertScript(startPositions);
            AddToInsertScript(seasons);
            AddToInsertScript(venues);
            AddToInsertScript(seasonPlans);
            AddToInsertScript(races);
            AddToInsertScript(raceStates);
            AddToInsertScript(raceDataList);
            AddToInsertScript(timeMeasurements);

            using (var streamWriter = new StreamWriter(insertScriptPath))
            {
                foreach (var line in insertScript)
                {
                    streamWriter.WriteLine(line);
                }
            }
        }