-
Notifications
You must be signed in to change notification settings - Fork 7.1k
/
HomeController.cs
137 lines (121 loc) · 4.89 KB
/
HomeController.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using TailSpin.SpaceGame.Web.Models;
namespace TailSpin.SpaceGame.Web.Controllers
{
public class HomeController : Controller
{
// High score repository.
private readonly IDocumentDBRepository<Score> _scoreRepository;
// User profile repository.
private readonly IDocumentDBRepository<Profile> _profileRespository;
public HomeController(
IDocumentDBRepository<Score> scoreRepository,
IDocumentDBRepository<Profile> profileRespository
)
{
_scoreRepository = scoreRepository;
_profileRespository = profileRespository;
}
public async Task<IActionResult> Index(
int page = 1,
int pageSize = 10,
string mode = "",
string region = ""
)
{
// Create the view model with initial values we already know.
var vm = new LeaderboardViewModel
{
Page = page,
PageSize = pageSize,
SelectedMode = mode,
SelectedRegion = region,
GameModes = new List<string>()
{
"Solo",
"Duo",
"Trio"
},
GameRegions = new List<string>()
{
"Milky Way",
"Andromeda",
"Pinwheel",
"NGC 1300",
"Messier 82",
}
};
try
{
// Form the query predicate.
// Select all scores that match the provided game mode and region (map).
// Select the score if the game mode or region is empty.
Func<Score, bool> queryPredicate = score =>
(string.IsNullOrEmpty(mode) || score.GameMode == mode) &&
(string.IsNullOrEmpty(region) || score.GameRegion == region);
// Fetch the total number of results in the background.
var countItemsTask = _scoreRepository.CountItemsAsync(queryPredicate);
// Fetch the scores that match the current filter.
IEnumerable<Score> scores = await _scoreRepository.GetItemsAsync(
queryPredicate, // the predicate defined above
score => score.HighScore, // sort descending by high score
page - 1, // subtract 1 to make the query 0-based
pageSize
);
// Wait for the total count.
vm.TotalResults = await countItemsTask;
// Set previous and next hyperlinks.
if (page > 1)
{
vm.PrevLink = $"/?page={page - 1}&pageSize={pageSize}&mode={mode}®ion={region}#leaderboard";
}
if (vm.TotalResults > page * pageSize)
{
vm.NextLink = $"/?page={page + 1}&pageSize={pageSize}&mode={mode}®ion={region}#leaderboard";
}
// Fetch the user profile for each score.
// This creates a list that's parallel with the scores collection.
var profiles = new List<Task<Profile>>();
foreach (var score in scores)
{
profiles.Add(_profileRespository.GetItemAsync(score.ProfileId));
}
Task<Profile>.WaitAll(profiles.ToArray());
// Combine each score with its profile.
vm.Scores = scores.Zip(profiles, (score, profile) => new ScoreProfile { Score = score, Profile = profile.Result });
return View(vm);
}
catch (Exception)
{
return View(vm);
}
}
[Route("/profile/{id}")]
public async Task<IActionResult> Profile(string id, string rank="")
{
try
{
// Fetch the user profile with the given identifier.
return View(new ProfileViewModel { Profile = await _profileRespository.GetItemAsync(id), Rank = rank });
}
catch (Exception)
{
return RedirectToAction("/");
}
}
public IActionResult Privacy()
{
return View();
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
}
}