/// <summary> /// This method runs for the life of the program, slowly evolving the level set. /// </summary> private static void Maintain() { int lastRatingsCount = 0; while (!IsClosing) { Thread.Sleep(1000); using (var levelsContext = new LevelsContext()) { int ratingsCount = levelsContext.Ratings.Count(); if (ratingsCount < lastRatingsCount) lastRatingsCount = ratingsCount; if (ratingsCount - lastRatingsCount > 10) { const int descendants = 3; var parents = levelsContext.Levels.OrderByDescending(level => levelsContext.GetAverageRatingForLevel(level)).Take(2 * descendants).ToList(); for (int i = 0; i < descendants * 2; i += 2) { Level l1 = parents[i].Level.Mutate(MUTATION_RATE); Level l2 = parents[i + 1].Level.Mutate(MUTATION_RATE); Level newLevel = l1.Crossover(l2, CROSSOVER_RATE); levelsContext.Levels.Add(newLevel); } } lastRatingsCount = ratingsCount; levelsContext.SaveChanges(); } } }
/// <summary> /// Called when a request is received from a client. This method must be thread-safe /// </summary> /// <param name="id">The unique identifier of the client</param> /// <param name="request">A string containing the request received</param> /// <returns>A string response, or "" if nothing must be sent</returns> static string OnClientRequest(int id, string request) { string[] requestParts = request.Split(' '); switch (requestParts[0]) { case "level": using (var levelsContext = new LevelsContext()) { int lid = int.Parse(requestParts[1]); Level l = levelsContext.GetLevelByID(lid); return l.Encode(); } case "random": using (var levelsContext = new LevelsContext()) { //TODO: give the client a random level. The solution is nontrivial return ""; } case "rate": using (var levelsContext = new LevelsContext()) { int lid = int.Parse(requestParts[1]); int rating = int.Parse(requestParts[2]); levelsContext.AddRating(lid, rating); levelsContext.SaveChanges(); } return "done"; default: return ""; } }
public static void Initialize() { Database.SetInitializer<LevelsContext>(new DropCreateDatabaseAlways<LevelsContext>()); using (var levelsContext = new LevelsContext()) { int count = levelsContext.Levels.Count(); if (count < MIN_LEVELS) { for (int i = count; i < MIN_LEVELS; i++) levelsContext.Levels.Add(GenerateRandomLevel()); } else if (count > MAX_LEVELS) { int toRemove = MAX_LEVELS - count; var levelsToRemove = levelsContext.Levels.OrderBy(level => levelsContext.GetAverageRatingForLevel(level)).Take(toRemove); levelsContext.Levels.RemoveRange(levelsToRemove); } levelsContext.SaveChanges(); } MaintainThread = new Thread(Maintain); MaintainThread.Start(); }
static void Main(string[] args) { MaintainLevels.Initialize(); Console.WriteLine("Database up and maintenance daemon running"); ServerSocket = new ServerSocket("any", SERVER_PORT, "\n", OnClientStateChange, OnClientRequest); Console.WriteLine("Server listening on port {0}", SERVER_PORT); using (var levelscontext = new LevelsContext()) { levelscontext.Levels.Add(new LevelEntity()); levelscontext.SaveChanges(); } for (; ; ) { Console.Write("> "); string message = Console.ReadLine(); switch (message) { case "exit": Exit(); return; case "echo": Console.WriteLine("Hello"); break; } } }