Added tracking of a player's state
This commit is contained in:
parent
64a2d4f9cb
commit
332cfd9fca
2
main.go
2
main.go
|
@ -15,6 +15,7 @@ func main() {
|
||||||
questions := models.QuestionSet{
|
questions := models.QuestionSet{
|
||||||
Questions: []models.Question{
|
Questions: []models.Question{
|
||||||
{
|
{
|
||||||
|
ID: "1",
|
||||||
Text: "What is 1 + 1?",
|
Text: "What is 1 + 1?",
|
||||||
Choices: []models.Choice{
|
Choices: []models.Choice{
|
||||||
{Text: "1"},
|
{Text: "1"},
|
||||||
|
@ -25,6 +26,7 @@ func main() {
|
||||||
Fact: "1 + 1 = 2",
|
Fact: "1 + 1 = 2",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
ID: "2",
|
||||||
Text: "What is 3 * 5?",
|
Text: "What is 3 * 5?",
|
||||||
Choices: []models.Choice{
|
Choices: []models.Choice{
|
||||||
{Text: "5"},
|
{Text: "5"},
|
||||||
|
|
|
@ -17,6 +17,7 @@ type Choice struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Question struct {
|
type Question struct {
|
||||||
|
ID string
|
||||||
Text string
|
Text string
|
||||||
Choices []Choice
|
Choices []Choice
|
||||||
Fact string
|
Fact string
|
||||||
|
@ -38,6 +39,7 @@ func (q Question) Render() (RenderedQuestion, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return RenderedQuestion{
|
return RenderedQuestion{
|
||||||
|
ID: q.ID,
|
||||||
Question: q.Text,
|
Question: q.Text,
|
||||||
Fact: q.Fact,
|
Fact: q.Fact,
|
||||||
Choices: choices,
|
Choices: choices,
|
||||||
|
@ -51,6 +53,7 @@ type RenderedChoice struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type RenderedQuestion struct {
|
type RenderedQuestion struct {
|
||||||
|
ID string
|
||||||
Question string
|
Question string
|
||||||
Fact string
|
Fact string
|
||||||
Choices []RenderedChoice
|
Choices []RenderedChoice
|
||||||
|
|
9
public/scripts/controllers/clearstate.js
Normal file
9
public/scripts/controllers/clearstate.js
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
import { Controller } from "https://unpkg.com/@hotwired/stimulus/dist/stimulus.js";
|
||||||
|
import { gameState } from "./gamestate.js";
|
||||||
|
|
||||||
|
export default class extends Controller {
|
||||||
|
startGame(ev) {
|
||||||
|
console.log("Start game");
|
||||||
|
gameState.clearChoices();
|
||||||
|
}
|
||||||
|
}
|
32
public/scripts/controllers/gamestate.js
Normal file
32
public/scripts/controllers/gamestate.js
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
const GAME_STATE_KEY = "gameState";
|
||||||
|
|
||||||
|
class GameState {
|
||||||
|
getQuestionChoice(qId) {
|
||||||
|
let savedItem = this._readGameState();
|
||||||
|
if (qId in savedItem) {
|
||||||
|
return savedItem[qId];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
setQuestionChoice(qId, cId) {
|
||||||
|
let savedItem = this._readGameState();
|
||||||
|
savedItem[qId] = cId;
|
||||||
|
localStorage.setItem(GAME_STATE_KEY, JSON.stringify(savedItem));
|
||||||
|
}
|
||||||
|
|
||||||
|
clearChoices() {
|
||||||
|
localStorage.removeItem(GAME_STATE_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
_readGameState() {
|
||||||
|
let savedItem = localStorage.getItem(GAME_STATE_KEY);
|
||||||
|
if (savedItem === null) {
|
||||||
|
return {};
|
||||||
|
} else {
|
||||||
|
return JSON.parse(savedItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export let gameState = new GameState();
|
|
@ -1,30 +1,57 @@
|
||||||
import { Controller } from "https://unpkg.com/@hotwired/stimulus/dist/stimulus.js";
|
import { Controller } from "https://unpkg.com/@hotwired/stimulus/dist/stimulus.js";
|
||||||
|
import { gameState } from "./gamestate.js";
|
||||||
|
|
||||||
export default class extends Controller {
|
export default class extends Controller {
|
||||||
static targets = ["radio", "answerDetails"];
|
static targets = ["radio", "answerDetails", "submit"];
|
||||||
|
|
||||||
static values = {
|
static values = {
|
||||||
|
qid: String,
|
||||||
answer: String
|
answer: String
|
||||||
};
|
};
|
||||||
|
|
||||||
connect() {
|
connect() {
|
||||||
|
let hasAnswer = gameState.getQuestionChoice(this.qidValue);
|
||||||
|
if (hasAnswer) {
|
||||||
|
this._revealAnswer();
|
||||||
|
|
||||||
|
let e = this.radioTargets.find((e) => e.value == hasAnswer);
|
||||||
|
if (e) {
|
||||||
|
e.checked = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkRadio(ev) {
|
||||||
|
this.submitTarget.disabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
submitAnswer(ev) {
|
submitAnswer(ev) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
|
|
||||||
|
this.submitTarget.disabled = false;
|
||||||
|
let e = this.radioTargets.find((e) => e.checked);
|
||||||
|
if (!e) {
|
||||||
|
alert("Please select an item");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gameState.setQuestionChoice(this.qidValue, e.value);
|
||||||
|
|
||||||
|
this.element.classList.add("reveal");
|
||||||
|
window.setTimeout(() => { this._revealAnswer(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
_revealAnswer() {
|
||||||
this.element.classList.add("reveal");
|
this.element.classList.add("reveal");
|
||||||
|
|
||||||
window.setTimeout(() => {
|
this.radioTargets.forEach(e => {
|
||||||
this.radioTargets.forEach(e => {
|
e.disabled = true;
|
||||||
e.disabled = true;
|
if (e.value === this.answerValue) {
|
||||||
if (e.value === this.answerValue) {
|
e.classList.add("answer");
|
||||||
e.classList.add("answer");
|
} else {
|
||||||
} else {
|
e.classList.add("wrong");
|
||||||
e.classList.add("wrong");
|
}
|
||||||
}
|
});
|
||||||
});
|
|
||||||
}, 1);
|
|
||||||
|
|
||||||
this.answerDetailsTarget.classList.remove("hidden");
|
this.answerDetailsTarget.classList.remove("hidden");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
import { Application } from "https://unpkg.com/@hotwired/stimulus/dist/stimulus.js";
|
import { Application } from "https://unpkg.com/@hotwired/stimulus/dist/stimulus.js";
|
||||||
|
|
||||||
|
import ClearStateController from "./controllers/clearstate.js";
|
||||||
import PickerController from "./controllers/picker.js";
|
import PickerController from "./controllers/picker.js";
|
||||||
|
|
||||||
window.Stimulus = Application.start();
|
window.Stimulus = Application.start();
|
||||||
|
|
||||||
Stimulus.register("picker", PickerController);
|
Stimulus.register("picker", PickerController);
|
||||||
|
Stimulus.register("clearstate", ClearStateController);
|
|
@ -24,6 +24,7 @@ label:has(input[type=radio]) {
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
label:has(input[type=radio]):hover {
|
label:has(input[type=radio]):hover {
|
||||||
|
|
|
@ -2,4 +2,4 @@
|
||||||
|
|
||||||
<p>Welcome to the quiz</p>
|
<p>Welcome to the quiz</p>
|
||||||
|
|
||||||
<a href="{{prefix}}/1">Lets go</a>
|
<a data-controller="clearstate" data-action="clearstate#startGame" href="{{prefix}}/1">Lets go</a>
|
|
@ -6,6 +6,7 @@
|
||||||
<link rel="stylesheet" href="https://cdn.simplecss.org/simple.min.css">
|
<link rel="stylesheet" href="https://cdn.simplecss.org/simple.min.css">
|
||||||
<link rel="stylesheet" href="{{prefix}}/assets/style.css">
|
<link rel="stylesheet" href="{{prefix}}/assets/style.css">
|
||||||
<link rel="stylesheet" href="{{prefix}}/assets/fontello/css/fontello.css">
|
<link rel="stylesheet" href="{{prefix}}/assets/fontello/css/fontello.css">
|
||||||
|
<script src="{{prefix}}/assets/scripts/main.js" type="module"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
{{embed}}
|
{{embed}}
|
||||||
|
|
|
@ -3,12 +3,13 @@
|
||||||
<i class="icon-ok"></i>
|
<i class="icon-ok"></i>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="question" data-controller="picker" data-picker-answer-value="{{.q.RightChoice}}">
|
<div class="question" data-controller="picker"
|
||||||
|
data-picker-qid-value="{{.q.ID}}" data-picker-answer-value="{{.q.RightChoice}}">
|
||||||
<p>{{.q.Question}}</p>
|
<p>{{.q.Question}}</p>
|
||||||
|
|
||||||
{{range .q.Choices}}
|
{{range .q.Choices}}
|
||||||
<label>
|
<label>
|
||||||
<input type="radio" name="ans" value="{{.ID}}" data-picker-target="radio">
|
<input type="radio" name="ans" value="{{.ID}}" data-picker-target="radio" data-action="picker#checkRadio">
|
||||||
{{if eq .ID $.q.RightChoice}}
|
{{if eq .ID $.q.RightChoice}}
|
||||||
<i class="icon-ok"></i>
|
<i class="icon-ok"></i>
|
||||||
{{else}}
|
{{else}}
|
||||||
|
@ -18,7 +19,7 @@
|
||||||
</label>
|
</label>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
<button data-action="picker#submitAnswer">Submit</button>
|
<button disabled data-picker-target="submit" data-action="picker#submitAnswer">Submit</button>
|
||||||
|
|
||||||
<div data-picker-target="answerDetails" class="hidden">
|
<div data-picker-target="answerDetails" class="hidden">
|
||||||
<p>{{.q.Fact}}</p>
|
<p>{{.q.Fact}}</p>
|
||||||
|
@ -26,6 +27,4 @@
|
||||||
<a href="{{.nextURL}}">Next</a>
|
<a href="{{.nextURL}}">Next</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="{{prefix}}/assets/scripts/main.js" type="module"></script>
|
|
Loading…
Reference in a new issue