import { a3 as constants } from '../../constants-BxjhKpTv.js';
import { z } from 'zod/v4';

var p5$1 = {
	describe: {
		overloads: [
			[
				"String",
				"FALLBACK|LABEL?"
			]
		]
	},
	describeElement: {
		overloads: [
			[
				"String",
				"String",
				"FALLBACK|LABEL?"
			]
		]
	},
	textOutput: {
		overloads: [
			[
				"FALLBACK|LABEL?"
			]
		]
	},
	gridOutput: {
		overloads: [
			[
				"FALLBACK|LABEL?"
			]
		]
	},
	remove: {
		overloads: [
			[
			]
		]
	},
	p5: {
		overloads: [
			[
				"Object",
				"String|HTMLElement"
			]
		]
	},
	color: {
		overloads: [
			[
				"Number",
				"Number?"
			],
			[
				"Number",
				"Number",
				"Number",
				"Number?"
			],
			[
				"String"
			],
			[
				"Number[]"
			],
			[
				"p5.Color"
			]
		]
	},
	red: {
		overloads: [
			[
				"p5.Color|Number[]|String"
			]
		]
	},
	green: {
		overloads: [
			[
				"p5.Color|Number[]|String"
			]
		]
	},
	blue: {
		overloads: [
			[
				"p5.Color|Number[]|String"
			]
		]
	},
	alpha: {
		overloads: [
			[
				"p5.Color|Number[]|String"
			]
		]
	},
	hue: {
		overloads: [
			[
				"p5.Color|Number[]|String"
			]
		]
	},
	saturation: {
		overloads: [
			[
				"p5.Color|Number[]|String"
			]
		]
	},
	brightness: {
		overloads: [
			[
				"p5.Color|Number[]|String"
			]
		]
	},
	lightness: {
		overloads: [
			[
				"p5.Color|Number[]|String"
			]
		]
	},
	lerpColor: {
		overloads: [
			[
				"p5.Color",
				"p5.Color",
				"Number"
			]
		]
	},
	paletteLerp: {
		overloads: [
			[
				"[p5.Color|String|Number|Number[], Number][]",
				"Number"
			]
		]
	},
	beginClip: {
		overloads: [
			[
				"Object?"
			]
		]
	},
	endClip: {
		overloads: [
			[
			]
		]
	},
	clip: {
		overloads: [
			[
				"Function",
				"Object?"
			]
		]
	},
	background: {
		overloads: [
			[
				"p5.Color"
			],
			[
				"String",
				"Number?"
			],
			[
				"Number",
				"Number?"
			],
			[
				"Number",
				"Number",
				"Number",
				"Number?"
			],
			[
				"Number[]"
			],
			[
				"p5.Image",
				"Number?"
			]
		]
	},
	clear: {
		overloads: [
			[
				"Number?",
				"Number?",
				"Number?",
				"Number?"
			],
			[
			]
		]
	},
	colorMode: {
		overloads: [
			[
				"RGB|HSB|HSL|RGBHDR|HWB|LAB|LCH|OKLAB|OKLCH",
				"Number?"
			],
			[
				"RGB|HSB|HSL|RGBHDR|HWB|LAB|LCH|OKLAB|OKLCH",
				"Number",
				"Number",
				"Number",
				"Number?"
			],
			[
			]
		]
	},
	fill: {
		overloads: [
			[
				"Number",
				"Number",
				"Number",
				"Number?"
			],
			[
				"String"
			],
			[
				"Number",
				"Number?"
			],
			[
				"Number[]"
			],
			[
				"p5.Color"
			]
		]
	},
	noFill: {
		overloads: [
			[
			]
		]
	},
	noStroke: {
		overloads: [
			[
			]
		]
	},
	stroke: {
		overloads: [
			[
				"Number",
				"Number",
				"Number",
				"Number?"
			],
			[
				"String"
			],
			[
				"Number",
				"Number?"
			],
			[
				"Number[]"
			],
			[
				"p5.Color"
			]
		]
	},
	erase: {
		overloads: [
			[
				"Number?",
				"Number?"
			]
		]
	},
	noErase: {
		overloads: [
			[
			]
		]
	},
	blendMode: {
		overloads: [
			[
				"BLEND|DARKEST|LIGHTEST|DIFFERENCE|MULTIPLY|EXCLUSION|SCREEN|REPLACE|OVERLAY|HARD_LIGHT|SOFT_LIGHT|DODGE|BURN|ADD|REMOVE|SUBTRACT"
			]
		]
	},
	print: {
		overloads: [
			[
				"Any"
			],
			[
				"String|Number|Array"
			]
		]
	},
	cursor: {
		overloads: [
			[
				"ARROW|CROSS|HAND|MOVE|TEXT|WAIT|String",
				"Number?",
				"Number?"
			]
		]
	},
	frameRate: {
		overloads: [
			[
				"Number"
			],
			[
			]
		]
	},
	getTargetFrameRate: {
		overloads: [
			[
			]
		]
	},
	noCursor: {
		overloads: [
			[
			]
		]
	},
	windowResized: {
		overloads: [
			[
				"Event?"
			]
		]
	},
	fullscreen: {
		overloads: [
			[
				"Boolean?"
			]
		]
	},
	pixelDensity: {
		overloads: [
			[
				"Number?"
			],
			[
			]
		]
	},
	displayDensity: {
		overloads: [
			[
			]
		]
	},
	getURL: {
		overloads: [
			[
			]
		]
	},
	getURLPath: {
		overloads: [
			[
			]
		]
	},
	getURLParams: {
		overloads: [
			[
			]
		]
	},
	worldToScreen: {
		overloads: [
			[
				"Number|p5.Vector",
				"Number",
				"Number?"
			]
		]
	},
	screenToWorld: {
		overloads: [
			[
				"Number|p5.Vector",
				"Number",
				"Number?"
			]
		]
	},
	setup: {
		overloads: [
			[
			]
		]
	},
	draw: {
		overloads: [
			[
			]
		]
	},
	registerAddon: {
		overloads: [
			[
				"Function"
			]
		]
	},
	createCanvas: {
		overloads: [
			[
				"Number?",
				"Number?",
				"P2D|WEBGL|P2DHDR|WEBGPU?",
				"HTMLCanvasElement?"
			],
			[
				"Number?",
				"Number?",
				"HTMLCanvasElement?"
			]
		]
	},
	resizeCanvas: {
		overloads: [
			[
				"Number",
				"Number",
				"Boolean?"
			]
		]
	},
	noCanvas: {
		overloads: [
			[
			]
		]
	},
	createGraphics: {
		overloads: [
			[
				"Number",
				"Number",
				"P2D|WEBGL?",
				"HTMLCanvasElement?"
			],
			[
				"Number",
				"Number",
				"HTMLCanvasElement?"
			]
		]
	},
	createFramebuffer: {
		overloads: [
			[
				"Object?"
			]
		]
	},
	clearDepth: {
		overloads: [
			[
				"Number?"
			]
		]
	},
	noLoop: {
		overloads: [
			[
			]
		]
	},
	loop: {
		overloads: [
			[
			]
		]
	},
	isLooping: {
		overloads: [
			[
			]
		]
	},
	redraw: {
		overloads: [
			[
				"Integer?"
			]
		]
	},
	applyMatrix: {
		overloads: [
			[
				"Number[]"
			],
			[
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number"
			],
			[
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number"
			]
		]
	},
	resetMatrix: {
		overloads: [
			[
			]
		]
	},
	rotate: {
		overloads: [
			[
				"Number",
				"p5.Vector|Number[]?"
			]
		]
	},
	rotateX: {
		overloads: [
			[
				"Number"
			]
		]
	},
	rotateY: {
		overloads: [
			[
				"Number"
			]
		]
	},
	rotateZ: {
		overloads: [
			[
				"Number"
			]
		]
	},
	scale: {
		overloads: [
			[
				"Number|p5.Vector|Number[]",
				"Number?",
				"Number?"
			],
			[
				"p5.Vector|Number[]"
			]
		]
	},
	shearX: {
		overloads: [
			[
				"Number"
			]
		]
	},
	shearY: {
		overloads: [
			[
				"Number"
			]
		]
	},
	translate: {
		overloads: [
			[
				"Number",
				"Number",
				"Number?"
			],
			[
				"p5.Vector"
			]
		]
	},
	push: {
		overloads: [
			[
			]
		]
	},
	pop: {
		overloads: [
			[
			]
		]
	},
	storeItem: {
		overloads: [
			[
				"String",
				"String|Number|Boolean|Object|Array"
			]
		]
	},
	getItem: {
		overloads: [
			[
				"String"
			]
		]
	},
	clearStorage: {
		overloads: [
			[
			]
		]
	},
	removeItem: {
		overloads: [
			[
				"String"
			]
		]
	},
	select: {
		overloads: [
			[
				"String",
				"String|p5.Element|HTMLElement?"
			]
		]
	},
	selectAll: {
		overloads: [
			[
				"String",
				"String|p5.Element|HTMLElement?"
			]
		]
	},
	createElement: {
		overloads: [
			[
				"String",
				"String?"
			]
		]
	},
	removeElements: {
		overloads: [
			[
			]
		]
	},
	addElement: {
		overloads: [
			[
			]
		]
	},
	createDiv: {
		overloads: [
			[
				"String?"
			]
		]
	},
	createP: {
		overloads: [
			[
				"String?"
			]
		]
	},
	createSpan: {
		overloads: [
			[
				"String?"
			]
		]
	},
	createImg: {
		overloads: [
			[
				"String",
				"String"
			],
			[
				"String",
				"String",
				"String?",
				"Function?"
			]
		]
	},
	createA: {
		overloads: [
			[
				"String",
				"String",
				"String?"
			]
		]
	},
	createSlider: {
		overloads: [
			[
				"Number",
				"Number",
				"Number?",
				"Number?"
			]
		]
	},
	createButton: {
		overloads: [
			[
				"String",
				"String?"
			]
		]
	},
	createCheckbox: {
		overloads: [
			[
				"String?",
				"Boolean?"
			]
		]
	},
	createSelect: {
		overloads: [
			[
				"Boolean?"
			],
			[
				"Object"
			]
		]
	},
	createRadio: {
		overloads: [
			[
				"Object?"
			],
			[
				"String?"
			],
			[
			]
		]
	},
	createColorPicker: {
		overloads: [
			[
				"String|p5.Color?"
			]
		]
	},
	createInput: {
		overloads: [
			[
				"String?",
				"String?"
			],
			[
				"String?"
			]
		]
	},
	createFileInput: {
		overloads: [
			[
				"Function",
				"Boolean?"
			]
		]
	},
	createVideo: {
		overloads: [
			[
				"String|String[]?",
				"Function?"
			]
		]
	},
	createAudio: {
		overloads: [
			[
				"String|String[]?",
				"Function?"
			]
		]
	},
	createCapture: {
		overloads: [
			[
				"AUDIO|VIDEO|Object?",
				"Object?",
				"Function?"
			]
		]
	},
	setMoveThreshold: {
		overloads: [
			[
				"Number"
			]
		]
	},
	setShakeThreshold: {
		overloads: [
			[
				"Number"
			]
		]
	},
	deviceMoved: {
		overloads: [
			[
			]
		]
	},
	deviceTurned: {
		overloads: [
			[
			]
		]
	},
	deviceShaken: {
		overloads: [
			[
			]
		]
	},
	keyPressed: {
		overloads: [
			[
				"KeyboardEvent?"
			]
		]
	},
	keyReleased: {
		overloads: [
			[
				"KeyboardEvent?"
			]
		]
	},
	keyTyped: {
		overloads: [
			[
				"KeyboardEvent?"
			]
		]
	},
	keyIsDown: {
		overloads: [
			[
				"Number|String"
			]
		]
	},
	mouseMoved: {
		overloads: [
			[
				"MouseEvent?"
			]
		]
	},
	mouseDragged: {
		overloads: [
			[
				"MouseEvent?"
			]
		]
	},
	mousePressed: {
		overloads: [
			[
				"MouseEvent?"
			]
		]
	},
	mouseReleased: {
		overloads: [
			[
				"MouseEvent?"
			]
		]
	},
	mouseClicked: {
		overloads: [
			[
				"MouseEvent?"
			]
		]
	},
	doubleClicked: {
		overloads: [
			[
				"MouseEvent?"
			]
		]
	},
	mouseWheel: {
		overloads: [
			[
				"WheelEvent?"
			]
		]
	},
	requestPointerLock: {
		overloads: [
			[
			]
		]
	},
	exitPointerLock: {
		overloads: [
			[
			]
		]
	},
	createImage: {
		overloads: [
			[
				"Integer",
				"Integer"
			]
		]
	},
	saveCanvas: {
		overloads: [
			[
				"p5.Framebuffer|p5.Element|HTMLCanvasElement",
				"String?",
				"String?"
			],
			[
				"String?",
				"String?"
			]
		]
	},
	saveFrames: {
		overloads: [
			[
				"String",
				"String",
				"Number",
				"Number",
				"function(Array)?"
			]
		]
	},
	loadImage: {
		overloads: [
			[
				"String|Request",
				"function(p5.Image)?",
				"function(Event)?"
			]
		]
	},
	saveGif: {
		overloads: [
			[
				"String",
				"Number",
				"Object?"
			]
		]
	},
	image: {
		overloads: [
			[
				"p5.Image|p5.Element|p5.Texture|p5.Framebuffer|p5.FramebufferTexture|p5.Renderer|p5.Graphics",
				"Number",
				"Number",
				"Number?",
				"Number?"
			],
			[
				"p5.Image|p5.Element|p5.Texture|p5.Framebuffer|p5.FramebufferTexture",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number?",
				"Number?",
				"CONTAIN|COVER?",
				"LEFT|RIGHT|CENTER?",
				"TOP|BOTTOM|CENTER?"
			]
		]
	},
	tint: {
		overloads: [
			[
				"Number",
				"Number",
				"Number",
				"Number?"
			],
			[
				"String"
			],
			[
				"Number",
				"Number?"
			],
			[
				"Number[]"
			],
			[
				"p5.Color"
			]
		]
	},
	noTint: {
		overloads: [
			[
			]
		]
	},
	imageMode: {
		overloads: [
			[
				"CORNER|CORNERS|CENTER"
			]
		]
	},
	blend: {
		overloads: [
			[
				"p5.Image",
				"Integer",
				"Integer",
				"Integer",
				"Integer",
				"Integer",
				"Integer",
				"Integer",
				"Integer",
				"BLEND|DARKEST|LIGHTEST|DIFFERENCE|MULTIPLY|EXCLUSION|SCREEN|REPLACE|OVERLAY|HARD_LIGHT|SOFT_LIGHT|DODGE|BURN|ADD|NORMAL"
			],
			[
				"Integer",
				"Integer",
				"Integer",
				"Integer",
				"Integer",
				"Integer",
				"Integer",
				"Integer",
				"BLEND|DARKEST|LIGHTEST|DIFFERENCE|MULTIPLY|EXCLUSION|SCREEN|REPLACE|OVERLAY|HARD_LIGHT|SOFT_LIGHT|DODGE|BURN|ADD|NORMAL"
			]
		]
	},
	copy: {
		overloads: [
			[
				"p5.Image|p5.Element",
				"Integer",
				"Integer",
				"Integer",
				"Integer",
				"Integer",
				"Integer",
				"Integer",
				"Integer"
			],
			[
				"Integer",
				"Integer",
				"Integer",
				"Integer",
				"Integer",
				"Integer",
				"Integer",
				"Integer"
			]
		]
	},
	filter: {
		overloads: [
			[
				"THRESHOLD|GRAY|OPAQUE|INVERT|POSTERIZE|BLUR|ERODE|DILATE|BLUR",
				"Number?",
				"Boolean?"
			],
			[
				"p5.Shader"
			]
		]
	},
	get: {
		overloads: [
			[
				"Number",
				"Number",
				"Number",
				"Number"
			],
			[
			],
			[
				"Number",
				"Number"
			]
		]
	},
	loadPixels: {
		overloads: [
			[
			]
		]
	},
	set: {
		overloads: [
			[
				"Number",
				"Number",
				"Number|Number[]|Object"
			]
		]
	},
	updatePixels: {
		overloads: [
			[
				"Number?",
				"Number?",
				"Number?",
				"Number?"
			],
			[
			]
		]
	},
	loadJSON: {
		overloads: [
			[
				"String|Request",
				"Function?",
				"Function?"
			]
		]
	},
	loadStrings: {
		overloads: [
			[
				"String|Request",
				"Function?",
				"Function?"
			]
		]
	},
	loadTable: {
		overloads: [
			[
				"String|Request",
				"String?",
				"String?",
				"Function?",
				"Function?"
			]
		]
	},
	loadXML: {
		overloads: [
			[
				"String|Request",
				"Function?",
				"Function?"
			]
		]
	},
	loadBytes: {
		overloads: [
			[
				"String|Request",
				"Function?",
				"Function?"
			]
		]
	},
	loadBlob: {
		overloads: [
			[
				"String|Request",
				"Function?",
				"Function?"
			]
		]
	},
	httpGet: {
		overloads: [
			[
				"String|Request",
				"String?",
				"Function?",
				"Function?"
			],
			[
				"String|Request",
				"Function",
				"Function?"
			]
		]
	},
	httpPost: {
		overloads: [
			[
				"String|Request",
				"Object|Boolean?",
				"String?",
				"Function?",
				"Function?"
			],
			[
				"String|Request",
				"Object|Boolean",
				"Function?",
				"Function?"
			],
			[
				"String|Request",
				"Function?",
				"Function?"
			]
		]
	},
	httpDo: {
		overloads: [
			[
				"String|Request",
				"String?",
				"String?",
				"Object?",
				"Function?",
				"Function?"
			],
			[
				"String|Request",
				"Function?",
				"Function?"
			]
		]
	},
	createWriter: {
		overloads: [
			[
				"String",
				"String?"
			]
		]
	},
	write: {
		overloads: [
			[
				"String|Number|Array"
			]
		]
	},
	close: {
		overloads: [
			[
			]
		]
	},
	save: {
		overloads: [
			[
				"Object|String?",
				"String?",
				"Boolean|String?"
			]
		]
	},
	saveJSON: {
		overloads: [
			[
				"Array|Object",
				"String",
				"Boolean?"
			]
		]
	},
	saveStrings: {
		overloads: [
			[
				"String[]",
				"String",
				"String?",
				"Boolean?"
			]
		]
	},
	saveTable: {
		overloads: [
			[
				"p5.Table",
				"String",
				"String?"
			]
		]
	},
	setContent: {
		overloads: [
			[
				"String"
			]
		]
	},
	abs: {
		overloads: [
			[
				"Number"
			]
		]
	},
	ceil: {
		overloads: [
			[
				"Number"
			]
		]
	},
	constrain: {
		overloads: [
			[
				"Number",
				"Number",
				"Number"
			]
		]
	},
	dist: {
		overloads: [
			[
				"Number",
				"Number",
				"Number",
				"Number"
			],
			[
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number"
			]
		]
	},
	exp: {
		overloads: [
			[
				"Number"
			]
		]
	},
	floor: {
		overloads: [
			[
				"Number"
			]
		]
	},
	lerp: {
		overloads: [
			[
				"Number",
				"Number",
				"Number"
			]
		]
	},
	log: {
		overloads: [
			[
				"Number"
			]
		]
	},
	mag: {
		overloads: [
			[
				"Number",
				"Number"
			]
		]
	},
	map: {
		overloads: [
			[
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Boolean?"
			]
		]
	},
	max: {
		overloads: [
			[
				"Number",
				"Number"
			],
			[
				"Number[]"
			]
		]
	},
	min: {
		overloads: [
			[
				"Number",
				"Number"
			],
			[
				"Number[]"
			]
		]
	},
	norm: {
		overloads: [
			[
				"Number",
				"Number",
				"Number"
			]
		]
	},
	pow: {
		overloads: [
			[
				"Number",
				"Number"
			]
		]
	},
	round: {
		overloads: [
			[
				"Number",
				"Number?"
			]
		]
	},
	sq: {
		overloads: [
			[
				"Number"
			]
		]
	},
	sqrt: {
		overloads: [
			[
				"Number"
			]
		]
	},
	fract: {
		overloads: [
			[
				"Number"
			]
		]
	},
	createVector: {
		overloads: [
			[
				"...Number[]"
			]
		]
	},
	noise: {
		overloads: [
			[
				"Number",
				"Number?",
				"Number?"
			]
		]
	},
	noiseDetail: {
		overloads: [
			[
				"Number"
			],
			[
				"Number",
				"Number"
			]
		]
	},
	noiseSeed: {
		overloads: [
			[
				"Number"
			]
		]
	},
	randomSeed: {
		overloads: [
			[
				"Number"
			]
		]
	},
	random: {
		overloads: [
			[
				"Number?",
				"Number?"
			],
			[
				"Array"
			]
		]
	},
	randomGaussian: {
		overloads: [
			[
				"Number?",
				"Number?"
			]
		]
	},
	acos: {
		overloads: [
			[
				"Number"
			]
		]
	},
	asin: {
		overloads: [
			[
				"Number"
			]
		]
	},
	atan: {
		overloads: [
			[
				"Number"
			]
		]
	},
	atan2: {
		overloads: [
			[
				"Number",
				"Number"
			]
		]
	},
	cos: {
		overloads: [
			[
				"Number"
			]
		]
	},
	sin: {
		overloads: [
			[
				"Number"
			]
		]
	},
	tan: {
		overloads: [
			[
				"Number"
			]
		]
	},
	degrees: {
		overloads: [
			[
				"Number"
			]
		]
	},
	radians: {
		overloads: [
			[
				"Number"
			]
		]
	},
	angleMode: {
		overloads: [
			[
				"RADIANS|DEGREES"
			],
			[
			]
		]
	},
	arc: {
		overloads: [
			[
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"CHORD|PIE|OPEN?",
				"Integer?"
			]
		]
	},
	ellipse: {
		overloads: [
			[
				"Number",
				"Number",
				"Number",
				"Number?"
			],
			[
				"Number",
				"Number",
				"Number",
				"Number",
				"Integer?"
			]
		]
	},
	circle: {
		overloads: [
			[
				"Number",
				"Number",
				"Number"
			]
		]
	},
	line: {
		overloads: [
			[
				"Number",
				"Number",
				"Number",
				"Number"
			],
			[
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number"
			]
		]
	},
	point: {
		overloads: [
			[
				"Number",
				"Number",
				"Number?"
			],
			[
				"p5.Vector"
			]
		]
	},
	quad: {
		overloads: [
			[
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Integer?",
				"Integer?"
			],
			[
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Integer?",
				"Integer?"
			]
		]
	},
	rect: {
		overloads: [
			[
				"Number",
				"Number",
				"Number",
				"Number?",
				"Number?",
				"Number?",
				"Number?",
				"Number?"
			],
			[
				"Number",
				"Number",
				"Number",
				"Number",
				"Integer?",
				"Integer?"
			]
		]
	},
	square: {
		overloads: [
			[
				"Number",
				"Number",
				"Number",
				"Number?",
				"Number?",
				"Number?",
				"Number?"
			]
		]
	},
	triangle: {
		overloads: [
			[
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number"
			]
		]
	},
	ellipseMode: {
		overloads: [
			[
				"CENTER|RADIUS|CORNER|CORNERS"
			]
		]
	},
	noSmooth: {
		overloads: [
			[
			]
		]
	},
	rectMode: {
		overloads: [
			[
				"CENTER|RADIUS|CORNER|CORNERS"
			]
		]
	},
	smooth: {
		overloads: [
			[
			]
		]
	},
	strokeCap: {
		overloads: [
			[
				"ROUND|SQUARE|PROJECT"
			]
		]
	},
	strokeJoin: {
		overloads: [
			[
				"MITER|BEVEL|ROUND"
			]
		]
	},
	strokeWeight: {
		overloads: [
			[
				"Number"
			]
		]
	},
	bezier: {
		overloads: [
			[
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number"
			],
			[
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number"
			]
		]
	},
	bezierPoint: {
		overloads: [
			[
				"Number",
				"Number",
				"Number",
				"Number",
				"Number"
			]
		]
	},
	bezierTangent: {
		overloads: [
			[
				"Number",
				"Number",
				"Number",
				"Number",
				"Number"
			]
		]
	},
	spline: {
		overloads: [
			[
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number"
			],
			[
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number"
			]
		]
	},
	splinePoint: {
		overloads: [
			[
				"Number",
				"Number",
				"Number",
				"Number",
				"Number"
			]
		]
	},
	splineTangent: {
		overloads: [
			[
				"Number",
				"Number",
				"Number",
				"Number",
				"Number"
			]
		]
	},
	bezierOrder: {
		overloads: [
			[
				"Number"
			],
			[
			]
		]
	},
	splineVertex: {
		overloads: [
			[
				"Number",
				"Number"
			],
			[
				"Number",
				"Number",
				"Number?"
			],
			[
				"Number",
				"Number",
				"Number?",
				"Number?"
			],
			[
				"Number",
				"Number",
				"Number",
				"Number?",
				"Number?"
			]
		]
	},
	splineProperty: {
		overloads: [
			[
				"String",
				null
			],
			[
				"String"
			]
		]
	},
	splineProperties: {
		overloads: [
			[
				"Object"
			]
		]
	},
	vertex: {
		overloads: [
			[
				"Number",
				"Number"
			],
			[
				"Number",
				"Number",
				"Number?",
				"Number?"
			],
			[
				"Number",
				"Number",
				"Number",
				"Number?",
				"Number?"
			]
		]
	},
	beginContour: {
		overloads: [
			[
			]
		]
	},
	endContour: {
		overloads: [
			[
				"OPEN|CLOSE?"
			]
		]
	},
	beginShape: {
		overloads: [
			[
				"POINTS|LINES|TRIANGLES|TRIANGLE_FAN|TRIANGLE_STRIP|QUADS|QUAD_STRIP|PATH?"
			]
		]
	},
	bezierVertex: {
		overloads: [
			[
				"Number",
				"Number",
				"Number?",
				"Number?"
			],
			[
				"Number",
				"Number",
				"Number",
				"Number?",
				"Number?"
			]
		]
	},
	endShape: {
		overloads: [
			[
				"CLOSE?",
				"Integer?"
			]
		]
	},
	normal: {
		overloads: [
			[
				"p5.Vector"
			],
			[
				"Number",
				"Number",
				"Number"
			]
		]
	},
	vertexProperty: {
		overloads: [
			[
				"String",
				"Number|Number[]"
			]
		]
	},
	getWorldInputs: {
		overloads: [
			[
				"Function"
			]
		]
	},
	getPixelInputs: {
		overloads: [
			[
				"Function"
			]
		]
	},
	getFinalColor: {
		overloads: [
			[
				"Function"
			]
		]
	},
	getColor: {
		overloads: [
			[
				"Function"
			]
		]
	},
	getObjectInputs: {
		overloads: [
			[
				"Function"
			]
		]
	},
	getCameraInputs: {
		overloads: [
			[
				"Function"
			]
		]
	},
	loadFont: {
		overloads: [
			[
				"String",
				"String?",
				"Object?",
				"Function?",
				"Function?"
			],
			[
				"String",
				"Function?",
				"Function?"
			]
		]
	},
	text: {
		overloads: [
			[
				"String|Object|Array|Number|Boolean",
				"Number",
				"Number",
				"Number?",
				"Number?"
			]
		]
	},
	textAlign: {
		overloads: [
			[
				"LEFT|CENTER|RIGHT?",
				"TOP|BOTTOM|CENTER|BASELINE?"
			]
		]
	},
	textAscent: {
		overloads: [
			[
				"String?"
			]
		]
	},
	textDescent: {
		overloads: [
			[
				"String?"
			]
		]
	},
	textLeading: {
		overloads: [
			[
				"Number?"
			]
		]
	},
	textFont: {
		overloads: [
			[
				"p5.Font|String|Object?",
				"Number?"
			]
		]
	},
	textSize: {
		overloads: [
			[
				"Number"
			],
			[
			]
		]
	},
	textStyle: {
		overloads: [
			[
				"NORMAL|ITALIC|BOLD|BOLDITALIC"
			],
			[
			]
		]
	},
	textWidth: {
		overloads: [
			[
				"String"
			]
		]
	},
	textWrap: {
		overloads: [
			[
				"WORD|CHAR"
			],
			[
			]
		]
	},
	textBounds: {
		overloads: [
			[
				"String",
				"Number",
				"Number",
				"Number?",
				"Number?"
			]
		]
	},
	textDirection: {
		overloads: [
			[
				"String"
			],
			[
			]
		]
	},
	textProperty: {
		overloads: [
			[
				"String",
				null
			],
			[
				"String"
			]
		]
	},
	textProperties: {
		overloads: [
			[
				"Object"
			],
			[
			]
		]
	},
	fontBounds: {
		overloads: [
			[
				"String",
				"Number",
				"Number",
				"Number?",
				"Number?"
			]
		]
	},
	fontWidth: {
		overloads: [
			[
				"String"
			]
		]
	},
	fontAscent: {
		overloads: [
			[
			]
		]
	},
	fontDescent: {
		overloads: [
			[
			]
		]
	},
	textWeight: {
		overloads: [
			[
				"Number"
			],
			[
			]
		]
	},
	float: {
		overloads: [
			[
				"String"
			],
			[
				"String[]"
			]
		]
	},
	int: {
		overloads: [
			[
				"String|Boolean|Number"
			],
			[
				"Array"
			]
		]
	},
	str: {
		overloads: [
			[
				"String|Boolean|Number"
			]
		]
	},
	boolean: {
		overloads: [
			[
				"String|Boolean|Number"
			],
			[
				"Array"
			]
		]
	},
	byte: {
		overloads: [
			[
				"String|Boolean|Number"
			],
			[
				"Array"
			]
		]
	},
	char: {
		overloads: [
			[
				"String|Number"
			],
			[
				"Array"
			]
		]
	},
	unchar: {
		overloads: [
			[
				"String"
			],
			[
				"String[]"
			]
		]
	},
	hex: {
		overloads: [
			[
				"Number",
				"Number?"
			],
			[
				"Number[]",
				"Number?"
			]
		]
	},
	unhex: {
		overloads: [
			[
				"String"
			],
			[
				"String[]"
			]
		]
	},
	day: {
		overloads: [
			[
			]
		]
	},
	hour: {
		overloads: [
			[
			]
		]
	},
	minute: {
		overloads: [
			[
			]
		]
	},
	millis: {
		overloads: [
			[
			]
		]
	},
	month: {
		overloads: [
			[
			]
		]
	},
	second: {
		overloads: [
			[
			]
		]
	},
	year: {
		overloads: [
			[
			]
		]
	},
	nf: {
		overloads: [
			[
				"Number|String",
				"Integer|String?",
				"Integer|String?"
			],
			[
				"Number[]",
				"Integer|String?",
				"Integer|String?"
			]
		]
	},
	nfc: {
		overloads: [
			[
				"Number|String",
				"Integer|String?"
			],
			[
				"Number[]",
				"Integer|String?"
			]
		]
	},
	nfp: {
		overloads: [
			[
				"Number",
				"Integer?",
				"Integer?"
			],
			[
				"Number[]",
				"Integer?",
				"Integer?"
			]
		]
	},
	nfs: {
		overloads: [
			[
				"Number",
				"Integer?",
				"Integer?"
			],
			[
				"Array",
				"Integer?",
				"Integer?"
			]
		]
	},
	splitTokens: {
		overloads: [
			[
				"String",
				"String?"
			]
		]
	},
	shuffle: {
		overloads: [
			[
				"Array",
				"Boolean?"
			]
		]
	},
	strokeMode: {
		overloads: [
			[
				"String"
			]
		]
	},
	buildGeometry: {
		overloads: [
			[
				"Function"
			]
		]
	},
	freeGeometry: {
		overloads: [
			[
				"p5.Geometry"
			]
		]
	},
	plane: {
		overloads: [
			[
				"Number?",
				"Number?",
				"Integer?",
				"Integer?"
			]
		]
	},
	box: {
		overloads: [
			[
				"Number?",
				"Number?",
				"Number?",
				"Integer?",
				"Integer?"
			]
		]
	},
	sphere: {
		overloads: [
			[
				"Number?",
				"Integer?",
				"Integer?"
			]
		]
	},
	cylinder: {
		overloads: [
			[
				"Number?",
				"Number?",
				"Integer?",
				"Integer?",
				"Boolean?",
				"Boolean?"
			]
		]
	},
	cone: {
		overloads: [
			[
				"Number?",
				"Number?",
				"Integer?",
				"Integer?",
				"Boolean?"
			]
		]
	},
	ellipsoid: {
		overloads: [
			[
				"Number?",
				"Number?",
				"Number?",
				"Integer?",
				"Integer?"
			]
		]
	},
	torus: {
		overloads: [
			[
				"Number?",
				"Number?",
				"Integer?",
				"Integer?"
			]
		]
	},
	curveDetail: {
		overloads: [
			[
				"Number"
			]
		]
	},
	orbitControl: {
		overloads: [
			[
				"Number?",
				"Number?",
				"Number?",
				"Object?"
			]
		]
	},
	debugMode: {
		overloads: [
			[
			],
			[
				"GRID|AXES"
			],
			[
				"GRID|AXES",
				"Number?",
				"Number?",
				"Number?",
				"Number?",
				"Number?"
			],
			[
				"GRID|AXES",
				"Number?",
				"Number?",
				"Number?",
				"Number?"
			],
			[
				"Number?",
				"Number?",
				"Number?",
				"Number?",
				"Number?",
				"Number?",
				"Number?",
				"Number?",
				"Number?"
			]
		]
	},
	noDebugMode: {
		overloads: [
			[
			]
		]
	},
	ambientLight: {
		overloads: [
			[
				"Number",
				"Number",
				"Number",
				"Number?"
			],
			[
				"Number",
				"Number?"
			],
			[
				"String"
			],
			[
				"Number[]"
			],
			[
				"p5.Color"
			]
		]
	},
	specularColor: {
		overloads: [
			[
				"Number",
				"Number",
				"Number"
			],
			[
				"Number"
			],
			[
				"String"
			],
			[
				"Number[]"
			],
			[
				"p5.Color"
			]
		]
	},
	directionalLight: {
		overloads: [
			[
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number"
			],
			[
				"Number",
				"Number",
				"Number",
				"p5.Vector"
			],
			[
				"p5.Color|Number[]|String",
				"Number",
				"Number",
				"Number"
			],
			[
				"p5.Color|Number[]|String",
				"p5.Vector"
			]
		]
	},
	pointLight: {
		overloads: [
			[
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number"
			],
			[
				"Number",
				"Number",
				"Number",
				"p5.Vector"
			],
			[
				"p5.Color|Number[]|String",
				"Number",
				"Number",
				"Number"
			],
			[
				"p5.Color|Number[]|String",
				"p5.Vector"
			]
		]
	},
	imageLight: {
		overloads: [
			[
				"p5.Image"
			]
		]
	},
	panorama: {
		overloads: [
			[
				"p5.Image"
			]
		]
	},
	lights: {
		overloads: [
			[
			]
		]
	},
	lightFalloff: {
		overloads: [
			[
				"Number",
				"Number",
				"Number"
			]
		]
	},
	spotLight: {
		overloads: [
			[
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number?",
				"Number?"
			],
			[
				"p5.Color|Number[]|String",
				"p5.Vector",
				"p5.Vector",
				"Number?",
				"Number?"
			],
			[
				"Number",
				"Number",
				"Number",
				"p5.Vector",
				"p5.Vector",
				"Number?",
				"Number?"
			],
			[
				"p5.Color|Number[]|String",
				"Number",
				"Number",
				"Number",
				"p5.Vector",
				"Number?",
				"Number?"
			],
			[
				"p5.Color|Number[]|String",
				"p5.Vector",
				"Number",
				"Number",
				"Number",
				"Number?",
				"Number?"
			],
			[
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"p5.Vector",
				"Number?",
				"Number?"
			],
			[
				"Number",
				"Number",
				"Number",
				"p5.Vector",
				"Number",
				"Number",
				"Number",
				"Number?",
				"Number?"
			],
			[
				"p5.Color|Number[]|String",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number",
				"Number?",
				"Number?"
			]
		]
	},
	noLights: {
		overloads: [
			[
			]
		]
	},
	loadModel: {
		overloads: [
			[
				"String|Request",
				"String?",
				"Boolean?",
				"function(p5.Geometry)?",
				"function(Event)?"
			],
			[
				"String|Request",
				"String?",
				"function(p5.Geometry)?",
				"function(Event)?"
			],
			[
				"String|Request",
				"Object?"
			]
		]
	},
	model: {
		overloads: [
			[
				"p5.Geometry",
				"Number?"
			]
		]
	},
	createModel: {
		overloads: [
			[
				"String",
				"String?",
				"Boolean?",
				"function(p5.Geometry)?",
				"function(Event)?"
			],
			[
				"String",
				"String?",
				"function(p5.Geometry)?",
				"function(Event)?"
			],
			[
				"String",
				"String?",
				"Object?"
			]
		]
	},
	loadShader: {
		overloads: [
			[
				"String|Request",
				"String|Request",
				"Function?",
				"Function?"
			]
		]
	},
	createShader: {
		overloads: [
			[
				"String",
				"String",
				"Object?"
			]
		]
	},
	loadFilterShader: {
		overloads: [
			[
				"String",
				"Function?",
				"Function?"
			]
		]
	},
	buildFilterShader: {
		overloads: [
			[
				"Function"
			],
			[
				"Object"
			]
		]
	},
	createFilterShader: {
		overloads: [
			[
				"String"
			]
		]
	},
	shader: {
		overloads: [
			[
				"p5.Shader"
			]
		]
	},
	strokeShader: {
		overloads: [
			[
				"p5.Shader"
			]
		]
	},
	imageShader: {
		overloads: [
			[
				"p5.Shader"
			]
		]
	},
	buildMaterialShader: {
		overloads: [
			[
				"Function"
			],
			[
				"Object"
			]
		]
	},
	loadMaterialShader: {
		overloads: [
			[
				"String",
				"Function?",
				"Function?"
			]
		]
	},
	baseMaterialShader: {
		overloads: [
			[
			]
		]
	},
	baseFilterShader: {
		overloads: [
			[
			]
		]
	},
	buildNormalShader: {
		overloads: [
			[
				"Function"
			],
			[
				"Object"
			]
		]
	},
	loadNormalShader: {
		overloads: [
			[
				"String",
				"Function?",
				"Function?"
			]
		]
	},
	baseNormalShader: {
		overloads: [
			[
			]
		]
	},
	buildColorShader: {
		overloads: [
			[
				"Function"
			],
			[
				"Object"
			]
		]
	},
	loadColorShader: {
		overloads: [
			[
				"String",
				"Function?",
				"Function?"
			]
		]
	},
	baseColorShader: {
		overloads: [
			[
			]
		]
	},
	buildStrokeShader: {
		overloads: [
			[
				"Function"
			],
			[
				"Object"
			]
		]
	},
	loadStrokeShader: {
		overloads: [
			[
				"String",
				"Function?",
				"Function?"
			]
		]
	},
	baseStrokeShader: {
		overloads: [
			[
			]
		]
	},
	resetShader: {
		overloads: [
			[
			]
		]
	},
	texture: {
		overloads: [
			[
				"p5.Image|p5.MediaElement|p5.Graphics|p5.Texture|p5.Framebuffer|p5.FramebufferTexture"
			]
		]
	},
	textureMode: {
		overloads: [
			[
				"IMAGE|NORMAL"
			]
		]
	},
	textureWrap: {
		overloads: [
			[
				"CLAMP|REPEAT|MIRROR",
				"CLAMP|REPEAT|MIRROR?"
			]
		]
	},
	normalMaterial: {
		overloads: [
			[
			]
		]
	},
	ambientMaterial: {
		overloads: [
			[
				"Number",
				"Number",
				"Number"
			],
			[
				"Number"
			],
			[
				"p5.Color|Number[]|String"
			]
		]
	},
	emissiveMaterial: {
		overloads: [
			[
				"Number",
				"Number",
				"Number",
				"Number?"
			],
			[
				"Number"
			],
			[
				"p5.Color|Number[]|String"
			]
		]
	},
	specularMaterial: {
		overloads: [
			[
				"Number",
				"Number?"
			],
			[
				"Number",
				"Number",
				"Number",
				"Number?"
			],
			[
				"p5.Color|Number[]|String"
			]
		]
	},
	shininess: {
		overloads: [
			[
				"Number"
			]
		]
	},
	metalness: {
		overloads: [
			[
				"Number"
			]
		]
	},
	roll: {
		overloads: [
			[
				"Number"
			]
		]
	},
	camera: {
		overloads: [
			[
				"Number?",
				"Number?",
				"Number?",
				"Number?",
				"Number?",
				"Number?",
				"Number?",
				"Number?",
				"Number?"
			]
		]
	},
	perspective: {
		overloads: [
			[
				"Number?",
				"Number?",
				"Number?",
				"Number?"
			]
		]
	},
	linePerspective: {
		overloads: [
			[
				"Boolean"
			],
			[
			]
		]
	},
	ortho: {
		overloads: [
			[
				"Number?",
				"Number?",
				"Number?",
				"Number?",
				"Number?",
				"Number?"
			]
		]
	},
	frustum: {
		overloads: [
			[
				"Number?",
				"Number?",
				"Number?",
				"Number?",
				"Number?",
				"Number?"
			]
		]
	},
	createCamera: {
		overloads: [
			[
			]
		]
	},
	setCamera: {
		overloads: [
			[
				"p5.Camera"
			]
		]
	},
	saveObj: {
		overloads: [
			[
				"String?"
			]
		]
	},
	saveStl: {
		overloads: [
			[
				"String?",
				"Object?"
			]
		]
	},
	fromAxisAngle: {
		overloads: [
			[
				"Number?",
				"Number?",
				"Number?",
				"Number?"
			]
		]
	},
	mult: {
		overloads: [
			[
				"p5.Quat?"
			]
		]
	},
	rotateBy: {
		overloads: [
			[
				"p5.Quat?"
			]
		]
	},
	setAttributes: {
		overloads: [
			[
				"String",
				"Boolean"
			],
			[
				"Object"
			]
		]
	}
};
var dataDoc = {
	p5: p5$1,
	"p5.Color": {
	toString: {
		overloads: [
			[
				"String?"
			]
		]
	},
	contrast: {
		overloads: [
			[
				"Color"
			]
		]
	},
	setRed: {
		overloads: [
			[
				"Number"
			]
		]
	},
	setGreen: {
		overloads: [
			[
				"Number"
			]
		]
	},
	setBlue: {
		overloads: [
			[
				"Number"
			]
		]
	},
	setAlpha: {
		overloads: [
			[
				"Number"
			]
		]
	}
},
	"p5.Graphics": {
	reset: {
		overloads: [
			[
			]
		]
	},
	remove: {
		overloads: [
			[
			]
		]
	},
	createFramebuffer: {
		overloads: [
			[
				"Object?"
			]
		]
	}
},
	"p5.Element": {
	remove: {
		overloads: [
			[
			]
		]
	},
	parent: {
		overloads: [
			[
				"String|p5.Element|Object"
			],
			[
			]
		]
	},
	child: {
		overloads: [
			[
			],
			[
				"String|p5.Element?"
			]
		]
	},
	html: {
		overloads: [
			[
			],
			[
				"String?",
				"Boolean?"
			]
		]
	},
	id: {
		overloads: [
			[
				"String"
			],
			[
			]
		]
	},
	"class": {
		overloads: [
			[
				"String"
			],
			[
			]
		]
	},
	addClass: {
		overloads: [
			[
				"String"
			]
		]
	},
	removeClass: {
		overloads: [
			[
				"String"
			]
		]
	},
	hasClass: {
		overloads: [
			[
				null
			]
		]
	},
	toggleClass: {
		overloads: [
			[
				null
			]
		]
	},
	center: {
		overloads: [
			[
				"String?"
			]
		]
	},
	position: {
		overloads: [
			[
			],
			[
				"Number?",
				"Number?",
				"String?"
			]
		]
	},
	show: {
		overloads: [
			[
			]
		]
	},
	hide: {
		overloads: [
			[
			]
		]
	},
	size: {
		overloads: [
			[
			],
			[
				"Number|AUTO?",
				"Number|AUTO?"
			]
		]
	},
	style: {
		overloads: [
			[
				"String"
			],
			[
				"String",
				"String|p5.Color"
			]
		]
	},
	attribute: {
		overloads: [
			[
			],
			[
				"String",
				"String"
			]
		]
	},
	removeAttribute: {
		overloads: [
			[
				"String"
			]
		]
	},
	value: {
		overloads: [
			[
			],
			[
				"String|Number"
			]
		]
	},
	mousePressed: {
		overloads: [
			[
				"Function|Boolean"
			]
		]
	},
	doubleClicked: {
		overloads: [
			[
				"Function|Boolean"
			]
		]
	},
	mouseWheel: {
		overloads: [
			[
				"Function|Boolean"
			]
		]
	},
	mouseReleased: {
		overloads: [
			[
				"Function|Boolean"
			]
		]
	},
	mouseClicked: {
		overloads: [
			[
				"Function|Boolean"
			]
		]
	},
	mouseMoved: {
		overloads: [
			[
				"Function|Boolean"
			]
		]
	},
	mouseOver: {
		overloads: [
			[
				"Function|Boolean"
			]
		]
	},
	mouseOut: {
		overloads: [
			[
				"Function|Boolean"
			]
		]
	},
	dragOver: {
		overloads: [
			[
				"Function|Boolean"
			]
		]
	},
	dragLeave: {
		overloads: [
			[
				"Function|Boolean"
			]
		]
	},
	changed: {
		overloads: [
			[
				"Function|Boolean"
			]
		]
	},
	input: {
		overloads: [
			[
				"Function|Boolean"
			]
		]
	},
	drop: {
		overloads: [
			[
				"Function",
				"Function?"
			]
		]
	},
	draggable: {
		overloads: [
			[
				"p5.Element?"
			]
		]
	}
},
	"p5.MediaElement": {
	play: {
		overloads: [
			[
			]
		]
	},
	stop: {
		overloads: [
			[
			]
		]
	},
	pause: {
		overloads: [
			[
			]
		]
	},
	loop: {
		overloads: [
			[
			]
		]
	},
	noLoop: {
		overloads: [
			[
			]
		]
	},
	autoplay: {
		overloads: [
			[
				"Boolean?"
			]
		]
	},
	volume: {
		overloads: [
			[
			],
			[
				"Number"
			]
		]
	},
	speed: {
		overloads: [
			[
			],
			[
				"Number"
			]
		]
	},
	time: {
		overloads: [
			[
				"Number?"
			]
		]
	},
	duration: {
		overloads: [
			[
			]
		]
	},
	onended: {
		overloads: [
			[
				"Function"
			]
		]
	},
	connect: {
		overloads: [
			[
				"AudioNode|Object"
			]
		]
	},
	disconnect: {
		overloads: [
			[
			]
		]
	},
	showControls: {
		overloads: [
			[
			]
		]
	},
	hideControls: {
		overloads: [
			[
			]
		]
	},
	addCue: {
		overloads: [
			[
				"Number",
				"Function",
				"Object?"
			]
		]
	},
	removeCue: {
		overloads: [
			[
				"Number"
			]
		]
	},
	clearCues: {
		overloads: [
			[
			]
		]
	}
},
	"p5.Image": {
	pixelDensity: {
		overloads: [
			[
				"Number?"
			]
		]
	},
	loadPixels: {
		overloads: [
			[
			]
		]
	},
	updatePixels: {
		overloads: [
			[
				"Integer?",
				"Integer?",
				"Integer?",
				"Integer?"
			]
		]
	},
	get: {
		overloads: [
			[
				"Number",
				"Number",
				"Number",
				"Number"
			],
			[
			],
			[
				"Number",
				"Number"
			]
		]
	},
	set: {
		overloads: [
			[
				"Number",
				"Number",
				"Number|Number[]|Object"
			]
		]
	},
	resize: {
		overloads: [
			[
				"Number",
				"Number"
			]
		]
	},
	copy: {
		overloads: [
			[
				"p5.Image|p5.Element",
				"Integer",
				"Integer",
				"Integer",
				"Integer",
				"Integer",
				"Integer",
				"Integer",
				"Integer"
			],
			[
				"Integer",
				"Integer",
				"Integer",
				"Integer",
				"Integer",
				"Integer",
				"Integer",
				"Integer"
			]
		]
	},
	mask: {
		overloads: [
			[
				"p5.Image"
			]
		]
	},
	filter: {
		overloads: [
			[
				"THRESHOLD|GRAY|OPAQUE|INVERT|POSTERIZE|ERODE|DILATE|BLUR",
				"Number?"
			]
		]
	},
	blend: {
		overloads: [
			[
				"p5.Image",
				"Integer",
				"Integer",
				"Integer",
				"Integer",
				"Integer",
				"Integer",
				"Integer",
				"Integer",
				"BLEND|DARKEST|LIGHTEST|DIFFERENCE|MULTIPLY|EXCLUSION|SCREEN|REPLACE|OVERLAY|HARD_LIGHT|SOFT_LIGHT|DODGE|BURN|ADD|NORMAL"
			],
			[
				"Integer",
				"Integer",
				"Integer",
				"Integer",
				"Integer",
				"Integer",
				"Integer",
				"Integer",
				"BLEND|DARKEST|LIGHTEST|DIFFERENCE|MULTIPLY|EXCLUSION|SCREEN|REPLACE|OVERLAY|HARD_LIGHT|SOFT_LIGHT|DODGE|BURN|ADD|NORMAL"
			]
		]
	},
	save: {
		overloads: [
			[
				"String",
				"String?"
			]
		]
	},
	reset: {
		overloads: [
			[
			]
		]
	},
	getCurrentFrame: {
		overloads: [
			[
			]
		]
	},
	setFrame: {
		overloads: [
			[
				"Number"
			]
		]
	},
	numFrames: {
		overloads: [
			[
			]
		]
	},
	play: {
		overloads: [
			[
			]
		]
	},
	pause: {
		overloads: [
			[
			]
		]
	},
	delay: {
		overloads: [
			[
				"Number",
				"Number?"
			]
		]
	}
},
	"p5.Table": {
	addRow: {
		overloads: [
			[
				"p5.TableRow?"
			]
		]
	},
	removeRow: {
		overloads: [
			[
				"Integer"
			]
		]
	},
	getRow: {
		overloads: [
			[
				"Integer"
			]
		]
	},
	getRows: {
		overloads: [
			[
			]
		]
	},
	findRow: {
		overloads: [
			[
				"String",
				"Integer|String"
			]
		]
	},
	findRows: {
		overloads: [
			[
				"String",
				"Integer|String"
			]
		]
	},
	matchRow: {
		overloads: [
			[
				"String|RegExp",
				"String|Integer"
			]
		]
	},
	matchRows: {
		overloads: [
			[
				"String",
				"String|Integer?"
			]
		]
	},
	getColumn: {
		overloads: [
			[
				"String|Number"
			]
		]
	},
	clearRows: {
		overloads: [
			[
			]
		]
	},
	addColumn: {
		overloads: [
			[
				"String?"
			]
		]
	},
	getColumnCount: {
		overloads: [
			[
			]
		]
	},
	getRowCount: {
		overloads: [
			[
			]
		]
	},
	removeTokens: {
		overloads: [
			[
				"String",
				"String|Integer?"
			]
		]
	},
	trim: {
		overloads: [
			[
				"String|Integer?"
			]
		]
	},
	removeColumn: {
		overloads: [
			[
				"String|Integer"
			]
		]
	},
	set: {
		overloads: [
			[
				"Integer",
				"String|Integer",
				"String|Number"
			]
		]
	},
	setNum: {
		overloads: [
			[
				"Integer",
				"String|Integer",
				"Number"
			]
		]
	},
	setString: {
		overloads: [
			[
				"Integer",
				"String|Integer",
				"String"
			]
		]
	},
	get: {
		overloads: [
			[
				"Integer",
				"String|Integer"
			]
		]
	},
	getNum: {
		overloads: [
			[
				"Integer",
				"String|Integer"
			]
		]
	},
	getString: {
		overloads: [
			[
				"Integer",
				"String|Integer"
			]
		]
	},
	getObject: {
		overloads: [
			[
				"String?"
			]
		]
	},
	getArray: {
		overloads: [
			[
			]
		]
	}
},
	"p5.TableRow": {
	set: {
		overloads: [
			[
				"String|Integer",
				"String|Number"
			]
		]
	},
	setNum: {
		overloads: [
			[
				"String|Integer",
				"Number|String"
			]
		]
	},
	setString: {
		overloads: [
			[
				"String|Integer",
				"String|Number|Boolean|Object"
			]
		]
	},
	get: {
		overloads: [
			[
				"String|Integer"
			]
		]
	},
	getNum: {
		overloads: [
			[
				"String|Integer"
			]
		]
	},
	getString: {
		overloads: [
			[
				"String|Integer"
			]
		]
	}
},
	"p5.XML": {
	getParent: {
		overloads: [
			[
			]
		]
	},
	getName: {
		overloads: [
			[
			]
		]
	},
	setName: {
		overloads: [
			[
				"String"
			]
		]
	},
	hasChildren: {
		overloads: [
			[
			]
		]
	},
	listChildren: {
		overloads: [
			[
			]
		]
	},
	getChildren: {
		overloads: [
			[
				"String?"
			]
		]
	},
	getChild: {
		overloads: [
			[
				"String|Integer"
			]
		]
	},
	addChild: {
		overloads: [
			[
				"p5.XML"
			]
		]
	},
	removeChild: {
		overloads: [
			[
				"String|Integer"
			]
		]
	},
	getAttributeCount: {
		overloads: [
			[
			]
		]
	},
	listAttributes: {
		overloads: [
			[
			]
		]
	},
	hasAttribute: {
		overloads: [
			[
				"String"
			]
		]
	},
	getNum: {
		overloads: [
			[
				"String",
				"Number?"
			]
		]
	},
	getString: {
		overloads: [
			[
				"String",
				"Number?"
			]
		]
	},
	setAttribute: {
		overloads: [
			[
				"String",
				"Number|String|Boolean"
			]
		]
	},
	getContent: {
		overloads: [
			[
				"String?"
			]
		]
	},
	serialize: {
		overloads: [
			[
			]
		]
	}
},
	"p5.Vector": {
	getValue: {
		overloads: [
			[
				"Number"
			]
		]
	},
	setValue: {
		overloads: [
			[
				"Number",
				"Number"
			]
		]
	},
	set: {
		overloads: [
			[
				"Number?",
				"Number?",
				"Number?"
			],
			[
				"p5.Vector|Number[]"
			]
		]
	},
	copy: {
		overloads: [
			[
			]
		]
	},
	add: {
		overloads: [
			[
				"Number|Array",
				"Number?",
				"Number?"
			],
			[
				"p5.Vector|Number[]"
			]
		]
	},
	rem: {
		overloads: [
			[
				"Number",
				"Number",
				"Number"
			],
			[
				"p5.Vector|Number[]"
			]
		]
	},
	sub: {
		overloads: [
			[
				"Number",
				"Number?",
				"Number?"
			],
			[
				"p5.Vector|Number[]"
			]
		]
	},
	mult: {
		overloads: [
			[
				"Number"
			],
			[
				"Number",
				"Number",
				"Number?"
			],
			[
				"Number[]"
			],
			[
				"p5.Vector"
			]
		]
	},
	div: {
		overloads: [
			[
				"Number"
			],
			[
				"Number",
				"Number",
				"Number?"
			],
			[
				"Number[]"
			],
			[
				"p5.Vector"
			]
		]
	},
	mag: {
		overloads: [
			[
			]
		]
	},
	magSq: {
		overloads: [
			[
			]
		]
	},
	dot: {
		overloads: [
			[
				"Number",
				"Number?",
				"Number?"
			],
			[
				"p5.Vector"
			]
		]
	},
	cross: {
		overloads: [
			[
				"p5.Vector"
			]
		]
	},
	dist: {
		overloads: [
			[
				"p5.Vector"
			]
		]
	},
	normalize: {
		overloads: [
			[
			]
		]
	},
	limit: {
		overloads: [
			[
				"Number"
			]
		]
	},
	setMag: {
		overloads: [
			[
				"Number"
			]
		]
	},
	heading: {
		overloads: [
			[
			]
		]
	},
	setHeading: {
		overloads: [
			[
				"Number"
			]
		]
	},
	rotate: {
		overloads: [
			[
				"Number"
			]
		]
	},
	angleBetween: {
		overloads: [
			[
				"p5.Vector"
			]
		]
	},
	lerp: {
		overloads: [
			[
				"Number",
				"Number",
				"Number",
				"Number"
			],
			[
				"p5.Vector",
				"Number"
			]
		]
	},
	slerp: {
		overloads: [
			[
				"p5.Vector",
				"Number"
			]
		]
	},
	reflect: {
		overloads: [
			[
				"p5.Vector"
			]
		]
	},
	array: {
		overloads: [
			[
			]
		]
	},
	equals: {
		overloads: [
			[
				"Number?",
				"Number?",
				"Number?"
			],
			[
				"p5.Vector|Array"
			]
		]
	},
	clampToZero: {
		overloads: [
			[
			]
		]
	},
	fromAngle: {
		overloads: [
			[
				"Number",
				"Number?"
			]
		]
	},
	fromAngles: {
		overloads: [
			[
				"Number",
				"Number",
				"Number?"
			]
		]
	},
	random2D: {
		overloads: [
			[
			]
		]
	},
	random3D: {
		overloads: [
			[
			]
		]
	}
},
	"p5.Font": {
	textToPaths: {
		overloads: [
			[
				"String",
				"Number",
				"Number",
				"Number?",
				"Number?"
			]
		]
	},
	textToPoints: {
		overloads: [
			[
				"String",
				"Number",
				"Number",
				"Object?"
			]
		]
	},
	textToContours: {
		overloads: [
			[
				"String",
				"Number",
				"Number",
				"Object?"
			]
		]
	},
	textToModel: {
		overloads: [
			[
				"String",
				"Number",
				"Number",
				"Number",
				"Number",
				"Object?"
			]
		]
	}
},
	"p5.Camera": {
	perspective: {
		overloads: [
			[
				"Number?",
				"Number?",
				"Number?",
				"Number?"
			]
		]
	},
	ortho: {
		overloads: [
			[
				"Number?",
				"Number?",
				"Number?",
				"Number?",
				"Number?",
				"Number?"
			]
		]
	},
	frustum: {
		overloads: [
			[
				"Number?",
				"Number?",
				"Number?",
				"Number?",
				"Number?",
				"Number?"
			]
		]
	},
	pan: {
		overloads: [
			[
				"Number"
			]
		]
	},
	tilt: {
		overloads: [
			[
				"Number"
			]
		]
	},
	lookAt: {
		overloads: [
			[
				"Number",
				"Number",
				"Number"
			]
		]
	},
	camera: {
		overloads: [
			[
				"Number?",
				"Number?",
				"Number?",
				"Number?",
				"Number?",
				"Number?",
				"Number?",
				"Number?",
				"Number?"
			]
		]
	},
	move: {
		overloads: [
			[
				"Number",
				"Number",
				"Number"
			]
		]
	},
	setPosition: {
		overloads: [
			[
				"Number",
				"Number",
				"Number"
			]
		]
	},
	set: {
		overloads: [
			[
				"p5.Camera"
			]
		]
	},
	slerp: {
		overloads: [
			[
				"p5.Camera",
				"p5.Camera",
				"Number"
			]
		]
	}
},
	"p5.Framebuffer": {
	resize: {
		overloads: [
			[
				"Number",
				"Number"
			]
		]
	},
	pixelDensity: {
		overloads: [
			[
				"Number?"
			]
		]
	},
	autoSized: {
		overloads: [
			[
				"Boolean?"
			]
		]
	},
	createCamera: {
		overloads: [
			[
			]
		]
	},
	remove: {
		overloads: [
			[
			]
		]
	},
	begin: {
		overloads: [
			[
			]
		]
	},
	end: {
		overloads: [
			[
			]
		]
	},
	draw: {
		overloads: [
			[
				"Function"
			]
		]
	},
	loadPixels: {
		overloads: [
			[
			]
		]
	},
	get: {
		overloads: [
			[
				"Number",
				"Number",
				"Number",
				"Number"
			],
			[
			],
			[
				"Number",
				"Number"
			]
		]
	}
},
	"p5.Geometry": {
	calculateBoundingBox: {
		overloads: [
			[
			]
		]
	},
	clearColors: {
		overloads: [
			[
			]
		]
	},
	flipU: {
		overloads: [
			[
			]
		]
	},
	computeFaces: {
		overloads: [
			[
			]
		]
	},
	computeNormals: {
		overloads: [
			[
				"FLAT|SMOOTH?",
				"Object?"
			]
		]
	},
	makeEdgesFromFaces: {
		overloads: [
			[
			]
		]
	},
	normalize: {
		overloads: [
			[
			]
		]
	},
	vertexProperty: {
		overloads: [
			[
				"String",
				"Number|Number[]",
				"Number?"
			]
		]
	},
	flipV: {
		overloads: [
			[
			]
		]
	}
},
	"p5.Shader": {
	version: {
		overloads: [
			[
			]
		]
	},
	inspectHooks: {
		overloads: [
			[
			]
		]
	},
	modify: {
		overloads: [
			[
				"Function",
				"Object?"
			],
			[
				"Object?"
			]
		]
	},
	copyToContext: {
		overloads: [
			[
				"p5|p5.Graphics"
			]
		]
	},
	setUniform: {
		overloads: [
			[
				"String",
				"Boolean|Number|Number[]|p5.Image|p5.Graphics|p5.MediaElement|p5.Texture"
			]
		]
	}
}
};

/**
 * @for p5
 * @requires core
 */

function validateParams(p5, fn, lifecycles) {
  // Cache for Zod schemas
  let schemaRegistry = new Map();

  // Mapping names of p5 types to their constructor functions.
  // p5Constructors:
  //   - Color: f()
  //   - Graphics: f()
  //   - Vector: f()
  // and so on.
  // const p5Constructors = {};
  // NOTE: This is a tempt fix for unit test but is not correct
  // Attaced constructors are `undefined`
  const p5Constructors = Object.keys(p5).reduce((acc, val) => {
    if (
      val.match(/^[A-Z]/) && // Starts with a capital
      !val.match(/^[A-Z][A-Z0-9]*$/) && // Is not an all caps constant
      p5[val] instanceof Function // Is a function
    ) {
      acc[val] = p5[val];
    }
    return acc;
  }, {});

  function loadP5Constructors() {
    // Make a list of all p5 classes to be used for argument validation
    // This must be done only when everything has loaded otherwise we get
    // an empty array
    for (let key of Object.keys(p5)) {
      // Get a list of all constructors in p5. They are functions whose names
      // start with a capital letter
      if (typeof p5[key] === 'function' && key[0] !== key[0].toLowerCase()) {
        p5Constructors[key] = p5[key];
      }
    }
  }

  // `constantsMap` maps constants to their values, e.g.
  // {
  //   ADD: 'lighter',
  //   ALT: 18,
  //   ARROW: 'default',
  //   AUTO: 'auto',
  //   ...
  // }
  const constantsMap = {};
  for (const [key, value] of Object.entries(constants)) {
    constantsMap[key] = value;
  }

  // Start initializing `schemaMap` with primitive types. `schemaMap` will
  // eventually contain both primitive types and web API objects.
  const schemaMap = {
    'Any': z.any(),
    'Array': z.array(z.any()),
    'Boolean': z.boolean(),
    'Function': z.function(),
    'Integer': z.number().int(),
    'Number': z.number(),
    'Object': z.object({}),
    'String': z.string()
  };

  const webAPIObjects = [
    'AudioNode',
    'HTMLCanvasElement',
    'HTMLElement',
    'KeyboardEvent',
    'MouseEvent',
    'RegExp',
    'TouchEvent',
    'UIEvent',
    'WheelEvent'
  ];

  function generateWebAPISchemas(apiObjects) {
    return apiObjects.reduce((acc, obj) => {
      acc[obj] = z.custom(data => data instanceof globalThis[obj], {
        message: `Expected a ${obj}`
      });
      return acc;
    }, {});
  }

  const webAPISchemas = generateWebAPISchemas(webAPIObjects);
  // Add web API schemas to the schema map.
  Object.assign(schemaMap, webAPISchemas);

  // For mapping 0-indexed parameters to their ordinal representation, e.g.
  // "first" for 0, "second" for 1, "third" for 2, etc.
  const ordinals = ['first', 'second', 'third', 'fourth', 'fifth', 'sixth', 'seventh', 'eighth', 'ninth', 'tenth'];

  function extractFuncNameAndClass(func) {
    const ichDot = func.lastIndexOf('.');
    const funcName = func.slice(ichDot + 1);
    const funcClass = func.slice(0, ichDot !== -1 ? ichDot : 0) || 'p5';
    return { funcName, funcClass };
  }

  function validBracketNesting(type) {
    let level = 0;
    for (let i = 0; i < type.length; i++) {
      if (type[i] === '[') {
        level++;
      } else if (type[i] === ']') {
        level--;
        if (level < 0) return false;
      }
    }
    return level === 0;
  }

  /**
   * This is a helper function that generates Zod schemas for a function based on
   * the parameter data from `docs/parameterData.json`.
   *
   * Example parameter data for function `background`:
   * "background": {
   *    "overloads": [
   *      ["p5.Color"],
   *      ["String", "Number?"],
   *      ["Number", "Number?"],
   *      ["Number", "Number", "Number", "Number?"],
   *      ["Number[]"],
   *      ["p5.Image", "Number?"]
   *    ]
   *  }
   * Where each array in `overloads` represents a set of valid overloaded
   * parameters, and `?` is a shorthand for `Optional`.
   *
   * @method generateZodSchemasForFunc
   * @private
   * @param {String} func - Name of the function. Expect global functions like `sin` and class methods like `p5.Vector.add`
   * @returns {z.ZodSchema} Zod schema
   */
  const generateZodSchemasForFunc = function (func) {
    const { funcName, funcClass } = extractFuncNameAndClass(func);
    let funcInfo = dataDoc[funcClass][funcName];

    if(!funcInfo) return;

    let overloads = [];
    if (funcInfo.hasOwnProperty('overloads')) {
      overloads = funcInfo.overloads;
    }

    // Returns a schema for a single type, i.e. z.boolean() for `boolean`.
    const generateTypeSchema = baseType => {
      if (!baseType) return z.any();

      let typeSchema;

      // Check for constants. Note that because we're ultimately interested in the value of
      // the constant, mapping constants to their values via `constantsMap` is
      // necessary.
      if (baseType in constantsMap) {
        typeSchema = z.literal(constantsMap[baseType]);
      }
      // Some more constants are attached directly to p5.prototype, e.g. by addons:
      else if (baseType.match(/^[A-Z][A-Z0-9]*$/) && baseType in fn) {
        typeSchema = z.literal(fn[baseType]);
      }
      // Function types
      else if (baseType.startsWith('function')) {
        typeSchema = z.function();
      }
      // All p5 objects start with `p5` in the documentation, i.e. `p5.Camera`.
      else if (/^p5\.[a-zA-Z0-9]+$/.exec(baseType) || baseType === 'p5') {
        const className = baseType.substring(baseType.indexOf('.') + 1);
        typeSchema = z.instanceof(p5Constructors[className]);
      }
      // For primitive types and web API objects.
      else if (schemaMap[baseType]) {
        typeSchema = schemaMap[baseType];
      }
      // Tuple types
      else if (
        baseType.startsWith('[') &&
        baseType.endsWith(']') &&
        validBracketNesting(baseType.slice(1, -1))
      ) {
        typeSchema = z.tuple(
          baseType
            .slice(1, -1)
            .split(/, */g)
            .map(entry => generateTypeSchema(entry))
        );
      }
      // JavaScript classes, e.g. Request
      else if (baseType.match(/^[A-Z]/) && baseType in window) {
        typeSchema = z.instanceof(window[baseType]);
      }
      // Generate a schema for a single parameter that can be of multiple
      // types / constants, i.e. `String|Number|Array`.
      //
      // Here, z.union() is used over z.enum() (which seems more intuitive) for
      // constants for the following reasons:
      // 1) z.enum() only allows a fixed set of allowable string values. However,
      // our constants sometimes have numeric or non-primitive values.
      // 2) In some cases, the type can be constants or strings, making z.enum()
      // insufficient for the use case.
      else if (baseType.includes('|') && baseType.split('|').every(t => validBracketNesting(t))) {
        const types = baseType.split('|');
        typeSchema = z.union(types
          .map(t => generateTypeSchema(t))
          .filter(s => s !== undefined));
      } else if (baseType.endsWith('[]')) {
        typeSchema = z.array(generateTypeSchema(baseType.slice(0, -2)));
      } else {
        throw new Error(`Unsupported type '${baseType}' in parameter validation. Please report this issue.`);
      }

      return typeSchema;
    };

    // Generate a schema for a single parameter. In the case where a parameter can
    // be of multiple types, `generateTypeSchema` is called for each type.
    const generateParamSchema = param => {
      const isOptional = param?.endsWith('?');
      param = param?.replace(/\?$/, '');

      const isRest = param?.startsWith('...') && param?.endsWith('[]');
      param = param?.replace(/^\.\.\.(.+)\[\]$/, '$1');

      let schema = generateTypeSchema(param);
      // Fallback to z.custom() because function types are no longer
      // returns a Zod schema.
      if (schema.def.type === 'function') {
        schema = z.custom(val => val instanceof Function);
      }

      if (isOptional) {
        schema = schema.optional();
      }
      return { schema, rest: isRest };
    };

    // Note that in Zod, `optional()` only checks for undefined, not the absence
    // of value.
    //
    // Let's say we have a function with 3 parameters, and the last one is
    // optional, i.e. func(a, b, c?). If we only have a z.tuple() for the
    // parameters, where the third schema is optional, then we will only be able
    // to validate func(10, 10, undefined), but not func(10, 10), which is
    // a completely valid call.
    //
    // Therefore, on top of using `optional()`, we also have to generate parameter
    // combinations that are valid for all numbers of parameters.
    const generateOverloadCombinations = params => {
      // No optional parameters, return the original parameter list right away.
      if (!params.some(p => p?.endsWith('?'))) {
        return [params];
      }

      const requiredParamsCount = params.filter(p => p === null || !p.endsWith('?')).length;
      const result = [];

      for (let i = requiredParamsCount; i <= params.length; i++) {
        result.push(params.slice(0, i));
      }

      return result;
    };

    // Generate schemas for each function overload and merge them
    const overloadSchemas = overloads.flatMap(overload => {
      const combinations = generateOverloadCombinations(overload);

      return combinations.map(combo => {
        const params = combo
          .map(p => generateParamSchema(p))
          .filter(s => s.schema !== undefined);

        let rest;
        if (params.at(-1)?.rest) {
          rest = params.pop();
        }

        let combined = z.tuple(params.map(s => s.schema));
        if (rest) {
          combined = combined.rest(rest.schema);
        }
        return combined;
      });
    });

    return overloadSchemas.length === 1
      ? overloadSchemas[0]
      : z.union(overloadSchemas);
  };

  /**
   * Finds the closest schema to the input arguments.
   *
   * This is a helper function that identifies the closest schema to the input
   * arguments, in the case of an initial validation error. We will then use the
   * closest schema to generate a friendly error message.
   *
   * @private
   * @param {z.ZodSchema} schema - Zod schema.
   * @param {Array} args - User input arguments.
   * @returns {z.ZodSchema} Closest schema matching the input arguments.
   */
  const findClosestSchema = function (schema, args) {
    if (!(schema instanceof z.ZodUnion)) {
      return schema;
    }

    // Helper function that scores how close the input arguments are to a schema.
    // Lower score means closer match.
    const scoreSchema = schema => {
      let score = Infinity;
      if (!(schema instanceof z.ZodTuple)) {
        console.warn('Schema below is not a tuple: ');
        printZodSchema(schema);
        return score;
      }

      const numArgs = args.length;
      const schemaItems = schema.def.items;
      const numSchemaItems = schemaItems.length;
      const numRequiredSchemaItems = schemaItems
        .filter(item => !item.isOptional())
        .length;

      if (numArgs >= numRequiredSchemaItems && numArgs <= numSchemaItems) {
        score = 0;
      }
      // Here, give more weight to mismatch in number of arguments.
      //
      // For example, color() can either take [Number, Number?] or
      // [Number, Number, Number, Number?] as list of parameters.
      // If the user passed in 3 arguments, [10, undefined, undefined], it's
      // more than likely that they intended to pass in 3 arguments, but the
      // last two arguments are invalid.
      //
      // If there's no bias towards matching the number of arguments, the error
      // message will show that we're expecting at most 2 arguments, but more
      // are received.
      else {
        score = Math.abs(
          numArgs < numRequiredSchemaItems ?
            numRequiredSchemaItems - numArgs :
            numArgs - numSchemaItems
        ) * 4;
      }

      for (let i = 0; i < Math.min(schemaItems.length, args.length); i++) {
        const paramSchema = schemaItems[i];
        const arg = args[i];

        if (!paramSchema.safeParse(arg).success) score++;
      }

      return score;
    };

    // Default to the first schema, so that we are guaranteed to return a result.
    let closestSchema = schema.def.options[0];
    // We want to return the schema with the lowest score.
    let bestScore = Infinity;

    const schemaUnion = schema.def.options;
    schemaUnion.forEach(schema => {
      const score = scoreSchema(schema);
      if (score < bestScore) {
        closestSchema = schema;
        bestScore = score;
      }
    });

    return closestSchema;
  };

  /**
   * Prints a friendly error message after parameter validation, if validation
   * has failed.
   *
   * @method _friendlyParamError
   * @private
   * @param {z.ZodError} zodErrorObj - The Zod error object containing validation errors.
   * @param {String} func - Name of the function. Expect global functions like `sin` and class methods like `p5.Vector.add`
   * @returns {String} The friendly error message.
   */
  const friendlyParamError = function (zodErrorObj, func, args) {
    let message = '🌸 p5.js says: ';
    let isVersionError = false;
    // The `zodErrorObj` might contain multiple errors of equal importance
    // (after scoring the schema closeness in `findClosestSchema`). Here, we
    // always print the first error so that user can work through the errors
    // one by one.
    let currentError = zodErrorObj.issues[0];

    // Helper function to build a type mismatch message.
    const buildTypeMismatchMessage =
      (actualType, expectedTypeStr, position) => {
        const positionStr = position ? `at the ${ordinals[position]} parameter` : '';
        const actualTypeStr = actualType ? `, but received ${actualType}` : '';
        return `Expected ${expectedTypeStr} ${positionStr}${actualTypeStr}`;
      };

    // Union errors occur when a parameter can be of multiple types but is not
    // of any of them. In this case, aggregate all possible types and print
    // a friendly error message that indicates what the expected types are at
    // which position (position is not 0-indexed, for accessibility reasons).
    const processUnionError = error => {
      const expectedTypes = new Set();
      let actualType;

      error.errors.forEach(err => {
        const issue = err[0];
        if (issue) {
          if (!actualType) {
            actualType = issue.message;
          }

          if (issue.code === 'invalid_type') {
            actualType = issue.message.split(', received ')[1];
            expectedTypes.add(issue.expected);
          }
          // The case for constants. Since we don't want to print out the actual
          // constant values in the error message, the error message will
          // direct users to the documentation.
          else if (issue.code === 'invalid_value') {
            expectedTypes.add('constant (please refer to documentation for allowed values)');
            actualType = args[error.path[0]];
          } else if (issue.code === 'custom') {
            const match = issue.message.match(/Input not instance of (\w+)/);
            if (match) expectedTypes.add(match[1]);
            actualType = undefined;
          }
        }
      });

      if (expectedTypes.size > 0) {
        if (error.path?.length > 0 && args[error.path[0]] instanceof Promise)  {
          message += 'Did you mean to put `await` before a loading function? ' +
            'An unexpected Promise was found. ';
          isVersionError = true;
        }

        const expectedTypesStr = Array.from(expectedTypes).join(' or ');
        const position = error.path.join('.');

        message += buildTypeMismatchMessage(
          actualType, expectedTypesStr, position
        );
      }

      return message;
    };

    switch (currentError.code) {
      case 'invalid_union': {
        processUnionError(currentError);
        break;
      }
      case 'too_small': {
        const minArgs = currentError.minimum;
        message += `Expected at least ${minArgs} argument${minArgs > 1 ? 's' : ''}, but received fewer`;
        break;
      }
      case 'invalid_type': {
        message += buildTypeMismatchMessage(currentError.message.split(', received ')[1], currentError.expected, currentError.path.join('.'));
        break;
      }
      case 'too_big': {
        const maxArgs = currentError.maximum;
        message += `Expected at most ${maxArgs} argument${maxArgs > 1 ? 's' : ''}, but received more`;
        break;
      }
      default: {
        console.log('Zod error object', currentError);
      }
    }

    // Let the user know which function is generating the error.
    message += ` in ${func}().`;

    // Generates a link to the documentation based on the given function name.
    // TODO: Check if the link is reachable before appending it to the error
    // message.
    const generateDocumentationLink = func => {
      const { funcName, funcClass } = extractFuncNameAndClass(func);
      const p5BaseUrl = 'https://p5js.org/reference';
      const url = `${p5BaseUrl}/${funcClass}/${funcName}`;

      return url;
    };

    if (currentError.code === 'too_big' || currentError.code === 'too_small') {
      const documentationLink = generateDocumentationLink(func);
      message += ` For more information, see ${documentationLink}.`;
    }

    if (isVersionError) {
      p5._error(this, message);
    } else {
      console.log(message);
    }
    return message;
  };

  /**
   * Runs parameter validation by matching the input parameters to Zod schemas
   * generated from the parameter data from `docs/parameterData.json`.
   *
   * @private
   * @param {String} func - Name of the function.
   * @param {Array} args - User input arguments.
   * @returns {Object} The validation result.
   * @returns {Boolean} result.success - Whether the validation was successful.
   * @returns {any} [result.data] - The parsed data if validation was successful.
   * @returns {String} [result.error] - The validation error message if validation has failed.
   */
  const validate = function (func, args) {
    if (p5.disableFriendlyErrors) {
      return; // skip FES
    }

    if (!Array.isArray(args)) {
      args = Array.from(args);
    }

    // An edge case: even when all arguments are optional and therefore,
    // theoretically allowed to stay undefined and valid, it is likely that the
    // user intended to call the function with non-undefined arguments. Skip
    // regular workflow and return a friendly error message right away.
    if (
      Array.isArray(args) &&
      args.length > 0 &&
      args.every(arg => arg === undefined)
    ) {
      const undefinedErrorMessage = `🌸 p5.js says: All arguments for ${func}() are undefined. There is likely an error in the code.`;

      return {
        success: false,
        error: undefinedErrorMessage
      };
    }

    let funcSchemas = schemaRegistry.get(func);
    if (!funcSchemas) {
      funcSchemas = generateZodSchemasForFunc(func);
      if (!funcSchemas) return;
      schemaRegistry.set(func, funcSchemas);
    }

    try {
      return {
        success: true,
        data: funcSchemas.parse(args)
      };
    } catch (error) {
      const closestSchema = findClosestSchema(funcSchemas, args);
      const zodError = closestSchema.safeParse(args).error;
      const errorMessage = friendlyParamError(zodError, func, args);

      return {
        success: false,
        error: errorMessage
      };
    }
  };

  fn._validate = validate; // TEMP: For unit tests

  p5.decorateHelper(
    /^(?!_).+$/,
    function(target, { name }){
      return function(...args){
        if (!p5.disableFriendlyErrors && !p5.disableParameterValidator) {
          validate(name, args);
        }
        return target.apply(this, args);
      };
    }
  );

  lifecycles.presetup = function(){
    loadP5Constructors();
  };
}

if (typeof p5 !== 'undefined') {
  validateParams(p5, p5.prototype);
}

export { validateParams as default };
