@ue-too/dynamics 0.9.4 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js.map CHANGED
@@ -2,16 +2,16 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/rigidbody.ts", "../src/collision-filter.ts", "../src/quadtree.ts", "../src/dynamic-tree.ts", "../src/collision.ts", "../src/pair-manager.ts", "../src/world.ts", "../src/constraint.ts"],
4
4
  "sourcesContent": [
5
- "import { PointCal, Point } from \"@ue-too/math\";\nimport { CollisionFilter, DEFAULT_COLLISION_FILTER } from \"./collision-filter\";\n\nexport interface RigidBody {\n center: Point;\n orientationAngle: number;\n linearVelocity: Point;\n angularVelocity: number;\n AABB: {min: Point, max: Point};\n mass: number;\n staticFrictionCoeff: number;\n momentOfInertia: number;\n \n // Collision filtering\n collisionFilter: CollisionFilter;\n \n // Sleeping system\n isSleeping: boolean;\n sleepThreshold: number;\n sleepTime: number;\n timeAtRest: number;\n \n step(deltaTime: number): void;\n isStatic(): boolean;\n isMovingStatic(): boolean;\n getMinMaxProjection(unitvector: Point): {min: number, max: number};\n getCollisionAxes(relativeBody: RigidBody): Point[];\n applyForce(force: Point): void;\n applyForceInOrientation(force: Point): void;\n // applyForceAtPoint(force: Point, point: Point): void;\n move(delta: Point): void;\n significantVertex(collisionNormal: Point): Point;\n getSignificantVertices(collisionNormal: Point): Point[];\n getNormalOfSignificantFace(collisionNormal: Point): Point;\n getAdjacentFaces(collisionNormal: Point): {startPoint: {coord: Point, index: number}, endPoint: {coord: Point, index: number}}[];\n \n // Sleeping methods\n setSleeping(sleeping: boolean): void;\n updateSleeping(deltaTime: number): void;\n}\n\nexport interface VisualComponent{\n draw(ctx: CanvasRenderingContext2D): void;\n}\n\nexport abstract class BaseRigidBody implements RigidBody{\n \n protected _center: Point;\n protected _mass: number = 50;\n protected _linearVelocity: Point;\n protected _angularVelocity: number; // in radians\n protected _orientationAngle: number = 0;\n protected linearAcceleartion: Point;\n protected force: Point;\n protected isStaticBody: boolean = false;\n protected _staticFrictionCoeff: number = 0.3;\n protected dynamicFrictionCoeff: number = 0.3;\n protected frictionEnabled: boolean = false;\n protected isMovingStaticBody: boolean = false;\n protected angularDampingFactor: number = 0.005;\n \n // Collision filtering\n public collisionFilter: CollisionFilter = { ...DEFAULT_COLLISION_FILTER };\n \n // Sleeping system\n public isSleeping: boolean = false;\n public sleepThreshold: number = 0.01; // Velocity threshold to consider sleeping\n public sleepTime: number = 0.5; // Time (seconds) to wait before sleeping\n public timeAtRest: number = 0;\n \n\n constructor(center: Point, _orientationAngle: number = 0, mass: number = 50, isStaticBody: boolean = false, frictionEnabled: boolean = false){\n this._center = center;\n this._orientationAngle = _orientationAngle;\n this._mass = mass;\n this.isStaticBody = isStaticBody;\n this.frictionEnabled = frictionEnabled;\n this.force = {x: 0, y: 0};\n this.linearAcceleartion = {x: 0, y: 0};\n this._linearVelocity = {x: 0, y: 0};\n this._angularVelocity = 0;\n }\n\n move(delta: Point): void {\n if (!this.isStatic()){\n this._center = PointCal.addVector(this._center, delta);\n }\n }\n\n rotateRadians(angle: number): void {\n this._orientationAngle += angle;\n }\n\n getCenter(): Point {\n return this._center;\n }\n\n getOrientationAngle(): number{\n return this._orientationAngle;\n }\n\n get angularVelocity(): number{\n return this._angularVelocity;\n }\n\n set angularVelocity(angularVelocity: number){\n this._angularVelocity = angularVelocity;\n }\n\n get orientationAngle(): number{\n return this._orientationAngle;\n }\n\n isStatic(): boolean{\n return this.isStaticBody;\n }\n\n isMovingStatic(): boolean {\n return this.isMovingStaticBody;\n }\n\n setLinearVelocity(linearVelocity: Point): void {\n this._linearVelocity = linearVelocity;\n }\n\n setMovingStatic(movingStatic: boolean):void {\n this.isMovingStaticBody = movingStatic;\n }\n\n setOrientationAngle(angle: number): void{\n this._orientationAngle = angle;\n }\n\n applyForce(force: Point): void {\n if (PointCal.magnitude(this.force) !== 0){\n this.force = PointCal.addVector(this.force, force);\n } else {\n this.force = force;\n }\n }\n\n applyForceInOrientation(force: Point | number): void {\n let forceTransformed: Point;\n if (typeof force === \"number\") {\n forceTransformed = PointCal.rotatePoint({x: force, y: 0}, this._orientationAngle);\n } else {\n forceTransformed = PointCal.rotatePoint(force, this._orientationAngle);\n }\n this.applyForce(forceTransformed);\n }\n\n step(deltaTime: number): void {\n if (this.frictionEnabled) {\n if (this.isStatic() || \n (this.linearVelocity.x == 0 && \n this.linearVelocity.y == 0 && \n PointCal.magnitude(PointCal.subVector({x: this.force.x, y: this.force.y}, {x: 0, y: 0})) >= 0 && \n PointCal.magnitude({x: this.force.x, y: this.force.y}) < this.staticFrictionCoeff * this.mass * 9.81)\n ) {\n if (this.force.z != undefined) {\n this.force = {x: 0, y: 0, z: this.force.z};\n } else {\n this.force = {x: 0, y: 0};\n }\n // return;\n } else {\n let kineticFrictionDirection = PointCal.multiplyVectorByScalar(PointCal.unitVector({x: this._linearVelocity.x, y: this._linearVelocity.y}), -1);\n let kineticFriction = PointCal.multiplyVectorByScalar(kineticFrictionDirection, this.dynamicFrictionCoeff * this.mass * 9.81);\n this.force = PointCal.addVector(this.force, kineticFriction);\n }\n }\n const angularDamping = this._angularVelocity != 0 ? this._angularVelocity > 0 ? -this.angularDampingFactor : this.angularDampingFactor : 0;\n // console.log(\"angular velocity\", this._angularVelocity);\n // console.log(\"angular damping\", angularDamping);\n if (Math.abs(this._angularVelocity) < Math.abs(angularDamping)) {\n this._angularVelocity = 0;\n } else {\n this._angularVelocity += angularDamping;\n }\n this._orientationAngle += this._angularVelocity * deltaTime;\n if (PointCal.magnitude({x: this._linearVelocity.x, y: this._linearVelocity.y}) < PointCal.magnitude(PointCal.divideVectorByScalar(PointCal.multiplyVectorByScalar(this.force, deltaTime), this.mass))){\n if (this._linearVelocity.z != undefined) {\n this._linearVelocity = {x: 0, y: 0, z: this._linearVelocity.z};\n } else {\n this._linearVelocity = {x: 0, y: 0};\n }\n }\n const gravitationalForce = -9.81 * this._mass;\n this.force = PointCal.addVector(this.force, {x: 0, y: 0, z: gravitationalForce});\n const deltaLinearVelocity = PointCal.divideVectorByScalar(PointCal.multiplyVectorByScalar(this.force, deltaTime), this.mass);\n this._linearVelocity = PointCal.addVector(this._linearVelocity, deltaLinearVelocity);\n const deltaCenter = PointCal.multiplyVectorByScalar(this._linearVelocity, deltaTime);\n // console.log('delta center', deltaCenter);\n this._center = PointCal.addVector(this._center, deltaCenter);\n if (this._center.z != undefined && this._center.z < 0) {\n this._center.z = 0;\n }\n this.force = {x: 0, y: 0};\n }\n\n get center(): Point {\n return this._center;\n }\n\n set center(dest: Point){\n this._center = dest;\n }\n\n get linearVelocity(): Point {\n return this._linearVelocity;\n }\n\n set linearVelocity(dest: Point){\n this._linearVelocity = dest;\n }\n\n get mass(): number{\n return this._mass;\n }\n\n get staticFrictionCoeff(): number{\n return this._staticFrictionCoeff;\n }\n\n set staticFrictionCoeff(coeff: number){\n this._staticFrictionCoeff = coeff;\n }\n\n abstract get momentOfInertia(): number;\n abstract getMinMaxProjection(unitvector: Point): {min: number, max: number};\n abstract getCollisionAxes(relativeBody: RigidBody): Point[];\n abstract get AABB(): {min: Point, max: Point};\n abstract significantVertex(collisionNormal: Point): Point;\n abstract getSignificantVertices(collisionNormal: Point): Point[];\n abstract getNormalOfSignificantFace(collisionNormal: Point): Point;\n abstract getAdjacentFaces(collisionNormal: Point): {startPoint: {coord: Point, index: number}, endPoint: {coord: Point, index: number}}[];\n\n // Sleeping methods\n setSleeping(sleeping: boolean): void {\n if (sleeping && !this.isSleeping) {\n this.isSleeping = true;\n this._linearVelocity = { x: 0, y: 0 };\n this._angularVelocity = 0;\n } else if (!sleeping && this.isSleeping) {\n this.isSleeping = false;\n this.timeAtRest = 0;\n }\n }\n\n updateSleeping(deltaTime: number): void {\n if (this.isStatic() || this.isMovingStatic()) return;\n\n const speed = PointCal.magnitude(this._linearVelocity);\n const angularSpeed = Math.abs(this._angularVelocity);\n\n if (speed < this.sleepThreshold && angularSpeed < this.sleepThreshold) {\n this.timeAtRest += deltaTime;\n if (this.timeAtRest >= this.sleepTime) {\n this.setSleeping(true);\n }\n } else {\n this.timeAtRest = 0;\n if (this.isSleeping) {\n this.setSleeping(false);\n }\n }\n }\n}\n\nexport class VisaulCircleBody implements VisualComponent, RigidBody {\n\n private _circle: Circle;\n private _context: CanvasRenderingContext2D;\n \n // Collision filtering\n public collisionFilter: CollisionFilter = { ...DEFAULT_COLLISION_FILTER };\n \n // Sleeping system\n public isSleeping: boolean = false;\n public sleepThreshold: number = 0.01;\n public sleepTime: number = 0.5;\n public timeAtRest: number = 0;\n\n constructor(center: Point = {x: 0, y: 0}, radius: number, drawingContext: CanvasRenderingContext2D, _orientationAngle: number = 0, mass: number = 50, isStatic: boolean = false, frictionEnabled: boolean = true) {\n this._circle = new Circle(center, radius, _orientationAngle, mass, isStatic, frictionEnabled);\n this._context = drawingContext;\n }\n\n draw(ctx: CanvasRenderingContext2D): void {\n ctx.beginPath();\n ctx.arc(this._circle.center.x, this._circle.center.y, this._circle.radius, 0, 2 * Math.PI);\n ctx.stroke();\n }\n\n step(deltaTime: number): void {\n this._circle.step(deltaTime);\n this.draw(this._context);\n }\n\n isStatic(): boolean {\n return this._circle.isStatic();\n }\n\n isMovingStatic(): boolean {\n return this._circle.isMovingStatic();\n }\n\n getMinMaxProjection(unitvector: Point): { min: number; max: number; } {\n return this._circle.getMinMaxProjection(unitvector);\n }\n\n getCollisionAxes(relativeBody: RigidBody): Point[] {\n return this._circle.getCollisionAxes(relativeBody);\n }\n\n applyForce(force: Point): void {\n this._circle.applyForce(force);\n }\n\n get AABB(): { min: Point; max: Point; } {\n return this._circle.AABB;\n }\n\n getMass(): number {\n return this._circle.mass;\n }\n\n applyForceInOrientation(force: Point): void {\n this._circle.applyForceInOrientation(force);\n }\n\n move(delta: Point): void {\n this._circle.move(delta);\n }\n\n getSignificantVertices(collisionNormal: Point): Point[] {\n return this._circle.getSignificantVertices(collisionNormal);\n }\n\n get center(): Point {\n return this._circle.center;\n }\n\n set center(dest: Point){\n this._circle.center = dest;\n }\n\n get linearVelocity(): Point {\n return this._circle.linearVelocity;\n }\n\n set linearVelocity(dest: Point){\n this._circle.linearVelocity = dest;\n }\n\n get orientationAngle(){\n return this._circle.orientationAngle;\n }\n\n significantVertex(collisionNormal: Point): Point {\n return this._circle.significantVertex(collisionNormal);\n }\n\n set angularVelocity(angularVelocity: number){\n this._circle.angularVelocity = angularVelocity;\n }\n\n get angularVelocity(): number{\n return this._circle.angularVelocity;\n }\n\n get mass(): number{\n return this._circle.mass;\n }\n\n getNormalOfSignificantFace(collisionNormal: Point): Point {\n return this._circle.getNormalOfSignificantFace(collisionNormal);\n }\n\n get staticFrictionCoeff(): number{\n return this._circle.staticFrictionCoeff;\n }\n\n set staticFrictionCoeff(coeff: number){\n this._circle.staticFrictionCoeff = coeff;\n }\n\n getAdjacentFaces(collisionNormal: Point): {startPoint: {coord: Point, index: number}, endPoint: {coord: Point, index: number}}[] {\n return this._circle.getAdjacentFaces(collisionNormal);\n }\n\n get momentOfInertia(): number {\n return this._circle.momentOfInertia;\n }\n\n // Sleeping methods\n setSleeping(sleeping: boolean): void {\n if (sleeping && !this.isSleeping) {\n this.isSleeping = true;\n this._circle.linearVelocity = { x: 0, y: 0 };\n this._circle.angularVelocity = 0;\n } else if (!sleeping && this.isSleeping) {\n this.isSleeping = false;\n this.timeAtRest = 0;\n }\n }\n\n updateSleeping(deltaTime: number): void {\n if (this._circle.isStatic() || this._circle.isMovingStatic()) return;\n\n const speed = PointCal.magnitude(this._circle.linearVelocity);\n const angularSpeed = Math.abs(this._circle.angularVelocity);\n\n if (speed < this.sleepThreshold && angularSpeed < this.sleepThreshold) {\n this.timeAtRest += deltaTime;\n if (this.timeAtRest >= this.sleepTime) {\n this.setSleeping(true);\n }\n } else {\n this.timeAtRest = 0;\n if (this.isSleeping) {\n this.setSleeping(false);\n }\n }\n }\n\n}\n\nexport class VisualPolygonBody implements VisualComponent, RigidBody {\n \n private _polygon: Polygon;\n private _context: CanvasRenderingContext2D;\n \n // Collision filtering\n public collisionFilter: CollisionFilter = { ...DEFAULT_COLLISION_FILTER };\n \n // Sleeping system\n public isSleeping: boolean = false;\n public sleepThreshold: number = 0.01;\n public sleepTime: number = 0.5;\n public timeAtRest: number = 0;\n\n constructor(center: Point = {x: 0, y: 0}, vertices: Point[], drawingContext: CanvasRenderingContext2D, _orientationAngle: number = 0, mass: number = 50, isStatic: boolean = false, frictionEnabled: boolean = true) {\n this._polygon = new Polygon(center, vertices, _orientationAngle, mass, isStatic, frictionEnabled);\n this._context = drawingContext;\n }\n\n draw(ctx: CanvasRenderingContext2D): void {\n ctx.beginPath();\n let vertices = this._polygon.getVerticesAbsCoord();\n ctx.moveTo(vertices[0].x, vertices[0].y);\n vertices.forEach(vertex => {\n ctx.lineTo(vertex.x, vertex.y);\n });\n ctx.lineTo(vertices[0].x, vertices[0].y);\n ctx.stroke();\n // ctx.beginPath();\n // ctx.rect(this._polygon.AABB.min.x, this._polygon.AABB.min.y, this._polygon.AABB.max.x - this._polygon.AABB.min.x, this._polygon.AABB.max.y - this._polygon.AABB.min.y);\n // ctx.stroke();\n }\n\n step(deltaTime: number): void {\n this._polygon.step(deltaTime);\n this.draw(this._context);\n }\n\n isStatic(): boolean {\n return this._polygon.isStatic();\n }\n\n isMovingStatic(): boolean {\n return this._polygon.isMovingStatic();\n }\n\n getMinMaxProjection(unitvector: Point): { min: number; max: number; } {\n return this._polygon.getMinMaxProjection(unitvector);\n }\n\n getCollisionAxes(relativeBody: RigidBody): Point[] {\n return this._polygon.getCollisionAxes(relativeBody);\n }\n\n applyForce(force: Point): void {\n this._polygon.applyForce(force);\n }\n\n applyForceInOrientation(force: Point): void {\n this._polygon.applyForceInOrientation(force);\n }\n\n setLinearVelocity(linearVelocity: Point): void {\n this._polygon.setLinearVelocity(linearVelocity);\n }\n\n move(delta: Point): void {\n this._polygon.move(delta);\n }\n\n get center(): Point {\n return this._polygon.center;\n }\n\n set center(dest: Point){\n this._polygon.center = dest;\n }\n\n get linearVelocity(): Point {\n return this._polygon.linearVelocity;\n }\n\n set linearVelocity(dest: Point){\n this._polygon.linearVelocity = dest;\n }\n\n get angularVelocity(): number{\n return this._polygon.angularVelocity;\n }\n\n set angularVelocity(angularVelocity: number){\n this._polygon.angularVelocity = angularVelocity;\n }\n\n get orientationAngle(): number{\n return this._polygon.orientationAngle;\n }\n\n significantVertex(collisionNormal: Point): Point {\n return this._polygon.significantVertex(collisionNormal);\n }\n\n getSignificantVertices(collisionNormal: Point): Point[] {\n return this._polygon.getSignificantVertices(collisionNormal);\n }\n\n get AABB(): {min: Point, max: Point}{\n return this._polygon.AABB;\n }\n\n get mass(): number{\n return this._polygon.mass;\n }\n \n get staticFrictionCoeff(): number{\n return this._polygon.staticFrictionCoeff;\n }\n\n set staticFrictionCoeff(coeff: number){\n this._polygon.staticFrictionCoeff = coeff;\n }\n\n get momentOfInertia(): number {\n return this._polygon.momentOfInertia;\n }\n\n getNormalOfSignificantFace(collisionNormal: Point): Point {\n return this._polygon.getNormalOfSignificantFace(collisionNormal);\n }\n\n getAdjacentFaces(collisionNormal: Point): {startPoint: {coord: Point, index: number}, endPoint: {coord: Point, index: number}}[] {\n return this._polygon.getAdjacentFaces(collisionNormal);\n }\n\n // Sleeping methods\n setSleeping(sleeping: boolean): void {\n if (sleeping && !this.isSleeping) {\n this.isSleeping = true;\n this._polygon.linearVelocity = { x: 0, y: 0 };\n this._polygon.angularVelocity = 0;\n } else if (!sleeping && this.isSleeping) {\n this.isSleeping = false;\n this.timeAtRest = 0;\n }\n }\n\n updateSleeping(deltaTime: number): void {\n if (this._polygon.isStatic() || this._polygon.isMovingStatic()) return;\n\n const speed = PointCal.magnitude(this._polygon.linearVelocity);\n const angularSpeed = Math.abs(this._polygon.angularVelocity);\n\n if (speed < this.sleepThreshold && angularSpeed < this.sleepThreshold) {\n this.timeAtRest += deltaTime;\n if (this.timeAtRest >= this.sleepTime) {\n this.setSleeping(true);\n }\n } else {\n this.timeAtRest = 0;\n if (this.isSleeping) {\n this.setSleeping(false);\n }\n }\n }\n}\n\nexport class Polygon extends BaseRigidBody {\n\n private vertices: Point[];\n private _momentOfInertia: number;\n\n constructor(center: Point = {x: 0, y: 0}, vertices: Point[], _orientationAngle: number = 0, mass: number = 50, isStatic: boolean = false, frictionEnabled: boolean = true) {\n super(center, _orientationAngle, mass, isStatic, frictionEnabled);\n this.vertices = vertices;\n this.step = this.step.bind(this);\n\n let numerator = this.vertices.reduce((acc, vertex, index) => {\n let nextPointIndex = index < this.vertices.length - 1 ? index + 1 : 0;\n let nextPoint = this.vertices[nextPointIndex];\n let crossProduct = PointCal.crossProduct(nextPoint, vertex);\n return acc + PointCal.magnitude(crossProduct) * (PointCal.dotProduct(vertex, vertex) + PointCal.dotProduct(vertex, nextPoint) + PointCal.dotProduct(nextPoint, nextPoint));\n }, 0);\n\n let denomiator = this.vertices.reduce((acc, vertex, index) => {\n return acc + PointCal.magnitude(PointCal.crossProduct(this.vertices[index < this.vertices.length - 1 ? index + 1 : 0], vertex));\n }, 0);\n\n \n this._momentOfInertia = this._mass * numerator / (6 * denomiator);\n }\n\n\n getVerticesAbsCoord(): Point[]{\n return this.vertices.map(vertex=>{\n return PointCal.addVector(this._center, PointCal.rotatePoint(vertex, this._orientationAngle));\n });\n }\n\n getCollisionAxes(relativeBody: RigidBody): Point[] {\n return this.getVerticesAbsCoord().map((vertex, index, absVertices)=>{\n let vector = PointCal.subVector(vertex, absVertices[absVertices.length - 1]);\n if (index > 0){\n vector = PointCal.subVector(vertex, absVertices[index - 1]); \n }\n return PointCal.unitVector(PointCal.rotatePoint(vector, Math.PI / 2));\n });\n }\n\n getMinMaxProjection(unitvector: Point): { min: number; max: number; } {\n let vertices = this.getVerticesAbsCoord();\n \n let projections = vertices.map( vertex => {\n return PointCal.dotProduct(vertex, unitvector);\n });\n\n \n return {min: Math.min(...projections), max: Math.max(...projections)};\n }\n\n get AABB(): { min: Point; max: Point; } {\n let points = this.getVerticesAbsCoord();\n let xCoords = points.map(vertex => vertex.x);\n let yCoords = points.map(vertex => vertex.y);\n return {min: {x: Math.min(...xCoords), y: Math.min(...yCoords)}, max: {x: Math.max(...xCoords), y: Math.max(...yCoords)}};\n }\n\n significantVertex(collisionNormal: Point): Point {\n let vertices = this.getVerticesAbsCoord();\n let verticesProjected = vertices.map(vertex => PointCal.dotProduct(vertex, collisionNormal));\n let maxIndex = verticesProjected.indexOf(Math.max(...verticesProjected));\n return vertices[maxIndex];\n }\n\n getSignificantVertices(collisionNormal: Point): Point[]{\n let vertices = this.getVerticesAbsCoord();\n let verticesProjected = vertices.map(vertex => PointCal.dotProduct(vertex, collisionNormal));\n let maxIndex = verticesProjected.indexOf(Math.max(...verticesProjected));\n const tipVertex = vertices[maxIndex];\n let prevPointIndex = maxIndex > 0 ? maxIndex - 1 : vertices.length - 1;\n let nextPointIndex = maxIndex < vertices.length - 1 ? maxIndex + 1 : 0;\n const prevPoint = vertices[prevPointIndex];\n const nextPoint = vertices[nextPointIndex];\n const prevPointProjected = PointCal.dotProduct(prevPoint, collisionNormal);\n const nextPointProjected = PointCal.dotProduct(nextPoint, collisionNormal);\n if (prevPointProjected > nextPointProjected) {\n return [prevPoint, tipVertex];\n } else {\n return [tipVertex, nextPoint];\n }\n }\n\n getNormalOfSignificantFace(collisionNormal: Point): Point{\n const vertices = this.getSignificantVertices(collisionNormal);\n const direction = PointCal.unitVectorFromA2B(vertices[0], vertices[1]);\n return PointCal.rotatePoint(direction, -Math.PI / 2);\n }\n\n getAdjacentFaces(collisionNormal: Point): {startPoint: {coord: Point, index: number}, endPoint: {coord: Point, index: number}}[]{\n let vertices = this.getVerticesAbsCoord();\n let verticesProjected = vertices.map(vertex => PointCal.dotProduct(vertex, collisionNormal));\n let maxIndex = verticesProjected.indexOf(Math.max(...verticesProjected));\n const tipVertex = vertices[maxIndex];\n let prevPointIndex = maxIndex > 0 ? maxIndex - 1 : vertices.length - 1;\n let nextPointIndex = maxIndex < vertices.length - 1 ? maxIndex + 1 : 0;\n const prevPoint = vertices[prevPointIndex];\n const nextPoint = vertices[nextPointIndex];\n const prevPointProjected = PointCal.dotProduct(prevPoint, collisionNormal);\n const nextPointProjected = PointCal.dotProduct(nextPoint, collisionNormal);\n const adjacentFaces: Point[] = [];\n const adjacentFacesWithIndex: {startPoint: {coord: Point, index: number}, endPoint: {coord: Point, index: number}}[] = [];\n if (prevPointProjected > nextPointProjected) {\n adjacentFaces.push(prevPoint, tipVertex);\n adjacentFacesWithIndex.push({startPoint: {coord: prevPoint, index: prevPointIndex}, endPoint: {coord: tipVertex, index: maxIndex}});\n\n // the nextface is the next face\n adjacentFacesWithIndex.unshift({startPoint: {coord: tipVertex, index: maxIndex}, endPoint: {coord: nextPoint, index: nextPointIndex}});\n // need to get the previous face of the previous face\n let prevPrevPointIndex = prevPointIndex > 0 ? prevPointIndex - 1 : vertices.length - 1;\n adjacentFacesWithIndex.unshift({startPoint: {coord: vertices[prevPrevPointIndex], index: prevPrevPointIndex}, endPoint: {coord: prevPoint, index: prevPointIndex}});\n } else {\n adjacentFaces.push(tipVertex, nextPoint);\n adjacentFacesWithIndex.push({startPoint: {coord: tipVertex, index: maxIndex}, endPoint: {coord: nextPoint, index: nextPointIndex}});\n\n // need to get the next face of the next face\n let nextNextPointIndex = nextPointIndex < vertices.length - 1 ? nextPointIndex + 1 : 0;\n adjacentFacesWithIndex.unshift({startPoint: {coord: nextPoint, index: nextPointIndex}, endPoint: {coord: vertices[nextNextPointIndex], index: nextNextPointIndex}})\n\n // the prevoius face is the previous face\n adjacentFacesWithIndex.unshift({startPoint: {coord: prevPoint, index: prevPointIndex}, endPoint: {coord: tipVertex, index: maxIndex}});\n }\n \n return adjacentFacesWithIndex;\n }\n\n get momentOfInertia(): number {\n return this._momentOfInertia;\n }\n\n}\n\nexport class Circle extends BaseRigidBody {\n\n private _radius: number;\n private _momentOfInertia: number;\n\n constructor(center: Point = {x: 0, y: 0}, radius: number, _orientationAngle: number = 0, mass: number = 50, isStatic: boolean = false, frictionEnabled: boolean = true) {\n super(center, _orientationAngle, mass, isStatic, frictionEnabled);\n this._radius = radius;\n this.step = this.step.bind(this);\n this._momentOfInertia = this._mass * this._radius * this._radius / 2;\n }\n\n getMinMaxProjection(unitvector: Point): { min: number; max: number; } {\n let PositiveFurthest = PointCal.addVector(this._center, PointCal.multiplyVectorByScalar(unitvector, this._radius));\n let NegativeFurthest = PointCal.addVector(this._center, PointCal.multiplyVectorByScalar(unitvector, -this._radius));\n return {min: PointCal.dotProduct(NegativeFurthest, unitvector), max: PointCal.dotProduct(PositiveFurthest, unitvector)};\n }\n\n getCollisionAxes(relativeBody: RigidBody): Point[] {\n return [PointCal.unitVector(PointCal.subVector(relativeBody.center, this._center))];\n }\n\n get AABB(): { min: Point; max: Point; } {\n return {min: PointCal.subVector(this._center, {x: this._radius, y: this._radius}), max: PointCal.addVector(this._center, {x: this._radius, y: this._radius})};\n }\n\n significantVertex(collisionNormal: Point): Point {\n return PointCal.addVector(this._center, PointCal.multiplyVectorByScalar(collisionNormal, this._radius));\n }\n\n get radius(): number {\n return this._radius;\n }\n\n getSignificantVertices(collisionNormal: Point): Point[]{\n return [PointCal.addVector(this._center, PointCal.multiplyVectorByScalar(collisionNormal, this._radius))];\n }\n\n getNormalOfSignificantFace(collisionNormal: Point): Point{\n return PointCal.unitVector(collisionNormal);\n }\n\n getAdjacentFaces(collisionNormal: Point): {startPoint: {coord: Point, index: number}, endPoint: {coord: Point, index: number}}[]{\n return [];\n }\n\n get momentOfInertia(): number {\n return this._momentOfInertia;\n }\n}\n",
6
- "export interface CollisionFilter {\n category: number; // What category this body belongs to\n mask: number; // What categories this body can collide with\n group: number; // Collision group (negative = never collide, positive = always collide if same group)\n}\n\nexport const DEFAULT_COLLISION_FILTER: CollisionFilter = {\n category: 0x0001,\n mask: 0xFFFF, \n group: 0\n};\n\nexport function canCollide(filterA: CollisionFilter, filterB: CollisionFilter): boolean {\n // If objects are in the same group\n if (filterA.group !== 0 && filterA.group === filterB.group) {\n return filterA.group > 0; // Positive groups collide, negative groups don't\n }\n\n // Check category-mask pairs\n return (filterA.category & filterB.mask) !== 0 && (filterB.category & filterA.mask) !== 0;\n}\n\n// Common collision categories for games\nexport const CollisionCategory = {\n STATIC: 0x0001, // Walls, floors, static objects\n DYNAMIC: 0x0002, // Moving objects \n PLAYER: 0x0004, // Player character\n ENEMY: 0x0008, // Enemy entities\n PROJECTILE: 0x0010, // Bullets, projectiles\n SENSOR: 0x0020, // Trigger zones, sensors\n PICKUP: 0x0040, // Items that can be collected\n PLATFORM: 0x0080, // One-way platforms\n} as const;",
7
- "import { Point } from \"@ue-too/math\";\nimport { RigidBody } from \"./rigidbody\";\nimport { SpatialIndex, SpatialIndexObject } from \"./dynamic-tree\";\n\nexport class RectangleBound{\n private bottomLeft: Point;\n private width: number;\n private height: number;\n\n constructor(bottomLeft: Point, width: number, height: number){\n this.bottomLeft = bottomLeft;\n this.width = width;\n this.height = height;\n }\n\n getWidth(){\n return this.width;\n }\n\n getHeight(){\n return this.height;\n }\n\n getbottomLeft(){\n return this.bottomLeft;\n }\n}\n\nexport type QuadTreeObject = SpatialIndexObject;\n\nexport class QuadTree<T extends QuadTreeObject> implements SpatialIndex<T> {\n private MAX_OBJECTS = 10; // per node\n private MAX_LEVELS = 5;\n\n private level: number;\n private objects: T[] = [];\n private nodes: (QuadTree<T> | undefined)[] = [];\n private bounds: RectangleBound;\n \n\n constructor(level: number, bounds: RectangleBound){\n this.level = level;\n this.objects = [];\n this.bounds = bounds;\n this.nodes = [undefined, undefined, undefined, undefined];\n }\n\n draw(context: CanvasRenderingContext2D){\n context.beginPath();\n context.rect(this.bounds.getbottomLeft().x, this.bounds.getbottomLeft().y, this.bounds.getWidth(), this.bounds.getHeight());\n context.stroke();\n // console.log(\"objects: \", this.objects.length, \"level: \", this.level);\n for(let index = 0; index < this.nodes.length; index++){\n let node = this.nodes[index];\n if(node != undefined){\n node.draw(context);\n }\n }\n }\n\n clear(){\n this.objects = [];\n for(let index = 0; index < this.nodes.length; index++){\n let node = this.nodes[index];\n if(node != undefined){\n node.clear();\n node = undefined;\n }\n }\n }\n\n split(){\n // console.log(\"split\");\n let subWidth = this.bounds.getWidth() / 2;\n let subHeight = this.bounds.getHeight() / 2;\n let bottomLeft = this.bounds.getbottomLeft();\n // bottom left is the first node and it goes clock wise \n this.nodes[0] = new QuadTree<T>(this.level + 1, new RectangleBound({x: bottomLeft.x, y: bottomLeft.y}, subWidth, subHeight));\n this.nodes[1] = new QuadTree<T>(this.level + 1, new RectangleBound({x: bottomLeft.x, y: bottomLeft.y + subHeight}, subWidth, subHeight));\n this.nodes[2] = new QuadTree<T>(this.level + 1, new RectangleBound({x: bottomLeft.x + subWidth, y: bottomLeft.y + subHeight}, subWidth, subHeight));\n this.nodes[3] = new QuadTree<T>(this.level + 1, new RectangleBound({x: bottomLeft.x + subWidth, y: bottomLeft.y}, subWidth, subHeight));\n }\n\n getIndex(vBody: T){\n let midPoint = {x: this.bounds.getbottomLeft().x + this.bounds.getWidth() / 2, y: this.bounds.getbottomLeft().y + this.bounds.getHeight() / 2};\n let points = vBody.AABB;\n let bottom = points.max.y < midPoint.y && points.min.y > this.bounds.getbottomLeft().y;\n let left = points.max.x < midPoint.x && points.min.x > this.bounds.getbottomLeft().x;\n let right = points.max.x > midPoint.x && points.min.x > midPoint.x;\n let top = points.max.y > midPoint.y && points.min.y > midPoint.y;\n // console.log(\"level\", this.level);\n if (bottom && left){\n return 0;\n } else if (bottom && right){\n return 3;\n } else if (top && left){\n return 1;\n } else if (top && right){\n return 2;\n }\n return -1;\n }\n\n insert(vBody: T){\n let node = this.nodes[0];\n if (node != undefined){\n let index = this.getIndex(vBody);\n\n if (index !== -1){\n node = this.nodes[index];\n node?.insert(vBody);\n return;\n }\n }\n\n this.objects.push(vBody);\n if(this.objects.length > this.MAX_OBJECTS && this.level < this.MAX_LEVELS){\n if (this.nodes[0] == null || this.nodes[0] == undefined){\n this.split();\n }\n let i = 0;\n while (i < this.objects.length){\n let index = this.getIndex(this.objects[i]);\n let node = this.nodes[index];\n if (index != -1 && node !== undefined){\n let vBody = this.objects[i];\n this.objects.splice(i, 1);\n node.insert(vBody);\n } else{\n i++;\n }\n }\n }\n }\n\n retrieve(vBody: T): T[]{\n let index = this.getIndex(vBody);\n let res = [];\n let node = this.nodes[index];\n if(index !== -1 && node !== undefined){\n res.push(...node.retrieve(vBody));\n }\n res.push(...this.objects);\n return res;\n }\n\n}",
8
- "import { Point } from \"@ue-too/math\";\n\nexport interface SpatialIndexObject {\n AABB: { min: Point, max: Point };\n}\n\nexport interface SpatialIndex<T extends SpatialIndexObject> {\n clear(): void;\n insert(object: T): void;\n retrieve(object: T): T[];\n draw?(context: CanvasRenderingContext2D): void;\n}\n\ninterface AABB {\n min: Point;\n max: Point;\n}\n\nclass TreeNode<T extends SpatialIndexObject> {\n public parent: TreeNode<T> | null = null;\n public children: [TreeNode<T> | null, TreeNode<T> | null] = [null, null];\n public aabb: AABB = { min: { x: 0, y: 0 }, max: { x: 0, y: 0 } };\n public object: T | null = null;\n public height: number = 0;\n\n constructor(object?: T) {\n if (object) {\n this.setLeaf(object);\n }\n }\n\n isLeaf(): boolean {\n return this.children[0] === null;\n }\n\n setLeaf(object: T): void {\n this.object = object;\n this.updateAABB();\n this.children = [null, null];\n this.height = 0;\n }\n\n setBranch(child1: TreeNode<T>, child2: TreeNode<T>): void {\n child1.parent = this;\n child2.parent = this;\n this.children = [child1, child2];\n this.object = null;\n this.updateAABB();\n this.height = 1 + Math.max(child1.height, child2.height);\n }\n\n updateAABB(margin: number = 0.1): void {\n if (this.isLeaf() && this.object) {\n // Create \"fat\" AABB with margin for dynamic objects\n const obj = this.object.AABB;\n this.aabb = {\n min: { x: obj.min.x - margin, y: obj.min.y - margin },\n max: { x: obj.max.x + margin, y: obj.max.y + margin }\n };\n } else if (this.children[0] && this.children[1]) {\n // Union of children AABBs\n const aabb1 = this.children[0].aabb;\n const aabb2 = this.children[1].aabb;\n this.aabb = {\n min: {\n x: Math.min(aabb1.min.x, aabb2.min.x),\n y: Math.min(aabb1.min.y, aabb2.min.y)\n },\n max: {\n x: Math.max(aabb1.max.x, aabb2.max.x),\n y: Math.max(aabb1.max.y, aabb2.max.y)\n }\n };\n }\n }\n\n getSibling(): TreeNode<T> | null {\n if (!this.parent) return null;\n return this.parent.children[0] === this ? this.parent.children[1] : this.parent.children[0];\n }\n\n getBalance(): number {\n if (this.isLeaf()) return 0;\n const leftHeight = this.children[0] ? this.children[0].height : 0;\n const rightHeight = this.children[1] ? this.children[1].height : 0;\n return leftHeight - rightHeight;\n }\n}\n\n// Endpoint for Sweep and Prune algorithm\ninterface Endpoint<T> {\n value: number;\n isMin: boolean;\n object: T;\n id: number;\n}\n\n// Optimized Sweep and Prune implementation\nexport class SweepAndPrune<T extends SpatialIndexObject> implements SpatialIndex<T> {\n private xEndpoints: Endpoint<T>[] = [];\n private objects: Map<T, { minEndpoint: Endpoint<T>, maxEndpoint: Endpoint<T> }> = new Map();\n private nextId: number = 0;\n\n clear(): void {\n this.xEndpoints = [];\n this.objects.clear();\n this.nextId = 0;\n }\n\n insert(object: T): void {\n const id = this.nextId++;\n \n const minEndpoint: Endpoint<T> = { value: object.AABB.min.x, isMin: true, object, id };\n const maxEndpoint: Endpoint<T> = { value: object.AABB.max.x, isMin: false, object, id };\n \n this.objects.set(object, { minEndpoint, maxEndpoint });\n\n // Use binary search + splice for O(n) insertion instead of O(n log n) sort\n this.insertEndpointSorted(minEndpoint);\n this.insertEndpointSorted(maxEndpoint);\n }\n\n update(object: T): void {\n const endpoints = this.objects.get(object);\n if (!endpoints) return;\n\n const newMinX = object.AABB.min.x;\n const newMaxX = object.AABB.max.x;\n\n // Update endpoint values and maintain sorted order\n if (endpoints.minEndpoint.value !== newMinX) {\n this.removeEndpoint(endpoints.minEndpoint);\n endpoints.minEndpoint.value = newMinX;\n this.insertEndpointSorted(endpoints.minEndpoint);\n }\n\n if (endpoints.maxEndpoint.value !== newMaxX) {\n this.removeEndpoint(endpoints.maxEndpoint);\n endpoints.maxEndpoint.value = newMaxX;\n this.insertEndpointSorted(endpoints.maxEndpoint);\n }\n }\n\n remove(object: T): void {\n const endpoints = this.objects.get(object);\n if (!endpoints) return;\n\n this.removeEndpoint(endpoints.minEndpoint);\n this.removeEndpoint(endpoints.maxEndpoint);\n this.objects.delete(object);\n }\n\n retrieve(queryObject: T): T[] {\n const result: T[] = [];\n const queryMin = queryObject.AABB.min.x;\n const queryMax = queryObject.AABB.max.x;\n\n // Find all objects that overlap on x-axis using sweep line\n for (const endpoint of this.xEndpoints) {\n if (endpoint.value > queryMax) break;\n \n if (endpoint.isMin && endpoint.object !== queryObject) {\n // Object starts - check if it overlaps with query on x-axis\n const objMax = this.objects.get(endpoint.object)?.maxEndpoint.value;\n if (objMax !== undefined && objMax >= queryMin) {\n // Check y-axis overlap\n if (this.aabbIntersects(endpoint.object.AABB, queryObject.AABB)) {\n result.push(endpoint.object);\n }\n }\n }\n }\n\n return result;\n }\n\n // Efficient method to find all collision pairs - the main strength of sweep-and-prune\n findAllOverlaps(): Array<{a: T, b: T}> {\n const pairs: Array<{a: T, b: T}> = [];\n const activeObjects = new Set<T>();\n \n for (const endpoint of this.xEndpoints) {\n if (endpoint.isMin) {\n // Check against all currently active objects\n for (const activeObj of activeObjects) {\n if (this.aabbIntersects(endpoint.object.AABB, activeObj.AABB)) {\n pairs.push({a: endpoint.object, b: activeObj});\n }\n }\n activeObjects.add(endpoint.object);\n } else {\n activeObjects.delete(endpoint.object);\n }\n }\n return pairs;\n }\n\n private insertEndpointSorted(endpoint: Endpoint<T>): void {\n // Binary search for insertion position\n let left = 0;\n let right = this.xEndpoints.length;\n \n while (left < right) {\n const mid = Math.floor((left + right) / 2);\n const midEndpoint = this.xEndpoints[mid];\n \n if (midEndpoint.value < endpoint.value || \n (midEndpoint.value === endpoint.value && midEndpoint.isMin && !endpoint.isMin)) {\n left = mid + 1;\n } else {\n right = mid;\n }\n }\n \n this.xEndpoints.splice(left, 0, endpoint);\n }\n\n private removeEndpoint(endpoint: Endpoint<T>): void {\n const index = this.xEndpoints.indexOf(endpoint);\n if (index !== -1) {\n this.xEndpoints.splice(index, 1);\n }\n }\n\n private aabbIntersects(aabb1: { min: Point, max: Point }, aabb2: { min: Point, max: Point }): boolean {\n return !(aabb1.max.x < aabb2.min.x || \n aabb1.min.x > aabb2.max.x || \n aabb1.max.y < aabb2.min.y || \n aabb1.min.y > aabb2.max.y);\n }\n\n // Enhanced visualization showing active sweep line and overlaps\n draw?(context: CanvasRenderingContext2D): void {\n context.strokeStyle = 'orange';\n context.lineWidth = 1;\n context.globalAlpha = 0.3;\n \n // Draw vertical lines at object boundaries\n for (const endpoint of this.xEndpoints) {\n context.beginPath();\n context.moveTo(endpoint.value, -1000);\n context.lineTo(endpoint.value, 1000);\n context.stroke();\n \n // Label min/max endpoints\n context.fillStyle = endpoint.isMin ? 'green' : 'red';\n context.fillText(endpoint.isMin ? 'min' : 'max', endpoint.value, -950);\n }\n \n context.globalAlpha = 1.0;\n }\n\n // Get statistics for performance monitoring\n getStats(): { endpointCount: number, objectCount: number } {\n return {\n endpointCount: this.xEndpoints.length,\n objectCount: this.objects.size\n };\n }\n}\n\nexport class DynamicTree<T extends SpatialIndexObject> implements SpatialIndex<T> {\n private root: TreeNode<T> | null = null;\n private nodeCount: number = 0;\n private margin: number = 0.1; // Fat AABB margin\n\n clear(): void {\n this.root = null;\n this.nodeCount = 0;\n }\n\n insert(object: T): void {\n const node = new TreeNode(object);\n this.insertNode(node);\n }\n\n private insertNode(node: TreeNode<T>): void {\n this.nodeCount++;\n\n if (!this.root) {\n this.root = node;\n return;\n }\n\n // Find the best sibling for the new node\n let sibling = this.findBestSibling(node);\n \n // Create new parent\n const oldParent = sibling.parent;\n const newParent = new TreeNode<T>();\n newParent.parent = oldParent;\n newParent.setBranch(sibling, node);\n\n if (oldParent) {\n // Replace sibling with newParent in oldParent\n if (oldParent.children[0] === sibling) {\n oldParent.children[0] = newParent;\n } else {\n oldParent.children[1] = newParent;\n }\n } else {\n // sibling was root\n this.root = newParent;\n }\n\n // Walk back up the tree fixing heights and AABBs\n let ancestor = newParent.parent;\n while (ancestor) {\n ancestor.updateAABB(this.margin);\n ancestor.height = 1 + Math.max(\n ancestor.children[0] ? ancestor.children[0].height : 0,\n ancestor.children[1] ? ancestor.children[1].height : 0\n );\n\n // Balance the tree\n ancestor = this.balance(ancestor);\n ancestor = ancestor.parent;\n }\n }\n\n private findBestSibling(node: TreeNode<T>): TreeNode<T> {\n let current = this.root!;\n\n while (!current.isLeaf()) {\n const child1 = current.children[0]!;\n const child2 = current.children[1]!;\n\n const area = this.getArea(current.aabb);\n const combinedAABB = this.combineAABB(current.aabb, node.aabb);\n const combinedArea = this.getArea(combinedAABB);\n\n // Cost of creating new parent for this node and current\n const cost = 2.0 * combinedArea;\n\n // Minimum cost of pushing node further down the tree\n const inheritanceCost = 2.0 * (combinedArea - area);\n\n // Cost of descending into child1\n let cost1: number;\n const aabb1 = this.combineAABB(node.aabb, child1.aabb);\n if (child1.isLeaf()) {\n cost1 = this.getArea(aabb1) + inheritanceCost;\n } else {\n const oldArea = this.getArea(child1.aabb);\n const newArea = this.getArea(aabb1);\n cost1 = (newArea - oldArea) + inheritanceCost;\n }\n\n // Cost of descending into child2\n let cost2: number;\n const aabb2 = this.combineAABB(node.aabb, child2.aabb);\n if (child2.isLeaf()) {\n cost2 = this.getArea(aabb2) + inheritanceCost;\n } else {\n const oldArea = this.getArea(child2.aabb);\n const newArea = this.getArea(aabb2);\n cost2 = (newArea - oldArea) + inheritanceCost;\n }\n\n // Descend according to the minimum cost\n if (cost < cost1 && cost < cost2) {\n break;\n }\n\n // Descend\n current = cost1 < cost2 ? child1 : child2;\n }\n\n return current;\n }\n\n private balance(node: TreeNode<T>): TreeNode<T> {\n if (node.isLeaf()) {\n return node;\n }\n\n const balance = node.getBalance();\n\n // Rotate if imbalanced\n if (balance < -1) {\n return this.rotateLeft(node);\n } else if (balance > 1) {\n return this.rotateRight(node);\n }\n\n return node;\n }\n\n private rotateLeft(node: TreeNode<T>): TreeNode<T> {\n const child2 = node.children[1]!;\n const child2Child1 = child2.children[0]!;\n const child2Child2 = child2.children[1]!;\n\n // Swap\n child2.children[0] = node;\n child2.parent = node.parent;\n node.parent = child2;\n\n // Update parent\n if (child2.parent) {\n if (child2.parent.children[0] === node) {\n child2.parent.children[0] = child2;\n } else {\n child2.parent.children[1] = child2;\n }\n } else {\n this.root = child2;\n }\n\n // Rotate\n if (child2Child1.height > child2Child2.height) {\n child2.children[1] = child2Child1;\n node.children[1] = child2Child2;\n child2Child2.parent = node;\n node.updateAABB(this.margin);\n child2.updateAABB(this.margin);\n node.height = 1 + Math.max(node.children[0]!.height, node.children[1]!.height);\n child2.height = 1 + Math.max(node.height, child2Child1.height);\n } else {\n child2.children[1] = child2Child2;\n node.children[1] = child2Child1;\n child2Child1.parent = node;\n node.updateAABB(this.margin);\n child2.updateAABB(this.margin);\n node.height = 1 + Math.max(node.children[0]!.height, node.children[1]!.height);\n child2.height = 1 + Math.max(node.height, child2Child2.height);\n }\n\n return child2;\n }\n\n private rotateRight(node: TreeNode<T>): TreeNode<T> {\n const child1 = node.children[0]!;\n const child1Child1 = child1.children[0]!;\n const child1Child2 = child1.children[1]!;\n\n // Swap\n child1.children[1] = node;\n child1.parent = node.parent;\n node.parent = child1;\n\n // Update parent\n if (child1.parent) {\n if (child1.parent.children[0] === node) {\n child1.parent.children[0] = child1;\n } else {\n child1.parent.children[1] = child1;\n }\n } else {\n this.root = child1;\n }\n\n // Rotate\n if (child1Child1.height > child1Child2.height) {\n child1.children[0] = child1Child1;\n node.children[0] = child1Child2;\n child1Child2.parent = node;\n node.updateAABB(this.margin);\n child1.updateAABB(this.margin);\n node.height = 1 + Math.max(node.children[0]!.height, node.children[1]!.height);\n child1.height = 1 + Math.max(child1Child1.height, node.height);\n } else {\n child1.children[0] = child1Child2;\n node.children[0] = child1Child1;\n child1Child1.parent = node;\n node.updateAABB(this.margin);\n child1.updateAABB(this.margin);\n node.height = 1 + Math.max(node.children[0]!.height, node.children[1]!.height);\n child1.height = 1 + Math.max(child1Child2.height, node.height);\n }\n\n return child1;\n }\n\n retrieve(object: T): T[] {\n const result: T[] = [];\n if (!this.root) return result;\n\n const stack: TreeNode<T>[] = [this.root];\n\n while (stack.length > 0) {\n const node = stack.pop()!;\n\n if (this.aabbIntersects(node.aabb, object.AABB)) {\n if (node.isLeaf()) {\n if (node.object && node.object !== object) {\n result.push(node.object);\n }\n } else {\n if (node.children[0]) stack.push(node.children[0]);\n if (node.children[1]) stack.push(node.children[1]);\n }\n }\n }\n\n return result;\n }\n\n draw(context: CanvasRenderingContext2D): void {\n if (!this.root) return;\n this.drawNode(context, this.root, 0);\n }\n\n private drawNode(context: CanvasRenderingContext2D, node: TreeNode<T>, depth: number): void {\n const { min, max } = node.aabb;\n \n // Different colors for different depths\n const colors = ['red', 'blue', 'green', 'orange', 'purple', 'brown'];\n context.strokeStyle = colors[depth % colors.length];\n context.lineWidth = Math.max(1, 3 - depth);\n\n context.beginPath();\n context.rect(min.x, min.y, max.x - min.x, max.y - min.y);\n context.stroke();\n\n if (!node.isLeaf()) {\n if (node.children[0]) this.drawNode(context, node.children[0], depth + 1);\n if (node.children[1]) this.drawNode(context, node.children[1], depth + 1);\n }\n }\n\n private getArea(aabb: AABB): number {\n return (aabb.max.x - aabb.min.x) * (aabb.max.y - aabb.min.y);\n }\n\n private combineAABB(aabb1: AABB, aabb2: AABB): AABB {\n return {\n min: {\n x: Math.min(aabb1.min.x, aabb2.min.x),\n y: Math.min(aabb1.min.y, aabb2.min.y)\n },\n max: {\n x: Math.max(aabb1.max.x, aabb2.max.x),\n y: Math.max(aabb1.max.y, aabb2.max.y)\n }\n };\n }\n\n private aabbIntersects(aabb1: AABB, aabb2: AABB): boolean {\n return !(aabb1.max.x < aabb2.min.x || \n aabb1.min.x > aabb2.max.x || \n aabb1.max.y < aabb2.min.y || \n aabb1.min.y > aabb2.max.y);\n }\n\n // Getter for tree statistics\n getStats(): { nodeCount: number, height: number } {\n return {\n nodeCount: this.nodeCount,\n height: this.root ? this.root.height : 0\n };\n }\n}",
5
+ "import { PointCal, Point } from \"@ue-too/math\";\nimport { CollisionFilter, DEFAULT_COLLISION_FILTER } from \"./collision-filter\";\n\n/**\n * Rigid body interface for 2D physics simulation.\n *\n * @remarks\n * Represents a physical object in the physics world with mass, velocity,\n * rotation, and collision properties. Can be either static (immovable) or\n * dynamic (responds to forces).\n *\n * Implemented by {@link Circle} and {@link Polygon} classes.\n *\n * @category Core\n */\nexport interface RigidBody {\n /** Center position in world coordinates */\n center: Point;\n /** Rotation angle in radians */\n orientationAngle: number;\n /** Linear velocity (pixels/second) */\n linearVelocity: Point;\n /** Angular velocity (radians/second) */\n angularVelocity: number;\n /** Axis-Aligned Bounding Box for broad phase collision */\n AABB: {min: Point, max: Point};\n /** Mass in arbitrary units (affects force response) */\n mass: number;\n /** Static friction coefficient (0-1) */\n staticFrictionCoeff: number;\n /** Moment of inertia (rotational mass) */\n momentOfInertia: number;\n\n /** Collision filtering configuration */\n collisionFilter: CollisionFilter;\n \n // Sleeping system\n isSleeping: boolean;\n sleepThreshold: number;\n sleepTime: number;\n timeAtRest: number;\n \n step(deltaTime: number): void;\n isStatic(): boolean;\n isMovingStatic(): boolean;\n getMinMaxProjection(unitvector: Point): {min: number, max: number};\n getCollisionAxes(relativeBody: RigidBody): Point[];\n applyForce(force: Point): void;\n applyForceInOrientation(force: Point): void;\n // applyForceAtPoint(force: Point, point: Point): void;\n move(delta: Point): void;\n significantVertex(collisionNormal: Point): Point;\n getSignificantVertices(collisionNormal: Point): Point[];\n getNormalOfSignificantFace(collisionNormal: Point): Point;\n getAdjacentFaces(collisionNormal: Point): {startPoint: {coord: Point, index: number}, endPoint: {coord: Point, index: number}}[];\n \n // Sleeping methods\n setSleeping(sleeping: boolean): void;\n updateSleeping(deltaTime: number): void;\n}\n\nexport interface VisualComponent{\n draw(ctx: CanvasRenderingContext2D): void;\n}\n\nexport abstract class BaseRigidBody implements RigidBody{\n \n protected _center: Point;\n protected _mass: number = 50;\n protected _linearVelocity: Point;\n protected _angularVelocity: number; // in radians\n protected _orientationAngle: number = 0;\n protected linearAcceleartion: Point;\n protected force: Point;\n protected isStaticBody: boolean = false;\n protected _staticFrictionCoeff: number = 0.3;\n protected dynamicFrictionCoeff: number = 0.3;\n protected frictionEnabled: boolean = false;\n protected isMovingStaticBody: boolean = false;\n protected angularDampingFactor: number = 0.005;\n \n // Collision filtering\n public collisionFilter: CollisionFilter = { ...DEFAULT_COLLISION_FILTER };\n \n // Sleeping system\n public isSleeping: boolean = false;\n public sleepThreshold: number = 0.01; // Velocity threshold to consider sleeping\n public sleepTime: number = 0.5; // Time (seconds) to wait before sleeping\n public timeAtRest: number = 0;\n \n\n constructor(center: Point, _orientationAngle: number = 0, mass: number = 50, isStaticBody: boolean = false, frictionEnabled: boolean = false){\n this._center = center;\n this._orientationAngle = _orientationAngle;\n this._mass = mass;\n this.isStaticBody = isStaticBody;\n this.frictionEnabled = frictionEnabled;\n this.force = {x: 0, y: 0};\n this.linearAcceleartion = {x: 0, y: 0};\n this._linearVelocity = {x: 0, y: 0};\n this._angularVelocity = 0;\n }\n\n move(delta: Point): void {\n if (!this.isStatic()){\n this._center = PointCal.addVector(this._center, delta);\n }\n }\n\n rotateRadians(angle: number): void {\n this._orientationAngle += angle;\n }\n\n getCenter(): Point {\n return this._center;\n }\n\n getOrientationAngle(): number{\n return this._orientationAngle;\n }\n\n get angularVelocity(): number{\n return this._angularVelocity;\n }\n\n set angularVelocity(angularVelocity: number){\n this._angularVelocity = angularVelocity;\n }\n\n get orientationAngle(): number{\n return this._orientationAngle;\n }\n\n isStatic(): boolean{\n return this.isStaticBody;\n }\n\n isMovingStatic(): boolean {\n return this.isMovingStaticBody;\n }\n\n setLinearVelocity(linearVelocity: Point): void {\n this._linearVelocity = linearVelocity;\n }\n\n setMovingStatic(movingStatic: boolean):void {\n this.isMovingStaticBody = movingStatic;\n }\n\n setOrientationAngle(angle: number): void{\n this._orientationAngle = angle;\n }\n\n applyForce(force: Point): void {\n if (PointCal.magnitude(this.force) !== 0){\n this.force = PointCal.addVector(this.force, force);\n } else {\n this.force = force;\n }\n }\n\n applyForceInOrientation(force: Point | number): void {\n let forceTransformed: Point;\n if (typeof force === \"number\") {\n forceTransformed = PointCal.rotatePoint({x: force, y: 0}, this._orientationAngle);\n } else {\n forceTransformed = PointCal.rotatePoint(force, this._orientationAngle);\n }\n this.applyForce(forceTransformed);\n }\n\n step(deltaTime: number): void {\n if (this.frictionEnabled) {\n if (this.isStatic() || \n (this.linearVelocity.x == 0 && \n this.linearVelocity.y == 0 && \n PointCal.magnitude(PointCal.subVector({x: this.force.x, y: this.force.y}, {x: 0, y: 0})) >= 0 && \n PointCal.magnitude({x: this.force.x, y: this.force.y}) < this.staticFrictionCoeff * this.mass * 9.81)\n ) {\n if (this.force.z != undefined) {\n this.force = {x: 0, y: 0, z: this.force.z};\n } else {\n this.force = {x: 0, y: 0};\n }\n // return;\n } else {\n let kineticFrictionDirection = PointCal.multiplyVectorByScalar(PointCal.unitVector({x: this._linearVelocity.x, y: this._linearVelocity.y}), -1);\n let kineticFriction = PointCal.multiplyVectorByScalar(kineticFrictionDirection, this.dynamicFrictionCoeff * this.mass * 9.81);\n this.force = PointCal.addVector(this.force, kineticFriction);\n }\n }\n const angularDamping = this._angularVelocity != 0 ? this._angularVelocity > 0 ? -this.angularDampingFactor : this.angularDampingFactor : 0;\n // console.log(\"angular velocity\", this._angularVelocity);\n // console.log(\"angular damping\", angularDamping);\n if (Math.abs(this._angularVelocity) < Math.abs(angularDamping)) {\n this._angularVelocity = 0;\n } else {\n this._angularVelocity += angularDamping;\n }\n this._orientationAngle += this._angularVelocity * deltaTime;\n if (PointCal.magnitude({x: this._linearVelocity.x, y: this._linearVelocity.y}) < PointCal.magnitude(PointCal.divideVectorByScalar(PointCal.multiplyVectorByScalar(this.force, deltaTime), this.mass))){\n if (this._linearVelocity.z != undefined) {\n this._linearVelocity = {x: 0, y: 0, z: this._linearVelocity.z};\n } else {\n this._linearVelocity = {x: 0, y: 0};\n }\n }\n const gravitationalForce = -9.81 * this._mass;\n this.force = PointCal.addVector(this.force, {x: 0, y: 0, z: gravitationalForce});\n const deltaLinearVelocity = PointCal.divideVectorByScalar(PointCal.multiplyVectorByScalar(this.force, deltaTime), this.mass);\n this._linearVelocity = PointCal.addVector(this._linearVelocity, deltaLinearVelocity);\n const deltaCenter = PointCal.multiplyVectorByScalar(this._linearVelocity, deltaTime);\n // console.log('delta center', deltaCenter);\n this._center = PointCal.addVector(this._center, deltaCenter);\n if (this._center.z != undefined && this._center.z < 0) {\n this._center.z = 0;\n }\n this.force = {x: 0, y: 0};\n }\n\n get center(): Point {\n return this._center;\n }\n\n set center(dest: Point){\n this._center = dest;\n }\n\n get linearVelocity(): Point {\n return this._linearVelocity;\n }\n\n set linearVelocity(dest: Point){\n this._linearVelocity = dest;\n }\n\n get mass(): number{\n return this._mass;\n }\n\n get staticFrictionCoeff(): number{\n return this._staticFrictionCoeff;\n }\n\n set staticFrictionCoeff(coeff: number){\n this._staticFrictionCoeff = coeff;\n }\n\n abstract get momentOfInertia(): number;\n abstract getMinMaxProjection(unitvector: Point): {min: number, max: number};\n abstract getCollisionAxes(relativeBody: RigidBody): Point[];\n abstract get AABB(): {min: Point, max: Point};\n abstract significantVertex(collisionNormal: Point): Point;\n abstract getSignificantVertices(collisionNormal: Point): Point[];\n abstract getNormalOfSignificantFace(collisionNormal: Point): Point;\n abstract getAdjacentFaces(collisionNormal: Point): {startPoint: {coord: Point, index: number}, endPoint: {coord: Point, index: number}}[];\n\n // Sleeping methods\n setSleeping(sleeping: boolean): void {\n if (sleeping && !this.isSleeping) {\n this.isSleeping = true;\n this._linearVelocity = { x: 0, y: 0 };\n this._angularVelocity = 0;\n } else if (!sleeping && this.isSleeping) {\n this.isSleeping = false;\n this.timeAtRest = 0;\n }\n }\n\n updateSleeping(deltaTime: number): void {\n if (this.isStatic() || this.isMovingStatic()) return;\n\n const speed = PointCal.magnitude(this._linearVelocity);\n const angularSpeed = Math.abs(this._angularVelocity);\n\n if (speed < this.sleepThreshold && angularSpeed < this.sleepThreshold) {\n this.timeAtRest += deltaTime;\n if (this.timeAtRest >= this.sleepTime) {\n this.setSleeping(true);\n }\n } else {\n this.timeAtRest = 0;\n if (this.isSleeping) {\n this.setSleeping(false);\n }\n }\n }\n}\n\nexport class VisaulCircleBody implements VisualComponent, RigidBody {\n\n private _circle: Circle;\n private _context: CanvasRenderingContext2D;\n \n // Collision filtering\n public collisionFilter: CollisionFilter = { ...DEFAULT_COLLISION_FILTER };\n \n // Sleeping system\n public isSleeping: boolean = false;\n public sleepThreshold: number = 0.01;\n public sleepTime: number = 0.5;\n public timeAtRest: number = 0;\n\n constructor(center: Point = {x: 0, y: 0}, radius: number, drawingContext: CanvasRenderingContext2D, _orientationAngle: number = 0, mass: number = 50, isStatic: boolean = false, frictionEnabled: boolean = true) {\n this._circle = new Circle(center, radius, _orientationAngle, mass, isStatic, frictionEnabled);\n this._context = drawingContext;\n }\n\n draw(ctx: CanvasRenderingContext2D): void {\n ctx.beginPath();\n ctx.arc(this._circle.center.x, this._circle.center.y, this._circle.radius, 0, 2 * Math.PI);\n ctx.stroke();\n }\n\n step(deltaTime: number): void {\n this._circle.step(deltaTime);\n this.draw(this._context);\n }\n\n isStatic(): boolean {\n return this._circle.isStatic();\n }\n\n isMovingStatic(): boolean {\n return this._circle.isMovingStatic();\n }\n\n getMinMaxProjection(unitvector: Point): { min: number; max: number; } {\n return this._circle.getMinMaxProjection(unitvector);\n }\n\n getCollisionAxes(relativeBody: RigidBody): Point[] {\n return this._circle.getCollisionAxes(relativeBody);\n }\n\n applyForce(force: Point): void {\n this._circle.applyForce(force);\n }\n\n get AABB(): { min: Point; max: Point; } {\n return this._circle.AABB;\n }\n\n getMass(): number {\n return this._circle.mass;\n }\n\n applyForceInOrientation(force: Point): void {\n this._circle.applyForceInOrientation(force);\n }\n\n move(delta: Point): void {\n this._circle.move(delta);\n }\n\n getSignificantVertices(collisionNormal: Point): Point[] {\n return this._circle.getSignificantVertices(collisionNormal);\n }\n\n get center(): Point {\n return this._circle.center;\n }\n\n set center(dest: Point){\n this._circle.center = dest;\n }\n\n get linearVelocity(): Point {\n return this._circle.linearVelocity;\n }\n\n set linearVelocity(dest: Point){\n this._circle.linearVelocity = dest;\n }\n\n get orientationAngle(){\n return this._circle.orientationAngle;\n }\n\n significantVertex(collisionNormal: Point): Point {\n return this._circle.significantVertex(collisionNormal);\n }\n\n set angularVelocity(angularVelocity: number){\n this._circle.angularVelocity = angularVelocity;\n }\n\n get angularVelocity(): number{\n return this._circle.angularVelocity;\n }\n\n get mass(): number{\n return this._circle.mass;\n }\n\n getNormalOfSignificantFace(collisionNormal: Point): Point {\n return this._circle.getNormalOfSignificantFace(collisionNormal);\n }\n\n get staticFrictionCoeff(): number{\n return this._circle.staticFrictionCoeff;\n }\n\n set staticFrictionCoeff(coeff: number){\n this._circle.staticFrictionCoeff = coeff;\n }\n\n getAdjacentFaces(collisionNormal: Point): {startPoint: {coord: Point, index: number}, endPoint: {coord: Point, index: number}}[] {\n return this._circle.getAdjacentFaces(collisionNormal);\n }\n\n get momentOfInertia(): number {\n return this._circle.momentOfInertia;\n }\n\n // Sleeping methods\n setSleeping(sleeping: boolean): void {\n if (sleeping && !this.isSleeping) {\n this.isSleeping = true;\n this._circle.linearVelocity = { x: 0, y: 0 };\n this._circle.angularVelocity = 0;\n } else if (!sleeping && this.isSleeping) {\n this.isSleeping = false;\n this.timeAtRest = 0;\n }\n }\n\n updateSleeping(deltaTime: number): void {\n if (this._circle.isStatic() || this._circle.isMovingStatic()) return;\n\n const speed = PointCal.magnitude(this._circle.linearVelocity);\n const angularSpeed = Math.abs(this._circle.angularVelocity);\n\n if (speed < this.sleepThreshold && angularSpeed < this.sleepThreshold) {\n this.timeAtRest += deltaTime;\n if (this.timeAtRest >= this.sleepTime) {\n this.setSleeping(true);\n }\n } else {\n this.timeAtRest = 0;\n if (this.isSleeping) {\n this.setSleeping(false);\n }\n }\n }\n\n}\n\nexport class VisualPolygonBody implements VisualComponent, RigidBody {\n \n private _polygon: Polygon;\n private _context: CanvasRenderingContext2D;\n \n // Collision filtering\n public collisionFilter: CollisionFilter = { ...DEFAULT_COLLISION_FILTER };\n \n // Sleeping system\n public isSleeping: boolean = false;\n public sleepThreshold: number = 0.01;\n public sleepTime: number = 0.5;\n public timeAtRest: number = 0;\n\n constructor(center: Point = {x: 0, y: 0}, vertices: Point[], drawingContext: CanvasRenderingContext2D, _orientationAngle: number = 0, mass: number = 50, isStatic: boolean = false, frictionEnabled: boolean = true) {\n this._polygon = new Polygon(center, vertices, _orientationAngle, mass, isStatic, frictionEnabled);\n this._context = drawingContext;\n }\n\n draw(ctx: CanvasRenderingContext2D): void {\n ctx.beginPath();\n let vertices = this._polygon.getVerticesAbsCoord();\n ctx.moveTo(vertices[0].x, vertices[0].y);\n vertices.forEach(vertex => {\n ctx.lineTo(vertex.x, vertex.y);\n });\n ctx.lineTo(vertices[0].x, vertices[0].y);\n ctx.stroke();\n // ctx.beginPath();\n // ctx.rect(this._polygon.AABB.min.x, this._polygon.AABB.min.y, this._polygon.AABB.max.x - this._polygon.AABB.min.x, this._polygon.AABB.max.y - this._polygon.AABB.min.y);\n // ctx.stroke();\n }\n\n step(deltaTime: number): void {\n this._polygon.step(deltaTime);\n this.draw(this._context);\n }\n\n isStatic(): boolean {\n return this._polygon.isStatic();\n }\n\n isMovingStatic(): boolean {\n return this._polygon.isMovingStatic();\n }\n\n getMinMaxProjection(unitvector: Point): { min: number; max: number; } {\n return this._polygon.getMinMaxProjection(unitvector);\n }\n\n getCollisionAxes(relativeBody: RigidBody): Point[] {\n return this._polygon.getCollisionAxes(relativeBody);\n }\n\n applyForce(force: Point): void {\n this._polygon.applyForce(force);\n }\n\n applyForceInOrientation(force: Point): void {\n this._polygon.applyForceInOrientation(force);\n }\n\n setLinearVelocity(linearVelocity: Point): void {\n this._polygon.setLinearVelocity(linearVelocity);\n }\n\n move(delta: Point): void {\n this._polygon.move(delta);\n }\n\n get center(): Point {\n return this._polygon.center;\n }\n\n set center(dest: Point){\n this._polygon.center = dest;\n }\n\n get linearVelocity(): Point {\n return this._polygon.linearVelocity;\n }\n\n set linearVelocity(dest: Point){\n this._polygon.linearVelocity = dest;\n }\n\n get angularVelocity(): number{\n return this._polygon.angularVelocity;\n }\n\n set angularVelocity(angularVelocity: number){\n this._polygon.angularVelocity = angularVelocity;\n }\n\n get orientationAngle(): number{\n return this._polygon.orientationAngle;\n }\n\n significantVertex(collisionNormal: Point): Point {\n return this._polygon.significantVertex(collisionNormal);\n }\n\n getSignificantVertices(collisionNormal: Point): Point[] {\n return this._polygon.getSignificantVertices(collisionNormal);\n }\n\n get AABB(): {min: Point, max: Point}{\n return this._polygon.AABB;\n }\n\n get mass(): number{\n return this._polygon.mass;\n }\n \n get staticFrictionCoeff(): number{\n return this._polygon.staticFrictionCoeff;\n }\n\n set staticFrictionCoeff(coeff: number){\n this._polygon.staticFrictionCoeff = coeff;\n }\n\n get momentOfInertia(): number {\n return this._polygon.momentOfInertia;\n }\n\n getNormalOfSignificantFace(collisionNormal: Point): Point {\n return this._polygon.getNormalOfSignificantFace(collisionNormal);\n }\n\n getAdjacentFaces(collisionNormal: Point): {startPoint: {coord: Point, index: number}, endPoint: {coord: Point, index: number}}[] {\n return this._polygon.getAdjacentFaces(collisionNormal);\n }\n\n // Sleeping methods\n setSleeping(sleeping: boolean): void {\n if (sleeping && !this.isSleeping) {\n this.isSleeping = true;\n this._polygon.linearVelocity = { x: 0, y: 0 };\n this._polygon.angularVelocity = 0;\n } else if (!sleeping && this.isSleeping) {\n this.isSleeping = false;\n this.timeAtRest = 0;\n }\n }\n\n updateSleeping(deltaTime: number): void {\n if (this._polygon.isStatic() || this._polygon.isMovingStatic()) return;\n\n const speed = PointCal.magnitude(this._polygon.linearVelocity);\n const angularSpeed = Math.abs(this._polygon.angularVelocity);\n\n if (speed < this.sleepThreshold && angularSpeed < this.sleepThreshold) {\n this.timeAtRest += deltaTime;\n if (this.timeAtRest >= this.sleepTime) {\n this.setSleeping(true);\n }\n } else {\n this.timeAtRest = 0;\n if (this.isSleeping) {\n this.setSleeping(false);\n }\n }\n }\n}\n\nexport class Polygon extends BaseRigidBody {\n\n private vertices: Point[];\n private _momentOfInertia: number;\n\n constructor(center: Point = {x: 0, y: 0}, vertices: Point[], _orientationAngle: number = 0, mass: number = 50, isStatic: boolean = false, frictionEnabled: boolean = true) {\n super(center, _orientationAngle, mass, isStatic, frictionEnabled);\n this.vertices = vertices;\n this.step = this.step.bind(this);\n\n let numerator = this.vertices.reduce((acc, vertex, index) => {\n let nextPointIndex = index < this.vertices.length - 1 ? index + 1 : 0;\n let nextPoint = this.vertices[nextPointIndex];\n let crossProduct = PointCal.crossProduct(nextPoint, vertex);\n return acc + PointCal.magnitude(crossProduct) * (PointCal.dotProduct(vertex, vertex) + PointCal.dotProduct(vertex, nextPoint) + PointCal.dotProduct(nextPoint, nextPoint));\n }, 0);\n\n let denomiator = this.vertices.reduce((acc, vertex, index) => {\n return acc + PointCal.magnitude(PointCal.crossProduct(this.vertices[index < this.vertices.length - 1 ? index + 1 : 0], vertex));\n }, 0);\n\n \n this._momentOfInertia = this._mass * numerator / (6 * denomiator);\n }\n\n\n getVerticesAbsCoord(): Point[]{\n return this.vertices.map(vertex=>{\n return PointCal.addVector(this._center, PointCal.rotatePoint(vertex, this._orientationAngle));\n });\n }\n\n getCollisionAxes(relativeBody: RigidBody): Point[] {\n return this.getVerticesAbsCoord().map((vertex, index, absVertices)=>{\n let vector = PointCal.subVector(vertex, absVertices[absVertices.length - 1]);\n if (index > 0){\n vector = PointCal.subVector(vertex, absVertices[index - 1]); \n }\n return PointCal.unitVector(PointCal.rotatePoint(vector, Math.PI / 2));\n });\n }\n\n getMinMaxProjection(unitvector: Point): { min: number; max: number; } {\n let vertices = this.getVerticesAbsCoord();\n \n let projections = vertices.map( vertex => {\n return PointCal.dotProduct(vertex, unitvector);\n });\n\n \n return {min: Math.min(...projections), max: Math.max(...projections)};\n }\n\n get AABB(): { min: Point; max: Point; } {\n let points = this.getVerticesAbsCoord();\n let xCoords = points.map(vertex => vertex.x);\n let yCoords = points.map(vertex => vertex.y);\n return {min: {x: Math.min(...xCoords), y: Math.min(...yCoords)}, max: {x: Math.max(...xCoords), y: Math.max(...yCoords)}};\n }\n\n significantVertex(collisionNormal: Point): Point {\n let vertices = this.getVerticesAbsCoord();\n let verticesProjected = vertices.map(vertex => PointCal.dotProduct(vertex, collisionNormal));\n let maxIndex = verticesProjected.indexOf(Math.max(...verticesProjected));\n return vertices[maxIndex];\n }\n\n getSignificantVertices(collisionNormal: Point): Point[]{\n let vertices = this.getVerticesAbsCoord();\n let verticesProjected = vertices.map(vertex => PointCal.dotProduct(vertex, collisionNormal));\n let maxIndex = verticesProjected.indexOf(Math.max(...verticesProjected));\n const tipVertex = vertices[maxIndex];\n let prevPointIndex = maxIndex > 0 ? maxIndex - 1 : vertices.length - 1;\n let nextPointIndex = maxIndex < vertices.length - 1 ? maxIndex + 1 : 0;\n const prevPoint = vertices[prevPointIndex];\n const nextPoint = vertices[nextPointIndex];\n const prevPointProjected = PointCal.dotProduct(prevPoint, collisionNormal);\n const nextPointProjected = PointCal.dotProduct(nextPoint, collisionNormal);\n if (prevPointProjected > nextPointProjected) {\n return [prevPoint, tipVertex];\n } else {\n return [tipVertex, nextPoint];\n }\n }\n\n getNormalOfSignificantFace(collisionNormal: Point): Point{\n const vertices = this.getSignificantVertices(collisionNormal);\n const direction = PointCal.unitVectorFromA2B(vertices[0], vertices[1]);\n return PointCal.rotatePoint(direction, -Math.PI / 2);\n }\n\n getAdjacentFaces(collisionNormal: Point): {startPoint: {coord: Point, index: number}, endPoint: {coord: Point, index: number}}[]{\n let vertices = this.getVerticesAbsCoord();\n let verticesProjected = vertices.map(vertex => PointCal.dotProduct(vertex, collisionNormal));\n let maxIndex = verticesProjected.indexOf(Math.max(...verticesProjected));\n const tipVertex = vertices[maxIndex];\n let prevPointIndex = maxIndex > 0 ? maxIndex - 1 : vertices.length - 1;\n let nextPointIndex = maxIndex < vertices.length - 1 ? maxIndex + 1 : 0;\n const prevPoint = vertices[prevPointIndex];\n const nextPoint = vertices[nextPointIndex];\n const prevPointProjected = PointCal.dotProduct(prevPoint, collisionNormal);\n const nextPointProjected = PointCal.dotProduct(nextPoint, collisionNormal);\n const adjacentFaces: Point[] = [];\n const adjacentFacesWithIndex: {startPoint: {coord: Point, index: number}, endPoint: {coord: Point, index: number}}[] = [];\n if (prevPointProjected > nextPointProjected) {\n adjacentFaces.push(prevPoint, tipVertex);\n adjacentFacesWithIndex.push({startPoint: {coord: prevPoint, index: prevPointIndex}, endPoint: {coord: tipVertex, index: maxIndex}});\n\n // the nextface is the next face\n adjacentFacesWithIndex.unshift({startPoint: {coord: tipVertex, index: maxIndex}, endPoint: {coord: nextPoint, index: nextPointIndex}});\n // need to get the previous face of the previous face\n let prevPrevPointIndex = prevPointIndex > 0 ? prevPointIndex - 1 : vertices.length - 1;\n adjacentFacesWithIndex.unshift({startPoint: {coord: vertices[prevPrevPointIndex], index: prevPrevPointIndex}, endPoint: {coord: prevPoint, index: prevPointIndex}});\n } else {\n adjacentFaces.push(tipVertex, nextPoint);\n adjacentFacesWithIndex.push({startPoint: {coord: tipVertex, index: maxIndex}, endPoint: {coord: nextPoint, index: nextPointIndex}});\n\n // need to get the next face of the next face\n let nextNextPointIndex = nextPointIndex < vertices.length - 1 ? nextPointIndex + 1 : 0;\n adjacentFacesWithIndex.unshift({startPoint: {coord: nextPoint, index: nextPointIndex}, endPoint: {coord: vertices[nextNextPointIndex], index: nextNextPointIndex}})\n\n // the prevoius face is the previous face\n adjacentFacesWithIndex.unshift({startPoint: {coord: prevPoint, index: prevPointIndex}, endPoint: {coord: tipVertex, index: maxIndex}});\n }\n \n return adjacentFacesWithIndex;\n }\n\n get momentOfInertia(): number {\n return this._momentOfInertia;\n }\n\n}\n\nexport class Circle extends BaseRigidBody {\n\n private _radius: number;\n private _momentOfInertia: number;\n\n constructor(center: Point = {x: 0, y: 0}, radius: number, _orientationAngle: number = 0, mass: number = 50, isStatic: boolean = false, frictionEnabled: boolean = true) {\n super(center, _orientationAngle, mass, isStatic, frictionEnabled);\n this._radius = radius;\n this.step = this.step.bind(this);\n this._momentOfInertia = this._mass * this._radius * this._radius / 2;\n }\n\n getMinMaxProjection(unitvector: Point): { min: number; max: number; } {\n let PositiveFurthest = PointCal.addVector(this._center, PointCal.multiplyVectorByScalar(unitvector, this._radius));\n let NegativeFurthest = PointCal.addVector(this._center, PointCal.multiplyVectorByScalar(unitvector, -this._radius));\n return {min: PointCal.dotProduct(NegativeFurthest, unitvector), max: PointCal.dotProduct(PositiveFurthest, unitvector)};\n }\n\n getCollisionAxes(relativeBody: RigidBody): Point[] {\n return [PointCal.unitVector(PointCal.subVector(relativeBody.center, this._center))];\n }\n\n get AABB(): { min: Point; max: Point; } {\n return {min: PointCal.subVector(this._center, {x: this._radius, y: this._radius}), max: PointCal.addVector(this._center, {x: this._radius, y: this._radius})};\n }\n\n significantVertex(collisionNormal: Point): Point {\n return PointCal.addVector(this._center, PointCal.multiplyVectorByScalar(collisionNormal, this._radius));\n }\n\n get radius(): number {\n return this._radius;\n }\n\n getSignificantVertices(collisionNormal: Point): Point[]{\n return [PointCal.addVector(this._center, PointCal.multiplyVectorByScalar(collisionNormal, this._radius))];\n }\n\n getNormalOfSignificantFace(collisionNormal: Point): Point{\n return PointCal.unitVector(collisionNormal);\n }\n\n getAdjacentFaces(collisionNormal: Point): {startPoint: {coord: Point, index: number}, endPoint: {coord: Point, index: number}}[]{\n return [];\n }\n\n get momentOfInertia(): number {\n return this._momentOfInertia;\n }\n}\n",
6
+ "/**\n * Collision filtering configuration for rigid bodies.\n *\n * @remarks\n * Collision filters use a bitmask system to control which bodies can collide\n * with each other. This is useful for creating layers, groups, and special\n * collision rules in your physics simulation.\n *\n * ### How Filtering Works\n *\n * Two bodies A and B can collide if ALL of these conditions are met:\n * 1. `(A.category & B.mask) !== 0` - A's category matches B's mask\n * 2. `(B.category & A.mask) !== 0` - B's category matches A's mask\n * 3. Group rules are satisfied (see group field)\n *\n * @category Types\n */\nexport interface CollisionFilter {\n /**\n * What category this body belongs to (bitmask).\n *\n * @example\n * ```typescript\n * category: CollisionCategory.PLAYER // 0x0004\n * ```\n */\n category: number;\n\n /**\n * What categories this body can collide with (bitmask).\n *\n * @example\n * ```typescript\n * // Collide with everything except other players\n * mask: ~CollisionCategory.PLAYER & 0xFFFF\n * ```\n */\n mask: number;\n\n /**\n * Collision group for special rules.\n * - 0: No group (use category/mask rules)\n * - Positive: Bodies in same group ALWAYS collide\n * - Negative: Bodies in same group NEVER collide\n *\n * @example\n * ```typescript\n * // Ragdoll parts shouldn't collide with each other\n * group: -1\n *\n * // Team members always collide (for physics interactions)\n * group: 1\n * ```\n */\n group: number;\n}\n\n/**\n * Default collision filter that collides with everything.\n *\n * @remarks\n * Uses category 0x0001 and mask 0xFFFF, meaning it belongs to the first\n * category and can collide with all 16 categories.\n *\n * @category Collision\n */\nexport const DEFAULT_COLLISION_FILTER: CollisionFilter = {\n category: 0x0001,\n mask: 0xFFFF,\n group: 0\n};\n\n/**\n * Determines if two bodies can collide based on their collision filters.\n *\n * @remarks\n * Checks group rules first, then falls back to category/mask matching.\n * This is used internally by the physics engine during broad phase collision detection.\n *\n * @param filterA - Collision filter of first body\n * @param filterB - Collision filter of second body\n * @returns True if the bodies should collide\n *\n * @example\n * ```typescript\n * const player: CollisionFilter = {\n * category: CollisionCategory.PLAYER,\n * mask: 0xFFFF,\n * group: 0\n * };\n *\n * const enemy: CollisionFilter = {\n * category: CollisionCategory.ENEMY,\n * mask: CollisionCategory.PLAYER | CollisionCategory.STATIC,\n * group: 0\n * };\n *\n * console.log(canCollide(player, enemy)); // true\n * ```\n *\n * @category Collision\n */\nexport function canCollide(filterA: CollisionFilter, filterB: CollisionFilter): boolean {\n // If objects are in the same group\n if (filterA.group !== 0 && filterA.group === filterB.group) {\n return filterA.group > 0; // Positive groups collide, negative groups don't\n }\n\n // Check category-mask pairs\n return (filterA.category & filterB.mask) !== 0 && (filterB.category & filterA.mask) !== 0;\n}\n\n/**\n * Predefined collision categories for common game entities.\n *\n * @remarks\n * These are bitmask constants (powers of 2) that can be combined using bitwise OR.\n * You can define up to 16 categories using values from 0x0001 to 0x8000.\n *\n * @example\n * Using predefined categories\n * ```typescript\n * // Player collides with everything except other players\n * player.collisionFilter = {\n * category: CollisionCategory.PLAYER,\n * mask: ~CollisionCategory.PLAYER & 0xFFFF,\n * group: 0\n * };\n *\n * // Projectile only collides with enemies and static objects\n * projectile.collisionFilter = {\n * category: CollisionCategory.PROJECTILE,\n * mask: CollisionCategory.ENEMY | CollisionCategory.STATIC,\n * group: 0\n * };\n * ```\n *\n * @category Collision\n */\nexport const CollisionCategory = {\n STATIC: 0x0001, // Walls, floors, static objects\n DYNAMIC: 0x0002, // Moving objects \n PLAYER: 0x0004, // Player character\n ENEMY: 0x0008, // Enemy entities\n PROJECTILE: 0x0010, // Bullets, projectiles\n SENSOR: 0x0020, // Trigger zones, sensors\n PICKUP: 0x0040, // Items that can be collected\n PLATFORM: 0x0080, // One-way platforms\n} as const;",
7
+ "import { Point } from \"@ue-too/math\";\nimport { RigidBody } from \"./rigidbody\";\nimport { SpatialIndex, SpatialIndexObject } from \"./dynamic-tree\";\n\nexport class RectangleBound{\n private bottomLeft: Point;\n private width: number;\n private height: number;\n\n constructor(bottomLeft: Point, width: number, height: number){\n this.bottomLeft = bottomLeft;\n this.width = width;\n this.height = height;\n }\n\n getWidth(){\n return this.width;\n }\n\n getHeight(){\n return this.height;\n }\n\n getbottomLeft(){\n return this.bottomLeft;\n }\n}\n\nexport type QuadTreeObject = SpatialIndexObject;\n\n/**\n * QuadTree spatial indexing structure for efficient collision detection.\n * @category Spatial Indexing\n */\nexport class QuadTree<T extends QuadTreeObject> implements SpatialIndex<T> {\n private MAX_OBJECTS = 10; // per node\n private MAX_LEVELS = 5;\n\n private level: number;\n private objects: T[] = [];\n private nodes: (QuadTree<T> | undefined)[] = [];\n private bounds: RectangleBound;\n \n\n constructor(level: number, bounds: RectangleBound){\n this.level = level;\n this.objects = [];\n this.bounds = bounds;\n this.nodes = [undefined, undefined, undefined, undefined];\n }\n\n draw(context: CanvasRenderingContext2D){\n context.beginPath();\n context.rect(this.bounds.getbottomLeft().x, this.bounds.getbottomLeft().y, this.bounds.getWidth(), this.bounds.getHeight());\n context.stroke();\n // console.log(\"objects: \", this.objects.length, \"level: \", this.level);\n for(let index = 0; index < this.nodes.length; index++){\n let node = this.nodes[index];\n if(node != undefined){\n node.draw(context);\n }\n }\n }\n\n clear(){\n this.objects = [];\n for(let index = 0; index < this.nodes.length; index++){\n let node = this.nodes[index];\n if(node != undefined){\n node.clear();\n node = undefined;\n }\n }\n }\n\n split(){\n // console.log(\"split\");\n let subWidth = this.bounds.getWidth() / 2;\n let subHeight = this.bounds.getHeight() / 2;\n let bottomLeft = this.bounds.getbottomLeft();\n // bottom left is the first node and it goes clock wise \n this.nodes[0] = new QuadTree<T>(this.level + 1, new RectangleBound({x: bottomLeft.x, y: bottomLeft.y}, subWidth, subHeight));\n this.nodes[1] = new QuadTree<T>(this.level + 1, new RectangleBound({x: bottomLeft.x, y: bottomLeft.y + subHeight}, subWidth, subHeight));\n this.nodes[2] = new QuadTree<T>(this.level + 1, new RectangleBound({x: bottomLeft.x + subWidth, y: bottomLeft.y + subHeight}, subWidth, subHeight));\n this.nodes[3] = new QuadTree<T>(this.level + 1, new RectangleBound({x: bottomLeft.x + subWidth, y: bottomLeft.y}, subWidth, subHeight));\n }\n\n getIndex(vBody: T){\n let midPoint = {x: this.bounds.getbottomLeft().x + this.bounds.getWidth() / 2, y: this.bounds.getbottomLeft().y + this.bounds.getHeight() / 2};\n let points = vBody.AABB;\n let bottom = points.max.y < midPoint.y && points.min.y > this.bounds.getbottomLeft().y;\n let left = points.max.x < midPoint.x && points.min.x > this.bounds.getbottomLeft().x;\n let right = points.max.x > midPoint.x && points.min.x > midPoint.x;\n let top = points.max.y > midPoint.y && points.min.y > midPoint.y;\n // console.log(\"level\", this.level);\n if (bottom && left){\n return 0;\n } else if (bottom && right){\n return 3;\n } else if (top && left){\n return 1;\n } else if (top && right){\n return 2;\n }\n return -1;\n }\n\n insert(vBody: T){\n let node = this.nodes[0];\n if (node != undefined){\n let index = this.getIndex(vBody);\n\n if (index !== -1){\n node = this.nodes[index];\n node?.insert(vBody);\n return;\n }\n }\n\n this.objects.push(vBody);\n if(this.objects.length > this.MAX_OBJECTS && this.level < this.MAX_LEVELS){\n if (this.nodes[0] == null || this.nodes[0] == undefined){\n this.split();\n }\n let i = 0;\n while (i < this.objects.length){\n let index = this.getIndex(this.objects[i]);\n let node = this.nodes[index];\n if (index != -1 && node !== undefined){\n let vBody = this.objects[i];\n this.objects.splice(i, 1);\n node.insert(vBody);\n } else{\n i++;\n }\n }\n }\n }\n\n retrieve(vBody: T): T[]{\n let index = this.getIndex(vBody);\n let res = [];\n let node = this.nodes[index];\n if(index !== -1 && node !== undefined){\n res.push(...node.retrieve(vBody));\n }\n res.push(...this.objects);\n return res;\n }\n\n}",
8
+ "import { Point } from \"@ue-too/math\";\n\n/**\n * Object that can be indexed spatially via AABB.\n * @category Types\n */\nexport interface SpatialIndexObject {\n AABB: { min: Point, max: Point };\n}\n\n/**\n * Interface for spatial indexing data structures.\n * @category Types\n */\nexport interface SpatialIndex<T extends SpatialIndexObject> {\n clear(): void;\n insert(object: T): void;\n retrieve(object: T): T[];\n draw?(context: CanvasRenderingContext2D): void;\n}\n\ninterface AABB {\n min: Point;\n max: Point;\n}\n\nclass TreeNode<T extends SpatialIndexObject> {\n public parent: TreeNode<T> | null = null;\n public children: [TreeNode<T> | null, TreeNode<T> | null] = [null, null];\n public aabb: AABB = { min: { x: 0, y: 0 }, max: { x: 0, y: 0 } };\n public object: T | null = null;\n public height: number = 0;\n\n constructor(object?: T) {\n if (object) {\n this.setLeaf(object);\n }\n }\n\n isLeaf(): boolean {\n return this.children[0] === null;\n }\n\n setLeaf(object: T): void {\n this.object = object;\n this.updateAABB();\n this.children = [null, null];\n this.height = 0;\n }\n\n setBranch(child1: TreeNode<T>, child2: TreeNode<T>): void {\n child1.parent = this;\n child2.parent = this;\n this.children = [child1, child2];\n this.object = null;\n this.updateAABB();\n this.height = 1 + Math.max(child1.height, child2.height);\n }\n\n updateAABB(margin: number = 0.1): void {\n if (this.isLeaf() && this.object) {\n // Create \"fat\" AABB with margin for dynamic objects\n const obj = this.object.AABB;\n this.aabb = {\n min: { x: obj.min.x - margin, y: obj.min.y - margin },\n max: { x: obj.max.x + margin, y: obj.max.y + margin }\n };\n } else if (this.children[0] && this.children[1]) {\n // Union of children AABBs\n const aabb1 = this.children[0].aabb;\n const aabb2 = this.children[1].aabb;\n this.aabb = {\n min: {\n x: Math.min(aabb1.min.x, aabb2.min.x),\n y: Math.min(aabb1.min.y, aabb2.min.y)\n },\n max: {\n x: Math.max(aabb1.max.x, aabb2.max.x),\n y: Math.max(aabb1.max.y, aabb2.max.y)\n }\n };\n }\n }\n\n getSibling(): TreeNode<T> | null {\n if (!this.parent) return null;\n return this.parent.children[0] === this ? this.parent.children[1] : this.parent.children[0];\n }\n\n getBalance(): number {\n if (this.isLeaf()) return 0;\n const leftHeight = this.children[0] ? this.children[0].height : 0;\n const rightHeight = this.children[1] ? this.children[1].height : 0;\n return leftHeight - rightHeight;\n }\n}\n\n// Endpoint for Sweep and Prune algorithm\ninterface Endpoint<T> {\n value: number;\n isMin: boolean;\n object: T;\n id: number;\n}\n\n/**\n * Sweep and Prune (SAP) spatial indexing algorithm.\n * @category Spatial Indexing\n */\nexport class SweepAndPrune<T extends SpatialIndexObject> implements SpatialIndex<T> {\n private xEndpoints: Endpoint<T>[] = [];\n private objects: Map<T, { minEndpoint: Endpoint<T>, maxEndpoint: Endpoint<T> }> = new Map();\n private nextId: number = 0;\n\n clear(): void {\n this.xEndpoints = [];\n this.objects.clear();\n this.nextId = 0;\n }\n\n insert(object: T): void {\n const id = this.nextId++;\n \n const minEndpoint: Endpoint<T> = { value: object.AABB.min.x, isMin: true, object, id };\n const maxEndpoint: Endpoint<T> = { value: object.AABB.max.x, isMin: false, object, id };\n \n this.objects.set(object, { minEndpoint, maxEndpoint });\n\n // Use binary search + splice for O(n) insertion instead of O(n log n) sort\n this.insertEndpointSorted(minEndpoint);\n this.insertEndpointSorted(maxEndpoint);\n }\n\n update(object: T): void {\n const endpoints = this.objects.get(object);\n if (!endpoints) return;\n\n const newMinX = object.AABB.min.x;\n const newMaxX = object.AABB.max.x;\n\n // Update endpoint values and maintain sorted order\n if (endpoints.minEndpoint.value !== newMinX) {\n this.removeEndpoint(endpoints.minEndpoint);\n endpoints.minEndpoint.value = newMinX;\n this.insertEndpointSorted(endpoints.minEndpoint);\n }\n\n if (endpoints.maxEndpoint.value !== newMaxX) {\n this.removeEndpoint(endpoints.maxEndpoint);\n endpoints.maxEndpoint.value = newMaxX;\n this.insertEndpointSorted(endpoints.maxEndpoint);\n }\n }\n\n remove(object: T): void {\n const endpoints = this.objects.get(object);\n if (!endpoints) return;\n\n this.removeEndpoint(endpoints.minEndpoint);\n this.removeEndpoint(endpoints.maxEndpoint);\n this.objects.delete(object);\n }\n\n retrieve(queryObject: T): T[] {\n const result: T[] = [];\n const queryMin = queryObject.AABB.min.x;\n const queryMax = queryObject.AABB.max.x;\n\n // Find all objects that overlap on x-axis using sweep line\n for (const endpoint of this.xEndpoints) {\n if (endpoint.value > queryMax) break;\n \n if (endpoint.isMin && endpoint.object !== queryObject) {\n // Object starts - check if it overlaps with query on x-axis\n const objMax = this.objects.get(endpoint.object)?.maxEndpoint.value;\n if (objMax !== undefined && objMax >= queryMin) {\n // Check y-axis overlap\n if (this.aabbIntersects(endpoint.object.AABB, queryObject.AABB)) {\n result.push(endpoint.object);\n }\n }\n }\n }\n\n return result;\n }\n\n // Efficient method to find all collision pairs - the main strength of sweep-and-prune\n findAllOverlaps(): Array<{a: T, b: T}> {\n const pairs: Array<{a: T, b: T}> = [];\n const activeObjects = new Set<T>();\n \n for (const endpoint of this.xEndpoints) {\n if (endpoint.isMin) {\n // Check against all currently active objects\n for (const activeObj of activeObjects) {\n if (this.aabbIntersects(endpoint.object.AABB, activeObj.AABB)) {\n pairs.push({a: endpoint.object, b: activeObj});\n }\n }\n activeObjects.add(endpoint.object);\n } else {\n activeObjects.delete(endpoint.object);\n }\n }\n return pairs;\n }\n\n private insertEndpointSorted(endpoint: Endpoint<T>): void {\n // Binary search for insertion position\n let left = 0;\n let right = this.xEndpoints.length;\n \n while (left < right) {\n const mid = Math.floor((left + right) / 2);\n const midEndpoint = this.xEndpoints[mid];\n \n if (midEndpoint.value < endpoint.value || \n (midEndpoint.value === endpoint.value && midEndpoint.isMin && !endpoint.isMin)) {\n left = mid + 1;\n } else {\n right = mid;\n }\n }\n \n this.xEndpoints.splice(left, 0, endpoint);\n }\n\n private removeEndpoint(endpoint: Endpoint<T>): void {\n const index = this.xEndpoints.indexOf(endpoint);\n if (index !== -1) {\n this.xEndpoints.splice(index, 1);\n }\n }\n\n private aabbIntersects(aabb1: { min: Point, max: Point }, aabb2: { min: Point, max: Point }): boolean {\n return !(aabb1.max.x < aabb2.min.x || \n aabb1.min.x > aabb2.max.x || \n aabb1.max.y < aabb2.min.y || \n aabb1.min.y > aabb2.max.y);\n }\n\n // Enhanced visualization showing active sweep line and overlaps\n draw?(context: CanvasRenderingContext2D): void {\n context.strokeStyle = 'orange';\n context.lineWidth = 1;\n context.globalAlpha = 0.3;\n \n // Draw vertical lines at object boundaries\n for (const endpoint of this.xEndpoints) {\n context.beginPath();\n context.moveTo(endpoint.value, -1000);\n context.lineTo(endpoint.value, 1000);\n context.stroke();\n \n // Label min/max endpoints\n context.fillStyle = endpoint.isMin ? 'green' : 'red';\n context.fillText(endpoint.isMin ? 'min' : 'max', endpoint.value, -950);\n }\n \n context.globalAlpha = 1.0;\n }\n\n // Get statistics for performance monitoring\n getStats(): { endpointCount: number, objectCount: number } {\n return {\n endpointCount: this.xEndpoints.length,\n objectCount: this.objects.size\n };\n }\n}\n\n/**\n * Dynamic AABB tree for efficient spatial queries.\n * @category Spatial Indexing\n */\nexport class DynamicTree<T extends SpatialIndexObject> implements SpatialIndex<T> {\n private root: TreeNode<T> | null = null;\n private nodeCount: number = 0;\n private margin: number = 0.1; // Fat AABB margin\n\n clear(): void {\n this.root = null;\n this.nodeCount = 0;\n }\n\n insert(object: T): void {\n const node = new TreeNode(object);\n this.insertNode(node);\n }\n\n private insertNode(node: TreeNode<T>): void {\n this.nodeCount++;\n\n if (!this.root) {\n this.root = node;\n return;\n }\n\n // Find the best sibling for the new node\n let sibling = this.findBestSibling(node);\n \n // Create new parent\n const oldParent = sibling.parent;\n const newParent = new TreeNode<T>();\n newParent.parent = oldParent;\n newParent.setBranch(sibling, node);\n\n if (oldParent) {\n // Replace sibling with newParent in oldParent\n if (oldParent.children[0] === sibling) {\n oldParent.children[0] = newParent;\n } else {\n oldParent.children[1] = newParent;\n }\n } else {\n // sibling was root\n this.root = newParent;\n }\n\n // Walk back up the tree fixing heights and AABBs\n let ancestor = newParent.parent;\n while (ancestor) {\n ancestor.updateAABB(this.margin);\n ancestor.height = 1 + Math.max(\n ancestor.children[0] ? ancestor.children[0].height : 0,\n ancestor.children[1] ? ancestor.children[1].height : 0\n );\n\n // Balance the tree\n ancestor = this.balance(ancestor);\n ancestor = ancestor.parent;\n }\n }\n\n private findBestSibling(node: TreeNode<T>): TreeNode<T> {\n let current = this.root!;\n\n while (!current.isLeaf()) {\n const child1 = current.children[0]!;\n const child2 = current.children[1]!;\n\n const area = this.getArea(current.aabb);\n const combinedAABB = this.combineAABB(current.aabb, node.aabb);\n const combinedArea = this.getArea(combinedAABB);\n\n // Cost of creating new parent for this node and current\n const cost = 2.0 * combinedArea;\n\n // Minimum cost of pushing node further down the tree\n const inheritanceCost = 2.0 * (combinedArea - area);\n\n // Cost of descending into child1\n let cost1: number;\n const aabb1 = this.combineAABB(node.aabb, child1.aabb);\n if (child1.isLeaf()) {\n cost1 = this.getArea(aabb1) + inheritanceCost;\n } else {\n const oldArea = this.getArea(child1.aabb);\n const newArea = this.getArea(aabb1);\n cost1 = (newArea - oldArea) + inheritanceCost;\n }\n\n // Cost of descending into child2\n let cost2: number;\n const aabb2 = this.combineAABB(node.aabb, child2.aabb);\n if (child2.isLeaf()) {\n cost2 = this.getArea(aabb2) + inheritanceCost;\n } else {\n const oldArea = this.getArea(child2.aabb);\n const newArea = this.getArea(aabb2);\n cost2 = (newArea - oldArea) + inheritanceCost;\n }\n\n // Descend according to the minimum cost\n if (cost < cost1 && cost < cost2) {\n break;\n }\n\n // Descend\n current = cost1 < cost2 ? child1 : child2;\n }\n\n return current;\n }\n\n private balance(node: TreeNode<T>): TreeNode<T> {\n if (node.isLeaf()) {\n return node;\n }\n\n const balance = node.getBalance();\n\n // Rotate if imbalanced\n if (balance < -1) {\n return this.rotateLeft(node);\n } else if (balance > 1) {\n return this.rotateRight(node);\n }\n\n return node;\n }\n\n private rotateLeft(node: TreeNode<T>): TreeNode<T> {\n const child2 = node.children[1]!;\n const child2Child1 = child2.children[0]!;\n const child2Child2 = child2.children[1]!;\n\n // Swap\n child2.children[0] = node;\n child2.parent = node.parent;\n node.parent = child2;\n\n // Update parent\n if (child2.parent) {\n if (child2.parent.children[0] === node) {\n child2.parent.children[0] = child2;\n } else {\n child2.parent.children[1] = child2;\n }\n } else {\n this.root = child2;\n }\n\n // Rotate\n if (child2Child1.height > child2Child2.height) {\n child2.children[1] = child2Child1;\n node.children[1] = child2Child2;\n child2Child2.parent = node;\n node.updateAABB(this.margin);\n child2.updateAABB(this.margin);\n node.height = 1 + Math.max(node.children[0]!.height, node.children[1]!.height);\n child2.height = 1 + Math.max(node.height, child2Child1.height);\n } else {\n child2.children[1] = child2Child2;\n node.children[1] = child2Child1;\n child2Child1.parent = node;\n node.updateAABB(this.margin);\n child2.updateAABB(this.margin);\n node.height = 1 + Math.max(node.children[0]!.height, node.children[1]!.height);\n child2.height = 1 + Math.max(node.height, child2Child2.height);\n }\n\n return child2;\n }\n\n private rotateRight(node: TreeNode<T>): TreeNode<T> {\n const child1 = node.children[0]!;\n const child1Child1 = child1.children[0]!;\n const child1Child2 = child1.children[1]!;\n\n // Swap\n child1.children[1] = node;\n child1.parent = node.parent;\n node.parent = child1;\n\n // Update parent\n if (child1.parent) {\n if (child1.parent.children[0] === node) {\n child1.parent.children[0] = child1;\n } else {\n child1.parent.children[1] = child1;\n }\n } else {\n this.root = child1;\n }\n\n // Rotate\n if (child1Child1.height > child1Child2.height) {\n child1.children[0] = child1Child1;\n node.children[0] = child1Child2;\n child1Child2.parent = node;\n node.updateAABB(this.margin);\n child1.updateAABB(this.margin);\n node.height = 1 + Math.max(node.children[0]!.height, node.children[1]!.height);\n child1.height = 1 + Math.max(child1Child1.height, node.height);\n } else {\n child1.children[0] = child1Child2;\n node.children[0] = child1Child1;\n child1Child1.parent = node;\n node.updateAABB(this.margin);\n child1.updateAABB(this.margin);\n node.height = 1 + Math.max(node.children[0]!.height, node.children[1]!.height);\n child1.height = 1 + Math.max(child1Child2.height, node.height);\n }\n\n return child1;\n }\n\n retrieve(object: T): T[] {\n const result: T[] = [];\n if (!this.root) return result;\n\n const stack: TreeNode<T>[] = [this.root];\n\n while (stack.length > 0) {\n const node = stack.pop()!;\n\n if (this.aabbIntersects(node.aabb, object.AABB)) {\n if (node.isLeaf()) {\n if (node.object && node.object !== object) {\n result.push(node.object);\n }\n } else {\n if (node.children[0]) stack.push(node.children[0]);\n if (node.children[1]) stack.push(node.children[1]);\n }\n }\n }\n\n return result;\n }\n\n draw(context: CanvasRenderingContext2D): void {\n if (!this.root) return;\n this.drawNode(context, this.root, 0);\n }\n\n private drawNode(context: CanvasRenderingContext2D, node: TreeNode<T>, depth: number): void {\n const { min, max } = node.aabb;\n \n // Different colors for different depths\n const colors = ['red', 'blue', 'green', 'orange', 'purple', 'brown'];\n context.strokeStyle = colors[depth % colors.length];\n context.lineWidth = Math.max(1, 3 - depth);\n\n context.beginPath();\n context.rect(min.x, min.y, max.x - min.x, max.y - min.y);\n context.stroke();\n\n if (!node.isLeaf()) {\n if (node.children[0]) this.drawNode(context, node.children[0], depth + 1);\n if (node.children[1]) this.drawNode(context, node.children[1], depth + 1);\n }\n }\n\n private getArea(aabb: AABB): number {\n return (aabb.max.x - aabb.min.x) * (aabb.max.y - aabb.min.y);\n }\n\n private combineAABB(aabb1: AABB, aabb2: AABB): AABB {\n return {\n min: {\n x: Math.min(aabb1.min.x, aabb2.min.x),\n y: Math.min(aabb1.min.y, aabb2.min.y)\n },\n max: {\n x: Math.max(aabb1.max.x, aabb2.max.x),\n y: Math.max(aabb1.max.y, aabb2.max.y)\n }\n };\n }\n\n private aabbIntersects(aabb1: AABB, aabb2: AABB): boolean {\n return !(aabb1.max.x < aabb2.min.x || \n aabb1.min.x > aabb2.max.x || \n aabb1.max.y < aabb2.min.y || \n aabb1.min.y > aabb2.max.y);\n }\n\n // Getter for tree statistics\n getStats(): { nodeCount: number, height: number } {\n return {\n nodeCount: this.nodeCount,\n height: this.root ? this.root.height : 0\n };\n }\n}",
9
9
  "import { BaseRigidBody, RigidBody } from \"./rigidbody\";\nimport { PointCal, Point } from \"@ue-too/math\";\nimport { QuadTree } from \"./quadtree\";\nimport { canCollide } from \"./collision-filter\";\n\nexport function resolveCollision(bodyA: RigidBody, bodyB: RigidBody, normal: Point): void {\n // console.log(\"resolve\");\n if (bodyA.isStatic() && bodyB.isStatic()) {\n return;\n }\n let restitution = 0.4;\n let inverseMassA = bodyA.isStatic() || bodyA.isMovingStatic() ? 0 : 1 / bodyA.mass;\n let inverseMassB = bodyB.isStatic() || bodyB.isMovingStatic() ? 0 : 1 / bodyB.mass;\n // console.log(\"inverse mass a\", inverseMassA);\n // console.log(\"inverse mass b\", inverseMassB);\n\n let relativeVelocity = PointCal.subVector(bodyA.linearVelocity, bodyB.linearVelocity);\n // console.log(\"relative velocity: \", relativeVelocity);\n // console.log(\"linear velocity of a\", bodyA.getLinearVelocity());\n // console.log(\"linear veolcity of b\", bodyB.getLinearVelocity());\n let J = -(1 + restitution) * PointCal.dotProduct(relativeVelocity, normal);\n J /= inverseMassA + inverseMassB;\n\n let deltaVelocityA = PointCal.multiplyVectorByScalar(normal, J * inverseMassA);\n let deltaVelocityB = PointCal.multiplyVectorByScalar(normal, J * inverseMassB);\n // console.log(\"delta velocity A:\", deltaVelocityA);\n // console.log(\"delta velocity B:\", deltaVelocityB);\n\n bodyA.linearVelocity = PointCal.addVector(bodyA.linearVelocity, deltaVelocityA);\n bodyB.linearVelocity = PointCal.subVector(bodyB.linearVelocity, deltaVelocityB);\n}\n\nexport function resolveCollisionWithRotation(bodyA: RigidBody, bodyB: RigidBody, contactManifold: {normal: Point, contactPoints: Point[]}){\n // console.log(\"resolve\");\n if (bodyA.isStatic() && bodyB.isStatic()) {\n return;\n }\n\n let restitution = 0.4;\n let inverseMassA = bodyA.isStatic() || bodyA.isMovingStatic() ? 0 : 1 / bodyA.mass;\n let inverseMassB = bodyB.isStatic() || bodyB.isMovingStatic() ? 0 : 1 / bodyB.mass;\n\n let inverseMMOIA = bodyA.isStatic() || bodyA.isMovingStatic() ? 0 : 1 / bodyA.momentOfInertia;\n let inverseMMOIB = bodyB.isStatic() || bodyB.isMovingStatic() ? 0 : 1 / bodyB.momentOfInertia;\n\n const Js: Point[] = [];\n for(let index = 0; index < contactManifold.contactPoints.length; index++){\n const contactPoint = contactManifold.contactPoints[index];\n const rA = PointCal.subVector(contactPoint, bodyA.center);\n const rB = PointCal.subVector(contactPoint, bodyB.center);\n const rAPerpendicular = {x: -rA.y, y: rA.x};\n const rBPerpendicular = {x: -rB.y, y: rB.x}; \n\n const angularVelocityA = PointCal.multiplyVectorByScalar(rAPerpendicular, bodyA.angularVelocity);\n const angularVelocityB = PointCal.multiplyVectorByScalar(rBPerpendicular, bodyB.angularVelocity);\n\n // console.log(\"inverse mass a\", inverseMassA);\n // console.log(\"inverse mass b\", inverseMassB);\n\n let relativeVelocity = PointCal.subVector(PointCal.addVector(bodyA.linearVelocity, angularVelocityA), PointCal.addVector(bodyB.linearVelocity, angularVelocityB));\n // console.log(\"relative velocity: \", relativeVelocity);\n // console.log(\"linear velocity of a\", bodyA.getLinearVelocity());\n // console.log(\"linear veolcity of b\", bodyB.getLinearVelocity());\n let relativeVelocityNormal = PointCal.dotProduct(relativeVelocity, contactManifold.normal);\n const rAPerpendicularNormal = PointCal.dotProduct(rAPerpendicular, contactManifold.normal);\n const rBPerpendicularNormal = PointCal.dotProduct(rBPerpendicular, contactManifold.normal);\n \n const denominator = inverseMassA + inverseMassB + rAPerpendicularNormal * rAPerpendicularNormal * inverseMMOIA + rBPerpendicularNormal * rBPerpendicularNormal * inverseMMOIB;\n let J = -(1 + restitution) * relativeVelocityNormal;\n J /= denominator;\n\n J /= contactManifold.contactPoints.length;\n\n Js.push(PointCal.multiplyVectorByScalar(contactManifold.normal, J));\n }\n\n Js.forEach((impulse, index) => {\n let deltaVelocityA = PointCal.multiplyVectorByScalar(impulse, inverseMassA);\n let deltaVelocityB = PointCal.multiplyVectorByScalar(impulse, inverseMassB);\n\n bodyA.linearVelocity = PointCal.addVector(bodyA.linearVelocity, deltaVelocityA);\n let resA = PointCal.crossProduct(PointCal.subVector(contactManifold.contactPoints[index], bodyA.center), impulse).z;\n resA = resA == undefined ? 0 : resA;\n let resB = PointCal.crossProduct(PointCal.subVector(contactManifold.contactPoints[index], bodyB.center), impulse).z;\n resB = resB == undefined ? 0 : resB;\n bodyA.angularVelocity += resA * inverseMMOIA;\n bodyB.angularVelocity -= resB * inverseMMOIB;\n bodyB.linearVelocity = PointCal.subVector(bodyB.linearVelocity, deltaVelocityB);\n });\n}\n\nexport function aabbIntersects(aabbA: {min: Point, max: Point}, aabbB: {min: Point, max: Point}): boolean{\n if ((aabbA.min.x <= aabbB.max.x && aabbB.min.x <= aabbA.max.x) && (aabbA.min.y <= aabbB.max.y && aabbB.min.y <= aabbA.max.y)) {\n return true;\n }\n return false;\n}\n\nexport function intersects(bodyA: RigidBody, bodyB: RigidBody): {collision: boolean, depth?: number, normal?: Point}{\n let axis: Point[] = [];\n let bodyAAxes = bodyA.getCollisionAxes(bodyB);\n let bodyBAxes = bodyB.getCollisionAxes(bodyA);\n\n axis.push(...bodyAAxes);\n axis.push(...bodyBAxes);\n\n let collision = true;\n let minDepth = Number.MAX_VALUE;\n let minAxis = axis[0];\n\n axis.forEach(projAxis => {\n let bodyAInterval = bodyA.getMinMaxProjection(projAxis);\n let bodyBInterval = bodyB.getMinMaxProjection(projAxis);\n\n if (bodyAInterval.min >= bodyBInterval.max || bodyBInterval.min >= bodyAInterval.max) {\n collision = false;\n }else {\n let depth = Math.abs(Math.min(bodyAInterval.max, bodyBInterval.max) - Math.max(bodyBInterval.min, bodyAInterval.min));\n if (depth < minDepth) {\n minDepth = depth;\n minAxis = projAxis;\n if (bodyAInterval.max < bodyBInterval.max) {\n minAxis = PointCal.multiplyVectorByScalar(minAxis, -1);\n }\n }\n }\n });\n\n if (collision){\n return {collision: collision, depth: minDepth, normal: minAxis};\n }else {\n return {collision: false, depth: undefined, normal: undefined};\n }\n}\n\nexport function narrowPhaseWithRigidBody(bodies: RigidBody[], combinationsToCheck: {bodyA: RigidBody, bodyB: RigidBody}[], resolveCollisionFlag: boolean): Point[]{\n if (!resolveCollisionFlag) {\n return [];\n }\n const contactPoints: Point[] = [];\n combinationsToCheck.forEach(combination => {\n let bodyA = combination.bodyA;\n let bodyB = combination.bodyB;\n if (bodyA == bodyB) {\n // console.log(\"same body\");\n return;\n }\n let bodyAZ = bodyA.center.z == undefined ? 0 : bodyA.center.z;\n let bodyBZ = bodyB.center.z == undefined ? 0 : bodyB.center.z;\n if(Math.abs(bodyAZ - bodyBZ) > 0.5){\n // console.log(\"z-index difference is too large\");\n return;\n }\n let {collision, depth, normal: normalAxis} = intersects(bodyA, bodyB);\n if (collision && normalAxis !== undefined && depth !== undefined) {\n // the normal axis points in the direction that push bodyA away from bodyB\n \n let moveDisplacement = PointCal.multiplyVectorByScalar(normalAxis, depth / 2);\n let revMoveDisplacement = PointCal.multiplyVectorByScalar(normalAxis, -depth / 2);\n\n if (!bodyA.isStatic()) {\n bodyA.move(moveDisplacement);\n }\n if (!bodyB.isStatic()) {\n bodyB.move(revMoveDisplacement);\n }\n if (bodyA.isStatic()) {\n // bodyA.move(revMoveDisplacement);\n bodyB.move(revMoveDisplacement);\n }\n if (bodyB.isStatic()) {\n bodyA.move(moveDisplacement);\n // bodyB.move(moveDisplacement);\n }\n\n // finding the collision contact point(s)\n const bodyASigNormal = bodyA.getNormalOfSignificantFace(PointCal.multiplyVectorByScalar(normalAxis, -1));\n const bodyBSigNormal = bodyB.getNormalOfSignificantFace(normalAxis);\n const bodyASigVertices = bodyA.getSignificantVertices(PointCal.multiplyVectorByScalar(normalAxis, -1));\n const bodyBSigVertices = bodyB.getSignificantVertices(normalAxis);\n const bodyAParallelIndicator = Math.abs(PointCal.dotProduct(bodyASigNormal, PointCal.multiplyVectorByScalar(normalAxis, -1)));\n const bodyBParallelIndicator = Math.abs(PointCal.dotProduct(bodyBSigNormal, normalAxis));\n \n if (bodyBSigVertices.length == 1 || bodyASigVertices.length == 1){\n // one of the body is a circle\n // console.log(\"involving a circle\");\n if (bodyBSigVertices.length == 1){\n // bodyB is a circle\n // contact point is on the perimeter of the circle and the direction is the collision normal\n contactPoints.push(bodyBSigVertices[0]);\n } else {\n // bodyA is a circle\n // contact point is on the perimeter of the circle and the direction is the collision normal\n contactPoints.push(bodyASigVertices[0]);\n }\n }\n else if (bodyAParallelIndicator > bodyBParallelIndicator) {\n // bodyA has the normal that is the most parallel to the collision normal\n const adjacentFaces = bodyA.getAdjacentFaces(PointCal.multiplyVectorByScalar(normalAxis, -1));\n let faceToClip = [...bodyBSigVertices];\n for(let index = 0; index < adjacentFaces.length - 1; index++){\n let startPoint = adjacentFaces[index].startPoint.coord;\n let endPoint = adjacentFaces[index].endPoint.coord;\n let direction = PointCal.subVector(endPoint, startPoint);\n let sigStart = PointCal.subVector(faceToClip[0], startPoint);\n let sigEnd = PointCal.subVector(faceToClip[1], startPoint);\n let startInside = PointCal.angleFromA2B(direction, sigStart) >= 0;\n let endInside = PointCal.angleFromA2B(direction, sigEnd) >= 0;\n if ((startInside ? 1 : 0) ^ (endInside ? 1 : 0)){\n // one of the point is outside the face\n let intersectionPoint = PointCal.getLineIntersection(startPoint, endPoint, faceToClip[0], faceToClip[1]);\n if (intersectionPoint.intersects && intersectionPoint.intersection !== undefined){\n if(startInside){\n faceToClip[1] = intersectionPoint.intersection;\n } else {\n faceToClip[0] = intersectionPoint.intersection;\n }\n }\n }\n }\n const referenceFace = adjacentFaces[adjacentFaces.length - 1];\n let startPoint = referenceFace.startPoint.coord;\n let endPoint = referenceFace.endPoint.coord;\n let direction = PointCal.subVector(endPoint, startPoint);\n let sigStart = PointCal.subVector(faceToClip[0], startPoint);\n let sigEnd = PointCal.subVector(faceToClip[1], startPoint);\n let startInside = PointCal.angleFromA2B(direction, sigStart) >= 0;\n let endInside = PointCal.angleFromA2B(direction, sigEnd) >= 0;\n if (startInside){\n contactPoints.push(faceToClip[0]);\n }\n if (endInside){\n contactPoints.push(faceToClip[1]);\n }\n } else {\n // bodyB has the normal that is the most parallel to the collision normal\n const adjacentFaces = bodyB.getAdjacentFaces(normalAxis);\n let faceToClip = [...bodyASigVertices];\n if(faceToClip.length == 0){\n console.log(\"warning\");\n }\n let count = 0;\n for(let index = 0; index < adjacentFaces.length - 1; index++){\n let startPoint = adjacentFaces[index].startPoint.coord;\n let endPoint = adjacentFaces[index].endPoint.coord;\n let direction = PointCal.subVector(endPoint, startPoint);\n let sigStart = PointCal.subVector(faceToClip[0], startPoint);\n let sigEnd = PointCal.subVector(faceToClip[1], startPoint);\n let startInside = PointCal.angleFromA2B(direction, sigStart) >= 0;\n let endInside = PointCal.angleFromA2B(direction, sigEnd) >= 0;\n if ((startInside ? 1 : 0) ^ (endInside ? 1 : 0)){\n count += 1;\n // one of the point is outside the face\n let intersectionPoint = PointCal.getLineIntersection(startPoint, endPoint, faceToClip[0], faceToClip[1]);\n if (intersectionPoint.intersects && intersectionPoint.intersection !== undefined){\n if(startInside){\n faceToClip[1] = intersectionPoint.intersection;\n } else {\n faceToClip[0] = intersectionPoint.intersection;\n }\n }\n }\n }\n const referenceFace = adjacentFaces[adjacentFaces.length - 1];\n let startPoint = referenceFace.startPoint.coord;\n let endPoint = referenceFace.endPoint.coord;\n let direction = PointCal.subVector(endPoint, startPoint);\n let sigStart = PointCal.subVector(faceToClip[0], startPoint);\n let sigEnd = PointCal.subVector(faceToClip[1], startPoint);\n let startInside = PointCal.angleFromA2B(direction, sigStart) >= 0;\n let endInside = PointCal.angleFromA2B(direction, sigEnd) >= 0;\n if (startInside){\n contactPoints.push(faceToClip[0]);\n }\n if (endInside){\n contactPoints.push(faceToClip[1]);\n }\n }\n if (resolveCollisionFlag) {\n resolveCollisionWithRotation(bodyA, bodyB, {normal: normalAxis, contactPoints: contactPoints});\n // resolveCollision(bodyA, bodyB, normalAxis);\n }\n }\n });\n return contactPoints;\n}\n\nexport function narrowPhase(bodies: BaseRigidBody[], combinationsToCheck: {bodyAIndex: number, bodyBIndex: number}[], resolveCollisionFlag: boolean): void {\n if (!resolveCollisionFlag) {\n return;\n }\n combinationsToCheck.forEach(combination => {\n let bodyA = bodies[combination.bodyAIndex];\n let bodyB = bodies[combination.bodyBIndex];\n let {collision, depth, normal: normalAxis} = intersects(bodyA, bodyB);\n if (collision && normalAxis !== undefined && depth !== undefined) {\n // console.log(\"collision\");\n let moveDisplacement = PointCal.multiplyVectorByScalar(normalAxis, depth / 2);\n let revMoveDisplacement = PointCal.multiplyVectorByScalar(normalAxis, -depth / 2);\n\n if (!bodyA.isStatic()) {\n bodyA.move(moveDisplacement);\n }\n if (!bodyB.isStatic()) {\n bodyB.move(revMoveDisplacement);\n }\n if (bodyA.isStatic()) {\n // bodyA.move(revMoveDisplacement);\n bodyB.move(revMoveDisplacement);\n }\n if (bodyB.isStatic()) {\n bodyA.move(moveDisplacement);\n // bodyB.move(moveDisplacement);\n }\n\n if (resolveCollisionFlag) {\n resolveCollision(bodyA, bodyB, normalAxis);\n }\n\n }\n })\n}\n\nexport function broadPhaseWithRigidBodyReturned(quadTree: QuadTree<RigidBody>, bodies: RigidBody[]): {bodyA: RigidBody, bodyB: RigidBody}[]{\n let possibleCombi: {bodyA: RigidBody, bodyB: RigidBody}[] = [];\n for(let index = 0; index <= bodies.length - 1; index++){\n let objsToCheck = quadTree.retrieve(bodies[index]);\n for(let jindex = 0; jindex <= objsToCheck.length - 1; jindex++){\n let bodyA = bodies[index];\n let bodyB = objsToCheck[jindex];\n if (bodyA.isStatic() && bodyB.isStatic()){\n continue;\n }\n if(!aabbIntersects(bodyA.AABB, bodyB.AABB)){\n continue;\n }\n possibleCombi.push({bodyA: bodyA, bodyB: bodyB});\n }\n }\n return possibleCombi\n}\n\nexport function broadPhaseWithSpatialIndex(spatialIndex: import(\"./dynamic-tree\").SpatialIndex<RigidBody>, bodies: RigidBody[]): {bodyA: RigidBody, bodyB: RigidBody}[]{\n let possibleCombi: {bodyA: RigidBody, bodyB: RigidBody}[] = [];\n for(let index = 0; index <= bodies.length - 1; index++){\n let objsToCheck = spatialIndex.retrieve(bodies[index]);\n for(let jindex = 0; jindex <= objsToCheck.length - 1; jindex++){\n let bodyA = bodies[index];\n let bodyB = objsToCheck[jindex];\n if (bodyA.isStatic() && bodyB.isStatic()){\n continue;\n }\n if(!aabbIntersects(bodyA.AABB, bodyB.AABB)){\n continue;\n }\n possibleCombi.push({bodyA: bodyA, bodyB: bodyB});\n }\n }\n return possibleCombi\n}\n\nexport function broadPhase(quadTree: QuadTree<RigidBody>, bodies: BaseRigidBody[]): {bodyAIndex: number, bodyBIndex: number}[]{\n let possibleCombi: {bodyAIndex: number, bodyBIndex: number}[] = [];\n for(let index = 0; index <= bodies.length - 1; index++){\n let objsToCheck = quadTree.retrieve(bodies[index]);\n for(let jindex = 0; jindex <= objsToCheck.length - 1; jindex++){\n let bodyA = bodies[index];\n let bodyB = objsToCheck[jindex];\n if (bodyA.isStatic() && bodyB.isStatic()){\n continue;\n }\n if(!aabbIntersects(bodyA.AABB, bodyB.AABB)){\n continue;\n }\n possibleCombi.push({bodyAIndex: index, bodyBIndex: jindex});\n }\n }\n return possibleCombi\n}\n\n// Enhanced broadphase with collision filtering\nexport function broadPhaseWithSpatialIndexFiltered(spatialIndex: import(\"./dynamic-tree\").SpatialIndex<RigidBody>, bodies: RigidBody[]): {bodyA: RigidBody, bodyB: RigidBody}[]{\n let possibleCombi: {bodyA: RigidBody, bodyB: RigidBody}[] = [];\n for(let index = 0; index <= bodies.length - 1; index++){\n let objsToCheck = spatialIndex.retrieve(bodies[index]);\n for(let jindex = 0; jindex <= objsToCheck.length - 1; jindex++){\n let bodyA = bodies[index];\n let bodyB = objsToCheck[jindex];\n \n // Skip if both are static\n if (bodyA.isStatic() && bodyB.isStatic()){\n continue;\n }\n \n // Apply collision filtering\n if (!canCollide(bodyA.collisionFilter, bodyB.collisionFilter)) {\n continue;\n }\n \n // Basic AABB check\n if(!aabbIntersects(bodyA.AABB, bodyB.AABB)){\n continue;\n }\n \n possibleCombi.push({bodyA: bodyA, bodyB: bodyB});\n }\n }\n return possibleCombi;\n}\n\n// Enhanced narrow phase that returns collision data for pair management\nexport function narrowPhaseWithRigidBodyAndPairs(bodies: RigidBody[], combinationsToCheck: {bodyA: RigidBody, bodyB: RigidBody}[], resolveCollisionFlag: boolean): {\n contactPoints: Point[],\n collisions: {bodyA: RigidBody, bodyB: RigidBody, contactPoints: Point[], normal?: Point, depth?: number}[]\n} {\n const contactPoints: Point[] = [];\n const collisions: {bodyA: RigidBody, bodyB: RigidBody, contactPoints: Point[], normal?: Point, depth?: number}[] = [];\n\n combinationsToCheck.forEach(combination => {\n let bodyA = combination.bodyA;\n let bodyB = combination.bodyB;\n \n let {collision, depth, normal: normalAxis} = intersects(bodyA, bodyB);\n if (collision && normalAxis !== undefined && depth !== undefined) {\n // Calculate contact points (simplified version)\n const collisionContactPoints: Point[] = [];\n \n // For now, use a simple contact point calculation\n // This could be enhanced later with proper clipping algorithms\n const contactCenter = {\n x: (bodyA.center.x + bodyB.center.x) / 2,\n y: (bodyA.center.y + bodyB.center.y) / 2\n };\n collisionContactPoints.push(contactCenter);\n \n const collisionData = {\n bodyA,\n bodyB,\n contactPoints: collisionContactPoints,\n normal: normalAxis,\n depth: depth\n };\n \n collisions.push(collisionData);\n contactPoints.push(...collisionContactPoints);\n\n if (resolveCollisionFlag) {\n // Position correction\n let moveDisplacement = PointCal.multiplyVectorByScalar(normalAxis, depth / 2);\n let revMoveDisplacement = PointCal.multiplyVectorByScalar(normalAxis, -depth / 2);\n\n if (!bodyA.isStatic()) {\n bodyA.move(moveDisplacement);\n }\n if (!bodyB.isStatic()) {\n bodyB.move(revMoveDisplacement);\n }\n if (bodyA.isStatic()) {\n bodyB.move(revMoveDisplacement);\n }\n if (bodyB.isStatic()) {\n bodyA.move(moveDisplacement);\n }\n\n // Resolve collision with rotation\n resolveCollisionWithRotation(bodyA, bodyB, {normal: normalAxis, contactPoints: collisionContactPoints});\n }\n }\n });\n\n return { contactPoints, collisions };\n}\n",
10
- "import { RigidBody } from \"./rigidbody\";\nimport { Point } from \"@ue-too/math\";\n\nexport interface CollisionPair {\n bodyA: RigidBody;\n bodyB: RigidBody;\n id: string;\n isActive: boolean;\n contactPoints: Point[];\n normal?: Point;\n depth?: number;\n frameCreated: number;\n frameUpdated: number;\n}\n\nexport interface PairEvents {\n created: CollisionPair[];\n updated: CollisionPair[];\n removed: CollisionPair[];\n}\n\nexport class PairManager {\n private pairs = new Map<string, CollisionPair>();\n private frameNumber = 0;\n private maxPairAge = 10; // Remove inactive pairs after N frames\n\n constructor() {}\n\n // Generate unique ID for a pair\n private getPairId(bodyA: RigidBody, bodyB: RigidBody): string {\n const idA = this.getBodyId(bodyA);\n const idB = this.getBodyId(bodyB);\n // Ensure consistent ordering\n return idA < idB ? `${idA}:${idB}` : `${idB}:${idA}`;\n }\n\n private getBodyId(body: RigidBody): string {\n // Use object reference as unique ID\n return body.toString();\n }\n\n // Update pairs for current frame\n updatePairs(newCollisions: {bodyA: RigidBody, bodyB: RigidBody, contactPoints?: Point[], normal?: Point, depth?: number}[]): PairEvents {\n this.frameNumber++;\n \n const events: PairEvents = {\n created: [],\n updated: [],\n removed: []\n };\n\n // Mark all existing pairs as inactive for this frame\n this.pairs.forEach(pair => {\n pair.isActive = false;\n });\n\n // Process new collisions\n for (const collision of newCollisions) {\n const id = this.getPairId(collision.bodyA, collision.bodyB);\n const existingPair = this.pairs.get(id);\n\n if (existingPair) {\n // Update existing pair\n existingPair.isActive = true;\n existingPair.frameUpdated = this.frameNumber;\n existingPair.contactPoints = collision.contactPoints || [];\n existingPair.normal = collision.normal;\n existingPair.depth = collision.depth;\n events.updated.push(existingPair);\n } else {\n // Create new pair\n const newPair: CollisionPair = {\n bodyA: collision.bodyA,\n bodyB: collision.bodyB,\n id,\n isActive: true,\n contactPoints: collision.contactPoints || [],\n normal: collision.normal,\n depth: collision.depth,\n frameCreated: this.frameNumber,\n frameUpdated: this.frameNumber\n };\n this.pairs.set(id, newPair);\n events.created.push(newPair);\n }\n }\n\n // Remove old inactive pairs\n const pairsToRemove: string[] = [];\n this.pairs.forEach((pair, id) => {\n if (!pair.isActive && (this.frameNumber - pair.frameUpdated) > this.maxPairAge) {\n pairsToRemove.push(id);\n events.removed.push(pair);\n }\n });\n\n pairsToRemove.forEach(id => {\n this.pairs.delete(id);\n });\n\n return events;\n }\n\n // Get all active pairs\n getActivePairs(): CollisionPair[] {\n return Array.from(this.pairs.values()).filter(pair => pair.isActive);\n }\n\n // Get pair by bodies\n getPair(bodyA: RigidBody, bodyB: RigidBody): CollisionPair | undefined {\n const id = this.getPairId(bodyA, bodyB);\n return this.pairs.get(id);\n }\n\n // Clear all pairs\n clear(): void {\n this.pairs.clear();\n this.frameNumber = 0;\n }\n\n // Get statistics\n getStats() {\n return {\n totalPairs: this.pairs.size,\n activePairs: this.getActivePairs().length,\n frameNumber: this.frameNumber\n };\n }\n}",
11
- "import { RigidBody } from \"./rigidbody\";\nimport * as Collision from \"./collision\";\nimport { RectangleBound, QuadTree} from \"./quadtree\"\nimport { DynamicTree, SpatialIndex, SweepAndPrune } from \"./dynamic-tree\";\nimport { Point } from \"@ue-too/math\";\nimport { Constraint } from \"./constraint\";\nimport { PinJointConstraint } from \"./constraint\";\nimport { PairManager, PairEvents } from \"./pair-manager\";\nimport { canCollide } from \"./collision-filter\";\n\nexport type SpatialIndexType = 'quadtree' | 'dynamictree' | 'sap';\n\nexport class World {\n private rigidBodyList: RigidBody[];\n private rigidBodyMap: Map<string, RigidBody>;\n private _resolveCollision: boolean;\n private maxTransWidth: number;\n private maxTransHeight: number;\n private bound: RectangleBound;\n private spatialIndex: SpatialIndex<RigidBody>;\n private spatialIndexType: SpatialIndexType;\n private constraints: Constraint[];\n private pinJoints: PinJointConstraint[] = [];\n private pairManager: PairManager;\n private enableSleeping: boolean = true;\n _context: CanvasRenderingContext2D | null = null;\n\n constructor(maxTransWidth: number, maxTransHeight: number, spatialIndexType: SpatialIndexType = 'dynamictree'){\n this.maxTransHeight = maxTransHeight;\n this.maxTransWidth = maxTransWidth;\n this.spatialIndexType = spatialIndexType;\n this.bound = new RectangleBound({x: -this.maxTransWidth, y: -this.maxTransHeight}, 2 * this.maxTransWidth, 2 * this.maxTransHeight);\n \n // Initialize spatial index based on type\n if (spatialIndexType === 'dynamictree') {\n this.spatialIndex = new DynamicTree<RigidBody>();\n } else if (spatialIndexType === 'sap') {\n this.spatialIndex = new SweepAndPrune<RigidBody>();\n } else {\n this.spatialIndex = new QuadTree(0, this.bound);\n }\n \n this.rigidBodyList = [];\n this.rigidBodyMap = new Map<string, RigidBody>();\n this._resolveCollision = true;\n this.constraints = [];\n this.pairManager = new PairManager();\n }\n\n addRigidBody(ident: string, body: RigidBody): void{\n this.rigidBodyList.push(body);\n this.rigidBodyMap.set(ident, body);\n \n // Add to spatial index immediately for sweep-and-prune\n if (this.spatialIndexType === 'sap') {\n this.spatialIndex.insert(body);\n }\n }\n\n removeRigidBody(ident: string): void{\n if (this.rigidBodyMap.has(ident)) {\n const body = this.rigidBodyMap.get(ident);\n this.rigidBodyMap.delete(ident);\n \n // Remove from spatial index for sweep-and-prune\n if (body && this.spatialIndexType === 'sap' && this.spatialIndex instanceof SweepAndPrune) {\n (this.spatialIndex as SweepAndPrune<RigidBody>).remove(body);\n }\n \n // Remove from rigidBodyList as well\n const index = this.rigidBodyList.findIndex(b => b === body);\n if (index !== -1) {\n this.rigidBodyList.splice(index, 1);\n }\n }\n }\n\n step(deltaTime: number): void{\n // Update sleeping states first\n if (this.enableSleeping) {\n this.getRigidBodyList().forEach(rigidBody => {\n rigidBody.updateSleeping(deltaTime);\n });\n }\n\n if(this._resolveCollision){\n const contactPoints = this.resolveCollisionPhase();\n }\n // if(this._context != null){\n // this.spatialIndex.draw?.(this._context);\n // contactPoints.forEach((contactPoint) => {\n // if(this._context != null){\n // this._context.lineWidth = 1;\n // this._context.strokeStyle = \"red\";\n // }\n // this._context?.beginPath();\n // this._context?.arc(contactPoint.x, contactPoint.y, 3, 0, 2 * Math.PI);\n // this._context?.stroke();\n // });\n // }\n this.constraints.forEach(constraint => constraint.enforce(deltaTime));\n this.getRigidBodyList().forEach(rigidBody => {\n if (!rigidBody.isSleeping) {\n rigidBody.step(deltaTime);\n }\n });\n }\n\n resolveCollisionPhase(): Point[]{\n let rigidBodyList: RigidBody[] = [];\n \n // Use incremental updates for sweep-and-prune, full rebuild for others\n if (this.spatialIndexType === 'sap') {\n // For sweep-and-prune: use incremental updates for better performance\n this.rigidBodyMap.forEach((body) => {\n if (!this.enableSleeping || !body.isSleeping) {\n rigidBodyList.push(body);\n // Update existing objects in spatial index\n if (this.spatialIndex instanceof SweepAndPrune) {\n (this.spatialIndex as SweepAndPrune<RigidBody>).update(body);\n }\n }\n });\n } else {\n // For QuadTree and DynamicTree: rebuild each frame (existing behavior)\n this.spatialIndex.clear();\n this.rigidBodyMap.forEach((body) => {\n if (!this.enableSleeping || !body.isSleeping) {\n rigidBodyList.push(body);\n this.spatialIndex.insert(body);\n }\n });\n }\n \n // console.log(\"spatial index size: \", this.spatialIndex);\n let possibleCombinations = Collision.broadPhaseWithSpatialIndexFiltered(this.spatialIndex, rigidBodyList);\n let collisionResults = Collision.narrowPhaseWithRigidBodyAndPairs(rigidBodyList, possibleCombinations, this._resolveCollision);\n \n // Update pair manager with new collisions\n const pairEvents = this.pairManager.updatePairs(collisionResults.collisions);\n \n // Wake up bodies that start colliding\n if (this.enableSleeping) {\n pairEvents.created.forEach(pair => {\n if (pair.bodyA.isSleeping) pair.bodyA.setSleeping(false);\n if (pair.bodyB.isSleeping) pair.bodyB.setSleeping(false);\n });\n }\n \n return collisionResults.contactPoints;\n }\n\n get resolveCollision(): boolean{\n return this._resolveCollision;\n }\n\n set resolveCollision(resolveCollision: boolean){\n this._resolveCollision = resolveCollision;\n }\n\n getRigidBodyList(){\n let rigidBodyList:RigidBody[] = [];\n this.rigidBodyMap.forEach((body) => {\n rigidBodyList.push(body);\n })\n return rigidBodyList;\n }\n\n getRigidBodyMap(): Map<string, RigidBody>{\n return this.rigidBodyMap;\n }\n\n setMaxTransHeight(height: number){\n this.maxTransHeight = height;\n }\n\n setMaxTransWidth(width: number){\n this.maxTransWidth = width;\n }\n\n addConstraint(constraint: Constraint): void{\n this.constraints.push(constraint);\n }\n\n getConstraints(): Constraint[]{\n return this.constraints;\n }\n\n addPinJoint(bodyA: RigidBody, bodyB: RigidBody, anchorA: Point, anchorB: Point) {\n this.pinJoints.push({ bodyA, bodyB, anchorA, anchorB });\n }\n\n get currentSpatialIndexType(): SpatialIndexType {\n return this.spatialIndexType;\n }\n\n setSpatialIndexType(type: SpatialIndexType): void {\n if (type === this.spatialIndexType) return;\n \n this.spatialIndexType = type;\n if (type === 'dynamictree') {\n this.spatialIndex = new DynamicTree<RigidBody>();\n } else if (type === 'sap') {\n this.spatialIndex = new SweepAndPrune<RigidBody>();\n } else {\n this.spatialIndex = new QuadTree(0, this.bound);\n }\n }\n\n getSpatialIndexStats(): any {\n if (this.spatialIndex instanceof DynamicTree) {\n return (this.spatialIndex as DynamicTree<RigidBody>).getStats();\n } else if (this.spatialIndex instanceof SweepAndPrune) {\n return {\n type: this.spatialIndexType,\n ...(this.spatialIndex as SweepAndPrune<RigidBody>).getStats()\n };\n }\n return { type: this.spatialIndexType, objects: this.rigidBodyMap.size };\n }\n\n // Sleeping control\n get sleepingEnabled(): boolean {\n return this.enableSleeping;\n }\n\n set sleepingEnabled(enabled: boolean) {\n this.enableSleeping = enabled;\n if (!enabled) {\n // Wake up all sleeping bodies\n this.rigidBodyMap.forEach(body => {\n if (body.isSleeping) {\n body.setSleeping(false);\n }\n });\n }\n }\n\n // Pair manager access\n getPairManager(): PairManager {\n return this.pairManager;\n }\n\n // Get collision statistics\n getCollisionStats() {\n return {\n ...this.pairManager.getStats(),\n sleepingBodies: Array.from(this.rigidBodyMap.values()).filter(body => body.isSleeping).length,\n totalBodies: this.rigidBodyMap.size\n };\n }\n}\n",
12
- "import { Point, PointCal } from \"@ue-too/math\";\nimport { RigidBody } from \"./rigidbody\";\n\nexport interface Constraint {\n enforce(dt: number): void;\n}\n\nexport class FixedPinJoint implements Constraint {\n\n private anchorA: Point;\n private worldAnchorA: Point;\n private bodyA: RigidBody;\n\n constructor(bodyA: RigidBody, anchorA: Point, worldAnchorA: Point) {\n this.bodyA = bodyA;\n this.anchorA = anchorA;\n this.worldAnchorA = worldAnchorA;\n }\n\n enforce(dt: number): void {\n this.solveWorldPinJointConstraint(dt);\n }\n\n solveWorldPinJointConstraint(dt: number) {\n const body = this.bodyA;\n const localAnchor = this.anchorA;\n const worldAnchor = this.worldAnchorA;\n\n // Transform local anchor point to world space\n const worldAnchorOnBody = PointCal.addVector(body.center, PointCal.rotatePoint(localAnchor, body.orientationAngle));\n\n // Calculate the difference between the anchor points\n const diff = PointCal.subVector(worldAnchorOnBody, worldAnchor);\n\n // Calculate the relative velocity of the anchor point\n const r = PointCal.subVector(worldAnchorOnBody, body.center);\n const velocity = PointCal.addVector(\n body.linearVelocity,\n PointCal.crossProduct({x: 0, y: 0, z: body.angularVelocity}, r)\n );\n\n // Calculate the mass matrix\n const invMass = body.isStatic() ? 0 : 1 / body.mass;\n const invI = body.isStatic() ? 0 : 1 / body.momentOfInertia;\n\n const K = {\n x: invMass + invI * r.y * r.y,\n y: invMass + invI * r.x * r.x,\n xy: -invI * r.x * r.y\n };\n\n // Calculate the impulse\n const baumgarte = 1; // Baumgarte stabilization factor\n const impulse = {\n x: -K.x * diff.x - K.xy * diff.y - baumgarte * diff.x / dt - velocity.x,\n y: -K.xy * diff.x - K.y * diff.y - baumgarte * diff.y / dt - velocity.y\n };\n\n // Apply the impulse\n if (!body.isStatic()) {\n body.linearVelocity.x += invMass * impulse.x;\n body.linearVelocity.y += invMass * impulse.y;\n body.angularVelocity += invI * (r.x * impulse.y - r.y * impulse.x);\n }\n }\n}\n\nexport class PinJoint implements Constraint {\n\n private anchorA: Point;\n private anchorB: Point;\n private bodyA: RigidBody;\n private bodyB: RigidBody;\n\n constructor(bodyA: RigidBody, bodyB: RigidBody, anchorA: Point, anchorB: Point) {\n this.bodyA = bodyA;\n this.bodyB = bodyB;\n this.anchorA = anchorA;\n this.anchorB = anchorB;\n }\n\n enforce(dt: number): void {\n this.solvePinJointConstraint(dt);\n }\n\n solvePinJointConstraint(dt: number) {\n const bodyA = this.bodyA;\n const bodyB = this.bodyB;\n const anchorA = this.anchorA;\n const anchorB = this.anchorB;\n\n // Transform local anchor points to world space\n const worldAnchorA = PointCal.addVector(bodyA.center, PointCal.rotatePoint(anchorA, bodyA.orientationAngle));\n const worldAnchorB = PointCal.addVector(bodyB.center, PointCal.rotatePoint(anchorB, bodyB.orientationAngle));\n \n // Calculate the difference between the two anchor points in world space\n const diff = PointCal.subVector(worldAnchorB, worldAnchorA);\n \n // Calculate the relative velocity of the anchor points\n const rA = PointCal.subVector(worldAnchorA, bodyA.center);\n const rB = PointCal.subVector(worldAnchorB, bodyB.center);\n const relativeVelocity = PointCal.subVector(\n PointCal.addVector(bodyB.linearVelocity, PointCal.crossProduct({x: 0, y: 0, z: bodyB.angularVelocity}, rB)),\n PointCal.addVector(bodyA.linearVelocity, PointCal.crossProduct({x: 0, y: 0, z: bodyA.angularVelocity}, rA))\n );\n \n // Calculate the mass matrix\n const invMassA = bodyA.isStatic() ? 0 : 1 / bodyA.mass;\n const invMassB = bodyB.isStatic() ? 0 : 1 / bodyB.mass;\n const invIA = bodyA.isStatic() ? 0 : 1 / bodyA.momentOfInertia;\n const invIB = bodyB.isStatic() ? 0 : 1 / bodyB.momentOfInertia;\n \n const K = {\n x: invMassA + invMassB + invIA * rA.y * rA.y + invIB * rB.y * rB.y,\n y: invMassA + invMassB + invIA * rA.x * rA.x + invIB * rB.x * rB.x,\n xy: -invIA * rA.x * rA.y - invIB * rB.x * rB.y\n };\n \n // Calculate the impulse\n const baumgarte = 1; // Baumgarte stabilization factor\n const impulse = {\n x: -K.x * diff.x - K.xy * diff.y - baumgarte * diff.x / dt - relativeVelocity.x,\n y: -K.xy * diff.x - K.y * diff.y - baumgarte * diff.y / dt - relativeVelocity.y\n };\n \n // Apply the impulse\n if (!bodyA.isStatic()) {\n bodyA.linearVelocity.x -= invMassA * impulse.x;\n bodyA.linearVelocity.y -= invMassA * impulse.y;\n bodyA.angularVelocity -= invIA * (rA.x * impulse.y - rA.y * impulse.x);\n }\n \n if (!bodyB.isStatic()) {\n bodyB.linearVelocity.x += invMassB * impulse.x;\n bodyB.linearVelocity.y += invMassB * impulse.y;\n bodyB.angularVelocity += invIB * (rB.x * impulse.y - rB.y * impulse.x);\n }\n }\n\n}\n\nexport interface PinJointConstraint {\n bodyA: RigidBody;\n bodyB: RigidBody;\n anchorA: Point; // Local anchor point for bodyA\n anchorB: Point; // Local anchor point for bodyB\n}\n\nexport function solvePinJointConstraint(constraint: PinJointConstraint, dt: number) {\n const { bodyA, bodyB, anchorA, anchorB } = constraint;\n\n // Transform local anchor points to world space\n const worldAnchorA = PointCal.addVector(bodyA.center, PointCal.rotatePoint(anchorA, bodyA.orientationAngle));\n const worldAnchorB = PointCal.addVector(bodyB.center, PointCal.rotatePoint(anchorB, bodyB.orientationAngle));\n\n // Calculate the difference between the two anchor points in world space\n const diff = PointCal.subVector(worldAnchorB, worldAnchorA);\n\n // Calculate the relative velocity of the anchor points\n const rA = PointCal.subVector(worldAnchorA, bodyA.center);\n const rB = PointCal.subVector(worldAnchorB, bodyB.center);\n const relativeVelocity = PointCal.subVector(\n PointCal.addVector(bodyB.linearVelocity, PointCal.crossProduct({x: 0, y: 0, z: bodyB.angularVelocity}, rB)),\n PointCal.addVector(bodyA.linearVelocity, PointCal.crossProduct({x: 0, y: 0, z: bodyA.angularVelocity}, rA))\n );\n\n // Calculate the mass matrix\n const invMassA = bodyA.isStatic() ? 0 : 1 / bodyA.mass;\n const invMassB = bodyB.isStatic() ? 0 : 1 / bodyB.mass;\n const invIA = bodyA.isStatic() ? 0 : 1 / bodyA.momentOfInertia;\n const invIB = bodyB.isStatic() ? 0 : 1 / bodyB.momentOfInertia;\n\n const K = {\n x: invMassA + invMassB + invIA * rA.y * rA.y + invIB * rB.y * rB.y,\n y: invMassA + invMassB + invIA * rA.x * rA.x + invIB * rB.x * rB.x,\n xy: -invIA * rA.x * rA.y - invIB * rB.x * rB.y\n };\n\n // Calculate the impulse\n const baumgarte = 0.5; // Baumgarte stabilization factor\n const impulse = {\n x: -K.x * diff.x - K.xy * diff.y - baumgarte * diff.x / dt - relativeVelocity.x,\n y: -K.xy * diff.x - K.y * diff.y - baumgarte * diff.y / dt - relativeVelocity.y\n };\n\n // Apply the impulse\n if (!bodyA.isStatic()) {\n bodyA.linearVelocity.x -= invMassA * impulse.x;\n bodyA.linearVelocity.y -= invMassA * impulse.y;\n bodyA.angularVelocity -= invIA * (rA.x * impulse.y - rA.y * impulse.x);\n }\n\n if (!bodyB.isStatic()) {\n bodyB.linearVelocity.x += invMassB * impulse.x;\n bodyB.linearVelocity.y += invMassB * impulse.y;\n bodyB.angularVelocity += invIB * (rB.x * impulse.y - rB.y * impulse.x);\n }\n}\n\nexport interface WorldPinJointConstraint {\n body: RigidBody;\n localAnchor: Point; // Anchor point in body's local space\n worldAnchor: Point; // Fixed point in world space\n}\n\nexport function solveWorldPinJointConstraint(constraint: WorldPinJointConstraint, dt: number) {\n const { body, localAnchor, worldAnchor } = constraint;\n\n // Transform local anchor point to world space\n const worldAnchorOnBody = PointCal.addVector(body.center, PointCal.rotatePoint(localAnchor, body.orientationAngle));\n\n // Calculate the difference between the anchor points\n const diff = PointCal.subVector(worldAnchorOnBody, worldAnchor);\n\n // Calculate the relative velocity of the anchor point\n const r = PointCal.subVector(worldAnchorOnBody, body.center);\n const velocity = PointCal.addVector(\n body.linearVelocity,\n PointCal.crossProduct({x: 0, y: 0, z: body.angularVelocity}, r)\n );\n\n // Calculate the mass matrix\n const invMass = body.isStatic() ? 0 : 1 / body.mass;\n const invI = body.isStatic() ? 0 : 1 / body.momentOfInertia;\n\n const K = {\n x: invMass + invI * r.y * r.y,\n y: invMass + invI * r.x * r.x,\n xy: -invI * r.x * r.y\n };\n\n // Calculate the impulse\n const baumgarte = 0.2; // Baumgarte stabilization factor\n const impulse = {\n x: -K.x * diff.x - K.xy * diff.y - baumgarte * diff.x / dt - velocity.x,\n y: -K.xy * diff.x - K.y * diff.y - baumgarte * diff.y / dt - velocity.y\n };\n\n // Apply the impulse\n if (!body.isStatic()) {\n body.linearVelocity.x += invMass * impulse.x;\n body.linearVelocity.y += invMass * impulse.y;\n body.angularVelocity += invI * (r.x * impulse.y - r.y * impulse.x);\n }\n}\n"
10
+ "import { RigidBody } from \"./rigidbody\";\nimport { Point } from \"@ue-too/math\";\n\n/**\n * Represents a collision pair between two bodies.\n *\n * @remarks\n * Tracks collision information across multiple frames, enabling\n * detection of collision start, update, and end events.\n *\n * @category Collision\n */\nexport interface CollisionPair {\n bodyA: RigidBody;\n bodyB: RigidBody;\n id: string;\n isActive: boolean;\n contactPoints: Point[];\n normal?: Point;\n depth?: number;\n frameCreated: number;\n frameUpdated: number;\n}\n\nexport interface PairEvents {\n created: CollisionPair[];\n updated: CollisionPair[];\n removed: CollisionPair[];\n}\n\n/**\n * Manages collision pairs across frames.\n *\n * @remarks\n * Tracks which bodies are colliding and for how long, enabling\n * collision lifecycle events (start, update, end). This is useful for\n * game logic like damage on collision start or triggers.\n *\n * Automatically cleans up old inactive pairs to prevent memory leaks.\n *\n * @example\n * Using collision events\n * ```typescript\n * const pairManager = world.getPairManager();\n *\n * world.step(dt);\n *\n * const events = pairManager.getActivePairs();\n * events.forEach(pair => {\n * if (pair.frameCreated === world.currentFrame) {\n * console.log('Collision started!');\n * }\n * });\n * ```\n *\n * @category Collision\n */\nexport class PairManager {\n private pairs = new Map<string, CollisionPair>();\n private frameNumber = 0;\n private maxPairAge = 10; // Remove inactive pairs after N frames\n\n constructor() {}\n\n // Generate unique ID for a pair\n private getPairId(bodyA: RigidBody, bodyB: RigidBody): string {\n const idA = this.getBodyId(bodyA);\n const idB = this.getBodyId(bodyB);\n // Ensure consistent ordering\n return idA < idB ? `${idA}:${idB}` : `${idB}:${idA}`;\n }\n\n private getBodyId(body: RigidBody): string {\n // Use object reference as unique ID\n return body.toString();\n }\n\n // Update pairs for current frame\n updatePairs(newCollisions: {bodyA: RigidBody, bodyB: RigidBody, contactPoints?: Point[], normal?: Point, depth?: number}[]): PairEvents {\n this.frameNumber++;\n \n const events: PairEvents = {\n created: [],\n updated: [],\n removed: []\n };\n\n // Mark all existing pairs as inactive for this frame\n this.pairs.forEach(pair => {\n pair.isActive = false;\n });\n\n // Process new collisions\n for (const collision of newCollisions) {\n const id = this.getPairId(collision.bodyA, collision.bodyB);\n const existingPair = this.pairs.get(id);\n\n if (existingPair) {\n // Update existing pair\n existingPair.isActive = true;\n existingPair.frameUpdated = this.frameNumber;\n existingPair.contactPoints = collision.contactPoints || [];\n existingPair.normal = collision.normal;\n existingPair.depth = collision.depth;\n events.updated.push(existingPair);\n } else {\n // Create new pair\n const newPair: CollisionPair = {\n bodyA: collision.bodyA,\n bodyB: collision.bodyB,\n id,\n isActive: true,\n contactPoints: collision.contactPoints || [],\n normal: collision.normal,\n depth: collision.depth,\n frameCreated: this.frameNumber,\n frameUpdated: this.frameNumber\n };\n this.pairs.set(id, newPair);\n events.created.push(newPair);\n }\n }\n\n // Remove old inactive pairs\n const pairsToRemove: string[] = [];\n this.pairs.forEach((pair, id) => {\n if (!pair.isActive && (this.frameNumber - pair.frameUpdated) > this.maxPairAge) {\n pairsToRemove.push(id);\n events.removed.push(pair);\n }\n });\n\n pairsToRemove.forEach(id => {\n this.pairs.delete(id);\n });\n\n return events;\n }\n\n // Get all active pairs\n getActivePairs(): CollisionPair[] {\n return Array.from(this.pairs.values()).filter(pair => pair.isActive);\n }\n\n // Get pair by bodies\n getPair(bodyA: RigidBody, bodyB: RigidBody): CollisionPair | undefined {\n const id = this.getPairId(bodyA, bodyB);\n return this.pairs.get(id);\n }\n\n // Clear all pairs\n clear(): void {\n this.pairs.clear();\n this.frameNumber = 0;\n }\n\n // Get statistics\n getStats() {\n return {\n totalPairs: this.pairs.size,\n activePairs: this.getActivePairs().length,\n frameNumber: this.frameNumber\n };\n }\n}",
11
+ "import { RigidBody } from \"./rigidbody\";\nimport * as Collision from \"./collision\";\nimport { RectangleBound, QuadTree} from \"./quadtree\"\nimport { DynamicTree, SpatialIndex, SweepAndPrune } from \"./dynamic-tree\";\nimport { Point } from \"@ue-too/math\";\nimport { Constraint } from \"./constraint\";\nimport { PinJointConstraint } from \"./constraint\";\nimport { PairManager, PairEvents } from \"./pair-manager\";\nimport { canCollide } from \"./collision-filter\";\n\n/**\n * Spatial indexing algorithm types.\n *\n * @remarks\n * Different algorithms have different performance characteristics:\n * - **quadtree**: Best for static or mostly-static worlds\n * - **dynamictree**: Good balance for mixed static/dynamic\n * - **sap**: Best for many dynamic bodies (sweep-and-prune)\n *\n * @category Core\n */\nexport type SpatialIndexType = 'quadtree' | 'dynamictree' | 'sap';\n\n/**\n * Main physics world managing rigid body simulation.\n *\n * @remarks\n * The World class is the main entry point for physics simulation. It manages\n * all rigid bodies, runs collision detection and response, enforces constraints,\n * and provides performance optimizations like sleeping and spatial indexing.\n *\n * ### Simulation Loop\n *\n * Call `world.step(deltaTime)` each frame to advance the simulation. This:\n * 1. Updates sleeping states\n * 2. Detects collisions (broad and narrow phase)\n * 3. Resolves collisions with impulses\n * 4. Enforces constraints\n * 5. Updates body positions and velocities\n *\n * ### Performance Tuning\n *\n * - Choose appropriate spatial index for your use case\n * - Enable sleeping for better performance with many bodies\n * - Use collision filtering to reduce collision checks\n *\n * @example\n * Basic setup\n * ```typescript\n * const world = new World(2000, 2000, 'dynamictree');\n *\n * // Add bodies\n * const ball = new Circle({ x: 0, y: 100 }, 20, 0, 10, false);\n * world.addRigidBody('ball', ball);\n *\n * // Simulation loop\n * function update(dt: number) {\n * world.step(dt);\n * }\n * ```\n *\n * @category Core\n */\nexport class World {\n private rigidBodyList: RigidBody[];\n private rigidBodyMap: Map<string, RigidBody>;\n private _resolveCollision: boolean;\n private maxTransWidth: number;\n private maxTransHeight: number;\n private bound: RectangleBound;\n private spatialIndex: SpatialIndex<RigidBody>;\n private spatialIndexType: SpatialIndexType;\n private constraints: Constraint[];\n private pinJoints: PinJointConstraint[] = [];\n private pairManager: PairManager;\n private enableSleeping: boolean = true;\n _context: CanvasRenderingContext2D | null = null;\n\n constructor(maxTransWidth: number, maxTransHeight: number, spatialIndexType: SpatialIndexType = 'dynamictree'){\n this.maxTransHeight = maxTransHeight;\n this.maxTransWidth = maxTransWidth;\n this.spatialIndexType = spatialIndexType;\n this.bound = new RectangleBound({x: -this.maxTransWidth, y: -this.maxTransHeight}, 2 * this.maxTransWidth, 2 * this.maxTransHeight);\n \n // Initialize spatial index based on type\n if (spatialIndexType === 'dynamictree') {\n this.spatialIndex = new DynamicTree<RigidBody>();\n } else if (spatialIndexType === 'sap') {\n this.spatialIndex = new SweepAndPrune<RigidBody>();\n } else {\n this.spatialIndex = new QuadTree(0, this.bound);\n }\n \n this.rigidBodyList = [];\n this.rigidBodyMap = new Map<string, RigidBody>();\n this._resolveCollision = true;\n this.constraints = [];\n this.pairManager = new PairManager();\n }\n\n addRigidBody(ident: string, body: RigidBody): void{\n this.rigidBodyList.push(body);\n this.rigidBodyMap.set(ident, body);\n \n // Add to spatial index immediately for sweep-and-prune\n if (this.spatialIndexType === 'sap') {\n this.spatialIndex.insert(body);\n }\n }\n\n removeRigidBody(ident: string): void{\n if (this.rigidBodyMap.has(ident)) {\n const body = this.rigidBodyMap.get(ident);\n this.rigidBodyMap.delete(ident);\n \n // Remove from spatial index for sweep-and-prune\n if (body && this.spatialIndexType === 'sap' && this.spatialIndex instanceof SweepAndPrune) {\n (this.spatialIndex as SweepAndPrune<RigidBody>).remove(body);\n }\n \n // Remove from rigidBodyList as well\n const index = this.rigidBodyList.findIndex(b => b === body);\n if (index !== -1) {\n this.rigidBodyList.splice(index, 1);\n }\n }\n }\n\n step(deltaTime: number): void{\n // Update sleeping states first\n if (this.enableSleeping) {\n this.getRigidBodyList().forEach(rigidBody => {\n rigidBody.updateSleeping(deltaTime);\n });\n }\n\n if(this._resolveCollision){\n const contactPoints = this.resolveCollisionPhase();\n }\n // if(this._context != null){\n // this.spatialIndex.draw?.(this._context);\n // contactPoints.forEach((contactPoint) => {\n // if(this._context != null){\n // this._context.lineWidth = 1;\n // this._context.strokeStyle = \"red\";\n // }\n // this._context?.beginPath();\n // this._context?.arc(contactPoint.x, contactPoint.y, 3, 0, 2 * Math.PI);\n // this._context?.stroke();\n // });\n // }\n this.constraints.forEach(constraint => constraint.enforce(deltaTime));\n this.getRigidBodyList().forEach(rigidBody => {\n if (!rigidBody.isSleeping) {\n rigidBody.step(deltaTime);\n }\n });\n }\n\n resolveCollisionPhase(): Point[]{\n let rigidBodyList: RigidBody[] = [];\n \n // Use incremental updates for sweep-and-prune, full rebuild for others\n if (this.spatialIndexType === 'sap') {\n // For sweep-and-prune: use incremental updates for better performance\n this.rigidBodyMap.forEach((body) => {\n if (!this.enableSleeping || !body.isSleeping) {\n rigidBodyList.push(body);\n // Update existing objects in spatial index\n if (this.spatialIndex instanceof SweepAndPrune) {\n (this.spatialIndex as SweepAndPrune<RigidBody>).update(body);\n }\n }\n });\n } else {\n // For QuadTree and DynamicTree: rebuild each frame (existing behavior)\n this.spatialIndex.clear();\n this.rigidBodyMap.forEach((body) => {\n if (!this.enableSleeping || !body.isSleeping) {\n rigidBodyList.push(body);\n this.spatialIndex.insert(body);\n }\n });\n }\n \n // console.log(\"spatial index size: \", this.spatialIndex);\n let possibleCombinations = Collision.broadPhaseWithSpatialIndexFiltered(this.spatialIndex, rigidBodyList);\n let collisionResults = Collision.narrowPhaseWithRigidBodyAndPairs(rigidBodyList, possibleCombinations, this._resolveCollision);\n \n // Update pair manager with new collisions\n const pairEvents = this.pairManager.updatePairs(collisionResults.collisions);\n \n // Wake up bodies that start colliding\n if (this.enableSleeping) {\n pairEvents.created.forEach(pair => {\n if (pair.bodyA.isSleeping) pair.bodyA.setSleeping(false);\n if (pair.bodyB.isSleeping) pair.bodyB.setSleeping(false);\n });\n }\n \n return collisionResults.contactPoints;\n }\n\n get resolveCollision(): boolean{\n return this._resolveCollision;\n }\n\n set resolveCollision(resolveCollision: boolean){\n this._resolveCollision = resolveCollision;\n }\n\n getRigidBodyList(){\n let rigidBodyList:RigidBody[] = [];\n this.rigidBodyMap.forEach((body) => {\n rigidBodyList.push(body);\n })\n return rigidBodyList;\n }\n\n getRigidBodyMap(): Map<string, RigidBody>{\n return this.rigidBodyMap;\n }\n\n setMaxTransHeight(height: number){\n this.maxTransHeight = height;\n }\n\n setMaxTransWidth(width: number){\n this.maxTransWidth = width;\n }\n\n addConstraint(constraint: Constraint): void{\n this.constraints.push(constraint);\n }\n\n getConstraints(): Constraint[]{\n return this.constraints;\n }\n\n addPinJoint(bodyA: RigidBody, bodyB: RigidBody, anchorA: Point, anchorB: Point) {\n this.pinJoints.push({ bodyA, bodyB, anchorA, anchorB });\n }\n\n get currentSpatialIndexType(): SpatialIndexType {\n return this.spatialIndexType;\n }\n\n setSpatialIndexType(type: SpatialIndexType): void {\n if (type === this.spatialIndexType) return;\n \n this.spatialIndexType = type;\n if (type === 'dynamictree') {\n this.spatialIndex = new DynamicTree<RigidBody>();\n } else if (type === 'sap') {\n this.spatialIndex = new SweepAndPrune<RigidBody>();\n } else {\n this.spatialIndex = new QuadTree(0, this.bound);\n }\n }\n\n getSpatialIndexStats(): any {\n if (this.spatialIndex instanceof DynamicTree) {\n return (this.spatialIndex as DynamicTree<RigidBody>).getStats();\n } else if (this.spatialIndex instanceof SweepAndPrune) {\n return {\n type: this.spatialIndexType,\n ...(this.spatialIndex as SweepAndPrune<RigidBody>).getStats()\n };\n }\n return { type: this.spatialIndexType, objects: this.rigidBodyMap.size };\n }\n\n // Sleeping control\n get sleepingEnabled(): boolean {\n return this.enableSleeping;\n }\n\n set sleepingEnabled(enabled: boolean) {\n this.enableSleeping = enabled;\n if (!enabled) {\n // Wake up all sleeping bodies\n this.rigidBodyMap.forEach(body => {\n if (body.isSleeping) {\n body.setSleeping(false);\n }\n });\n }\n }\n\n // Pair manager access\n getPairManager(): PairManager {\n return this.pairManager;\n }\n\n // Get collision statistics\n getCollisionStats() {\n return {\n ...this.pairManager.getStats(),\n sleepingBodies: Array.from(this.rigidBodyMap.values()).filter(body => body.isSleeping).length,\n totalBodies: this.rigidBodyMap.size\n };\n }\n}\n",
12
+ "import { Point, PointCal } from \"@ue-too/math\";\nimport { RigidBody } from \"./rigidbody\";\n\n/**\n * Physics constraint interface.\n *\n * @remarks\n * Constraints restrict the motion of rigid bodies. Common examples include\n * pin joints, distance constraints, and angle limits.\n *\n * Constraints are solved using iterative methods and Baumgarte stabilization\n * to prevent drift over time.\n *\n * @category Constraints\n */\nexport interface Constraint {\n /**\n * Enforces the constraint for one timestep.\n *\n * @param dt - Timestep in seconds\n */\n enforce(dt: number): void;\n}\n\n/**\n * Pin joint connecting a body to a fixed world point.\n *\n * @remarks\n * Creates a pendulum-like constraint where a point on the body is pinned\n * to a fixed location in world space. The body can rotate around this point.\n *\n * Uses Baumgarte stabilization to prevent drift.\n *\n * @example\n * Create a pendulum\n * ```typescript\n * const bob = new Circle({ x: 0, y: 100 }, 20, 0, 10, false);\n * const joint = new FixedPinJoint(\n * bob,\n * { x: 0, y: 0 }, // Anchor on bob (center)\n * { x: 0, y: 0 } // World anchor (ceiling)\n * );\n * world.addRigidBody('bob', bob);\n * world.addConstraint(joint);\n * ```\n *\n * @category Constraints\n */\nexport class FixedPinJoint implements Constraint {\n\n private anchorA: Point;\n private worldAnchorA: Point;\n private bodyA: RigidBody;\n\n constructor(bodyA: RigidBody, anchorA: Point, worldAnchorA: Point) {\n this.bodyA = bodyA;\n this.anchorA = anchorA;\n this.worldAnchorA = worldAnchorA;\n }\n\n enforce(dt: number): void {\n this.solveWorldPinJointConstraint(dt);\n }\n\n solveWorldPinJointConstraint(dt: number) {\n const body = this.bodyA;\n const localAnchor = this.anchorA;\n const worldAnchor = this.worldAnchorA;\n\n // Transform local anchor point to world space\n const worldAnchorOnBody = PointCal.addVector(body.center, PointCal.rotatePoint(localAnchor, body.orientationAngle));\n\n // Calculate the difference between the anchor points\n const diff = PointCal.subVector(worldAnchorOnBody, worldAnchor);\n\n // Calculate the relative velocity of the anchor point\n const r = PointCal.subVector(worldAnchorOnBody, body.center);\n const velocity = PointCal.addVector(\n body.linearVelocity,\n PointCal.crossProduct({x: 0, y: 0, z: body.angularVelocity}, r)\n );\n\n // Calculate the mass matrix\n const invMass = body.isStatic() ? 0 : 1 / body.mass;\n const invI = body.isStatic() ? 0 : 1 / body.momentOfInertia;\n\n const K = {\n x: invMass + invI * r.y * r.y,\n y: invMass + invI * r.x * r.x,\n xy: -invI * r.x * r.y\n };\n\n // Calculate the impulse\n const baumgarte = 1; // Baumgarte stabilization factor\n const impulse = {\n x: -K.x * diff.x - K.xy * diff.y - baumgarte * diff.x / dt - velocity.x,\n y: -K.xy * diff.x - K.y * diff.y - baumgarte * diff.y / dt - velocity.y\n };\n\n // Apply the impulse\n if (!body.isStatic()) {\n body.linearVelocity.x += invMass * impulse.x;\n body.linearVelocity.y += invMass * impulse.y;\n body.angularVelocity += invI * (r.x * impulse.y - r.y * impulse.x);\n }\n }\n}\n\n/**\n * Pin joint connecting two bodies together.\n *\n * @remarks\n * Connects two bodies at specified anchor points. The bodies can rotate\n * relative to each other around the joint.\n *\n * Useful for creating chains, ragdolls, and mechanical linkages.\n *\n * @example\n * Create a chain\n * ```typescript\n * const link1 = new Circle({ x: 0, y: 0 }, 10);\n * const link2 = new Circle({ x: 30, y: 0 }, 10);\n *\n * const joint = new PinJoint(\n * link1,\n * link2,\n * { x: 10, y: 0 }, // Right edge of link1\n * { x: -10, y: 0 } // Left edge of link2\n * );\n *\n * world.addRigidBody('link1', link1);\n * world.addRigidBody('link2', link2);\n * world.addConstraint(joint);\n * ```\n *\n * @category Constraints\n */\nexport class PinJoint implements Constraint {\n\n private anchorA: Point;\n private anchorB: Point;\n private bodyA: RigidBody;\n private bodyB: RigidBody;\n\n constructor(bodyA: RigidBody, bodyB: RigidBody, anchorA: Point, anchorB: Point) {\n this.bodyA = bodyA;\n this.bodyB = bodyB;\n this.anchorA = anchorA;\n this.anchorB = anchorB;\n }\n\n enforce(dt: number): void {\n this.solvePinJointConstraint(dt);\n }\n\n solvePinJointConstraint(dt: number) {\n const bodyA = this.bodyA;\n const bodyB = this.bodyB;\n const anchorA = this.anchorA;\n const anchorB = this.anchorB;\n\n // Transform local anchor points to world space\n const worldAnchorA = PointCal.addVector(bodyA.center, PointCal.rotatePoint(anchorA, bodyA.orientationAngle));\n const worldAnchorB = PointCal.addVector(bodyB.center, PointCal.rotatePoint(anchorB, bodyB.orientationAngle));\n \n // Calculate the difference between the two anchor points in world space\n const diff = PointCal.subVector(worldAnchorB, worldAnchorA);\n \n // Calculate the relative velocity of the anchor points\n const rA = PointCal.subVector(worldAnchorA, bodyA.center);\n const rB = PointCal.subVector(worldAnchorB, bodyB.center);\n const relativeVelocity = PointCal.subVector(\n PointCal.addVector(bodyB.linearVelocity, PointCal.crossProduct({x: 0, y: 0, z: bodyB.angularVelocity}, rB)),\n PointCal.addVector(bodyA.linearVelocity, PointCal.crossProduct({x: 0, y: 0, z: bodyA.angularVelocity}, rA))\n );\n \n // Calculate the mass matrix\n const invMassA = bodyA.isStatic() ? 0 : 1 / bodyA.mass;\n const invMassB = bodyB.isStatic() ? 0 : 1 / bodyB.mass;\n const invIA = bodyA.isStatic() ? 0 : 1 / bodyA.momentOfInertia;\n const invIB = bodyB.isStatic() ? 0 : 1 / bodyB.momentOfInertia;\n \n const K = {\n x: invMassA + invMassB + invIA * rA.y * rA.y + invIB * rB.y * rB.y,\n y: invMassA + invMassB + invIA * rA.x * rA.x + invIB * rB.x * rB.x,\n xy: -invIA * rA.x * rA.y - invIB * rB.x * rB.y\n };\n \n // Calculate the impulse\n const baumgarte = 1; // Baumgarte stabilization factor\n const impulse = {\n x: -K.x * diff.x - K.xy * diff.y - baumgarte * diff.x / dt - relativeVelocity.x,\n y: -K.xy * diff.x - K.y * diff.y - baumgarte * diff.y / dt - relativeVelocity.y\n };\n \n // Apply the impulse\n if (!bodyA.isStatic()) {\n bodyA.linearVelocity.x -= invMassA * impulse.x;\n bodyA.linearVelocity.y -= invMassA * impulse.y;\n bodyA.angularVelocity -= invIA * (rA.x * impulse.y - rA.y * impulse.x);\n }\n \n if (!bodyB.isStatic()) {\n bodyB.linearVelocity.x += invMassB * impulse.x;\n bodyB.linearVelocity.y += invMassB * impulse.y;\n bodyB.angularVelocity += invIB * (rB.x * impulse.y - rB.y * impulse.x);\n }\n }\n\n}\n\nexport interface PinJointConstraint {\n bodyA: RigidBody;\n bodyB: RigidBody;\n anchorA: Point; // Local anchor point for bodyA\n anchorB: Point; // Local anchor point for bodyB\n}\n\nexport function solvePinJointConstraint(constraint: PinJointConstraint, dt: number) {\n const { bodyA, bodyB, anchorA, anchorB } = constraint;\n\n // Transform local anchor points to world space\n const worldAnchorA = PointCal.addVector(bodyA.center, PointCal.rotatePoint(anchorA, bodyA.orientationAngle));\n const worldAnchorB = PointCal.addVector(bodyB.center, PointCal.rotatePoint(anchorB, bodyB.orientationAngle));\n\n // Calculate the difference between the two anchor points in world space\n const diff = PointCal.subVector(worldAnchorB, worldAnchorA);\n\n // Calculate the relative velocity of the anchor points\n const rA = PointCal.subVector(worldAnchorA, bodyA.center);\n const rB = PointCal.subVector(worldAnchorB, bodyB.center);\n const relativeVelocity = PointCal.subVector(\n PointCal.addVector(bodyB.linearVelocity, PointCal.crossProduct({x: 0, y: 0, z: bodyB.angularVelocity}, rB)),\n PointCal.addVector(bodyA.linearVelocity, PointCal.crossProduct({x: 0, y: 0, z: bodyA.angularVelocity}, rA))\n );\n\n // Calculate the mass matrix\n const invMassA = bodyA.isStatic() ? 0 : 1 / bodyA.mass;\n const invMassB = bodyB.isStatic() ? 0 : 1 / bodyB.mass;\n const invIA = bodyA.isStatic() ? 0 : 1 / bodyA.momentOfInertia;\n const invIB = bodyB.isStatic() ? 0 : 1 / bodyB.momentOfInertia;\n\n const K = {\n x: invMassA + invMassB + invIA * rA.y * rA.y + invIB * rB.y * rB.y,\n y: invMassA + invMassB + invIA * rA.x * rA.x + invIB * rB.x * rB.x,\n xy: -invIA * rA.x * rA.y - invIB * rB.x * rB.y\n };\n\n // Calculate the impulse\n const baumgarte = 0.5; // Baumgarte stabilization factor\n const impulse = {\n x: -K.x * diff.x - K.xy * diff.y - baumgarte * diff.x / dt - relativeVelocity.x,\n y: -K.xy * diff.x - K.y * diff.y - baumgarte * diff.y / dt - relativeVelocity.y\n };\n\n // Apply the impulse\n if (!bodyA.isStatic()) {\n bodyA.linearVelocity.x -= invMassA * impulse.x;\n bodyA.linearVelocity.y -= invMassA * impulse.y;\n bodyA.angularVelocity -= invIA * (rA.x * impulse.y - rA.y * impulse.x);\n }\n\n if (!bodyB.isStatic()) {\n bodyB.linearVelocity.x += invMassB * impulse.x;\n bodyB.linearVelocity.y += invMassB * impulse.y;\n bodyB.angularVelocity += invIB * (rB.x * impulse.y - rB.y * impulse.x);\n }\n}\n\nexport interface WorldPinJointConstraint {\n body: RigidBody;\n localAnchor: Point; // Anchor point in body's local space\n worldAnchor: Point; // Fixed point in world space\n}\n\nexport function solveWorldPinJointConstraint(constraint: WorldPinJointConstraint, dt: number) {\n const { body, localAnchor, worldAnchor } = constraint;\n\n // Transform local anchor point to world space\n const worldAnchorOnBody = PointCal.addVector(body.center, PointCal.rotatePoint(localAnchor, body.orientationAngle));\n\n // Calculate the difference between the anchor points\n const diff = PointCal.subVector(worldAnchorOnBody, worldAnchor);\n\n // Calculate the relative velocity of the anchor point\n const r = PointCal.subVector(worldAnchorOnBody, body.center);\n const velocity = PointCal.addVector(\n body.linearVelocity,\n PointCal.crossProduct({x: 0, y: 0, z: body.angularVelocity}, r)\n );\n\n // Calculate the mass matrix\n const invMass = body.isStatic() ? 0 : 1 / body.mass;\n const invI = body.isStatic() ? 0 : 1 / body.momentOfInertia;\n\n const K = {\n x: invMass + invI * r.y * r.y,\n y: invMass + invI * r.x * r.x,\n xy: -invI * r.x * r.y\n };\n\n // Calculate the impulse\n const baumgarte = 0.2; // Baumgarte stabilization factor\n const impulse = {\n x: -K.x * diff.x - K.xy * diff.y - baumgarte * diff.x / dt - velocity.x,\n y: -K.xy * diff.x - K.y * diff.y - baumgarte * diff.y / dt - velocity.y\n };\n\n // Apply the impulse\n if (!body.isStatic()) {\n body.linearVelocity.x += invMass * impulse.x;\n body.linearVelocity.y += invMass * impulse.y;\n body.angularVelocity += invI * (r.x * impulse.y - r.y * impulse.x);\n }\n}\n"
13
13
  ],
14
- "mappings": "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",
15
- "debugId": "E95FEA238308AF2664756E2164756E21",
14
+ "mappings": "AAAA,mBAAS,qBCkEF,IAAM,EAA4C,CACrD,SAAU,EACV,KAAM,MACN,MAAO,CACX,EAgCO,SAAS,CAAU,CAAC,EAA0B,EAAmC,CAEpF,GAAI,EAAQ,QAAU,GAAK,EAAQ,QAAU,EAAQ,MACjD,OAAO,EAAQ,MAAQ,EAI3B,OAAQ,EAAQ,SAAW,EAAQ,QAAU,IAAM,EAAQ,SAAW,EAAQ,QAAU,EA8BrF,IAAM,GAAoB,CAC7B,OAAQ,EACR,QAAS,EACT,OAAQ,EACR,MAAO,EACP,WAAY,GACZ,OAAQ,GACR,OAAQ,GACR,SAAU,GACd,EDnFO,MAAe,CAAkC,CAE1C,QACA,MAAgB,GAChB,gBACA,iBACA,kBAA4B,EAC5B,mBACA,MACA,aAAwB,GACxB,qBAA+B,IAC/B,qBAA+B,IAC/B,gBAA2B,GAC3B,mBAA8B,GAC9B,qBAA+B,MAGlC,gBAAmC,IAAK,CAAyB,EAGjE,WAAsB,GACtB,eAAyB,KACzB,UAAoB,IACpB,WAAqB,EAG5B,WAAW,CAAC,EAAe,EAA4B,EAAG,EAAe,GAAI,EAAwB,GAAO,EAA2B,GAAM,CACzI,KAAK,QAAU,EACf,KAAK,kBAAoB,EACzB,KAAK,MAAQ,EACb,KAAK,aAAe,EACpB,KAAK,gBAAkB,EACvB,KAAK,MAAQ,CAAC,EAAG,EAAG,EAAG,CAAC,EACxB,KAAK,mBAAqB,CAAC,EAAG,EAAG,EAAG,CAAC,EACrC,KAAK,gBAAkB,CAAC,EAAG,EAAG,EAAG,CAAC,EAClC,KAAK,iBAAmB,EAG5B,IAAI,CAAC,EAAoB,CACrB,GAAI,CAAC,KAAK,SAAS,EACf,KAAK,QAAU,EAAS,UAAU,KAAK,QAAS,CAAK,EAI7D,aAAa,CAAC,EAAqB,CAC/B,KAAK,mBAAqB,EAG9B,SAAS,EAAU,CACf,OAAO,KAAK,QAGhB,mBAAmB,EAAU,CACzB,OAAO,KAAK,qBAGZ,gBAAe,EAAU,CACzB,OAAO,KAAK,oBAGZ,gBAAe,CAAC,EAAwB,CACxC,KAAK,iBAAmB,KAGxB,iBAAgB,EAAU,CAC1B,OAAO,KAAK,kBAGhB,QAAQ,EAAW,CACf,OAAO,KAAK,aAGhB,cAAc,EAAY,CACtB,OAAO,KAAK,mBAGhB,iBAAiB,CAAC,EAA6B,CAC3C,KAAK,gBAAkB,EAG3B,eAAe,CAAC,EAA4B,CACxC,KAAK,mBAAqB,EAG9B,mBAAmB,CAAC,EAAoB,CACpC,KAAK,kBAAoB,EAG7B,UAAU,CAAC,EAAoB,CAC3B,GAAI,EAAS,UAAU,KAAK,KAAK,IAAM,EACnC,KAAK,MAAQ,EAAS,UAAU,KAAK,MAAO,CAAK,EAEjD,UAAK,MAAQ,EAIrB,uBAAuB,CAAC,EAA6B,CACjD,IAAI,EACJ,GAAI,OAAO,IAAU,SACjB,EAAmB,EAAS,YAAY,CAAC,EAAG,EAAO,EAAG,CAAC,EAAG,KAAK,iBAAiB,EAEhF,OAAmB,EAAS,YAAY,EAAO,KAAK,iBAAiB,EAEzE,KAAK,WAAW,CAAgB,EAGpC,IAAI,CAAC,EAAyB,CAC1B,GAAI,KAAK,gBACL,GAAI,KAAK,SAAS,GACb,KAAK,eAAe,GAAK,GACzB,KAAK,eAAe,GAAK,GACzB,EAAS,UAAU,EAAS,UAAU,CAAC,EAAG,KAAK,MAAM,EAAG,EAAG,KAAK,MAAM,CAAC,EAAG,CAAC,EAAG,EAAG,EAAG,CAAC,CAAC,CAAC,GAAK,GAC5F,EAAS,UAAU,CAAC,EAAG,KAAK,MAAM,EAAG,EAAG,KAAK,MAAM,CAAC,CAAC,EAAI,KAAK,oBAAsB,KAAK,KAAO,KAEjG,GAAI,KAAK,MAAM,GAAK,KAChB,KAAK,MAAQ,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,KAAK,MAAM,CAAC,EAEzC,UAAK,MAAQ,CAAC,EAAG,EAAG,EAAG,CAAC,EAGzB,KACH,IAAI,EAA2B,EAAS,uBAAuB,EAAS,WAAW,CAAC,EAAG,KAAK,gBAAgB,EAAG,EAAG,KAAK,gBAAgB,CAAC,CAAC,EAAG,EAAE,EAC1I,EAAkB,EAAS,uBAAuB,EAA0B,KAAK,qBAAuB,KAAK,KAAO,IAAI,EAC5H,KAAK,MAAQ,EAAS,UAAU,KAAK,MAAO,CAAe,EAGnE,IAAM,EAAiB,KAAK,kBAAoB,EAAI,KAAK,iBAAmB,EAAI,CAAC,KAAK,qBAAuB,KAAK,qBAAuB,EAGzI,GAAI,KAAK,IAAI,KAAK,gBAAgB,EAAI,KAAK,IAAI,CAAc,EACzD,KAAK,iBAAmB,EAExB,UAAK,kBAAoB,EAG7B,GADA,KAAK,mBAAqB,KAAK,iBAAmB,EAC9C,EAAS,UAAU,CAAC,EAAG,KAAK,gBAAgB,EAAG,EAAG,KAAK,gBAAgB,CAAC,CAAC,EAAI,EAAS,UAAU,EAAS,qBAAqB,EAAS,uBAAuB,KAAK,MAAO,CAAS,EAAG,KAAK,IAAI,CAAC,EAChM,GAAI,KAAK,gBAAgB,GAAK,KAC1B,KAAK,gBAAkB,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,KAAK,gBAAgB,CAAC,EAE7D,UAAK,gBAAkB,CAAC,EAAG,EAAG,EAAG,CAAC,EAG1C,IAAM,EAAqB,MAAQ,KAAK,MACxC,KAAK,MAAQ,EAAS,UAAU,KAAK,MAAO,CAAC,EAAG,EAAG,EAAG,EAAG,CAAqB,CAAC,EAC/E,IAAM,EAAsB,EAAS,qBAAqB,EAAS,uBAAuB,KAAK,MAAO,CAAS,EAAG,KAAK,IAAI,EAC3H,KAAK,gBAAkB,EAAS,UAAU,KAAK,gBAAiB,CAAmB,EACnF,IAAM,EAAc,EAAS,uBAAuB,KAAK,gBAAiB,CAAS,EAGnF,GADA,KAAK,QAAU,EAAS,UAAU,KAAK,QAAS,CAAW,EACvD,KAAK,QAAQ,GAAK,MAAa,KAAK,QAAQ,EAAI,EAChD,KAAK,QAAQ,EAAI,EAErB,KAAK,MAAQ,CAAC,EAAG,EAAG,EAAG,CAAC,KAGxB,OAAM,EAAU,CAChB,OAAO,KAAK,WAGZ,OAAM,CAAC,EAAY,CACnB,KAAK,QAAU,KAGf,eAAc,EAAU,CACxB,OAAO,KAAK,mBAGZ,eAAc,CAAC,EAAY,CAC3B,KAAK,gBAAkB,KAGvB,KAAI,EAAU,CACd,OAAO,KAAK,SAGZ,oBAAmB,EAAU,CAC7B,OAAO,KAAK,wBAGZ,oBAAmB,CAAC,EAAc,CAClC,KAAK,qBAAuB,EAahC,WAAW,CAAC,EAAyB,CACjC,GAAI,GAAY,CAAC,KAAK,WAClB,KAAK,WAAa,GAClB,KAAK,gBAAkB,CAAE,EAAG,EAAG,EAAG,CAAE,EACpC,KAAK,iBAAmB,EACrB,QAAI,CAAC,GAAY,KAAK,WACzB,KAAK,WAAa,GAClB,KAAK,WAAa,EAI1B,cAAc,CAAC,EAAyB,CACpC,GAAI,KAAK,SAAS,GAAK,KAAK,eAAe,EAAG,OAE9C,IAAM,EAAQ,EAAS,UAAU,KAAK,eAAe,EAC/C,EAAe,KAAK,IAAI,KAAK,gBAAgB,EAEnD,GAAI,EAAQ,KAAK,gBAAkB,EAAe,KAAK,gBAEnD,GADA,KAAK,YAAc,EACf,KAAK,YAAc,KAAK,UACxB,KAAK,YAAY,EAAI,EAIzB,QADA,KAAK,WAAa,EACd,KAAK,WACL,KAAK,YAAY,EAAK,EAItC,CAEO,MAAM,EAAuD,CAExD,QACA,SAGD,gBAAmC,IAAK,CAAyB,EAGjE,WAAsB,GACtB,eAAyB,KACzB,UAAoB,IACpB,WAAqB,EAE5B,WAAW,CAAC,EAAgB,CAAC,EAAG,EAAG,EAAG,CAAC,EAAG,EAAgB,EAA0C,EAA4B,EAAG,EAAe,GAAI,EAAoB,GAAO,EAA2B,GAAM,CAC9M,KAAK,QAAU,IAAI,GAAO,EAAQ,EAAQ,EAAmB,EAAM,EAAU,CAAe,EAC5F,KAAK,SAAW,EAGpB,IAAI,CAAC,EAAqC,CACtC,EAAI,UAAU,EACd,EAAI,IAAI,KAAK,QAAQ,OAAO,EAAG,KAAK,QAAQ,OAAO,EAAG,KAAK,QAAQ,OAAQ,EAAG,EAAI,KAAK,EAAE,EACzF,EAAI,OAAO,EAGf,IAAI,CAAC,EAAyB,CAC1B,KAAK,QAAQ,KAAK,CAAS,EAC3B,KAAK,KAAK,KAAK,QAAQ,EAG3B,QAAQ,EAAY,CAChB,OAAO,KAAK,QAAQ,SAAS,EAGjC,cAAc,EAAY,CACtB,OAAO,KAAK,QAAQ,eAAe,EAGvC,mBAAmB,CAAC,EAAkD,CAClE,OAAO,KAAK,QAAQ,oBAAoB,CAAU,EAGtD,gBAAgB,CAAC,EAAkC,CAC/C,OAAO,KAAK,QAAQ,iBAAiB,CAAY,EAGrD,UAAU,CAAC,EAAoB,CAC3B,KAAK,QAAQ,WAAW,CAAK,KAG7B,KAAI,EAAgC,CACpC,OAAO,KAAK,QAAQ,KAGxB,OAAO,EAAW,CACd,OAAO,KAAK,QAAQ,KAGxB,uBAAuB,CAAC,EAAoB,CACxC,KAAK,QAAQ,wBAAwB,CAAK,EAG9C,IAAI,CAAC,EAAoB,CACrB,KAAK,QAAQ,KAAK,CAAK,EAG3B,sBAAsB,CAAC,EAAiC,CACpD,OAAO,KAAK,QAAQ,uBAAuB,CAAe,KAG1D,OAAM,EAAU,CAChB,OAAO,KAAK,QAAQ,UAGpB,OAAM,CAAC,EAAY,CACnB,KAAK,QAAQ,OAAS,KAGtB,eAAc,EAAU,CACxB,OAAO,KAAK,QAAQ,kBAGpB,eAAc,CAAC,EAAY,CAC3B,KAAK,QAAQ,eAAiB,KAG9B,iBAAgB,EAAE,CAClB,OAAO,KAAK,QAAQ,iBAGxB,iBAAiB,CAAC,EAA+B,CAC7C,OAAO,KAAK,QAAQ,kBAAkB,CAAe,KAGrD,gBAAe,CAAC,EAAwB,CACxC,KAAK,QAAQ,gBAAkB,KAG/B,gBAAe,EAAU,CACzB,OAAO,KAAK,QAAQ,mBAGpB,KAAI,EAAU,CACd,OAAO,KAAK,QAAQ,KAGxB,0BAA0B,CAAC,EAA+B,CACtD,OAAO,KAAK,QAAQ,2BAA2B,CAAe,KAG9D,oBAAmB,EAAU,CAC7B,OAAO,KAAK,QAAQ,uBAGpB,oBAAmB,CAAC,EAAc,CAClC,KAAK,QAAQ,oBAAsB,EAGvC,gBAAgB,CAAC,EAAgH,CAC7H,OAAO,KAAK,QAAQ,iBAAiB,CAAe,KAGpD,gBAAe,EAAW,CAC1B,OAAO,KAAK,QAAQ,gBAIxB,WAAW,CAAC,EAAyB,CACjC,GAAI,GAAY,CAAC,KAAK,WAClB,KAAK,WAAa,GAClB,KAAK,QAAQ,eAAiB,CAAE,EAAG,EAAG,EAAG,CAAE,EAC3C,KAAK,QAAQ,gBAAkB,EAC5B,QAAI,CAAC,GAAY,KAAK,WACzB,KAAK,WAAa,GAClB,KAAK,WAAa,EAI1B,cAAc,CAAC,EAAyB,CACpC,GAAI,KAAK,QAAQ,SAAS,GAAK,KAAK,QAAQ,eAAe,EAAG,OAE9D,IAAM,EAAQ,EAAS,UAAU,KAAK,QAAQ,cAAc,EACtD,EAAe,KAAK,IAAI,KAAK,QAAQ,eAAe,EAE1D,GAAI,EAAQ,KAAK,gBAAkB,EAAe,KAAK,gBAEnD,GADA,KAAK,YAAc,EACf,KAAK,YAAc,KAAK,UACxB,KAAK,YAAY,EAAI,EAIzB,QADA,KAAK,WAAa,EACd,KAAK,WACL,KAAK,YAAY,EAAK,EAKtC,CAEO,MAAM,EAAwD,CAEzD,SACA,SAGD,gBAAmC,IAAK,CAAyB,EAGjE,WAAsB,GACtB,eAAyB,KACzB,UAAoB,IACpB,WAAqB,EAE5B,WAAW,CAAC,EAAgB,CAAC,EAAG,EAAG,EAAG,CAAC,EAAG,EAAmB,EAA0C,EAA4B,EAAG,EAAe,GAAI,EAAoB,GAAO,EAA2B,GAAM,CACjN,KAAK,SAAW,IAAI,GAAQ,EAAQ,EAAU,EAAmB,EAAM,EAAU,CAAe,EAChG,KAAK,SAAW,EAGpB,IAAI,CAAC,EAAqC,CACtC,EAAI,UAAU,EACd,IAAI,EAAW,KAAK,SAAS,oBAAoB,EACjD,EAAI,OAAO,EAAS,GAAG,EAAG,EAAS,GAAG,CAAC,EACvC,EAAS,QAAQ,KAAU,CACvB,EAAI,OAAO,EAAO,EAAG,EAAO,CAAC,EAChC,EACD,EAAI,OAAO,EAAS,GAAG,EAAG,EAAS,GAAG,CAAC,EACvC,EAAI,OAAO,EAMf,IAAI,CAAC,EAAyB,CAC1B,KAAK,SAAS,KAAK,CAAS,EAC5B,KAAK,KAAK,KAAK,QAAQ,EAG3B,QAAQ,EAAY,CAChB,OAAO,KAAK,SAAS,SAAS,EAGlC,cAAc,EAAY,CACtB,OAAO,KAAK,SAAS,eAAe,EAGxC,mBAAmB,CAAC,EAAkD,CAClE,OAAO,KAAK,SAAS,oBAAoB,CAAU,EAGvD,gBAAgB,CAAC,EAAkC,CAC/C,OAAO,KAAK,SAAS,iBAAiB,CAAY,EAGtD,UAAU,CAAC,EAAoB,CAC3B,KAAK,SAAS,WAAW,CAAK,EAGlC,uBAAuB,CAAC,EAAoB,CACxC,KAAK,SAAS,wBAAwB,CAAK,EAG/C,iBAAiB,CAAC,EAA6B,CAC3C,KAAK,SAAS,kBAAkB,CAAc,EAGlD,IAAI,CAAC,EAAoB,CACrB,KAAK,SAAS,KAAK,CAAK,KAGxB,OAAM,EAAU,CAChB,OAAO,KAAK,SAAS,UAGrB,OAAM,CAAC,EAAY,CACnB,KAAK,SAAS,OAAS,KAGvB,eAAc,EAAU,CACxB,OAAO,KAAK,SAAS,kBAGrB,eAAc,CAAC,EAAY,CAC3B,KAAK,SAAS,eAAiB,KAG/B,gBAAe,EAAU,CACzB,OAAO,KAAK,SAAS,mBAGrB,gBAAe,CAAC,EAAwB,CACxC,KAAK,SAAS,gBAAkB,KAGhC,iBAAgB,EAAU,CAC1B,OAAO,KAAK,SAAS,iBAGzB,iBAAiB,CAAC,EAA+B,CAC7C,OAAO,KAAK,SAAS,kBAAkB,CAAe,EAG1D,sBAAsB,CAAC,EAAiC,CACpD,OAAO,KAAK,SAAS,uBAAuB,CAAe,KAG3D,KAAI,EAA4B,CAChC,OAAO,KAAK,SAAS,QAGrB,KAAI,EAAU,CACd,OAAO,KAAK,SAAS,QAGrB,oBAAmB,EAAU,CAC7B,OAAO,KAAK,SAAS,uBAGrB,oBAAmB,CAAC,EAAc,CAClC,KAAK,SAAS,oBAAsB,KAGpC,gBAAe,EAAW,CAC1B,OAAO,KAAK,SAAS,gBAGzB,0BAA0B,CAAC,EAA+B,CACtD,OAAO,KAAK,SAAS,2BAA2B,CAAe,EAGnE,gBAAgB,CAAC,EAAgH,CAC7H,OAAO,KAAK,SAAS,iBAAiB,CAAe,EAIzD,WAAW,CAAC,EAAyB,CACjC,GAAI,GAAY,CAAC,KAAK,WAClB,KAAK,WAAa,GAClB,KAAK,SAAS,eAAiB,CAAE,EAAG,EAAG,EAAG,CAAE,EAC5C,KAAK,SAAS,gBAAkB,EAC7B,QAAI,CAAC,GAAY,KAAK,WACzB,KAAK,WAAa,GAClB,KAAK,WAAa,EAI1B,cAAc,CAAC,EAAyB,CACpC,GAAI,KAAK,SAAS,SAAS,GAAK,KAAK,SAAS,eAAe,EAAG,OAEhE,IAAM,EAAQ,EAAS,UAAU,KAAK,SAAS,cAAc,EACvD,EAAe,KAAK,IAAI,KAAK,SAAS,eAAe,EAE3D,GAAI,EAAQ,KAAK,gBAAkB,EAAe,KAAK,gBAEnD,GADA,KAAK,YAAc,EACf,KAAK,YAAc,KAAK,UACxB,KAAK,YAAY,EAAI,EAIzB,QADA,KAAK,WAAa,EACd,KAAK,WACL,KAAK,YAAY,EAAK,EAItC,CAEO,MAAM,WAAgB,CAAc,CAE/B,SACA,iBAER,WAAW,CAAC,EAAgB,CAAC,EAAG,EAAG,EAAG,CAAC,EAAG,EAAmB,EAA4B,EAAG,EAAe,GAAI,EAAoB,GAAO,EAA2B,GAAM,CACvK,MAAM,EAAQ,EAAmB,EAAM,EAAU,CAAe,EAChE,KAAK,SAAW,EAChB,KAAK,KAAO,KAAK,KAAK,KAAK,IAAI,EAE/B,IAAI,EAAY,KAAK,SAAS,OAAO,CAAC,EAAK,EAAQ,IAAU,CACzD,IAAI,EAAiB,EAAQ,KAAK,SAAS,OAAS,EAAI,EAAQ,EAAI,EAChE,EAAY,KAAK,SAAS,GAC1B,EAAe,EAAS,aAAa,EAAW,CAAM,EAC1D,OAAO,EAAM,EAAS,UAAU,CAAY,GAAK,EAAS,WAAW,EAAQ,CAAM,EAAI,EAAS,WAAW,EAAQ,CAAS,EAAI,EAAS,WAAW,EAAW,CAAS,IACzK,CAAC,EAEA,EAAa,KAAK,SAAS,OAAO,CAAC,EAAK,EAAQ,IAAU,CAC1D,OAAO,EAAM,EAAS,UAAU,EAAS,aAAa,KAAK,SAAS,EAAQ,KAAK,SAAS,OAAS,EAAI,EAAQ,EAAI,GAAI,CAAM,CAAC,GAC/H,CAAC,EAGJ,KAAK,iBAAmB,KAAK,MAAQ,GAAa,EAAI,GAI1D,mBAAmB,EAAW,CAC1B,OAAO,KAAK,SAAS,IAAI,KAAQ,CAC7B,OAAO,EAAS,UAAU,KAAK,QAAS,EAAS,YAAY,EAAQ,KAAK,iBAAiB,CAAC,EAC/F,EAGL,gBAAgB,CAAC,EAAkC,CAC/C,OAAO,KAAK,oBAAoB,EAAE,IAAI,CAAC,EAAQ,EAAO,IAAc,CAChE,IAAI,EAAS,EAAS,UAAU,EAAQ,EAAY,EAAY,OAAS,EAAE,EAC3E,GAAI,EAAQ,EACR,EAAS,EAAS,UAAU,EAAQ,EAAY,EAAQ,EAAE,EAE9D,OAAO,EAAS,WAAW,EAAS,YAAY,EAAQ,KAAK,GAAK,CAAC,CAAC,EACvE,EAGL,mBAAmB,CAAC,EAAkD,CAGlE,IAAI,EAFW,KAAK,oBAAoB,EAEb,IAAK,KAAU,CACtC,OAAO,EAAS,WAAW,EAAQ,CAAU,EAChD,EAGD,MAAO,CAAC,IAAK,KAAK,IAAI,GAAG,CAAW,EAAG,IAAK,KAAK,IAAI,GAAG,CAAW,CAAC,KAGpE,KAAI,EAAgC,CACpC,IAAI,EAAS,KAAK,oBAAoB,EAClC,EAAU,EAAO,IAAI,KAAU,EAAO,CAAC,EACvC,EAAU,EAAO,IAAI,KAAU,EAAO,CAAC,EAC3C,MAAO,CAAC,IAAK,CAAC,EAAG,KAAK,IAAI,GAAG,CAAO,EAAG,EAAG,KAAK,IAAI,GAAG,CAAO,CAAC,EAAG,IAAK,CAAC,EAAG,KAAK,IAAI,GAAG,CAAO,EAAG,EAAG,KAAK,IAAI,GAAG,CAAO,CAAC,CAAC,EAG5H,iBAAiB,CAAC,EAA+B,CAC7C,IAAI,EAAW,KAAK,oBAAoB,EACpC,EAAoB,EAAS,IAAI,KAAU,EAAS,WAAW,EAAQ,CAAe,CAAC,EACvF,EAAW,EAAkB,QAAQ,KAAK,IAAI,GAAG,CAAiB,CAAC,EACvE,OAAO,EAAS,GAGpB,sBAAsB,CAAC,EAAgC,CACnD,IAAI,EAAW,KAAK,oBAAoB,EACpC,EAAoB,EAAS,IAAI,KAAU,EAAS,WAAW,EAAQ,CAAe,CAAC,EACvF,EAAW,EAAkB,QAAQ,KAAK,IAAI,GAAG,CAAiB,CAAC,EACjE,EAAY,EAAS,GACvB,EAAiB,EAAW,EAAI,EAAW,EAAI,EAAS,OAAS,EACjE,EAAiB,EAAW,EAAS,OAAS,EAAI,EAAW,EAAI,EAC/D,EAAY,EAAS,GACrB,EAAY,EAAS,GACrB,EAAqB,EAAS,WAAW,EAAW,CAAe,EACnE,EAAqB,EAAS,WAAW,EAAW,CAAe,EACzE,GAAI,EAAqB,EACrB,MAAO,CAAC,EAAW,CAAS,EAE5B,WAAO,CAAC,EAAW,CAAS,EAIpC,0BAA0B,CAAC,EAA8B,CACrD,IAAM,EAAW,KAAK,uBAAuB,CAAe,EACtD,EAAY,EAAS,kBAAkB,EAAS,GAAI,EAAS,EAAE,EACrE,OAAO,EAAS,YAAY,EAAW,CAAC,KAAK,GAAK,CAAC,EAGvD,gBAAgB,CAAC,EAA+G,CAC5H,IAAI,EAAW,KAAK,oBAAoB,EACpC,EAAoB,EAAS,IAAI,KAAU,EAAS,WAAW,EAAQ,CAAe,CAAC,EACvF,EAAW,EAAkB,QAAQ,KAAK,IAAI,GAAG,CAAiB,CAAC,EACjE,EAAY,EAAS,GACvB,EAAiB,EAAW,EAAI,EAAW,EAAI,EAAS,OAAS,EACjE,EAAiB,EAAW,EAAS,OAAS,EAAI,EAAW,EAAI,EAC/D,EAAY,EAAS,GACrB,EAAY,EAAS,GACrB,EAAqB,EAAS,WAAW,EAAW,CAAe,EACnE,EAAqB,EAAS,WAAW,EAAW,CAAe,EACnE,EAAyB,CAAC,EAC1B,EAAiH,CAAC,EACxH,GAAI,EAAqB,EAAoB,CACzC,EAAc,KAAK,EAAW,CAAS,EACvC,EAAuB,KAAK,CAAC,WAAY,CAAC,MAAO,EAAW,MAAO,CAAc,EAAG,SAAU,CAAC,MAAO,EAAW,MAAO,CAAQ,CAAC,CAAC,EAGlI,EAAuB,QAAQ,CAAC,WAAY,CAAC,MAAO,EAAW,MAAO,CAAQ,EAAG,SAAU,CAAC,MAAO,EAAW,MAAO,CAAc,CAAC,CAAC,EAErI,IAAI,EAAqB,EAAiB,EAAI,EAAiB,EAAI,EAAS,OAAS,EACrF,EAAuB,QAAQ,CAAC,WAAY,CAAC,MAAO,EAAS,GAAqB,MAAO,CAAkB,EAAG,SAAU,CAAC,MAAO,EAAW,MAAO,CAAc,CAAC,CAAC,EAC/J,KACH,EAAc,KAAK,EAAW,CAAS,EACvC,EAAuB,KAAK,CAAC,WAAY,CAAC,MAAO,EAAW,MAAO,CAAQ,EAAG,SAAU,CAAC,MAAO,EAAW,MAAO,CAAc,CAAC,CAAC,EAGlI,IAAI,EAAqB,EAAiB,EAAS,OAAS,EAAI,EAAiB,EAAI,EACrF,EAAuB,QAAQ,CAAC,WAAY,CAAC,MAAO,EAAW,MAAO,CAAc,EAAG,SAAU,CAAC,MAAO,EAAS,GAAqB,MAAO,CAAkB,CAAC,CAAC,EAGlK,EAAuB,QAAQ,CAAC,WAAY,CAAC,MAAO,EAAW,MAAO,CAAc,EAAG,SAAU,CAAC,MAAO,EAAW,MAAO,CAAQ,CAAC,CAAC,EAGzI,OAAO,KAGP,gBAAe,EAAW,CAC1B,OAAO,KAAK,iBAGpB,CAEO,MAAM,WAAe,CAAc,CAE9B,QACA,iBAER,WAAW,CAAC,EAAgB,CAAC,EAAG,EAAG,EAAG,CAAC,EAAG,EAAgB,EAA4B,EAAG,EAAe,GAAI,EAAoB,GAAO,EAA2B,GAAM,CACpK,MAAM,EAAQ,EAAmB,EAAM,EAAU,CAAe,EAChE,KAAK,QAAU,EACf,KAAK,KAAO,KAAK,KAAK,KAAK,IAAI,EAC/B,KAAK,iBAAmB,KAAK,MAAQ,KAAK,QAAU,KAAK,QAAU,EAGvE,mBAAmB,CAAC,EAAkD,CAClE,IAAI,EAAmB,EAAS,UAAU,KAAK,QAAS,EAAS,uBAAuB,EAAY,KAAK,OAAO,CAAC,EAC7G,EAAmB,EAAS,UAAU,KAAK,QAAS,EAAS,uBAAuB,EAAY,CAAC,KAAK,OAAO,CAAC,EAClH,MAAO,CAAC,IAAK,EAAS,WAAW,EAAkB,CAAU,EAAG,IAAK,EAAS,WAAW,EAAkB,CAAU,CAAC,EAG1H,gBAAgB,CAAC,EAAkC,CAC/C,MAAO,CAAC,EAAS,WAAW,EAAS,UAAU,EAAa,OAAQ,KAAK,OAAO,CAAC,CAAC,KAGlF,KAAI,EAAgC,CACpC,MAAO,CAAC,IAAK,EAAS,UAAU,KAAK,QAAS,CAAC,EAAG,KAAK,QAAS,EAAG,KAAK,OAAO,CAAC,EAAG,IAAK,EAAS,UAAU,KAAK,QAAS,CAAC,EAAG,KAAK,QAAS,EAAG,KAAK,OAAO,CAAC,CAAC,EAGhK,iBAAiB,CAAC,EAA+B,CAC7C,OAAO,EAAS,UAAU,KAAK,QAAS,EAAS,uBAAuB,EAAiB,KAAK,OAAO,CAAC,KAGtG,OAAM,EAAW,CACjB,OAAO,KAAK,QAGhB,sBAAsB,CAAC,EAAgC,CACnD,MAAO,CAAC,EAAS,UAAU,KAAK,QAAS,EAAS,uBAAuB,EAAiB,KAAK,OAAO,CAAC,CAAC,EAG5G,0BAA0B,CAAC,EAA8B,CACrD,OAAO,EAAS,WAAW,CAAe,EAG9C,gBAAgB,CAAC,EAA+G,CAC5H,MAAO,CAAC,KAGR,gBAAe,EAAW,CAC1B,OAAO,KAAK,iBAEpB,CEzxBO,MAAM,CAAc,CACf,WACA,MACA,OAER,WAAW,CAAC,EAAmB,EAAe,EAAe,CACzD,KAAK,WAAa,EAClB,KAAK,MAAQ,EACb,KAAK,OAAS,EAGlB,QAAQ,EAAE,CACN,OAAO,KAAK,MAGhB,SAAS,EAAE,CACP,OAAO,KAAK,OAGhB,aAAa,EAAE,CACX,OAAO,KAAK,WAEpB,CAQO,MAAM,CAA8D,CAC/D,YAAc,GACd,WAAa,EAEb,MACA,QAAe,CAAC,EAChB,MAAqC,CAAC,EACtC,OAGR,WAAW,CAAC,EAAe,EAAuB,CAC9C,KAAK,MAAQ,EACb,KAAK,QAAU,CAAC,EAChB,KAAK,OAAS,EACd,KAAK,MAAQ,CAAC,OAAW,OAAW,OAAW,MAAS,EAG5D,IAAI,CAAC,EAAkC,CACnC,EAAQ,UAAU,EAClB,EAAQ,KAAK,KAAK,OAAO,cAAc,EAAE,EAAG,KAAK,OAAO,cAAc,EAAE,EAAG,KAAK,OAAO,SAAS,EAAG,KAAK,OAAO,UAAU,CAAC,EAC1H,EAAQ,OAAO,EAEf,QAAQ,EAAQ,EAAG,EAAQ,KAAK,MAAM,OAAQ,IAAQ,CAClD,IAAI,EAAO,KAAK,MAAM,GACtB,GAAG,GAAQ,KACP,EAAK,KAAK,CAAO,GAK7B,KAAK,EAAE,CACH,KAAK,QAAU,CAAC,EAChB,QAAQ,EAAQ,EAAG,EAAQ,KAAK,MAAM,OAAQ,IAAQ,CAClD,IAAI,EAAO,KAAK,MAAM,GACtB,GAAG,GAAQ,KACP,EAAK,MAAM,EACX,EAAO,QAKnB,KAAK,EAAE,CAEH,IAAI,EAAW,KAAK,OAAO,SAAS,EAAI,EACpC,EAAY,KAAK,OAAO,UAAU,EAAI,EACtC,EAAa,KAAK,OAAO,cAAc,EAE3C,KAAK,MAAM,GAAK,IAAI,EAAY,KAAK,MAAQ,EAAG,IAAI,EAAe,CAAC,EAAG,EAAW,EAAG,EAAG,EAAW,CAAC,EAAG,EAAU,CAAS,CAAC,EAC3H,KAAK,MAAM,GAAK,IAAI,EAAY,KAAK,MAAQ,EAAG,IAAI,EAAe,CAAC,EAAG,EAAW,EAAG,EAAG,EAAW,EAAI,CAAS,EAAG,EAAU,CAAS,CAAC,EACvI,KAAK,MAAM,GAAK,IAAI,EAAY,KAAK,MAAQ,EAAG,IAAI,EAAe,CAAC,EAAG,EAAW,EAAI,EAAU,EAAG,EAAW,EAAI,CAAS,EAAG,EAAU,CAAS,CAAC,EAClJ,KAAK,MAAM,GAAK,IAAI,EAAY,KAAK,MAAQ,EAAG,IAAI,EAAe,CAAC,EAAG,EAAW,EAAI,EAAU,EAAG,EAAW,CAAC,EAAG,EAAU,CAAS,CAAC,EAG1I,QAAQ,CAAC,EAAS,CACd,IAAI,EAAW,CAAC,EAAG,KAAK,OAAO,cAAc,EAAE,EAAI,KAAK,OAAO,SAAS,EAAI,EAAG,EAAG,KAAK,OAAO,cAAc,EAAE,EAAI,KAAK,OAAO,UAAU,EAAI,CAAC,EACzI,EAAS,EAAM,KACf,EAAS,EAAO,IAAI,EAAI,EAAS,GAAK,EAAO,IAAI,EAAI,KAAK,OAAO,cAAc,EAAE,EACjF,EAAO,EAAO,IAAI,EAAI,EAAS,GAAK,EAAO,IAAI,EAAI,KAAK,OAAO,cAAc,EAAE,EAC/E,EAAQ,EAAO,IAAI,EAAI,EAAS,GAAK,EAAO,IAAI,EAAI,EAAS,EAC7D,EAAM,EAAO,IAAI,EAAI,EAAS,GAAK,EAAO,IAAI,EAAI,EAAS,EAE/D,GAAI,GAAU,EACV,MAAO,GACJ,QAAI,GAAU,EACjB,MAAO,GACJ,QAAI,GAAO,EACd,MAAO,GACJ,QAAI,GAAO,EACd,MAAO,GAEX,MAAO,GAGX,MAAM,CAAC,EAAS,CACZ,IAAI,EAAO,KAAK,MAAM,GACtB,GAAI,GAAQ,KAAU,CAClB,IAAI,EAAQ,KAAK,SAAS,CAAK,EAE/B,GAAI,IAAU,GAAG,CACb,EAAO,KAAK,MAAM,GAClB,GAAM,OAAO,CAAK,EAClB,QAKR,GADA,KAAK,QAAQ,KAAK,CAAK,EACpB,KAAK,QAAQ,OAAS,KAAK,aAAe,KAAK,MAAQ,KAAK,WAAW,CACtE,GAAI,KAAK,MAAM,IAAM,MAAQ,KAAK,MAAM,IAAM,KAC1C,KAAK,MAAM,EAEf,IAAI,EAAI,EACR,MAAO,EAAI,KAAK,QAAQ,OAAO,CAC3B,IAAI,EAAQ,KAAK,SAAS,KAAK,QAAQ,EAAE,EACrC,EAAO,KAAK,MAAM,GACtB,GAAI,GAAS,IAAM,IAAS,OAAU,CAClC,IAAI,EAAQ,KAAK,QAAQ,GACzB,KAAK,QAAQ,OAAO,EAAG,CAAC,EACxB,EAAK,OAAO,CAAK,EAEjB,WAMhB,QAAQ,CAAC,EAAc,CACnB,IAAI,EAAQ,KAAK,SAAS,CAAK,EAC3B,EAAM,CAAC,EACP,EAAO,KAAK,MAAM,GACtB,GAAG,IAAU,IAAM,IAAS,OACxB,EAAI,KAAK,GAAG,EAAK,SAAS,CAAK,CAAC,EAGpC,OADA,EAAI,KAAK,GAAG,KAAK,OAAO,EACjB,EAGf,CC5HA,MAAM,CAAuC,CAClC,OAA6B,KAC7B,SAAqD,CAAC,KAAM,IAAI,EAChE,KAAa,CAAE,IAAK,CAAE,EAAG,EAAG,EAAG,CAAE,EAAG,IAAK,CAAE,EAAG,EAAG,EAAG,CAAE,CAAE,EACxD,OAAmB,KACnB,OAAiB,EAExB,WAAW,CAAC,EAAY,CACpB,GAAI,EACA,KAAK,QAAQ,CAAM,EAI3B,MAAM,EAAY,CACd,OAAO,KAAK,SAAS,KAAO,KAGhC,OAAO,CAAC,EAAiB,CACrB,KAAK,OAAS,EACd,KAAK,WAAW,EAChB,KAAK,SAAW,CAAC,KAAM,IAAI,EAC3B,KAAK,OAAS,EAGlB,SAAS,CAAC,EAAqB,EAA2B,CACtD,EAAO,OAAS,KAChB,EAAO,OAAS,KAChB,KAAK,SAAW,CAAC,EAAQ,CAAM,EAC/B,KAAK,OAAS,KACd,KAAK,WAAW,EAChB,KAAK,OAAS,EAAI,KAAK,IAAI,EAAO,OAAQ,EAAO,MAAM,EAG3D,UAAU,CAAC,EAAiB,IAAW,CACnC,GAAI,KAAK,OAAO,GAAK,KAAK,OAAQ,CAE9B,IAAM,EAAM,KAAK,OAAO,KACxB,KAAK,KAAO,CACR,IAAK,CAAE,EAAG,EAAI,IAAI,EAAI,EAAQ,EAAG,EAAI,IAAI,EAAI,CAAO,EACpD,IAAK,CAAE,EAAG,EAAI,IAAI,EAAI,EAAQ,EAAG,EAAI,IAAI,EAAI,CAAO,CACxD,EACG,QAAI,KAAK,SAAS,IAAM,KAAK,SAAS,GAAI,CAE7C,IAAM,EAAQ,KAAK,SAAS,GAAG,KACzB,EAAQ,KAAK,SAAS,GAAG,KAC/B,KAAK,KAAO,CACR,IAAK,CACD,EAAG,KAAK,IAAI,EAAM,IAAI,EAAG,EAAM,IAAI,CAAC,EACpC,EAAG,KAAK,IAAI,EAAM,IAAI,EAAG,EAAM,IAAI,CAAC,CACxC,EACA,IAAK,CACD,EAAG,KAAK,IAAI,EAAM,IAAI,EAAG,EAAM,IAAI,CAAC,EACpC,EAAG,KAAK,IAAI,EAAM,IAAI,EAAG,EAAM,IAAI,CAAC,CACxC,CACJ,GAIR,UAAU,EAAuB,CAC7B,GAAI,CAAC,KAAK,OAAQ,OAAO,KACzB,OAAO,KAAK,OAAO,SAAS,KAAO,KAAO,KAAK,OAAO,SAAS,GAAK,KAAK,OAAO,SAAS,GAG7F,UAAU,EAAW,CACjB,GAAI,KAAK,OAAO,EAAG,MAAO,GAC1B,IAAM,EAAa,KAAK,SAAS,GAAK,KAAK,SAAS,GAAG,OAAS,EAC1D,EAAc,KAAK,SAAS,GAAK,KAAK,SAAS,GAAG,OAAS,EACjE,OAAO,EAAa,EAE5B,CAcO,MAAM,CAAuE,CACxE,WAA4B,CAAC,EAC7B,QAA0E,IAAI,IAC9E,OAAiB,EAEzB,KAAK,EAAS,CACV,KAAK,WAAa,CAAC,EACnB,KAAK,QAAQ,MAAM,EACnB,KAAK,OAAS,EAGlB,MAAM,CAAC,EAAiB,CACpB,IAAM,EAAK,KAAK,SAEV,EAA2B,CAAE,MAAO,EAAO,KAAK,IAAI,EAAG,MAAO,GAAM,SAAQ,IAAG,EAC/E,EAA2B,CAAE,MAAO,EAAO,KAAK,IAAI,EAAG,MAAO,GAAO,SAAQ,IAAG,EAEtF,KAAK,QAAQ,IAAI,EAAQ,CAAE,cAAa,aAAY,CAAC,EAGrD,KAAK,qBAAqB,CAAW,EACrC,KAAK,qBAAqB,CAAW,EAGzC,MAAM,CAAC,EAAiB,CACpB,IAAM,EAAY,KAAK,QAAQ,IAAI,CAAM,EACzC,GAAI,CAAC,EAAW,OAEhB,IAAM,EAAU,EAAO,KAAK,IAAI,EAC1B,EAAU,EAAO,KAAK,IAAI,EAGhC,GAAI,EAAU,YAAY,QAAU,EAChC,KAAK,eAAe,EAAU,WAAW,EACzC,EAAU,YAAY,MAAQ,EAC9B,KAAK,qBAAqB,EAAU,WAAW,EAGnD,GAAI,EAAU,YAAY,QAAU,EAChC,KAAK,eAAe,EAAU,WAAW,EACzC,EAAU,YAAY,MAAQ,EAC9B,KAAK,qBAAqB,EAAU,WAAW,EAIvD,MAAM,CAAC,EAAiB,CACpB,IAAM,EAAY,KAAK,QAAQ,IAAI,CAAM,EACzC,GAAI,CAAC,EAAW,OAEhB,KAAK,eAAe,EAAU,WAAW,EACzC,KAAK,eAAe,EAAU,WAAW,EACzC,KAAK,QAAQ,OAAO,CAAM,EAG9B,QAAQ,CAAC,EAAqB,CAC1B,IAAM,EAAc,CAAC,EACf,EAAW,EAAY,KAAK,IAAI,EAChC,EAAW,EAAY,KAAK,IAAI,EAGtC,QAAW,KAAY,KAAK,WAAY,CACpC,GAAI,EAAS,MAAQ,EAAU,MAE/B,GAAI,EAAS,OAAS,EAAS,SAAW,EAAa,CAEnD,IAAM,EAAS,KAAK,QAAQ,IAAI,EAAS,MAAM,GAAG,YAAY,MAC9D,GAAI,IAAW,QAAa,GAAU,GAElC,GAAI,KAAK,eAAe,EAAS,OAAO,KAAM,EAAY,IAAI,EAC1D,EAAO,KAAK,EAAS,MAAM,IAM3C,OAAO,EAIX,eAAe,EAAwB,CACnC,IAAM,EAA6B,CAAC,EAC9B,EAAgB,IAAI,IAE1B,QAAW,KAAY,KAAK,WACxB,GAAI,EAAS,MAAO,CAEhB,QAAW,KAAa,EACpB,GAAI,KAAK,eAAe,EAAS,OAAO,KAAM,EAAU,IAAI,EACxD,EAAM,KAAK,CAAC,EAAG,EAAS,OAAQ,EAAG,CAAS,CAAC,EAGrD,EAAc,IAAI,EAAS,MAAM,EAEjC,OAAc,OAAO,EAAS,MAAM,EAG5C,OAAO,EAGH,oBAAoB,CAAC,EAA6B,CAEtD,IAAI,EAAO,EACP,EAAQ,KAAK,WAAW,OAE5B,MAAO,EAAO,EAAO,CACjB,IAAM,EAAM,KAAK,OAAO,EAAO,GAAS,CAAC,EACnC,EAAc,KAAK,WAAW,GAEpC,GAAI,EAAY,MAAQ,EAAS,OAC5B,EAAY,QAAU,EAAS,OAAS,EAAY,OAAS,CAAC,EAAS,MACxE,EAAO,EAAM,EAEb,OAAQ,EAIhB,KAAK,WAAW,OAAO,EAAM,EAAG,CAAQ,EAGpC,cAAc,CAAC,EAA6B,CAChD,IAAM,EAAQ,KAAK,WAAW,QAAQ,CAAQ,EAC9C,GAAI,IAAU,GACV,KAAK,WAAW,OAAO,EAAO,CAAC,EAI/B,cAAc,CAAC,EAAmC,EAA4C,CAClG,MAAO,EAAE,EAAM,IAAI,EAAI,EAAM,IAAI,GACxB,EAAM,IAAI,EAAI,EAAM,IAAI,GACxB,EAAM,IAAI,EAAI,EAAM,IAAI,GACxB,EAAM,IAAI,EAAI,EAAM,IAAI,GAIrC,IAAK,CAAC,EAAyC,CAC3C,EAAQ,YAAc,SACtB,EAAQ,UAAY,EACpB,EAAQ,YAAc,IAGtB,QAAW,KAAY,KAAK,WACxB,EAAQ,UAAU,EAClB,EAAQ,OAAO,EAAS,MAAO,KAAK,EACpC,EAAQ,OAAO,EAAS,MAAO,IAAI,EACnC,EAAQ,OAAO,EAGf,EAAQ,UAAY,EAAS,MAAQ,QAAU,MAC/C,EAAQ,SAAS,EAAS,MAAQ,MAAQ,MAAO,EAAS,MAAO,IAAI,EAGzE,EAAQ,YAAc,EAI1B,QAAQ,EAAmD,CACvD,MAAO,CACH,cAAe,KAAK,WAAW,OAC/B,YAAa,KAAK,QAAQ,IAC9B,EAER,CAMO,MAAM,CAAqE,CACtE,KAA2B,KAC3B,UAAoB,EACpB,OAAiB,IAEzB,KAAK,EAAS,CACV,KAAK,KAAO,KACZ,KAAK,UAAY,EAGrB,MAAM,CAAC,EAAiB,CACpB,IAAM,EAAO,IAAI,EAAS,CAAM,EAChC,KAAK,WAAW,CAAI,EAGhB,UAAU,CAAC,EAAyB,CAGxC,GAFA,KAAK,YAED,CAAC,KAAK,KAAM,CACZ,KAAK,KAAO,EACZ,OAIJ,IAAI,EAAU,KAAK,gBAAgB,CAAI,EAGjC,EAAY,EAAQ,OACpB,EAAY,IAAI,EAItB,GAHA,EAAU,OAAS,EACnB,EAAU,UAAU,EAAS,CAAI,EAE7B,EAEA,GAAI,EAAU,SAAS,KAAO,EAC1B,EAAU,SAAS,GAAK,EAExB,OAAU,SAAS,GAAK,EAI5B,UAAK,KAAO,EAIhB,IAAI,EAAW,EAAU,OACzB,MAAO,EACH,EAAS,WAAW,KAAK,MAAM,EAC/B,EAAS,OAAS,EAAI,KAAK,IACvB,EAAS,SAAS,GAAK,EAAS,SAAS,GAAG,OAAS,EACrD,EAAS,SAAS,GAAK,EAAS,SAAS,GAAG,OAAS,CACzD,EAGA,EAAW,KAAK,QAAQ,CAAQ,EAChC,EAAW,EAAS,OAIpB,eAAe,CAAC,EAAgC,CACpD,IAAI,EAAU,KAAK,KAEnB,MAAO,CAAC,EAAQ,OAAO,EAAG,CACtB,IAAM,EAAS,EAAQ,SAAS,GAC1B,EAAS,EAAQ,SAAS,GAE1B,EAAO,KAAK,QAAQ,EAAQ,IAAI,EAChC,EAAe,KAAK,YAAY,EAAQ,KAAM,EAAK,IAAI,EACvD,EAAe,KAAK,QAAQ,CAAY,EAGxC,EAAO,EAAM,EAGb,EAAkB,GAAO,EAAe,GAG1C,EACE,EAAQ,KAAK,YAAY,EAAK,KAAM,EAAO,IAAI,EACrD,GAAI,EAAO,OAAO,EACd,EAAQ,KAAK,QAAQ,CAAK,EAAI,EAC3B,KACH,IAAM,EAAU,KAAK,QAAQ,EAAO,IAAI,EAExC,EADgB,KAAK,QAAQ,CAAK,EACf,EAAW,EAIlC,IAAI,EACE,EAAQ,KAAK,YAAY,EAAK,KAAM,EAAO,IAAI,EACrD,GAAI,EAAO,OAAO,EACd,EAAQ,KAAK,QAAQ,CAAK,EAAI,EAC3B,KACH,IAAM,EAAU,KAAK,QAAQ,EAAO,IAAI,EAExC,EADgB,KAAK,QAAQ,CAAK,EACf,EAAW,EAIlC,GAAI,EAAO,GAAS,EAAO,EACvB,MAIJ,EAAU,EAAQ,EAAQ,EAAS,EAGvC,OAAO,EAGH,OAAO,CAAC,EAAgC,CAC5C,GAAI,EAAK,OAAO,EACZ,OAAO,EAGX,IAAM,EAAU,EAAK,WAAW,EAGhC,GAAI,EAAU,GACV,OAAO,KAAK,WAAW,CAAI,EACxB,QAAI,EAAU,EACjB,OAAO,KAAK,YAAY,CAAI,EAGhC,OAAO,EAGH,UAAU,CAAC,EAAgC,CAC/C,IAAM,EAAS,EAAK,SAAS,GACvB,EAAe,EAAO,SAAS,GAC/B,EAAe,EAAO,SAAS,GAQrC,GALA,EAAO,SAAS,GAAK,EACrB,EAAO,OAAS,EAAK,OACrB,EAAK,OAAS,EAGV,EAAO,OACP,GAAI,EAAO,OAAO,SAAS,KAAO,EAC9B,EAAO,OAAO,SAAS,GAAK,EAE5B,OAAO,OAAO,SAAS,GAAK,EAGhC,UAAK,KAAO,EAIhB,GAAI,EAAa,OAAS,EAAa,OACnC,EAAO,SAAS,GAAK,EACrB,EAAK,SAAS,GAAK,EACnB,EAAa,OAAS,EACtB,EAAK,WAAW,KAAK,MAAM,EAC3B,EAAO,WAAW,KAAK,MAAM,EAC7B,EAAK,OAAS,EAAI,KAAK,IAAI,EAAK,SAAS,GAAI,OAAQ,EAAK,SAAS,GAAI,MAAM,EAC7E,EAAO,OAAS,EAAI,KAAK,IAAI,EAAK,OAAQ,EAAa,MAAM,EAE7D,OAAO,SAAS,GAAK,EACrB,EAAK,SAAS,GAAK,EACnB,EAAa,OAAS,EACtB,EAAK,WAAW,KAAK,MAAM,EAC3B,EAAO,WAAW,KAAK,MAAM,EAC7B,EAAK,OAAS,EAAI,KAAK,IAAI,EAAK,SAAS,GAAI,OAAQ,EAAK,SAAS,GAAI,MAAM,EAC7E,EAAO,OAAS,EAAI,KAAK,IAAI,EAAK,OAAQ,EAAa,MAAM,EAGjE,OAAO,EAGH,WAAW,CAAC,EAAgC,CAChD,IAAM,EAAS,EAAK,SAAS,GACvB,EAAe,EAAO,SAAS,GAC/B,EAAe,EAAO,SAAS,GAQrC,GALA,EAAO,SAAS,GAAK,EACrB,EAAO,OAAS,EAAK,OACrB,EAAK,OAAS,EAGV,EAAO,OACP,GAAI,EAAO,OAAO,SAAS,KAAO,EAC9B,EAAO,OAAO,SAAS,GAAK,EAE5B,OAAO,OAAO,SAAS,GAAK,EAGhC,UAAK,KAAO,EAIhB,GAAI,EAAa,OAAS,EAAa,OACnC,EAAO,SAAS,GAAK,EACrB,EAAK,SAAS,GAAK,EACnB,EAAa,OAAS,EACtB,EAAK,WAAW,KAAK,MAAM,EAC3B,EAAO,WAAW,KAAK,MAAM,EAC7B,EAAK,OAAS,EAAI,KAAK,IAAI,EAAK,SAAS,GAAI,OAAQ,EAAK,SAAS,GAAI,MAAM,EAC7E,EAAO,OAAS,EAAI,KAAK,IAAI,EAAa,OAAQ,EAAK,MAAM,EAE7D,OAAO,SAAS,GAAK,EACrB,EAAK,SAAS,GAAK,EACnB,EAAa,OAAS,EACtB,EAAK,WAAW,KAAK,MAAM,EAC3B,EAAO,WAAW,KAAK,MAAM,EAC7B,EAAK,OAAS,EAAI,KAAK,IAAI,EAAK,SAAS,GAAI,OAAQ,EAAK,SAAS,GAAI,MAAM,EAC7E,EAAO,OAAS,EAAI,KAAK,IAAI,EAAa,OAAQ,EAAK,MAAM,EAGjE,OAAO,EAGX,QAAQ,CAAC,EAAgB,CACrB,IAAM,EAAc,CAAC,EACrB,GAAI,CAAC,KAAK,KAAM,OAAO,EAEvB,IAAM,EAAuB,CAAC,KAAK,IAAI,EAEvC,MAAO,EAAM,OAAS,EAAG,CACrB,IAAM,EAAO,EAAM,IAAI,EAEvB,GAAI,KAAK,eAAe,EAAK,KAAM,EAAO,IAAI,EAC1C,GAAI,EAAK,OAAO,GACZ,GAAI,EAAK,QAAU,EAAK,SAAW,EAC/B,EAAO,KAAK,EAAK,MAAM,EAExB,KACH,GAAI,EAAK,SAAS,GAAI,EAAM,KAAK,EAAK,SAAS,EAAE,EACjD,GAAI,EAAK,SAAS,GAAI,EAAM,KAAK,EAAK,SAAS,EAAE,GAK7D,OAAO,EAGX,IAAI,CAAC,EAAyC,CAC1C,GAAI,CAAC,KAAK,KAAM,OAChB,KAAK,SAAS,EAAS,KAAK,KAAM,CAAC,EAG/B,QAAQ,CAAC,EAAmC,EAAmB,EAAqB,CACxF,IAAQ,MAAK,OAAQ,EAAK,KAGpB,EAAS,CAAC,MAAO,OAAQ,QAAS,SAAU,SAAU,OAAO,EAQnE,GAPA,EAAQ,YAAc,EAAO,EAAQ,EAAO,QAC5C,EAAQ,UAAY,KAAK,IAAI,EAAG,EAAI,CAAK,EAEzC,EAAQ,UAAU,EAClB,EAAQ,KAAK,EAAI,EAAG,EAAI,EAAG,EAAI,EAAI,EAAI,EAAG,EAAI,EAAI,EAAI,CAAC,EACvD,EAAQ,OAAO,EAEX,CAAC,EAAK,OAAO,EAAG,CAChB,GAAI,EAAK,SAAS,GAAI,KAAK,SAAS,EAAS,EAAK,SAAS,GAAI,EAAQ,CAAC,EACxE,GAAI,EAAK,SAAS,GAAI,KAAK,SAAS,EAAS,EAAK,SAAS,GAAI,EAAQ,CAAC,GAIxE,OAAO,CAAC,EAAoB,CAChC,OAAQ,EAAK,IAAI,EAAI,EAAK,IAAI,IAAM,EAAK,IAAI,EAAI,EAAK,IAAI,GAGtD,WAAW,CAAC,EAAa,EAAmB,CAChD,MAAO,CACH,IAAK,CACD,EAAG,KAAK,IAAI,EAAM,IAAI,EAAG,EAAM,IAAI,CAAC,EACpC,EAAG,KAAK,IAAI,EAAM,IAAI,EAAG,EAAM,IAAI,CAAC,CACxC,EACA,IAAK,CACD,EAAG,KAAK,IAAI,EAAM,IAAI,EAAG,EAAM,IAAI,CAAC,EACpC,EAAG,KAAK,IAAI,EAAM,IAAI,EAAG,EAAM,IAAI,CAAC,CACxC,CACJ,EAGI,cAAc,CAAC,EAAa,EAAsB,CACtD,MAAO,EAAE,EAAM,IAAI,EAAI,EAAM,IAAI,GACxB,EAAM,IAAI,EAAI,EAAM,IAAI,GACxB,EAAM,IAAI,EAAI,EAAM,IAAI,GACxB,EAAM,IAAI,EAAI,EAAM,IAAI,GAIrC,QAAQ,EAA0C,CAC9C,MAAO,CACH,UAAW,KAAK,UAChB,OAAQ,KAAK,KAAO,KAAK,KAAK,OAAS,CAC3C,EAER,CCtjBA,mBAAS,qBAIF,SAAS,EAAgB,CAAC,EAAkB,EAAkB,EAAqB,CAEtF,GAAI,EAAM,SAAS,GAAK,EAAM,SAAS,EACnC,OAEJ,IAAI,EAAc,IACd,EAAe,EAAM,SAAS,GAAK,EAAM,eAAe,EAAI,EAAI,EAAI,EAAM,KAC1E,EAAe,EAAM,SAAS,GAAK,EAAM,eAAe,EAAI,EAAI,EAAI,EAAM,KAI1E,EAAmB,EAAS,UAAU,EAAM,eAAgB,EAAM,cAAc,EAIhF,EAAI,EAAE,EAAI,GAAe,EAAS,WAAW,EAAkB,CAAM,EACzE,GAAK,EAAe,EAEpB,IAAI,EAAiB,EAAS,uBAAuB,EAAQ,EAAI,CAAY,EACzE,EAAiB,EAAS,uBAAuB,EAAQ,EAAI,CAAY,EAI7E,EAAM,eAAiB,EAAS,UAAU,EAAM,eAAgB,CAAc,EAC9E,EAAM,eAAiB,EAAS,UAAU,EAAM,eAAgB,CAAc,EAG3E,SAAS,EAA4B,CAAC,EAAkB,EAAkB,EAAyD,CAEtI,GAAI,EAAM,SAAS,GAAK,EAAM,SAAS,EACnC,OAGJ,IAAI,EAAc,IACd,EAAe,EAAM,SAAS,GAAK,EAAM,eAAe,EAAI,EAAI,EAAI,EAAM,KAC1E,EAAe,EAAM,SAAS,GAAK,EAAM,eAAe,EAAI,EAAI,EAAI,EAAM,KAE1E,EAAe,EAAM,SAAS,GAAK,EAAM,eAAe,EAAI,EAAI,EAAI,EAAM,gBAC1E,EAAe,EAAM,SAAS,GAAK,EAAM,eAAe,EAAI,EAAI,EAAI,EAAM,gBAExE,EAAc,CAAC,EACrB,QAAQ,EAAQ,EAAG,EAAQ,EAAgB,cAAc,OAAQ,IAAQ,CACrE,IAAM,EAAe,EAAgB,cAAc,GAC7C,EAAK,EAAS,UAAU,EAAc,EAAM,MAAM,EAClD,EAAK,EAAS,UAAU,EAAc,EAAM,MAAM,EAClD,EAAkB,CAAC,EAAG,CAAC,EAAG,EAAG,EAAG,EAAG,CAAC,EACpC,EAAkB,CAAC,EAAG,CAAC,EAAG,EAAG,EAAG,EAAG,CAAC,EAEpC,EAAmB,EAAS,uBAAuB,EAAiB,EAAM,eAAe,EACzF,EAAmB,EAAS,uBAAuB,EAAiB,EAAM,eAAe,EAK3F,EAAmB,EAAS,UAAU,EAAS,UAAU,EAAM,eAAgB,CAAgB,EAAG,EAAS,UAAU,EAAM,eAAgB,CAAgB,CAAC,EAI5J,EAAyB,EAAS,WAAW,EAAkB,EAAgB,MAAM,EACnF,EAAwB,EAAS,WAAW,EAAiB,EAAgB,MAAM,EACnF,EAAwB,EAAS,WAAW,EAAiB,EAAgB,MAAM,EAEnF,EAAc,EAAe,EAAe,EAAwB,EAAwB,EAAe,EAAwB,EAAwB,EAC7J,EAAI,EAAE,EAAI,GAAe,EAC7B,GAAK,EAEL,GAAK,EAAgB,cAAc,OAEnC,EAAG,KAAK,EAAS,uBAAuB,EAAgB,OAAQ,CAAC,CAAC,EAGtE,EAAG,QAAQ,CAAC,EAAS,IAAU,CAC3B,IAAI,EAAiB,EAAS,uBAAuB,EAAS,CAAY,EACtE,EAAiB,EAAS,uBAAuB,EAAS,CAAY,EAE1E,EAAM,eAAiB,EAAS,UAAU,EAAM,eAAgB,CAAc,EAC9E,IAAI,EAAO,EAAS,aAAa,EAAS,UAAU,EAAgB,cAAc,GAAQ,EAAM,MAAM,EAAG,CAAO,EAAE,EAClH,EAAO,GAAQ,KAAY,EAAI,EAC/B,IAAI,EAAO,EAAS,aAAa,EAAS,UAAU,EAAgB,cAAc,GAAQ,EAAM,MAAM,EAAG,CAAO,EAAE,EAClH,EAAO,GAAQ,KAAY,EAAI,EAC/B,EAAM,iBAAmB,EAAO,EAChC,EAAM,iBAAmB,EAAO,EAChC,EAAM,eAAiB,EAAS,UAAU,EAAM,eAAgB,CAAc,EACjF,EAGE,SAAS,CAAc,CAAC,EAAiC,EAAyC,CACrG,GAAK,EAAM,IAAI,GAAK,EAAM,IAAI,GAAK,EAAM,IAAI,GAAK,EAAM,IAAI,IAAO,EAAM,IAAI,GAAK,EAAM,IAAI,GAAK,EAAM,IAAI,GAAK,EAAM,IAAI,GACtH,MAAO,GAEX,MAAO,GAGJ,SAAS,CAAU,CAAC,EAAkB,EAAuE,CAChH,IAAI,EAAgB,CAAC,EACjB,EAAY,EAAM,iBAAiB,CAAK,EACxC,EAAY,EAAM,iBAAiB,CAAK,EAE5C,EAAK,KAAK,GAAG,CAAS,EACtB,EAAK,KAAK,GAAG,CAAS,EAEtB,IAAI,EAAY,GACZ,EAAW,OAAO,UAClB,EAAU,EAAK,GAoBnB,GAlBA,EAAK,QAAQ,KAAY,CACrB,IAAI,EAAgB,EAAM,oBAAoB,CAAQ,EAClD,EAAgB,EAAM,oBAAoB,CAAQ,EAEtD,GAAI,EAAc,KAAO,EAAc,KAAO,EAAc,KAAO,EAAc,IAC7E,EAAY,GACV,KACF,IAAI,EAAQ,KAAK,IAAI,KAAK,IAAI,EAAc,IAAK,EAAc,GAAG,EAAI,KAAK,IAAI,EAAc,IAAK,EAAc,GAAG,CAAC,EACpH,GAAI,EAAQ,GAGR,GAFA,EAAW,EACX,EAAU,EACN,EAAc,IAAM,EAAc,IAClC,EAAU,EAAS,uBAAuB,EAAS,EAAE,IAIpE,EAEG,EACA,MAAO,CAAC,UAAW,EAAW,MAAO,EAAU,OAAQ,CAAO,EAE9D,WAAO,CAAC,UAAW,GAAO,MAAO,OAAW,OAAQ,MAAS,EAI9D,SAAS,EAAwB,CAAC,EAAqB,EAA6D,EAAuC,CAC9J,GAAI,CAAC,EACD,MAAO,CAAC,EAEZ,IAAM,EAAyB,CAAC,EAiJhC,OAhJA,EAAoB,QAAQ,KAAe,CACvC,IAAwB,MAApB,EACoB,MAApB,GAAQ,EACZ,GAAI,GAAS,EAET,OAEJ,IAAI,EAAS,EAAM,OAAO,GAAK,KAAY,EAAI,EAAM,OAAO,EACxD,EAAS,EAAM,OAAO,GAAK,KAAY,EAAI,EAAM,OAAO,EAC5D,GAAG,KAAK,IAAI,EAAS,CAAM,EAAI,IAE3B,OAEJ,IAAK,YAAW,QAAO,OAAQ,GAAc,EAAW,EAAO,CAAK,EACpE,GAAI,GAAa,IAAe,QAAa,IAAU,OAAW,CAG9D,IAAI,EAAmB,EAAS,uBAAuB,EAAY,EAAQ,CAAC,EACxE,EAAsB,EAAS,uBAAuB,EAAY,CAAC,EAAQ,CAAC,EAEhF,GAAI,CAAC,EAAM,SAAS,EAChB,EAAM,KAAK,CAAgB,EAE/B,GAAI,CAAC,EAAM,SAAS,EAChB,EAAM,KAAK,CAAmB,EAElC,GAAI,EAAM,SAAS,EAEf,EAAM,KAAK,CAAmB,EAElC,GAAI,EAAM,SAAS,EACf,EAAM,KAAK,CAAgB,EAK/B,IAAM,EAAiB,EAAM,2BAA2B,EAAS,uBAAuB,EAAY,EAAE,CAAC,EACjG,EAAiB,EAAM,2BAA2B,CAAU,EAC5D,EAAmB,EAAM,uBAAuB,EAAS,uBAAuB,EAAY,EAAE,CAAC,EAC/F,EAAmB,EAAM,uBAAuB,CAAU,EAC1D,EAAyB,KAAK,IAAI,EAAS,WAAW,EAAgB,EAAS,uBAAuB,EAAY,EAAE,CAAC,CAAC,EACtH,EAAyB,KAAK,IAAI,EAAS,WAAW,EAAgB,CAAU,CAAC,EAEvF,GAAI,EAAiB,QAAU,GAAK,EAAiB,QAAU,EAG3D,GAAI,EAAiB,QAAU,EAG3B,EAAc,KAAK,EAAiB,EAAE,EAItC,OAAc,KAAK,EAAiB,EAAE,EAGzC,QAAI,EAAyB,EAAwB,CAEtD,IAAM,EAAgB,EAAM,iBAAiB,EAAS,uBAAuB,EAAY,EAAE,CAAC,EACxF,EAAa,CAAC,GAAG,CAAgB,EACrC,QAAQ,EAAQ,EAAG,EAAQ,EAAc,OAAS,EAAG,IAAQ,CACzD,IAAI,EAAa,EAAc,GAAO,WAAW,MAC7C,EAAW,EAAc,GAAO,SAAS,MACzC,EAAY,EAAS,UAAU,EAAU,CAAU,EACnD,EAAW,EAAS,UAAU,EAAW,GAAI,CAAU,EACvD,EAAS,EAAS,UAAU,EAAW,GAAI,CAAU,EACrD,EAAc,EAAS,aAAa,EAAW,CAAQ,GAAK,EAC5D,EAAY,EAAS,aAAa,EAAW,CAAM,GAAK,EAC5D,IAAK,EAAc,EAAI,IAAM,EAAY,EAAI,GAAG,CAE5C,IAAI,EAAoB,EAAS,oBAAoB,EAAY,EAAU,EAAW,GAAI,EAAW,EAAE,EACvG,GAAI,EAAkB,YAAc,EAAkB,eAAiB,OACnE,GAAG,EACC,EAAW,GAAK,EAAkB,aAElC,OAAW,GAAK,EAAkB,cAKlD,IAAM,EAAgB,EAAc,EAAc,OAAS,GACvD,EAAa,EAAc,WAAW,MACtC,EAAW,EAAc,SAAS,MAClC,EAAY,EAAS,UAAU,EAAU,CAAU,EACnD,EAAW,EAAS,UAAU,EAAW,GAAI,CAAU,EACvD,EAAS,EAAS,UAAU,EAAW,GAAI,CAAU,EACrD,EAAc,EAAS,aAAa,EAAW,CAAQ,GAAK,EAC5D,EAAY,EAAS,aAAa,EAAW,CAAM,GAAK,EAC5D,GAAI,EACA,EAAc,KAAK,EAAW,EAAE,EAEpC,GAAI,EACA,EAAc,KAAK,EAAW,EAAE,EAEjC,KAEH,IAAM,EAAgB,EAAM,iBAAiB,CAAU,EACnD,EAAa,CAAC,GAAG,CAAgB,EACrC,GAAG,EAAW,QAAU,EACpB,QAAQ,IAAI,SAAS,EAEzB,IAAI,EAAQ,EACZ,QAAQ,EAAQ,EAAG,EAAQ,EAAc,OAAS,EAAG,IAAQ,CACzD,IAAI,EAAa,EAAc,GAAO,WAAW,MAC7C,EAAW,EAAc,GAAO,SAAS,MACzC,EAAY,EAAS,UAAU,EAAU,CAAU,EACnD,EAAW,EAAS,UAAU,EAAW,GAAI,CAAU,EACvD,EAAS,EAAS,UAAU,EAAW,GAAI,CAAU,EACrD,EAAc,EAAS,aAAa,EAAW,CAAQ,GAAK,EAC5D,EAAY,EAAS,aAAa,EAAW,CAAM,GAAK,EAC5D,IAAK,EAAc,EAAI,IAAM,EAAY,EAAI,GAAG,CAC5C,GAAS,EAET,IAAI,EAAoB,EAAS,oBAAoB,EAAY,EAAU,EAAW,GAAI,EAAW,EAAE,EACvG,GAAI,EAAkB,YAAc,EAAkB,eAAiB,OACnE,GAAG,EACC,EAAW,GAAK,EAAkB,aAElC,OAAW,GAAK,EAAkB,cAKlD,IAAM,EAAgB,EAAc,EAAc,OAAS,GACvD,EAAa,EAAc,WAAW,MACtC,EAAW,EAAc,SAAS,MAClC,EAAY,EAAS,UAAU,EAAU,CAAU,EACnD,EAAW,EAAS,UAAU,EAAW,GAAI,CAAU,EACvD,EAAS,EAAS,UAAU,EAAW,GAAI,CAAU,EACrD,EAAc,EAAS,aAAa,EAAW,CAAQ,GAAK,EAC5D,EAAY,EAAS,aAAa,EAAW,CAAM,GAAK,EAC5D,GAAI,EACA,EAAc,KAAK,EAAW,EAAE,EAEpC,GAAI,EACA,EAAc,KAAK,EAAW,EAAE,EAGxC,GAAI,EACA,GAA6B,EAAO,EAAO,CAAC,OAAQ,EAAY,cAAe,CAAa,CAAC,GAIxG,EACM,EAGJ,SAAS,EAAW,CAAC,EAAyB,EAAiE,EAAqC,CACvJ,GAAI,CAAC,EACD,OAEJ,EAAoB,QAAQ,KAAe,CACvC,IAAI,EAAQ,EAAO,EAAY,YAC3B,EAAQ,EAAO,EAAY,aAC1B,YAAW,QAAO,OAAQ,GAAc,EAAW,EAAO,CAAK,EACpE,GAAI,GAAa,IAAe,QAAa,IAAU,OAAW,CAE9D,IAAI,EAAmB,EAAS,uBAAuB,EAAY,EAAQ,CAAC,EACxE,EAAsB,EAAS,uBAAuB,EAAY,CAAC,EAAQ,CAAC,EAEhF,GAAI,CAAC,EAAM,SAAS,EAChB,EAAM,KAAK,CAAgB,EAE/B,GAAI,CAAC,EAAM,SAAS,EAChB,EAAM,KAAK,CAAmB,EAElC,GAAI,EAAM,SAAS,EAEf,EAAM,KAAK,CAAmB,EAElC,GAAI,EAAM,SAAS,EACf,EAAM,KAAK,CAAgB,EAI/B,GAAI,EACA,GAAiB,EAAO,EAAO,CAAU,GAIpD,EAGE,SAAS,EAA+B,CAAC,EAA+B,EAA4D,CACvI,IAAI,EAAwD,CAAC,EAC7D,QAAQ,EAAQ,EAAG,GAAS,EAAO,OAAS,EAAG,IAAQ,CACnD,IAAI,EAAc,EAAS,SAAS,EAAO,EAAM,EACjD,QAAQ,EAAS,EAAG,GAAU,EAAY,OAAS,EAAG,IAAS,CAC3D,IAAI,EAAQ,EAAO,GACf,EAAQ,EAAY,GACxB,GAAI,EAAM,SAAS,GAAK,EAAM,SAAS,EACnC,SAEJ,GAAG,CAAC,EAAe,EAAM,KAAM,EAAM,IAAI,EACrC,SAEJ,EAAc,KAAK,CAAC,MAAO,EAAO,MAAO,CAAK,CAAC,GAGvD,OAAO,EAGJ,SAAS,EAA0B,CAAC,EAAgE,EAA4D,CACnK,IAAI,EAAwD,CAAC,EAC7D,QAAQ,EAAQ,EAAG,GAAS,EAAO,OAAS,EAAG,IAAQ,CACnD,IAAI,EAAc,EAAa,SAAS,EAAO,EAAM,EACrD,QAAQ,EAAS,EAAG,GAAU,EAAY,OAAS,EAAG,IAAS,CAC3D,IAAI,EAAQ,EAAO,GACf,EAAQ,EAAY,GACxB,GAAI,EAAM,SAAS,GAAK,EAAM,SAAS,EACnC,SAEJ,GAAG,CAAC,EAAe,EAAM,KAAM,EAAM,IAAI,EACrC,SAEJ,EAAc,KAAK,CAAC,MAAO,EAAO,MAAO,CAAK,CAAC,GAGvD,OAAO,EAGJ,SAAS,EAAU,CAAC,EAA+B,EAAoE,CAC1H,IAAI,EAA4D,CAAC,EACjE,QAAQ,EAAQ,EAAG,GAAS,EAAO,OAAS,EAAG,IAAQ,CACnD,IAAI,EAAc,EAAS,SAAS,EAAO,EAAM,EACjD,QAAQ,EAAS,EAAG,GAAU,EAAY,OAAS,EAAG,IAAS,CAC3D,IAAI,EAAQ,EAAO,GACf,EAAQ,EAAY,GACxB,GAAI,EAAM,SAAS,GAAK,EAAM,SAAS,EACnC,SAEJ,GAAG,CAAC,EAAe,EAAM,KAAM,EAAM,IAAI,EACrC,SAEJ,EAAc,KAAK,CAAC,WAAY,EAAO,WAAY,CAAM,CAAC,GAGlE,OAAO,EAIJ,SAAS,EAAkC,CAAC,EAAgE,EAA4D,CAC3K,IAAI,EAAwD,CAAC,EAC7D,QAAQ,EAAQ,EAAG,GAAS,EAAO,OAAS,EAAG,IAAQ,CACnD,IAAI,EAAc,EAAa,SAAS,EAAO,EAAM,EACrD,QAAQ,EAAS,EAAG,GAAU,EAAY,OAAS,EAAG,IAAS,CAC3D,IAAI,EAAQ,EAAO,GACf,EAAQ,EAAY,GAGxB,GAAI,EAAM,SAAS,GAAK,EAAM,SAAS,EACnC,SAIJ,GAAI,CAAC,EAAW,EAAM,gBAAiB,EAAM,eAAe,EACxD,SAIJ,GAAG,CAAC,EAAe,EAAM,KAAM,EAAM,IAAI,EACrC,SAGJ,EAAc,KAAK,CAAC,MAAO,EAAO,MAAO,CAAK,CAAC,GAGvD,OAAO,EAIJ,SAAS,EAAgC,CAAC,EAAqB,EAA6D,EAGjI,CACE,IAAM,EAAyB,CAAC,EAC1B,EAA6G,CAAC,EAsDpH,OApDA,EAAoB,QAAQ,KAAe,CACvC,IAAwB,MAApB,EACoB,MAApB,GAAQ,GAEP,YAAW,QAAO,OAAQ,GAAc,EAAW,EAAO,CAAK,EACpE,GAAI,GAAa,IAAe,QAAa,IAAU,OAAW,CAE9D,IAAM,EAAkC,CAAC,EAInC,EAAgB,CAClB,GAAI,EAAM,OAAO,EAAI,EAAM,OAAO,GAAK,EACvC,GAAI,EAAM,OAAO,EAAI,EAAM,OAAO,GAAK,CAC3C,EACA,EAAuB,KAAK,CAAa,EAEzC,IAAM,EAAgB,CAClB,QACA,QACA,cAAe,EACf,OAAQ,EACR,MAAO,CACX,EAKA,GAHA,EAAW,KAAK,CAAa,EAC7B,EAAc,KAAK,GAAG,CAAsB,EAExC,EAAsB,CAEtB,IAAI,EAAmB,EAAS,uBAAuB,EAAY,EAAQ,CAAC,EACxE,EAAsB,EAAS,uBAAuB,EAAY,CAAC,EAAQ,CAAC,EAEhF,GAAI,CAAC,EAAM,SAAS,EAChB,EAAM,KAAK,CAAgB,EAE/B,GAAI,CAAC,EAAM,SAAS,EAChB,EAAM,KAAK,CAAmB,EAElC,GAAI,EAAM,SAAS,EACf,EAAM,KAAK,CAAmB,EAElC,GAAI,EAAM,SAAS,EACf,EAAM,KAAK,CAAgB,EAI/B,GAA6B,EAAO,EAAO,CAAC,OAAQ,EAAY,cAAe,CAAsB,CAAC,IAGjH,EAEM,CAAE,gBAAe,YAAW,EC7ZhC,MAAM,CAAY,CACb,MAAQ,IAAI,IACZ,YAAc,EACd,WAAa,GAErB,WAAW,EAAG,EAGN,SAAS,CAAC,EAAkB,EAA0B,CAC1D,IAAM,EAAM,KAAK,UAAU,CAAK,EAC1B,EAAM,KAAK,UAAU,CAAK,EAEhC,OAAO,EAAM,EAAM,GAAG,KAAO,IAAQ,GAAG,KAAO,IAG3C,SAAS,CAAC,EAAyB,CAEvC,OAAO,EAAK,SAAS,EAIzB,WAAW,CAAC,EAA4H,CACpI,KAAK,cAEL,IAAM,EAAqB,CACvB,QAAS,CAAC,EACV,QAAS,CAAC,EACV,QAAS,CAAC,CACd,EAGA,KAAK,MAAM,QAAQ,KAAQ,CACvB,EAAK,SAAW,GACnB,EAGD,QAAW,KAAa,EAAe,CACnC,IAAM,EAAK,KAAK,UAAU,EAAU,MAAO,EAAU,KAAK,EACpD,EAAe,KAAK,MAAM,IAAI,CAAE,EAEtC,GAAI,EAEA,EAAa,SAAW,GACxB,EAAa,aAAe,KAAK,YACjC,EAAa,cAAgB,EAAU,eAAiB,CAAC,EACzD,EAAa,OAAS,EAAU,OAChC,EAAa,MAAQ,EAAU,MAC/B,EAAO,QAAQ,KAAK,CAAY,EAC7B,KAEH,IAAM,EAAyB,CAC3B,MAAO,EAAU,MACjB,MAAO,EAAU,MACjB,KACA,SAAU,GACV,cAAe,EAAU,eAAiB,CAAC,EAC3C,OAAQ,EAAU,OAClB,MAAO,EAAU,MACjB,aAAc,KAAK,YACnB,aAAc,KAAK,WACvB,EACA,KAAK,MAAM,IAAI,EAAI,CAAO,EAC1B,EAAO,QAAQ,KAAK,CAAO,GAKnC,IAAM,EAA0B,CAAC,EAYjC,OAXA,KAAK,MAAM,QAAQ,CAAC,EAAM,IAAO,CAC7B,GAAI,CAAC,EAAK,UAAa,KAAK,YAAc,EAAK,aAAgB,KAAK,WAChE,EAAc,KAAK,CAAE,EACrB,EAAO,QAAQ,KAAK,CAAI,EAE/B,EAED,EAAc,QAAQ,KAAM,CACxB,KAAK,MAAM,OAAO,CAAE,EACvB,EAEM,EAIX,cAAc,EAAoB,CAC9B,OAAO,MAAM,KAAK,KAAK,MAAM,OAAO,CAAC,EAAE,OAAO,KAAQ,EAAK,QAAQ,EAIvE,OAAO,CAAC,EAAkB,EAA6C,CACnE,IAAM,EAAK,KAAK,UAAU,EAAO,CAAK,EACtC,OAAO,KAAK,MAAM,IAAI,CAAE,EAI5B,KAAK,EAAS,CACV,KAAK,MAAM,MAAM,EACjB,KAAK,YAAc,EAIvB,QAAQ,EAAG,CACP,MAAO,CACH,WAAY,KAAK,MAAM,KACvB,YAAa,KAAK,eAAe,EAAE,OACnC,YAAa,KAAK,WACtB,EAER,CCrGO,MAAM,EAAM,CACP,cACA,aACA,kBACA,cACA,eACA,MACA,aACA,iBACA,YACA,UAAkC,CAAC,EACnC,YACA,eAA0B,GAClC,SAA4C,KAE5C,WAAW,CAAC,EAAuB,EAAwB,EAAqC,cAAc,CAO1G,GANA,KAAK,eAAiB,EACtB,KAAK,cAAgB,EACrB,KAAK,iBAAmB,EACxB,KAAK,MAAQ,IAAI,EAAe,CAAC,EAAG,CAAC,KAAK,cAAe,EAAG,CAAC,KAAK,cAAc,EAAG,EAAI,KAAK,cAAe,EAAI,KAAK,cAAc,EAG9H,IAAqB,cACrB,KAAK,aAAe,IAAI,EACrB,QAAI,IAAqB,MAC5B,KAAK,aAAe,IAAI,EAExB,UAAK,aAAe,IAAI,EAAS,EAAG,KAAK,KAAK,EAGlD,KAAK,cAAgB,CAAC,EACtB,KAAK,aAAe,IAAI,IACxB,KAAK,kBAAoB,GACzB,KAAK,YAAc,CAAC,EACpB,KAAK,YAAc,IAAI,EAG3B,YAAY,CAAC,EAAe,EAAsB,CAK9C,GAJA,KAAK,cAAc,KAAK,CAAI,EAC5B,KAAK,aAAa,IAAI,EAAO,CAAI,EAG7B,KAAK,mBAAqB,MAC1B,KAAK,aAAa,OAAO,CAAI,EAIrC,eAAe,CAAC,EAAoB,CAChC,GAAI,KAAK,aAAa,IAAI,CAAK,EAAG,CAC9B,IAAM,EAAO,KAAK,aAAa,IAAI,CAAK,EAIxC,GAHA,KAAK,aAAa,OAAO,CAAK,EAG1B,GAAQ,KAAK,mBAAqB,OAAS,KAAK,wBAAwB,EACvE,KAAK,aAA0C,OAAO,CAAI,EAI/D,IAAM,EAAQ,KAAK,cAAc,UAAU,KAAK,IAAM,CAAI,EAC1D,GAAI,IAAU,GACV,KAAK,cAAc,OAAO,EAAO,CAAC,GAK9C,IAAI,CAAC,EAAwB,CAEzB,GAAI,KAAK,eACL,KAAK,iBAAiB,EAAE,QAAQ,KAAa,CACzC,EAAU,eAAe,CAAS,EACrC,EAGL,GAAG,KAAK,kBAAkB,CACtB,IAAM,EAAgB,KAAK,sBAAsB,EAcrD,KAAK,YAAY,QAAQ,KAAc,EAAW,QAAQ,CAAS,CAAC,EACpE,KAAK,iBAAiB,EAAE,QAAQ,KAAa,CACzC,GAAI,CAAC,EAAU,WACX,EAAU,KAAK,CAAS,EAE/B,EAGL,qBAAqB,EAAW,CAC5B,IAAI,EAA6B,CAAC,EAGlC,GAAI,KAAK,mBAAqB,MAE1B,KAAK,aAAa,QAAQ,CAAC,IAAS,CAChC,GAAI,CAAC,KAAK,gBAAkB,CAAC,EAAK,YAG9B,GAFA,EAAc,KAAK,CAAI,EAEnB,KAAK,wBAAwB,EAC5B,KAAK,aAA0C,OAAO,CAAI,GAGtE,EAGD,UAAK,aAAa,MAAM,EACxB,KAAK,aAAa,QAAQ,CAAC,IAAS,CAChC,GAAI,CAAC,KAAK,gBAAkB,CAAC,EAAK,WAC9B,EAAc,KAAK,CAAI,EACvB,KAAK,aAAa,OAAO,CAAI,EAEpC,EAIL,IAAI,EAAiC,GAAmC,KAAK,aAAc,CAAa,EACpG,EAA6B,GAAiC,EAAe,EAAsB,KAAK,iBAAiB,EAGvH,EAAa,KAAK,YAAY,YAAY,EAAiB,UAAU,EAG3E,GAAI,KAAK,eACL,EAAW,QAAQ,QAAQ,KAAQ,CAC/B,GAAI,EAAK,MAAM,WAAY,EAAK,MAAM,YAAY,EAAK,EACvD,GAAI,EAAK,MAAM,WAAY,EAAK,MAAM,YAAY,EAAK,EAC1D,EAGL,OAAO,EAAiB,iBAGxB,iBAAgB,EAAW,CAC3B,OAAO,KAAK,qBAGZ,iBAAgB,CAAC,EAA0B,CAC3C,KAAK,kBAAoB,EAG7B,gBAAgB,EAAE,CACd,IAAI,EAA4B,CAAC,EAIjC,OAHA,KAAK,aAAa,QAAQ,CAAC,IAAS,CAChC,EAAc,KAAK,CAAI,EAC1B,EACM,EAGX,eAAe,EAA0B,CACrC,OAAO,KAAK,aAGhB,iBAAiB,CAAC,EAAe,CAC7B,KAAK,eAAiB,EAG1B,gBAAgB,CAAC,EAAc,CAC3B,KAAK,cAAgB,EAGzB,aAAa,CAAC,EAA6B,CACvC,KAAK,YAAY,KAAK,CAAU,EAGpC,cAAc,EAAgB,CAC1B,OAAO,KAAK,YAGhB,WAAW,CAAC,EAAkB,EAAkB,EAAgB,EAAgB,CAC5E,KAAK,UAAU,KAAK,CAAE,QAAO,QAAO,UAAS,SAAQ,CAAC,KAGtD,wBAAuB,EAAqB,CAC5C,OAAO,KAAK,iBAGhB,mBAAmB,CAAC,EAA8B,CAC9C,GAAI,IAAS,KAAK,iBAAkB,OAGpC,GADA,KAAK,iBAAmB,EACpB,IAAS,cACT,KAAK,aAAe,IAAI,EACrB,QAAI,IAAS,MAChB,KAAK,aAAe,IAAI,EAExB,UAAK,aAAe,IAAI,EAAS,EAAG,KAAK,KAAK,EAItD,oBAAoB,EAAQ,CACxB,GAAI,KAAK,wBAAwB,EAC7B,OAAQ,KAAK,aAAwC,SAAS,EAC3D,QAAI,KAAK,wBAAwB,EACpC,MAAO,CACH,KAAM,KAAK,oBACP,KAAK,aAA0C,SAAS,CAChE,EAEJ,MAAO,CAAE,KAAM,KAAK,iBAAkB,QAAS,KAAK,aAAa,IAAK,KAItE,gBAAe,EAAY,CAC3B,OAAO,KAAK,kBAGZ,gBAAe,CAAC,EAAkB,CAElC,GADA,KAAK,eAAiB,EAClB,CAAC,EAED,KAAK,aAAa,QAAQ,KAAQ,CAC9B,GAAI,EAAK,WACL,EAAK,YAAY,EAAK,EAE7B,EAKT,cAAc,EAAgB,CAC1B,OAAO,KAAK,YAIhB,iBAAiB,EAAG,CAChB,MAAO,IACA,KAAK,YAAY,SAAS,EAC7B,eAAgB,MAAM,KAAK,KAAK,aAAa,OAAO,CAAC,EAAE,OAAO,KAAQ,EAAK,UAAU,EAAE,OACvF,YAAa,KAAK,aAAa,IACnC,EAER,CC9SA,mBAAgB,qBAgDT,MAAM,EAAoC,CAErC,QACA,aACA,MAER,WAAW,CAAC,EAAkB,EAAgB,EAAqB,CAC/D,KAAK,MAAQ,EACb,KAAK,QAAU,EACf,KAAK,aAAe,EAGxB,OAAO,CAAC,EAAkB,CACtB,KAAK,6BAA6B,CAAE,EAGxC,4BAA4B,CAAC,EAAY,CACrC,IAAM,EAAO,KAAK,MACZ,EAAc,KAAK,QACnB,EAAc,KAAK,aAGnB,EAAoB,EAAS,UAAU,EAAK,OAAQ,EAAS,YAAY,EAAa,EAAK,gBAAgB,CAAC,EAG5G,EAAO,EAAS,UAAU,EAAmB,CAAW,EAGxD,EAAI,EAAS,UAAU,EAAmB,EAAK,MAAM,EACrD,EAAW,EAAS,UACtB,EAAK,eACL,EAAS,aAAa,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAK,eAAe,EAAG,CAAC,CAClE,EAGM,EAAU,EAAK,SAAS,EAAI,EAAI,EAAI,EAAK,KACzC,EAAO,EAAK,SAAS,EAAI,EAAI,EAAI,EAAK,gBAEtC,EAAI,CACN,EAAG,EAAU,EAAO,EAAE,EAAI,EAAE,EAC5B,EAAG,EAAU,EAAO,EAAE,EAAI,EAAE,EAC5B,GAAI,CAAC,EAAO,EAAE,EAAI,EAAE,CACxB,EAGM,EAAY,EACZ,EAAU,CACZ,EAAG,CAAC,EAAE,EAAI,EAAK,EAAI,EAAE,GAAK,EAAK,EAFjB,EAEiC,EAAK,EAAI,EAAK,EAAS,EACtE,EAAG,CAAC,EAAE,GAAK,EAAK,EAAI,EAAE,EAAI,EAAK,EAHjB,EAGiC,EAAK,EAAI,EAAK,EAAS,CAC1E,EAGA,GAAI,CAAC,EAAK,SAAS,EACf,EAAK,eAAe,GAAK,EAAU,EAAQ,EAC3C,EAAK,eAAe,GAAK,EAAU,EAAQ,EAC3C,EAAK,iBAAmB,GAAQ,EAAE,EAAI,EAAQ,EAAI,EAAE,EAAI,EAAQ,GAG5E,CA+BO,MAAM,EAA+B,CAEhC,QACA,QACA,MACA,MAER,WAAW,CAAC,EAAkB,EAAkB,EAAgB,EAAgB,CAC5E,KAAK,MAAQ,EACb,KAAK,MAAQ,EACb,KAAK,QAAU,EACf,KAAK,QAAU,EAGnB,OAAO,CAAC,EAAkB,CACtB,KAAK,wBAAwB,CAAE,EAGnC,uBAAuB,CAAC,EAAY,CAChC,IAAM,EAAQ,KAAK,MACb,EAAQ,KAAK,MACb,EAAU,KAAK,QACf,EAAU,KAAK,QAGf,EAAe,EAAS,UAAU,EAAM,OAAQ,EAAS,YAAY,EAAS,EAAM,gBAAgB,CAAC,EACrG,EAAe,EAAS,UAAU,EAAM,OAAQ,EAAS,YAAY,EAAS,EAAM,gBAAgB,CAAC,EAGrG,EAAO,EAAS,UAAU,EAAc,CAAY,EAGpD,EAAK,EAAS,UAAU,EAAc,EAAM,MAAM,EAClD,EAAK,EAAS,UAAU,EAAc,EAAM,MAAM,EAClD,EAAmB,EAAS,UAC9B,EAAS,UAAU,EAAM,eAAgB,EAAS,aAAa,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAM,eAAe,EAAG,CAAE,CAAC,EAC1G,EAAS,UAAU,EAAM,eAAgB,EAAS,aAAa,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAM,eAAe,EAAG,CAAE,CAAC,CAC9G,EAGM,EAAW,EAAM,SAAS,EAAI,EAAI,EAAI,EAAM,KAC5C,EAAW,EAAM,SAAS,EAAI,EAAI,EAAI,EAAM,KAC5C,EAAQ,EAAM,SAAS,EAAI,EAAI,EAAI,EAAM,gBACzC,EAAQ,EAAM,SAAS,EAAI,EAAI,EAAI,EAAM,gBAEzC,EAAI,CACN,EAAG,EAAW,EAAW,EAAQ,EAAG,EAAI,EAAG,EAAI,EAAQ,EAAG,EAAI,EAAG,EACjE,EAAG,EAAW,EAAW,EAAQ,EAAG,EAAI,EAAG,EAAI,EAAQ,EAAG,EAAI,EAAG,EACjE,GAAI,CAAC,EAAQ,EAAG,EAAI,EAAG,EAAI,EAAQ,EAAG,EAAI,EAAG,CACjD,EAGM,EAAY,EACZ,EAAU,CACZ,EAAG,CAAC,EAAE,EAAI,EAAK,EAAI,EAAE,GAAK,EAAK,EAFjB,EAEiC,EAAK,EAAI,EAAK,EAAiB,EAC9E,EAAG,CAAC,EAAE,GAAK,EAAK,EAAI,EAAE,EAAI,EAAK,EAHjB,EAGiC,EAAK,EAAI,EAAK,EAAiB,CAClF,EAGA,GAAI,CAAC,EAAM,SAAS,EAChB,EAAM,eAAe,GAAK,EAAW,EAAQ,EAC7C,EAAM,eAAe,GAAK,EAAW,EAAQ,EAC7C,EAAM,iBAAmB,GAAS,EAAG,EAAI,EAAQ,EAAI,EAAG,EAAI,EAAQ,GAGxE,GAAI,CAAC,EAAM,SAAS,EAChB,EAAM,eAAe,GAAK,EAAW,EAAQ,EAC7C,EAAM,eAAe,GAAK,EAAW,EAAQ,EAC7C,EAAM,iBAAmB,GAAS,EAAG,EAAI,EAAQ,EAAI,EAAG,EAAI,EAAQ,GAIhF,CASO,SAAS,EAAuB,CAAC,EAAgC,EAAY,CAChF,IAAQ,QAAO,QAAO,UAAS,WAAY,EAGrC,EAAe,EAAS,UAAU,EAAM,OAAQ,EAAS,YAAY,EAAS,EAAM,gBAAgB,CAAC,EACrG,EAAe,EAAS,UAAU,EAAM,OAAQ,EAAS,YAAY,EAAS,EAAM,gBAAgB,CAAC,EAGrG,EAAO,EAAS,UAAU,EAAc,CAAY,EAGpD,EAAK,EAAS,UAAU,EAAc,EAAM,MAAM,EAClD,EAAK,EAAS,UAAU,EAAc,EAAM,MAAM,EAClD,EAAmB,EAAS,UAC9B,EAAS,UAAU,EAAM,eAAgB,EAAS,aAAa,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAM,eAAe,EAAG,CAAE,CAAC,EAC1G,EAAS,UAAU,EAAM,eAAgB,EAAS,aAAa,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAM,eAAe,EAAG,CAAE,CAAC,CAC9G,EAGM,EAAW,EAAM,SAAS,EAAI,EAAI,EAAI,EAAM,KAC5C,EAAW,EAAM,SAAS,EAAI,EAAI,EAAI,EAAM,KAC5C,EAAQ,EAAM,SAAS,EAAI,EAAI,EAAI,EAAM,gBACzC,EAAQ,EAAM,SAAS,EAAI,EAAI,EAAI,EAAM,gBAEzC,EAAI,CACN,EAAG,EAAW,EAAW,EAAQ,EAAG,EAAI,EAAG,EAAI,EAAQ,EAAG,EAAI,EAAG,EACjE,EAAG,EAAW,EAAW,EAAQ,EAAG,EAAI,EAAG,EAAI,EAAQ,EAAG,EAAI,EAAG,EACjE,GAAI,CAAC,EAAQ,EAAG,EAAI,EAAG,EAAI,EAAQ,EAAG,EAAI,EAAG,CACjD,EAGM,EAAY,IACZ,EAAU,CACZ,EAAG,CAAC,EAAE,EAAI,EAAK,EAAI,EAAE,GAAK,EAAK,EAFjB,IAEiC,EAAK,EAAI,EAAK,EAAiB,EAC9E,EAAG,CAAC,EAAE,GAAK,EAAK,EAAI,EAAE,EAAI,EAAK,EAHjB,IAGiC,EAAK,EAAI,EAAK,EAAiB,CAClF,EAGA,GAAI,CAAC,EAAM,SAAS,EAChB,EAAM,eAAe,GAAK,EAAW,EAAQ,EAC7C,EAAM,eAAe,GAAK,EAAW,EAAQ,EAC7C,EAAM,iBAAmB,GAAS,EAAG,EAAI,EAAQ,EAAI,EAAG,EAAI,EAAQ,GAGxE,GAAI,CAAC,EAAM,SAAS,EAChB,EAAM,eAAe,GAAK,EAAW,EAAQ,EAC7C,EAAM,eAAe,GAAK,EAAW,EAAQ,EAC7C,EAAM,iBAAmB,GAAS,EAAG,EAAI,EAAQ,EAAI,EAAG,EAAI,EAAQ,GAUrE,SAAS,EAA4B,CAAC,EAAqC,EAAY,CAC1F,IAAQ,OAAM,cAAa,eAAgB,EAGrC,EAAoB,EAAS,UAAU,EAAK,OAAQ,EAAS,YAAY,EAAa,EAAK,gBAAgB,CAAC,EAG5G,EAAO,EAAS,UAAU,EAAmB,CAAW,EAGxD,EAAI,EAAS,UAAU,EAAmB,EAAK,MAAM,EACrD,EAAW,EAAS,UACtB,EAAK,eACL,EAAS,aAAa,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAK,eAAe,EAAG,CAAC,CAClE,EAGM,EAAU,EAAK,SAAS,EAAI,EAAI,EAAI,EAAK,KACzC,EAAO,EAAK,SAAS,EAAI,EAAI,EAAI,EAAK,gBAEtC,EAAI,CACN,EAAG,EAAU,EAAO,EAAE,EAAI,EAAE,EAC5B,EAAG,EAAU,EAAO,EAAE,EAAI,EAAE,EAC5B,GAAI,CAAC,EAAO,EAAE,EAAI,EAAE,CACxB,EAGM,EAAY,IACZ,EAAU,CACZ,EAAG,CAAC,EAAE,EAAI,EAAK,EAAI,EAAE,GAAK,EAAK,EAFjB,IAEiC,EAAK,EAAI,EAAK,EAAS,EACtE,EAAG,CAAC,EAAE,GAAK,EAAK,EAAI,EAAE,EAAI,EAAK,EAHjB,IAGiC,EAAK,EAAI,EAAK,EAAS,CAC1E,EAGA,GAAI,CAAC,EAAK,SAAS,EACf,EAAK,eAAe,GAAK,EAAU,EAAQ,EAC3C,EAAK,eAAe,GAAK,EAAU,EAAQ,EAC3C,EAAK,iBAAmB,GAAQ,EAAE,EAAI,EAAQ,EAAI,EAAE,EAAI,EAAQ",
15
+ "debugId": "ABD8E4A8414E2D7E64756E2164756E21",
16
16
  "names": []
17
17
  }