Finished the results page
This commit is contained in:
parent
d6b09e2305
commit
3107bd8a2f
6
main.go
6
main.go
|
@ -52,8 +52,8 @@ func main() {
|
||||||
app.Get("/", func(c *fiber.Ctx) error {
|
app.Get("/", func(c *fiber.Ctx) error {
|
||||||
return c.Render("index", fiber.Map{})
|
return c.Render("index", fiber.Map{})
|
||||||
})
|
})
|
||||||
app.Get("/end", func(c *fiber.Ctx) error {
|
app.Get("/results", func(c *fiber.Ctx) error {
|
||||||
return c.Render("end", fiber.Map{})
|
return c.Render("results", fiber.Map{})
|
||||||
})
|
})
|
||||||
app.Get("/:qid", func(c *fiber.Ctx) error {
|
app.Get("/:qid", func(c *fiber.Ctx) error {
|
||||||
qID, err := c.ParamsInt("qid")
|
qID, err := c.ParamsInt("qid")
|
||||||
|
@ -71,7 +71,7 @@ func main() {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
nextURL := prefix + "/end"
|
nextURL := prefix + "/results"
|
||||||
reachedEnd := true
|
reachedEnd := true
|
||||||
if idx+1 < len(questions.Questions) {
|
if idx+1 < len(questions.Questions) {
|
||||||
nextURL = fmt.Sprintf("%v/%d", prefix, idx+2)
|
nextURL = fmt.Sprintf("%v/%d", prefix, idx+2)
|
||||||
|
|
|
@ -2,9 +2,11 @@ import { Controller } from "https://unpkg.com/@hotwired/stimulus/dist/stimulus.j
|
||||||
import { gameState } from "./gamestate.js";
|
import { gameState } from "./gamestate.js";
|
||||||
|
|
||||||
const ANIMATION_DURATION = 1500.0;
|
const ANIMATION_DURATION = 1500.0;
|
||||||
|
const MAX_QUESTIONS = 10;
|
||||||
|
const CIRCLE_RADIUS = 50;
|
||||||
|
|
||||||
export default class extends Controller {
|
export default class extends Controller {
|
||||||
static targets = ['path', 'count'];
|
static targets = ['path', 'pathBack', 'count', 'postScore', 'rank'];
|
||||||
|
|
||||||
connect() {
|
connect() {
|
||||||
this._startT = 0;
|
this._startT = 0;
|
||||||
|
@ -13,41 +15,41 @@ export default class extends Controller {
|
||||||
}
|
}
|
||||||
|
|
||||||
_startAnimating(t) {
|
_startAnimating(t) {
|
||||||
this._finalScore = 3;
|
this._finalScore = 10;
|
||||||
|
|
||||||
this._startT = t;
|
this._startT = t;
|
||||||
this._finalArcPostition = 360 * this._finalScore / 10;
|
this._finalArcPostition = 360 * this._finalScore / MAX_QUESTIONS;
|
||||||
this._updateCounterEvery = ANIMATION_DURATION / this._finalScore;
|
|
||||||
this._updateCounterAt = 0;
|
|
||||||
|
|
||||||
this._currentlyDisplayedScore = 0;
|
this._currentlyDisplayedScore = 0;
|
||||||
this.countTarget.innerText = "0";
|
this.countTarget.innerText = "0%";
|
||||||
requestAnimationFrame(this._animateFrame.bind(this));
|
requestAnimationFrame(this._animateFrame.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
_animateFrame(t) {
|
_animateFrame(t) {
|
||||||
let tt = t - this._startT;
|
let tt = t - this._startT;
|
||||||
|
let tScaled = tt / ANIMATION_DURATION;
|
||||||
|
|
||||||
if (tt >= ANIMATION_DURATION) {
|
if (tt >= ANIMATION_DURATION) {
|
||||||
|
|
||||||
if (this._finalArcPostition == 360) {
|
if (this._finalArcPostition == 360) {
|
||||||
this.pathTarget.setAttribute("d", this._describeCircle(50, 50, 45));
|
this.pathTarget.setAttribute("d", this._describeCircle(CIRCLE_RADIUS, CIRCLE_RADIUS, CIRCLE_RADIUS - 5));
|
||||||
} else {
|
} else {
|
||||||
this.pathTarget.setAttribute("d", this._describeArc(50, 50, 45, 0, this._finalArcPostition));
|
this.pathTarget.setAttribute("d", this._describeArc(CIRCLE_RADIUS, CIRCLE_RADIUS, CIRCLE_RADIUS - 5, 0, this._finalArcPostition));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.countTarget.innerText = this._finalScore.toString();
|
let scoreToDisplay = (this._finalScore * 100 / MAX_QUESTIONS) | 0;
|
||||||
|
this.countTarget.innerText = `${scoreToDisplay}%`;
|
||||||
|
window.setTimeout(() => this._showPostStore(), 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let arcT = Math.sin(tt / ANIMATION_DURATION * Math.PI / 2.0);
|
let arcT = Math.sin(tt / ANIMATION_DURATION * Math.PI / 2.0);
|
||||||
|
|
||||||
this.pathTarget.setAttribute("d", this._describeArc(50, 50, 45, 0, this._finalArcPostition * arcT));
|
this.pathTarget.setAttribute("d", this._describeArc(CIRCLE_RADIUS, CIRCLE_RADIUS, CIRCLE_RADIUS - 5, 0, this._finalArcPostition * arcT));
|
||||||
|
|
||||||
if (tt >= this._updateCounterAt) {
|
let scoreToDisplay = (arcT * this._finalScore * 100 / MAX_QUESTIONS) | 0;
|
||||||
this._currentlyDisplayedScore++;
|
if (scoreToDisplay != this._currentlyDisplayedScore) {
|
||||||
this.countTarget.innerText = this._currentlyDisplayedScore.toString();
|
this._currentlyDisplayedScore = scoreToDisplay;
|
||||||
this._updateCounterAt += this._updateCounterEvery;
|
this.countTarget.innerText = `${scoreToDisplay}%`;
|
||||||
}
|
}
|
||||||
|
|
||||||
requestAnimationFrame(this._animateFrame.bind(this));
|
requestAnimationFrame(this._animateFrame.bind(this));
|
||||||
|
@ -87,4 +89,9 @@ export default class extends Controller {
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_showPostStore() {
|
||||||
|
this.rankTarget.innerText = "Developer";
|
||||||
|
|
||||||
|
this.postScoreTarget.classList.remove("hidden");
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,3 +1,7 @@
|
||||||
|
:root {
|
||||||
|
--score-color: green;
|
||||||
|
}
|
||||||
|
|
||||||
div.offscreen {
|
div.offscreen {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
left: -100px;
|
left: -100px;
|
||||||
|
@ -85,6 +89,65 @@ input[type=radio] {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.vspacer {
|
||||||
|
height: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Your score
|
||||||
|
*/
|
||||||
|
div.score-wrapper {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.yourscore {
|
||||||
|
margin-inline: auto;
|
||||||
|
position: relative;
|
||||||
|
text-align: left;
|
||||||
|
|
||||||
|
width: 250px;
|
||||||
|
height: 250px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.yourscore svg {
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: -10;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.yourscore svg path {
|
||||||
|
stroke: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.yourscore svg path.score {
|
||||||
|
stroke: var(--score-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
div.yourscore .counter {
|
||||||
|
position: absolute;
|
||||||
|
font-size: 4em;
|
||||||
|
|
||||||
|
top: calc(50% - 0.75em);
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
color: var(--score-color);
|
||||||
|
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.post-score {
|
||||||
|
margin-block-start: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.rank {
|
||||||
|
font-size: 1.5em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page transition
|
* Page transition
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
<h1>Well Done</h1>
|
|
||||||
|
|
||||||
<p>You reached the end</p>
|
|
||||||
|
|
||||||
<div data-controller="yourscore">
|
|
||||||
<svg xml:space="preserve" id="svg2" x="0" y="0" version="1.1" viewBox="0 0 100 100">
|
|
||||||
<g transform="rotate(90,50,50)">
|
|
||||||
<path data-yourscore-target="path" fill="none" stroke="#f8f8f8" stroke-width="10"/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
<div data-yourscore-target="count">0</div>
|
|
||||||
</div>
|
|
22
views/results.html
Normal file
22
views/results.html
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<h1>Results</h1>
|
||||||
|
|
||||||
|
<div data-controller="yourscore" class="score-wrapper">
|
||||||
|
<p>Your final score is</p>
|
||||||
|
<div>
|
||||||
|
<div class="yourscore">
|
||||||
|
<svg xml:space="preserve" id="svg2" x="0" y="0" version="1.1" viewBox="0 0 100 100">
|
||||||
|
<g transform="rotate(90,50,50)">
|
||||||
|
<path data-yourscore-target="pathBack" fill="none" stroke-width="10" d="M 5 50 A 45 45 0 0 0 95 50 A 45 45 0 1 0 5 50"/>
|
||||||
|
<path data-yourscore-target="path" fill="none" stroke-width="10" class="score"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
<div data-yourscore-target="count" class="counter">0%</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div data-yourscore-target="postScore" class="post-score hidden">
|
||||||
|
<div>You achieved a rank of</div>
|
||||||
|
<div data-yourscore-target="rank" class="rank"></div>
|
||||||
|
<div class="vspacer"></div>
|
||||||
|
<a href="{{prefix}}/end" class="button">Continue</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
Loading…
Reference in a new issue