Skip to content

Commit

Permalink
untested commit
Browse files Browse the repository at this point in the history
  • Loading branch information
TheBlindHawk committed Apr 5, 2024
1 parent 9a988e9 commit 9e279b2
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 3 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ npm install @theblindhawk/roulette
> 2. a few keywords such as "roll" will be changing into "spin"
> 3. Vue and React utilities will be coming in the form of new packages (roulette-spinner-react and roulette-spinner-vue)
>
> Apologies for the inconvinience!
> Apologies for the inconvenience!
## v3.0 Features

Expand Down
3 changes: 3 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ <h2>You rolled on: </h2>
<div id="roulette-doughnut"></div>
<button id="start-doughnut" style="margin:auto;display:block;">start</button>
</div>
</div>
<div style="display:flex;justify-content: space-evenly;align-items: center;">

</div>
<script type="module">
import Roulette from './src/index.ts';
Expand Down
69 changes: 67 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,7 @@ export default class Roulette {
const sections = this.sections.length
const point = (360 * index) / this.sections.length + 360 / this.sections.length / 2 - this.arrow.shift
const loosen = this.settings.roll.landing === 'random'
? Math.round((Math.random() * 320) / sections - 320 / sections / 2)
: 0
? Math.round((Math.random() * 320) / sections - 320 / sections / 2) : 0
const sprint = Math.floor(this.settings.roll.duration / 360 / 3) * 360 + point + loosen

const audio_distance = 360 / this.sections.length
Expand Down Expand Up @@ -125,6 +124,72 @@ export default class Roulette {
return section.value
}

public asyncRoll(promise: Promise<number>) {
if (this.rolling) {
console.error(errors.roulette_is_rolling)
return
}

let section: SectionData | undefined
this.onstart?.(undefined as unknown as number)
this.rolling = true

let milliseconds = 0
let rotation = this.rotation
const sections = this.sections.length
const loosen = this.settings.roll.landing === 'random'
? Math.round((Math.random() * 320) / sections - 320 / sections / 2) : 0
let sprint = Math.floor(this.settings.roll.duration / 360 / 3) * 360 + loosen

const audio_distance = 360 / this.sections.length
let audio_counter = (rotation + this.board.shift) % audio_distance

this.audio.playOnce()

const ival = setInterval(() => {
const next_rotation = -sprint
* (milliseconds / this.settings.roll.duration)
* (milliseconds / this.settings.roll.duration - 2)
- this.board.shift
audio_counter += next_rotation - rotation
rotation = section ? next_rotation : next_rotation % 360

this.board.rotateImage((rotation % 360) * -1)

if (audio_counter >= audio_distance) {
this.audio.playOnSection()
audio_counter -= audio_distance
}

if (section && (rotation >= sprint || milliseconds >= this.settings.roll.duration)) {
clearInterval(ival)
this.rotation = rotation % 360
this.onstop?.(section)
this.rolling = false
}
milliseconds += 20
}, 20)

promise.then((index) => {
section = this.sections.find(index)

if (index < 0 || index >= this.sections.length) {
console.error(errors.index_out_of_bounds(index))
clearInterval(ival)
this.rolling = false
return
}

sprint += (360 * index) / this.sections.length + 360 / this.sections.length / 2 - this.arrow.shift
})

promise.catch((error) => {
console.error(error)
clearInterval(ival)
this.rolling = false
})
}

private drawSVGRoulette() {
if (this.board.custom_image) return

Expand Down
19 changes: 19 additions & 0 deletions tests/async-roll.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/* @jest-environment jsdom */
/* jslint browser: true */
/* global document window */
import { test, vi } from 'vitest'
import Roulette from '../src/index'

vi.useFakeTimers({ shouldAdvanceTime: true })
vi.spyOn(window.HTMLMediaElement.prototype, 'play').mockImplementation(() => {})
document.body.innerHTML = `<div id="roulette"></div>`

test('roulette asyncRoll by index', () => {
const roulette = new Roulette({ container: 'roulette', sections: ['a', 'b', 'c'] })
const { promise, resolve } = Promise.withResolvers()
const last_roll = roulette.asyncRoll(promise)
vi.advanceTimersByTime(2000) // 2 seconds API delay
resolve(0)
vi.advanceTimersByTime(10000)
expect(last_roll).toBe('a')
})

0 comments on commit 9e279b2

Please sign in to comment.