PageRenderTime 5ms CodeModel.GetById 3ms app.highlight 43ms RepoModel.GetById 1ms app.codeStats 1ms

/Fixer/Program.cs

https://github.com/db81/Zero-K-Infrastructure
C# | 1040 lines | 812 code | 135 blank | 93 comment | 201 complexity | 919cc23b603f5005fab8d3d32f85a0a5 MD5 | raw file
   1using System;
   2using System.Collections.Generic;
   3using System.Data.Entity;
   4using System.Data.Linq;
   5using System.Drawing;
   6using System.Drawing.Drawing2D;
   7using System.Drawing.Imaging;
   8using System.Globalization;
   9using System.IO;
  10using System.Linq;
  11using System.Net;
  12using System.Net.NetworkInformation;
  13using System.Net.Sockets;
  14using System.Text;
  15using System.Text.RegularExpressions;
  16using System.Threading;
  17using System.Threading.Tasks;
  18using System.Xml.Serialization;
  19//using LobbyClient;
  20//using NightWatch;
  21using CaTracker;
  22using LobbyClient;
  23using Microsoft.Linq.Translations;
  24using PlasmaShared;
  25using ZkData.UnitSyncLib;
  26using ZeroKWeb;
  27using ZkData;
  28using Encoder = System.Drawing.Imaging.Encoder;
  29
  30namespace Fixer
  31{
  32    public static class Program
  33    {
  34        const int MaxBanHours = 24 * 36525;   // 100 years
  35
  36        public static string GenerateMACAddress()
  37        {
  38            var sBuilder = new StringBuilder();
  39            var r = new Random();
  40            int number;
  41            byte b;
  42            for (int i = 0; i < 6; i++)
  43            {
  44                number = r.Next(0, 255);
  45                b = Convert.ToByte(number);
  46                if (i == 0)
  47                {
  48                    b = setBit(b, 6); //--> set locally administered
  49                    b = unsetBit(b, 7); // --> set unicast 
  50                }
  51                sBuilder.Append(number.ToString("X2"));
  52            }
  53            return sBuilder.ToString().ToUpper();
  54        }
  55
  56        private static byte setBit(byte b, int BitNumber)
  57        {
  58            if (BitNumber < 8 && BitNumber > -1)
  59            {
  60                return (byte)(b | (byte)(0x01 << BitNumber));
  61            }
  62            else
  63            {
  64                throw new InvalidOperationException(
  65                "Der Wert für BitNumber " + BitNumber.ToString() + " war nicht im zulässigen Bereich! (BitNumber = (min)0 - (max)7)");
  66            }
  67        }
  68
  69        private static byte unsetBit(byte b, int BitNumber)
  70        {
  71            if (BitNumber < 8 && BitNumber > -1)
  72            {
  73                return (byte)(b | (byte)(0x00 << BitNumber));
  74            }
  75            else
  76            {
  77                throw new InvalidOperationException(
  78                "Der Wert für BitNumber " + BitNumber.ToString() + " war nicht im zulässigen Bereich! (BitNumber = (min)0 - (max)7)");
  79            }
  80        }
  81
  82        static byte[] GetBytes(string str)
  83        {
  84            byte[] bytes = new byte[str.Length * sizeof(char)];
  85            System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
  86            return bytes;
  87        }
  88
  89        public static void TestCRC()
  90        {
  91            for (int i = 0; i < 8192; i++)
  92            {
  93                string mac = GenerateMACAddress() + "lobby.springrts.com";
  94                byte[] mac2 = Encoding.ASCII.GetBytes(mac);
  95                uint hash1 = LobbyClient.Crc.Crc32(mac2);
  96                uint hash2 = LobbyClient.Crc.Crc32Old(mac2);
  97                if (hash1 != hash2)
  98                {
  99                    Console.WriteLine("MISMATCH: {0} vs. {1} (MAC {2})", hash1, hash2, mac);
 100                }
 101            }
 102        }
 103
 104        public static void GetNICs()
 105        {
 106            var nics = NetworkInterface.GetAllNetworkInterfaces();
 107            foreach (NetworkInterface nic in nics)
 108            {
 109                System.Console.WriteLine("{0} | type {1}", nic.GetPhysicalAddress(), nic.NetworkInterfaceType);
 110            }
 111        }
 112
 113        public static void FixDuplicatedAccounts()
 114        {
 115            GlobalConst.Mode = ModeType.Test;
 116            var db = new ZkDataContext();
 117            var duplicates = db.Accounts.GroupBy(x => x.Name).Where(x => x.Count() > 1).ToList();
 118            foreach (var duplicateGroup in duplicates)
 119            {
 120                var keep = duplicateGroup.OrderByDescending(x => x.SpringBattlePlayers.Count()).ThenByDescending(x => x.LastLogin).First();
 121                foreach (var todel in duplicateGroup.ToList())
 122                    if (keep.AccountID != todel.AccountID)
 123                    {
 124                        try
 125                        {
 126                            db.ForumThreadLastReads.DeleteAllOnSubmit(todel.ForumThreadLastReads.ToList());
 127                            db.AccountBattleAwards.DeleteAllOnSubmit(todel.AccountBattleAwards.ToList());
 128                            db.Accounts.DeleteOnSubmit(todel);
 129                            db.SubmitChanges();
 130                            Console.WriteLine("Deleted {0}", todel.Name);
 131                        }
 132                        catch (Exception ex)
 133                        {
 134                            using (var db2 = new ZkDataContext())
 135                            {
 136                                var acc = db2.Accounts.Find(todel.AccountID);
 137                                acc.IsDeleted = true;
 138                                acc.Name = string.Format("___DELETED___{0}", todel.AccountID); // hacky way to avoid duplicates
 139                                db2.SubmitChanges();
 140                            }
 141                            Console.WriteLine("Failed to delete {0}", todel.Name);
 142                        }
 143                    }
 144            }
 145        }
 146
 147        public enum OptionType
 148        {
 149            Undefined = 0,
 150            Bool = 1,
 151            List = 2,
 152            Number = 3,
 153            String = 4,
 154            Section = 5
 155        }
 156        public static OptionType Type { get; set; }
 157
 158        public static bool GetPair(string Value, out string result)
 159        {
 160            result = "";
 161            Type = OptionType.Number;
 162            switch (Type)
 163            {
 164                case OptionType.Bool:
 165                    if (Value != "0" && Value != "1") return false;
 166                    return true;
 167
 168                case OptionType.Number:
 169                    double d;
 170                    if (!double.TryParse(Value, out d)) return false;
 171                    return true;
 172
 173                case OptionType.String:
 174                    return true;
 175            }
 176
 177            return false;
 178        }
 179
 180        public static void FixStuff()
 181        {
 182            //UpdateMissionProgression(13);
 183            /*
 184            var db = new ZkDataContext();
 185            int accountID = 5806;
 186            List<CampaignJournal> unlockedJournals = new List<CampaignJournal>();
 187            CampaignPlanet planet = db.CampaignPlanets.First(x => x.PlanetID == 13);
 188            int campID = planet.CampaignID;
 189            db.CampaignEvents.InsertOnSubmit(Global.CreateCampaignEvent(accountID, campID, "Planet completed: {0}", planet));
 190            //foreach (CampaignJournal journal in db.CampaignJournals.Where(x => x.CampaignID == campID && x.PlanetID == planet.PlanetID && x.UnlockOnPlanetCompletion))
 191            //{
 192            //    unlockedJournals.Add(journal);
 193            //}
 194            //foreach (CampaignJournal uj in unlockedJournals)
 195            //{
 196            //    db.CampaignEvents.InsertOnSubmit(Global.CreateCampaignEvent(accountID, campID, "{1} - Journal entry unlocked: {0}", uj, uj.CampaignPlanet));
 197            //}
 198            db.SubmitChanges();
 199            */
 200        }
 201
 202        public static void AddClanLeader()
 203        {
 204            var db = new ZkDataContext();
 205            var role = db.RoleTypes.First(x => x.IsClanOnly);
 206            foreach (var clan in db.Clans.Where(x => !x.IsDeleted))
 207            {
 208                if (!clan.AccountRoles.Any(y => y.RoleType.IsClanOnly))
 209                {
 210                    var picked = clan.Accounts.Where(x => x.LastLogin >= DateTime.UtcNow.AddDays(-7)).OrderByDescending(x => x.Level).FirstOrDefault();
 211                    if (picked == null) clan.Accounts.OrderByDescending(x => x.LastLogin).FirstOrDefault();
 212                    if (picked != null)
 213                    {
 214                        clan.AccountRoles.Add(new AccountRole()
 215                        {
 216                            AccountID = picked.AccountID,
 217                            ClanID = clan.ClanID,
 218                            Inauguration = DateTime.UtcNow,
 219                            RoleTypeID = role.RoleTypeID
 220                        });
 221                    }
 222                }
 223            }
 224            db.SubmitAndMergeChanges();
 225        }
 226
 227
 228        public static void GetGameStats(DateTime from)
 229        {
 230            //GlobalConst.Mode = ModeType.Live;
 231            var db = new ZkDataContext();
 232            var bats = db.SpringBattles.Where(x => x.StartTime >= from && x.Duration >= 60*5).ToList();
 233            Console.WriteLine("Battles from {0}", from);
 234            var total = bats.Count;
 235            Console.WriteLine("Total: {0}",total);
 236            var breakdown = bats.GroupBy(x => x.PlayerCount).OrderBy(x => x.Key).Select(x => new {
 237                Size = x.Key,
 238                Count = x.Count()
 239            }).ToList();
 240
 241            foreach (var b in breakdown) {
 242                Console.WriteLine("Size: {0}    Battles: {1}",b.Size,b.Count);    
 243            }
 244            
 245
 246            
 247        }
 248
 249
 250
 251        [STAThread]
 252        static void Main(string[] args)
 253        {
 254            //GetGameStats(new DateTime(2014,12,1));
 255            //var ns = new NubSimulator();
 256            //ns.SpawnMany();
 257            //Console.ReadLine();
 258
 259            //MigrateDatabase();
 260            //FixDuplicatedAccounts();
 261            //BcryptPasswords();
 262            //var db = new ZkDataContext(true);
 263            //var test = db.Accounts.OrderByDescending(x => x.EffectiveElo).WithTranslations().Take(5).ToList();
 264
 265
 266            //MigrateDatabase();
 267            //var test = GlobalConst.GetContentService().DownloadFile("Zero-K v1.1.0");
 268            //var db = new ZkDataContext();
 269            //var post = db.ForumPosts.First(x => x.ForumPostID == 113893);
 270
 271
 272            //var db = new ZkDataContext(false);
 273            //db.Database.CreateIfNotExists();
 274
 275            //PlanetwarsFixer.StartGalaxy(24,3919,3925);
 276            //AddClanLeader();
 277            //return;
 278            //TestPwMatch();
 279            FixStuff();
 280
 281            //var guid = Guid.NewGuid().ToString();
 282
 283            //var pp = new PayPalInterface();
 284            //pp.ImportPaypalHistory(Directory.GetCurrentDirectory());
 285
 286            //Test1v1Elo();
 287            //GenerateTechs();
 288
 289            //FixDemoEngineVersion();
 290
 291            //ImportSpringiePlayers();
 292            //RecalculateBattleElo();
 293            //FixMaps();
 294
 295            //PickHomworldOwners();
 296
 297            //PlanetwarsFixer.PurgeGalaxy(24, false, true);
 298            //PlanetwarsFixer.RandomizeMaps(24);
 299            //SetPlanetTeamSizes();
 300
 301            //RandomizePlanetOwners(24);
 302            //GenerateStructures(24);
 303            //PlanetwarsFixer.GenerateArtefacts(24, new int[] { 3940, 3949, 3954, 3929, 3956 });
 304
 305            //SwapPlanetOwners(3948, 3955);
 306            //SwapPlanetOwners(3973, 3932);
 307            //PlanetwarsFixer.AddWormholes();
 308            //PlanetwarsFixer.RemoveTechStructures(true, true);
 309            //StartGalaxy(24);
 310
 311            //TestPrediction();
 312            //FixMissionScripts();
 313
 314            //AnalyzeModuleUsagePatterns();
 315            //AnalyzeCommUsagePatterns();
 316
 317            //UpdateMissionProgression(12);
 318            //PrintNightwatchSubscriptions("zkadmin");
 319
 320            //RecountForumVotes();
 321            //GetForumKarmaLadder();
 322            //GetForumKarmaVotes();
 323            //GetForumVotesByVoter(161294, 5340);
 324            //DeleteUserVotes(189201, null);  //neon    
 325            //GetClanStackWinRate(465, 2000); //Mean
 326            //GetForumVotesByUserVoterAgnostic(161294);
 327            //GetAverageElo();
 328        }
 329
 330        static void CountPlayers()
 331        {
 332            var db = new ZkDataContext();
 333            var accs =
 334                db.SpringBattles.OrderByDescending(x => x.SpringBattleID)
 335                    .Take(5000)
 336                    .SelectMany(x => x.SpringBattlePlayers)
 337                    .Where(x => !x.IsSpectator)
 338                    .Select(x => new { x.Account, x.SpringBattle.Duration })
 339                    .GroupBy(x => x.Account)
 340                    .Select(x => new { Account = x.Key, Duration = x.Sum(y => y.Duration) })
 341                    .ToList();
 342
 343            var durOther = accs.Where(x => x.Account.LobbyVersion != null && !x.Account.LobbyVersion.StartsWith("ZK")).Sum(x => (long)x.Duration);
 344            var durZk = accs.Where(x => x.Account.LobbyVersion != null && x.Account.LobbyVersion.StartsWith("ZK")).Sum(x => (long)x.Duration);
 345
 346            var cntOther = accs.Where(x => x.Account.LobbyVersion != null && !x.Account.LobbyVersion.StartsWith("ZK")).Count();
 347            var cntZk = accs.Where(x => x.Account.LobbyVersion != null && x.Account.LobbyVersion.StartsWith("ZK")).Count();
 348        }
 349
 350        static void MigrateDatabase()
 351        {
 352            var cloner = new DbCloner("zero-k_ef", "zero-k_test",
 353                "Data Source=omega.licho.eu,100;Initial Catalog=zero-k_test;Persist Security Info=True;User ID=zero-k;Password=zkdevpass1;MultipleActiveResultSets=true");
 354            cloner.CloneAllTables();
 355        }
 356
 357        static void SetPlanetTeamSizes()
 358        {
 359            var db = new ZkDataContext();
 360            var gal = db.Galaxies.First(x => x.IsDefault);
 361            var planets = gal.Planets.ToList().OrderBy(x => x.Resource.MapDiagonal).ToList();
 362            var cnt = planets.Count;
 363            int num = 0;
 364            foreach (var p in planets)
 365            {
 366                //if (num < cnt*0.15) p.TeamSize = 1;else 
 367                if (num < cnt * 0.80) p.TeamSize = 2;
 368                //else if (num < cnt*0.85) p.TeamSize = 3;
 369                else p.TeamSize = 3;
 370                num++;
 371            }
 372            db.SubmitAndMergeChanges();
 373        }
 374
 375        public static void RecalculateKudos()
 376        {
 377            var db = new ZkDataContext();
 378            foreach (var acc in db.Accounts.Where(x => x.KudosPurchases.Any() || x.ContributionsByAccountID.Any())) acc.Kudos = acc.KudosGained - acc.KudosSpent;
 379            db.SubmitAndMergeChanges();
 380        }
 381
 382
 383        public static void CountUserIDs()
 384        {
 385            var db = new ZkDataContext();
 386            var userIDs = db.AccountUserIDs.ToList();
 387            var uniqueIDs = userIDs.Select(x => x.UserID).Distinct().ToList();
 388            Dictionary<long, int> userIDCounts = new Dictionary<long, int>();
 389            System.Console.WriteLine("{0} userIDs, {1} uniques", userIDs.Count, uniqueIDs.Count);
 390            foreach (long userID in uniqueIDs)
 391            {
 392                int count = userIDs.Count(x => x.UserID == userID);
 393                userIDCounts[userID] = count;
 394            }
 395            var sortedIDs = uniqueIDs.OrderByDescending(x => userIDCounts[x]).Take(20).ToList();
 396            foreach (int userID in sortedIDs)
 397            {
 398                System.Console.WriteLine("{0}: {1}", userID, userIDCounts[userID]);
 399            }
 400        }
 401
 402        public static void SetFFATeams()
 403        {
 404            var db = new ZkDataContext();
 405            foreach (var m in db.Resources.Where(x => x.FeaturedOrder != null && x.TypeID == ResourceType.Map))
 406            {
 407                var lg = m.SpringBattlesByMapResourceID.Take(100).ToList();
 408                double cnt = lg.Count;
 409                if (cnt == 0) continue;
 410                ;
 411                if (lg.Count(x => x.HasBots) / (double)cnt > 0.5)
 412                {
 413                    m.MapIsChickens = true;
 414                }
 415
 416                if (lg.Count(x => x.PlayerCount == 2) / cnt > 0.4)
 417                {
 418                    m.MapIs1v1 = true;
 419                }
 420
 421                var teams =
 422                    m.SpringBattlesByMapResourceID.Take(100).GroupBy(
 423                        x => x.SpringBattlePlayers.Where(y => !y.IsSpectator).Select(y => y.AllyNumber).Distinct().Count()).OrderByDescending(
 424                            x => x.Count()).Select(x => x.Key).FirstOrDefault();
 425                if (teams > 2)
 426                {
 427                    m.MapIsFfa = true;
 428                    m.MapFFAMaxTeams = teams;
 429                }
 430                else { }
 431
 432
 433
 434            }
 435            db.SubmitChanges();
 436
 437        }
 438
 439
 440
 441        public static void FixMissionScripts()
 442        {
 443            var db = new ZkDataContext();
 444            var missions = db.Missions.ToList();
 445            foreach (Mission mission in missions)
 446            {
 447                mission.Script = Regex.Replace(mission.Script, "GameType=([^;]+);", (m) => { return string.Format("GameType={0};", mission.NameWithVersion); });
 448            }
 449            db.SubmitChanges();
 450        }
 451
 452        static void GetModuleUsage(int moduleID, List<Commander> comms, ZkDataContext db)
 453        {
 454            var modules = db.CommanderModules.Where(x => comms.Contains(x.Commander) && x.ModuleUnlockID == moduleID).ToList();
 455            int numModules = 0;
 456            Unlock wantedModule = db.Unlocks.FirstOrDefault(x => x.UnlockID == moduleID);
 457            int moduleCost = (int)wantedModule.MetalCost;
 458            numModules = modules.Count;
 459
 460            System.Console.WriteLine("MODULE: " + wantedModule.Name);
 461            System.Console.WriteLine("Instances: " + numModules);
 462            System.Console.WriteLine("Total cost: " + numModules * moduleCost);
 463            System.Console.WriteLine();
 464        }
 465
 466        public static void AnalyzeModuleUsagePatterns()
 467        {
 468            var db = new ZkDataContext();
 469            var modules = db.Unlocks.Where(x => x.UnlockType == UnlockTypes.Weapon).ToList();
 470
 471            var players = db.Accounts.Where(x => x.Elo >= 1700 && DateTime.Compare(x.LastLogin.AddMonths(3), DateTime.UtcNow) > 0).ToList();
 472            System.Console.WriteLine("Number of accounts to process: " + players.Count);
 473            var comms = db.Commanders.Where(x => players.Contains(x.AccountByAccountID)).ToList();
 474            System.Console.WriteLine("Number of comms to process: " + comms.Count);
 475            System.Console.WriteLine();
 476
 477
 478            foreach (Unlock module in modules)
 479            {
 480                GetModuleUsage(module.UnlockID, comms, db);
 481            }
 482        }
 483
 484        public static void AnalyzeCommUsagePatterns()
 485        {
 486            var db = new ZkDataContext();
 487            var chasses = db.Unlocks.Where(x => x.UnlockType == UnlockTypes.Chassis).ToList();
 488
 489            var players = db.Accounts.Where(x => x.Elo >= 1700 && DateTime.Compare(x.LastLogin.AddMonths(3), DateTime.UtcNow) > 0).ToList();
 490            System.Console.WriteLine("Number of accounts to process: " + players.Count);
 491            System.Console.WriteLine();
 492
 493            foreach (Unlock chassis in chasses)
 494            {
 495                var comms = db.Commanders.Where(x => players.Contains(x.AccountByAccountID) && x.ChassisUnlockID == chassis.UnlockID).ToList();
 496                int chassisCount = comms.Count;
 497                System.Console.WriteLine("CHASSIS " + chassis.Name + " : " + chassisCount);
 498            }
 499        }
 500
 501        public static void ProgressCampaign(ZkDataContext db, Account acc, Mission mission, bool completeNext = false, string missionVars = "")
 502        {
 503            CampaignPlanet planet = db.CampaignPlanets.FirstOrDefault(p => p.MissionID == mission.MissionID);
 504            if (planet != null)
 505            {
 506                AccountCampaignProgress progress = acc.AccountCampaignProgress.FirstOrDefault(x => x.PlanetID == planet.PlanetID && x.CampaignID == planet.CampaignID);
 507                bool alreadyCompleted = false;
 508                int accountID = acc.AccountID;
 509                int campID = planet.CampaignID;
 510                Campaign camp = planet.Campaign;
 511                List<CampaignPlanet> unlockedPlanets = new List<CampaignPlanet>();
 512                List<CampaignJournal> unlockedJournals = new List<CampaignJournal>();
 513
 514                // start with processing the mission vars, if there are any
 515                byte[] missionVarsAsByteArray = System.Convert.FromBase64String(missionVars);
 516                string missionVarsDecoded = System.Text.Encoding.UTF8.GetString(missionVarsAsByteArray);
 517                foreach (string kvpRaw in missionVarsDecoded.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
 518                {
 519                    string kvpRaw2 = kvpRaw.Trim();
 520                    string key = "", value = "";
 521                    string[] kvpSplit = kvpRaw2.Split(new[] { '=' }, StringSplitOptions.RemoveEmptyEntries);
 522                    if (kvpSplit.Length == 2)
 523                    {
 524                        key = kvpSplit[0].Trim();
 525                        value = kvpSplit[1].Trim();
 526                    }
 527                    else
 528                    {
 529                        throw new Exception("Invalid key-value pair in decoded mission vars: " + missionVarsDecoded);
 530                    }
 531                    if (!(string.IsNullOrEmpty(key) || string.IsNullOrEmpty(value)))
 532                    {
 533                        CampaignVar cv = camp.CampaignVars.First(x => x.KeyString == key);
 534                        AccountCampaignVar acv = acc.AccountCampaignVars.FirstOrDefault(x => x.CampaignID == campID && x.VarID == cv.VarID);
 535                        if (acv == null)
 536                        {
 537                            db.AccountCampaignVars.InsertOnSubmit(new AccountCampaignVar() { AccountID = accountID, CampaignID = campID, VarID = cv.VarID, Value = value });
 538                        }
 539                        else acv.Value = value;
 540                    }
 541                }
 542
 543                //reload DB - this allows the vars submitted this session to be used by the following code
 544                db.SubmitChanges();
 545                db = new ZkDataContext();
 546                acc = db.Accounts.First(x => x.AccountID == accountID);
 547
 548                // now we unlock planets and journal entries
 549                // first mark this planet as completed - but only if it's already unlocked
 550                if (progress != null)
 551                {
 552                    alreadyCompleted = progress.IsCompleted;
 553                }
 554                else if (planet.StartsUnlocked)
 555                {
 556                    progress = new AccountCampaignProgress() { AccountID = accountID, CampaignID = campID, PlanetID = planet.PlanetID, IsCompleted = false, IsUnlocked = true };
 557                    db.AccountCampaignProgress.InsertOnSubmit(progress);
 558                }
 559
 560                if (progress != null && planet.IsUnlocked(accountID))
 561                {
 562                    progress.IsCompleted = true;
 563
 564
 565                    // unlock planets made available by completing this one
 566                    var links = camp.CampaignLinks.Where(x => x.UnlockingPlanetID == planet.PlanetID);
 567                    foreach (CampaignLink link in links)
 568                    {
 569                        CampaignPlanet toUnlock = link.PlanetToUnlock;
 570                        bool proceed = true;
 571                        var requiredVars = toUnlock.CampaignPlanetVars;
 572                        if (requiredVars.Count() == 0) proceed = true;
 573                        else
 574                        {
 575                            foreach (CampaignPlanetVar variable in requiredVars)
 576                            {
 577                                AccountCampaignVar accountVar = acc.AccountCampaignVars.FirstOrDefault(x => x.CampaignID == campID && x.VarID == variable.RequiredVarID);
 578                                if (!(accountVar != null && accountVar.Value == variable.RequiredValue))
 579                                {
 580                                    proceed = false;
 581                                    break;  // failed to meet var requirement, stop here
 582                                }
 583                            }
 584                        }
 585
 586                        if (proceed)    // met requirements for unlocking planet
 587                        {
 588                            AccountCampaignProgress progress2 = toUnlock.AccountCampaignProgress.FirstOrDefault(x => x.CampaignID == campID && x.AccountID == accountID);
 589                            if (progress2 == null)
 590                            {
 591                                progress2 = new AccountCampaignProgress() { AccountID = accountID, CampaignID = campID, PlanetID = toUnlock.PlanetID, IsCompleted = completeNext, IsUnlocked = true };
 592                                db.AccountCampaignProgress.InsertOnSubmit(progress2);
 593                                unlockedPlanets.Add(toUnlock);
 594                            }
 595                            else if (!progress2.IsUnlocked)
 596                            {
 597                                progress2.IsUnlocked = true;
 598                                unlockedPlanets.Add(toUnlock);
 599                            }
 600                        }
 601                    }
 602                }
 603                // unlock journals
 604                var journalsWithVars = db.CampaignJournals.Where(x => x.CampaignID == campID && x.CampaignJournalVars.Any());
 605                foreach (CampaignJournal journal in journalsWithVars)
 606                {
 607                    bool proceed = true;
 608                    var requiredVars = journal.CampaignJournalVars.Where(x => x.CampaignID == campID).ToList();
 609                    foreach (CampaignJournalVar variable in requiredVars)
 610                    {
 611                        AccountCampaignVar accountVar = acc.AccountCampaignVars.FirstOrDefault(x => x.CampaignID == campID && x.VarID == variable.RequiredVarID);
 612                        if (!(accountVar != null && accountVar.Value == variable.RequiredValue))
 613                        {
 614                            proceed = false;
 615                            break;  // failed to meet var requirement, stop here
 616                        }
 617                    }
 618
 619                    if (proceed)    // met requirements for unlocking journal
 620                    {
 621                        AccountCampaignJournalProgress jp = journal.AccountCampaignJournalProgress.FirstOrDefault(x => x.AccountID == accountID);
 622                        if (jp == null)
 623                        {
 624                            jp = new AccountCampaignJournalProgress() { AccountID = accountID, CampaignID = campID, JournalID = journal.JournalID, IsUnlocked = true };
 625                            db.AccountCampaignJournalProgress.InsertOnSubmit(jp);
 626                            unlockedJournals.Add(journal);
 627                        }
 628                        else if (!jp.IsUnlocked)
 629                        {
 630                            jp.IsUnlocked = true;
 631                            unlockedJournals.Add(journal);
 632                        }
 633                    }
 634                }
 635
 636                if (!alreadyCompleted)
 637                {
 638                    System.Console.WriteLine("Planet completed: {0}", planet);
 639                    foreach (CampaignJournal journal in db.CampaignJournals.Where(x => x.CampaignID == campID && x.CampaignPlanet.PlanetID == planet.PlanetID && x.UnlockOnPlanetCompletion))
 640                    {
 641                        unlockedJournals.Add(journal);
 642                    }
 643                }
 644                foreach (CampaignPlanet unlocked in unlockedPlanets)
 645                {
 646                    System.Console.WriteLine("Planet unlocked: {0}", unlocked);
 647                    foreach (CampaignJournal journal in db.CampaignJournals.Where(x => x.CampaignID == campID && x.CampaignPlanet.PlanetID == unlocked.PlanetID && x.UnlockOnPlanetUnlock))
 648                    {
 649                        unlockedJournals.Add(journal);
 650                    }
 651                }
 652                foreach (CampaignJournal uj in unlockedJournals)
 653                {
 654                    System.Console.WriteLine("{1} - Journal entry unlocked: {0}", uj, uj.CampaignPlanet);
 655                }
 656                db.SubmitChanges();
 657            }
 658        }
 659
 660        public static void UpdateMissionProgression(int planetID, bool completeNext = false, string missionVars = "")
 661        {
 662            ZkDataContext db = new ZkDataContext();
 663            var accp = db.AccountCampaignProgress.Where(x => x.PlanetID == planetID && x.IsCompleted).ToList();
 664            foreach (var prog in accp)
 665            {
 666                Account acc = prog.Account;
 667                System.Console.WriteLine(acc);
 668                ProgressCampaign(db, acc, prog.CampaignPlanet.Mission, completeNext, missionVars);
 669            }
 670        }
 671
 672        public static void PrintNightwatchSubscriptions(string channel)
 673        {
 674            ZkDataContext db = new ZkDataContext();
 675            var subscriptions = db.LobbyChannelSubscriptions.Where(x => x.Channel == channel);
 676            foreach (var entry in subscriptions)
 677            {
 678                Account acc = entry.Account;
 679                System.Console.WriteLine(acc);
 680            }
 681        }
 682
 683        public static void GetClanStackWinRate(int clanID, int minElo)
 684        {
 685            int won = 0, lost = 0;
 686            ZkDataContext db = new ZkDataContext();
 687            Clan clan = db.Clans.FirstOrDefault(x => x.ClanID == clanID);
 688            var battles = db.SpringBattles.Where(x => x.SpringBattlePlayers.Count(p => p.Account.ClanID == clanID && p.Account.Elo >= minElo && !p.IsSpectator) >= 2
 689                && x.StartTime.CompareTo(DateTime.Now.AddMonths(-1)) > 0 && x.ResourceByMapResourceID.MapIsSpecial != true && !x.IsFfa).ToList();
 690            System.Console.WriteLine(clan.ClanName + ", " + battles.Count);
 691            foreach (SpringBattle battle in battles)
 692            {
 693                int onWinners = 0, onLosers = 0;
 694                var players = battle.SpringBattlePlayers.Where(p => p.Account.ClanID == clanID && p.Account.Elo >= minElo && !p.IsSpectator).ToList();
 695                foreach (SpringBattlePlayer player in players)
 696                {
 697                    if (player.IsInVictoryTeam) onWinners++;
 698                    else onLosers++;
 699                }
 700                if (onWinners > onLosers)
 701                {
 702                    won++;
 703                    System.Console.WriteLine("won " + battle.SpringBattleID);
 704                }
 705                else if (onLosers > onWinners)
 706                {
 707                    lost++;
 708                    System.Console.WriteLine("lost " + battle.SpringBattleID);
 709                }
 710                //else System.Console.WriteLine("OMG, B" + battle.SpringBattleID);
 711            }
 712            System.Console.WriteLine(won + ", " + lost);
 713        }
 714
 715        public static void GetAverageElo()
 716        {
 717            int count = 0;
 718            double eloSum = 0;
 719            ZkDataContext db = new ZkDataContext();
 720            foreach (Account acc in db.Accounts.Where(x => x.SpringBattlePlayers.Any(g => g.SpringBattle.StartTime > DateTime.UtcNow.AddMonths(-1)) && x.EloWeight == GlobalConst.EloWeightMax))
 721            {
 722                System.Console.WriteLine(String.Format("{0}: {1}", acc.Name, acc.EffectiveElo));
 723                eloSum += acc.EffectiveElo;
 724                count++;
 725            }
 726            double average = eloSum / count;
 727            System.Console.WriteLine(String.Format("Average: {0}, Total players: {1}", average, count));
 728        }
 729
 730        static void FixDemoEngineVersion()
 731        {
 732            var db = new ZkDataContext();
 733            foreach (var b in db.SpringBattles.Where(x => x.Title.Contains("[engine")))
 734            {
 735                var match = Regex.Match(b.Title, @"\[engine([^\]]+)\]");
 736                if (match.Success)
 737                {
 738                    var eng = match.Groups[1].Value;
 739                    if (eng != b.EngineVersion) b.EngineVersion = eng;
 740                }
 741            }
 742            db.SubmitChanges();
 743        }
 744
 745        public class EloEntry
 746        {
 747            public double Elo = 1500;
 748            public int Cnt = 0;
 749
 750        }
 751
 752        public static void Test1v1Elo()
 753        {
 754            var db = new ZkDataContext();
 755            Dictionary<Account, EloEntry> PlayerElo = new Dictionary<Account, EloEntry>();
 756
 757            int cnt = 0;
 758            foreach (var sb in db.SpringBattles.Where(x => !x.IsMission && !x.HasBots && !x.IsFfa && x.PlayerCount == 2).OrderBy(x => x.SpringBattleID))
 759            {
 760                cnt++;
 761
 762                double winnerElo = 0;
 763                double loserElo = 0;
 764
 765                var losers = sb.SpringBattlePlayers.Where(x => !x.IsSpectator && !x.IsInVictoryTeam).Select(x => new { Player = x, x.Account }).ToList();
 766                var winners = sb.SpringBattlePlayers.Where(x => !x.IsSpectator && x.IsInVictoryTeam).Select(x => new { Player = x, x.Account }).ToList();
 767
 768                if (losers.Count != 1 || winners.Count != 1)
 769                {
 770                    continue;
 771                }
 772
 773                foreach (var r in winners)
 774                {
 775                    EloEntry el;
 776                    if (!PlayerElo.TryGetValue(r.Account, out el)) el = new EloEntry();
 777                    winnerElo += el.Elo;
 778                }
 779                foreach (var r in losers)
 780                {
 781                    EloEntry el;
 782                    if (!PlayerElo.TryGetValue(r.Account, out el)) el = new EloEntry();
 783                    loserElo += el.Elo;
 784                }
 785
 786                winnerElo = winnerElo / winners.Count;
 787                loserElo = loserElo / losers.Count;
 788
 789                var eWin = 1 / (1 + Math.Pow(10, (loserElo - winnerElo) / 400));
 790                var eLose = 1 / (1 + Math.Pow(10, (winnerElo - loserElo) / 400));
 791
 792                var sumCount = losers.Count + winners.Count;
 793                var scoreWin = Math.Sqrt(sumCount / 2.0) * 32 * (1 - eWin);
 794                var scoreLose = Math.Sqrt(sumCount / 2.0) * 32 * (0 - eLose);
 795
 796                foreach (var r in winners)
 797                {
 798                    var change = (float)(scoreWin);
 799                    EloEntry elo;
 800                    if (!PlayerElo.TryGetValue(r.Account, out elo))
 801                    {
 802                        elo = new EloEntry();
 803                        PlayerElo[r.Account] = elo;
 804                    }
 805                    elo.Elo += change;
 806                    elo.Cnt++;
 807                }
 808
 809                foreach (var r in losers)
 810                {
 811                    var change = (float)(scoreLose);
 812                    EloEntry elo;
 813                    if (!PlayerElo.TryGetValue(r.Account, out elo))
 814                    {
 815                        elo = new EloEntry();
 816                        PlayerElo[r.Account] = elo;
 817                    }
 818                    elo.Elo += change;
 819                    elo.Cnt++;
 820                }
 821            }
 822
 823
 824            Console.WriteLine("Total battles: {0}", cnt);
 825            Console.WriteLine("Name;1v1Elo;TeamElo;1v1Played;TeamPlayed");
 826            foreach (var entry in PlayerElo.Where(x => x.Value.Cnt > 40).OrderByDescending(x => x.Value.Elo))
 827            {
 828                Console.WriteLine("{0};{1:f0};{2:f0};{3};{4}", entry.Key.Name, entry.Value.Elo, entry.Key.EffectiveElo, entry.Value.Cnt, entry.Key.SpringBattlePlayers.Count(x => !x.IsSpectator && x.SpringBattle.PlayerCount > 2));
 829            }
 830
 831        }
 832
 833        public static void TestPrediction()
 834        {
 835            var db = new ZkDataContext();
 836            var cnt = 0;
 837            var winPro = 0;
 838            var winLessNub = 0;
 839            var winMoreVaried = 0;
 840            var winPredicted = 0;
 841
 842
 843            foreach (var sb in db.SpringBattles.Where(x => !x.IsMission && !x.HasBots && !x.IsFfa && x.IsEloProcessed && x.PlayerCount >= 8 && !x.Events.Any()).OrderByDescending(x => x.SpringBattleID))
 844            {
 845
 846                var losers = sb.SpringBattlePlayers.Where(x => !x.IsSpectator && !x.IsInVictoryTeam).Select(x => new { Player = x, x.Account }).ToList();
 847                var winners = sb.SpringBattlePlayers.Where(x => !x.IsSpectator && x.IsInVictoryTeam).Select(x => new { Player = x, x.Account }).ToList();
 848
 849                if (losers.Count == 0 || winners.Count == 0 || losers.Count == winners.Count) continue;
 850
 851                if (winners.Select(x => x.Account.EffectiveElo).Max() > losers.Select(x => x.Account.EffectiveElo).Max()) winPro++;
 852                if (winners.Select(x => x.Account.EffectiveElo).Min() > losers.Select(x => x.Account.EffectiveElo).Min()) winLessNub++;
 853
 854                if (winners.Select(x => x.Account.EffectiveElo).StdDev() > losers.Select(x => x.Account.EffectiveElo).StdDev()) winMoreVaried++;
 855
 856                var winnerElo = winners.Select(x => x.Account.EffectiveElo).Average();
 857                var loserElo = losers.Select(x => x.Account.EffectiveElo).Average();
 858
 859                var eWin = 1 / (1 + Math.Pow(10, (loserElo - winnerElo) / 400));
 860                var eLose = 1 / (1 + Math.Pow(10, (winnerElo - loserElo) / 400));
 861
 862                if (eWin > eLose) winPredicted++;
 863
 864
 865                cnt++;
 866                if (cnt == 200) break;
 867            }
 868
 869            Console.WriteLine("prwin: {0},  lessnubwin: {1},  morevaried: {2},  count: {3}, predicted:{4}", winPro, winLessNub, winMoreVaried, cnt, winPredicted);
 870        }
 871
 872        static void RecalculateBattleElo()
 873        {
 874            using (var db = new ZkDataContext())
 875            {
 876                foreach (var b in db.SpringBattles.Where(x => !x.IsEloProcessed).ToList())
 877                {
 878                    Console.WriteLine(b.SpringBattleID);
 879                    b.CalculateAllElo();
 880                }
 881                db.SubmitChanges();
 882            }
 883        }
 884
 885        static void ImportSpringiePlayers()
 886        {
 887            var db = new ZkDataContext();
 888            foreach (var line in File.ReadLines("springie.csv").AsParallel())
 889            {
 890                var m = Regex.Match(line, "\"[0-9]+\";\"([^\"]+)\";\"[0-9]+\";\"[0-9]+\";\"([^\"]+)\";\"([^\"]+)\"");
 891                if (m.Success)
 892                {
 893                    string name = m.Groups[1].Value;
 894                    double elo = double.Parse(m.Groups[2].Value, CultureInfo.InvariantCulture);
 895                    double w = double.Parse(m.Groups[3].Value, CultureInfo.InvariantCulture);
 896                    if (elo != 1500 || w != 1)
 897                    {
 898                        foreach (var a in db.Accounts.Where(x => x.Name == name))
 899                        {
 900                            a.Elo = (float)elo;
 901                            a.EloWeight = (float)w;
 902                        }
 903                        Console.WriteLine(name);
 904                    }
 905                }
 906            }
 907            db.SubmitChanges();
 908        }
 909
 910        static void FixMaps()
 911        {
 912            try
 913            {
 914                var db = new ZkDataContext();
 915                foreach (var r in db.Resources.Where(x => x.LastChange == null)) r.LastChange = DateTime.UtcNow;
 916                db.SubmitChanges();
 917                return;
 918
 919                foreach (var resource in db.Resources.Where(x => x.TypeID == ResourceType.Map))//&&x.MapSizeSquared == null))
 920                {
 921                    var file = String.Format("{0}/{1}.metadata.xml.gz", GlobalConst.SiteDiskPath + @"\Resources", resource.InternalName.EscapePath());
 922                    var map = (Map)new XmlSerializer(typeof(Map)).Deserialize(new MemoryStream(File.ReadAllBytes(file).Decompress()));
 923
 924                    resource.MapWidth = map.Size.Width / 512;
 925                    resource.MapHeight = map.Size.Height / 512;
 926
 927                    if (string.IsNullOrEmpty(resource.AuthorName))
 928                    {
 929
 930                        if (!string.IsNullOrEmpty(map.Author)) resource.AuthorName = map.Author;
 931                        else
 932                        {
 933                            Console.WriteLine("regex test");
 934                            var m = Regex.Match(map.Description, "by ([\\w]+)", RegexOptions.IgnoreCase);
 935                            if (m.Success) resource.AuthorName = m.Groups[1].Value;
 936                        }
 937                    }
 938                    Console.WriteLine("author: " + resource.AuthorName);
 939
 940
 941                    if (resource.MapIsSpecial == null) resource.MapIsSpecial = map.ExtractorRadius > 120 || map.MaxWind > 40;
 942                    resource.MapSizeSquared = (map.Size.Width / 512) * (map.Size.Height / 512);
 943                    resource.MapSizeRatio = (float)map.Size.Width / map.Size.Height;
 944
 945                    var minimap = String.Format("{0}/{1}.minimap.jpg", GlobalConst.SiteDiskPath + @"\Resources", resource.InternalName.EscapePath());
 946
 947                    using (var im = Image.FromFile(minimap))
 948                    {
 949                        int w, h;
 950
 951                        if (resource.MapSizeRatio > 1)
 952                        {
 953                            w = 96;
 954                            h = (int)(w / resource.MapSizeRatio);
 955                        }
 956                        else
 957                        {
 958                            h = 96;
 959                            w = (int)(h * resource.MapSizeRatio);
 960                        }
 961
 962                        using (var correctMinimap = new Bitmap(w, h, PixelFormat.Format24bppRgb))
 963                        {
 964                            using (var graphics = Graphics.FromImage(correctMinimap))
 965                            {
 966                                graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
 967                                graphics.DrawImage(im, 0, 0, w, h);
 968                            }
 969
 970                            var jgpEncoder = ImageCodecInfo.GetImageEncoders().First(x => x.FormatID == ImageFormat.Jpeg.Guid);
 971                            var encoderParams = new EncoderParameters(1);
 972                            encoderParams.Param[0] = new EncoderParameter(Encoder.Quality, 100L);
 973
 974                            var target = String.Format("{0}/{1}.thumbnail.jpg", GlobalConst.SiteDiskPath + @"\Resources", resource.InternalName.EscapePath());
 975                            correctMinimap.Save(target, jgpEncoder, encoderParams);
 976                        }
 977                    }
 978                    Console.WriteLine(string.Format("{0}", resource.InternalName));
 979                }
 980                db.SubmitChanges();
 981            }
 982            catch (Exception ex)
 983            {
 984                Console.WriteLine(ex);
 985            }
 986        }
 987
 988        public static void MassBan(string name, int startIndex, int endIndex, string reason, int banHours, bool banSite = false, bool banLobby = true, bool banIP = false, bool banID = false)
 989        {
 990            ZkDataContext db = new ZkDataContext();
 991            for (int i = startIndex; i <= endIndex; i++)
 992            {
 993                Account acc = db.Accounts.FirstOrDefault(x => x.Name == name + i);
 994                if (acc != null)
 995                {
 996                    int? userID = banID ? (int?)acc.AccountUserIDs.OrderByDescending(x => x.LastLogin).FirstOrDefault().UserID : null;
 997                    string userIP = banIP ? acc.AccountIPs.OrderByDescending(x => x.LastLogin).FirstOrDefault().IP : null;
 998                    System.Console.WriteLine(acc.Name, userID, userIP);
 999                    Punishment punishment = new Punishment
1000                    {
1001                        Time = DateTime.UtcNow,
1002                        Reason = reason,
1003                        BanSite = banSite,
1004                        BanLobby = banLobby,
1005                        BanExpires = DateTime.UtcNow.AddHours(banHours),
1006                        BanIP = userIP,
1007                        CreatedAccountID = 5806,
1008                        UserID = userID,
1009                    };
1010                    acc.PunishmentsByAccountID.Add(punishment);
1011                }
1012            }
1013            db.SubmitChanges();
1014        }
1015
1016
1017        public static void TestPwMatch()
1018        {
1019            Global.Nightwatch = new Nightwatch();
1020            Global.Nightwatch.Start();
1021            Global.PlanetWarsMatchMaker = new PlanetWarsMatchMaker(Global.Nightwatch.Tas);
1022            var db = new ZkDataContext();
1023            var gal = db.Galaxies.First(x => x.IsDefault);
1024            Global.PlanetWarsMatchMaker.AddAttackOption(gal.Planets.Skip(1).First());
1025            /*
1026            Utils.StartAsync(() =>
1027            {
1028                Thread.Sleep(30000);
1029                challenge = new AttackOption();
1030                challenge.Attackers.Add(tas.ExistingUsers["Licho"]);
1031                challenge.Defenders.Add(tas.ExistingUsers["gajop"]);
1032                AcceptChallenge();
1033            });*/
1034
1035
1036            Console.ReadLine();
1037
1038        }
1039    }
1040}