Beispiel #1
0
        public ActionResult BombPlanet(int planetID, int count, bool?useWarp)
        {
            var     db  = new ZkDataContext();
            Account acc = db.Accounts.Single(x => x.AccountID == Global.AccountID);

            if (acc.Faction == null)
            {
                return(Content("Join some faction first"));
            }
            Planet planet     = db.Planets.Single(x => x.PlanetID == planetID);
            bool   accessible = (useWarp == true) ? planet.CanBombersWarp(acc.Faction) : planet.CanBombersAttack(acc.Faction);

            if (!accessible)
            {
                return(Content("You cannot attack here"));
            }
            if (Global.Server.GetPlanetBattles(planet).Any(x => x.IsInGame))
            {
                return(Content("Battle in progress on the planet, cannot bomb planet"));
            }

            bool selfbomb = acc.FactionID == planet.OwnerFactionID;

            if (count < 0)
            {
                count = 0;
            }
            double avail = Math.Min(count, acc.GetBombersAvailable());

            if (useWarp == true)
            {
                avail = Math.Min(acc.GetWarpAvailable(), avail);
            }

            var capa = acc.GetBomberCapacity();

            if (avail > capa)
            {
                return(Content("Too many bombers - the fleet limit is " + capa));
            }

            if (avail > 0)
            {
                double defense   = planet.PlanetStructures.Where(x => x.IsActive).Sum(x => x.StructureType.EffectBomberDefense) ?? 0;
                double effective = avail;
                if (!selfbomb)
                {
                    effective = effective - defense;
                }

                if (effective <= 0)
                {
                    return(Content("Enemy defenses completely block your ships"));
                }

                acc.SpendBombers(avail);
                if (useWarp == true)
                {
                    acc.SpendWarps(avail);
                }

                var r = new Random();

                double strucKillChance = !selfbomb ? effective * GlobalConst.BomberKillStructureChance : 0;
                int    strucKillCount  = (int)Math.Floor(strucKillChance + r.NextDouble());

                double ipKillChance = effective * GlobalConst.BomberKillIpChance;
                int    ipKillCount  = (int)Math.Floor(ipKillChance + r.NextDouble());

                List <PlanetStructure> structs = planet.PlanetStructures.Where(x => x.StructureType.IsBomberDestructible).ToList();
                var bombed = new List <StructureType>();
                while (structs.Count > 0 && strucKillCount > 0)
                {
                    strucKillCount--;
                    PlanetStructure s = structs[r.Next(structs.Count)];
                    bombed.Add(s.StructureType);
                    structs.Remove(s);
                    db.PlanetStructures.DeleteOnSubmit(s);
                }

                double ipKillAmmount = ipKillCount * GlobalConst.BomberKillIpAmount;
                if (ipKillAmmount > 0)
                {
                    var influenceDecayMin = planet.PlanetStructures.Where(x => x.IsActive && x.StructureType.EffectPreventInfluenceDecayBelow != null).Select(x => x.StructureType.EffectPreventInfluenceDecayBelow).OrderByDescending(x => x).FirstOrDefault() ?? 0;


                    foreach (PlanetFaction pf in planet.PlanetFactions.Where(x => x.FactionID != acc.FactionID))
                    {
                        pf.Influence -= ipKillAmmount;
                        if (pf.Influence < 0)
                        {
                            pf.Influence = 0;
                        }

                        // prevent bombing below influence decaymin for owner - set by active structures
                        if (pf.FactionID == planet.OwnerFactionID && pf.Influence < influenceDecayMin)
                        {
                            pf.Influence = influenceDecayMin;
                        }
                    }
                }

                var args = new List <object>
                {
                    acc,
                    acc.Faction,
                    !selfbomb ? planet.Faction : null,
                    planet,
                    avail,
                    defense,
                    useWarp == true ? "They attacked by warp. " : "",
                    ipKillAmmount
                };
                args.AddRange(bombed);

                string str;
                if (selfbomb)
                {
                    str = "{0} of {1} bombed own planet {3} using {4} bombers against {5} defenses. {6}Ground armies lost {7} influence";
                }
                else
                {
                    str = "{0} of {1} bombed {2} planet {3} using {4} bombers against {5} defenses. {6}Ground armies lost {7} influence";
                }
                if (bombed.Count > 1)
                {
                    str += " and ";
                    int counter = 8;
                    foreach (var b in bombed)
                    {
                        str += "{" + counter + "}" + ", ";
                        counter++;
                    }
                    str += " were destroyed.";
                }
                else if (bombed.Count == 1)
                {
                    str += " and {8} was destroyed.";
                }
                else
                {
                    str += ".";
                }

                db.Events.InsertOnSubmit(PlanetwarsEventCreator.CreateEvent(str, args.ToArray()));
            }

            db.SaveChanges();
            PlanetWarsTurnHandler.SetPlanetOwners(new PlanetwarsEventCreator());
            return(RedirectToAction("Planet", new { id = planetID }));
        }
        private static SpringBattle SaveSpringBattle(SpringBattleContext result, ZkDataContext db)
        {
            var sb = new SpringBattle
            {
                HostAccountID     = Account.AccountByName(db, result.LobbyStartContext.FounderName)?.AccountID,
                Mode              = result.LobbyStartContext.Mode,
                Duration          = result.Duration,
                EngineGameID      = result.EngineBattleID,
                MapResourceID     = db.Resources.Single(x => x.InternalName == result.LobbyStartContext.Map).ResourceID,
                ModResourceID     = db.Resources.Single(x => x.InternalName == result.LobbyStartContext.Mod).ResourceID,
                HasBots           = result.LobbyStartContext.Bots.Any(),
                IsMission         = result.LobbyStartContext.IsMission,
                PlayerCount       = result.ActualPlayers.Count(x => !x.IsSpectator),
                StartTime         = result.StartTime,
                Title             = result.LobbyStartContext.Title,
                ReplayFileName    = Path.GetFileName(result.ReplayName),
                EngineVersion     = result.LobbyStartContext.EngineVersion,
                IsMatchMaker      = result.LobbyStartContext.IsMatchMakerGame,
                ApplicableRatings = 0,
            };

            db.SpringBattles.InsertOnSubmit(sb);

            // store players
            foreach (BattlePlayerResult p in result.ActualPlayers)
            {
                var account = Account.AccountByName(db, p.Name);
                if (account != null)
                {
                    sb.SpringBattlePlayers.Add(new SpringBattlePlayer
                    {
                        Account         = account,
                        AccountID       = account.AccountID,
                        AllyNumber      = p.AllyNumber,
                        IsInVictoryTeam = p.IsVictoryTeam,
                        IsSpectator     = p.IsSpectator,
                        LoseTime        = p.LoseTime
                    });
                }
            }

            // store bots
            var victoryAllyID = result.ActualPlayers.Where(x => x.IsVictoryTeam).Select(x => (int?)x.AllyNumber).FirstOrDefault() ?? -1;

            if (victoryAllyID == -1)
            {
                victoryAllyID = (result.ActualPlayers.Min(x => (int?)x.AllyNumber) ?? -1) + 1;                    // no player won, its likely to be next lowes team (stupid hack needed)
            }
            foreach (var bot in result.LobbyStartContext.Bots)
            {
                sb.SpringBattleBots.Add(new SpringBattleBot()
                {
                    AllyNumber      = bot.AllyID,
                    BotAI           = bot.BotAI,
                    BotName         = bot.BotName,
                    IsInVictoryTeam = bot.AllyID == victoryAllyID
                });
            }

            db.SaveChanges();

            return(db.SpringBattles.FirstOrDefault(x => x.SpringBattleID == sb.SpringBattleID)); // reselect from db to get proper lazy proxies
        }
Beispiel #3
0
        public async Task Process(SetAccountRelation rel)
        {
            if (!IsLoggedIn)
            {
                return;
            }

            if (string.IsNullOrEmpty(rel.TargetName) && string.IsNullOrEmpty(rel.SteamID))
            {
                return;
            }

            using (var db = new ZkDataContext())
            {
                ulong steamId = 0;

                var srcAccount = db.Accounts.Find(User.AccountID);
                ulong.TryParse(rel.SteamID, out steamId);
                var trgtAccount = Account.AccountByName(db, rel.TargetName) ?? db.Accounts.FirstOrDefault(x => x.SteamID == steamId);
                if (trgtAccount == null)
                {
                    if (!string.IsNullOrEmpty(rel.TargetName))
                    {
                        await Respond("No such account found");                                        // only warn if name is set and not just steam id
                    }
                    return;
                }

                var friendAdded = false;

                var entry = srcAccount.RelalationsByOwner.FirstOrDefault(x => x.TargetAccountID == trgtAccount.AccountID);
                if ((rel.Relation == Relation.None) && (entry != null))
                {
                    db.AccountRelations.Remove(entry);
                }
                if (rel.Relation != Relation.None)
                {
                    if (entry == null)
                    {
                        if (rel.Relation == Relation.Friend)
                        {
                            friendAdded = true;
                        }
                        entry = new AccountRelation()
                        {
                            Owner = srcAccount, Target = trgtAccount, Relation = rel.Relation
                        };
                        srcAccount.RelalationsByOwner.Add(entry);
                    }
                    else
                    {
                        entry.Relation = rel.Relation;
                    }
                }
                db.SaveChanges();

                ConnectedUser targetConnectedUser;
                if (server.ConnectedUsers.TryGetValue(trgtAccount.Name, out targetConnectedUser))
                {
                    targetConnectedUser.LoadFriendsIgnores(); // update partner's mutual lists

                    if (friendAdded)                          // friend added, sync new friend to me (user, battle and channels)
                    {
                        await server.TwoWaySyncUsers(Name, new List <string>() { targetConnectedUser.Name });

                        foreach (var chan in
                                 server.Channels.Values.Where(
                                     x => (x != null) && x.Users.ContainsKey(Name) && x.Users.ContainsKey(targetConnectedUser.Name)))
                        {
                            await SendCommand(new ChannelUserAdded()
                            {
                                ChannelName = chan.Name, UserName = targetConnectedUser.Name
                            });
                        }
                    }
                }

                LoadFriendsIgnores();
                await SendCommand(new FriendList()
                {
                    Friends = FriendEntries.ToList()
                });
                await SendCommand(new IgnoreList()
                {
                    Ignores = Ignores.ToList()
                });
            }
        }
        public ActionResult VotePost(int forumPostID, int delta)
        {
            var db    = new ZkDataContext();
            var myAcc = Global.Account;

            var penalty = Punishment.GetActivePunishment(Global.AccountID, Request.UserHostAddress, 0, null, x => x.BanForum);

            if (penalty != null)
            {
                return(Content(string.Format("You cannot vote while banned from forum!\nExpires: {0} UTC\nReason: {1}", penalty.BanExpires, penalty.Reason)));
            }

            if (myAcc.Level < GlobalConst.MinLevelForForumVote)
            {
                return(Content(string.Format("You cannot vote until you are level {0} or higher", GlobalConst.MinLevelForForumVote)));
            }
            if ((Global.Account.ForumTotalUpvotes - Global.Account.ForumTotalDownvotes) < GlobalConst.MinNetKarmaToVote)
            {
                return(Content("Your net karma is too low to vote"));
            }

            if (delta > 1)
            {
                delta = 1;
            }
            else if (delta < -1)
            {
                delta = -1;
            }

            var post   = db.ForumPosts.First(x => x.ForumPostID == forumPostID);
            var author = post.Account;

            if (author.AccountID == Global.AccountID)
            {
                return(Content("Cannot vote for your own posts"));
            }
            if (myAcc.VotesAvailable <= 0)
            {
                return(Content("Out of votes"));
            }

            var existingVote = db.AccountForumVotes.SingleOrDefault(x => x.ForumPostID == forumPostID && x.AccountID == Global.AccountID);

            if (existingVote != null) // clear existing vote
            {
                var oldDelta = existingVote.Vote;
                // reverse vote effects
                if (oldDelta > 0)
                {
                    author.ForumTotalUpvotes = author.ForumTotalUpvotes - oldDelta;
                    post.Upvotes             = post.Upvotes - oldDelta;
                }
                else if (oldDelta < 0)
                {
                    author.ForumTotalDownvotes = author.ForumTotalDownvotes + oldDelta;
                    post.Downvotes             = post.Downvotes + oldDelta;
                }
                db.AccountForumVotes.DeleteOnSubmit(existingVote);
            }
            if (delta > 0)
            {
                author.ForumTotalUpvotes = author.ForumTotalUpvotes + delta;
                post.Upvotes             = post.Upvotes + delta;
            }
            else if (delta < 0)
            {
                author.ForumTotalDownvotes = author.ForumTotalDownvotes - delta;
                post.Downvotes             = post.Downvotes - delta;
            }

            if (delta != 0)
            {
                var voteEntry = new AccountForumVote {
                    AccountID = Global.AccountID, ForumPostID = forumPostID, Vote = delta
                };
                db.AccountForumVotes.InsertOnSubmit(voteEntry);
                myAcc.VotesAvailable--;
            }

            db.SaveChanges();

            return(RedirectToAction("Thread", new { id = post.ForumThreadID, postID = forumPostID }));
        }
    /// <summary>
    /// Process planet wars turn
    /// </summary>
    /// <param name="mapName"></param>
    /// <param name="extraData"></param>
    /// <param name="db"></param>
    /// <param name="winnerSide">0 = first team wins, 1 = second team wins</param>
    /// <param name="players"></param>
    /// <param name="text"></param>
    /// <param name="sb"></param>
    ///
    public static void ResolveBattleOutcome(string mapName, List <string> extraData, ZkDataContext db, int?winnerSide, List <Account> players, List <Account> firstSidePlayers, StringBuilder text, SpringBattle sb, IPlanetwarsEventCreator eventCreator, ZkLobbyServer.ZkLobbyServer server)
    {
        if (extraData == null)
        {
            extraData = new List <string>();
        }
        Galaxy gal         = db.Galaxies.Single(x => x.IsDefault);
        Planet planet      = gal.Planets.Single(x => x.Resource.InternalName == mapName);
        var    hqStructure = db.StructureTypes.FirstOrDefault(x => x.EffectDisconnectedMetalMalus != null || x.EffectDistanceMetalBonusMax != null);

        text.AppendFormat("Battle on {1}/PlanetWars/Planet/{0} has ended\n", planet.PlanetID, GlobalConst.BaseSiteUrl);

        bool firstFactionWon;
        bool wasFirstCcDestroyed  = false;
        bool wasSecondCcDestroyed = false;

        if (winnerSide != null)
        {
            if (winnerSide == 0)
            {
                firstFactionWon = true;
            }
            else
            {
                firstFactionWon = false;
            }

            wasFirstCcDestroyed  = extraData.Any(x => x.StartsWith("hqkilled,0"));
            wasSecondCcDestroyed = extraData.Any(x => x.StartsWith("hqkilled,1"));
        }
        else
        {
            text.AppendFormat("No winner on this battle!");
            Trace.TraceError("PW battle without a winner {0}", sb != null ? sb.SpringBattleID : (int?)null);
            return;
        }

        Faction firstFaction      = firstSidePlayers.Where(x => x.Faction != null).Select(x => x.Faction).First();
        var     secondSidePlayers = players.Where(x => x.FactionID != firstFaction.FactionID && x.FactionID != null).ToList();
        Faction secondFaction     = null;

        if (secondSidePlayers.Any())
        {
            secondFaction = secondSidePlayers.Where(x => x.Faction != null).Select(x => x.Faction).First();
        }

        Faction winningFaction;
        Faction losingFaction;
        bool    ccDestroyed = false;

        if (firstFactionWon)
        {
            winningFaction = firstFaction;
            losingFaction  = secondFaction;
            ccDestroyed    = wasFirstCcDestroyed;
        }
        else
        {
            winningFaction = secondFaction;
            losingFaction  = firstFaction;
            ccDestroyed    = wasSecondCcDestroyed;
        }

        if (winningFaction == null)
        {
            text.AppendFormat("Winning team had no players!");
            Trace.TraceError("PW battle where the winner had no players!", sb != null ? sb.SpringBattleID : (int?)null);
            return;
        }

        double baseInfluence   = GlobalConst.BaseInfluencePerBattle;
        double influenceChange = baseInfluence;
        double loserInfluence  = 0;
        double ipMultiplier    = 1;

        string influenceReport = "";
        string ipReason;

        bool reducedEnemyInfluence = false;
        bool flippedDominance      = false;
        bool planetConquered       = false;

        if (ccDestroyed)
        {
            ipMultiplier = GlobalConst.PlanetWarsLostCcMultiplier;
            ipReason     = "due to winning but losing Command Centre";
        }
        else
        {
            ipReason = "due to winning flawlessly";
        }


        influenceChange = (influenceChange) * ipMultiplier;
        if (influenceChange < 0)
        {
            influenceChange = 0;
        }
        influenceChange = Math.Floor(influenceChange * 100) / 100;

        PlanetFaction entry = planet.PlanetFactions.FirstOrDefault();

        if (entry == null)
        {
            entry = new PlanetFaction {
                Faction = winningFaction, Planet = planet,
            };
            planet.PlanetFactions.Add(entry);
        }
        // if non-winner currently dominates planet
        if (entry.Faction != winningFaction)
        {
            loserInfluence = entry.Influence;

            // if win is insufficient to change this
            if (loserInfluence >= influenceChange)
            {
                reducedEnemyInfluence = true;
                entry.Influence      -= influenceChange;
            }
            else // flip dominance
            {
                flippedDominance = true;
                planet.PlanetFactions.Remove(entry);
                entry = new PlanetFaction {
                    Faction = winningFaction, Planet = planet,
                };
                planet.PlanetFactions.Add(entry);
                entry.Influence += (influenceChange - loserInfluence);

                if (entry.Influence >= GlobalConst.PlanetWarsMaximumIP)
                {
                    entry.Influence = GlobalConst.PlanetWarsMaximumIP;
                    planetConquered = true;
                }
            }
        }
        else // increase winner's existing dominance
        {
            if (entry.Influence < GlobalConst.PlanetWarsMaximumIP)
            {
                entry.Influence += influenceChange;
                if (entry.Influence >= GlobalConst.PlanetWarsMaximumIP)
                {
                    entry.Influence = GlobalConst.PlanetWarsMaximumIP;
                    planetConquered = true;
                }
            }
        }

        string contestReport = "";
        int    newContested  = 0;

        if (planetConquered)
        {
            foreach (Link link in planet.LinksByPlanetID1.Union(planet.LinksByPlanetID2).ToList())
            {
                Planet        otherPlanet        = link.PlanetID1 == planet.PlanetID ? link.PlanetByPlanetID2 : link.PlanetByPlanetID1;
                PlanetFaction otherPlanetFaction = otherPlanet.PlanetFactions.FirstOrDefault();

                if (otherPlanetFaction.Faction != winningFaction && otherPlanetFaction.Influence > GlobalConst.BreakthroughInfluence)
                {
                    otherPlanetFaction.Influence = GlobalConst.BreakthroughInfluence;
                    if (newContested > 0)
                    {
                        contestReport += ", ";
                    }
                    contestReport += otherPlanet.Name;
                    newContested++;
                }
            }
        }
        if (newContested > 0)
        {
            contestReport = "Adjacent planets now contested: " + contestReport + ".";
        }

        // Check all planets to see if they are contested by a single faction
        string controlReport = "";
        int    newControlled = 0;

        foreach (Planet p1 in gal.Planets)
        {
            List <Faction> l = GetContestingFactions(p1);

            if (l.Count() == 1)
            {
                Faction       f      = l.FirstOrDefault(); // this faction should be made dominant if it is not already
                PlanetFaction cEntry = p1.PlanetFactions.FirstOrDefault();
                if (cEntry.Faction != f)
                {
                    p1.PlanetFactions.Remove(cEntry);
                    cEntry = new PlanetFaction {
                        Faction = f, Planet = p1, Influence = 0
                    };
                    p1.PlanetFactions.Add(cEntry);
                }
                if (cEntry.Influence != GlobalConst.PlanetWarsMaximumIP)
                {
                    cEntry.Influence = GlobalConst.PlanetWarsMaximumIP;
                    if (newControlled > 0)
                    {
                        controlReport += ", ";
                    }
                    controlReport += p1.Name;
                    newControlled++;
                }
            }
        }
        if (newControlled > 0)
        {
            controlReport = "Planets automatically controlled: " + controlReport + ".";
        }

        // Update actual *control* of all planets
        PlanetWarsTurnHandler.SetPlanetOwners(eventCreator, db, sb);

        try
        {
            if (planetConquered)
            {
                influenceReport = String.Format("{0} conquered the planet, gained {1} influence ({2}% {3} of {4})",
                                                winningFaction.Shortcut,
                                                influenceChange,
                                                (int)(ipMultiplier * 100.0),
                                                ipReason,
                                                baseInfluence + " base");
            }
            else
            {
                if (reducedEnemyInfluence)
                {
                    influenceReport = String.Format("{0} reduced influence of {1} by {2} ({3}% {4} of {5}); {6} has {7} influence remaining on {8}",
                                                    winningFaction.Shortcut,
                                                    (losingFaction == null) ? "opposing faction" : losingFaction.Shortcut,
                                                    influenceChange,
                                                    (int)(ipMultiplier * 100.0),
                                                    ipReason,
                                                    baseInfluence + " base",
                                                    entry.Faction,
                                                    entry.Influence,
                                                    entry.Planet);
                }
                else
                {
                    if (flippedDominance)
                    {
                        influenceReport = String.Format("{0} took dominance from {1} and gained {2} influence ({3}% {4} of {5}); {6} now has {7} influence on {8}",
                                                        winningFaction.Shortcut,
                                                        (losingFaction == null) ? "opposing faction" : losingFaction.Shortcut,
                                                        influenceChange,
                                                        (int)(ipMultiplier * 100.0),
                                                        ipReason,
                                                        baseInfluence + " base",
                                                        entry.Faction,
                                                        entry.Influence,
                                                        entry.Planet);
                    }
                    else
                    {
                        influenceReport = String.Format("{0} gained {1} influence ({2}% {3} of {4}); {5} now has {6} influence on {7} ",
                                                        winningFaction.Shortcut,
                                                        influenceChange,
                                                        (int)(ipMultiplier * 100.0),
                                                        ipReason,
                                                        baseInfluence + " base",
                                                        entry.Faction,
                                                        entry.Influence,
                                                        entry.Planet);
                    }
                }
            }
        }
        catch (Exception ex)
        {
            Trace.TraceError(ex.ToString());
        }

        // paranoia!
        try
        {
            var mainEvent = eventCreator.CreateEvent("{0} defeated {1} on {2} in {3}. {4}. {5} {6}",
                                                     winningFaction,
                                                     (losingFaction == null) ? "opposing faction" : losingFaction.Shortcut,
                                                     planet,
                                                     (sb == null) ? "no battle" : string.Format("B{0}", sb.SpringBattleID),
                                                     influenceReport,
                                                     contestReport,
                                                     controlReport
                                                     );
            db.Events.InsertOnSubmit(mainEvent);
            text.AppendLine(mainEvent.PlainText);
        }
        catch (Exception ex)
        {
            Trace.TraceError(ex.ToString());
        }

        db.SaveChanges();

        /*gal.Turn++;
         * db.SaveChanges();
         *
         * db = new ZkDataContext(); // is this needed - attempt to fix setplanetownersbeing buggy
         * SetPlanetOwners(eventCreator, db, sb != null ? db.SpringBattles.Find(sb.SpringBattleID) : null);
         * gal = db.Galaxies.Single(x => x.IsDefault);*/
    }
Beispiel #6
0
        public async Task <LoginCheckerResponse> DoLogin(Login login, string ip)
        {
            await semaphore.WaitAsync();

            try
            {
                var userID       = login.UserID;
                var lobbyVersion = login.LobbyVersion;

                using (var db = new ZkDataContext())
                {
                    if (!VerifyIp(ip))
                    {
                        return(new LoginCheckerResponse(LoginResponse.Code.BannedTooManyConnectionAttempts));
                    }

                    SteamWebApi.PlayerInfo info = null;
                    if (!string.IsNullOrEmpty(login.SteamAuthToken))
                    {
                        info = await server.SteamWebApi.VerifyAndGetAccountInformation(login.SteamAuthToken);

                        if (info == null)
                        {
                            LogIpFailure(ip);
                            return(new LoginCheckerResponse(LoginResponse.Code.InvalidSteamToken));
                        }
                    }

                    Account accBySteamID = null;
                    Account accByLogin   = null;
                    if (info != null)
                    {
                        accBySteamID = db.Accounts.Include(x => x.Clan).Include(x => x.Faction).FirstOrDefault(x => x.SteamID == info.steamid);
                    }
                    if (!string.IsNullOrEmpty(login.Name))
                    {
                        var loginToUpper = login.Name.ToUpper();
                        accByLogin = db.Accounts.Include(x => x.Clan).Include(x => x.Faction).FirstOrDefault(x => x.Name == login.Name) ?? db.Accounts.Include(x => x.Clan).Include(x => x.Faction).FirstOrDefault(x => x.Name.ToUpper() == loginToUpper);
                    }

                    if (accBySteamID == null)
                    {
                        if (accByLogin == null)
                        {
                            LogIpFailure(ip);
                            if (!string.IsNullOrEmpty(login.Name))
                            {
                                return(new LoginCheckerResponse(LoginResponse.Code.InvalidName));
                            }
                            else
                            {
                                return(new LoginCheckerResponse(LoginResponse.Code.SteamNotLinkedAndLoginMissing));
                            }
                        }

                        if (string.IsNullOrEmpty(login.PasswordHash) || !accByLogin.VerifyPassword(login.PasswordHash))
                        {
                            LogIpFailure(ip);
                            return(new LoginCheckerResponse(LoginResponse.Code.InvalidPassword));
                        }
                    }
                    var acc = accBySteamID ?? accByLogin;

                    var ret = new LoginCheckerResponse(LoginResponse.Code.Ok);
                    ret.LoginResponse.Name = acc.Name;
                    var user = ret.User;

                    acc.Country = ResolveCountry(ip);
                    if ((acc.Country == null) || string.IsNullOrEmpty(acc.Country))
                    {
                        acc.Country = "??";
                    }
                    acc.LobbyVersion = lobbyVersion;
                    acc.LastLogin    = DateTime.UtcNow;
                    if (info != null)
                    {
                        if (db.Accounts.Any(x => x.SteamID == info.steamid && x.Name != acc.Name))
                        {
                            LogIpFailure(ip);
                            return(new LoginCheckerResponse(LoginResponse.Code.SteamLinkedToDifferentAccount));
                        }
                        acc.SteamID   = info.steamid;
                        acc.SteamName = info.personaname;
                    }

                    user.LobbyVersion = login.LobbyVersion;
                    user.IpAddress    = ip;

                    UpdateUserFromAccount(user, acc);
                    LogIP(db, acc, ip);
                    LogUserID(db, acc, userID);

                    db.SaveChanges();

                    ret.LoginResponse.SessionToken = Guid.NewGuid().ToString(); // create session token

                    var banPenalty = Punishment.GetActivePunishment(acc.AccountID, ip, userID, x => x.BanLobby);

                    if (banPenalty != null)
                    {
                        return
                            (BlockLogin(
                                 $"Banned until {banPenalty.BanExpires} (match to {banPenalty.AccountByAccountID.Name}), reason: {banPenalty.Reason}",
                                 acc,
                                 ip,
                                 userID));
                    }

                    if (!acc.HasVpnException && GlobalConst.VpnCheckEnabled)
                    {
                        if (HasVpn(ip, acc, db))
                        {
                            return(BlockLogin("Connection using proxy or VPN is not allowed! (You can ask for exception)", acc, ip, userID));
                        }
                    }

                    return(ret);
                }
            }
            finally
            {
                semaphore.Release();
            }
        }
        public ActionResult SubmitPost(
            int?threadID,
            int?categoryID,
            int?resourceID,
            int?missionID,
            int?springBattleID,
            int?clanID,
            int?planetID,
            string text,
            string title,
            string wikiKey,
            int?forumPostID,
            bool?isMinorEdit)
        {
            if (threadID == null && missionID == null && resourceID == null && springBattleID == null && clanID == null && planetID == null &&
                forumPostID == null && string.IsNullOrWhiteSpace(title))
            {
                return(Content("Cannot post new thread with blank title"));
            }
            if (string.IsNullOrWhiteSpace(text))
            {
                return(Content("Please type some text :)"));
            }

            var penalty = Punishment.GetActivePunishment(Global.AccountID, Request.UserHostAddress, 0, null, x => x.BanForum);

            if (penalty != null)
            {
                return
                    (Content(
                         string.Format("You cannot post while banned from forum!\nExpires: {0} UTC\nReason: {1}", penalty.BanExpires, penalty.Reason)));
            }

            var db = new ZkDataContext();

            using (var scope = new TransactionScope())
            {
                var thread   = db.ForumThreads.SingleOrDefault(x => x.ForumThreadID == threadID);
                var category = thread?.ForumCategory;
                if (category == null && categoryID != null)
                {
                    category = db.ForumCategories.FirstOrDefault(x => x.ForumCategoryID == categoryID);
                }
                string currentTitle = null;

                // update title
                if (thread != null && !string.IsNullOrEmpty(title))
                {
                    currentTitle   = thread.Title;
                    thread.Title   = title;
                    thread.WikiKey = wikiKey;
                }
                if (thread != null && planetID != null)
                {
                    var planet = db.Planets.Single(x => x.PlanetID == planetID);
                    thread.Title = "Planet " + planet.Name;
                }
                if (thread != null && clanID != null)
                {
                    var clan = db.Clans.Single(x => x.ClanID == clanID);
                    thread.Title = "Clan " + clan.ClanName;
                }
                if (thread != null && missionID != null)
                {
                    var mission = db.Missions.Single(x => x.MissionID == missionID);
                    thread.Title = "Mission " + mission.Name;
                }
                if (thread != null && resourceID != null)
                {
                    var map = db.Resources.Single(x => x.ResourceID == resourceID);
                    thread.Title = "Map " + map.InternalName;
                }

                if (threadID == null && category != null) // new thread
                {
                    if (category.IsLocked)
                    {
                        return(Content("Thread is locked"));
                    }

                    if (category.ForumMode == ForumMode.Wiki)
                    {
                        if (string.IsNullOrEmpty(wikiKey) || !Account.IsValidLobbyName(wikiKey))
                        {
                            return(Content("You need to set a valid wiki key"));
                        }
                        if (db.ForumThreads.Any(y => y.WikiKey == wikiKey))
                        {
                            return(Content("This wiki key already exists"));
                        }
                    }

                    if (string.IsNullOrEmpty(title))
                    {
                        return(Content("Title cannot be empty"));
                    }
                    thread = new ForumThread();
                    thread.CreatedAccountID = Global.AccountID;
                    thread.Title            = title;
                    thread.WikiKey          = wikiKey;
                    thread.ForumCategoryID  = category.ForumCategoryID;
                    db.ForumThreads.InsertOnSubmit(thread);
                }

                if (thread == null && resourceID != null) // non existing thread, we posted new post on map
                {
                    var res = db.Resources.Single(x => x.ResourceID == resourceID);
                    if (res.ForumThread != null)
                    {
                        return(Content("Double post"));
                    }
                    thread = new ForumThread
                    {
                        Title             = "Map " + res.InternalName,
                        CreatedAccountID  = Global.AccountID,
                        LastPostAccountID = Global.AccountID
                    };
                    thread.ForumCategory = db.ForumCategories.FirstOrDefault(x => x.ForumMode == ForumMode.Maps);
                    res.ForumThread      = thread;
                    db.ForumThreads.InsertOnSubmit(thread);
                }

                if (thread == null && springBattleID != null) // non existing thread, we posted new post on battle
                {
                    var bat = db.SpringBattles.Single(x => x.SpringBattleID == springBattleID);
                    if (bat.ForumThread != null)
                    {
                        return(Content("Double post"));
                    }
                    thread = new ForumThread {
                        Title = bat.FullTitle, CreatedAccountID = Global.AccountID, LastPostAccountID = Global.AccountID
                    };
                    thread.ForumCategory = db.ForumCategories.FirstOrDefault(x => x.ForumMode == ForumMode.SpringBattles);
                    bat.ForumThread      = thread;
                    db.ForumThreads.InsertOnSubmit(thread);
                }

                if (thread == null && clanID != null)
                {
                    var clan = db.Clans.Single(x => x.ClanID == clanID);
                    if (clan.ForumThread != null)
                    {
                        return(Content("Double post"));
                    }
                    thread = new ForumThread
                    {
                        Title             = "Clan " + clan.ClanName,
                        CreatedAccountID  = Global.AccountID,
                        LastPostAccountID = Global.AccountID
                    };
                    thread.ForumCategory = db.ForumCategories.FirstOrDefault(x => x.ForumMode == ForumMode.Clans);
                    clan.ForumThread     = thread;
                    thread.Clan          = clan;
                    db.ForumThreads.InsertOnSubmit(thread);
                }

                if (thread == null && planetID != null)
                {
                    var planet = db.Planets.Single(x => x.PlanetID == planetID);
                    if (planet.ForumThread != null)
                    {
                        return(Content("Double post"));
                    }
                    thread = new ForumThread
                    {
                        Title             = "Planet " + planet.Name,
                        CreatedAccountID  = Global.AccountID,
                        LastPostAccountID = Global.AccountID
                    };
                    thread.ForumCategory = db.ForumCategories.FirstOrDefault(x => x.ForumMode == ForumMode.Planets);
                    planet.ForumThread   = thread;
                    db.ForumThreads.InsertOnSubmit(thread);
                }


                if (thread == null)
                {
                    return(Content("Thread not found"));
                }
                if (thread.IsLocked && Global.Account.AdminLevel < AdminLevel.Moderator)
                {
                    return(Content("Thread is locked"));
                }
                if (thread.RestrictedClanID != null && thread.RestrictedClanID != Global.Account.ClanID)
                {
                    return(Content("Cannot post in this clan"));
                }

                var lastPost = thread.ForumPosts.OrderByDescending(x => x.ForumPostID).FirstOrDefault();

                int?gotoPostId = null;
                //double post preventer
                if (lastPost == null || lastPost.AuthorAccountID != Global.AccountID || lastPost.Text != text ||
                    (!string.IsNullOrEmpty(title) && title != currentTitle))
                {
                    if (forumPostID != null)
                    {
                        var post = thread.ForumPosts.Single(x => x.ForumPostID == forumPostID);
                        if (!post.CanEdit(Global.Account))
                        {
                            throw new ApplicationException("Not authorized to edit the post");
                        }
                        post.ForumPostEdits.Add(
                            new ForumPostEdit
                        {
                            EditorAccountID = Global.AccountID,
                            EditTime        = DateTime.UtcNow,
                            OriginalText    = post.Text,
                            NewText         = text
                        });
                        post.Text = text;
                    }
                    else
                    {
                        var p = new ForumPost {
                            AuthorAccountID = Global.AccountID, Text = text, Created = DateTime.UtcNow
                        };
                        thread.ForumPosts.Add(p);
                        db.SaveChanges();
                        gotoPostId = p.ForumPostID;
                    }

                    if (isMinorEdit != true)
                    {
                        thread.LastPost          = DateTime.UtcNow;
                        thread.LastPostAccountID = Global.AccountID;
                    }
                    thread.PostCount = thread.ForumPosts.Count();
                    thread.UpdateLastRead(Global.AccountID, true, thread.LastPost);

                    db.SaveChanges();
                }

                scope.Complete();


                if (missionID.HasValue)
                {
                    return(RedirectToAction("Detail", "Missions", new { id = missionID }));
                }
                if (resourceID.HasValue)
                {
                    return(RedirectToAction("Detail", "Maps", new { id = resourceID }));
                }
                if (springBattleID.HasValue)
                {
                    return(RedirectToAction("Detail", "Battles", new { id = springBattleID }));
                }
                if (clanID.HasValue)
                {
                    return(RedirectToAction("Detail", "Clans", new { id = clanID }));
                }
                if (planetID.HasValue)
                {
                    return(RedirectToAction("Planet", "Planetwars", new { id = planetID }));
                }
                if (forumPostID.HasValue)
                {
                    return(RedirectToAction("Thread", "Forum", new { id = thread.ForumThreadID, postID = forumPostID }));
                }
                return(RedirectToAction("Thread", "Forum", new { id = thread.ForumThreadID, postID = gotoPostId }));
            }
        }
        public async Task<RegisterResponse> DoRegister(Register register, string ip)
        {
            if (!Account.IsValidLobbyName(register.Name)) return new RegisterResponse(RegisterResponse.Code.NameHasInvalidCharacters);

            if (server.ConnectedUsers.ContainsKey(register.Name)) return new RegisterResponse(RegisterResponse.Code.AlreadyConnected);

            if (string.IsNullOrEmpty(register.PasswordHash) && string.IsNullOrEmpty(register.SteamAuthToken)) return new RegisterResponse(RegisterResponse.Code.MissingBothPasswordAndToken);

            if (!VerifyIp(ip)) return new RegisterResponse(RegisterResponse.Code.BannedTooManyAttempts);

            var banPenalty = Punishment.GetActivePunishment(null, ip, register.UserID, register.InstallID, x => x.BanLobby);
            if (banPenalty != null) return new RegisterResponse(RegisterResponse.Code.Banned) {BanReason =  banPenalty.Reason};

            SteamWebApi.PlayerInfo info = null;
            if (!string.IsNullOrEmpty(register.SteamAuthToken))
            {
                info = await server.SteamWebApi.VerifyAndGetAccountInformation(register.SteamAuthToken);
                if (info == null) return new RegisterResponse(RegisterResponse.Code.InvalidSteamToken);
            }

            using (var db = new ZkDataContext())
            {
                var registerName = register.Name.ToUpper();
                var existingByName = db.Accounts.FirstOrDefault(x => x.Name.ToUpper() == registerName);
                if (existingByName != null)
                {
                    if (info != null && existingByName.SteamID == info.steamid) return new RegisterResponse(RegisterResponse.Code.AlreadyRegisteredWithThisSteamToken);

                    if (info == null && !string.IsNullOrEmpty(register.PasswordHash) && existingByName.VerifyPassword(register.PasswordHash)) return new RegisterResponse(RegisterResponse.Code.AlreadyRegisteredWithThisPassword);

                    return new RegisterResponse(RegisterResponse.Code.NameAlreadyTaken);
                }

                var acc = new Account() { Name = register.Name };
                acc.SetPasswordHashed(register.PasswordHash);
                acc.SetName(register.Name);
                acc.SetAvatar();
                acc.Email = register.Email;
                if (info != null)
                {
                    var existingBySteam = db.Accounts.FirstOrDefault(x => x.SteamID == info.steamid);
                    if (existingBySteam != null)
                        return new RegisterResponse(RegisterResponse.Code.SteamAlreadyRegistered);

                    acc.SteamID = info.steamid;
                    acc.SteamName = info.personaname;
                } else if (string.IsNullOrEmpty(register.PasswordHash))
                {
                    return new RegisterResponse(RegisterResponse.Code.InvalidPassword);
                }
                LogIP(db, acc, ip);
                LogUserID(db, acc, register.UserID, register.InstallID);
                db.Accounts.Add(acc);
                db.SaveChanges();
                var smurfs = acc.GetSmurfs().Where(a => a.PunishmentsByAccountID.Any(x => x.BanExpires > DateTime.UtcNow));
                if (smurfs.Any())
                {
                    await server.GhostChanSay(GlobalConst.ModeratorChannel, string.Format("Smurf Alert! {0} might be a smurf of {1}. Check https://zero-k.info/Users/AdminUserDetail/{2}", acc.Name, smurfs.OrderByDescending(x => x.Level).First().Name, acc.AccountID));
                }
            }
            return new RegisterResponse(RegisterResponse.Code.Ok);
        }
Beispiel #9
0
        //private


        //Runs in O(N log(N)) for all players
        private void UpdateRankings(IEnumerable <Player> players)
        {
            try
            {
                Dictionary <int, float> oldRatings = new Dictionary <int, float>();

                //check for ladder elo updates
                using (var db = new ZkDataContext())
                {
                    var battleIDs         = pendingDebriefings.Keys.ToList();
                    var lastBattlePlayers = db.SpringBattlePlayers.Where(p => battleIDs.Contains(p.SpringBattleID) && !p.IsSpectator).Include(x => x.Account).ToList();
                    oldRatings = lastBattlePlayers.ToDictionary(p => p.AccountID, p => playerRatings[p.AccountID].LadderElo);
                    lastBattlePlayers.ForEach(p => playerRatings[p.AccountID].LadderElo = Ranks.UpdateLadderRating(p.Account, category, this.players[p.AccountID].avgElo + RatingOffset, p.IsInVictoryTeam, !p.IsInVictoryTeam, db));
                }

                //update ladders
                int currentDay  = RatingSystems.ConvertDateToDays(DateTime.UtcNow);
                int playerCount = 0;
                using (var db = new ZkDataContext())
                {
                    foreach (var p in players)
                    {
                        if (p.days.Count == 0)
                        {
                            Trace.TraceError("WHR " + category + " has invalid player " + p.id + " with no days(games)");
                            continue;
                        }
                        float elo = p.days.Last().GetElo() + RatingOffset;
                        float lastNaturalRatingVar = p.avgEloVar * GlobalConst.EloToNaturalRatingMultiplierSquared;
                        var   lastDay = p.days.Last();
                        float ladderElo;
                        if (playerRatings.ContainsKey(p.id))
                        {
                            ladderElo = playerRatings[p.id].LadderElo;
                        }
                        else
                        {
                            ladderElo = (float?)db.AccountRatings.Where(x => x.AccountID == p.id && x.RatingCategory == category).FirstOrDefault()?.LadderElo ?? DefaultRating.LadderElo;
                        }
                        playerRatings[p.id] = new PlayerRating(int.MaxValue, 1, elo, lastNaturalRatingVar, GlobalConst.NaturalRatingVariancePerDay(lastDay.totalWeight), lastDay.day, currentDay, ladderElo, !float.IsNaN(p.avgElo));
                        float rating = -playerRatings[p.id].LadderElo + 0.001f * (float)rand.NextDouble();
                        if (playerKeys.ContainsKey(p.id))
                        {
                            sortedPlayers.Remove(playerKeys[p.id]);
                        }
                        playerKeys[p.id]      = rating;
                        sortedPlayers[rating] = p.id;
                        if (playerRatings[p.id].Ranked)
                        {
                            playerCount++;
                        }
                    }
                }
                this.activePlayers = playerCount;
                int          rank                  = 0;
                List <int>   newTopPlayers         = new List <int>();
                int          matched               = 0;
                List <float> newPercentileBrackets = new List <float>();
                newPercentileBrackets.Add(playerRatings[sortedPlayers.First().Value].LadderElo + 420);
                float   percentile;
                float[] percentilesRev = Ranks.Percentiles.Reverse().ToArray();
                foreach (var pair in sortedPlayers)
                {
                    if (playerRatings[pair.Value].Ranked)
                    {
                        newTopPlayers.Add(pair.Value);
                        if (rank == matched && rank < topPlayers.Count && topPlayers[rank] == pair.Value)
                        {
                            matched++;
                        }
                        rank++;
                        percentile = (float)rank / activePlayers;
                        if (newPercentileBrackets.Count <= Ranks.Percentiles.Length && percentile > percentilesRev[newPercentileBrackets.Count - 1])
                        {
                            newPercentileBrackets.Add(playerRatings[pair.Value].LadderElo);
                        }
                        playerRatings[pair.Value].ApplyLadderUpdate(rank, percentile, currentDay, true);
                    }
                    else if (playerRatings[pair.Value].Rank < int.MaxValue)
                    {
                        playerRatings[pair.Value].ApplyLadderUpdate(int.MaxValue, 1, currentDay, false);
                    }
                }
                newPercentileBrackets.Add(newPercentileBrackets.Last() - 420);
                PercentileBrackets = newPercentileBrackets.Select(x => x).Reverse().ToArray();
                topPlayers         = newTopPlayers;
                laddersCache       = new List <Account>();
                Trace.TraceInformation("WHR " + category + " Ladders updated with " + topPlayers.Count + "/" + this.players.Count + " entries. Brackets are now: " + string.Join(", ", PercentileBrackets));

                var playerIds = players.Select(x => x.id).ToList();
                if (playerIds.Count() < 100)
                {
                    SaveToDB(playerIds);
                }
                else
                {
                    SaveToDB();
                }

                //check for rank updates

                if (pendingDebriefings.Any())
                {
                    List <int>                playersWithRatingChange = new List <int>();
                    Dictionary <int, int>     oldRanks         = new Dictionary <int, int>();
                    Dictionary <int, Account> updatedRanks     = new Dictionary <int, Account>();
                    Dictionary <int, Account> involvedAccounts = new Dictionary <int, Account>();
                    Trace.TraceInformation("WHR Filling in Debriefings for Battles: " + pendingDebriefings.Keys.Select(x => "B" + x).StringJoin());
                    using (var db = new ZkDataContext())
                    {
                        var battleIDs         = pendingDebriefings.Keys.ToList();
                        var lastBattlePlayers = db.SpringBattlePlayers.Where(p => battleIDs.Contains(p.SpringBattleID) && !p.IsSpectator).Include(x => x.Account).ToList();
                        involvedAccounts = lastBattlePlayers.ToDictionary(p => p.AccountID, p => p.Account);
                        Trace.TraceInformation("WHR Debriefing players: " + involvedAccounts.Values.Select(x => x.Name).StringJoin());
                        oldRanks     = lastBattlePlayers.ToDictionary(p => p.AccountID, p => p.Account.Rank);
                        updatedRanks = lastBattlePlayers.Where(p => Ranks.UpdateRank(p.Account, p.IsInVictoryTeam, !p.IsInVictoryTeam, db)).Select(x => x.Account).ToDictionary(p => p.AccountID, p => p);
                        updatedRanks.Values.ForEach(p => db.Entry(p).State = EntityState.Modified);
                        playersWithRatingChange = lastBattlePlayers.Select(x => x.AccountID).ToList();

                        lastBattlePlayers.Where(p => playerOldRatings.ContainsKey(RatingSystems.GetRatingId(p.AccountID)) && !p.EloChange.HasValue).ForEach(p =>
                        {
                            //p.EloChange = playerRatings[RatingSystems.GetRatingId(p.AccountID)].RealElo - playerOldRatings[RatingSystems.GetRatingId(p.AccountID)].RealElo;
                            p.EloChange = playerRatings[p.AccountID].LadderElo - oldRatings[p.AccountID];
                        });

                        db.SpringBattlePlayers.Where(p => battleIDs.Contains(p.SpringBattleID) && !p.IsSpectator).ToList().ForEach(x => playerOldRatings[RatingSystems.GetRatingId(x.AccountID)] = playerRatings[RatingSystems.GetRatingId(x.AccountID)]);
                        db.SaveChanges();
                    }
                    //Publish new results only after saving new stats to db.
                    pendingDebriefings.ForEach(pair =>
                    {
                        pair.Value.partialDebriefing.DebriefingUsers.Values.ForEach(user => {
                            try
                            {
                                user.EloChange  = playerRatings[user.AccountID].LadderElo - oldRatings[user.AccountID];
                                user.IsRankup   = updatedRanks.ContainsKey(user.AccountID) && oldRanks[user.AccountID] < updatedRanks[user.AccountID].Rank;
                                user.IsRankdown = updatedRanks.ContainsKey(user.AccountID) && oldRanks[user.AccountID] > updatedRanks[user.AccountID].Rank;
                                var prog        = Ranks.GetRankProgress(involvedAccounts[user.AccountID], this);
                                if (prog == null)
                                {
                                    Trace.TraceWarning("User " + user.AccountID + " is wrongfully unranked");
                                }
                                user.NextRankElo = prog.RankCeilElo;
                                user.PrevRankElo = prog.RankFloorElo;
                                user.NewElo      = prog.CurrentElo;
                            }
                            catch (Exception ex)
                            {
                                Trace.TraceError("Unable to complete debriefing for user " + user.AccountID + ": " + ex);
                            }
                        });
                        pair.Value.partialDebriefing.RatingCategory = category.ToString();
                        pair.Value.debriefingConsumer.Invoke(pair.Value.partialDebriefing);
                    });
                    RatingsUpdated(this, new RatingUpdate()
                    {
                        affectedPlayers = playersWithRatingChange
                    });
                    pendingDebriefings.Clear();
                }


                //check for topX updates
                GetTopPlayers(GlobalConst.LadderSize);
                foreach (var listener in topPlayersUpdateListeners)
                {
                    if (matched < listener.Value)
                    {
                        listener.Key.TopPlayersUpdated(GetTopPlayers(listener.Value));
                    }
                }
            }
            catch (Exception ex)
            {
                string dbg = "WHR " + category + ": Failed to update rankings " + ex + "\nPlayers: ";
                foreach (var p in players)
                {
                    dbg += p.id + " (" + p.days.Count + " days), ";
                }
                Trace.TraceError(dbg);
            }
        }
        public ActionResult SubmitCreate(Clan clan, HttpPostedFileBase image, HttpPostedFileBase bgimage, bool noFaction = false)
        {
            //using (var scope = new TransactionScope())
            //{
            ZkDataContext db      = new ZkDataContext();
            bool          created = clan.ClanID == 0; // existing clan vs creation
            var           acc     = db.Accounts.Single(x => x.AccountID == Global.AccountID);

            //return Content(noFaction ? "true":"false");
            if (noFaction)
            {
                clan.FactionID = null;
            }

            Faction new_faction = db.Factions.SingleOrDefault(x => x.FactionID == clan.FactionID);

            if ((new_faction != null) && new_faction.IsDeleted)
            {
                return(Content("Cannot create clans in deleted factions"));
            }

            if (string.IsNullOrEmpty(clan.ClanName) || string.IsNullOrEmpty(clan.Shortcut))
            {
                return(Content("Name and shortcut cannot be empty!"));
            }
            if (!ZkData.Clan.IsShortcutValid(clan.Shortcut))
            {
                return(Content("Shortcut must have at least 1 characters and contain only numbers and letters"));
            }

            if (created && (image == null || image.ContentLength == 0))
            {
                return(Content("A clan image is required"));
            }

            Clan orgClan = null;

            if (!created)
            {
                if (!Global.IsModerator && (!Global.Account.HasClanRight(x => x.RightEditTexts) || clan.ClanID != Global.Account.ClanID))
                {
                    return(Content("Unauthorized"));
                }

                // check if our name or shortcut conflicts with existing clans
                var existingClans = db.Clans.Where(x => ((SqlFunctions.PatIndex(clan.Shortcut, x.Shortcut) > 0 || SqlFunctions.PatIndex(clan.ClanName, x.ClanName) > 0) && x.ClanID != clan.ClanID));
                if (existingClans.Count() > 0)
                {
                    if (existingClans.Any(x => !x.IsDeleted))
                    {
                        return(Content("Clan with this shortcut or name already exists"));
                    }
                }

                orgClan = db.Clans.Single(x => x.ClanID == clan.ClanID);
                string orgImageUrl   = Server.MapPath(orgClan.GetImageUrl());
                string orgBGImageUrl = Server.MapPath(orgClan.GetBGImageUrl());
                string orgShortcut   = orgClan.Shortcut;
                string newImageUrl   = Server.MapPath(clan.GetImageUrl());
                string newBGImageUrl = Server.MapPath(clan.GetBGImageUrl());

                if (Global.IsModerator && (!Global.Account.HasClanRight(x => x.RightEditTexts) || clan.ClanID != Global.Account.ClanID))
                {
                    Global.Server.GhostChanSay(GlobalConst.ModeratorChannel, string.Format("{0} edited clan {1} {2}", Global.Account.Name, orgClan.ClanName, Url.Action("Detail", "Clans", new { id = clan.ClanID }, "http")));
                    if (orgClan.ClanName != clan.ClanName)
                    {
                        Global.Server.GhostChanSay(GlobalConst.ModeratorChannel, string.Format("{0} => {1}", orgClan.ClanName, clan.ClanName));
                    }
                }

                orgClan.ClanName    = clan.ClanName;
                orgClan.Shortcut    = clan.Shortcut;
                orgClan.Description = clan.Description;
                orgClan.SecretTopic = clan.SecretTopic;
                orgClan.Password    = clan.Password;
                bool shortcutChanged = orgShortcut != clan.Shortcut;

                if (image != null && image.ContentLength > 0)
                {
                    var im = Image.FromStream(image.InputStream);
                    if (im.Width != 64 || im.Height != 64)
                    {
                        im = im.GetResized(64, 64, InterpolationMode.HighQualityBicubic);
                    }
                    im.Save(newImageUrl);
                }
                else if (shortcutChanged)
                {
                    //if (System.IO.File.Exists(newImageUrl)) System.IO.File.Delete(newImageUrl);
                    //System.IO.File.Move(orgImageUrl, newImageUrl);
                    try {
                        //var im = Image.FromFile(orgImageUrl);
                        //im.Save(newImageUrl);
                        System.IO.File.Copy(orgImageUrl, newImageUrl, true);
                    } catch (System.IO.FileNotFoundException fnfex) // shouldn't happen but hey
                    {
                        return(Content("A clan image is required"));
                    }
                }

                if (bgimage != null && bgimage.ContentLength > 0)
                {
                    var im = Image.FromStream(bgimage.InputStream);
                    im.Save(newBGImageUrl);
                }
                else if (shortcutChanged)
                {
                    //if (System.IO.File.Exists(newBGImageUrl)) System.IO.File.Delete(newBGImageUrl);
                    //System.IO.File.Move(orgBGImageUrl, newBGImageUrl);
                    try
                    {
                        //var im = Image.FromFile(orgBGImageUrl);
                        //im.Save(newBGImageUrl);
                        System.IO.File.Copy(orgBGImageUrl, newBGImageUrl, true);
                    }
                    catch (System.IO.FileNotFoundException fnfex)
                    {
                        // there wasn't an original background image, do nothing
                    }
                }

                if (clan.FactionID != orgClan.FactionID)
                {
                    // set factions of members
                    Faction oldFaction = orgClan.Faction;
                    orgClan.FactionID = clan.FactionID;
                    foreach (Account member in orgClan.Accounts)
                    {
                        if (member.FactionID != clan.FactionID && member.FactionID != null)
                        {
                            FactionsController.PerformLeaveFaction(member.AccountID, true, db);
                        }
                        member.FactionID = clan.FactionID;
                    }
                    db.SaveChanges();
                    if (clan.FactionID != null)
                    {
                        db.Events.InsertOnSubmit(PlanetwarsEventCreator.CreateEvent("Clan {0} moved to faction {1}", orgClan, orgClan.Faction));
                    }
                    else
                    {
                        db.Events.InsertOnSubmit(PlanetwarsEventCreator.CreateEvent("Clan {0} left faction {1}", orgClan, oldFaction));
                    }
                }
                db.SaveChanges();
            }
            else
            {
                if (Global.Clan != null)
                {
                    return(Content("You already have a clan"));
                }
                // should just change their faction for them?
                if (Global.FactionID != 0 && Global.FactionID != clan.FactionID)
                {
                    return(Content("Clan must belong to same faction you are in"));
                }

                // check if our name or shortcut conflicts with existing clans
                // if so, allow us to create a new clan over it if it's a deleted clan, else block action
                var existingClans = db.Clans.Where(x => ((SqlFunctions.PatIndex(clan.Shortcut, x.Shortcut) > 0 || SqlFunctions.PatIndex(clan.ClanName, x.ClanName) > 0) && x.ClanID != clan.ClanID));
                if (existingClans.Count() > 0)
                {
                    if (existingClans.Any(x => !x.IsDeleted))
                    {
                        return(Content("Clan with this shortcut or name already exists"));
                    }
                    Clan deadClan  = existingClans.First();
                    Clan inputClan = clan;
                    clan = deadClan;
                    if (noFaction)
                    {
                        clan.FactionID = null;
                    }
                    clan.IsDeleted   = false;
                    clan.ClanName    = inputClan.ClanName;
                    clan.Password    = inputClan.Password;
                    clan.Description = inputClan.Description;
                    clan.SecretTopic = inputClan.SecretTopic;
                }
                else
                {
                    db.Clans.InsertOnSubmit(clan);
                }

                db.SaveChanges();

                acc.ClanID = clan.ClanID;

                // we created a new clan, set self as founder and rights
                AddClanLeader(acc.AccountID, clan.ClanID, db);

                db.SaveChanges();

                if (image != null && image.ContentLength > 0)
                {
                    var im = Image.FromStream(image.InputStream);
                    if (im.Width != 64 || im.Height != 64)
                    {
                        im = im.GetResized(64, 64, InterpolationMode.HighQualityBicubic);
                    }
                    im.Save(Server.MapPath(clan.GetImageUrl()));
                }
                if (bgimage != null && bgimage.ContentLength > 0)
                {
                    var im = Image.FromStream(bgimage.InputStream);
                    im.Save(Server.MapPath(clan.GetBGImageUrl()));
                }

                db.Events.InsertOnSubmit(PlanetwarsEventCreator.CreateEvent("New clan {0} formed by {1}", clan, acc));
                db.SaveChanges();
            }

            Global.Server.PublishAccountUpdate(acc);
            //scope.Complete();
            Global.Server.ChannelManager.AddClanChannel(clan);;
            Global.Server.SetTopic(clan.GetClanChannel(), clan.SecretTopic, Global.Account.Name);
            //}
            return(RedirectToAction("Detail", new { id = clan.ClanID }));
        }
        /// <summary>
        /// Go to home page; also updates news read dates
        /// </summary>
        public ActionResult Index()
        {
            var db = new ZkDataContext();


            var result = new IndexResult()
            {
                Spotlight         = SpotlightHandler.GetRandom(),
                Top10Players      = RatingSystems.GetRatingSystem(RatingCategory.MatchMaking).GetTopPlayers(10),
                WikiRecentChanges = MediaWikiRecentChanges.LoadRecentChanges()
            };

            result.LobbyStats = MemCache.GetCached("lobby_stats", GetCurrentLobbyStats, 60 * 2);

            result.News = db.News.Where(x => x.Created < DateTime.UtcNow).OrderByDescending(x => x.Created);
            if (Global.Account != null)
            {
                result.Headlines =
                    db.News.Where(
                        x => x.Created <DateTime.UtcNow && x.HeadlineUntil != null && x.HeadlineUntil> DateTime.UtcNow && !x.ForumThread.ForumThreadLastReads.Any(y => y.AccountID == Global.AccountID && y.LastRead != null)).
                    OrderByDescending(x => x.Created).ToList();

                if (result.Headlines.Any())
                {
                    foreach (var h in result.Headlines)
                    {
                        h.ForumThread.UpdateLastRead(Global.AccountID, false);
                    }

                    db.SaveChanges();
                }
            }
            else
            {
                result.Headlines = new List <News>();
            }


            var accessibleThreads = db.ForumThreads.Where(x => x.RestrictedClanID == null || x.RestrictedClanID == Global.ClanID);

            accessibleThreads = accessibleThreads.Where(x => x.ForumCategory.ForumMode != ForumMode.Archive);
            if (!Global.IsAccountAuthorized)
            {
                result.NewThreads = accessibleThreads.OrderByDescending(x => x.LastPost).Take(10).Select(x => new NewThreadEntry()
                {
                    ForumThread = x
                });
            }
            else
            {
                result.NewThreads = (from t in accessibleThreads
                                     let read = t.ForumThreadLastReads.FirstOrDefault(x => x.AccountID == Global.AccountID)
                                                let readForum = t.ForumCategory.ForumLastReads.FirstOrDefault(x => x.AccountID == Global.AccountID)
                                                                where (read == null || t.LastPost > read.LastRead) && (readForum == null || t.LastPost > readForum.LastRead)
                                                                orderby t.LastPost descending
                                                                select new NewThreadEntry {
                    ForumThread = t, WasRead = read != null, WasWritten = read != null && read.LastPosted != null
                }).
                                    Take(10);
            }



            return(View("HomeIndex", result));
        }
Beispiel #12
0
        private void TimerOnElapsed(object sender, ElapsedEventArgs elapsedEventArgs)
        {
            try
            {
                timer.Stop();

                // auto change PW mode based on time
                if (MiscVar.PlanetWarsNextModeTime != null && MiscVar.PlanetWarsNextModeTime < DateTime.UtcNow && MiscVar.PlanetWarsNextMode != null)
                {
                    MiscVar.PlanetWarsMode = MiscVar.PlanetWarsNextMode ?? PlanetWarsModes.AllOffline;

                    MiscVar.PlanetWarsNextMode     = null;
                    MiscVar.PlanetWarsNextModeTime = null;

                    using (var db = new ZkDataContext())
                    {
                        db.Events.Add(server.PlanetWarsEventCreator.CreateEvent("PlanetWars changed status to {0}", MiscVar.PlanetWarsMode.Description()));
                        db.SaveChanges();
                    }
                }


                if (MiscVar.PlanetWarsMode != lastPlanetWarsMode)
                {
                    server.Broadcast(GeneratePwStatus());
                    UpdateLobby();
                    lastPlanetWarsMode = MiscVar.PlanetWarsMode;
                }

                if (MiscVar.PlanetWarsMode != PlanetWarsModes.Running)
                {
                    return;
                }

                // Some sort of battle timer
                // PlanetWarsTurnHandler.UpdateEconomy(new ZkDataContext(), server.PlanetWarsEventCreator);

                if (Challenge == null)
                {
                    // attack timer
                    if (DateTime.UtcNow > GetAttackDeadline())
                    {
                        AttackerSideCounter++;
                        ResetAttackOptions();
                    }
                }
                else
                {
                    // accept timer
                    if (DateTime.UtcNow > GetAcceptDeadline())
                    {
                        if ((Challenge.Defenders.Count >= Challenge.Attackers.Count - 1) && (Challenge.Defenders.Count > 0))
                        {
                            AcceptChallenge();
                        }
                        else
                        {
                            RecordPlanetwarsLoss(Challenge);
                            AttackerSideCounter++;
                            ResetAttackOptions();
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Trace.TraceError("PlanetWars timer error: {0}", ex);
            }
            finally
            {
                timer.Start();
            }
        }
Beispiel #13
0
        private ActionResult ChangePlanetMap(int planetID, int structureTypeID, int targetID, int?newMapID)
        {
            var             db        = new ZkDataContext();
            PlanetStructure structure = db.PlanetStructures.FirstOrDefault(x => x.PlanetID == planetID && x.StructureTypeID == structureTypeID);
            Planet          source    = db.Planets.FirstOrDefault(x => x.PlanetID == planetID);
            Planet          target    = db.Planets.FirstOrDefault(x => x.PlanetID == targetID);
            Galaxy          gal       = db.Galaxies.FirstOrDefault(x => x.GalaxyID == source.GalaxyID);

            if (newMapID == null)
            {
                List <Resource> mapList =
                    db.Resources.Where(
                        x =>
                        x.MapPlanetWarsIcon != null && x.Planets.Where(p => p.GalaxyID == gal.GalaxyID).Count() == 0 && x.MapSupportLevel >= MapSupportLevel.Featured &&
                        x.ResourceID != source.MapResourceID).ToList();
                if (mapList.Count > 0)
                {
                    int r = new Random().Next(mapList.Count);
                    newMapID = mapList[r].ResourceID;
                }
            }
            if (newMapID != null)
            {
                Resource newMap = db.Resources.Single(x => x.ResourceID == newMapID);
                target.Resource = newMap;
                gal.IsDirty     = true;
                string word = "";
                if (target.Faction == source.Faction)
                {
                    if (target.TeamSize < GlobalConst.PlanetWarsMaxTeamsize)
                    {
                        target.TeamSize++;
                    }
                    word = "terraformed";
                }
                else
                {
                    word = "nanodegraded";
                    if (target.TeamSize > 1)
                    {
                        target.TeamSize--;
                    }
                }

                db.Events.InsertOnSubmit(PlanetwarsEventCreator.CreateEvent("{0} {1} has been {6} by {2} from {3} {4}. New team size is {5} vs {5}",
                                                                            target.Faction,
                                                                            target,
                                                                            structure.StructureType,
                                                                            source.Faction,
                                                                            source,
                                                                            target.TeamSize,
                                                                            word));
            }
            else
            {
                return
                    (Content(string.Format("Terraform attempt on {0} {1} using {2} from {3} {4} has failed - no valid maps",
                                           target.Faction,
                                           target,
                                           structure.StructureType,
                                           source.Faction,
                                           source)));
            }
            db.SaveChanges();
            return(null);
        }
Beispiel #14
0
        public ActionResult SendDropships(int planetID, int count, bool?useWarp)
        {
            var     db  = new ZkDataContext();
            Account acc = db.Accounts.Single(x => x.AccountID == Global.AccountID);

            if (acc.Faction == null)
            {
                return(Content("Join a faction first"));
            }
            Planet planet     = db.Planets.SingleOrDefault(x => x.PlanetID == planetID);
            int    there      = planet.PlanetFactions.Where(x => x.FactionID == acc.FactionID).Sum(x => (int?)x.Dropships) ?? 0;
            bool   accessible = useWarp == true?planet.CanDropshipsWarp(acc.Faction) : planet.CanDropshipsAttack(acc.Faction);

            if (!accessible)
            {
                return(Content(string.Format("That planet cannot be attacked")));
            }
            if (Global.Server.GetPlanetBattles(planet).Any(x => x.IsInGame))
            {
                return(Content("Battle in progress on the planet, cannot send ships"));
            }

            int cnt = Math.Max(count, 0);

            int capa = acc.GetDropshipCapacity();

            if (cnt + there > capa)
            {
                return(Content("Too many dropships on planet - the fleet limit is " + capa));
            }
            cnt = Math.Min(cnt, (int)acc.GetDropshipsAvailable());
            if (useWarp == true)
            {
                cnt = Math.Min(cnt, (int)acc.GetWarpAvailable());
            }
            if (cnt > 0)
            {
                acc.SpendDropships(cnt);
                if (useWarp == true)
                {
                    acc.SpendWarps(cnt);
                    if (cnt < GlobalConst.DropshipsForFullWarpIPGain)
                    {
                        return(Content($"You must send at least {GlobalConst.DropshipsForFullWarpIPGain} dropships when warping"));
                    }
                }

                if (planet.Account != null)
                {
                    Global.Server.GhostPm(planet.Account.Name, string.Format(
                                              "Warning: long range scanners detected fleet of {0} ships inbound to your planet {1} {3}/Planetwars/Planet/{2}",
                                              cnt,
                                              planet.Name,
                                              planet.PlanetID,
                                              GlobalConst.BaseSiteUrl));
                }
                PlanetFaction pac = planet.PlanetFactions.SingleOrDefault(x => x.FactionID == acc.FactionID);
                if (pac == null)
                {
                    pac = new PlanetFaction {
                        FactionID = Global.FactionID, PlanetID = planetID
                    };
                    db.PlanetFactions.InsertOnSubmit(pac);
                }
                pac.Dropships         += cnt;
                pac.DropshipsLastAdded = DateTime.UtcNow;

                if (cnt > 0)
                {
                    db.Events.InsertOnSubmit(PlanetwarsEventCreator.CreateEvent("{0} sends {1} {2} dropships to {3} {4} {5}",
                                                                                acc,
                                                                                cnt,
                                                                                acc.Faction,
                                                                                planet.Faction,
                                                                                planet,
                                                                                useWarp == true ? "using warp drives" : ""));
                }
                db.SaveChanges();
            }
            return(RedirectToAction("Planet", new { id = planetID }));
        }
Beispiel #15
0
        public async Task <ActionResult> Punish(int accountID,
                                                string reason,
                                                bool banMute,
                                                bool banVotes,
                                                bool banCommanders,
                                                bool banSite,
                                                bool banLobby,
                                                bool banSpecChat,
                                                bool banForum,
                                                bool messageOnly,
                                                string banIP,
                                                long?banUserID,
                                                string installID,
                                                double banHours)
        {
            ZkDataContext db  = new ZkDataContext();
            Account       acc = db.Accounts.SingleOrDefault(x => x.AccountID == accountID);

            if (acc == null)
            {
                return(Content("Invalid accountID"));
            }

            if (banHours > MaxBanHours)
            {
                banHours = MaxBanHours;                         // todo show some notification
            }
            Punishment punishment = new Punishment
            {
                Time             = DateTime.UtcNow,
                Reason           = reason,
                BanMute          = banMute,
                BanVotes         = banVotes,
                BanCommanders    = banCommanders,
                BanSite          = banSite,
                BanLobby         = banLobby,
                BanExpires       = DateTime.UtcNow.AddHours(banHours),
                BanUnlocks       = false,
                BanSpecChat      = banSpecChat,
                MessageOnly      = messageOnly,
                BanIP            = banIP,
                BanForum         = banForum,
                DeleteXP         = false,
                DeleteInfluence  = false,
                CreatedAccountID = Global.AccountID,
                InstallID        = installID,
                UserID           = banUserID
            };

            acc.PunishmentsByAccountID.Add(punishment);
            db.SaveChanges();

            // notify lobby of changes and post log message
            try
            {
                string pmAction = "";

                bool activePenalty = banLobby || banMute || banForum || banSpecChat || banVotes || banCommanders || banSite;

                if (messageOnly && !activePenalty)
                {
                    await Global.Server.GhostChanSay(GlobalConst.ModeratorChannel, string.Format("Message sent to {0} {1}  ", acc.Name, Url.Action("Detail", "Users", new { id = acc.AccountID }, "http")));

                    await Global.Server.GhostChanSay(GlobalConst.ModeratorChannel, string.Format(" - message: {0} ", reason));

                    await Global.Server.GhostPm(acc.Name, string.Format("A moderator has sent you a message: {0}", reason));
                }
                else
                {
                    await Global.Server.GhostChanSay(GlobalConst.ModeratorChannel, string.Format("New penalty for {0} {1}  ", acc.Name, Url.Action("Detail", "Users", new { id = acc.AccountID }, "http")));

                    await Global.Server.GhostChanSay(GlobalConst.ModeratorChannel, string.Format(" - reason: {0} ", reason));

                    await Global.Server.GhostPm(acc.Name, string.Format("Your account has received moderator action, reason: {0}", reason));

                    if (banLobby == true)
                    {
                        await Global.Server.KickFromServer(Global.Account.Name, acc.Name, reason);

                        pmAction += "Lobby banned, ";
                    }
                    if (banMute == true)
                    {
                        await Global.Server.PublishAccountUpdate(acc);

                        pmAction += "Muted, ";
                    }
                    if (banForum == true)
                    {
                        pmAction += "Forum banned, ";
                    }
                    if (banSpecChat == true)
                    {
                        pmAction += "Spectator all-chat muted, ";
                    }
                    if (banVotes == true)
                    {
                        pmAction += "Vote powers restricted, ";
                    }
                    if (banCommanders == true)
                    {
                        pmAction += "Custom commanders restricted, ";
                    }
                    if (banSite == true)
                    {
                        pmAction += "Site banned, ";
                    }

                    if (activePenalty)
                    {
                        pmAction = pmAction.Substring(0, Math.Max(0, pmAction.Length - 2)); // removes trailing comma and space
                        await Global.Server.GhostPm(acc.Name, string.Format("Action taken: {0}", pmAction));

                        await Global.Server.GhostPm(acc.Name, string.Format("Total duration: {0} hours", banHours));

                        await Global.Server.GhostChanSay(GlobalConst.ModeratorChannel, string.Format(" - duration: {0}h ", banHours));

                        await Global.Server.GhostChanSay(GlobalConst.ModeratorChannel, string.Format(" - penalty type: {0}", pmAction));
                    }
                    else
                    {
                        await Global.Server.GhostPm(acc.Name, "Action taken: Warning");

                        await Global.Server.GhostChanSay(GlobalConst.ModeratorChannel, " - penalty type: Warning");
                    }
                }
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());
                await Global.Server.GhostChanSay(GlobalConst.ModeratorChannel, ex.ToString());
            }
            return(RedirectToAction("Detail", new { id = accountID }));
        }
        /*
         * public static void Test1v1Elo()
         * {
         *  var db = new ZkDataContext();
         *  Dictionary<Account, EloEntry> PlayerElo = new Dictionary<Account, EloEntry>();
         *
         *  int cnt = 0;
         *  foreach (var sb in db.SpringBattles.Where(x => !x.IsMission && !x.HasBots && x.PlayerCount == 2).OrderBy(x => x.SpringBattleID))
         *  {
         *      cnt++;
         *
         *      double winnerElo = 0;
         *      double loserElo = 0;
         *
         *      var losers = sb.SpringBattlePlayers.Where(x => !x.IsSpectator && !x.IsInVictoryTeam).Select(x => new { Player = x, x.Account }).ToList();
         *      var winners = sb.SpringBattlePlayers.Where(x => !x.IsSpectator && x.IsInVictoryTeam).Select(x => new { Player = x, x.Account }).ToList();
         *
         *      if (losers.Count != 1 || winners.Count != 1)
         *      {
         *          continue;
         *      }
         *
         *      foreach (var r in winners)
         *      {
         *          EloEntry el;
         *          if (!PlayerElo.TryGetValue(r.Account, out el)) el = new EloEntry();
         *          winnerElo += el.Elo;
         *      }
         *      foreach (var r in losers)
         *      {
         *          EloEntry el;
         *          if (!PlayerElo.TryGetValue(r.Account, out el)) el = new EloEntry();
         *          loserElo += el.Elo;
         *      }
         *
         *      winnerElo = winnerElo / winners.Count;
         *      loserElo = loserElo / losers.Count;
         *
         *      var eWin = 1 / (1 + Math.Pow(10, (loserElo - winnerElo) / 400));
         *      var eLose = 1 / (1 + Math.Pow(10, (winnerElo - loserElo) / 400));
         *
         *      var sumCount = losers.Count + winners.Count;
         *      var scoreWin = Math.Sqrt(sumCount / 2.0) * 32 * (1 - eWin);
         *      var scoreLose = Math.Sqrt(sumCount / 2.0) * 32 * (0 - eLose);
         *
         *      foreach (var r in winners)
         *      {
         *          var change = (float)(scoreWin);
         *          EloEntry elo;
         *          if (!PlayerElo.TryGetValue(r.Account, out elo))
         *          {
         *              elo = new EloEntry();
         *              PlayerElo[r.Account] = elo;
         *          }
         *          elo.Elo += change;
         *          elo.Cnt++;
         *      }
         *
         *      foreach (var r in losers)
         *      {
         *          var change = (float)(scoreLose);
         *          EloEntry elo;
         *          if (!PlayerElo.TryGetValue(r.Account, out elo))
         *          {
         *              elo = new EloEntry();
         *              PlayerElo[r.Account] = elo;
         *          }
         *          elo.Elo += change;
         *          elo.Cnt++;
         *      }
         *  }
         *
         *
         *  Console.WriteLine("Total battles: {0}", cnt);
         *  Console.WriteLine("Name;1v1Elo;TeamElo;1v1Played;TeamPlayed");
         *  foreach (var entry in PlayerElo.Where(x => x.Value.Cnt > 40).OrderByDescending(x => x.Value.Elo))
         *  {
         *      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));
         *  }
         *
         * }*/

        /*
         * public static void TestPrediction()
         * {
         *  var db = new ZkDataContext();
         *  var cnt = 0;
         *  var winPro = 0;
         *  var winLessNub = 0;
         *  var winMoreVaried = 0;
         *  var winPredicted = 0;
         *
         *
         *  foreach (var sb in db.SpringBattles.Where(x => !x.IsMission && !x.HasBots && x.IsEloProcessed && x.PlayerCount >= 8 && !x.Events.Any()).OrderByDescending(x => x.SpringBattleID))
         *  {
         *
         *      var losers = sb.SpringBattlePlayers.Where(x => !x.IsSpectator && !x.IsInVictoryTeam).Select(x => new { Player = x, x.Account }).ToList();
         *      var winners = sb.SpringBattlePlayers.Where(x => !x.IsSpectator && x.IsInVictoryTeam).Select(x => new { Player = x, x.Account }).ToList();
         *
         *      if (losers.Count == 0 || winners.Count == 0 || losers.Count == winners.Count) continue;
         *
         *      if (winners.Select(x => x.Account.EffectiveElo).Max() > losers.Select(x => x.Account.EffectiveElo).Max()) winPro++;
         *      if (winners.Select(x => x.Account.EffectiveElo).Min() > losers.Select(x => x.Account.EffectiveElo).Min()) winLessNub++;
         *
         *      if (winners.Select(x => x.Account.EffectiveElo).StdDev() > losers.Select(x => x.Account.EffectiveElo).StdDev()) winMoreVaried++;
         *
         *      var winnerElo = winners.Select(x => x.Account.EffectiveElo).Average();
         *      var loserElo = losers.Select(x => x.Account.EffectiveElo).Average();
         *
         *      var eWin = 1 / (1 + Math.Pow(10, (loserElo - winnerElo) / 400));
         *      var eLose = 1 / (1 + Math.Pow(10, (winnerElo - loserElo) / 400));
         *
         *      if (eWin > eLose) winPredicted++;
         *
         *
         *      cnt++;
         *      if (cnt == 200) break;
         *  }
         *
         *  Console.WriteLine("prwin: {0},  lessnubwin: {1},  morevaried: {2},  count: {3}, predicted:{4}", winPro, winLessNub, winMoreVaried, cnt, winPredicted);
         * }
         *
         * static void RecalculateBattleElo()
         * {
         *  using (var db = new ZkDataContext())
         *  {
         *      foreach (var b in db.SpringBattles.Where(x => !x.IsEloProcessed).ToList())
         *      {
         *          Console.WriteLine(b.SpringBattleID);
         *          b.CalculateAllElo();
         *      }
         *      db.SaveChanges();
         *  }
         * }
         *
         * static void ImportSpringiePlayers()
         * {
         *  var db = new ZkDataContext();
         *  foreach (var line in File.ReadLines("springie.csv").AsParallel())
         *  {
         *      var m = Regex.Match(line, "\"[0-9]+\";\"([^\"]+)\";\"[0-9]+\";\"[0-9]+\";\"([^\"]+)\";\"([^\"]+)\"");
         *      if (m.Success)
         *      {
         *          string name = m.Groups[1].Value;
         *          double elo = double.Parse(m.Groups[2].Value, CultureInfo.InvariantCulture);
         *          double w = double.Parse(m.Groups[3].Value, CultureInfo.InvariantCulture);
         *          if (elo != 1500 || w != 1)
         *          {
         *              foreach (var a in db.Accounts.Where(x => x.Name == name))
         *              {
         *                  a.Elo = (float)elo;
         *                  a.EloWeight = (float)w;
         *              }
         *              Console.WriteLine(name);
         *          }
         *      }
         *  }
         *  db.SaveChanges();
         * }*/

        static void FixMaps()
        {
            try
            {
                var db = new ZkDataContext();
                foreach (var r in db.Resources.Where(x => x.LastChange == null))
                {
                    r.LastChange = DateTime.UtcNow;
                }
                db.SaveChanges();
                return;

                foreach (var resource in db.Resources.Where(x => x.TypeID == ResourceType.Map))//&&x.MapSizeSquared == null))
                {
                    var file = String.Format("{0}/{1}.metadata.xml.gz", GlobalConst.SiteDiskPath + @"\Resources", resource.InternalName.EscapePath());
                    var map  = (Map) new XmlSerializer(typeof(Map)).Deserialize(new MemoryStream(File.ReadAllBytes(file).Decompress()));

                    resource.MapWidth  = map.Size.Width / 512;
                    resource.MapHeight = map.Size.Height / 512;

                    if (string.IsNullOrEmpty(resource.AuthorName))
                    {
                        if (!string.IsNullOrEmpty(map.Author))
                        {
                            resource.AuthorName = map.Author;
                        }
                        else
                        {
                            Console.WriteLine("regex test");
                            var m = Regex.Match(map.Description, "by ([\\w]+)", RegexOptions.IgnoreCase);
                            if (m.Success)
                            {
                                resource.AuthorName = m.Groups[1].Value;
                            }
                        }
                    }
                    Console.WriteLine("author: " + resource.AuthorName);


                    if (resource.MapIsSpecial == null)
                    {
                        resource.MapIsSpecial = map.ExtractorRadius > 120 || map.MaxWind > 40;
                    }
                    resource.MapSizeSquared = (map.Size.Width / 512) * (map.Size.Height / 512);
                    resource.MapSizeRatio   = (float)map.Size.Width / map.Size.Height;

                    var minimap = String.Format("{0}/{1}.minimap.jpg", GlobalConst.SiteDiskPath + @"\Resources", resource.InternalName.EscapePath());

                    using (var im = Image.FromFile(minimap))
                    {
                        int w, h;

                        if (resource.MapSizeRatio > 1)
                        {
                            w = 96;
                            h = (int)(w / resource.MapSizeRatio);
                        }
                        else
                        {
                            h = 96;
                            w = (int)(h * resource.MapSizeRatio);
                        }

                        using (var correctMinimap = new Bitmap(w, h, PixelFormat.Format24bppRgb))
                        {
                            using (var graphics = Graphics.FromImage(correctMinimap))
                            {
                                graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
                                graphics.DrawImage(im, 0, 0, w, h);
                            }

                            var jgpEncoder    = ImageCodecInfo.GetImageEncoders().First(x => x.FormatID == ImageFormat.Jpeg.Guid);
                            var encoderParams = new EncoderParameters(1);
                            encoderParams.Param[0] = new EncoderParameter(Encoder.Quality, 100L);

                            var target = String.Format("{0}/{1}.thumbnail.jpg", GlobalConst.SiteDiskPath + @"\Resources", resource.InternalName.EscapePath());
                            correctMinimap.Save(target, jgpEncoder, encoderParams);
                        }
                    }
                    Console.WriteLine(string.Format("{0}", resource.InternalName));
                }
                db.SaveChanges();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        }
Beispiel #17
0
        public async Task <RegisterResponse> DoRegister(Register register, string ip)
        {
            if (!Account.IsValidLobbyName(register.Name))
            {
                return(new RegisterResponse(RegisterResponse.Code.NameHasInvalidCharacters));
            }

            if (server.ConnectedUsers.ContainsKey(register.Name))
            {
                return(new RegisterResponse(RegisterResponse.Code.AlreadyConnected));
            }

            if (string.IsNullOrEmpty(register.PasswordHash) && string.IsNullOrEmpty(register.SteamAuthToken))
            {
                return(new RegisterResponse(RegisterResponse.Code.MissingBothPasswordAndToken));
            }

            if (!VerifyIp(ip))
            {
                return(new RegisterResponse(RegisterResponse.Code.BannedTooManyAttempts));
            }

            var banPenalty = Punishment.GetActivePunishment(null, ip, register.UserID, x => x.BanLobby);

            if (banPenalty != null)
            {
                return new RegisterResponse(RegisterResponse.Code.Banned)
                       {
                           BanReason = banPenalty.Reason
                       }
            }
            ;

            SteamWebApi.PlayerInfo info = null;
            if (!string.IsNullOrEmpty(register.SteamAuthToken))
            {
                info = await server.SteamWebApi.VerifyAndGetAccountInformation(register.SteamAuthToken);

                if (info == null)
                {
                    return(new RegisterResponse(RegisterResponse.Code.InvalidSteamToken));
                }
            }

            using (var db = new ZkDataContext())
            {
                var registerName   = register.Name.ToUpper();
                var existingByName = db.Accounts.FirstOrDefault(x => x.Name.ToUpper() == registerName);
                if (existingByName != null)
                {
                    if (info != null && existingByName.SteamID == info.steamid)
                    {
                        return(new RegisterResponse(RegisterResponse.Code.AlreadyRegisteredWithThisSteamToken));
                    }

                    if (info == null && !string.IsNullOrEmpty(register.PasswordHash) && existingByName.VerifyPassword(register.PasswordHash))
                    {
                        return(new RegisterResponse(RegisterResponse.Code.AlreadyRegisteredWithThisPassword));
                    }

                    return(new RegisterResponse(RegisterResponse.Code.NameAlreadyTaken));
                }

                var acc = new Account()
                {
                    Name = register.Name
                };
                acc.SetPasswordHashed(register.PasswordHash);
                acc.SetName(register.Name);
                acc.SetAvatar();
                acc.Email = register.Email;
                if (info != null)
                {
                    var existingBySteam = db.Accounts.FirstOrDefault(x => x.SteamID == info.steamid);
                    if (existingBySteam != null)
                    {
                        return(new RegisterResponse(RegisterResponse.Code.SteamAlreadyRegistered));
                    }

                    acc.SteamID   = info.steamid;
                    acc.SteamName = info.personaname;
                }
                else if (string.IsNullOrEmpty(register.PasswordHash))
                {
                    return(new RegisterResponse(RegisterResponse.Code.InvalidPassword));
                }
                LogIP(db, acc, ip);
                LogUserID(db, acc, register.UserID);
                db.Accounts.Add(acc);
                db.SaveChanges();
            }
            return(new RegisterResponse(RegisterResponse.Code.Ok));
        }
        public void UpdateRatings()
        {
            if (!RatingSystems.Initialized)
            {
                return;
            }
            if (latestBattle == null)
            {
                //Trace.TraceInformation("WHR " + category +": No battles to evaluate");
                return;
            }
            lock (updateLock)
            {
                Action updateAction = null;
                if (lastUpdate == null)
                {
                    updateAction = (() =>
                    {
                        Trace.TraceInformation("Initializing WHR " + category + " ratings for " + battlesRegistered + " battles, this will take some time.. From B" + firstBattle?.SpringBattleID + " to B" + latestBattle?.SpringBattleID);
                        runIterations(75);
                        UpdateRankings(players.Values);
                        playerOldRatings = new Dictionary <int, PlayerRating>(playerRatings);
                    });
                }
                else if (DateTime.UtcNow.Subtract(lastUpdateTime).TotalHours >= GlobalConst.LadderUpdatePeriod)
                {
                    updateAction = (() =>
                    {
                        Trace.TraceInformation("Updating all WHR " + category + " ratings");
                        runIterations(1);
                        UpdateRankings(players.Values);
                    });
                    lastUpdateTime = DateTime.UtcNow;
                }
                else if (!latestBattle.Equals(lastUpdate))
                {
                    updateAction = (() =>
                    {
                        Trace.TraceInformation("Updating WHR " + category + " ratings for last Battle: " + latestBattle.SpringBattleID);
                        IEnumerable <Player> players = latestBattle.SpringBattlePlayers.Where(p => !p.IsSpectator).Select(p => getPlayerById(RatingSystems.GetRatingId(p.AccountID)));
                        players.ForEach(p => p.runOneNewtonIteration());
                        players.ForEach(p => p.updateUncertainty());
                        UpdateRankings(players);
                    });
                }
                else
                {
                    //Trace.TraceInformation("No WHR " + category +" ratings to update");
                    return;
                }
                var lastUpdateEx = lastUpdate;
                Task.Factory.StartNew(() =>
                {
                    try
                    {
                        lock (updateLockInternal)
                        {
                            DateTime start = DateTime.Now;
                            updateAction.Invoke();
                            Trace.TraceInformation("WHR " + category + " Ratings updated in " + DateTime.Now.Subtract(start).TotalSeconds + " seconds, " + (GC.GetTotalMemory(false) / (1 << 20)) + "MiB total memory allocated");

                            IEnumerable <Account> updatedRanks = new List <Account>();
                            using (var db = new ZkDataContext())
                            {
                                var lastBattlePlayers = db.SpringBattlePlayers.Where(p => p.SpringBattleID == latestBattle.SpringBattleID && !p.IsSpectator).Include(x => x.Account).ToList();
                                if (latestBattle.GetRatingCategory() == category && lastBattleRanked)
                                {
                                    lastBattleRanked = false;
                                    lastBattlePlayers.Where(p => playerOldRatings.ContainsKey(RatingSystems.GetRatingId(p.AccountID)) && !p.EloChange.HasValue).ForEach(p =>
                                    {
                                        p.EloChange = playerRatings[RatingSystems.GetRatingId(p.AccountID)].RealElo - playerOldRatings[RatingSystems.GetRatingId(p.AccountID)].RealElo;
                                    });
                                    updatedRanks = lastBattlePlayers.Where(p => Ranks.UpdateRank(p.Account, p.IsInVictoryTeam, !p.IsInVictoryTeam, db)).Select(x => x.Account).ToList();
                                    updatedRanks.ForEach(p => db.Entry(p).State = EntityState.Modified);
                                }
                                db.SpringBattlePlayers.Where(p => p.SpringBattleID == latestBattle.SpringBattleID && !p.IsSpectator).ToList().ForEach(x => playerOldRatings[RatingSystems.GetRatingId(x.AccountID)] = playerRatings[RatingSystems.GetRatingId(x.AccountID)]);
                                db.SaveChanges();
                            }
                            RatingsUpdated(this, new RatingUpdate()
                            {
                                affectedPlayers = updatedRanks.Select(p => RatingSystems.GetRatingId(p.AccountID))
                            });
                        }
                    }
                    catch (Exception ex)
                    {
                        Trace.TraceError("Thread error while updating WHR " + category + " " + ex);
                    }
                }, CancellationToken.None, TaskCreationOptions.None, PriorityScheduler.BelowNormal);
                lastUpdate = latestBattle;
            }
        }
Beispiel #19
0
        //private


        //Runs in O(N log(N)) for all players
        private void UpdateRankings(IEnumerable <Player> players)
        {
            try
            {
                int currentDay = RatingSystems.ConvertDateToDays(DateTime.UtcNow);
                foreach (var p in players)
                {
                    if (p.days.Count == 0)
                    {
                        Trace.TraceError("WHR " + category + " has invalid player " + p.id + " with no days(games)");
                        continue;
                    }
                    float elo             = p.days.Last().getElo() + RatingOffset;
                    float lastUncertainty = p.days.Last().uncertainty * 100;
                    int   lastDay         = p.days.Last().day;
                    playerRatings[p.id] = new PlayerRating(int.MaxValue, 1, elo, lastUncertainty, lastDay, currentDay);
                    float rating = -playerRatings[p.id].Elo + 0.001f * (float)rand.NextDouble();
                    if (playerKeys.ContainsKey(p.id))
                    {
                        sortedPlayers.Remove(playerKeys[p.id]);
                    }
                    playerKeys[p.id]      = rating;
                    sortedPlayers[rating] = p.id;
                }
                float[] playerUncertainties = new float[playerRatings.Count];
                int     index = 0;
                float   DynamicMaxUncertainty = GlobalConst.MinimumDynamicMaxLadderUncertainty;
                int     maxAge = GlobalConst.LadderActivityDays;
                foreach (var pair in playerRatings)
                {
                    if (currentDay - pair.Value.LastGameDate > maxAge)
                    {
                        playerUncertainties[index++] = 9999 + index; //don't use infinity because i'm doing shady floating point things
                    }
                    else
                    {
                        playerUncertainties[index++] = (float)pair.Value.Uncertainty;
                    }
                }
                Array.Sort(playerUncertainties);
                DynamicMaxUncertainty = Math.Max(DynamicMaxUncertainty, playerUncertainties[Math.Min(playerUncertainties.Length, GlobalConst.LadderSize) - 1] + 0.01f);
                int          activePlayers         = Math.Max(1, ~Array.BinarySearch(playerUncertainties, DynamicMaxUncertainty));
                int          rank                  = 0;
                List <int>   newTopPlayers         = new List <int>();
                int          matched               = 0;
                List <float> newPercentileBrackets = new List <float>();
                newPercentileBrackets.Add(3000);
                float   percentile;
                float[] percentilesRev = Ranks.Percentiles.Reverse().ToArray();
                foreach (var pair in sortedPlayers)
                {
                    if (playerRatings[pair.Value].Uncertainty <= DynamicMaxUncertainty && currentDay - playerRatings[pair.Value].LastGameDate <= maxAge)
                    {
                        newTopPlayers.Add(pair.Value);
                        if (rank == matched && rank < topPlayers.Count && topPlayers[rank] == pair.Value)
                        {
                            matched++;
                        }
                        rank++;
                        percentile = (float)rank / activePlayers;
                        if (newPercentileBrackets.Count <= Ranks.Percentiles.Length && percentile > percentilesRev[newPercentileBrackets.Count - 1])
                        {
                            newPercentileBrackets.Add(playerRatings[pair.Value].Elo);
                        }
                        playerRatings[pair.Value].ApplyLadderUpdate(rank, percentile, currentDay);
                    }
                    else if (playerRatings[pair.Value].Rank < int.MaxValue)
                    {
                        playerRatings[pair.Value].ApplyLadderUpdate(int.MaxValue, 1, currentDay);
                    }
                }
                this.activePlayers = rank;
                newPercentileBrackets.Add(0);
                PercentileBrackets = newPercentileBrackets.Select(x => x).Reverse().ToArray();
                topPlayers         = newTopPlayers;
                laddersCache       = new List <Account>();
                Trace.TraceInformation("WHR " + category + " Ladders updated with " + topPlayers.Count + "/" + this.players.Count + " entries, max uncertainty selected: " + DynamicMaxUncertainty + " brackets are now: " + string.Join(", ", PercentileBrackets));

                var playerIds = players.Select(x => x.id).ToList();
                if (playerIds.Count() < 100)
                {
                    SaveToDB(playerIds);
                }
                else
                {
                    SaveToDB();
                }

                //check for rank updates
                using (var db = new ZkDataContext())
                {
                    var lastBattlePlayers = db.SpringBattlePlayers.Where(p => p.SpringBattleID == latestBattle.SpringBattleID && !p.IsSpectator).Include(x => x.Account).ToList();
                    if (latestBattle.GetRatingCategory() == category && lastBattleRanked)
                    {
                        lastBattleRanked = false;
                        lastBattlePlayers.Where(p => playerOldRatings.ContainsKey(RatingSystems.GetRatingId(p.AccountID)) && !p.EloChange.HasValue).ForEach(p =>
                        {
                            p.EloChange = playerRatings[RatingSystems.GetRatingId(p.AccountID)].RealElo - playerOldRatings[RatingSystems.GetRatingId(p.AccountID)].RealElo;
                        });
                        var updatedRanks = lastBattlePlayers.Where(p => Ranks.UpdateRank(p.Account, p.IsInVictoryTeam, !p.IsInVictoryTeam, db)).Select(x => x.Account).ToList();
                        updatedRanks.ForEach(p => db.Entry(p).State = EntityState.Modified);
                        RatingsUpdated(this, new RatingUpdate()
                        {
                            affectedPlayers = lastBattlePlayers.Select(x => x.AccountID)
                        });
                    }
                    db.SpringBattlePlayers.Where(p => p.SpringBattleID == latestBattle.SpringBattleID && !p.IsSpectator).ToList().ForEach(x => playerOldRatings[RatingSystems.GetRatingId(x.AccountID)] = playerRatings[RatingSystems.GetRatingId(x.AccountID)]);
                    db.SaveChanges();
                }


                //check for topX updates
                GetTopPlayers(GlobalConst.LadderSize);
                foreach (var listener in topPlayersUpdateListeners)
                {
                    if (matched < listener.Value)
                    {
                        listener.Key.TopPlayersUpdated(GetTopPlayers(listener.Value));
                    }
                }
            }
            catch (Exception ex)
            {
                string dbg = "WHR " + category + ": Failed to update rankings " + ex + "\nPlayers: ";
                foreach (var p in players)
                {
                    dbg += p.id + " (" + p.days.Count + " days), ";
                }
                Trace.TraceError(dbg);
            }
        }
Beispiel #20
0
        /// <summary>
        /// Create or modify a PlanetWars <see cref="FactionTreaty"/>
        /// </summary>
        /// <param name="factionTreatyID">Existing <see cref="FactionTreaty"/> ID, if modifying one</param>
        /// <param name="turns">How long the treaty lasts</param>
        /// <param name="acceptingFactionID"></param>
        /// <param name="effectTypeID"><see cref="TreatyEffect"/> to add or remove, if applicable</param>
        /// <param name="effectValue"></param>
        /// <param name="planetID">Specifies the <see cref="Planet"/> for planet-based effects</param>
        /// <param name="isReverse"></param>
        /// <param name="note">Diplomatic note readable by both parties, to better communicate their intentions</param>
        /// <param name="add">If not null or empty, add the specified <see cref="TreatyEffect"/></param>
        /// <param name="delete">Delete the specified <see cref="TreatyEffect"/>?</param>
        /// <param name="propose">If not null or empty, this is a newly proposed treaty</param>
        /// <returns></returns>
        public ActionResult ModifyTreaty(int factionTreatyID,
                                         int?turns,
                                         int?acceptingFactionID,
                                         int?effectTypeID,
                                         double?effectValue,
                                         int?planetID,
                                         bool?isReverse,
                                         string note,
                                         string add, int?delete, string propose)
        {
            if (!Global.Account.HasFactionRight(x => x.RightDiplomacy))
            {
                return(Content("Not a diplomat!"));
            }

            FactionTreaty treaty;

            // submit, store treaty in db
            var db = new ZkDataContext();

            if (factionTreatyID > 0)
            {
                treaty = db.FactionTreaties.Single(x => x.FactionTreatyID == factionTreatyID);
                if (treaty.TreatyState != TreatyState.Invalid)
                {
                    return(Content("Treaty already in progress!"));
                }
            }
            else
            {
                treaty = new FactionTreaty();
                db.FactionTreaties.InsertOnSubmit(treaty);
                treaty.FactionByAcceptingFactionID = db.Factions.Single(x => x.FactionID == acceptingFactionID);
            }
            treaty.AccountByProposingAccountID = db.Accounts.Find(Global.AccountID);
            treaty.FactionByProposingFactionID = db.Factions.Single(x => x.FactionID == Global.FactionID);
            treaty.TurnsRemaining = turns;
            treaty.TurnsTotal     = turns;
            treaty.TreatyNote     = note;


            if (!string.IsNullOrEmpty(add))
            {
                TreatyEffectType effectType = db.TreatyEffectTypes.Single(x => x.EffectTypeID == effectTypeID);
                var effect = new TreatyEffect
                {
                    FactionByGivingFactionID    = isReverse == true ? treaty.FactionByAcceptingFactionID : treaty.FactionByProposingFactionID,
                    FactionByReceivingFactionID =
                        isReverse == true ? treaty.FactionByProposingFactionID : treaty.FactionByAcceptingFactionID,
                    TreatyEffectType = effectType,
                    FactionTreaty    = treaty
                };
                if (effectType.HasValue)
                {
                    if (effectType.MinValue.HasValue && effectValue < effectType.MinValue.Value)
                    {
                        effectValue = effectType.MinValue;
                    }
                    if (effectType.MaxValue.HasValue && effectValue > effectType.MaxValue.Value)
                    {
                        effectValue = effectType.MaxValue;
                    }
                }
                if (effectType.HasValue)
                {
                    effect.Value = effectValue;
                }
                if (effectType.IsPlanetBased)
                {
                    effect.PlanetID = planetID.Value;
                }
                db.TreatyEffects.InsertOnSubmit(effect);
            }
            if (delete != null)
            {
                db.TreatyEffects.DeleteOnSubmit(db.TreatyEffects.Single(x => x.TreatyEffectID == delete));
            }
            db.SaveChanges();

            if (!string.IsNullOrEmpty(propose))
            {
                treaty.TreatyState = TreatyState.Proposed;

                db.Events.InsertOnSubmit(PlanetwarsEventCreator.CreateEvent("{0} proposes a new treaty between {1} and {2} - {3}", treaty.AccountByProposingAccountID, treaty.FactionByProposingFactionID, treaty.FactionByAcceptingFactionID, treaty));

                db.SaveChanges();
                return(RedirectToAction("Detail", new { id = treaty.ProposingFactionID }));
            }


            return(View("FactionTreatyDefinition", db.FactionTreaties.Find(treaty.FactionTreatyID)));
        }
        /// <summary>
        ///     Go to a specific <see cref="ForumThread" />
        /// </summary>
        /// <param name="lastPost">Go to last post</param>
        /// <param name="lastSeen">UNUSED</param>
        /// <param name="postID">A specific <see cref="ForumPost" /> ID to go to</param>
        /// <returns></returns>
        public ActionResult Thread(int?id, int?postID)
        {
            if (id == null)
            {
                if (postID == null)
                {
                    return(RedirectToAction("Index"));
                }
                else
                {
                    return(RedirectToAction("Post", new { id = postID }));
                }
            }

            var db = new ZkDataContext();
            var t  = db.ForumThreads.FirstOrDefault(x => x.ForumThreadID == id);

            // TODO - indicate thread has been deleted
            if (t == null)
            {
                return(RedirectToAction("Index"));
            }


            var cat = t.ForumCategory;

            if (cat != null)
            {
                if (cat.ForumMode == ForumMode.Missions && t.Missions.Any())
                {
                    return(RedirectToAction("Detail", "Missions", new { id = t.Missions.First().MissionID }));
                }
                if (cat.ForumMode == ForumMode.Maps && t.Resources.Any())
                {
                    return(RedirectToAction("Detail", "Maps", new { id = t.Resources.First().ResourceID }));
                }
                if (cat.ForumMode == ForumMode.SpringBattles && t.SpringBattles.Any())
                {
                    return(RedirectToAction("Detail", "Battles", new { id = t.SpringBattles.First().SpringBattleID }));
                }
                if (cat.ForumMode == ForumMode.Clans && t.Clan != null)
                {
                    return(RedirectToAction("Detail", "Clans", new { id = t.RestrictedClanID }));
                }
                if (cat.ForumMode == ForumMode.Planets && t.Planets.Any())
                {
                    return(RedirectToAction("Planet", "Planetwars", new { id = t.Planets.First().PlanetID }));
                }
            }

            var res = new ThreadResult();

            res.GoToPost = postID ?? t.UpdateLastRead(Global.AccountID, false);

            db.SaveChanges();

            res.Path          = cat?.GetPath() ?? new List <ForumCategory>();
            res.CurrentThread = t;

            return(View(res));
        }
        public LoginResponse Login(User user, Login login, Client client)
        {
            string ip           = client.RemoteEndpointIP;
            long   userID       = login.UserID;
            string lobbyVersion = login.LobbyVersion;

            using (var db = new ZkDataContext()) {
                Account acc = db.Accounts.Include(x => x.Clan).Include(x => x.Faction).FirstOrDefault(x => x.Name == login.Name);
                if (acc == null)
                {
                    return new LoginResponse {
                               ResultCode = LoginResponse.Code.InvalidName
                    }
                }
                ;
                if (!acc.VerifyPassword(login.PasswordHash))
                {
                    return new LoginResponse {
                               ResultCode = LoginResponse.Code.InvalidPassword
                    }
                }
                ;
                if (state.Clients.ContainsKey(login.Name))
                {
                    return new LoginResponse {
                               ResultCode = LoginResponse.Code.AlreadyConnected
                    }
                }
                ;

                acc.Country      = ResolveCountry(ip);
                acc.LobbyVersion = lobbyVersion;
                acc.LastLogin    = DateTime.UtcNow;

                user.ClientType   = login.ClientType;
                user.LobbyVersion = login.LobbyVersion;
                UpdateUserFromAccount(user, acc);

                LogIP(db, acc, ip);

                LogUserID(db, acc, userID);

                db.SaveChanges();


                var banMute = Punishment.GetActivePunishment(acc.AccountID, ip, userID, x => x.BanMute, db);
                if (banMute != null)
                {
                    user.BanMute = true;
                }


                Punishment banPenalty = Punishment.GetActivePunishment(acc.AccountID, ip, userID, x => x.BanLobby, db);

                if (banPenalty != null)
                {
                    return
                        (BlockLogin(
                             string.Format("Banned until {0} (match to {1}), reason: {2}", banPenalty.BanExpires, banPenalty.AccountByAccountID.Name,
                                           banPenalty.Reason), acc, ip, userID));
                }

                Account accAnteep = db.Accounts.FirstOrDefault(x => x.AccountID == 4490);
                if (accAnteep != null)
                {
                    if (accAnteep.AccountUserIDs.Any(y => y.UserID == userID))
                    {
                        Talk(String.Format("Suspected Anteep smurf: {0} (ID match {1}) {2}", acc.Name, userID,
                                           string.Format("{1}/Users/Detail/{0}", acc.AccountID, GlobalConst.BaseSiteUrl)));
                    }

                    if (userID > 0 && userID < 1000)
                    {
                        Talk(String.Format("Suspected Anteep smurf: {0} (too short userID {1}) {2}", acc.Name, userID,
                                           string.Format("{1}/Users/Detail/{0}", acc.AccountID, GlobalConst.BaseSiteUrl)));
                    }

                    if (accAnteep.AccountIPs.Any(y => y.IP == ip))
                    {
                        Talk(String.Format("Suspected Anteep smurf: {0} (IP match {1}) {2}", acc.Name, ip,
                                           string.Format("{1}/Users/Detail/{0}", acc.AccountID, GlobalConst.BaseSiteUrl)));
                    }
                }

                if (!acc.HasVpnException && GlobalConst.VpnCheckEnabled)
                {
                    // check user IP against http://dnsbl.tornevall.org
                    // does not catch all smurfs
                    // mostly false positives, do not use
                    string reversedIP = string.Join(".", ip.Split('.').Reverse().ToArray());
                    try {
                        IPAddress[] resolved = Dns.GetHostEntry(string.Format("{0}.dnsbl.tornevall.org", reversedIP)).AddressList;
                        if (resolved.Length > 0)
                        {
                            Talk(String.Format("User {0} {3} has IP {1} on dnsbl.tornevall.org ({2} result/s)", acc.Name, ip, resolved.Length,
                                               string.Format("{1}/Users/Detail/{0}", acc.AccountID, GlobalConst.BaseSiteUrl)));
                        }
                    } catch (SocketException sockEx) {
                        // not in database, do nothing
                    }
                }

                try {
                    if (!acc.HasVpnException)
                    {
                        for (int i = 0; i <= 1; i++)
                        {
                            var whois = new Whois();
                            Dictionary <string, string> data = whois.QueryByIp(ip, i == 1);

                            if (!data.ContainsKey("netname"))
                            {
                                data["netname"] = "UNKNOWN NETNAME";
                            }
                            if (!data.ContainsKey("org-name"))
                            {
                                data["org-name"] = "UNKNOWN ORG";
                            }
                            if (!data.ContainsKey("abuse-mailbox"))
                            {
                                data["abuse-mailbox"] = "no mailbox";
                            }
                            if (!data.ContainsKey("notify"))
                            {
                                data["notify"] = "no notify address";
                            }
                            if (!data.ContainsKey("role"))
                            {
                                data["role"] = "UNKNOWN ROLE";
                            }
                            if (!data.ContainsKey("descr"))
                            {
                                data["descr"] = "no description";
                            }
                            if (!data.ContainsKey("remarks"))
                            {
                                data["remarks"] = "no remarks";
                            }

                            List <string> blockedCompanies = db.BlockedCompanies.Select(x => x.CompanyName.ToLower()).ToList();
                            List <string> blockedHosts     = db.BlockedHosts.Select(x => x.HostName).ToList();

                            /*if (acc.Country == "MY")
                             * {
                             * client.Say(SayPlace.User, "KingRaptor", String.Format("USER {0}\nnetname: {1}\norgname: {2}\ndescr: {3}\nabuse-mailbox: {4}",
                             *  acc.Name, data["netname"], data["org-name"], data["descr"], data["abuse-mailbox"]), false);
                             * }*/

                            bool blockedHost = blockedHosts.Any(x => data["abuse-mailbox"].Contains(x)) ||
                                               (blockedHosts.Any(x => data["notify"].Contains(x)));

                            foreach (string company in blockedCompanies)
                            {
                                if (data["netname"].ToLower().Contains(company) || data["org-name"].ToLower().Contains(company) ||
                                    data["descr"].ToLower().Contains(company) || data["role"].ToLower().Contains(company) ||
                                    data["remarks"].ToLower().Contains(company))
                                {
                                    blockedHost = true;
                                    break;
                                }
                            }

                            string hostname = Dns.GetHostEntry(ip).HostName;
                            if (blockedHosts.Any(hostname.Contains))
                            {
                                blockedHost = true;
                            }

                            if (blockedHost)
                            {
                                return(BlockLogin("Connection using proxy or VPN is not allowed! (You can ask for exception)", acc, ip, userID));
                            }
                        }
                    }
                } catch (SocketException sockEx) {} catch (Exception ex) {
                    Trace.TraceError("VPN check error: {0}", ex);
                }

                if (state.Clients.TryAdd(login.Name, client))
                {
                    return new LoginResponse {
                               ResultCode = LoginResponse.Code.Ok
                    }
                }
                ;
                else
                {
                    return new LoginResponse()
                           {
                               ResultCode = LoginResponse.Code.AlreadyConnected
                           }
                };
            }
        }

        string ResolveCountry(string ip)
        {
            if (IsLanIP(ip))
            {
                return("CZ");
            }
            else
            {
                try {
                    return(geoIP.Country(ip).Country.IsoCode);
                } catch (Exception ex) {
                    Trace.TraceWarning("{0} Unable to resolve country", this);
                    return("??");
                }
            }
        }

        LoginResponse BlockLogin(string reason, Account acc, string ip, long user_id)
        {
            Talk(string.Format("Login denied for {0} IP:{1} ID:{2} reason: {3}", acc.Name, ip, user_id, reason));
            return(new LoginResponse {
                Reason = reason, ResultCode = LoginResponse.Code.Banned
            });
        }
    public static void EndTurn(string mapName, List <string> extraData, ZkDataContext db, int?winNum, List <Account> players, StringBuilder text, SpringBattle sb, List <Account> attackers, IPlanetwarsEventCreator eventCreator, ZkLobbyServer.ZkLobbyServer server)
    {
        if (extraData == null)
        {
            extraData = new List <string>();
        }
        Galaxy gal         = db.Galaxies.Single(x => x.IsDefault);
        Planet planet      = gal.Planets.Single(x => x.Resource.InternalName == mapName);
        var    hqStructure = db.StructureTypes.FirstOrDefault(x => x.EffectDisconnectedMetalMalus != null || x.EffectDistanceMetalBonusMax != null);

        text.AppendFormat("Battle on {1}/PlanetWars/Planet/{0} has ended\n", planet.PlanetID, GlobalConst.BaseSiteUrl);


        Faction attacker  = attackers.Where(x => x.Faction != null).Select(x => x.Faction).First();
        var     defenders = players.Where(x => x.FactionID != attacker.FactionID && x.FactionID != null).ToList();
        bool    isAttackerWinner;
        bool    wasAttackerCcDestroyed = false;
        bool    wasDefenderCcDestroyed = false;

        if (winNum != null)
        {
            if (winNum == 0)
            {
                isAttackerWinner = true;
            }
            else
            {
                isAttackerWinner = false;
            }

            wasAttackerCcDestroyed = extraData.Any(x => x.StartsWith("hqkilled,0"));
            wasDefenderCcDestroyed = extraData.Any(x => x.StartsWith("hqkilled,1"));
        }
        else
        {
            text.AppendFormat("No winner on this battle!");
            Trace.TraceError("PW battle without a winner {0}", sb != null ? sb.SpringBattleID : (int?)null);
            return;
        }

        var evacuatedStructureTypeIDs = GetEvacuatedStructureTypes(extraData, db);

        string influenceReport = "";

        // distribute influence
        // save influence gains
        // give influence to main attackers
        double planetIpDefs = planet.GetEffectiveIpDefense();

        double  baseInfluence         = GlobalConst.BaseInfluencePerBattle;
        double  influenceChange       = baseInfluence;
        double  loserInfluence        = 0;
        Faction loserFaction          = attacker; // TODO make this less awful
        bool    reducedEnemyInfluence = false;
        bool    flippedDominance      = false;
        bool    planetConquered       = false;

        double shipBonus = planet.GetEffectiveShipIpBonus(attacker);

        double defenseBonus = -planetIpDefs;
        double techBonus    = attacker.GetFactionUnlocks().Count() * GlobalConst.InfluencePerTech;
        double ipMultiplier = 1;
        string ipReason;

        if (!isAttackerWinner)
        {
            if (wasDefenderCcDestroyed)
            {
                ipMultiplier = GlobalConst.PlanetWarsDefenderWinKillCcMultiplier;
                ipReason     = "from losing but killing defender's CC";
            }
            else
            {
                ipMultiplier = 0;
                ipReason     = "from losing horribly";
            }
        }
        else
        {
            if (wasAttackerCcDestroyed)
            {
                ipReason     = "from losing own CC";
                ipMultiplier = GlobalConst.PlanetWarsAttackerWinLoseCcMultiplier;
            }
            else
            {
                ipReason = "from winning flawlessly";
            }
        }

        influenceChange = (influenceChange + shipBonus + techBonus + defenseBonus) * ipMultiplier;
        if (influenceChange < 0)
        {
            influenceChange = 0;
        }
        influenceChange = Math.Floor(influenceChange * 100) / 100;

        // main winner influence
        // PlanetFaction entry = planet.PlanetFactions.FirstOrDefault(x => x.Faction == attacker);
        PlanetFaction entry = planet.PlanetFactions.FirstOrDefault();

        if (entry == null)
        {
            entry = new PlanetFaction {
                Faction = attacker, Planet = planet,
            };
            planet.PlanetFactions.Add(entry);
        }
        // if non-winner currently dominates planet
        if (entry.Faction != attacker)
        {
            loserFaction   = entry.Faction;
            loserInfluence = entry.Influence;

            // if win is insufficient to change this
            if (loserInfluence >= influenceChange)
            {
                reducedEnemyInfluence = true;
                entry.Influence      -= influenceChange;
            }
            else // flip dominance
            {
                flippedDominance = true;
                planet.PlanetFactions.Remove(entry);
                entry = new PlanetFaction {
                    Faction = attacker, Planet = planet,
                };
                planet.PlanetFactions.Add(entry);
                entry.Influence += (influenceChange - loserInfluence);

                if (entry.Influence >= GlobalConst.PlanetWarsMaximumIP)
                {
                    entry.Influence = GlobalConst.PlanetWarsMaximumIP;
                    planetConquered = true;
                }
            }
        }
        else // increase winner's existing dominance
        {
            if (entry.Influence < GlobalConst.PlanetWarsMaximumIP)
            {
                entry.Influence += influenceChange;
                if (entry.Influence >= GlobalConst.PlanetWarsMaximumIP)
                {
                    entry.Influence = GlobalConst.PlanetWarsMaximumIP;
                    planetConquered = true;
                }
            }
        }

        // TODO remove dependence on attacker

        if (planetConquered)
        {
            // Contest Adjacent Planets
            // GlobalConst.PlanetWarsBreakthroughIP
        }

        // Check all planets to see if they are contested by a single faction

        try
        {
            if (reducedEnemyInfluence)
            {
                influenceReport = String.Format("{0} reduced influence of {1} by {2} ({3}% {4} of {5}{6}{7}{8})",
                                                attacker.Shortcut,
                                                loserFaction.Shortcut,
                                                influenceChange,
                                                (int)(ipMultiplier * 100.0),
                                                ipReason,
                                                baseInfluence + " base",
                                                techBonus > 0 ? " +" + techBonus + " from techs" : "",
                                                shipBonus > 0 ? " +" + shipBonus + " from dropships" : "",
                                                defenseBonus != 0 ? " -" + -defenseBonus + " from defenses" : "");
            }
            else
            {
                if (flippedDominance)
                {
                    influenceReport = String.Format("{0} took dominance from {1} and gained {2} influence ({3}% {4} of {5}{6}{7}{8})",
                                                    attacker.Shortcut,
                                                    loserFaction.Shortcut,
                                                    influenceChange - loserInfluence,
                                                    (int)(ipMultiplier * 100.0),
                                                    ipReason,
                                                    baseInfluence + " base",
                                                    techBonus > 0 ? " +" + techBonus + " from techs" : "",
                                                    shipBonus > 0 ? " +" + shipBonus + " from dropships" : "",
                                                    defenseBonus != 0 ? " -" + -defenseBonus + " from defenses" : "");
                }
                else
                {
                    influenceReport = String.Format("{0} gained {1} influence ({2}% {3} of {4}{5}{6}{7})",
                                                    attacker.Shortcut,
                                                    influenceChange,
                                                    (int)(ipMultiplier * 100.0),
                                                    ipReason,
                                                    baseInfluence + " base",
                                                    techBonus > 0 ? " +" + techBonus + " from techs" : "",
                                                    shipBonus > 0 ? " +" + shipBonus + " from dropships" : "",
                                                    defenseBonus != 0 ? " -" + -defenseBonus + " from defenses" : "");
                }
            }
        }
        catch (Exception ex)
        {
            Trace.TraceError(ex.ToString());
        }

        // distribute metal
        var attackersTotalMetal = CalculateFactionMetalGain(planet, hqStructure, attacker, GlobalConst.PlanetWarsAttackerMetal, eventCreator, db, text, sb);
        var attackerMetal       = Math.Floor(attackersTotalMetal / attackers.Count);

        foreach (Account w in attackers)
        {
            w.ProduceMetal(attackerMetal);
            var ev = eventCreator.CreateEvent("{0} gained {1} metal from battle {2}",
                                              w,
                                              attackerMetal,
                                              sb);
            db.Events.InsertOnSubmit(ev);
            text.AppendLine(ev.PlainText);
        }


        var defendersTotalMetal = planet.OwnerFactionID == null?Math.Floor(GlobalConst.PlanetWarsDefenderMetal) : CalculateFactionMetalGain(planet, hqStructure, planet.Faction, GlobalConst.PlanetWarsDefenderMetal, eventCreator, db, text, sb);

        if (defenders.Count > 0)
        {
            var defenderMetal = Math.Floor(defendersTotalMetal / defenders.Count);
            foreach (Account w in defenders)
            {
                w.ProduceMetal(defenderMetal);
                var ev = eventCreator.CreateEvent("{0} gained {1} metal from battle {2}", w, defenderMetal, sb);
                db.Events.InsertOnSubmit(ev);
                text.AppendLine(ev.PlainText);
            }
        }
        else
        {
            // planet had no defenders, give metal to owner's faction
            if (planet.OwnerFactionID != null)
            {
                planet.Faction.ProduceMetal(defendersTotalMetal);
                var ev = eventCreator.CreateEvent("{0} gained {1} metal from battle {2}", planet.Faction, defendersTotalMetal, sb);
                db.Events.InsertOnSubmit(ev);
            }
        }


        // remove attacker's dropships
        foreach (var pf in planet.PlanetFactions.Where(x => x.Faction == attacker))
        {
            pf.Dropships = 0;
        }


        // remove dropships staying for too long (return to faction pool)
        foreach (var pf in planet.PlanetFactions.Where(x => x.Faction != attacker && x.Dropships > 0 && x.DropshipsLastAdded != null))
        {
            if (DateTime.UtcNow.Subtract(pf.DropshipsLastAdded.Value).TotalMinutes > GlobalConst.PlanetWarsDropshipsStayForMinutes)
            {
                pf.Faction.ProduceDropships(pf.Dropships);
                pf.Dropships = 0;
            }
        }


        // add attack points
        foreach (Account acc in players)
        {
            int ap = acc.Faction == attacker ? GlobalConst.AttackPointsForVictory : GlobalConst.AttackPointsForDefeat;
            if (acc.Faction != null)
            {
                AccountPlanet apentry = planet.AccountPlanets.SingleOrDefault(x => x.AccountID == acc.AccountID);
                if (apentry == null)
                {
                    apentry = new AccountPlanet {
                        AccountID = acc.AccountID, PlanetID = planet.PlanetID
                    };
                    db.AccountPlanets.InsertOnSubmit(apentry);
                }

                apentry.AttackPoints += ap;
            }
            acc.PwAttackPoints += ap;
        }

        // paranoia!
        try
        {
            var mainEvent = eventCreator.CreateEvent("{0} attacked {1} {2} in {3} and {4}. {5}",
                                                     attacker,
                                                     planet.Faction,
                                                     planet,
                                                     sb,
                                                     isAttackerWinner ? "won" : "lost",
                                                     influenceReport
                                                     );
            db.Events.InsertOnSubmit(mainEvent);
            text.AppendLine(mainEvent.PlainText);
        }
        catch (Exception ex)
        {
            Trace.TraceError(ex.ToString());
        }

        // destroy pw structures killed ingame
        if (!isAttackerWinner)
        {
            var handled = new List <string>();
            foreach (string line in extraData.Where(x => x.StartsWith("structurekilled", StringComparison.InvariantCulture)))
            {
                string[] data     = line.Substring(16).Split(',');
                string   unitName = data[0];
                if (handled.Contains(unitName))
                {
                    continue;
                }
                handled.Add(unitName);
                foreach (PlanetStructure s in planet.PlanetStructures.Where(x => x.StructureType.IngameUnitName == unitName))
                {
                    if (s.StructureType.IsIngameDestructible)
                    {
                        s.ReactivateAfterDestruction();

                        var ev = eventCreator.CreateEvent("{0} has been disabled on {1} planet {2}. {3}", s.StructureType.Name, planet.Faction, planet, sb);
                        db.Events.InsertOnSubmit(ev);
                        text.AppendLine(ev.PlainText);
                    }
                }
            }
        }
        else
        {
            // attacker won disable all but evacuated
            foreach (var s in planet.PlanetStructures.Where(x => x.StructureType.IsIngameDestructible))
            {
                if (evacuatedStructureTypeIDs.Contains(s.StructureTypeID))
                {
                    var evSaved = eventCreator.CreateEvent("{0} structure {1} on planet {2} has been saved by evacuation. {3}",
                                                           planet.Faction,
                                                           s.StructureType,
                                                           planet,
                                                           sb);
                    db.Events.InsertOnSubmit(evSaved);
                    text.AppendLine(evSaved.PlainText);
                }
                else
                {
                    s.ReactivateAfterDestruction();
                }
            }
            // destroy structures by battle (usually defenses)
            foreach (PlanetStructure s in planet.PlanetStructures.Where(x => x.StructureType.BattleDeletesThis).ToList())
            {
                if (evacuatedStructureTypeIDs.Contains(s.StructureTypeID))
                {
                    var evSaved = eventCreator.CreateEvent("{0} structure {1} on planet {2} has been saved by evacuation. {3}",
                                                           planet.Faction,
                                                           s.StructureType,
                                                           planet,
                                                           sb);
                    db.Events.InsertOnSubmit(evSaved);
                    text.AppendLine(evSaved.PlainText);
                }
                else
                {
                    planet.PlanetStructures.Remove(s);
                }
            }

            var ev = eventCreator.CreateEvent("All non-evacuated structures have been disabled on {0} planet {1}. {2}", planet.Faction, planet, sb);
            db.Events.InsertOnSubmit(ev);
            text.AppendLine(ev.PlainText);
        }

        db.SaveChanges();

        // no longer used?
        //gal.DecayInfluence();
        //gal.SpreadInfluence();

        // process faction energies
        foreach (var fac in db.Factions.Where(x => !x.IsDeleted))
        {
            fac.ProcessEnergy(gal.Turn);
        }

        // process production (incl. victory points)
        gal.ProcessProduction();
        db.SaveChanges();

        var vpFacs = db.Factions.Where(x => x.VictoryPoints > 0);

        if (vpFacs.Count() > 1)
        {
            foreach (var fac in vpFacs)
            {
                fac.VictoryPoints -= Math.Min(fac.VictoryPoints, GlobalConst.VictoryPointDecay);
            }
        }

        // delete one time activated structures
        gal.DeleteOneTimeActivated(eventCreator, db);
        db.SaveChanges();

        // process treaties
        foreach (var tr in db.FactionTreaties.Where(x => x.TreatyState == TreatyState.Accepted || x.TreatyState == TreatyState.Suspended))
        {
            var failedTradeFaction = tr.ProcessTrade(false);
            if (failedTradeFaction == null)
            {
                tr.TreatyState = TreatyState.Accepted;
                if (tr.TurnsTotal != null)
                {
                    tr.TurnsRemaining--;

                    if (tr.TurnsRemaining <= 0) // treaty expired
                    {
                        tr.TreatyState = TreatyState.Ended;
                        tr.FactionByAcceptingFactionID.ProduceMetal(tr.AcceptingFactionGuarantee ?? 0);
                        tr.FactionByProposingFactionID.ProduceMetal(tr.ProposingFactionGuarantee ?? 0);
                    }
                }
            }
            else
            {
                // failed to perform trade
                if (tr.TreatyUnableToTradeMode == TreatyUnableToTradeMode.Suspend)
                {
                    tr.TreatyState = TreatyState.Suspended;
                }
                else
                { // forced cancel
                    tr.CancelTreaty(failedTradeFaction);
                    db.Events.InsertOnSubmit(server.PlanetWarsEventCreator.CreateEvent("Treaty {0} between {1} and {2} cancelled by {3} because it failed to trade", tr, tr.FactionByProposingFactionID, tr.FactionByAcceptingFactionID, failedTradeFaction));
                }
            }
        }

        // burn extra energy
        foreach (var fac in db.Factions.Where(x => !x.IsDeleted))
        {
            fac.ConvertExcessEnergyToMetal();
        }


        int?oldOwner = planet.OwnerAccountID;

        gal.Turn++;
        db.SaveChanges();

        db = new ZkDataContext(); // is this needed - attempt to fix setplanetownersbeing buggy
        SetPlanetOwners(eventCreator, db, sb != null ? db.SpringBattles.Find(sb.SpringBattleID) : null);
        gal = db.Galaxies.Single(x => x.IsDefault);

        var winByVictoryPoints = db.Factions.FirstOrDefault(x => !x.IsDeleted && x.VictoryPoints >= GlobalConst.PlanetWarsVictoryPointsToWin);

        if (winByVictoryPoints != null)
        {
            WinGame(db,
                    gal,
                    winByVictoryPoints,
                    eventCreator.CreateEvent("CONGRATULATIONS!! {0} has won the PlanetWars by getting enough victory points!", winByVictoryPoints));
            db.SaveChanges();
        }


        planet = gal.Planets.Single(x => x.Resource.InternalName == mapName);
        if (planet.OwnerAccountID != oldOwner && planet.OwnerAccountID != null)
        {
            text.AppendFormat("Congratulations!! Planet {0} was conquered by {1} !!  {3}/PlanetWars/Planet/{2}\n",
                              planet.Name,
                              planet.Account.Name,
                              planet.PlanetID,
                              GlobalConst.BaseSiteUrl);
        }

        server.PublishUserProfilePlanetwarsPlayers();

        try
        {
            // store history
            foreach (Planet p in gal.Planets)
            {
                var hist = db.PlanetOwnerHistories.FirstOrDefault(x => x.PlanetID == p.PlanetID && x.Turn == gal.Turn);
                if (hist == null)
                {
                    hist = new PlanetOwnerHistory()
                    {
                        PlanetID = p.PlanetID, Turn = gal.Turn
                    };
                    db.PlanetOwnerHistories.Add(hist);
                }
                hist.OwnerAccountID = p.OwnerAccountID;
                hist.OwnerClanID    = p.OwnerAccountID != null ? p.Account.ClanID : null;
                hist.OwnerFactionID = p.OwnerFactionID;
            }

            db.SaveChanges();
        }
        catch (Exception ex)
        {
            Trace.TraceError(ex.ToString());
            text.AppendLine("error saving history: " + ex);
        }

        //rotate map
        if (GlobalConst.RotatePWMaps)
        {
            db     = new ZkDataContext();
            gal    = db.Galaxies.Single(x => x.IsDefault);
            planet = gal.Planets.Single(x => x.Resource.InternalName == mapName);
            var mapList = db.Resources.Where(x => x.MapPlanetWarsIcon != null && x.Planets.Where(p => p.GalaxyID == gal.GalaxyID).Count() == 0 && x.MapSupportLevel >= MapSupportLevel.Featured &&
                                             x.ResourceID != planet.MapResourceID && x.MapWaterLevel == planet.Resource.MapWaterLevel).ToList();
            if (mapList.Count > 0)
            {
                int      r          = new Random().Next(mapList.Count);
                int      resourceID = mapList[r].ResourceID;
                Resource newMap     = db.Resources.Single(x => x.ResourceID == resourceID);
                text.AppendLine(String.Format("Map cycler - {0} maps found, selected map {1} to replace map {2}", mapList.Count, newMap.InternalName, planet.Resource.InternalName));
                planet.Resource = newMap;
                gal.IsDirty     = true;
            }
            else
            {
                text.AppendLine("Map cycler - no maps found");
            }
            db.SaveChanges();
        }
    }
Beispiel #24
0
        public ActionResult CommanderProfile(int profileNumber, string name, int?chassis, string deleteCommander)
        {
            if (profileNumber < 1 || profileNumber > GlobalConst.CommanderProfileCount)
            {
                return(Content("WTF! get lost"));
            }

            var db = new ZkDataContext();

            using (var scope = new TransactionScope())
            {
                var unlocks = GetUserUnlockCountsListIncludingFree(db);

                Commander comm = db.Commanders.SingleOrDefault(x => x.ProfileNumber == profileNumber && x.AccountID == Global.AccountID);
                if (comm != null)
                {
                    if (!string.IsNullOrEmpty(deleteCommander))                     // delete commander
                    {
                        db.Commanders.DeleteOnSubmit(comm);
                        db.SaveChanges();
                        scope.Complete();
                        return(GetCommanderProfileView(profileNumber));
                    }
                }
                else
                {
                    comm = new Commander()
                    {
                        AccountID = Global.AccountID, ProfileNumber = profileNumber
                    };
                    db.Commanders.InsertOnSubmit(comm);
                }

                if (comm.Unlock == null)
                {
                    var chassisUnlock = unlocks.FirstOrDefault(x => x.Unlock.UnlockID == chassis);
                    if ((chassis == null || chassisUnlock == null))
                    {
                        return(GetCommanderProfileView(profileNumber));
                    }
                    else
                    {
                        comm.ChassisUnlockID = chassis.Value;
                        comm.Unlock          = chassisUnlock.Unlock;
                    }
                }

                if (!string.IsNullOrEmpty(name))
                {
                    if (name.Length > GlobalConst.MaxCommanderNameLength)
                    {
                        name = name.Substring(0, GlobalConst.MaxCommanderNameLength);
                    }
                    name      = Regex.Replace(name, @"[^\u0020-\u007E]", string.Empty); // remove unicode stuff
                    comm.Name = name;
                }

                // process modules
                foreach (var key in Request.Form.AllKeys.Where(x => !string.IsNullOrEmpty(x)))
                {
                    var m = Regex.Match(key, "m([0-9]+)");
                    if (m.Success)
                    {
                        var slotId = int.Parse(m.Groups[1].Value);
                        int unlockId;
                        int.TryParse(Request.Form[key], out unlockId);

                        if (unlockId > 0)
                        {
                            CommanderSlot slot = db.CommanderSlots.SingleOrDefault(x => x.CommanderSlotID == slotId);
                            if (slot == null)
                            {
                                return(Content("WTF get lost!"));
                            }

                            Unlock unlock = db.Unlocks.SingleOrDefault(x => x.UnlockID == unlockId);
                            if (unlock == null)
                            {
                                return(Content("WTF get lost!"));
                            }

                            if (!unlocks.Any(x => x.Unlock.UnlockID == unlock.UnlockID))
                            {
                                return(Content("WTF get lost!"));
                            }
                            if (slot.MorphLevel < unlock.MorphLevel || !IsUnlockValidForSlot(unlock, slot))
                            {
                                return(Content(string.Format("WTF cannot use {0} in slot {1}", unlock.Name, slot.CommanderSlotID)));
                            }
                            if (!string.IsNullOrEmpty(unlock.LimitForChassis))
                            {
                                var validChassis = unlock.LimitForChassis.Split(',');
                                if (!validChassis.Contains(comm.Unlock.Code))
                                {
                                    return(Content(string.Format("{0} cannot be used in commander {1}", unlock.Name, comm.Unlock.Name)));
                                }
                            }
                            if (!IsPrerequisiteUnlockPresent(comm, unlock))
                            {
                                return(Content(string.Format("{0} missing prerequisite module", unlock.Name)));
                            }

                            var comSlot = comm.CommanderModules.SingleOrDefault(x => x.SlotID == slotId);
                            if (comSlot == null)
                            {
                                comSlot = new CommanderModule()
                                {
                                    SlotID = slotId
                                };
                                comm.CommanderModules.Add(comSlot);
                            }
                            comSlot.ModuleUnlockID = unlockId;
                        }
                        else
                        {
                            var oldModule = comm.CommanderModules.FirstOrDefault(x => x.SlotID == slotId);
                            if (oldModule != null)
                            {
                                comm.CommanderModules.Remove(oldModule);
                            }
                        }
                    }
                }

                // process decorations
                foreach (var key in Request.Form.AllKeys.Where(x => !string.IsNullOrEmpty(x)))
                {
                    var d = Regex.Match(key, "d([0-9]+)");
                    if (d.Success)
                    {
                        var slotId = int.Parse(d.Groups[1].Value);
                        int unlockId;
                        int.TryParse(Request.Form[key], out unlockId);

                        if (unlockId > 0)
                        {
                            CommanderDecorationSlot decSlot = db.CommanderDecorationSlots.SingleOrDefault(x => x.CommanderDecorationSlotID == slotId);
                            if (decSlot == null)
                            {
                                return(Content("WTF get lost!"));
                            }

                            Unlock unlock = db.Unlocks.SingleOrDefault(x => x.UnlockID == unlockId && x.UnlockType == UnlockTypes.Decoration);
                            if (unlock == null)
                            {
                                return(Content("WTF get lost!"));
                            }

                            if (!unlocks.Any(x => x.Unlock.UnlockID == unlock.UnlockID))
                            {
                                return(Content("WTF get lost!"));
                            }
                            if (!string.IsNullOrEmpty(unlock.LimitForChassis))
                            {
                                var validChassis = unlock.LimitForChassis.Split(',');
                                if (!validChassis.Contains(comm.Unlock.Code))
                                {
                                    return(Content(string.Format("{0} cannot be used in commander {1}", unlock.Name, comm.Unlock.Name)));
                                }
                            }

                            var comSlot = comm.CommanderDecorations.SingleOrDefault(x => x.SlotID == slotId);
                            if (comSlot == null)
                            {
                                comSlot = new CommanderDecoration()
                                {
                                    SlotID = slotId
                                };
                                comm.CommanderDecorations.Add(comSlot);
                            }
                            comSlot.DecorationUnlockID = unlockId;
                        }
                        else
                        {
                            var oldDecoration = comm.CommanderDecorations.FirstOrDefault(x => x.SlotID == slotId);
                            if (oldDecoration != null)
                            {
                                comm.CommanderDecorations.Remove(oldDecoration);
                            }
                        }
                    }
                }

                // remove a module/decoration if ordered to
                foreach (var toDel in Request.Form.AllKeys.Where(x => !string.IsNullOrEmpty(x)))
                {
                    var m = Regex.Match(toDel, "deleteSlot([0-9]+)");
                    if (m.Success)
                    {
                        var slotId = int.Parse(m.Groups[1].Value);
                        comm.CommanderModules.Remove(comm.CommanderModules.SingleOrDefault(x => x.SlotID == slotId));
                    }

                    var d = Regex.Match(toDel, "deleteDecorationSlot([0-9]+)");
                    if (d.Success)
                    {
                        var decSlotId = int.Parse(d.Groups[1].Value);
                        comm.CommanderDecorations.Remove(comm.CommanderDecorations.SingleOrDefault(x => x.SlotID == decSlotId));
                    }
                }

                // cleanup invalid modules?

                db.SaveChanges();
                foreach (var unlock in comm.CommanderModules.GroupBy(x => x.Unlock))
                {
                    if (unlock.Key == null)
                    {
                        continue;
                    }
                    var owned = unlocks.Where(x => x.Unlock.UnlockID == unlock.Key.UnlockID).Sum(x => (int?)x.Count) ?? 0;
                    if (owned < unlock.Count())
                    {
                        var toRemove = unlock.Count() - owned;

                        foreach (var m in unlock.OrderByDescending(x => x.SlotID))
                        {
                            db.CommanderModules.DeleteOnSubmit(m);
                            //comm.CommanderModules.Remove(m);
                            toRemove--;
                            if (toRemove <= 0)
                            {
                                break;
                            }
                        }
                    }
                }

                db.SaveChanges();
                scope.Complete();
            }

            return(GetCommanderProfileView(profileNumber));
        }
        //stores replay, springbattle, processes rating and xp, returns whether battle ended normally
        public static bool SubmitSpringBattleResult(SpringBattleContext result, ZkLobbyServer.ZkLobbyServer server, Action <BattleDebriefing> consumer)
        {
            var ret = new BattleDebriefing();

            try
            {
                bool isValidGame = true;
                if (!result.GameEndedOk)
                {
                    ret.Message = "Game didn't end properly";
                    isValidGame = false;
                }
                if (result.IsCheating)
                {
                    ret.Message = "Cheats were enabled during this game";
                    isValidGame = false;
                }

                var db   = new ZkDataContext();
                var text = new StringBuilder();

                var sb = SaveSpringBattle(result, db);

                if (isValidGame)
                {
                    StoreAwards(result.OutputExtras, sb, db);
                }
                StoreLogs(result.OutputExtras, sb, db);

                if (result.LobbyStartContext.Mode == AutohostMode.Planetwars)
                {
                    ProcessPlanetWars(result, server, sb, db, text);
                }


                Dictionary <int, int> orgLevels = sb.SpringBattlePlayers.Select(x => x.Account).ToDictionary(x => x.AccountID, x => x.Level);

                //fill in applicable ratings
                bool noElo = !isValidGame || result.LobbyStartContext.ModOptions.Any(x => x.Key.ToLower() == "noelo" && x.Value != "0" && x.Value != "false");
                if (!noElo)
                {
                    RatingSystems.FillApplicableRatings(sb, result);
                }

                if (isValidGame)
                {
                    ProcessXP(result, server, db, sb);
                }


                ret.Url            = string.Format("{1}/Battles/Detail/{0}", sb.SpringBattleID, GlobalConst.BaseSiteUrl);
                ret.ServerBattleID = sb.SpringBattleID;

                server.GhostSay(
                    new Say()
                {
                    Text =
                        string.Format("BATTLE DETAILS AND REPLAY ----> {0} <-----", ret.Url),
                    IsEmote = true,
                    Place   = SayPlace.Battle,
                    User    = GlobalConst.NightwatchName
                },
                    result.LobbyStartContext.BattleID);


                foreach (var p in sb.SpringBattlePlayers.Where(x => !x.IsSpectator))
                {
                    ret.DebriefingUsers[p.Account.Name] = new BattleDebriefing.DebriefingUser()
                    {
                        AccountID       = p.AccountID,
                        LoseTime        = p.LoseTime ?? -1,
                        AllyNumber      = p.AllyNumber,
                        IsInVictoryTeam = p.IsInVictoryTeam,
                        EloChange       = 0,
                        IsRankdown      = false,
                        IsRankup        = false,
                        NewElo          = -1,
                        NextRankElo     = -1,
                        PrevRankElo     = -1,
                        NewRank         = p.Account.Rank,
                        XpChange        = p.XpChange ?? 0,
                        NewXp           = p.Account.Xp,
                        NextLevelXp     = Account.GetXpForLevel(p.Account.Level + 1),
                        PrevLevelXp     = Account.GetXpForLevel(p.Account.Level),
                        IsLevelUp       = orgLevels[p.AccountID] < p.Account.Level,
                        Awards          = sb.AccountBattleAwards.Where(x => x.AccountID == p.AccountID).Select(x => new BattleDebriefing.DebriefingAward()
                        {
                            Value       = x.Value,
                            Key         = x.AwardKey,
                            Description = x.AwardDescription
                        }).ToList()
                    };
                }

                //send to rating

                if (!noElo)
                {
                    RatingSystems.ProcessResult(sb, result, new PendingDebriefing()
                    {
                        debriefingConsumer = consumer,
                        partialDebriefing  = ret,
                        battle             = sb,
                    });
                }

                Trace.TraceInformation("Battle ended: Server exited for B" + sb.SpringBattleID);
                db.SaveChanges();

                return(true);
            }
            catch (Exception ex)
            {
                var data = JsonConvert.SerializeObject(result);
                Trace.TraceError($"{ex}\nData:\n{data}");
                ret.Message = "Error processing game result: " + ex.Message;
                return(false);
            }
        }
Beispiel #26
0
        public static void StartGalaxy(int galaxyID, params int[] startingPlanets)
        {
            using (var db = new ZkDataContext())
            {
                var facs = db.Factions.Where(x => !x.IsDeleted).ToList();
                if (startingPlanets == null || startingPlanets.Length < facs.Count)
                {
                    startingPlanets =
                        db.Planets.Where(x => x.GalaxyID == galaxyID && x.PlanetStructures.Any(y => y.StructureType.OwnerChangeWinsGame == true))
                        .OrderBy(x => x.Y)
                        .ThenBy(x => x.Y)
                        .Select(x => x.PlanetID)
                        .ToArray();
                }

                for (int i = 0; i < facs.Count; i++)
                {
                    var pid     = startingPlanets[i];
                    var planet  = db.Planets.First(x => x.PlanetID == pid);
                    var faction = facs[i];
                    planet.PlanetFactions.Add(new PlanetFaction()
                    {
                        Faction   = faction,
                        Influence = 100
                    });
                    planet.Faction = faction;
                }

                db.SaveChanges();

                /*foreach (Account acc in db.Accounts)
                 * {
                 *  double elo = acc.Elo;
                 *  if (acc.Elo1v1 > elo) elo = acc.Elo1v1;
                 *  acc.EloPw = elo;
                 * }
                 * System.Console.WriteLine("PW Elo set");
                 * foreach (Faction fac in db.Factions)
                 * {
                 *  var accounts = fac.Accounts.Where(x=> x.Planets.Count > 0).ToList();
                 *  foreach (Account acc in accounts)
                 *  {
                 *      acc.ProduceDropships(1);
                 *  }
                 *  fac.ProduceDropships(5);
                 * }
                 * System.Console.WriteLine("Dropships ready");
                 */
                var gal = db.Galaxies.Single(x => x.GalaxyID == galaxyID);
                foreach (Planet planet in gal.Planets)
                {
                    if (planet.Faction != null)
                    {
                        foreach (PlanetStructure s in planet.PlanetStructures)
                        {
                            //s.ActivatedOnTurn = 0;
                            s.IsActive = true;
                        }
                    }
                    else
                    {
                        foreach (PlanetStructure s in planet.PlanetStructures.Where(x => x.StructureType.OwnerChangeWinsGame != true))
                        {
                            s.IsActive        = false;
                            s.ActivatedOnTurn = null;
                        }
                    }
                }
                System.Console.WriteLine("Structure activation set");

                gal.Turn    = 0;
                gal.Started = DateTime.UtcNow;
                db.SaveChanges();
            }
        }
Beispiel #27
0
        public ActionResult Punish(int accountID,
                                   string reason,
                                   bool deleteXP,
                                   bool deleteInfluence,
                                   bool banMute,
                                   bool banCommanders,
                                   bool banSite,
                                   bool banLobby,
                                   bool banUnlocks,
                                   bool banSpecChat,
                                   bool banForum,
                                   bool setRightsToZero,
                                   string banIP,
                                   long?banUserID,
                                   double banHours)
        {
            ZkDataContext db  = new ZkDataContext();
            Account       acc = db.Accounts.SingleOrDefault(x => x.AccountID == accountID);

            if (acc == null)
            {
                return(Content("Invalid accountID"));
            }

            if (banHours > MaxBanHours)
            {
                banHours = MaxBanHours;                         // todo show some notification
            }
            Punishment punishment = new Punishment
            {
                Time             = DateTime.UtcNow,
                Reason           = reason,
                BanMute          = banMute,
                BanCommanders    = banCommanders,
                BanSite          = banSite,
                BanLobby         = banLobby,
                BanExpires       = DateTime.UtcNow.AddHours(banHours),
                BanUnlocks       = banUnlocks,
                BanSpecChat      = banSpecChat,
                BanIP            = banIP,
                BanForum         = banForum,
                DeleteXP         = deleteXP,
                DeleteInfluence  = deleteInfluence,
                CreatedAccountID = Global.AccountID,
                UserID           = banUserID
            };

            acc.PunishmentsByAccountID.Add(punishment);
            db.SaveChanges();

            // notify lobby of changes and post log message
            try
            {
                if (banLobby == true)
                {
                    Global.Server.KickFromServer(Global.Account.Name, acc.Name, reason);
                }
                if (banMute == true)
                {
                    Global.Server.PublishAccountUpdate(acc);
                }

                Global.Server.GhostChanSay(GlobalConst.ModeratorChannel, string.Format("New penalty for {0} {1}  ", acc.Name, Url.Action("Detail", "Users", new { id = acc.AccountID }, "http")));
                Global.Server.GhostChanSay(GlobalConst.ModeratorChannel, string.Format("Reason: {0} ", reason));
                Global.Server.GhostPm(acc.Name, string.Format("Your account has received moderator action: {0}", reason));
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());
                Global.Server.GhostChanSay(GlobalConst.ModeratorChannel, ex.ToString());
            }
            return(RedirectToAction("Detail", new { id = accountID }));
        }
Beispiel #28
0
        static void GenerateStructures(int galaxyID)
        {
            var rand  = new Random();
            var db    = new ZkDataContext();
            var gal   = db.Galaxies.Single(x => x.GalaxyID == galaxyID);
            var names = Resources.names.Lines().ToList();

            var wormhole  = 16;
            var wormhole2 = 19;


            var mine     = 1;
            var mine2    = 3;
            var mine3    = 4;
            var warp     = 10;
            var chicken  = 20;
            var dfac     = 6;
            var ddepot   = 7;
            int artefact = 9;
            int militia  = 594;

            /*
             * 567	Jumpjet/Specialist Plant
             * 568	Screamer
             * 569	Athena
             * 570	Heavy Tank Factory
             * 571	Airplane Plant
             * 572	Krow
             * 573	Bantha
             * 574	Jugglenaut
             * 575	Detriment
             * 576	Singularity Reactor
             * 577	Annihilator
             * 578	Doomsday Machine
             * 579	Behemoth
             * 580	Starlight
             * 581	Big Bertha
             * 582	Goliath
             * 583	Licho
             * 584	Reef
             * 585	Scythe
             * 586	Panther
             * 587	Black Dawn
             * 588	Dominatrix
             * 589	Newton
             * 590	Shield Bot Factory
             * 591	Silencer
             * 592	Disco Rave Party*/


            List <int> bannedStructures = new List <int>()
            {
            };                                               // { 568, 577, 578, 584, 585, 586, 588, 589, 571, 590 };

            var structs = db.StructureTypes.Where(x => x.Unlock != null && !bannedStructures.Contains(x.StructureTypeID));
            List <Tuple <int, int> > costs = new List <Tuple <int, int> >();

            foreach (var s in structs)
            {
                costs.Add(Tuple.Create((int)(5000 / s.Cost), s.StructureTypeID)); // probabality is relative to 1200-cost
            }
            var sumCosts = costs.Sum(x => x.Item1);

            foreach (var p in gal.Planets)
            {
                p.PlanetStructures.Clear();
                //p.Name = names[rand.Next(names.Count)];
                //names.Remove(p.Name);
                //if (rand.Next(50) == 0 ) p.AddStruct(wormhole2);
                //else
                //if (rand.Next(10)<8)
                p.AddStruct(wormhole);
                //p.AddStruct(militia);

                //if (rand.Next(30) ==0) p.AddStruct(mine3);
                //else if (rand.Next(20)==0) p.AddStruct(mine2);
                //else
                //if (rand.Next(20) ==0) p.AddStruct(mine);

                //if (rand.Next(20) == 0) p.AddStruct(dfac);
                //if (rand.Next(20) == 0) p.AddStruct(ddepot);
                //if (rand.Next(20) == 0) p.AddStruct(warp);

                if (p.Resource.MapIsChickens == true)
                {
                    p.AddStruct(chicken);
                }

                // tech structures

                /*if (rand.Next(8) ==0)
                 * {
                 *
                 *  var probe = rand.Next(sumCosts);
                 *  foreach (var s in costs)
                 *  {
                 *      probe -= s.Item1;
                 *      if (probe <= 0)
                 *      {
                 *          p.AddStruct(s.Item2);
                 *          break;
                 *      }
                 *  }
                 * }*/
            }

            // artefacts
            //foreach (var p in gal.Planets.Where(x => x.Resource.MapIsChickens!=true && !x.Resource.MapIsFfa != true && x.Resource.MapIs1v1 != true).Shuffle().Take(5)) p.AddStruct(artefact);

            // jump gates
            //foreach (var p in gal.Planets.Shuffle().Take(6)) p.AddStruct(warp);

            db.SaveChanges();
            db.SaveChanges();
        }
Beispiel #29
0
        public void SaveGalaxy(int galaxyNumber)
        {
            // using (var scope = new TransactionScope())
            {
                try
                {
                    var db  = new ZkDataContext();
                    var gal = db.Galaxies.SingleOrDefault(x => x.GalaxyID == galaxyNumber);
                    if (gal == null || galaxyNumber == 0)
                    {
                        gal = new Galaxy();
                        db.Galaxies.InsertOnSubmit(gal);
                    }
                    else if (gal.Started != null)
                    {
                        MessageBox.Show("This galaxy is running, cannot edit it!");
                        return;
                    }
                    else
                    {
                        db.Links.DeleteAllOnSubmit(gal.Links);
                        db.Planets.DeleteAllOnSubmit(gal.Planets);
                    }
                    gal.IsDirty = true;
                    db.SaveChanges();
                    galaxyNumber = gal.GalaxyID;

                    var maps = Maps.Shuffle();
                    var cnt  = 0;

                    foreach (var d in PlanetDrawings)
                    {
                        var memPlanet = d.Planet;

                        var p = new Planet();
                        db.Planets.Add(p);

                        p.Name           = memPlanet.Name;
                        p.GalaxyID       = galaxyNumber;
                        p.OwnerAccountID = memPlanet.OwnerAccountID;
                        p.X = (float)(Canvas.GetLeft(d) / imageSource.Width);
                        p.Y = (float)(Canvas.GetTop(d) / imageSource.Height);
                        if (memPlanet.MapResourceID == null)
                        {
                            p.MapResourceID = maps[cnt].ResourceID;
                            cnt++;
                            cnt = cnt % maps.Count;
                        }
                        else
                        {
                            p.MapResourceID = memPlanet.MapResourceID;
                        }

                        p.PlanetStructures.Clear();
                        p.PlanetStructures.AddRange(memPlanet.PlanetStructures.Select(x => new PlanetStructure()
                        {
                            StructureTypeID = x.StructureTypeID
                        }));
                    }
                    db.SaveChanges();

                    var linkList =
                        LinkDrawings.Select(
                            d =>
                            new Link()
                    {
                        GalaxyID  = galaxyNumber,
                        PlanetID1 = db.Planets.Single(x => x.GalaxyID == galaxyNumber && x.Name == d.Planet1.Planet.Name).PlanetID,
                        PlanetID2 = db.Planets.Single(x => x.GalaxyID == galaxyNumber && x.Name == d.Planet2.Planet.Name).PlanetID
                    });
                    db.Links.InsertAllOnSubmit(linkList);
                    db.SaveChanges();
                    // scope.Complete();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
                MessageBox.Show("Exported!");
            }
        }
        public static ReturnValue RegisterResource(int apiVersion,
                                                   string springVersion,
                                                   string md5,
                                                   int length,
                                                   ResourceType resourceType,
                                                   string archiveName,
                                                   string internalName,
                                                   byte[] serializedData,
                                                   List <string> dependencies,
                                                   byte[] minimap,
                                                   byte[] metalMap,
                                                   byte[] heightMap,
                                                   byte[] torrentData)
        {
            if (md5 == null)
            {
                throw new ArgumentNullException("md5");
            }
            if (archiveName == null)
            {
                throw new ArgumentNullException("archiveName");
            }
            if (internalName == null)
            {
                throw new ArgumentNullException("internalName");
            }
            if (serializedData == null)
            {
                throw new ArgumentNullException("serializedData");
            }
            if (torrentData == null)
            {
                throw new ArgumentNullException("torrentData");
            }
            if (PlasmaServerApiVersion > apiVersion)
            {
                throw new Exception("Obsolete PlasmaServer Client");
            }
            if (dependencies == null)
            {
                dependencies = new List <string>();
            }

            var db = new ZkDataContext();


            var contentFile = db.ResourceContentFiles.FirstOrDefault(x => x.Md5 == md5);

            if (contentFile != null)
            {
                // content file already stored
                if (contentFile.Resource.InternalName != internalName)
                {
                    return(ReturnValue.Md5AlreadyExistsWithDifferentName);
                }

                // new spring version we add its hash
                StoreMetadata(md5, contentFile.Resource, serializedData, torrentData, minimap, metalMap, heightMap);
                db.SaveChanges();
                return(ReturnValue.Ok);
            }

            var resource = db.Resources.Where(x => x.InternalName == internalName).SingleOrDefault();

            if (resource == null)
            {
                resource = new Resource {
                    InternalName = internalName, TypeID = resourceType
                };
                db.Resources.Add(resource);
                StoreMetadata(md5, resource, serializedData, torrentData, minimap, metalMap, heightMap);
            }

            if (!resource.ResourceDependencies.Select(x => x.NeedsInternalName).Except(dependencies).Any())
            {
                // new dependencies are superset
                foreach (var depend in dependencies)
                {
                    // add missing dependencies
                    var s = depend;
                    if (!resource.ResourceDependencies.Any(x => x.NeedsInternalName == s))
                    {
                        resource.ResourceDependencies.Add(new ResourceDependency {
                            NeedsInternalName = depend
                        });
                    }
                }
            }

            if (resource.ResourceContentFiles.Any(x => x.Length == length && x.Md5 != md5))
            {
                return(ReturnValue.Md5AlreadyExistsWithDifferentName);
                // add proper message - file exists with different md5 and same size - cant register cant detect mirrors
            }

            var newContentFile = new ResourceContentFile {
                FileName = archiveName, Length = length, Md5 = md5, Resource = resource
            };

            resource.ResourceContentFiles.Add(newContentFile);
            ResourceLinkProvider.UpdateLinks(newContentFile);
            File.WriteAllBytes(GetTorrentPath(internalName, md5), torrentData); // add new torrent file

            db.SaveChanges();



            return(ReturnValue.Ok);
        }