PageSourceSearch

https://shionn.github.io/js/tortuga-2026.js

js shionn.github.io collected 2026-10-03 09:56:56 UTC 25,687 bytes, 572 lines download raw bytes

1'use strict';
2
3q(function() {
4
5	const _FIG = 1;
6	const _DECORD = 2;
7	const _SMALL = { xp: 1, type: _FIG };
8	const _MEDIUM = { xp: 2, type: _FIG };
9	const _BIG = { xp: 5, type: _FIG };
10	const _SMALL_DECOR = { xp: 1, type: _DECORD };
11	const _MEDIUM_DECOR = { xp: 2, type: _DECORD };
12	const _BIG_DECOR = { xp: 5, type: _DECORD };
13	const _GRADES = ["Mousse", "Pirate de pacotille", "Flibustiers", "Cannoniers", "Loups de mers", "Ecumeurs des mers", "Quartier maître", "Pirate émérite", "Terreur des mers", "Quartier maître en chef", "Second du capitaine"];
14	const _CAPTAIN_GRADES = ["Capitaine Déchu", "Capitaine Maudit", "Capitaine", "Capitaine Cendré", "Capitaine Tenebreux", "Capitaine Supreme", "Amiral Maudit", "Amiral", "Amiral Cendré", "Amiral Tenebreux", "Amiral Supreme",];
15	const _PAINT = 1;
16	const _LVL_UP = 2;
17	const _END_QUEST = 3;
18	const _GAIN_BADGE = 4;
19	const _CHALLENGE_DONE = 5;
20	const _QUEST_DONE = 6;
21	const _LANG_CORRECTION = 7;
22	const _BUG_BOUNTY = 8;
23
24	let _badge = function(name, icon, description, revealed) {
25		this.name = name;
26		this.icon = icon;
27		this.description = description;
28		this.revealed = revealed;
29	};
30
31	const _BADGE = [];
32
33	let _progressBar = function(current, target) {
34		let pct = current * 100 / target;
35		return q("<span>").addClass("progress")
36			.append(q("<span>").css("width", pct + "%"))
37			.append(q("<span>").text(current + "/" + target));
38	}
39
40	let _player = function(name, avatar, lvl = 1) {
41		this.name = name;
42		this.avatar = avatar;
43		this.lvl = lvl;
44		this.xp = 0;
45		this.figurines = 0;
46		this.decorts = 0;
47		this.captain = false;
48		this.badges = [];
49		this.quests = [];
50
51		this.paint = function(count, type) {
52			if (type.type == _FIG) {
53				this.figurines += count;
54			} else {
55				this.decorts += count;
56			}
57			return this.gainXp(count * type.xp);
58		}
59
60		this.gainXp = function(gain) {
61			this.xp += gain;
62			let target = this.xpTarget()
63			if (this.xp >= target) {
64				this.xp -= target;
65				this.lvl++;
66				return true;
67			}
68			return false;
69		}
70
71		this.grade = function(lvl) {
72			if (this.captain) {
73				return _CAPTAIN_GRADES[this.lvl - 1];
74			}
75			return _GRADES[this.lvl - 1];
76		}
77
78		this.xpTarget = function() {
79			let target = this.lvl * 10;
80			if (this.captain) {
81				target = target * 2;
82			}
83			return target;
84		}
85
86		this.avatarPath = function() {
87			return "pictures/defis/tortuga-2025/" + this.avatar;
88		}
89
90		this.addBadge = function(badge) {
91			if (this.badges.indexOf(badge) === -1 && (_BADGE[badge].revealed || this.name !== "Shionn")) {
92				this.badges.push(badge);
93				return true;
94			}
95			return false;
96		}
97
98		this.countQuest = function(quest) {
99			if (this.quests.indexOf(quest) === -1) this.quests.push(quest);
100			return this.quests.length;
101		}
102	};
103
104	let _history = function(event, date, player, value, desc, type) {
105		this.event = event;
106		this.date = date;
107		this.player = player;
108		this.value = value;
109		this.desc = desc;
110		this.type = type;
111
112		this.description = function() {
113			switch (event) {
114				case _PAINT: return "peint " + value + " " + desc + " (+" + (value * type.xp) + " xp)";
115				case _LVL_UP: return "passe " + desc +" (" + value + ")";
116				case _END_QUEST: return "fini la quete";
117				case _GAIN_BADGE: return "gagne le badge " + _BADGE[value].name+ " ";
118				case _CHALLENGE_DONE: return "accomplis le défis de Phylios (+" + (value) + " xp)";
119				case _QUEST_DONE: return "accomplis la quête du JV (+" + (value) + " xp)";
120				case _LANG_CORRECTION: return "corrige "+value+" faute.s (+" + (value) + " xp)";
121				case _BUG_BOUNTY: return "trouve un bug (+" + (value) + " xp)";
122			}
123		}
124	};
125
126	let _quest = function(id, name, objectif, size) {
127		this.id = id;
128		this.name = name;
129		this.objectif = objectif;
130		this.size = size;
131		this.current = 0;
132
133		this.history = [];
134
135		this.render = function() {
136			let table = q("<table>").addClass("quest");
137			let head = q("<thead>");
138			head.append(q("<tr>").append(q("<th>").attr("colspan", "3").text(this.name + " : " + this.objectif)));
139			table.append(head);
140
141			let body = q("<tbody>");
142			body.append(q("<tr>").append(q("<td>").attr("colspan", "3").append(_progressBar(this.current, this.size))));
143			table.append(body);
144
145			head = q("<thead>");
146			head.append(q("<tr>").append(q("<th>").attr("colspan", "3").text("Historique")));
147			table.append(head);
148
149			body = q("<tbody>");
150			this.history.forEach(h => {
151				let desc = q("<td>").text(h.description());
152				if (h.event === _GAIN_BADGE) {
153					desc = desc.append(q("<i>").attr("class",_BADGE[h.value].icon))
154				}
155				let line = q("<tr>")
156					.append(q("<td>").text(h.date))
157					.append(q("<td>").text(h.player.name))
158					.append(desc);
159				body.append(line)
160			});
161
162			q("#tortuga-2026-" + this.id).append(table.append(body));
163			return this;
164		}
165
166		this.doChallenge = function(date, player) {
167			this.history.push(new _history(_CHALLENGE_DONE, date, player, 5));
168			if (player.gainXp(5)) {
169				this.history.push(new _history(_LVL_UP, date, player, player.lvl, player.grade()));
170			}
171			return this;
172		}
173
174		this.doVideoGameQuest = function(date, player, xp) {
175			this.history.push(new _history(_QUEST_DONE, date, player, xp));
176			if (player.gainXp(xp)) {
177				this.history.push(new _history(_LVL_UP, date, player, player.lvl, player.grade()));
178			}
179			return this;
180		}
181
182		this.doLangCorrection = function(date, player, count) {
183			this.history.push(new _history(_LANG_CORRECTION, date, player, count));
184			if (player.gainXp(count)) {
185				this.history.push(new _history(_LVL_UP, date, player, player.lvl, player.grade()));
186			}
187			return this;
188		}
189
190		this.doBugBounty = function(date, player) {
191			this.history.push(new _history(_BUG_BOUNTY, date, player, 5));
192			if (player.gainXp(5)) {
193				this.history.push(new _history(_LVL_UP, date, player, player.lvl, player.grade()));
194			}
195			return this;
196		}
197
198		this.progress = function(date, player, count, desc, type) {
199			this.history.push(new _history(_PAINT, date, player, count, desc, type));
200			if (player.paint(count, type)) {
201				this.history.push(new _history(_LVL_UP, date, player, player.lvl, player.grade()));
202				while(player.paint(0, type)) {
203					this.history.push(new _history(_LVL_UP, date, player, player.lvl, player.grade()));
204				}
205			};
206			if (count>=10 && type ===_SMALL) this.addBadge(date, player, 1); // 10 petite fig d'un coup
207			if (count>=5 && type ===_MEDIUM) this.addBadge(date, player, 2); // 5 fig moyenne d'un coup
208			if (count>=2 && type ===_BIG) this.addBadge(date, player, 3); // 2 grosse fig d'un coup
209			// 4 petit gros non auto
210			if (this.hasSend(player, _SMALL) && this.hasSend(player, _MEDIUM) && this.hasSend(player, _BIG)) this.addBadge(date, player, 4); //petit/moyen/gros
211			if (this.countHistory(_PAINT, player) >= 3) this.addBadge(date, player, 5); // faire 3 contribution
212			if (this.countHistory(_PAINT, player) >= 5) this.addBadge(date, player, 6); // faire 5 contribution
213			if (this.current === 0 && count >= this.size) this.addBadge(date, player, 7); // one shot
214			if (this.sumFigHistory(_PAINT, player, _FIG) >= 20) this.addBadge(date, player, 8); // envoyer 20 figurine
215			if (this.countHistory(_PAINT, player) >= 10) this.addBadge(date, player, 9); // faire 10 contribution
216			// 10 gargantuesque non auto
217			// 11 bon plan
218			if (player.countQuest(this.id)>=10) this.addBadge(date, player, 12); // faire 10 quetes
219			if (player.countQuest(this.id)>=20) this.addBadge(date, player, 13); // faire 20 quetes
220			if (player.countQuest(this.id)>=30) this.addBadge(date, player, 20); // faire 30 quetes
221			if (this.hasSend(player, _SMALL_DECOR) && this.hasSend(player, _MEDIUM_DECOR) && this.hasSend(player, _BIG_DECOR)) this.addBadge(date, player, 14); //petit/moyen/gros decors
222			if (this.sumFigHistory(_PAINT, player, _DECORD) >= 15) this.addBadge(date, player, 15); // envoyer 15 décors
223			this.current = this.current + count;
224			if (this.isFinished()) {
225				if (type.type === _FIG) this.addBadge(date, player, 0); // coup final fig
226				if (type.type === _DECORD) this.addBadge(date, player, 16); // coup final decor
227				this.current = this.size;
228				this.history.push(new _history(_END_QUEST, date, player));
229			}
230			return this;
231		};
232
233		this.hasSend = function(player, type) {
234			return this.history.findIndex( (v) => v.player === player && v.type === type ) !== -1;
235		};
236
237		this.countHistory = function(event, player) {
238			return this.history.filter((v)=>v.event === event && v.player === player).length;
239		};
240
241		this.sumFigHistory = function(event, player, figType) {
242			return this.history.filter((v)=>v.event === event && v.player === player && v.type.type === figType).map(h=>h.value).reduce((a,b)=>a+b, 0);
243		};
244
245		this.addBadge = function(date, player, badge) {
246			if (player.addBadge(badge)) {
247				this.history.push(new _history(_GAIN_BADGE, date, player, badge));
248				_BADGE[badge].revealed = true;
249				if (player.badges.length >= 8) this.addBadge(date, player, 17); // obtenir 8 badge
250				if (player.badges.length >= 15) this.addBadge(date, player, 18); // obtenir presque tous les badges
251				if (player.badges.length >= 20) this.addBadge(date, player, 19); // obtenir tous les badge
252			}
253			return this;
254		};
255
256		this.isFinished = function() {
257			return this.current >= this.size;
258		}
259
260	};
261
262	let _renderPlayers = function(players) {
263		let table = q("<table>").addClass("players").addClass("boxed");
264		table.append(q("<thead>").append(q("<tr>").append(q("<th>").attr("colspan", "6").text("Participants"))));
265
266		let body = q("<tbody>");
267
268		let lines = [];
269		let figurines = 0;
270		let decorts = 0;
271		players.forEach((player, index) => {
272			if (index % 2 === 0) {
273				lines = [q("<tr>"), q("<tr>"), q("<tr>"), q("<tr>"), q("<tr>")];
274				body.append(lines[0]).append(lines[1]).append(lines[2]).append(lines[3]).append(lines[4]);
275			}
276			lines[0]
277				.append(q("<td>").attr("rowspan", 5).append(q("<img>").attr("src", player.avatarPath())))
278				.append(q("<td>").addClass("subtitle").text("Joueur"))
279				.append(q("<td>").text(player.name));
280			lines[1]
281				.append(q("<td>").addClass("subtitle").text("Niveau"))
282				.append(q("<td>").text(player.grade() + " (" + player.lvl + ")"));
283			lines[2]
284				.append(q("<td>").addClass("subtitle").text("Exp."))
285				.append(q("<td>").addClass("xp").append(_progressBar(player.xp, player.xpTarget())));
286			lines[3]
287				.append(q("<td>").addClass("subtitle").text("Contrib."))
288				.append(q("<td>").text(player.figurines + " figs / " + player.decorts + " decs"));
289			let badge = q("<td>").addClass("badge");
290			player.badges.forEach(b => {
291				badge.append(q("<i>").attr("class", _BADGE[b].icon));
292			});
293			lines[4]
294				.append(q("<td>").addClass("subtitle").text("Badges"))
295				.append(badge);
296
297			if (index % 2 === 1) {
298				lines = [];
299			}
300
301			figurines += player.figurines;
302			decorts += player.decorts;
303		});
304		if (lines.length) {
305			lines[0].append(q("<td>").addClass("subtitle").attr("rowspan", 5).attr("colspan", 3));
306		}
307		/*_BADGE.forEach(b => {
308			if (b.revealed) {
309				body.append(q("<tr>").append(q("<td>").attr("colspan", 6).addClass("badge").append(q("<i>").attr("class", b.icon)).append(q("<strong>").text(b.name + ": " )).append(q("<span>").text(b.description))));
310			}
311		});//*/
312
313		body.append(q("<tr>")
314			.append(q("<td>").attr("colspan", 2).addClass("subtitle").text("Total Figurines"))
315			.append(q("<td>").text(figurines))
316			.append(q("<td>").attr("colspan", 2).addClass("subtitle").text("Total Décors"))
317			.append(q("<td>").text(decorts)));
318
319		q("#tortuga-2026-participants").append(table.append(body));
320	};
321
322	let _renderQuests = function(quests) {
323		let table = q("<table>").addClass("boxed").addClass("all-quests");
324		table.append(q("<thead>").append(q("<tr>").append(q("<th>").attr("colspan", "3").text("Quetes"))));
325		let body = q("<tbody>");
326		quests.forEach(qu => {
327			let line = q("<tr>");
328			line.append(q("<td>").text(qu.name)).append(q("<td>").text(qu.objectif)).append(q("<td>").append(_progressBar(qu.current, qu.size)));
329			body.append(line);
330		});
331
332		q("#tortuga-2026-all-quests").append(table.append(body));
333	};
334
335	_BADGE.push(
336		new _badge("Coup Final", "fa fa-flag", "Achever une quête", true),
337		new _badge("Populeux", "ra ra-rabbit", "Envoyer 10 petites figurines d'un coup", true),
338		new _badge("Bourrin", "ra ra-octopus", "Envoyer 5 figurines moyenne d'un coup", true),
339		new _badge("Massif", "ra ra-dragon", "Envoyer 2 grande figurines d'un coup", true),
340		//new _badge("Petit/Gros", "ra ra-two-dragons", "Envoyer une petite figurine et une grande dans la même quête", false),
341		new _badge("Petit/Moyen/Gros", "ra ra-hydra", "Envoyer une figurine de chaque taille dans la même quête", true),
342		new _badge("Mitraillette", "ra ra-barbed-arrow", "Faire 3 contributions à la même quête", true),
343		new _badge("Gatling", "ra ra-arrow-cluster", "Faire 5 contributions à la même quête", true),
344		new _badge("One shot", "ra ra-lightning-storm", "Accomplir une quête d'un seul coup", true),
345		new _badge("Vague", "ra ra-double-team ", "Envoyer 20 figurine lors de la même quête", true),
346		new _badge("Uzi", "ra ra-bullets", "Faire 10 contributions à la même quête", true),
347
348		new _badge("Gargantuesque", "ra ra-monster-skull", "Peindre une très grosse figurine (>=120mm)", true),
349		new _badge("Bon plan", "fa fa-thumbs-up", "Faire profiter la commu d'un bon plan", true),
350		new _badge("Ten", "fa fa-battery-quarter", "Participer à 10 quêtes différentes", true),
351		new _badge("Twenty", "fa fa-battery-half", "Participer à 20 quêtes différentes", true),
352		new _badge("Du cailloux à la Tour", "ra ra-tower", "Envoyer un décors de chaque taille dans la même quête", true),
353		new _badge("Decorama", "ra ra-castle-emblem", "Envoyer 15 décors dans la même quête", true),
354		new _badge("Dernier clou", "ra ra-ankh", "Achever une quête avec un décor", true),
355		new _badge("Collectionneur", "ra ra-player", "Obtenir 8 badges", true),
356		new _badge("Presque tous", "ra ra-muscle-up", "Obtenir presque tous les badges", true),
357		new _badge("Gotha'em all", "ra ra-queen-crown", "Obtenir tous les badge", true),
358
359		new _badge("Thirty", "fa fa-battery-three-quarters", "Participer à 30 quêtes différentes", true),
360		new _badge("Forty", "fa fa-battery-full", "Participer à 40 quêtes différentes", true),
361	);
362
363	const _Gargantuesque = 11;
364	const _BonPlan = 12;
365
366	let angest = new _player("Angest", "pirate12.png", 2);
367	//let anuabi = new _player("Anuabi", "pirate12.png", 2);
368	//let ben = new _player("Ben illustrateur", "pirate07.png");
369	let bnachee = new _player("Bnachee", "pirate02.png");
370	let cuistotfou = new _player("Cuistotfou", "pirate13.png");
371	let faran = new _player("Fararn", "pirate16.png", 2);
372	//let hyasull = new _player("Hyasull", "pirate13.png");
373	let jeff = new _player("Jeff von Zarovich", "pirate15.png");
374	//let ludovic5799 = new _player("Ludovic5799", "pirate01.png");
375	let phylios = new _player("Phylios", "pirate07.png", 2);
376	//let matdeubeul = new _player("Matdeubeul", "TODO");
377	let marco = new _player("Marco", "pirate07.png");
378	let maud = new _player("Maud", "pirate12.png");
379	let melou = new _player("Melou", "pirate04.png");
380	//let rahanis = new _player("Rahanis Sylvéclat", "pirate09.png");
381	let shionn = new _player("Shionn", "pirate02.png", 2);
382	let tupad = new _player("Tupad_", "pirate07.png", 2);
383	let tony = new _player("Tony", "pirate14.png", 2);
384	let transfopaper = new _player("Transfopaper", "pirate09.png", 2)
385	let whisp = new _player("Whisp", "pirate00.png", 2);
386	let makushiman = new _player("Makushiman", "pirate07.png")
387	whisp.captain = true;
388
389	// Décoder le Parchemin de Barbe Drue
390	let q1 = new _quest("quest-1", "Décoder le Parchemin de Barbe Drue", "Peindre 40 figurines", 40)
391			.doVideoGameQuest("01/01/2026", bnachee, 10)
392			.doLangCorrection("01/01/2026", transfopaper, 2)
393			.progress("03/01/2026", whisp, 1, "Sorcier HQ", _SMALL)
394			.doChallenge("03/01/2026", whisp)
395			.progress("03/01/2026", tony, 1, "Beast", _SMALL)
396			.progress("03/01/2026", shionn, 4, "Leader Chaos D&L", _SMALL)
397			.progress("07/01/2026", bnachee, 1, "Gunpla", _MEDIUM)
398			.progress("08/01/2026", whisp, 1, "homme des neiges", _MEDIUM)
399			.progress("12/01/2026", shionn, 3, "Fanatique Gobelin", _SMALL)
400			.progress("12/01/2026", shionn, 1, "Shaman Gobelin", _SMALL)
401			.doLangCorrection("13/01/2026", faran, 5)
402			.progress("15/01/2026", whisp, 1, "Tu'ur", _MEDIUM)
403			.progress("16/01/2026", tupad, 4, "Bariccade", _MEDIUM_DECOR)
404			.doLangCorrection("17/01/2026", marco, 1)
405			.progress("20/01/2026", whisp, 5, "Chacals", _SMALL)
406			.progress("20/01/2026", transfopaper, 1, "Nain", _SMALL)
407			.progress("20/01/2026", jeff, 2, "Orc", _SMALL)
408			.doChallenge("20/01/2026", jeff)
409			.progress("20/01/2026", shionn, 1, "Mazael", _MEDIUM)
410			.progress("20/01/2026", shionn, 1, "Brigit", _SMALL)
411			.doChallenge("20/01/2026", shionn)
412			.doLangCorrection("23/01/2026", marco, 2)
413			.progress("29/01/2026", phylios, 9, "Gretchin", _SMALL)
414			.progress("29/01/2026", shionn, 4, "Waytress of Lay", _SMALL)
415			.render();
416
417	let q2 = new _quest("quest-2", "Collecter du bois", "Peindre 40 figurines", 40+15)
418			.progress("29/01/2026", shionn, 2, "Waytress of Lay", _SMALL)
419			.progress("29/01/2026", shionn, 1, "Champion of Lay", _SMALL)
420			.doVideoGameQuest("30/01/2026", transfopaper, 10)
421			.doBugBounty("30/01/2026", marco) // glissade sur le quai
422			.progress("01/02/2026", tupad, 15, "Cristaux SC2", _MEDIUM_DECOR)
423			.doVideoGameQuest("05/02/2026", cuistotfou, 5)
424			.progress("13/02/2026", tony, 1, "Sony Jona", _SMALL)
425			.progress("13/02/2026", whisp, 7, "Voleurs à dos de fourmis géantes", _MEDIUM)
426			.progress("13/02/2026", whisp, 1, "Chef à pieds", _SMALL)
427			.progress("13/02/2026", whisp, 1, "Elementaire de pierre sableuse", _MEDIUM)
428			.progress("15/02/2026", whisp, 3, "Lézard", _MEDIUM)
429			.progress("15/02/2026", angest, 1, "Requin", _BIG)
430			.progress("15/02/2026", angest, 1, "Harley Queen", _BIG)
431			.progress("16/02/2026", shionn, 10, "Nains", _SMALL)
432			.progress("16/02/2026", shionn, 1, "court-agent", _SMALL)
433			.progress("16/02/2026", shionn, 1, "krill-conscript", _MEDIUM)
434			.progress("17/02/2026", whisp, 1, "Gwen, la Tanneuse d'Heavenrir", _SMALL)
435			.progress("20/02/2026", whisp, 2, "Nobles", _SMALL)
436			.progress("20/02/2026", whisp, 3, "Depouille", _SMALL_DECOR)
437			.progress("21/02/2026", shionn, 1, "Gastefauve Noir-serment", _BIG)
438			.progress("22/02/2026", shionn, 1, "Bishop of Elishu", _MEDIUM)
439			.doChallenge("22/02/2026", shionn)
440			.progress("22/02/2026", shionn, 1, "Truc Genshin", _SMALL_DECOR)
441			.progress("23/02/2026", whisp, 1, "Hallebardier", _SMALL)
442			.render();
443
444	let q3 = new _quest("quest-3", "Rassembler un équipage", "Peindre 40 figurines", 40)
445			.progress("23/02/2026", whisp, 2, "Yeti", _SMALL)
446			.progress("24/02/2026", whisp, 1, "Nounours", _SMALL)
447			.progress("25/02/2026", angest, 5, "Ghasts", _SMALL)
448			.progress("25/02/2026", angest, 2, "Gyaa-Yothn", _MEDIUM)
449			.progress("25/02/2026", angest, 2, "Gugs", _MEDIUM)
450			.progress("27/02/2026", shionn, 6, "Din Huine", _SMALL)
451			.progress("28/02/2026", jeff, 2, "Orc", _SMALL)
452			.doChallenge("28/02/2026", jeff)
453			.progress("01/03/2026", angest, 1, "Dhole", _MEDIUM)
454			.doChallenge("01/03/2026", jeff)
455			.progress("01/03/2026", jeff, 2, "Singe Orc", _SMALL)
456			.progress("02/03/2026", tupad, 4, "Quart Table SC", _BIG_DECOR)
457			.progress("02/03/2026", tupad, 6, "Gisement Gaz", _SMALL_DECOR)
458			.progress("02/03/2026", whisp, 1, "Elemental de Terre", _MEDIUM)
459			.progress("03/03/2026", whisp, 1, "Elemental de Feu", _MEDIUM)
460			.progress("08/03/2026", bnachee, 1, "Gungam (WG)", _SMALL)
461			.progress("15/03/2026", angest, 2, "Grenouille", _MEDIUM)
462			.progress("16/03/2026", tony, 2, "Heros Divers", _SMALL)
463			.progress("16/03/2026", tony, 2, "Heros Divers", _SMALL)
464			.render();
465
466	let q4 = new _quest("quest-4", "Rassembler un équipage (shionn proctrastine)", "Peindre 40 figurines", 40)
467			.progress("16/03/2026", tony, 3, "Heros Divers", _SMALL)
468			.progress("18/03/2026", angest, 2, "Terminators", _MEDIUM)
469			.progress("22/03/2026", angest, 2, "Terminators", _MEDIUM)
470			.progress("22/03/2026", angest, 1, "Infernus", _SMALL)
471			.progress("22/03/2026", shionn, 5, "Cavalerie Noir", _MEDIUM)
472			.progress("27/03/2026", tony, 1, "Buste de Zeus", _SMALL)
473			.progress("30/03/2026", tony, 1, "Buste animé", _SMALL)
474			.progress("30/03/2026", shionn, 1, "Roi Nain", _SMALL)
475			.progress("30/03/2026", shionn, 1, "Driade", _MEDIUM)
476			.doChallenge("30/03/2026", shionn)
477			.progress("31/03/2026", whisp, 1, "Coffre", _BIG_DECOR)
478			.progress("31/03/2026", whisp, 2, "Clef", _MEDIUM_DECOR)
479			.progress("07/04/2026", tony, 1, "Nain", _SMALL)
480			.progress("07/04/2026", whisp, 1, "Tarrasque", _BIG)
481			.progress("07/04/2026", whisp, 1, "Socle Tarrasque", _BIG_DECOR)
482			.doChallenge("09/04/2026", whisp)
483			.doChallenge("12/04/2026", jeff)
484			.progress("12/04/2026", jeff, 1, "Boss ki tue", _MEDIUM)
485			.progress("12/04/2026", jeff, 1, "Grunt", _SMALL)
486			.progress("14/04/2026", whisp, 1, "Guldan", _MEDIUM)
487			.progress("20/04/2026", transfopaper, 1, "squelette pirate", _SMALL)
488			.progress("21/04/2026", phylios, 1, "Lapin", _SMALL)
489			.progress("28/04/2026", whisp, 1, "Bourgeois", _SMALL)
490			.doChallenge("22/04/2026", shionn)
491			.progress("04/05/2026", bnachee, 5, "Gunpla", _SMALL)
492			.progress("04/05/2026", shionn, 1, "Noir Serment sur data", _BIG)
493			.progress("04/05/2026", shionn, 5, "Nains", _SMALL)
494			.render();
495
496	let q5 = new _quest("quest-5", "Rassembler un équipage (x3)", "Peindre 40 figurines", 40)
497			.progress("04/05/2026", shionn, 9, "Nains", _SMALL)
498			.progress("04/05/2026", shionn, 1, "Herlad of Frost", _SMALL)
499			.progress("04/05/2026", shionn, 6, "Nains D&L", _SMALL)
500			.progress("07/05/2026", whisp, 1, "Araignée", _BIG)
501			.addBadge("07/05/2026", whisp, _Gargantuesque)
502			.progress("09/05/2026", bnachee, 1, "Gunpla", _SMALL)
503			.progress("10/05/2026", bnachee, 1, "Gunpla", _SMALL)
504			.progress("11/05/2026", whisp, 1, "Inosuke", _MEDIUM)
505			.progress("24/05/2026", jeff, 1, "Decort de faction orc", _MEDIUM_DECOR)
506			.progress("28/05/2026", makushiman, 19, "Dragon eclipse", _SMALL)
507			.render();
508
509	let q6 = new _quest("quest-6", "Reflexion en attendant la suite", "Peindre 80 figurines", 80)
510			.progress("28/05/2026", makushiman, 4, "Dragon eclipse", _SMALL)
511			.progress("28/05/2026", makushiman, 5, "Descent 2", _SMALL)
512			.progress("28/05/2026", makushiman, 9, "Massive Darkness", _SMALL)
513			.progress("29/05/2026", whisp, 1, "gob sur araignée", _SMALL)
514			.doChallenge("29/05/2026", whisp)
515			.progress("30/05/2026", shionn, 1, "nains sur nounours", _MEDIUM)
516			.doChallenge("30/05/2026", shionn)
517			.progress("30/05/2026", shionn, 7, "Guerrier Chaos Warcry", _SMALL)
518			.progress("30/05/2026", shionn, 3, "Guerrier Chaos Warcry", _MEDIUM)
519			.progress("30/05/2026", shionn, 4, "Nains", _SMALL)
520			.progress("30/05/2026", shionn, 1, "Canon Nains", _SMALL_DECOR)
521			.progress("07/06/2026", whisp, 1, "Lazarus", _SMALL)
522			.progress("07/06/2026", whisp, 1, "Lazarus", _MEDIUM)
523			.progress("09/06/2026", tupad, 30, "Gaunt", _SMALL)
524			.progress("09/06/2026", tupad, 1, "Cerveau tyranide", _MEDIUM)
525			.progress("09/06/2026", tupad, 12, "Fantasin WW2", _SMALL)
526			.render();
527
528	let q7 = new _quest("quest-7", "Shionn prepare une alpha", "Peindre 80 figurines", 80)
529			.progress("09/06/2026", tupad, 41-12, "Fantasin WW2", _SMALL)
530			.progress("09/06/2026", tupad, 9, "Gundam", _MEDIUM)
531			.progress("24/06/2026", tupad, 9, "Gundam", _MEDIUM)
532			.progress("24/06/2026", makushiman, 1, "Ryff", _SMALL)
533			.progress("25/06/2026", makushiman, 1, "Chaman", _MEDIUM)
534			.progress("27/06/2026", whisp, 1, "Nyrah le silencieux", _BIG)
535			.doChallenge("27/06/2026", whisp)
536			.progress("01/07/2026", makushiman, 1, "Niork le troll", _SMALL)
537			.progress("01/07/2026", makushiman, 1, "Elysia la sorcière", _SMALL)
538			.progress("02/07/2026", whisp, 1, "Loup Garou", _SMALL)
539			.progress("02/07/2026", shionn, 10, "Guerrier Nains", _SMALL)
540			.progress("02/07/2026", shionn, 10, "Maraudeur STD", _SMALL)
541			.progress("02/07/2026", bnachee, 1, "Gundam", _SMALL)
542			.progress("02/07/2026", melou, 3, "Terminator Space wolf", _MEDIUM)
543			.progress("02/07/2026", melou, 3, "Griffe Sanglante", _SMALL)
544			.render();
545
546	let q8 = new _quest("quest-8", "Dungeon 2", "Peindre 40 figurines", 40)
547			.progress("02/07/2026", melou, 4, "Griffe Sanglante", _SMALL)
548			.doVideoGameQuest("04/07/2026", phylios, 15)
549			.doLangCorrection("04/07/2026", phylios)
550			.doVideoGameQuest("04/07/2026", maud, 15)
551			.doLangCorrection("04/07/2026", maud)
552			.doVideoGameQuest("05/07/2026", whisp, 7)
553			.progress("09/07/2026", makushiman, 1, "Firple", _SMALL)
554			.progress("16/07/2026", makushiman, 1, "Azmozeus (Massive Darkness)", _MEDIUM)
555			.doVideoGameQuest("17/07/2026", tupad, 15)
556			.progress("22/07/2026", makushiman, 1, "Buer (Massive Darkness)", _MEDIUM)
557			.progress("27/07/2026", tupad, 4, "Ice Archer (warcrow)", _SMALL)
558			.progress("27/07/2026", tupad, 1, "Orc panoceania (infinity)", _SMALL)
559			.progress("27/07/2026", tupad, 1, "Larbin fang (kharnages)", _MEDIUM)
560			.progress("27/07/2026", tupad, 1, "Vestale khemiste (kharnages)", _MEDIUM)
561			.progress("27/07/2026", tupad, 2, "Drones panoceania (infinity)", _MEDIUM)
562			.progress("27/07/2026", tupad, 1, "Drones panoceania (infinity)", _SMALL)
563			.progress("27/07/2026", shionn, 10, "Maraudeur STD", _SMALL)
564			.progress("27/07/2026", shionn, 6, "Soulless (deuslair)", _SMALL)
565			.progress("27/07/2026", shionn, 1, "Tueur Nain", _SMALL)
566			.render();
567
568//
569	_renderPlayers([angest, bnachee, cuistotfou, faran, jeff, makushiman, mar
569co, maud, melou, phylios, shionn, tony, transfopaper, tupad, whisp]);
570	_renderQuests([q1,q2,q3,q4,q5,q6,q7,q8]);
571
572});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.