Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added feeling stuck button #492

Merged
merged 6 commits into from
Jun 20, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 52 additions & 8 deletions ServerCore/Pages/Events/FastestSolves.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,49 @@
ViewData["AdminRoute"] = "/Events/FastestSolves";
ViewData["AuthorRoute"] = "/Events/FastestSolves";
ViewData["PlayRoute"] = "/Events/FastestSolves";

Boolean unsolvedFilter = Model.StateFilter == FastestSolvesModel.PuzzleStateFilter.Unsolved;
}

<h2>Fastest Solves</h2>
<br/>
<div>
<a class="radioButton"
asp-page="./FastestSolves"
asp-route-sort="@Model.Sort"
asp-route-stateFilter="@FastestSolvesModel.PuzzleStateFilter.All">

<input id="StateFilter" name="StateFilter" value="All" type="radio" @(unsolvedFilter ? "" : "checked")> All
</a>
<a class="radioButton"
asp-page="./FastestSolves"
asp-route-sort="@Model.Sort"
asp-route-stateFilter="@FastestSolvesModel.PuzzleStateFilter.Unsolved">

<input id="StateFilter" name="StateFilter" value="Unsolved" type="radio" @(unsolvedFilter ? "checked" : "")> Unsolved
</a>
</div>
<br/>
<table class="table table-condensed">
<thead>
<tr>
<th>
Rank
</th>
<th>
@Html.DisplayNameFor(model => model.Puzzles[0].Puzzle.Name)
<a asp-page="./FastestSolves"
asp-route-sort="@(Model.SortForColumnLink(FastestSolvesModel.SortOrder.PuzzleAscending,
FastestSolvesModel.SortOrder.PuzzleDescending))"
asp-route-stateFilter="@Model.StateFilter">

@Html.DisplayNameFor(model => model.Puzzles[0].Puzzle.Name)
</a>
</th>
<th>
Teams
<a asp-page="./FastestSolves"
asp-route-sort="@(Model.SortForColumnLink(FastestSolvesModel.SortOrder.CountAscending,
FastestSolvesModel.SortOrder.CountDescending))"
asp-route-stateFilter="@Model.StateFilter">

Teams Solved
</a>
</th>
<th>
First
Expand All @@ -32,6 +60,12 @@
<th>
Third
</th>
@if (Model.CurrentTeam != null)
{
<th>
Status for @Model.CurrentTeam.Name
</th>
}
</tr>
</thead>
<tbody>
Expand All @@ -40,9 +74,6 @@
Func<TimeSpan, string> convertTimeToString = ts => string.Format("{0:00}.{1:00}:{2:00}:{3:00}", ts.TotalDays, Math.Abs(ts.Hours), Math.Abs(ts.Minutes), Math.Abs(ts.Seconds));

<tr>
<td>
@(puzzle.SortOrder + 1)
</td>
<td>
@(puzzle.Puzzle.Name)
</td>
Expand All @@ -68,6 +99,19 @@
<text>@puzzle.Fastest[2].Name (@convertTimeToString(puzzle.Fastest[2].Time.Value))</text>
}
</td>
@if (Model.CurrentTeam != null)
{
<th>
@if (puzzle.IsSolved)
{
<text>Solved!</text>
}
else
{
<text>Unsolved</text>
}
</th>
}
</tr>
}
</tbody>
Expand Down
105 changes: 102 additions & 3 deletions ServerCore/Pages/Events/FastestSolves.cshtml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using ServerCore.DataModel;
using ServerCore.Helpers;
using ServerCore.ModelBases;

namespace ServerCore.Pages.Events
Expand All @@ -15,12 +16,24 @@ public class FastestSolvesModel : EventSpecificPageModel
{
public List<PuzzleStats> Puzzles { get; private set; }

public PuzzleStateFilter? StateFilter { get; set; }

public SortOrder? Sort { get; set; }

public Team CurrentTeam { get; set; }

private const SortOrder DefaultSort = SortOrder.RankAscending;

public FastestSolvesModel(PuzzleServerContext serverContext, UserManager<IdentityUser> userManager) : base(serverContext, userManager)
{
}

public async Task OnGetAsync()
public async Task OnGetAsync(SortOrder? sort, PuzzleStateFilter? stateFilter)
{
this.Sort = sort;
this.StateFilter = stateFilter;
this.CurrentTeam = (await UserEventHelper.GetTeamForPlayer(_context, Event, LoggedInUser));
lambertwang-zz marked this conversation as resolved.
Show resolved Hide resolved

Dictionary<int, string> teamNameLookup = new Dictionary<int, string>();

// build an ID-to-name mapping to improve perf
Expand All @@ -37,35 +50,105 @@ public async Task OnGetAsync()
.Select(g => new {
Puzzle = g.Key,
SolveCount = g.Count(),
Fastest = g.OrderBy(s => s.SolvedTime - s.UnlockedTime).Take(3).Select(s => new { s.Team.ID, Time = s.SolvedTime - s.UnlockedTime})
Fastest = g.OrderBy(s => s.SolvedTime - s.UnlockedTime).Take(3).Select(s => new { s.Team.ID, Time = s.SolvedTime - s.UnlockedTime }),
IsSolvedByUserTeam = g.Where(s => s.Team == this.CurrentTeam).Any()
})
.OrderByDescending(p => p.SolveCount).ThenBy(p => p.Puzzle.Name)
.ToListAsync();

var unlockedData = this.CurrentTeam == null ? null : (new HashSet<int>(
await PuzzleStateHelper.GetSparseQuery(_context, this.Event, null, null)
.Where(state => state.Team == this.CurrentTeam && state.UnlockedTime != null)
.Select(s => s.PuzzleID)
.ToListAsync()));

var puzzles = new List<PuzzleStats>(puzzlesData.Count);
for (int i = 0; i < puzzlesData.Count; i++)
{
var data = puzzlesData[i];

// For players, we will hide puzzles they have not unlocked yet.
if (EventRole == EventRole.play &&
(unlockedData == null ||
lambertwang-zz marked this conversation as resolved.
Show resolved Hide resolved
!unlockedData.Contains(data.Puzzle.ID)))
{
continue;
}

var stats = new PuzzleStats()
{
Puzzle = data.Puzzle,
SolveCount = data.SolveCount,
SortOrder = i,
Fastest = data.Fastest.Select(f => new FastRecord() { ID = f.ID, Name = teamNameLookup[f.ID], Time = f.Time }).ToArray()
Fastest = data.Fastest.Select(f => new FastRecord() { ID = f.ID, Name = teamNameLookup[f.ID], Time = f.Time }).ToArray(),
IsSolved = data.IsSolvedByUserTeam
};

puzzles.Add(stats);
}

if (this.StateFilter == PuzzleStateFilter.Unsolved)
{
puzzles = puzzles.Where(stats => !stats.IsSolved).ToList();
}

switch (sort ?? DefaultSort)
{
case SortOrder.RankAscending:
puzzles.Sort((rhs, lhs) => (rhs.SortOrder - lhs.SortOrder));
break;
case SortOrder.RankDescending:
puzzles.Sort((rhs, lhs) => (lhs.SortOrder - rhs.SortOrder));
break;
case SortOrder.CountAscending:
puzzles.Sort((rhs, lhs) => (rhs.SolveCount - lhs.SolveCount));
break;
case SortOrder.CountDescending:
puzzles.Sort((rhs, lhs) => (lhs.SolveCount - rhs.SolveCount));
break;
case SortOrder.PuzzleAscending:
puzzles.Sort((rhs, lhs) => (String.Compare(rhs.Puzzle.Name,
lhs.Puzzle.Name,
StringComparison.OrdinalIgnoreCase)));

break;
case SortOrder.PuzzleDescending:
puzzles.Sort((rhs, lhs) => (String.Compare(lhs.Puzzle.Name,
rhs.Puzzle.Name,
StringComparison.OrdinalIgnoreCase)));

break;
default:
throw new ArgumentException($"unknown sort: {sort}");
}

this.Puzzles = puzzles;
}

public SortOrder? SortForColumnLink(SortOrder ascendingSort, SortOrder descendingSort)
{
SortOrder result = ascendingSort;

if (result == (this.Sort ?? DefaultSort))
{
result = descendingSort;
}

if (result == DefaultSort)
{
return null;
}

return result;
}

public class PuzzleStats
{
public Puzzle Puzzle;
public int SolveCount;
public int SortOrder;
public FastRecord[] Fastest;
public bool IsSolved;
}

public class FastRecord
Expand All @@ -74,5 +157,21 @@ public class FastRecord
public string Name;
public TimeSpan? Time;
}

public enum SortOrder
{
RankAscending,
RankDescending,
PuzzleAscending,
PuzzleDescending,
CountAscending,
CountDescending
}

public enum PuzzleStateFilter
{
All,
Unsolved
}
}
}
10 changes: 10 additions & 0 deletions ServerCore/Pages/Teams/Play.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,16 @@
<input id="StateFilter" name="StateFilter" value="Unsolved" type="radio" @(unsolvedFilter ? "checked" : "")> Unsolved
</a>
</div>
<br/>
<a asp-page="/Events/FastestSolves"
asp-route-sort="CountDescending"
asp-route-stateFilter="Unsolved">

Feeling stuck?
</a>
<br/>
The link above will take you to a page where you can view puzzles, sorted by how many teams have solved them.
<br/>
<br/>
<table class="table">
<thead>
Expand Down