Skip to content

Commit

Permalink
Add code documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
Bubobubobubobubo committed Nov 26, 2023
1 parent 626a8be commit d717fc8
Show file tree
Hide file tree
Showing 7 changed files with 212 additions and 62 deletions.
85 changes: 47 additions & 38 deletions src/AudioVisualisation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@
import { getAnalyser } from "superdough";
import { type Editor } from "./main";

/**
* Draw a circle at a specific position on the canvas.
* @param {number} x - The x-coordinate of the circle's center.
* @param {number} y - The y-coordinate of the circle's center.
* @param {number} radius - The radius of the circle.
* @param {string} color - The fill color of the circle.
*/
export const drawCircle = (
/**
* Draw a circle at a specific position on the canvas.
* @param {number} x - The x-coordinate of the circle's center.
* @param {number} y - The y-coordinate of the circle's center.
* @param {number} radius - The radius of the circle.
* @param {string} color - The fill color of the circle.
*/
app: Editor,
x: number,
y: number,
radius: number,
color: string,
color: string
): void => {
// @ts-ignore
const canvas: HTMLCanvasElement = app.interface.feedback;
Expand All @@ -28,15 +28,15 @@ export const drawCircle = (
ctx.closePath();
};

/**
* Blinks a script indicator circle.
* @param script - The type of script.
* @param no - The shift amount multiplier.
*/
export const blinkScript = (
/**
* Blinks a script indicator circle.
* @param script - The type of script.
* @param no - The shift amount multiplier.
*/
app: Editor,
script: "local" | "global" | "init",
no?: number,
no?: number
) => {
if (no !== undefined && no < 1 && no > 9) return;
const blinkDuration =
Expand All @@ -55,15 +55,15 @@ export const blinkScript = (
horizontalOffset + shift,
app.interface.feedback.clientHeight - 15,
8,
"#fdba74",
"#fdba74"
);
};

/**
* Clears the circle at a given shift.
* @param shift - The pixel distance from the origin.
*/
const _clearBlinker = (shift: number) => {
/**
* Clears the circle at a given shift.
* @param shift - The pixel distance from the origin.
*/
const x = 50 + shift;
const y = app.interface.feedback.clientHeight - 15;
const radius = 8;
Expand Down Expand Up @@ -91,17 +91,18 @@ export const blinkScript = (
0,
0,
(app.interface.feedback as HTMLCanvasElement).width,
(app.interface.feedback as HTMLCanvasElement).height,
(app.interface.feedback as HTMLCanvasElement).height
);
}, blinkDuration);
}
};

/**
* Manages animation updates using requestAnimationFrame.
* @param app - The Editor application context.
*/
export const scriptBlinkers = () => {
/**
* Manages animation updates using requestAnimationFrame.
* @param app - The Editor application context.
*/

let lastFrameTime = Date.now();
const frameRate = 10;
const minFrameDelay = 1000 / frameRate;
Expand Down Expand Up @@ -134,15 +135,16 @@ export interface OscilloscopeConfig {
let lastZeroCrossingType: string | null = null; // 'negToPos' or 'posToNeg'
let lastRenderTime: number = 0;

/**
* Initializes and runs an oscilloscope using an AnalyzerNode.
* @param {HTMLCanvasElement} canvas - The canvas element to draw the oscilloscope.
* @param {OscilloscopeConfig} config - Configuration for the oscilloscope's appearance and behavior.
*/
export const runOscilloscope = (
canvas: HTMLCanvasElement,
app: Editor,
app: Editor
): void => {
/**
* Runs the oscilloscope visualization on the provided canvas element.
*
* @param canvas - The HTMLCanvasElement on which to render the visualization.
* @param app - The Editor object containing the configuration for the oscilloscope.
*/
let config = app.osc;
let analyzer = getAnalyser(config.fftSize);
let dataArray = new Float32Array(analyzer.frequencyBinCount);
Expand All @@ -155,7 +157,7 @@ export const runOscilloscope = (
width: number,
height: number,
offset_height: number,
offset_width: number,
offset_width: number
) {
const maxFPS = 30;
const now = performance.now();
Expand All @@ -170,11 +172,11 @@ export const runOscilloscope = (

const performanceFactor = 1;
const reducedDataSize = Math.floor(
freqDataArray.length * performanceFactor,
freqDataArray.length * performanceFactor
);
const numBars = Math.min(
reducedDataSize,
app.osc.orientation === "horizontal" ? width : height,
app.osc.orientation === "horizontal" ? width : height
);
const barWidth =
app.osc.orientation === "horizontal" ? width / numBars : height / numBars;
Expand All @@ -187,23 +189,23 @@ export const runOscilloscope = (
for (let i = 0; i < numBars; i++) {
barHeight = Math.floor(
freqDataArray[Math.floor((i * freqDataArray.length) / numBars)] *
((height / 256) * app.osc.size),
((height / 256) * app.osc.size)
);

if (app.osc.orientation === "horizontal") {
canvasCtx.fillRect(
x + offset_width,
(height - barHeight) / 2 + offset_height,
barWidth + 1,
barHeight,
barHeight
);
x += barWidth;
} else {
canvasCtx.fillRect(
(width - barHeight) / 2 + offset_width,
y + offset_height,
barHeight,
barWidth + 1,
barWidth + 1
);
y += barWidth;
}
Expand Down Expand Up @@ -232,12 +234,19 @@ export const runOscilloscope = (
-OFFSET_WIDTH,
-OFFSET_HEIGHT,
WIDTH + 2 * OFFSET_WIDTH,
HEIGHT + 2 * OFFSET_HEIGHT,
HEIGHT + 2 * OFFSET_HEIGHT
);
return;
}

if (analyzer.fftSize !== app.osc.fftSize) {
// Disconnect and release the old analyzer if it exists
if (analyzer) {
analyzer.disconnect();
analyzer = null; // Release the reference for garbage collection
}

// Create a new analyzer with the updated FFT size
analyzer = getAnalyser(app.osc.fftSize);
dataArray = new Float32Array(analyzer.frequencyBinCount);
}
Expand All @@ -252,7 +261,7 @@ export const runOscilloscope = (
-OFFSET_WIDTH,
-OFFSET_HEIGHT,
WIDTH + 2 * OFFSET_WIDTH,
HEIGHT + 2 * OFFSET_HEIGHT,
HEIGHT + 2 * OFFSET_HEIGHT
);
}
canvasCtx.lineWidth = app.osc.thickness;
Expand Down
11 changes: 7 additions & 4 deletions src/Clock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,7 @@ export class Clock {
lastPlayPressTime: number;
totalPauseTime: number;

constructor(
public app: Editor,
ctx: AudioContext,
) {
constructor(public app: Editor, ctx: AudioContext) {
this.time_position = { bar: 0, beat: 0, pulse: 0 };
this.time_signature = [4, 4];
this.logicalTime = 0;
Expand All @@ -77,6 +74,12 @@ export class Clock {
}

convertTicksToTimeposition(ticks: number): TimePosition {
/**
* Converts ticks to a TimePosition object.
* @param ticks The number of ticks to convert.
* @returns The TimePosition object representing the converted ticks.
*/

const beatsPerBar = this.app.clock.time_signature[0];
const ppqnPosition = ticks % this.app.clock.ppqn;
const beatNumber = Math.floor(ticks / this.app.clock.ppqn);
Expand Down
23 changes: 20 additions & 3 deletions src/Documentation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export const makeExampleFactory = (application: Editor): Function => {
const make_example = (
description: string,
code: string,
open: boolean = false,
open: boolean = false
) => {
const codeId = `codeExample${application.exampleCounter++}`;
// Store the code snippet in the data structure
Expand All @@ -70,7 +70,11 @@ export const makeExampleFactory = (application: Editor): Function => {
};

export const documentation_factory = (application: Editor) => {
// Initialize a data structure to store code examples by their unique IDs
/**
* Creates the documentation for the given application.
* @param application The editor application.
* @returns An object containing various documentation sections.
*/
application.api.codeExamples = {};

return {
Expand Down Expand Up @@ -109,6 +113,10 @@ export const documentation_factory = (application: Editor) => {
};

export const showDocumentation = (app: Editor) => {
/**
* Shows or hides the documentation based on the current state of the app.
* @param app - The Editor instance.
*/
if (document.getElementById("app")?.classList.contains("hidden")) {
document.getElementById("app")?.classList.remove("hidden");
document.getElementById("documentation")?.classList.add("hidden");
Expand All @@ -129,21 +137,30 @@ export const showDocumentation = (app: Editor) => {
};

export const hideDocumentation = () => {
/**
* Hides the documentation section and shows the main application.
*/
if (document.getElementById("app")?.classList.contains("hidden")) {
document.getElementById("app")?.classList.remove("hidden");
document.getElementById("documentation")?.classList.add("hidden");
}
};

export const updateDocumentationContent = (app: Editor, bindings: any) => {
/**
* Updates the content of the documentation pane with the converted markdown.
*
* @param app - The editor application.
* @param bindings - Additional bindings for the showdown converter.
*/
const converter = new showdown.Converter({
emoji: true,
moreStyling: true,
backslashEscapesHTMLTags: true,
extensions: [showdownHighlight({ auto_detection: true }), ...bindings],
});
const converted_markdown = converter.makeHtml(
app.docs[app.currentDocumentationPane],
app.docs[app.currentDocumentationPane]
);
document.getElementById("documentation-content")!.innerHTML =
converted_markdown;
Expand Down
6 changes: 6 additions & 0 deletions src/DomElements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ export const buttonGroups = {

//@ts-ignore
export const createDocumentationStyle = (app: Editor) => {
/**
* Creates a documentation style object.
* @param {Editor} app - The editor object.
* @returns {Object} - The documentation style object.
*/

return {
h1: "text-white lg:text-4xl text-xl lg:ml-4 lg:mx-4 mx-2 lg:my-4 my-2 lg:mb-4 mb-4 border-b-4 pt-4 pb-3 px-2",
h2: "text-white lg:text-3xl text-xl lg:ml-4 lg:mx-4 mx-2 lg:my-4 my-2 lg:mb-4 mb-4 border-b-2 pt-12 pb-3 px-2",
Expand Down
44 changes: 37 additions & 7 deletions src/Evaluator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,19 @@ const codeReplace = (code: string): string => {

const tryCatchWrapper = async (
application: Editor,
code: string,
code: string
): Promise<boolean> => {
/**
* Wraps the provided code in a try-catch block and executes it.
*
* @param application - The editor application.
* @param code - The code to be executed.
* @returns A promise that resolves to a boolean indicating whether the code executed successfully or not.
*/

try {
await new Function(`"use strict"; ${codeReplace(code)}`).call(
application.api,
application.api
);
return true;
} catch (error) {
Expand All @@ -26,18 +34,32 @@ const cache = new Map<string, Function>();
const MAX_CACHE_SIZE = 40;

const addFunctionToCache = (code: string, fn: Function) => {
/**
* Adds a function to the cache.
* @param code - The code associated with the function.
* @param fn - The function to be added to the cache.
*/
if (cache.size >= MAX_CACHE_SIZE) {
cache.delete(cache.keys().next().value);
}
cache.set(code, fn);
};

// Optimized evaluate function with reduced complexity
export const tryEvaluate = async (
application: Editor,
code: File,
timeout = 5000,
timeout = 5000
): Promise<void> => {
/**
* Tries to evaluate the provided code within a specified timeout period.
* Increments the evaluation count of the code file.
* If the code is valid, updates the committed code and adds the evaluated function to the cache.
* If the code is invalid, retries the evaluation.
* @param application - The editor application.
* @param code - The code file to evaluate.
* @param timeout - The timeout period in milliseconds (default: 5000).
* @returns A Promise that resolves when the evaluation is complete.
*/
code.evaluations!++;
const candidateCode = code.candidate;

Expand All @@ -55,7 +77,7 @@ export const tryEvaluate = async (
if (isCodeValid) {
code.committed = code.candidate;
const newFunction = new Function(
`"use strict"; ${codeReplace(wrappedCode)}`,
`"use strict"; ${codeReplace(wrappedCode)}`
);
addFunctionToCache(candidateCode, newFunction);
} else {
Expand All @@ -71,8 +93,16 @@ export const tryEvaluate = async (
export const evaluate = async (
application: Editor,
code: File,
timeout = 1000,
timeout = 1000
): Promise<void> => {
/**
* Evaluates the given code using the provided application and timeout.
* @param application The editor application.
* @param code The code file to evaluate.
* @param timeout The timeout value in milliseconds (default: 1000).
* @returns A Promise that resolves when the evaluation is complete.
*/

try {
await Promise.race([
tryCatchWrapper(application, code.committed as string),
Expand All @@ -87,7 +117,7 @@ export const evaluate = async (

export const evaluateOnce = async (
application: Editor,
code: string,
code: string
): Promise<void> => {
/**
* Evaluates the code once without any caching or error-handling mechanisms besides the tryCatchWrapper.
Expand Down
Loading

0 comments on commit d717fc8

Please sign in to comment.