Compare commits
10 Commits
ac93ccbcdb
...
fc3605034f
Author | SHA1 | Date | |
---|---|---|---|
fc3605034f | |||
668e2a6190 | |||
6dfb39ccbd | |||
eba7fac4db | |||
bdf3e3437a | |||
8068c002b7 | |||
ea64a2aecb | |||
348e7a83b8 | |||
7a0e234baf | |||
c21aa3e633 |
150
src/routes/quick/+page.svelte
Normal file
150
src/routes/quick/+page.svelte
Normal file
|
@ -0,0 +1,150 @@
|
|||
<script lang="js">
|
||||
import { createData } from '$lib/createData';
|
||||
import { scaleData } from '$lib/scaleData';
|
||||
import { error } from '@sveltejs/kit';
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
// Constants / Parameters
|
||||
const FPS = 20;
|
||||
const AMOUNT = 100;
|
||||
|
||||
// System variables
|
||||
const data = scaleData(createData(AMOUNT));
|
||||
/** @type {HTMLCanvasElement} */
|
||||
let canvas;
|
||||
/** @type {CanvasRenderingContext2D} */
|
||||
let context;
|
||||
/** @type {number} */
|
||||
let width;
|
||||
/** @type {number} */
|
||||
let interv;
|
||||
onMount(() => {
|
||||
// Initialize the canvas dimensions
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
|
||||
// Try getting 2D context
|
||||
const ctx = canvas.getContext('2d');
|
||||
if (!ctx) error(417, 'Canvas not supported');
|
||||
|
||||
// Initialize global variables
|
||||
context = ctx;
|
||||
width = canvas.width / AMOUNT;
|
||||
|
||||
// Start continuous animation
|
||||
interv = setInterval(animate, 1000 / FPS);
|
||||
|
||||
// Assign first job over the entire array
|
||||
queue.push(new Job(data, 0, data.length));
|
||||
});
|
||||
|
||||
/** @type {Job[]} */
|
||||
let queue = [];
|
||||
|
||||
/** Response type for the quicksort algorithm */
|
||||
class Response {
|
||||
/**
|
||||
* @param {boolean} done
|
||||
* @param {number|null} index
|
||||
* @param {number|null} start
|
||||
* @param {number|null} end
|
||||
*/
|
||||
constructor(done, index, start, end) {
|
||||
this.done = done;
|
||||
this.index = index;
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates follow up jobs from response.
|
||||
* @param {number[]} array
|
||||
* @returns {Job[]}
|
||||
*/
|
||||
generate(array) {
|
||||
if (this.done) return [];
|
||||
|
||||
return [
|
||||
new Job(array, this.start ?? 0, this.index ?? 0),
|
||||
new Job(array, this.index ?? 0 + 1, this.end ?? 0)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/** Represent a call to the quicksort algorithm. */
|
||||
class Job {
|
||||
/**
|
||||
* @param {number[]} array
|
||||
* @param {number} start
|
||||
* @param {number} end
|
||||
*/
|
||||
constructor(array, start, end) {
|
||||
this.array = array;
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
|
||||
this.pivot = array[end - 1];
|
||||
this.index = start;
|
||||
this.compr = start;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Response|void}
|
||||
*/
|
||||
step() {
|
||||
// Base case, end condition
|
||||
if (this.start >= this.end - 1 || this.start < 0) return new Response(true, null, null, null);
|
||||
|
||||
// Comparator reached end of range, swap pivot
|
||||
if (this.compr >= this.end - 1) {
|
||||
[this.array[this.index], this.array[this.end - 1]] = [
|
||||
this.array[this.end - 1],
|
||||
this.array[this.index]
|
||||
];
|
||||
|
||||
return new Response(false, this.index, this.start, this.end);
|
||||
}
|
||||
|
||||
// Compare with pivot to split range in two
|
||||
if (this.array[this.compr] <= this.pivot) {
|
||||
[this.array[this.index], this.array[this.compr]] = [
|
||||
this.array[this.compr],
|
||||
this.array[this.index]
|
||||
];
|
||||
this.index++;
|
||||
}
|
||||
this.compr++;
|
||||
}
|
||||
}
|
||||
|
||||
/** Render a single frame of the sorting algorithm at a time on the canvas. */
|
||||
function animate() {
|
||||
// Clear canvas with black background
|
||||
context.fillStyle = 'black';
|
||||
context.fillRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
// Display datapoints as lines
|
||||
context.fillStyle = 'white';
|
||||
data.forEach((d, i) => {
|
||||
let color = 'white';
|
||||
// Try chosing color based on all job indecies
|
||||
queue.forEach((q) => {
|
||||
const { index, compr } = q;
|
||||
if (i === index) color = 'red';
|
||||
else if (i === compr) color = 'lime';
|
||||
});
|
||||
// Display datapoint with chosen color
|
||||
context.fillStyle = color;
|
||||
context.fillRect(i * width, canvas.height, width - 1, -d * canvas.height);
|
||||
});
|
||||
|
||||
// Step job and handle result
|
||||
const result = queue[0].step();
|
||||
if (result) {
|
||||
queue.shift();
|
||||
if (!result.done) queue.push(...result.generate(data));
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<canvas bind:this={canvas} class="fixed top-0 left-0" />
|
|
@ -16,6 +16,8 @@
|
|||
let context;
|
||||
/** @type {number} */
|
||||
let width;
|
||||
/** @type {number} */
|
||||
let interv;
|
||||
onMount(() => {
|
||||
// Initialize the canvas dimensions
|
||||
canvas.width = window.innerWidth;
|
||||
|
@ -30,7 +32,7 @@
|
|||
width = canvas.width / AMOUNT;
|
||||
|
||||
// Start continuous animation
|
||||
setInterval(animate, 1000 / FPS);
|
||||
interv = setInterval(animate, 1000 / FPS);
|
||||
});
|
||||
|
||||
/** Render a single frame of the sorting algorithm at a time on the canvas. */
|
||||
|
|
Loading…
Reference in New Issue
Block a user