diff --git a/ServerCore/Pages/Events/CreateDemo.cshtml b/ServerCore/Pages/Events/CreateDemo.cshtml new file mode 100644 index 00000000..c88d2bc6 --- /dev/null +++ b/ServerCore/Pages/Events/CreateDemo.cshtml @@ -0,0 +1,63 @@ +@page +@model ServerCore.Pages.Events.CreateDemoModel + +@{ + ViewData["Title"] = "Create Demo Event"; +} + +

Create Demo Event

+ +

Demo Event

+
+
+
+
+
+
+ + + +
+
+ + + +
+
+ + + +
+
+
+ +
+
+
+
+ Usage: +
    +
  • The default event start time is now (in UTC), and the default event end is one day later. Adjust them now if you want.
  • +
  • Related times will update to roughly matching values.
  • +
  • All puzzles have a partial named PARTIAL, and an answer named ANSWER.
  • +
  • If you check the "StartTheEvent" checkbox, the start puzzle will unlock now.
  • +
  • If you do not check that box, then you will need to mark that puzzle as solved on that puzzle's Status page.
  • +
+
+
+
+ +
+
+
+
+ +
+ Back to List +
+ +@section Scripts { + @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} +} diff --git a/ServerCore/Pages/Events/CreateDemo.cshtml.cs b/ServerCore/Pages/Events/CreateDemo.cshtml.cs new file mode 100644 index 00000000..16d29b68 --- /dev/null +++ b/ServerCore/Pages/Events/CreateDemo.cshtml.cs @@ -0,0 +1,191 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; +using ServerCore.DataModel; + +namespace ServerCore.Pages.Events +{ + public class CreateDemoModel : PageModel + { + private readonly PuzzleServerContext _context; + + [BindProperty] + public Event Event { get; set; } + + [BindProperty] + public bool StartTheEvent { get; set; } + + public CreateDemoModel(PuzzleServerContext context) + { + _context = context; + } + + public IActionResult OnGet() + { + // Populate default fields + Event = new Event(); + + for (int i = 1; ; i++) + { + string name = $"Watership Demo {i}"; + if (_context.Events.Where(e => e.Name == name).FirstOrDefault() == null) + { + Event.Name = name; + break; + } + } + + DateTime now = DateTime.UtcNow; + Event.TeamRegistrationBegin = now; + Event.StandingsAvailableBegin = now; + Event.EventBegin = now; + Event.AnswerSubmissionEnd = now.AddDays(1); + + return Page(); + } + + public async Task OnPostAsync() + { + if (!ModelState.IsValid) + { + return Page(); + } + + // + // Add the event and save, so the event gets an ID. + // + Event.TeamRegistrationEnd = Event.AnswerSubmissionEnd; + Event.TeamNameChangeEnd = Event.AnswerSubmissionEnd; + Event.TeamMembershipChangeEnd = Event.AnswerSubmissionEnd; + Event.TeamMiscDataChangeEnd = Event.AnswerSubmissionEnd; + Event.TeamDeleteEnd = Event.AnswerSubmissionEnd; + Event.AnswersAvailableBegin = Event.AnswerSubmissionEnd; + _context.Events.Add(Event); + + await _context.SaveChangesAsync(); + + // + // Add start puzzle, three module puzzles, and one module meta (marked as the final event puzzle for this demo) + // + Puzzle start = new Puzzle + { + Name = "!!!Get Hopping!!!", + Event = Event, + IsPuzzle = false + }; + _context.Puzzles.Add(start); + + Puzzle easy = new Puzzle + { + Name = "Bunny Slope", + Event = Event, + IsPuzzle = true, + SolveValue = 10, + Group = "Thumper's Stumpers", + OrderInGroup = 1, + MinPrerequisiteCount = 1 + }; + _context.Puzzles.Add(easy); + + Puzzle intermediate = new Puzzle + { + Name = "Rabbit Run", + Event = Event, + IsPuzzle = true, + SolveValue = 10, + Group = "Thumper's Stumpers", + OrderInGroup = 2, + MinPrerequisiteCount = 1 + }; + _context.Puzzles.Add(intermediate); + + Puzzle hard = new Puzzle + { + Name = "Hare-Raising", + Event = Event, + IsPuzzle = true, + SolveValue = 10, + Group = "Thumper's Stumpers", + OrderInGroup = 3, + MinPrerequisiteCount = 1 + }; + _context.Puzzles.Add(hard); + + Puzzle meta = new Puzzle + { + Name = "Lagomorph Meta", + Event = Event, + IsPuzzle = true, + IsMetaPuzzle = true, + IsFinalPuzzle = true, + SolveValue = 100, + Group = "Thumper's Stumpers", + OrderInGroup = 99, + MinPrerequisiteCount = 2 + }; + _context.Puzzles.Add(meta); + + await _context.SaveChangesAsync(); + + // + // Add responses, PARTIAL is a partial, ANSWER is the answer. + // + _context.Responses.Add(new Response() { Puzzle = easy, SubmittedText = "PARTIAL", ResponseText = "Keep going..." }); + _context.Responses.Add(new Response() { Puzzle = easy, SubmittedText = "ANSWER", ResponseText = "Correct!", IsSolution = true }); + _context.Responses.Add(new Response() { Puzzle = intermediate, SubmittedText = "PARTIAL", ResponseText = "Keep going..." }); + _context.Responses.Add(new Response() { Puzzle = intermediate, SubmittedText = "ANSWER", ResponseText = "Correct!", IsSolution = true }); + _context.Responses.Add(new Response() { Puzzle = hard, SubmittedText = "PARTIAL", ResponseText = "Keep going..." }); + _context.Responses.Add(new Response() { Puzzle = hard, SubmittedText = "ANSWER", ResponseText = "Correct!", IsSolution = true }); + _context.Responses.Add(new Response() { Puzzle = meta, SubmittedText = "PARTIAL", ResponseText = "Keep going..." }); + _context.Responses.Add(new Response() { Puzzle = meta, SubmittedText = "ANSWER", ResponseText = "Correct!", IsSolution = true }); + + await _context.SaveChangesAsync(); + + // + // Set up prequisite links. + // The first two depend on start puzzle, then the third depends on one of the first two, then the meta depends on two of the first three. + // + _context.Prerequisites.Add(new Prerequisites() { Puzzle = easy, Prerequisite = start }); + _context.Prerequisites.Add(new Prerequisites() { Puzzle = intermediate, Prerequisite = start }); + _context.Prerequisites.Add(new Prerequisites() { Puzzle = hard, Prerequisite = easy }); + _context.Prerequisites.Add(new Prerequisites() { Puzzle = hard, Prerequisite = intermediate }); + _context.Prerequisites.Add(new Prerequisites() { Puzzle = meta, Prerequisite = easy }); + _context.Prerequisites.Add(new Prerequisites() { Puzzle = meta, Prerequisite = intermediate }); + _context.Prerequisites.Add(new Prerequisites() { Puzzle = meta, Prerequisite = hard }); + + await _context.SaveChangesAsync(); + + // + // Create teams. Can we add players to these? + // + Team team1 = new Team { Name = "Team Bugs", Event = Event }; + _context.Teams.Add(team1); + + Team team2 = new Team { Name = "Team Babs", Event = Event }; + _context.Teams.Add(team2); + + Team team3 = new Team { Name = "Team Buster", Event = Event }; + _context.Teams.Add(team3); + + await _context.SaveChangesAsync(); + + // TODO: Event Owners + // TODO: Puzzle Authors + // TODO: Team Members + // TODO: Files (need to know how to detect whether local blob storage is configured) + // Is there a point to adding Feedback or is that quick/easy enough to demo by hand? + + // + // Mark the start puzzle as solved if we were asked to. + // + if (StartTheEvent) + { + await PuzzleStateHelper.SetSolveStateAsync(_context, Event, start, null, DateTime.UtcNow); + } + + return RedirectToPage("./Index"); + } + } +} \ No newline at end of file diff --git a/ServerCore/Pages/Events/Index.cshtml b/ServerCore/Pages/Events/Index.cshtml index aa345af8..d57e7ff7 100644 --- a/ServerCore/Pages/Events/Index.cshtml +++ b/ServerCore/Pages/Events/Index.cshtml @@ -8,7 +8,8 @@

Index

- Create New + Create New
+ Create New with demo content

diff --git a/ServerCore/Pages/Teams/Play.cshtml b/ServerCore/Pages/Teams/Play.cshtml index d44af7d6..cdfa01a4 100644 --- a/ServerCore/Pages/Teams/Play.cshtml +++ b/ServerCore/Pages/Teams/Play.cshtml @@ -50,7 +50,7 @@ @Html.DisplayFor(modelItem => item.Puzzle.Group)
- @Html.DisplayFor(modelItem => item.Puzzle.OrderInGroup) + @((item.Puzzle.IsMetaPuzzle || item.Puzzle.IsFinalPuzzle) ? "Meta" : item.Puzzle.OrderInGroup.ToString()) @Html.DisplayFor(modelItem => item.Puzzle.PuzzleFile.ShortName)