guess-the-year-web-component 3.2.3 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/custom-elements.json +19 -1
- package/dist/guess-the-year.d.ts +21 -16
- package/dist/guess-the-year.d.ts.map +1 -1
- package/dist/index.html +3 -8
- package/dist/lib/controller/scorecontroller.d.ts +2 -1
- package/dist/lib/controller/scorecontroller.d.ts.map +1 -1
- package/dist/lib/i18n/EN.d.ts.map +1 -1
- package/dist/lib/i18n/NL.d.ts.map +1 -1
- package/dist/main.bundle.js +200 -0
- package/dist/main.bundle.js.map +1 -0
- package/package.json +26 -27
- package/src/guess-the-year.ts +335 -273
- package/src/index.html +2 -7
- package/src/lib/ApiService.ts +1 -1
- package/src/lib/Util.ts +1 -1
- package/src/lib/controller/scorecontroller.ts +12 -1
- package/src/lib/i18n/EN.ts +18 -4
- package/src/lib/i18n/NL.ts +19 -5
- package/src/scss/_layout.scss +18 -5
- package/src/scss/_typography.scss +3 -2
- package/src/scss/_variables.scss +5 -5
- package/src/scss/main.scss +55 -1
- package/src/scss/views/_intro.scss +16 -4
- package/src/scss/views/_stage.scss +149 -43
- package/webpack.config.cjs +23 -25
- package/dist/guess-the-year.js +0 -751
- package/dist/guess-the-year.js.map +0 -1
- package/dist/lib/ApiService.js +0 -134
- package/dist/lib/ApiService.js.map +0 -1
- package/dist/lib/Icon.js +0 -2
- package/dist/lib/Icon.js.map +0 -1
- package/dist/lib/Incident.js +0 -37
- package/dist/lib/Incident.js.map +0 -1
- package/dist/lib/Util.js +0 -69
- package/dist/lib/Util.js.map +0 -1
- package/dist/lib/controller/scorecontroller.js +0 -38
- package/dist/lib/controller/scorecontroller.js.map +0 -1
- package/dist/lib/enums.js +0 -10
- package/dist/lib/enums.js.map +0 -1
- package/dist/lib/i18n/EN.js +0 -148
- package/dist/lib/i18n/EN.js.map +0 -1
- package/dist/lib/i18n/NL.js +0 -152
- package/dist/lib/i18n/NL.js.map +0 -1
- package/dist/lib/i18n/i18n.js +0 -10
- package/dist/lib/i18n/i18n.js.map +0 -1
- package/dist/main.js +0 -205
- package/todo.txt +0 -0
- /package/dist/{main.js.LICENSE.txt → main.bundle.js.LICENSE.txt} +0 -0
package/dist/guess-the-year.js
DELETED
|
@@ -1,751 +0,0 @@
|
|
|
1
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
-
};
|
|
7
|
-
import { LitElement, css, html } from "lit";
|
|
8
|
-
import { customElement, property, state } from "lit/decorators.js";
|
|
9
|
-
import dayjs from "dayjs";
|
|
10
|
-
import { Dayjs } from "dayjs";
|
|
11
|
-
const { setTimeout } = window;
|
|
12
|
-
import { Categories, Category } from "./lib/Incident";
|
|
13
|
-
import { NoImageImg } from "./lib/Icon";
|
|
14
|
-
import { ApiService, ContentFeedback } from "./lib/ApiService";
|
|
15
|
-
import { Util } from "./lib/Util";
|
|
16
|
-
import { i18nFactory } from "./lib/i18n/i18n";
|
|
17
|
-
import { GameState } from "./lib/enums";
|
|
18
|
-
import stylesheet from "./scss/main.scss";
|
|
19
|
-
import { QuestionScoreController } from "./lib/controller/scorecontroller";
|
|
20
|
-
const SPLASH_DELAY = 1000;
|
|
21
|
-
const MAX_QUESTIONS = 10;
|
|
22
|
-
const HINT_COST = 2;
|
|
23
|
-
const MIN_YEAR = 1950;
|
|
24
|
-
const MAX_YEAR = parseInt(dayjs().format('YYYY'), 10);
|
|
25
|
-
const GTY_FROM_YEAR_VAR = 'gty-from-year';
|
|
26
|
-
const GTY_TO_YEAR_VAR = 'gty-to-year';
|
|
27
|
-
const GTY_NUM_QUESTIONS_VAR = 'gty-number-of-questions';
|
|
28
|
-
const MAX_DOB = 1915;
|
|
29
|
-
const MIN_DOB = parseInt(dayjs().format('YYYY'), 10) - 10;
|
|
30
|
-
const GTY_PLAYER_DOB_VAR = 'gty-player-dob';
|
|
31
|
-
let GuessTheYear = class GuessTheYear extends LitElement {
|
|
32
|
-
get loading() {
|
|
33
|
-
return this._loading;
|
|
34
|
-
}
|
|
35
|
-
set loading(value) {
|
|
36
|
-
this._loading = value;
|
|
37
|
-
}
|
|
38
|
-
constructor() {
|
|
39
|
-
super();
|
|
40
|
-
this.sources = [];
|
|
41
|
-
this._loading = false;
|
|
42
|
-
this.teeeApiUrl = "https://api.tee-e.com";
|
|
43
|
-
this.reportBrokenImages = false;
|
|
44
|
-
this.date = "";
|
|
45
|
-
this.country = "";
|
|
46
|
-
this.category = "";
|
|
47
|
-
this.emotion = "";
|
|
48
|
-
this.impact = "";
|
|
49
|
-
this.from = dayjs(`${window.localStorage.getItem(GTY_FROM_YEAR_VAR) || MIN_YEAR}-01-01`, "YYYY-MM-DD");
|
|
50
|
-
this.to = dayjs(`${window.localStorage.getItem(GTY_TO_YEAR_VAR) || MAX_YEAR}-01-01`, "YYYY-MM-DD");
|
|
51
|
-
this.noImageSrc = "";
|
|
52
|
-
this.suppressImages = false;
|
|
53
|
-
this.maxHints = 3;
|
|
54
|
-
this.numberOfQuestions = parseInt(window.localStorage.getItem(GTY_NUM_QUESTIONS_VAR) || MAX_QUESTIONS + '', 10);
|
|
55
|
-
this._numberOfQuestionsSeen = 0;
|
|
56
|
-
this._playerDob = parseInt(window.localStorage.getItem(GTY_PLAYER_DOB_VAR) || 0 + '', 10);
|
|
57
|
-
this._incident = undefined;
|
|
58
|
-
this._answers = [];
|
|
59
|
-
this._hint = undefined;
|
|
60
|
-
this._showHint = true;
|
|
61
|
-
this._showFooter = false;
|
|
62
|
-
this._hintsIndex = 0;
|
|
63
|
-
this._hints = [];
|
|
64
|
-
this._solution = undefined;
|
|
65
|
-
this._renderState = GameState.INIT;
|
|
66
|
-
this._score = 30;
|
|
67
|
-
this.totalScore = 0;
|
|
68
|
-
// _answer is stored as string because it will be entered character for character
|
|
69
|
-
this._answer = undefined;
|
|
70
|
-
this._apiService = new ApiService(this.teeeApiUrl);
|
|
71
|
-
this.i18n = i18nFactory("nl");
|
|
72
|
-
this._handleImageLoadError = (evt, incident) => {
|
|
73
|
-
// grab the image element that triggered the error
|
|
74
|
-
const targetImage = evt.target;
|
|
75
|
-
console.debug(`Error loading image: ${targetImage.src} `);
|
|
76
|
-
// find out which no image source needs to be used
|
|
77
|
-
const noImageSrc = this.noImageSrc || NoImageImg;
|
|
78
|
-
// don't try to set the image source if it
|
|
79
|
-
// has already been set
|
|
80
|
-
if (targetImage.src == noImageSrc) {
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
// report broken images back to the server if set.
|
|
84
|
-
if (this.reportBrokenImages) {
|
|
85
|
-
if (incident) {
|
|
86
|
-
this._apiService.postAttributeQualityFeedback(incident.id, "image", targetImage.src, ContentFeedback.incorrect);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
// wait a bit before setting the image
|
|
90
|
-
// so we don't hammer the no image server
|
|
91
|
-
setTimeout(() => {
|
|
92
|
-
targetImage.src = noImageSrc;
|
|
93
|
-
}, 250);
|
|
94
|
-
return false;
|
|
95
|
-
};
|
|
96
|
-
this._score0 = new QuestionScoreController(this, 30, 1000);
|
|
97
|
-
}
|
|
98
|
-
connectedCallback() {
|
|
99
|
-
console.debug("connectedCallback");
|
|
100
|
-
super.connectedCallback();
|
|
101
|
-
// first step is splash
|
|
102
|
-
this._renderState = GameState.SPLASH;
|
|
103
|
-
}
|
|
104
|
-
disconnectedCallback() {
|
|
105
|
-
console.debug("disconnectedCallback");
|
|
106
|
-
super.disconnectedCallback();
|
|
107
|
-
this._renderState = GameState.INIT;
|
|
108
|
-
this._score0.stop();
|
|
109
|
-
this._score0.reset();
|
|
110
|
-
}
|
|
111
|
-
firstUpdated(changedProperties) {
|
|
112
|
-
console.debug("firstUpdated");
|
|
113
|
-
super.firstUpdated(changedProperties);
|
|
114
|
-
}
|
|
115
|
-
shouldUpdate(changedProperties) {
|
|
116
|
-
console.debug("shouldUpdate");
|
|
117
|
-
return super.shouldUpdate(changedProperties);
|
|
118
|
-
}
|
|
119
|
-
update(changedProperties) {
|
|
120
|
-
console.debug("update");
|
|
121
|
-
return super.update(changedProperties);
|
|
122
|
-
}
|
|
123
|
-
updated(changedProperties) {
|
|
124
|
-
console.debug("updated");
|
|
125
|
-
return super.updated(changedProperties);
|
|
126
|
-
}
|
|
127
|
-
render() {
|
|
128
|
-
/**
|
|
129
|
-
* this is the main render function
|
|
130
|
-
* it renders different stages during the game
|
|
131
|
-
*/
|
|
132
|
-
console.debug("render");
|
|
133
|
-
return html `
|
|
134
|
-
<div class="guess-the-year-container">
|
|
135
|
-
${this._renderState == GameState.INIT ? "Loading..." : ""}
|
|
136
|
-
${this._renderState == GameState.SPLASH
|
|
137
|
-
? this.renderSplashScreen()
|
|
138
|
-
: ""}
|
|
139
|
-
${this._renderState == GameState.INTRO ? this.renderGameIntro() : ""}
|
|
140
|
-
${this._renderState == GameState.PLAY ? this.renderGameStage() : ""}
|
|
141
|
-
${this._renderState == GameState.END ? this.renderGameEnd() : ""}
|
|
142
|
-
${this._renderFooter()}
|
|
143
|
-
</div>
|
|
144
|
-
`;
|
|
145
|
-
}
|
|
146
|
-
colorElement(element, color) {
|
|
147
|
-
var _a, _b;
|
|
148
|
-
console.debug("colorElement");
|
|
149
|
-
(_b = (_a = this === null || this === void 0 ? void 0 : this.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector(element)) === null || _b === void 0 ? void 0 : _b.style.setProperty("color", color);
|
|
150
|
-
}
|
|
151
|
-
// this renders the game header
|
|
152
|
-
_renderHeader(content = this.i18n.translate("game-name")) {
|
|
153
|
-
return html `
|
|
154
|
-
<section id="top" class="header guess-the-year-header">
|
|
155
|
-
<h1>${content}</h1>
|
|
156
|
-
</section>
|
|
157
|
-
`;
|
|
158
|
-
}
|
|
159
|
-
// this renders the game footer
|
|
160
|
-
_renderFooter() {
|
|
161
|
-
if (this._showFooter) {
|
|
162
|
-
return html `
|
|
163
|
-
<section class="footer guess-the-year-footer">
|
|
164
|
-
<div class="guess-the-year-copyright">
|
|
165
|
-
${"The Throwback Company ©" + dayjs().year()}
|
|
166
|
-
</div>
|
|
167
|
-
</section>
|
|
168
|
-
`;
|
|
169
|
-
}
|
|
170
|
-
return html ``;
|
|
171
|
-
}
|
|
172
|
-
// render the splash screen
|
|
173
|
-
renderSplashScreen() {
|
|
174
|
-
console.debug("renderSplashScreen");
|
|
175
|
-
// (pretend) to load before the game starts
|
|
176
|
-
setTimeout(() => {
|
|
177
|
-
this._renderState = GameState.INTRO;
|
|
178
|
-
}, SPLASH_DELAY);
|
|
179
|
-
return html `
|
|
180
|
-
<div id="splash-screen-container" class="splashscreen">
|
|
181
|
-
<div class="splash-logo">
|
|
182
|
-
<h2>${this.i18n.translate("game-name")}</h2>
|
|
183
|
-
<p>${this.i18n.translate("Loading...")}</p>
|
|
184
|
-
</div>
|
|
185
|
-
</div>
|
|
186
|
-
`;
|
|
187
|
-
}
|
|
188
|
-
// renders a selector for a year
|
|
189
|
-
// TODO: set type of selector
|
|
190
|
-
_renderYearStepXSelectOptions(from, to, step, selectedValue) {
|
|
191
|
-
const selected = parseInt(selectedValue, 10);
|
|
192
|
-
// pre-render year options
|
|
193
|
-
// and mark selected when they match
|
|
194
|
-
const selectYearOptions = [];
|
|
195
|
-
for (let i = from; i <= to; i += step) {
|
|
196
|
-
selectYearOptions.push(html `
|
|
197
|
-
<option value="${i}" ?selected=${selected == i}>${i}</option>
|
|
198
|
-
`);
|
|
199
|
-
}
|
|
200
|
-
return html `${selectYearOptions}`;
|
|
201
|
-
}
|
|
202
|
-
// render the game intro
|
|
203
|
-
// allows to select the number of questions,
|
|
204
|
-
// select the year range
|
|
205
|
-
// and to start the game
|
|
206
|
-
renderGameIntro() {
|
|
207
|
-
console.debug("renderGameIntro");
|
|
208
|
-
// pre-render number of question options
|
|
209
|
-
// and mark selected when they match
|
|
210
|
-
const selectQuestionOptions = [];
|
|
211
|
-
for (let i = 1; i <= MAX_QUESTIONS; i++) {
|
|
212
|
-
selectQuestionOptions.push(html `
|
|
213
|
-
<option value="${i}" ?selected=${this.numberOfQuestions == i}>
|
|
214
|
-
${i}
|
|
215
|
-
</option>
|
|
216
|
-
`);
|
|
217
|
-
}
|
|
218
|
-
return html `
|
|
219
|
-
${this._renderHeader(this.i18n.translate("game-introduction-welcome"))}
|
|
220
|
-
|
|
221
|
-
<div class="game-intro">
|
|
222
|
-
<div class="game-explanation">
|
|
223
|
-
<p>
|
|
224
|
-
${this.i18n.translate("game-introduction-p1")}
|
|
225
|
-
</p>
|
|
226
|
-
|
|
227
|
-
<p>
|
|
228
|
-
${this.i18n.translate("game-introduction-p2")}
|
|
229
|
-
</p>
|
|
230
|
-
|
|
231
|
-
<p>
|
|
232
|
-
${this.i18n.translate("game-introduction-p3")}
|
|
233
|
-
</p>
|
|
234
|
-
</div>
|
|
235
|
-
|
|
236
|
-
<div class="game-settings">
|
|
237
|
-
<p>
|
|
238
|
-
${this.i18n.translate("game-settings-p0")}
|
|
239
|
-
|
|
240
|
-
${this.i18n.translate("game-settings-p1-1")}
|
|
241
|
-
<select @change="${this._setNumberOfQuestions}">
|
|
242
|
-
${selectQuestionOptions}
|
|
243
|
-
</select>
|
|
244
|
-
${this.i18n.translate("game-settings-p1-2")}
|
|
245
|
-
${this.i18n.translate("game-settings-p2")}
|
|
246
|
-
<select @change="${this._setFromDate}">
|
|
247
|
-
${this._renderYearStepXSelectOptions(MIN_YEAR, MAX_YEAR, 5, this.from.format("YYYY"))}
|
|
248
|
-
</select>
|
|
249
|
-
${this.i18n.translate("game-settings-p3")}
|
|
250
|
-
<select @change="${this._setToDate}">
|
|
251
|
-
${this._renderYearStepXSelectOptions(MIN_YEAR, MAX_YEAR, 5, this.to.format("YYYY"))}
|
|
252
|
-
</select>
|
|
253
|
-
${this.i18n.translate("game-settings-p4")}
|
|
254
|
-
${this.i18n.translate("game-settings-p5-1")}
|
|
255
|
-
<select @change="${this._setPlayerDob}">
|
|
256
|
-
${this._renderYearStepXSelectOptions(MAX_DOB, MIN_DOB, 1, this._playerDob + '')}
|
|
257
|
-
</select>
|
|
258
|
-
${this.i18n.translate("game-settings-p5-2")}
|
|
259
|
-
</p>
|
|
260
|
-
</div>
|
|
261
|
-
|
|
262
|
-
<div class="game-start">
|
|
263
|
-
<button @click="${this.setupNewGame}">${this.i18n.translate("start")}</button>
|
|
264
|
-
</div>
|
|
265
|
-
</div>
|
|
266
|
-
`;
|
|
267
|
-
}
|
|
268
|
-
_setPlayerDob(event) {
|
|
269
|
-
this._playerDob = Number(event.target.value);
|
|
270
|
-
window.localStorage.setItem(GTY_PLAYER_DOB_VAR, this._playerDob + '');
|
|
271
|
-
}
|
|
272
|
-
_setNumberOfQuestions(event) {
|
|
273
|
-
this.numberOfQuestions = Number(event.target.value);
|
|
274
|
-
window.localStorage.setItem(GTY_NUM_QUESTIONS_VAR, this.numberOfQuestions + '');
|
|
275
|
-
}
|
|
276
|
-
_setFromDate(event) {
|
|
277
|
-
this.from = this.from.year(event.target.value);
|
|
278
|
-
window.localStorage.setItem(GTY_FROM_YEAR_VAR, this.from.format('YYYY') + '');
|
|
279
|
-
}
|
|
280
|
-
_setToDate(event) {
|
|
281
|
-
this.to = this.to.year(event.target.value);
|
|
282
|
-
window.localStorage.setItem(GTY_TO_YEAR_VAR, this.to.format('YYYY') + '');
|
|
283
|
-
}
|
|
284
|
-
// renders the actual game stage
|
|
285
|
-
renderGameStage() {
|
|
286
|
-
console.debug("renderGameStage");
|
|
287
|
-
return html `
|
|
288
|
-
${this._renderHeader(this.i18n.translate("game-call-to-action").replace(/__FROM__/, this.from.year() + '').replace(/__TO__/, this.to.year() + ''))}
|
|
289
|
-
<div class="guess-the-year-game-stage">
|
|
290
|
-
<div class="game-score">${this._renderGameScore()}</div>
|
|
291
|
-
|
|
292
|
-
<div class="container">
|
|
293
|
-
<div class="incident">${this._renderIncident()}</div>
|
|
294
|
-
${this._renderHint()}
|
|
295
|
-
<div class="sources">${this.renderSources()}</div>
|
|
296
|
-
</div>
|
|
297
|
-
|
|
298
|
-
<div class="game-controls">
|
|
299
|
-
<div class="game-controls--hint">${this._renderHintButton()}</div>
|
|
300
|
-
<div class="game-controls--answers">${this._renderAnswers()}</div>
|
|
301
|
-
</div>
|
|
302
|
-
|
|
303
|
-
${this._renderFeedback()}
|
|
304
|
-
</div>
|
|
305
|
-
`;
|
|
306
|
-
}
|
|
307
|
-
// renders the item for the year to guess
|
|
308
|
-
_renderIncident() {
|
|
309
|
-
var _a, _b;
|
|
310
|
-
return html `
|
|
311
|
-
<div class="incident--title">
|
|
312
|
-
<h1>${(_a = this._incident) === null || _a === void 0 ? void 0 : _a.title}</h1>
|
|
313
|
-
</div>
|
|
314
|
-
|
|
315
|
-
${this._renderIncidentImage(this._incident)}
|
|
316
|
-
|
|
317
|
-
<div class="incident--text">
|
|
318
|
-
<p>${(_b = this._incident) === null || _b === void 0 ? void 0 : _b.text}</p>
|
|
319
|
-
</div>
|
|
320
|
-
`;
|
|
321
|
-
}
|
|
322
|
-
_shouldDisplayAnImage(incident) {
|
|
323
|
-
const hasImage = !!(incident && incident.image && incident.image[0]);
|
|
324
|
-
const displayImages = !this.suppressImages;
|
|
325
|
-
return hasImage && displayImages;
|
|
326
|
-
}
|
|
327
|
-
// renders the optional image with the item
|
|
328
|
-
_renderIncidentImage(incident) {
|
|
329
|
-
if (incident && this._shouldDisplayAnImage(incident)) {
|
|
330
|
-
return html `
|
|
331
|
-
<div class="incident--image">
|
|
332
|
-
<img
|
|
333
|
-
@error=${(evt) => {
|
|
334
|
-
this._handleImageLoadError(evt, incident);
|
|
335
|
-
}}
|
|
336
|
-
src="${incident.image[0]}"
|
|
337
|
-
/>
|
|
338
|
-
</div>
|
|
339
|
-
`;
|
|
340
|
-
}
|
|
341
|
-
if (!this.suppressImages) {
|
|
342
|
-
// Preserve html structure to prevent the webcomponent to collapse.
|
|
343
|
-
return html `<div class="incident--image">
|
|
344
|
-
<img/>
|
|
345
|
-
</div>`;
|
|
346
|
-
}
|
|
347
|
-
return html ``;
|
|
348
|
-
}
|
|
349
|
-
// renders a list of possible answers
|
|
350
|
-
_renderAnswers() {
|
|
351
|
-
return html `
|
|
352
|
-
<div class="answers--list">
|
|
353
|
-
<ul>
|
|
354
|
-
${this._answers.map((answer) => html `<li @click="${this._handleAnswerClicked}">${answer}</li>`)}
|
|
355
|
-
</ul>
|
|
356
|
-
</div>
|
|
357
|
-
`;
|
|
358
|
-
}
|
|
359
|
-
// renders the current question score
|
|
360
|
-
// it counts back to 0
|
|
361
|
-
_renderGameScore() {
|
|
362
|
-
return html `
|
|
363
|
-
<div class="game-score--total">
|
|
364
|
-
<div class="game-score--label">${this.i18n.translate("question-number")}:</div>
|
|
365
|
-
<div class="game-score--value">
|
|
366
|
-
${this._numberOfQuestionsSeen} van ${this.numberOfQuestions}
|
|
367
|
-
</div>
|
|
368
|
-
</div>
|
|
369
|
-
|
|
370
|
-
<div class="game-score--score">
|
|
371
|
-
<div class="game-score--label">${this.i18n.translate("question-score")}:</div>
|
|
372
|
-
<div class="game-score--value">${this._score0.value}</div>
|
|
373
|
-
</div>
|
|
374
|
-
|
|
375
|
-
<div class="game-score--total">
|
|
376
|
-
<div class="game-score--label">${this.i18n.translate("total-score")}:</div>
|
|
377
|
-
<div class="game-score--value">${this.totalScore}</div>
|
|
378
|
-
</div>
|
|
379
|
-
`;
|
|
380
|
-
}
|
|
381
|
-
// handles the click on an answer
|
|
382
|
-
_handleAnswerClicked(event) {
|
|
383
|
-
// get the clicked answer
|
|
384
|
-
const answer = event.target.textContent;
|
|
385
|
-
// stop the score counter
|
|
386
|
-
this._score0.stop();
|
|
387
|
-
// remove the hint button
|
|
388
|
-
this._showHint = false;
|
|
389
|
-
// check if the answer is correct
|
|
390
|
-
if (answer) {
|
|
391
|
-
// this._apiService.postIncidentAnswer(this._incident?.id, answer);
|
|
392
|
-
console.debug(answer, this._solution, this._score, answer == this._solution);
|
|
393
|
-
this._answer = answer;
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
// renders the requested hint
|
|
397
|
-
_renderHint() {
|
|
398
|
-
if (!this._hint) {
|
|
399
|
-
return html ``;
|
|
400
|
-
}
|
|
401
|
-
return html ` <p>${this._hint}</p> `;
|
|
402
|
-
}
|
|
403
|
-
// renders the hint button until
|
|
404
|
-
// all max hints have been used
|
|
405
|
-
_renderHintButton() {
|
|
406
|
-
if (!this._showHint) {
|
|
407
|
-
return html ``;
|
|
408
|
-
}
|
|
409
|
-
return html `
|
|
410
|
-
<div class="game-controls--hint">
|
|
411
|
-
<button @click="${this._handleHintClicked}">
|
|
412
|
-
${this.i18n.translate("show-hint")} (${this._hints.length - this._hintsIndex})
|
|
413
|
-
</button>
|
|
414
|
-
</div>
|
|
415
|
-
`;
|
|
416
|
-
}
|
|
417
|
-
// handles the click on the hint button
|
|
418
|
-
// and shows the next hint if available
|
|
419
|
-
// subtracts the cost of the hint from
|
|
420
|
-
// the question score
|
|
421
|
-
_handleHintClicked() {
|
|
422
|
-
console.debug("handleHintClicked", [this._hintsIndex, this._hints.length]);
|
|
423
|
-
if (this._hintsIndex < this._hints.length) {
|
|
424
|
-
const hintText = this._generateHintText(this._hints[this._hintsIndex]);
|
|
425
|
-
if (hintText) {
|
|
426
|
-
this._hint = hintText;
|
|
427
|
-
this._hintsIndex++;
|
|
428
|
-
this._score0.subtract(HINT_COST);
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
if (this._hintsIndex >= this._hints.length) {
|
|
432
|
-
// this._hintsIndex = 0;
|
|
433
|
-
this._showHint = false;
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
// renders the feedback overlay
|
|
437
|
-
_renderFeedback() {
|
|
438
|
-
var _a, _b;
|
|
439
|
-
// do not show anything until an answer has been made
|
|
440
|
-
// and the score is greater than 0
|
|
441
|
-
if (!this._answer && this._score0.value > 0) {
|
|
442
|
-
return html ``;
|
|
443
|
-
}
|
|
444
|
-
// check if the answer is correct
|
|
445
|
-
// cast to strings to compare
|
|
446
|
-
const is_correct = this._answer + "" == this._solution + "";
|
|
447
|
-
const score = is_correct ? this._score0.value : 0;
|
|
448
|
-
if (this._score0.isRunning()) {
|
|
449
|
-
this._score0.stop();
|
|
450
|
-
}
|
|
451
|
-
this.totalScore += score;
|
|
452
|
-
// Fire-and-forget recallability feedback.
|
|
453
|
-
if ((_a = this._incident) === null || _a === void 0 ? void 0 : _a.id) {
|
|
454
|
-
this._apiService.incidentRecallability((_b = this._incident) === null || _b === void 0 ? void 0 : _b.id, this._playerDob, is_correct);
|
|
455
|
-
}
|
|
456
|
-
if (is_correct) {
|
|
457
|
-
return html `
|
|
458
|
-
<div class="feedback">
|
|
459
|
-
<div class="feedback--content">
|
|
460
|
-
<h3>${this.i18n.translate("answer-correct")}!</h3>
|
|
461
|
-
<p>
|
|
462
|
-
${this._hintsIndex == 1 ? this.i18n.translate("used-hint-singular") : this.i18n.translate("used-hint-plural").replace(/__HINTS__/, this._hintsIndex + '')}
|
|
463
|
-
</p>
|
|
464
|
-
<p>
|
|
465
|
-
${score == 1 ? this.i18n.translate("number-points-singular") : this.i18n.translate("number-points-plural").replace(/__POINTS__/, score + '')}
|
|
466
|
-
</p>
|
|
467
|
-
|
|
468
|
-
${this._renderNextQuestionButton()}
|
|
469
|
-
</div>
|
|
470
|
-
</div>
|
|
471
|
-
`;
|
|
472
|
-
}
|
|
473
|
-
else if (!is_correct && this._answer) {
|
|
474
|
-
return html `
|
|
475
|
-
<div class="feedback">
|
|
476
|
-
<div class="feedback--content">
|
|
477
|
-
<h3>${this.i18n.translate("answer-wrong")}</h3>
|
|
478
|
-
<p>
|
|
479
|
-
${this.i18n.translate("correct-answer-was").replace(/__WRONG__/, this._answer + '').replace(/__CORRECT__/, this._solution + '')}
|
|
480
|
-
</p>
|
|
481
|
-
${this._renderNextQuestionButton()}
|
|
482
|
-
</div>
|
|
483
|
-
</div>
|
|
484
|
-
`;
|
|
485
|
-
}
|
|
486
|
-
else {
|
|
487
|
-
return html `
|
|
488
|
-
<div class="feedback">
|
|
489
|
-
<div class="feedback--content">
|
|
490
|
-
<h3>Helaas</h3>
|
|
491
|
-
<p>
|
|
492
|
-
${this.i18n.translate("no-answer-correct-answer-was").replace(/__CORRECT__/, this._solution + '')}
|
|
493
|
-
</p>
|
|
494
|
-
${this._renderNextQuestionButton()}
|
|
495
|
-
</div>
|
|
496
|
-
</div>
|
|
497
|
-
`;
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
// renders the next question button
|
|
501
|
-
_renderNextQuestionButton() {
|
|
502
|
-
if (this._numberOfQuestionsSeen < this.numberOfQuestions) {
|
|
503
|
-
return html `
|
|
504
|
-
<button @click="${this._loadQuestion}">${this.i18n.translate("next-question")}</button>
|
|
505
|
-
`;
|
|
506
|
-
}
|
|
507
|
-
return html ` <button @click="${this._endGame}">${this.i18n.translate("quit")}</button> `;
|
|
508
|
-
}
|
|
509
|
-
// renders the end of the game
|
|
510
|
-
_endGame() {
|
|
511
|
-
this._renderState = GameState.END;
|
|
512
|
-
}
|
|
513
|
-
renderGameEnd() {
|
|
514
|
-
console.debug("renderGameEnd");
|
|
515
|
-
const maxScore = this.numberOfQuestions * this._score;
|
|
516
|
-
const scoreRatio = Math.round((this.totalScore / maxScore) * 100);
|
|
517
|
-
return html `
|
|
518
|
-
${this._renderHeader("The end!")}
|
|
519
|
-
<div class="guess-the-year-game-end">
|
|
520
|
-
<p>
|
|
521
|
-
${this.i18n.translate("end").replace(/__SCORE__/, this.totalScore + '').replace(/__MAX_SCORE__/, maxScore + '').replace(/__PERCENT__/, scoreRatio + '')}
|
|
522
|
-
</p>
|
|
523
|
-
<p>
|
|
524
|
-
${this.i18n.translate(Util.scoreToValueJudgement(scoreRatio))}
|
|
525
|
-
</p>
|
|
526
|
-
</div>
|
|
527
|
-
<button @click="${() => (this._renderState = GameState.SPLASH)}" >
|
|
528
|
-
${this.i18n.translate("new-game")}
|
|
529
|
-
</button>
|
|
530
|
-
${this._renderFooter()}
|
|
531
|
-
`;
|
|
532
|
-
}
|
|
533
|
-
setupNewGame() {
|
|
534
|
-
console.debug("new game!");
|
|
535
|
-
console.debug({
|
|
536
|
-
"number of questions": this.numberOfQuestions,
|
|
537
|
-
from: this.from.toISOString(),
|
|
538
|
-
to: this.to.toISOString(),
|
|
539
|
-
});
|
|
540
|
-
this.totalScore = 0;
|
|
541
|
-
this._numberOfQuestionsSeen = 0;
|
|
542
|
-
this._loadQuestion();
|
|
543
|
-
}
|
|
544
|
-
_resetStage() {
|
|
545
|
-
this.sources = [];
|
|
546
|
-
this._incident = undefined;
|
|
547
|
-
this._hints = [];
|
|
548
|
-
this._answer = undefined;
|
|
549
|
-
this._answers = [];
|
|
550
|
-
this._hintsIndex = 0;
|
|
551
|
-
this._score0.reset();
|
|
552
|
-
this._showHint = false;
|
|
553
|
-
this._hint = undefined;
|
|
554
|
-
}
|
|
555
|
-
async _loadQuestion() {
|
|
556
|
-
var _a;
|
|
557
|
-
this._resetStage();
|
|
558
|
-
const response = await this._apiService.fetchOneIncident(this.country, this.category, this.emotion, this.impact, this.date, this.from.format("YYYY-MM-DD"), this.to.format("YYYY-MM-DD"), "40", "quiz_year");
|
|
559
|
-
this._incident = response.incident;
|
|
560
|
-
this.sources = response.sources;
|
|
561
|
-
this._solution = Number((((_a = response.incident) === null || _a === void 0 ? void 0 : _a.yearplusmonth) || "").substring(0, 4));
|
|
562
|
-
const answers = [this._solution];
|
|
563
|
-
const from = this.from.year();
|
|
564
|
-
const to = this.to.year();
|
|
565
|
-
// generate 3 more random and unique answers between to and from
|
|
566
|
-
while (answers.length < 4) {
|
|
567
|
-
const randomAnswer = Math.floor(Math.random() * (to - from)) + from;
|
|
568
|
-
if (!answers.includes(randomAnswer)) {
|
|
569
|
-
answers.push(randomAnswer);
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
// sort theses answers
|
|
573
|
-
answers.sort();
|
|
574
|
-
this._answers = answers;
|
|
575
|
-
for (let i = 0; i < this.maxHints; i++) {
|
|
576
|
-
console.debug("loading hint", i);
|
|
577
|
-
const response = await this._apiService.fetchOneIncident(this.country, Util.shuffleArray([...Categories]).shift(), undefined, undefined, "", `${this._solution}-01-01`, `${this._solution}-12-31`, undefined, undefined);
|
|
578
|
-
if (response.incident) {
|
|
579
|
-
this._hints.push(response.incident);
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
|
-
if (this._hints.length === 0) {
|
|
583
|
-
this._showHint = false;
|
|
584
|
-
}
|
|
585
|
-
else {
|
|
586
|
-
this._showHint = true;
|
|
587
|
-
}
|
|
588
|
-
// start render game stage
|
|
589
|
-
this._renderState = GameState.PLAY;
|
|
590
|
-
// start score counter
|
|
591
|
-
this._score0.start();
|
|
592
|
-
// increment question counter
|
|
593
|
-
this._numberOfQuestionsSeen += 1;
|
|
594
|
-
}
|
|
595
|
-
_generateHintText(hintIncident) {
|
|
596
|
-
let hint = "";
|
|
597
|
-
const hintTemplates = this.i18n.HintTemplates[hintIncident.category];
|
|
598
|
-
switch (hintIncident.category) {
|
|
599
|
-
case Category.newsItem:
|
|
600
|
-
hint = (hintTemplates[Math.round(Math.random() * hintTemplates.length)] || "").replace(/__TITLE__/, hintIncident.title);
|
|
601
|
-
break;
|
|
602
|
-
case Category.radioSong:
|
|
603
|
-
// The title property of radioSongs always follow this pattern: track - artist
|
|
604
|
-
const track = hintIncident.title.replace(/(.*?)\s+\-.*/, "$1");
|
|
605
|
-
const artist = hintIncident.title.replace(/.*\-(.*)/, "$1");
|
|
606
|
-
hint = (hintTemplates[Math.round(Math.random() * hintTemplates.length)] ||
|
|
607
|
-
hintTemplates[0])
|
|
608
|
-
.replace(/__ARTIST__/, artist)
|
|
609
|
-
.replace(/__TRACK__/, track);
|
|
610
|
-
break;
|
|
611
|
-
case Category.cinemaMovie:
|
|
612
|
-
hint = (hintTemplates[Math.round(Math.random() * hintTemplates.length)] ||
|
|
613
|
-
hintTemplates[0]).replace(/__TITLE__/, hintIncident.title);
|
|
614
|
-
break;
|
|
615
|
-
case Category.tech:
|
|
616
|
-
hint = (hintTemplates[Math.round(Math.random() * hintTemplates.length)] ||
|
|
617
|
-
hintTemplates[0]).replace(/__TITLE__/, hintIncident.title);
|
|
618
|
-
break;
|
|
619
|
-
case Category.newsPresenter:
|
|
620
|
-
hint = (hintTemplates[Math.round(Math.random() * hintTemplates.length)] ||
|
|
621
|
-
hintTemplates[0]).replace(/__TITLE__/, hintIncident.title || hintIncident.text);
|
|
622
|
-
break;
|
|
623
|
-
case Category.tvShowOrSeries:
|
|
624
|
-
hint = (hintTemplates[Math.round(Math.random() * hintTemplates.length)] ||
|
|
625
|
-
hintTemplates[0]).replace(/__TITLE__/, hintIncident.title || hintIncident.text);
|
|
626
|
-
break;
|
|
627
|
-
case Category.sports:
|
|
628
|
-
hint = (hintTemplates[Math.round(Math.random() * hintTemplates.length)] ||
|
|
629
|
-
hintTemplates[0]).replace(/__TITLE__/, hintIncident.title || hintIncident.text);
|
|
630
|
-
break;
|
|
631
|
-
case Category.showbizz:
|
|
632
|
-
hint = (hintTemplates[Math.round(Math.random() * hintTemplates.length)] ||
|
|
633
|
-
hintTemplates[0]).replace(/__TITLE__/, hintIncident.title || hintIncident.text);
|
|
634
|
-
break;
|
|
635
|
-
}
|
|
636
|
-
return hint;
|
|
637
|
-
}
|
|
638
|
-
renderSources() {
|
|
639
|
-
console.debug("renderSources");
|
|
640
|
-
if (!this.sources.length) {
|
|
641
|
-
return html ``;
|
|
642
|
-
}
|
|
643
|
-
// deduplicate array via [...new Set(this.sources)]
|
|
644
|
-
return html `
|
|
645
|
-
<div class="guess-the-year-sources" >
|
|
646
|
-
Source: ${[...new Set(this.sources)].join(", ")}
|
|
647
|
-
</div>
|
|
648
|
-
`;
|
|
649
|
-
}
|
|
650
|
-
};
|
|
651
|
-
GuessTheYear.styles = css `
|
|
652
|
-
${stylesheet}
|
|
653
|
-
`;
|
|
654
|
-
__decorate([
|
|
655
|
-
property({ type: String, attribute: "tee-e-api-url" })
|
|
656
|
-
], GuessTheYear.prototype, "teeeApiUrl", void 0);
|
|
657
|
-
__decorate([
|
|
658
|
-
property({ type: Boolean, attribute: "report-broken-images" })
|
|
659
|
-
], GuessTheYear.prototype, "reportBrokenImages", void 0);
|
|
660
|
-
__decorate([
|
|
661
|
-
property({ type: String })
|
|
662
|
-
], GuessTheYear.prototype, "date", void 0);
|
|
663
|
-
__decorate([
|
|
664
|
-
property({ type: String })
|
|
665
|
-
], GuessTheYear.prototype, "country", void 0);
|
|
666
|
-
__decorate([
|
|
667
|
-
property({ type: String })
|
|
668
|
-
], GuessTheYear.prototype, "category", void 0);
|
|
669
|
-
__decorate([
|
|
670
|
-
property({ type: String })
|
|
671
|
-
], GuessTheYear.prototype, "emotion", void 0);
|
|
672
|
-
__decorate([
|
|
673
|
-
property({ type: String })
|
|
674
|
-
], GuessTheYear.prototype, "impact", void 0);
|
|
675
|
-
__decorate([
|
|
676
|
-
property({
|
|
677
|
-
type: Dayjs,
|
|
678
|
-
converter: {
|
|
679
|
-
fromAttribute: (value) => {
|
|
680
|
-
console.debug(["from", "from", value]);
|
|
681
|
-
if (!value) {
|
|
682
|
-
return dayjs();
|
|
683
|
-
}
|
|
684
|
-
if (value.length >= 10) {
|
|
685
|
-
return dayjs(value, "YYYY-MM-DD");
|
|
686
|
-
}
|
|
687
|
-
return dayjs(`${value}-01-01`, "YYYY-MM-DD");
|
|
688
|
-
},
|
|
689
|
-
toAttribute: (value) => {
|
|
690
|
-
console.debug(["from", "to", value]);
|
|
691
|
-
return value.format("YYYY-MM-DD");
|
|
692
|
-
},
|
|
693
|
-
},
|
|
694
|
-
})
|
|
695
|
-
], GuessTheYear.prototype, "from", void 0);
|
|
696
|
-
__decorate([
|
|
697
|
-
property({
|
|
698
|
-
type: Dayjs,
|
|
699
|
-
converter: {
|
|
700
|
-
fromAttribute: (value) => {
|
|
701
|
-
console.debug(["to", "from", value]);
|
|
702
|
-
if (!value) {
|
|
703
|
-
return dayjs();
|
|
704
|
-
}
|
|
705
|
-
if (value.length >= 10) {
|
|
706
|
-
return dayjs(value, "YYYY-MM-DD");
|
|
707
|
-
}
|
|
708
|
-
return dayjs(`${value}-12-31`, "YYYY-MM-DD");
|
|
709
|
-
},
|
|
710
|
-
toAttribute: (value) => {
|
|
711
|
-
console.debug(["to", "to", value]);
|
|
712
|
-
return value.format("YYYY-MM-DD");
|
|
713
|
-
},
|
|
714
|
-
},
|
|
715
|
-
})
|
|
716
|
-
], GuessTheYear.prototype, "to", void 0);
|
|
717
|
-
__decorate([
|
|
718
|
-
property({ type: String, attribute: "no-image-src" })
|
|
719
|
-
], GuessTheYear.prototype, "noImageSrc", void 0);
|
|
720
|
-
__decorate([
|
|
721
|
-
property({ type: Boolean, attribute: "suppress-images" })
|
|
722
|
-
], GuessTheYear.prototype, "suppressImages", void 0);
|
|
723
|
-
__decorate([
|
|
724
|
-
property({ type: Number, attribute: "max-hints" })
|
|
725
|
-
], GuessTheYear.prototype, "maxHints", void 0);
|
|
726
|
-
__decorate([
|
|
727
|
-
property({ type: Number, attribute: "number-of-questions", reflect: true })
|
|
728
|
-
], GuessTheYear.prototype, "numberOfQuestions", void 0);
|
|
729
|
-
__decorate([
|
|
730
|
-
state()
|
|
731
|
-
], GuessTheYear.prototype, "_incident", void 0);
|
|
732
|
-
__decorate([
|
|
733
|
-
state()
|
|
734
|
-
], GuessTheYear.prototype, "_hint", void 0);
|
|
735
|
-
__decorate([
|
|
736
|
-
state()
|
|
737
|
-
], GuessTheYear.prototype, "_solution", void 0);
|
|
738
|
-
__decorate([
|
|
739
|
-
state()
|
|
740
|
-
], GuessTheYear.prototype, "_renderState", void 0);
|
|
741
|
-
__decorate([
|
|
742
|
-
state()
|
|
743
|
-
], GuessTheYear.prototype, "_score", void 0);
|
|
744
|
-
__decorate([
|
|
745
|
-
state()
|
|
746
|
-
], GuessTheYear.prototype, "_answer", void 0);
|
|
747
|
-
GuessTheYear = __decorate([
|
|
748
|
-
customElement("guess-the-year")
|
|
749
|
-
], GuessTheYear);
|
|
750
|
-
export { GuessTheYear };
|
|
751
|
-
//# sourceMappingURL=guess-the-year.js.map
|