local i=require("\064\112\107\103\047\064\106\115\100\111\116\108\117\097\047\106\101\115\116-\103\108\111\098\097\108\115")local J=require("\046\046\047\118\101\099\116\111\114\115")local d=i.expect local k=i.it local H=i.beforeAll local l=i.describe local F=20 local m H(function()m=J(Random.new())end)l("\117\110\105\116",function()k("\114\101\116\117\114\110\115 \086\101\099\116\111\114\050 \111\102 \108\101\110\103\116\104 \061 \049",function()for i=1,F,1 do local J=m.vector2.unit();(d(J.Magnitude)).toBeCloseTo(1)end end)k("\114\101\116\117\114\110\115 \086\101\099\116\111\114\051 \111\102 \108\101\110\103\116\104 \061 \049",function()for i=1,F,1 do local J=m.vector3.unit();(d(J.Magnitude)).toBeCloseTo(1)end end)end)l("\111\102\076\101\110\103\116\104",function()k("\114\101\116\117\114\110\115 \086\101\099\116\111\114\050 \111\102 \108\101\110\103\116\104 \061 \049",function()for i=1,F,1 do local J=m.vector2.ofLength(i);(d(J.Magnitude)).toBeCloseTo(i)end end)k("\114\101\116\117\114\110\115 \086\101\099\116\111\114\051 \111\102 \108\101\110\103\116\104 \061 \049",function()for i=1,F,1 do local J=m.vector3.ofLength(i);(d(J.Magnitude)).toBeCloseTo(i)end end)end)l("\105\110\067\105\114\099\108\101",function()k("\114\101\116\117\114\110\115 \097 \112\111\105\110\116 \119\105\116\104\105\110 \116\104\101 \114\097\100\105\117\115",function()for i=1,F,1 do local J=100*math.random()local k=m.vector2.inCircle(J);(d(k.Magnitude)).toBeLessThanOrEqual(J)end end)k("\114\101\116\117\114\110\115 \097 \112\111\105\110\116 \119\105\116\104\105\110 \116\104\101 \114\097\100\105\117\115 \103\105\118\101\110 \097 \099\101\110\116\101\114",function()for i=1,F,1 do local J=100*math.random()local k=Vector2.new(100*math.random(),100*math.random())local H=m.vector2.inCircle(J,k);(d((H-k).Magnitude)).toBeLessThanOrEqual(J)end end)end)l("\105\110\083\112\104\101\114\101",function()k("\114\101\116\117\114\110\115 \097 \112\111\105\110\116 \119\105\116\104\105\110 \116\104\101 \114\097\100\105\117\115",function()for i=1,F,1 do local J=100*math.random()local k=m.vector3.inSphere(J);(d(k.Magnitude)).toBeLessThanOrEqual(J)end end)k("\114\101\116\117\114\110\115 \097 \112\111\105\110\116 \119\105\116\104\105\110 \116\104\101 \114\097\100\105\117\115 \103\105\118\101\110 \097 \099\101\110\116\101\114",function()for i=1,F,1 do local J=100*math.random()local k=Vector3.new(100*math.random(),100*math.random(),100*math.random())local H=m.vector3.inSphere(J,k);(d((H-k).Magnitude)).toBeLessThanOrEqual(J)end end)end)l("\105\110\082\101\099\116\097\110\103\108\101",function()k("\114\101\116\117\114\110\115 \097 \112\111\105\110\116 \105\110\115\105\100\101 \097 \114\101\099\116\097\110\103\108\101 \100\101\102\105\110\101\100 \098\121 \116\119\111 \112\111\105\110\116\115",function()for i=1,F,1 do local J=m.vector2.inCircle(1000)local k=m.vector2.inCircle(1000)local H=m.vector2.inRectangle({pointA=J;pointB=k});(d(H.X)).toBeGreaterThanOrEqual(math.min(J.X,k.X));(d(H.X)).toBeLessThanOrEqual(math.max(J.X,k.X));(d(H.Y)).toBeGreaterThanOrEqual(math.min(J.Y,k.Y));(d(H.Y)).toBeLessThanOrEqual(math.max(J.Y,k.Y))end end)k("\114\101\116\117\114\110\115 \097 \112\111\105\110\116 \105\110\115\105\100\101 \097 \114\101\099\116\097\110\103\108\101 \100\101\102\105\110\101\100 \098\121 \097 \099\101\110\116\101\114 \097\110\100 \097 \115\105\122\101",function()for i=1,F,1 do local J=m.vector2.inCircle(1000)local k=(m.vector2.inCircle(1000)):Abs()local H=m.vector2.inRectangle({center=J,size=k});(d(H.X)).toBeGreaterThanOrEqual(J.X-k.X/2);(d(H.X)).toBeLessThanOrEqual(J.X+k.X/2);(d(H.Y)).toBeGreaterThanOrEqual(J.Y-k.Y/2);(d(H.Y)).toBeLessThanOrEqual(J.Y+k.Y/2)end end)end)l("\105\110\066\111\120",function()k("\114\101\116\117\114\110\115 \097 \112\111\105\110\116 \105\110\115\105\100\101 \116\104\101 \118\111\108\117\109\101",function()for i=1,F,1 do local J=m.vector3.inSphere(1000)local k=(m.vector3.inSphere(100)):Abs()local H=m.vector3.inBox(k,J);(d(H.X)).toBeGreaterThanOrEqual(J.X-k.X/2);(d(H.X)).toBeLessThanOrEqual(J.X+k.X/2);(d(H.Y)).toBeGreaterThanOrEqual(J.Y-k.Y/2);(d(H.Y)).toBeLessThanOrEqual(J.Y+k.Y/2);(d(H.Z)).toBeGreaterThanOrEqual(J.Z-k.Z/2);(d(H.Z)).toBeLessThanOrEqual(J.Z+k.Z/2)end end)end)
local JestGlobals = require('@pkg/@jsdotlua/jest-globals')

local createVectors = require('../vectors')

local expect = JestGlobals.expect
local it = JestGlobals.it
local beforeAll = JestGlobals.beforeAll
local describe = JestGlobals.describe

local FUZZ_COUNT = 20

local generator

beforeAll(function()
    generator = createVectors(Random.new())
end)

describe('unit', function()
    it('returns Vector2 of length = 1', function()
        for _ = 1, FUZZ_COUNT do
            local value = generator.vector2.unit()

            expect(value.Magnitude).toBeCloseTo(1)
        end
    end)

    it('returns Vector3 of length = 1', function()
        for _ = 1, FUZZ_COUNT do
            local value = generator.vector3.unit()

            expect(value.Magnitude).toBeCloseTo(1)
        end
    end)
end)

describe('ofLength', function()
    it('returns Vector2 of length = 1', function()
        for i = 1, FUZZ_COUNT do
            local value = generator.vector2.ofLength(i)

            expect(value.Magnitude).toBeCloseTo(i)
        end
    end)

    it('returns Vector3 of length = 1', function()
        for i = 1, FUZZ_COUNT do
            local value = generator.vector3.ofLength(i)

            expect(value.Magnitude).toBeCloseTo(i)
        end
    end)
end)

describe('inCircle', function()
    it('returns a point within the radius', function()
        for _ = 1, FUZZ_COUNT do
            local radius = 100 * math.random()
            local value = generator.vector2.inCircle(radius)

            expect(value.Magnitude).toBeLessThanOrEqual(radius)
        end
    end)

    it('returns a point within the radius given a center', function()
        for _ = 1, FUZZ_COUNT do
            local radius = 100 * math.random()
            local center = Vector2.new(100 * math.random(), 100 * math.random())
            local value = generator.vector2.inCircle(radius, center)

            expect((value - center).Magnitude).toBeLessThanOrEqual(radius)
        end
    end)
end)

describe('inSphere', function()
    it('returns a point within the radius', function()
        for _ = 1, FUZZ_COUNT do
            local radius = 100 * math.random()
            local value = generator.vector3.inSphere(radius)

            expect(value.Magnitude).toBeLessThanOrEqual(radius)
        end
    end)

    it('returns a point within the radius given a center', function()
        for _ = 1, FUZZ_COUNT do
            local radius = 100 * math.random()
            local center =
                Vector3.new(100 * math.random(), 100 * math.random(), 100 * math.random())
            local value = generator.vector3.inSphere(radius, center)

            expect((value - center).Magnitude).toBeLessThanOrEqual(radius)
        end
    end)
end)

describe('inRectangle', function()
    it('returns a point inside a rectangle defined by two points', function()
        for _ = 1, FUZZ_COUNT do
            local pointA = generator.vector2.inCircle(1000)
            local pointB = generator.vector2.inCircle(1000)
            local value = generator.vector2.inRectangle({ pointA = pointA, pointB = pointB })

            expect(value.X).toBeGreaterThanOrEqual(math.min(pointA.X, pointB.X))
            expect(value.X).toBeLessThanOrEqual(math.max(pointA.X, pointB.X))
            expect(value.Y).toBeGreaterThanOrEqual(math.min(pointA.Y, pointB.Y))
            expect(value.Y).toBeLessThanOrEqual(math.max(pointA.Y, pointB.Y))
        end
    end)

    it('returns a point inside a rectangle defined by a center and a size', function()
        for _ = 1, FUZZ_COUNT do
            local center = generator.vector2.inCircle(1000)
            local size = generator.vector2.inCircle(1000):Abs()
            local value = generator.vector2.inRectangle({ center = center, size = size })

            expect(value.X).toBeGreaterThanOrEqual(center.X - size.X / 2)
            expect(value.X).toBeLessThanOrEqual(center.X + size.X / 2)
            expect(value.Y).toBeGreaterThanOrEqual(center.Y - size.Y / 2)
            expect(value.Y).toBeLessThanOrEqual(center.Y + size.Y / 2)
        end
    end)
end)

describe('inBox', function()
    it('returns a point inside the volume', function()
        for _ = 1, FUZZ_COUNT do
            local center = generator.vector3.inSphere(1000)
            local size = generator.vector3.inSphere(100):Abs()
            local value = generator.vector3.inBox(size, center)

            expect(value.X).toBeGreaterThanOrEqual(center.X - size.X / 2)
            expect(value.X).toBeLessThanOrEqual(center.X + size.X / 2)
            expect(value.Y).toBeGreaterThanOrEqual(center.Y - size.Y / 2)
            expect(value.Y).toBeLessThanOrEqual(center.Y + size.Y / 2)
            expect(value.Z).toBeGreaterThanOrEqual(center.Z - size.Z / 2)
            expect(value.Z).toBeLessThanOrEqual(center.Z + size.Z / 2)
        end
    end)
end)
