PageSourceSearch

https://geoeduc.com/js/components/question/memory.js

js geoeduc.com collected 2026-10-04 20:01:43 UTC 7,087 bytes, 261 lines download raw bytes

1const memoryGridConfig = {
2    small:  { cols: 6, max: 6 },
3    medium: { cols: 4, max: 8 },
4    big:    { cols: 6, max: 12 },
5};
6
7let memoryFiles = [];
8
9function getMemoryMode() {
10    return $('#input-question-memory').val() || 'small';
11}
12
13function getMemoryConfig() {
14    return memoryGridConfig[getMemoryMode()] || memoryGridConfig.small;
15}
16
17function syncMemoryFilesToForm() {
18    const dt = new DataTransfer();
19    memoryFiles.forEach(file => dt.items.add(file));
20    const syncInput = document.getElementById('memory-image-sync');
21    if (syncInput) syncInput.files = dt.files;
22}
23
24function addMemoryFile() {
25    const { max } = getMemoryConfig();
26    if (memoryFiles.length >= max) {
27        show.error({ text: `Grid preenchido (${max}/${max}).`, close: true });
28        return;
29    }  
30    $('#memory-image-input').trigger('click');
31}
32
33function renderMemoryGrid() {
34    const grid = $('#memory-images');
35    const { cols, max } = getMemoryConfig();
36
37    if (memoryFiles.length > max) {
38        memoryFiles = memoryFiles.slice(0, max);
39    }
40
41    grid.css('grid-template-columns', `repeat(${cols}, minmax(0, 1fr))`);
42    grid.empty();
43
44    for (let i = 0; i < max; i++) {
45        if (memoryFiles[i]) {
46            const url = URL.createObjectURL(memoryFiles[i]);
47            grid.append(`
48                <div class="memory-slot">
49                    <img src="${url}" alt="Imagem ${i + 1}">
50                    <button type="button" class="memory-remove" data-index="${i}">×</button>
51                </div>
52            `);
53        } else {
54            grid.append(`<div class="memory-slot empty"></div>`);
55        }
56    }
57
58    syncMemoryFilesToForm();
59}
60
61function loadMemoryGrid(files) {
62    if (!files) return;
63
64    const grid = $('#memory-images');
65    const { cols, max } = getMemoryConfig();
66
67    const limitedFiles = files.slice(0, max);
68
69    grid.css('grid-template-columns', `repeat(${cols}, minmax(0, 1fr))`);
70    grid.empty();
71
72    for (let i = 0; i < max; i++) {
73        const url = limitedFiles[i];
74
75        if (url) {
76            const safeUrl = encodeURI(url);
77
78            const slot = $(`
79                <div class="memory-slot">
80                    <img loading="lazy" src="${safeUrl}" alt="Imagem ${i + 1}">
81                    <button type="button" class="memory-remove" data-index="${i}">×</button>
82                </div>
83            `);
84
85            grid.append(slot);
86        } else {
87            grid.append(`<div class="memory-slot empty"></div>`);
88        }
89    }
90}
91
92let jogadas = 0;
93let acertos = 0;
94let erros = 0;
95let acertosTotal = 0;
96
97let tempo = 0;
98let timer = null;
99
100let clickCard = null;
101let slot1 = null;
102let slot2 = null;
103let lock = false;
104
105function atualizarHUD() {
106    $("#hud-tempo").text(tempo);
107    $("#hud-jogadas").text(jogadas);
108    $("#hud-acertos").text(acertos);
109    $("#hud-erros").text(erros);
110
111    $("#points-memory").val(acertos);
112    $("#erros-memory").val(erros);
113    $("#time-memory").val(tempo);
114    $("#plays-memory").val(jogadas);
115}
116
117function iniciarTimer() {
118    if (timer) clearInterval(timer);
119
120    tempo = 0;
121    timer = setInterval(() => {
122        tempo++;
123        atualizarHUD();
124    }, 1000);
125}
126
127function animacaoVitoria() {    
128    show.success({ text:"🎉 Parabéns! Você completou o jogo!"});
129    $(".memory-slot").addClass("vitoria");
130
131    setTimeout(() => {
132        $(".memory-slot").removeClass("vitoria");
133    }, 1500);
134}
135
136function verificarVitoria(totalPares) {
137    if (acertos === totalPares) {
138        clearInterval(timer);
139        animacaoVitoria();
140    }
141}
142
143function resetSelection() {
144    card1 = card2 = null;
145    slot1 = slot2 = null;            
146    lock = false;
147}
148
149
150// 4. Clique
151$(document).on('click', '.memory-slot', function (e) {    
152    const slot = $(this);
153    
154    lock = true;
155
156    // impede clicar na mesma carta ou em carta já resolvida
157    if (slot.hasClass('flipped') || slot.hasClass('matched')) return;
158
159    slot.addClass('flipped');
160    clickMemorySlot(slot);
161    
162    e.stopPropagation();
163});
164
165function clickMemorySlot(slot) {
166    jogadas++;
167    if ($('.flipped').length === 2) {
168        $('.flipped').each(function() {
169            if (!$(this).hasClass('matched')) {
170                if ( $(this).data('id') === slot.data('id') && $(this).data('slot') !== slot.data('slot') ) {
171                    acertos++;
172                    slot.addClass('matched').removeClass('flipped');
173                    $(this).addClass('matched').removeClass('flipped');
174                    setTimeout(() => { resetSelection(); lock = false; verificarVitoria(acertosTotal); }, 300);
175                } else {
176                    erros++;
177
178                    setTimeout(() => {
179                        slot.removeClass('flipped');
180                        $(this).removeClass('flipped');
181                        
182                        resetSelection();
183                        lock = false;
184                    }, 700);
185                }
186            }            
187        })
188    }
189
190    lock = false;
191    atualizarHUD();
192}
193
194function generateQuizMemory(id, files) {
195    if (!files) return;
196
197    $('#quiz-option').append(`
198        <div id="hud" class="hud-memory">
199            <span>⏱ Tempo: <span id="hud-tempo">0</span>s</span>
200            <span>🎯 Jogadas: <span id="hud-jogadas">0</span></span>
201            <span>✔ Acertos: <span id="hud-acertos">0</span></span>
202            <span>❌ Erros: <span id="hud-erros">0</span></span>
203
204            <input type="text" name="points" id="points-memory" hidden/>
205            <input type="text" name="erros" id="erros-memory" hidden/>
206            <input type="text" name="time" id="time-memory" hidden/>
207            <input type="text" name="plays" id="plays-memory" hidden/>
208            <input hidden name="answer" value="${id}" />
209        </div>
210
211
212        <div class="d-flex justify-content-center start-memory-game">
213            <div id="memory-images" class="memory-grid mt-3"></div>
214        </div>
215    `);
216
217    const grid = $('#memory-images');
218    const { cols, max } = getMemoryConfig();
219
220    // 1. Cria pares com ID fixo
221    const base = files.slice(0, max).map((url, i) => ({
222        id: i,
223        url: decodeURIComponent(url)
224    }));
225
226    const pairs = [...base, ...base];
227
228    // 2. Embaralha
229    for (let i = pairs.length - 1; i > 0; i--) {
230        const j = Math.floor(Math.random() * (i + 1));
231        [pairs[i], pairs[j]] = [pairs[j], pairs[i]];
232    }
233
234    grid.css('grid-template-columns', `repeat(${cols}, minmax(0, 1fr))`);
235    grid.empty();
236
237    // 3. Monta o grid
238    pairs.forEach((card, i) => {
239        grid.append(`
240            <div class="memory-slot" data-id="${card.id}" data-slot="${i}">
241                <div class="card-inner">
242                    <div class="card-front"></div>
243                    <div class="card-back">
244                        <img loading="lazy" src="${card.url}">
245                    </div>
246                </div>
247            </div>
248        `);
249    });
250
251    acertos = 0; 
252    erros = 0; 
253    jogadas = 0;
254    acertosTotal = max; // quantidade de pares
255    atualizarHUD(); 
256    iniciarTimer(); 
257   
258}
259
260
261

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.