-
Notifications
You must be signed in to change notification settings - Fork 5
Rollv2 #82
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rollv2 #82
Changes from all commits
a4e2111
48b4b9f
85646b5
c23fa9c
3ed1728
c045149
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,61 +1,239 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||
| $(window).on('load', function(){ | ||||||||||||||||||||||||||||||||||||||||||||||||
| var frameSpeed = 1000, | ||||||||||||||||||||||||||||||||||||||||||||||||
| frameContainer = $('#frame-container'), | ||||||||||||||||||||||||||||||||||||||||||||||||
| frames = $('.frame',frameContainer ), | ||||||||||||||||||||||||||||||||||||||||||||||||
| frameCount = frames.length, | ||||||||||||||||||||||||||||||||||||||||||||||||
| messageContainer = $('#message-container'), | ||||||||||||||||||||||||||||||||||||||||||||||||
| messages = $('.message', messageContainer) | ||||||||||||||||||||||||||||||||||||||||||||||||
| messageCount = messages.length, | ||||||||||||||||||||||||||||||||||||||||||||||||
| t = null, | ||||||||||||||||||||||||||||||||||||||||||||||||
| start = $('#start'), | ||||||||||||||||||||||||||||||||||||||||||||||||
| showFrame = function (n){ | ||||||||||||||||||||||||||||||||||||||||||||||||
| if (n != frameCount){ | ||||||||||||||||||||||||||||||||||||||||||||||||
| return frames.hide().eq(n).show() && messages.hide().eq(n).show(); | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
| return frames.eq(frameCount).show() && messages.eq(messageCount).show(); | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||
| nextFrame = function(){ | ||||||||||||||||||||||||||||||||||||||||||||||||
| if (index == frameCount){ | ||||||||||||||||||||||||||||||||||||||||||||||||
| stopFrames(); | ||||||||||||||||||||||||||||||||||||||||||||||||
| showFrame(frameCount - 1); | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
| else { | ||||||||||||||||||||||||||||||||||||||||||||||||
| showFrame(++index); | ||||||||||||||||||||||||||||||||||||||||||||||||
| t = setTimeout(nextFrame,frameSpeed); | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||
| stopFrames = function(){ | ||||||||||||||||||||||||||||||||||||||||||||||||
| clearInterval(t); | ||||||||||||||||||||||||||||||||||||||||||||||||
| index = 0; | ||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||
| frameContainer | ||||||||||||||||||||||||||||||||||||||||||||||||
| start.on('click', nextFrame) | ||||||||||||||||||||||||||||||||||||||||||||||||
| stopFrames(); | ||||||||||||||||||||||||||||||||||||||||||||||||
| showFrame(0); | ||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||
| function uniqueRollPool(tasks) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| const seen = new Set(); | ||||||||||||||||||||||||||||||||||||||||||||||||
| const output = []; | ||||||||||||||||||||||||||||||||||||||||||||||||
| (tasks || []).forEach((task) => { | ||||||||||||||||||||||||||||||||||||||||||||||||
| if (!task || !task.name || !task.image) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
| const key = `${task.name}|${task.image}|${task.link || ''}`; | ||||||||||||||||||||||||||||||||||||||||||||||||
| if (!seen.has(key)) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| seen.add(key); | ||||||||||||||||||||||||||||||||||||||||||||||||
| output.push(task); | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||
| return output; | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| function shufflePool(tasks) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| const shuffled = [...tasks]; | ||||||||||||||||||||||||||||||||||||||||||||||||
| for (let i = shuffled.length - 1; i > 0; i -= 1) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| const j = Math.floor(Math.random() * (i + 1)); | ||||||||||||||||||||||||||||||||||||||||||||||||
| [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]; | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
| return shuffled; | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| function buildRollSequence(pool, finalTask) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| const safePool = uniqueRollPool(pool); | ||||||||||||||||||||||||||||||||||||||||||||||||
| if (!safePool.length) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| return [finalTask, finalTask, finalTask, finalTask, finalTask].filter(Boolean); | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| const sequence = []; | ||||||||||||||||||||||||||||||||||||||||||||||||
| const spins = Math.max(10, Math.floor(safePool.length * 1.35)); | ||||||||||||||||||||||||||||||||||||||||||||||||
| while (sequence.length < spins) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| const chunk = shufflePool(safePool); | ||||||||||||||||||||||||||||||||||||||||||||||||
| for (let i = 0; i < chunk.length && sequence.length < spins; i += 1) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| sequence.push(chunk[i]); | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
| sequence.push(finalTask); | ||||||||||||||||||||||||||||||||||||||||||||||||
| return sequence; | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| function runSlotRollAnimation(sequence, renderTask, onComplete) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| let index = 0; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| const tick = () => { | ||||||||||||||||||||||||||||||||||||||||||||||||
| renderTask(sequence[index], index, sequence.length); | ||||||||||||||||||||||||||||||||||||||||||||||||
| index += 1; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| if (index >= sequence.length) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| if (typeof onComplete === 'function') { | ||||||||||||||||||||||||||||||||||||||||||||||||
| onComplete(sequence[sequence.length - 1]); | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| const progress = index / sequence.length; | ||||||||||||||||||||||||||||||||||||||||||||||||
| const delay = 30 + Math.floor(Math.pow(progress, 2) * 150); | ||||||||||||||||||||||||||||||||||||||||||||||||
| window.setTimeout(tick, delay); | ||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| tick(); | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| function ensureTaskRollModal() { | ||||||||||||||||||||||||||||||||||||||||||||||||
| let dialog = document.getElementById('taskRollModal'); | ||||||||||||||||||||||||||||||||||||||||||||||||
| if (dialog) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| return dialog; | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| dialog = document.createElement('dialog'); | ||||||||||||||||||||||||||||||||||||||||||||||||
| dialog.id = 'taskRollModal'; | ||||||||||||||||||||||||||||||||||||||||||||||||
| dialog.className = 'task-action-modal task-roll-modal rsText'; | ||||||||||||||||||||||||||||||||||||||||||||||||
| dialog.innerHTML = ` | ||||||||||||||||||||||||||||||||||||||||||||||||
| <div class="rect task-action-shell task-roll-shell"> | ||||||||||||||||||||||||||||||||||||||||||||||||
| <div class="task-action-header task-roll-header"> | ||||||||||||||||||||||||||||||||||||||||||||||||
| <h3 id="taskRollTitle" class="task-roll-title">Rolling New Task</h3> | ||||||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||||||
| <hr class="task-action-divider task-roll-divider"> | ||||||||||||||||||||||||||||||||||||||||||||||||
| <p id="taskRollSubtitle" class="task-roll-subtitle">Welcome to your next grind!</p> | ||||||||||||||||||||||||||||||||||||||||||||||||
| <div class="task-roll-reel"> | ||||||||||||||||||||||||||||||||||||||||||||||||
| <img id="taskRollImage" class="task-roll-image" src="/static/assets/Cake_of_guidance_detail.png" alt="Rolling task image" /> | ||||||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||||||
| <div id="taskRollName" class="task-roll-name">Rolling...</div> | ||||||||||||||||||||||||||||||||||||||||||||||||
| <div class="task-action-progress-wrap task-roll-progress-wrap"> | ||||||||||||||||||||||||||||||||||||||||||||||||
| <div class="task-action-progress-bar task-roll-progress-bar"> | ||||||||||||||||||||||||||||||||||||||||||||||||
| <div id="taskRollProgressFill" class="task-roll-progress-fill"></div> | ||||||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||||||
| <div class="task-action-footer"> | ||||||||||||||||||||||||||||||||||||||||||||||||
| <button id="taskRollConfirm" class="button-style task-roll-confirm" type="button" disabled>Rolling...</button> | ||||||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||||||
| `; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| document.body.appendChild(dialog); | ||||||||||||||||||||||||||||||||||||||||||||||||
| return dialog; | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| function showTaskRollModal(options) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| const { | ||||||||||||||||||||||||||||||||||||||||||||||||
| title, | ||||||||||||||||||||||||||||||||||||||||||||||||
| subtitle, | ||||||||||||||||||||||||||||||||||||||||||||||||
| sequence, | ||||||||||||||||||||||||||||||||||||||||||||||||
| onRender, | ||||||||||||||||||||||||||||||||||||||||||||||||
| onComplete, | ||||||||||||||||||||||||||||||||||||||||||||||||
| } = options; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| const modal = ensureTaskRollModal(); | ||||||||||||||||||||||||||||||||||||||||||||||||
| const titleNode = modal.querySelector('#taskRollTitle'); | ||||||||||||||||||||||||||||||||||||||||||||||||
| const subtitleNode = modal.querySelector('#taskRollSubtitle'); | ||||||||||||||||||||||||||||||||||||||||||||||||
| const imageNode = modal.querySelector('#taskRollImage'); | ||||||||||||||||||||||||||||||||||||||||||||||||
| const nameNode = modal.querySelector('#taskRollName'); | ||||||||||||||||||||||||||||||||||||||||||||||||
| const progressFill = modal.querySelector('#taskRollProgressFill'); | ||||||||||||||||||||||||||||||||||||||||||||||||
| const confirmButton = modal.querySelector('#taskRollConfirm'); | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| titleNode.textContent = title || 'Rolling New Task'; | ||||||||||||||||||||||||||||||||||||||||||||||||
| subtitleNode.textContent = subtitle || 'This could be your next grind!'; | ||||||||||||||||||||||||||||||||||||||||||||||||
| confirmButton.disabled = true; | ||||||||||||||||||||||||||||||||||||||||||||||||
| confirmButton.textContent = 'Rolling...'; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| const setVisualTask = (task, index, total) => { | ||||||||||||||||||||||||||||||||||||||||||||||||
| if (!task) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
| imageNode.src = resolveTaskImageSrc(task.image); | ||||||||||||||||||||||||||||||||||||||||||||||||
| nameNode.textContent = task.name; | ||||||||||||||||||||||||||||||||||||||||||||||||
| const progress = total > 1 ? Math.min(100, Math.floor((index / (total - 1)) * 100)) : 100; | ||||||||||||||||||||||||||||||||||||||||||||||||
| progressFill.style.width = `${progress}%`; | ||||||||||||||||||||||||||||||||||||||||||||||||
| if (typeof onRender === 'function') { | ||||||||||||||||||||||||||||||||||||||||||||||||
| onRender(task); | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| confirmButton.onclick = () => { | ||||||||||||||||||||||||||||||||||||||||||||||||
| if (typeof modal.close === 'function') { | ||||||||||||||||||||||||||||||||||||||||||||||||
| modal.close(); | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| modal.addEventListener('cancel', (event) => { | ||||||||||||||||||||||||||||||||||||||||||||||||
| if (confirmButton.disabled) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| event.preventDefault(); | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
| }, { once: true }); | ||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+142
to
+146
|
||||||||||||||||||||||||||||||||||||||||||||||||
| modal.addEventListener('cancel', (event) => { | |
| if (confirmButton.disabled) { | |
| event.preventDefault(); | |
| } | |
| }, { once: true }); | |
| // Ensure we don't accumulate multiple cancel listeners across calls. | |
| if (modal._taskRollCancelHandler) { | |
| modal.removeEventListener('cancel', modal._taskRollCancelHandler); | |
| } | |
| const cancelHandler = (event) => { | |
| if (confirmButton.disabled) { | |
| event.preventDefault(); | |
| } | |
| }; | |
| modal._taskRollCancelHandler = cancelHandler; | |
| modal.addEventListener('cancel', cancelHandler); |
Copilot
AI
Feb 22, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function hardcodes specific usernames ('shadukat' and 'gerni shadu') to provide special behavior. Hardcoded usernames in business logic create maintainability concerns and make the code less flexible. Consider moving these special user identifiers to a configuration file or database, or implementing a user role/flag system that can be managed through the admin interface rather than requiring code changes.
| function isSpecialInstantRollUser() { | |
| const username = getCurrentUsername().toLowerCase(); | |
| return username === 'shadukat' || username === 'gerni shadu'; | |
| function getSpecialInstantRollUsers() { | |
| if (typeof window !== 'undefined' && | |
| Array.isArray(window.SPECIAL_INSTANT_ROLL_USERS) && | |
| window.SPECIAL_INSTANT_ROLL_USERS.length > 0) { | |
| return window.SPECIAL_INSTANT_ROLL_USERS | |
| .map((name) => (typeof name === 'string' ? name.toLowerCase() : '')) | |
| .filter(Boolean); | |
| } | |
| // Default special users for instant roll behavior; can be overridden | |
| // by defining window.SPECIAL_INSTANT_ROLL_USERS elsewhere. | |
| return ['shadukat', 'gerni shadu']; | |
| } | |
| function isSpecialInstantRollUser() { | |
| const username = getCurrentUsername().toLowerCase(); | |
| if (!username) { | |
| return false; | |
| } | |
| const specialUsers = getSpecialInstantRollUsers(); | |
| return specialUsers.indexOf(username) !== -1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When the final task is null or undefined (if generation fails), this will create a sequence ending with null. The subsequent code in showTaskRollModal may fail when trying to access properties on the finalTask. Consider adding validation to handle cases where finalTask might be null/undefined, or ensure the calling code validates this before building the sequence.