예제 #1
0
        private HttpResponse processPost(HttpRequest req)
        {
            switch (req.Post["fnc"].Value)
            {
            case "create":
                var items  = req.Post["items"].Value.Replace("\r", "").Trim().Split('\n').Select(line => line.Trim()).ToArray();
                var hash   = MD5.Create().ComputeHash(items.JoinString("\n").ToUtf8()).ToHex();
                var newSet = new RankSet {
                    Hash = hash, Items = items, Name = req.Post["title"].Value
                };
                if (!_setsDic.ContainsKey(hash))
                {
                    lock (this)
                        if (!_setsDic.ContainsKey(hash))
                        {
                            var newSetSlim = newSet.ToSlim();
                            _setsDic[hash] = newSetSlim;
                            _setsList.Add(newSetSlim);
                            ClassifyJson.SerializeToFile(newSet, setPath(hash));
                        }
                }
                return(HttpResponse.Redirect(req.Url.WithQuery("set", hash)));

            case "start":
                lock (this)
                {
                    var currentSetHash = req.Post["set"].Value;
                    var setFilePath    = setPath(currentSetHash);
                    if (!File.Exists(setFilePath))
                    {
                        return(HttpResponse.PlainText("That set does not exist.", HttpStatusCode._404_NotFound));
                    }
                    var currentSet = ClassifyJson.DeserializeFile <RankSet>(setFilePath);

retry:
                    var publicToken = Rnd.GenerateString(32);
                    var privateToken = Rnd.GenerateString(32);
                    var path         = rankingPath(publicToken);
                    if (File.Exists(path) || currentSet.DicRankings.ContainsKey(publicToken))
                    {
                        goto retry;
                    }
                    var newRanking = new RankRanking {
                        Finished = false, PublicToken = publicToken, PrivateToken = privateToken, SetHash = currentSetHash, Title = req.Post["title"].Value, Question = req.Post["question"].Value
                    };
                    var newRankingSlim = newRanking.ToSlim();
                    currentSet.DicRankings[publicToken] = newRankingSlim;
                    currentSet.ListRankings.Add(newRankingSlim);
                    ClassifyJson.SerializeToFile(newRanking, path);
                    ClassifyJson.SerializeToFile(currentSet, setFilePath);
                    return(HttpResponse.Redirect(req.Url.WithoutQuery().WithQuery("ranking", publicToken).WithQuery("secret", privateToken)));
                }

            case "rank":
                lock (this)
                {
                    var publicToken     = req.Post["ranking"].Value;
                    var privateToken    = req.Post["secret"].Value;
                    var rankingFilePath = rankingPath(publicToken);
                    if (!File.Exists(rankingFilePath))
                    {
                        return(HttpResponse.PlainText("That ranking does not exist.", HttpStatusCode._404_NotFound));
                    }
                    var currentRanking = ClassifyJson.DeserializeFile <RankRanking>(rankingFilePath);
                    if (privateToken != currentRanking.PrivateToken)
                    {
                        return(HttpResponse.PlainText("You cannot vote in this ranking.", HttpStatusCode._404_NotFound));
                    }

                    var setFilePath = setPath(currentRanking.SetHash);
                    if (!File.Exists(setFilePath))
                    {
                        return(HttpResponse.PlainText("That set does not exist.", HttpStatusCode._404_NotFound));
                    }
                    var currentSet = ClassifyJson.DeserializeFile <RankSet>(setFilePath);

                    if (!int.TryParse(req.Post["ix1"].Value, out var ix1) || !int.TryParse(req.Post["ix2"].Value, out var ix2) || !int.TryParse(req.Post["more"].Value, out var more) || (more != ix1 && more != ix2))
                    {
                        return(HttpResponse.PlainText("Invalid integers.", HttpStatusCode._404_NotFound));
                    }

                    var newComparison = new RankComparison(more == ix1 ? ix2 : ix1, more == ix1 ? ix1 : ix2);

                    // Transitive closure
                    var ancestorLesses = currentRanking.Comparisons.Where(c => c.More == newComparison.Less).Select(c => c.Less).ToList();
                    ancestorLesses.Add(newComparison.Less);
                    var descendantMores = currentRanking.Comparisons.Where(c => c.Less == newComparison.More).Select(c => c.More).ToList();
                    descendantMores.Add(newComparison.More);
                    for (int i = 0; i < ancestorLesses.Count; i++)
                    {
                        for (int j = 0; j < descendantMores.Count; j++)
                        {
                            currentRanking.Comparisons.Add(new RankComparison(ancestorLesses[i], descendantMores[j]));
                        }
                    }

                    var result = attemptRanking(currentRanking, currentSet);
                    if (result.ix1 == -1)
                    {
                        currentRanking.Finished = true;

                        // This relies on reference equality, i.e. that currentSet.ListRankings contains the same object
                        currentSet.DicRankings[publicToken].Finished = true;

                        ClassifyJson.SerializeToFile(currentSet, setFilePath);
                    }
                    ClassifyJson.SerializeToFile(currentRanking, rankingFilePath);

                    return(HttpResponse.Redirect(req.Url.WithoutQuery().WithQuery("ranking", publicToken).WithQuery("secret", privateToken)));
                }
            }

            return(HttpResponse.PlainText("What?", HttpStatusCode._500_InternalServerError));
        }
예제 #2
0
        private static (int ix1, int ix2, int[] ranked) attemptRanking(RankRanking ranking, RankSet set)
        {
            var ix1           = -1;
            var ix2           = -1;
            var indexesToRank = Enumerable.Range(0, set.Items.Length).Except(ranking.Ignore).ToArray();
            var ranked        = indexesToRank.OrderBy((i1, i2) =>
            {
                if (i1 == i2)
                {
                    return(0);
                }
                if (ranking.Comparisons.Contains(new RankComparison(i1, i2)))
                {
                    return(1);
                }
                if (ranking.Comparisons.Contains(new RankComparison(i2, i1)))
                {
                    return(-1);
                }

                if (ix1 == -1)
                {
                    ix1 = i1;
                    ix2 = i2;
                }
                return(0);
            }).ToArray();

            return(ix1, ix2, ranked);
        }