From 2bcad27120c66832f18e344a87f325c589f12e94 Mon Sep 17 00:00:00 2001 From: spaenleh Date: Fri, 10 Mar 2023 23:20:37 +0100 Subject: [PATCH] fix: wordcloud --- src/App.css | 36 ---- src/App.tsx | 165 ++++++++++----- src/constants.ts | 6 + src/index.css | 9 + src/utils.test.ts | 30 +++ src/utils.ts | 439 ++++++++++++++++++++-------------------- test/word-cloud.test.ts | 153 +++++++------- tsconfig.json | 1 + vite.config.ts | 6 +- 9 files changed, 448 insertions(+), 397 deletions(-) create mode 100644 src/constants.ts create mode 100644 src/utils.test.ts diff --git a/src/App.css b/src/App.css index b9d355d..902778b 100644 --- a/src/App.css +++ b/src/App.css @@ -4,39 +4,3 @@ padding: 2rem; text-align: center; } - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; - transition: filter 300ms; -} -.logo:hover { - filter: drop-shadow(0 0 2em #646cffaa); -} -.logo.react:hover { - filter: drop-shadow(0 0 2em #61dafbaa); -} - -@keyframes logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} - -@media (prefers-reduced-motion: no-preference) { - a:nth-of-type(2) .logo { - animation: logo-spin infinite 20s linear; - } -} - -.card { - padding: 2em; -} - -.read-the-docs { - color: #888; -} diff --git a/src/App.tsx b/src/App.tsx index 6a1ca6e..005af61 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,79 +1,132 @@ import "./App.css"; import { - centerOfObject, futurPosition, - putWordInRandomPositionOnParent, - setFirstWordInCenterOfParent, - WordArray, + getArea, + getBoundingRect, + placeWordOnOuterCircle, + Word, } from "./utils"; import * as React from "react"; +import { + CENTER_X, + CENTER_Y, + CONTAINER_HEIGHT, + CONTAINER_WIDTH, + DEFAULT_RECT, +} from "./constants"; -const defaultWords = [ - { id: "1234", text: "test", x: 10, y: 100 }, - { id: "2345", text: "hello", x: 50, y: 10 }, - { id: "3456", text: "haha", x: 130, y: 40 }, -]; +const CUT_OFF = 0.5; -const PARENT_ID = "rect"; +export const MAX_FONT_SIZE = 20; +export const MIN_FONT_SIZE = 6; + +const defaultWords: Word[] = [ + { id: "word-1", text: " Big word ", coef: 0.99 }, + { id: "word-2", text: "hello", coef: 0.8 }, + { id: "word-4", text: "caramba", coef: 0.97 }, + { id: "word-3", text: "all", coef: 0.74 }, + { id: "word-5", text: "Piniata", coef: 0.6 }, + { id: "word-6", text: "Taxi", coef: 0.93 }, + { id: "word-7", text: "papa", coef: 0.94 }, + { id: "word-8", text: "chicita", coef: 0.66 }, + { id: "word-9", text: "hellicopter", coef: 0.92 }, + { id: "word-10", text: "chiold", coef: 0.75 }, + { id: "word-11", text: "text", coef: 0.81 }, + { id: "word-12", text: "document", coef: 0.77 }, + { id: "word-13", text: "text", coef: 0.89 }, + { id: "word-14", text: "finger", coef: 0.91 }, + { id: "word-15", text: "girl", coef: 0.88 }, +]; const Wordcloud = () => { const [words, setWords] = React.useState(defaultWords); const updateWords = () => { - console.log("start"); - setWords((prevWords) => { - let passRect: WordArray = []; - - const newWords = prevWords.map((w) => { - const elem = document.getElementById(w.id); - - if (elem) { - if (passRect.length === 0) { - w = setFirstWordInCenterOfParent(w, PARENT_ID); - passRect.push(w); - console.log(w); - } else { - // Get the height and width of the word - const heightW = elem.getBoundingClientRect().height; - const widthW = elem.getBoundingClientRect().width; - - // put the word in random place arround the parent - w = putWordInRandomPositionOnParent(w, PARENT_ID); - - // Get the center of the word - w = centerOfObject(w, heightW, widthW); - - // move the word - w = futurPosition(w, passRect, 1, PARENT_ID); - - passRect.push(w); - } - } - return w; - }); - - return newWords; + const wordsToPlace = prevWords + .map((w) => ({ ...w, rect: getBoundingRect(w.id) || DEFAULT_RECT })) + .sort((a, b) => (a.coef > b.coef ? -1 : 1)); + const rectsToPlace = wordsToPlace.map((w) => w.rect); + const firstRect = { ...rectsToPlace[0] }; + const centeredRect = { + width: firstRect.width, + height: firstRect.height, + x: CENTER_X, + y: CENTER_Y, + }; + const newPositions = rectsToPlace.slice(1).reduce( + (placedElements, rect) => { + // move the word + const futureWord = futurPosition( + // put the word in random place around the parent + placeWordOnOuterCircle(rect), + placedElements, + 3 + ); + return [...placedElements, futureWord]; + }, + [centeredRect] + ); + return wordsToPlace.map((word, idx) => ({ + ...word, + rect: newPositions[idx], + })); }); - console.log("stop"); }; React.useEffect(() => { updateWords(); }, []); + return ( - - {words.map((word) => ( - - {word.text} - - ))} - + + {words.map((word) => { + const fontSize = + (word.coef - CUT_OFF) * + (1 / (1 - CUT_OFF)) ** 2 * + (MAX_FONT_SIZE - MIN_FONT_SIZE) + + MIN_FONT_SIZE; + + return ( + + {word.text} + + ); + })} + + ); }; diff --git a/src/constants.ts b/src/constants.ts new file mode 100644 index 0000000..0e23997 --- /dev/null +++ b/src/constants.ts @@ -0,0 +1,6 @@ +export const CONTAINER_WIDTH = 500; +export const CONTAINER_HEIGHT = 300; +export const CENTER_Y = CONTAINER_HEIGHT / 2; +export const CENTER_X = CONTAINER_WIDTH / 2; + +export const DEFAULT_RECT = { x: CENTER_X, y: CENTER_Y, width: 10, height: 10 }; diff --git a/src/index.css b/src/index.css index 2c3fac6..e87754f 100644 --- a/src/index.css +++ b/src/index.css @@ -55,6 +55,11 @@ button:focus-visible { outline: 4px auto -webkit-focus-ring-color; } + /* set fill color for svg text element */ +text { + fill: rgba(255, 255, 255, 0.87); +} + @media (prefers-color-scheme: light) { :root { color: #213547; @@ -66,4 +71,8 @@ button:focus-visible { button { background-color: #f9f9f9; } + /* set fill color for svg element */ + text { + fill: #213547 + } } diff --git a/src/utils.test.ts b/src/utils.test.ts new file mode 100644 index 0000000..6069b29 --- /dev/null +++ b/src/utils.test.ts @@ -0,0 +1,30 @@ +import { describe, expect, it } from "vitest"; +import { areCentersTooClose, Coordinate, Rectangle } from "./utils"; + +const origin: Coordinate = { + x: 0, + y: 0, +}; + +describe("areCentersTooClose", () => { + it("No collisions", () => { + expect(areCentersTooClose(origin, { x: 6, y: 0 }, 2, 2)).toBe(false); + expect(areCentersTooClose(origin, { x: 0, y: 6 }, 2, 2)).toBe(false); + expect(areCentersTooClose({ x: 0, y: 6 }, origin, 2, 2)).toBe(false); + }); + it("Collisions in X", () => { + expect(areCentersTooClose(origin, { x: 2, y: 0 }, 3, 2)).toBe(true); + expect(areCentersTooClose(origin, { x: 2, y: 0 }, 2.1, 2)).toBe(true); + expect(areCentersTooClose({ x: 2, y: 0 }, origin, 2.1, 2)).toBe(true); + }); + it("Collisions in Y", () => { + expect(areCentersTooClose(origin, { x: 0, y: 2 }, 2, 3)).toBe(true); + expect(areCentersTooClose(origin, { x: 0, y: 2 }, 2, 2.1)).toBe(true); + expect(areCentersTooClose({ x: 0, y: 2 }, origin, 2, 2.1)).toBe(true); + }); + it("Collisions in X and Y", () => { + expect(areCentersTooClose(origin, { x: 2, y: 2 }, 2.5, 2.5)).toBe(true); + expect(areCentersTooClose(origin, { x: -2, y: -2 }, 2.5, 2.5)).toBe(true); + expect(areCentersTooClose({ x: -2, y: -2 }, origin, 2.5, 2.5)).toBe(true); + }); +}); diff --git a/src/utils.ts b/src/utils.ts index fb06ffb..af3600b 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,255 +1,256 @@ +import { + CENTER_X, + CENTER_Y, + CONTAINER_HEIGHT, + CONTAINER_WIDTH, + DEFAULT_RECT, +} from "./constants"; + export type Word = { id: string; text: string; + coef: number; + rect?: Rectangle; +}; + +export type Rectangle = { x: number; y: number; + width: number; + height: number; }; -export type WordArray = Word[]; - export type Coordinate = { x: number; y: number; }; -// This function put the first word in the center of the parent rectangle -export const setFirstWordInCenterOfParent = (w: Word, p: string) => { - const parent = getCoordinateByID(p); - const word = getCoordinateByID(w.id); - - w.x = Math.floor(parent.w / 2) - word.w / 2; - w.y = Math.floor(parent.h / 2) - word.h / 2; - - return w; +export const getBoundingRect = ( + id: string, + tagName: "svg" | "text" = "text" +): Rectangle => { + const bbox = + ( + document.getElementsByTagName(tagName).namedItem(id) || undefined + )?.getBoundingClientRect() || DEFAULT_RECT; + return { + x: bbox.x, + y: bbox.y, + width: bbox.width + 10, + height: bbox.height - 5, + }; }; -// function that return the coordinate of the parent in an array -export const getCoordinateByID = (parent: string) => { - const p = document.getElementById(parent); +export const getArea = (rect: Rectangle): number => rect.width * rect.height; - if (p) { - const x = p.getBoundingClientRect().x; - const y = p.getBoundingClientRect().y; - const w = p.getBoundingClientRect().width; - const h = p.getBoundingClientRect().height; - - return { x, y, w, h }; +// This function put the first word in the center of the parent rectangle +export const setFirstWordInCenterOfParent = (w: Word, p: string): Rectangle => { + const parentElement = document.getElementsByTagName("svg").namedItem(p); + const word = getBoundingRect(w.id); + if (parentElement && word) { + const parent = parentElement.getBBox(); + + const newX = (parent.width - word.width) / 2; + const newY = (parent.height - word.height) / 2; + return { x: newX, y: newY, width: word.width, height: word.height }; } - - return { x: 0, y: 0, w: 0, h: 0 }; -}; - -// This function return a random interger between two numbers -export const randomIntFromInterval = (min: number, max: number) => { - return Math.floor(Math.random() * (max - min + 1) + min); + return { x: 0, y: 0, width: 50, height: 20 }; }; // This function put the word in a random place -export const putWordInRandomPositionOnParent = (w: Word, p: string) => { - const parent = getCoordinateByID(p); - +export const placeWordOnOuterCircle = (w: Rectangle) => { // Chose the parent face - const parentFace = randomIntFromInterval(1, 4); - const xValue = randomIntFromInterval(0, parent.w); - const yValue = randomIntFromInterval(0, parent.h); - - if (parentFace === 1) { - w.x = xValue; - w.y = 0; - } else if (parentFace === 2) { - w.x = 0; - w.y = yValue; - } else if (parentFace === 3) { - w.x = xValue; - w.y = parent.h; - } else if (parentFace == 4) { - w.x = parent.w; - w.y = yValue; - } - - return w; + const angle = Math.random() * 360; + const radius = Math.max(CONTAINER_HEIGHT, CONTAINER_WIDTH) / 2; + console.log(angle); + const newPosition = { + ...w, + x: radius * Math.cos(angle) + CENTER_X, + y: radius * Math.sin(angle) + CENTER_Y, + }; + return newPosition; }; -export const centerOfObject = (word: Word, h: number, w: number): Word => { - word.x += Math.floor(w / 2); - word.y += Math.floor(h / 2); - - return word; -}; - -export const uncenteredWord = (word: Word, h: number, w: number): Word => { - word.x -= Math.floor(w / 2); - word.y -= Math.floor(h / 2); - - return word; -}; - -export const netForce = (w: Word, passRect: WordArray): Coordinate => { - let diffX: number[] = []; - let diffY: number[] = []; - - passRect.forEach((passW) => { - diffX.push(passW.x - w.x); - diffY.push(passW.y - w.y); - }); - - let sumDiffX = 0; - let sumDiffY = 0; - - diffX.map((e) => (sumDiffX += e)); - diffY.map((e) => (sumDiffY += e)); - - return { x: sumDiffX, y: sumDiffY }; -}; - -export const getTriangleFromNetForce = ( - word: Word, - netForce: Coordinate +const getMoveDirection = ( + pastWords: Rectangle[], + currentWord: Rectangle ): Coordinate => { - const x = word.x; - const y = netForce.y; - - return { x, y }; -}; - -export const moveWordOnHypotenuse = ( - A: Coordinate, // adjacent - hypotenuse - B: Coordinate, // hypotenuse - opposite - C: Coordinate, // right angle - step: number -) => { - const lenghtHypontenus = distanceBetweenPoint(A, B); - const distanceBC = distanceBetweenPoint(B, C); - - const angle = Math.asin(distanceBC / lenghtHypontenus) * (180 / Math.PI); - - const x = Math.floor(A.x + step * Math.cos(angle) * (180 / Math.PI)); - const y = Math.floor(A.y + step * Math.sin(angle) * (180 / Math.PI)); - - return { x, y }; -}; - -export const limiteOfParent = (word: Word, parent: string) => { - const coordinateParent = getCoordinateByID(parent); - const coordinateWord = getCoordinateByID(word.id); - - const unCenteredW = uncenteredWord(word, coordinateWord.h, coordinateWord.w); - - if ( - unCenteredW.x > coordinateParent.w || - unCenteredW.y > coordinateParent.w || - unCenteredW.x < 0 || - unCenteredW.y < 0 - ) { - return 1; - } else { - return 0; - } + return pastWords.reduce( + (acc, word) => { + const differences = { + x: word.x - currentWord.x, + y: word.y - currentWord.y, + }; + return { x: acc.x + differences.x, y: acc.y + differences.y }; + }, + { x: 0, y: 0 } + ); }; export const futurPosition = ( - word: Word, - passRect: WordArray, - step: number, - parent: string + word: Rectangle, + passRect: Rectangle[], + step: number ) => { - let isCollision = 0; - - while (!isCollision) { - const netForceW = netForce(word, passRect); - const rightAnglePoint = getTriangleFromNetForce(word, netForceW); - - const futurWPosition = moveWordOnHypotenuse( - { x: word.x, y: word.y }, - netForceW, - rightAnglePoint, - step - ); - - // set the position - let tmpW = word; - let tmpWX = word; - let tmpWY = word; - - tmpW.x = futurWPosition.x; - tmpW.y = futurWPosition.y; - - tmpWX.x = futurWPosition.x; - tmpWY.y = futurWPosition.y; + let isCollision = false; + let movedWord: Rectangle = { + x: word.x, + y: word.y, + width: word.width, + height: word.height, + }; + let iter = 0; + let displacement = 0; + do { + const moveDirection = getMoveDirection(passRect, movedWord); + const hypothenus = Math.sqrt(moveDirection.x ** 2 + moveDirection.y ** 2); + const stepX = (step / hypothenus) * moveDirection.x; + const stepY = (step / hypothenus) * moveDirection.y; + const futurPosition: Rectangle = { + ...movedWord, + x: movedWord.x + (Math.abs(stepX) > 0.01 ? stepX : 0), + y: movedWord.y + (Math.abs(stepY) > 0.01 ? stepY : 0), + }; // test if the word can be move over the hypotenuse - isCollision = allCollision(tmpW, passRect); - - if (isCollision) { - // test collision on x - const isCollisionX = allCollision(tmpWX, passRect); - const isCollisionY = allCollision(tmpWY, passRect); - - if (isCollisionX && isCollisionY) { - return word; - } - - if (!isCollisionX) { - word.x = tmpWX.x; - - if (limiteOfParent(word, parent)) { - return word; - } - } - - if (!isCollisionY) { - word.y = tmpWY.y; - if (limiteOfParent(word, parent)) { - return word; + if (allCollision(futurPosition, passRect)) { + const onlyMoveOverX = { ...futurPosition, y: movedWord.y }; + const onlyMoveOverY = { ...futurPosition, x: movedWord.x }; + const xColl = allCollision(onlyMoveOverX, passRect); + const yColl = allCollision(onlyMoveOverY, passRect); + if (xColl) { + if (yColl) { + // do not move anymore + isCollision = true; + } else { + movedWord = { ...onlyMoveOverY }; } + } else { + movedWord = { ...onlyMoveOverX }; } } else { - word = tmpW; - if (limiteOfParent(word, parent)) { - return word; - } + movedWord = { ...futurPosition }; } - } - return word; -}; - -export const distanceBetweenWord = (w1: Word, w2: Word) => { - return Math.sqrt(Math.pow(w2.x - w1.x, 2) + Math.pow(w2.y - w1.y, 2)); -}; + displacement = Math.abs(stepX) + Math.abs(stepY); + iter++; + } while (!isCollision && displacement > 2 && iter < 600); + console.log(isCollision, displacement, iter); -export const distanceBetweenPoint = (w1: Coordinate, w2: Coordinate) => { - return Math.sqrt(Math.pow(w2.x - w1.x, 2) + Math.pow(w2.y - w1.y, 2)); + return movedWord; }; -export const collision = (w1: Word, w2: Word) => { - const positionW1 = getCoordinateByID(w1.id); - const positionW2 = getCoordinateByID(w2.id); - - w1 = uncenteredWord(w1, positionW1.w, positionW1.h); - w2 = uncenteredWord(w2, positionW2.w, positionW2.h); - - if ( - w1.x < w2.x + positionW2.w && - w1.x + positionW1.w > w2.x && - w1.y < w2.y + positionW2.h && - positionW1.h + w1.y > w2.y - ) { - return 1; - } else { - return 0; - } -}; - -export const allCollision = (word: Word, passRect: WordArray): any => { - passRect.forEach((w: Word) => { - if (word.id !== w.id) { - if (collision(word, w)) { - return 1; - } else { - return 0; - } - } else { - return 0; - } - }); -}; +export const areCentersTooClose = ( + centerA: Coordinate, + centerB: Coordinate, + minX: number, + minY: number +): boolean => + Math.abs(centerA.x - centerB.x) < minX && + Math.abs(centerA.y - centerB.y) < minY; + +export const allCollision = (word: Rectangle, passRect: Rectangle[]): boolean => + passRect + .map((rect) => + areCentersTooClose( + rect, + word, + (rect.width + word.width) / 2, + (rect.height + word.height) / 2 + ) + ) + .some((t) => t === true); + +// export const distanceBetweenWord = (w1: Word, w2: Word) => { +// return Math.sqrt(Math.pow(w2.x - w1.x, 2) + Math.pow(w2.y - w1.y, 2)); +// }; + +// export const distanceBetweenPoint = (w1: Coordinate, w2: Coordinate) => { +// return Math.sqrt(Math.pow(w2.x - w1.x, 2) + Math.pow(w2.y - w1.y, 2)); +// }; + +// export const collision = (w1: Rectangle, w2: Rectangle) => { +// if ( +// w1.x < w2.x + 2.w && +// w1.x + positionW1.w > w2.x && +// w1.y < w2.y + positionW2.h && +// positionW1.h + w1.y > w2.y +// ) { +// return true; +// } else { +// return false; +// } +// }; + +// export const uncenteredWord = ( +// word: Rectangle, +// h: number, +// w: number +// ): Rectangle => { +// word.x -= Math.floor(w / 2); +// word.y -= Math.floor(h / 2); + +// return word; +// }; + +// export const netForce = (w: Rectangle, passRect: Rectangle[]): Coordinate => { +// let diffX: number[] = []; +// let diffY: number[] = []; + +// passRect.forEach((passW) => { +// diffX.push(passW.x - w.x); +// diffY.push(passW.y - w.y); +// }); + +// let sumDiffX = 0; +// let sumDiffY = 0; + +// diffX.map((e) => (sumDiffX += e)); +// diffY.map((e) => (sumDiffY += e)); + +// return { x: sumDiffX, y: sumDiffY }; +// }; + +// export const getTriangleFromNetForce = ( +// word: Rectangle, +// netForce: Coordinate +// ): Coordinate => { +// const x = word.x; +// const y = netForce.y; + +// return { x, y }; +// }; + +// export const moveWordOnHypotenuse = ( +// A: Coordinate, // adjacent - hypotenuse +// B: Coordinate, // hypotenuse - opposite +// C: Coordinate, // right angle +// step: number +// ) => { +// const lenghtHypontenus = distanceBetweenPoint(A, B); +// const distanceBC = distanceBetweenPoint(B, C); + +// const angle = Math.asin(distanceBC / lenghtHypontenus) * (180 / Math.PI); + +// const x = Math.floor(A.x + step * Math.cos(angle) * (180 / Math.PI)); +// const y = Math.floor(A.y + step * Math.sin(angle) * (180 / Math.PI)); + +// return { x, y }; +// }; + +// export const limiteOfParent = (word: Word, parent: string) => { +// const coordinateParent = getCoordinateByID(parent); +// const coordinateWord = getCoordinateByID(word.id); + +// const unCenteredW = uncenteredWord(word, coordinateWord.h, coordinateWord.w); + +// if ( +// unCenteredW.x > coordinateParent.w || +// unCenteredW.y > coordinateParent.w || +// unCenteredW.x < 0 || +// unCenteredW.y < 0 +// ) { +// return 1; +// } else { +// return 0; +// } +// }; diff --git a/test/word-cloud.test.ts b/test/word-cloud.test.ts index 6c6dd18..825721a 100644 --- a/test/word-cloud.test.ts +++ b/test/word-cloud.test.ts @@ -1,88 +1,71 @@ import { test, expect, describe, it } from "vitest"; -import { WordArray, Coordinate } from "../src/utils"; - -import { - centerOfObject, - distanceBetweenWord, - netForce, - uncenteredWord, -} from "../src/utils"; - -describe("Distance", () => { - it("Naive test", () => { - const words: WordArray = [ - { id: "1", text: "hello", x: 1, y: 1 }, - { id: "2", text: "world", x: 1, y: 2 }, - ]; - - let w1 = words[0]; - let w2 = words[1]; - - expect(distanceBetweenWord(w1, w2)).toEqual(1); - }); -}); -test(" Distance naive test", () => { - const words: WordArray = [ - { id: "1", text: "hello", x: 1, y: 1 }, - { id: "2", text: "world", x: 1, y: 2 }, - ]; - - let w1 = words[0]; - let w2 = words[1]; - - expect(distanceBetweenWord(w1, w2)).toEqual(1); -}); - -test("center of word naive test", () => { - const words: WordArray = [ - { id: "1", text: "hello", x: 0, y: 5 }, - { id: "2", text: "world", x: 5, y: 2 }, - ]; - - let w1 = words[0]; - let h = 10; - let w = 10; - - let res = centerOfObject(w1, h, w); - - expect(res).toEqual({ id: "1", text: "hello", x: 5, y: 10 }); -}); - -test("uncenter the word", () => { - const words: WordArray = [ - { id: "1", text: "hello", x: 0, y: 5 }, - { id: "2", text: "world", x: 5, y: 2 }, - ]; - - let w1 = words[0]; - let h = 10; - let w = 10; - - let centered = centerOfObject(w1, h, w); - let uncentered = uncenteredWord(centered, h, w); - - expect(uncentered).toEqual(w1); -}); - -describe("netForce", () => { - it("Naive test", () => { - const words: WordArray = [ - { id: "1", text: "hello", x: 3, y: 4 }, - { id: "2", text: "world", x: 4, y: 6 }, - { id: "3", text: "world", x: 8, y: 5 }, - ]; - - let passRect = [words[1], words[2]]; - - let net = netForce(words[0], passRect); - - expect(net).toEqual({ x: 6, y: 3 }); - }); -}); - -describe("Triangle from net force", () => { - it("Naive test", () => { - let net = { x: 6, y: 3 }; - }); +// import { WordArray, Coordinate } from "../src/utils"; + +// import { +// centerOfObject, +// distanceBetweenWord, +// netForce, +// uncenteredWord, +// } from "../src/utils"; + +describe.skip("Distance", () => { + // it("Naive test", () => { + // const words: WordArray = [ + // { id: "1", text: "hello", x: 1, y: 1 }, + // { id: "2", text: "world", x: 1, y: 2 }, + // ]; + // let w1 = words[0]; + // let w2 = words[1]; + // expect(distanceBetweenWord(w1, w2)).toEqual(1); + // }); + // }); + // test(" Distance naive test", () => { + // const words: WordArray = [ + // { id: "1", text: "hello", x: 1, y: 1 }, + // { id: "2", text: "world", x: 1, y: 2 }, + // ]; + // let w1 = words[0]; + // let w2 = words[1]; + // expect(distanceBetweenWord(w1, w2)).toEqual(1); + // }); + // test("center of word naive test", () => { + // const words: WordArray = [ + // { id: "1", text: "hello", x: 0, y: 5 }, + // { id: "2", text: "world", x: 5, y: 2 }, + // ]; + // let w1 = words[0]; + // let h = 10; + // let w = 10; + // let res = centerOfObject(w1, h, w); + // expect(res).toEqual({ id: "1", text: "hello", x: 5, y: 10 }); + // }); + // test("uncenter the word", () => { + // const words: WordArray = [ + // { id: "1", text: "hello", x: 0, y: 5 }, + // { id: "2", text: "world", x: 5, y: 2 }, + // ]; + // let w1 = words[0]; + // let h = 10; + // let w = 10; + // let centered = centerOfObject(w1, h, w); + // let uncentered = uncenteredWord(centered, h, w); + // expect(uncentered).toEqual(w1); + // }); + // describe("netForce", () => { + // it("Naive test", () => { + // const words: WordArray = [ + // { id: "1", text: "hello", x: 3, y: 4 }, + // { id: "2", text: "world", x: 4, y: 6 }, + // { id: "3", text: "world", x: 8, y: 5 }, + // ]; + // let passRect = [words[1], words[2]]; + // let net = netForce(words[0], passRect); + // expect(net).toEqual({ x: 6, y: 3 }); + // }); + // }); + // describe("Triangle from net force", () => { + // it("Naive test", () => { + // let net = { x: 6, y: 3 }; + // }); }); diff --git a/tsconfig.json b/tsconfig.json index 3d0a51a..4e11f3f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,6 +3,7 @@ "target": "ESNext", "useDefineForClassFields": true, "lib": ["DOM", "DOM.Iterable", "ESNext"], + "types": ["vitest/importMeta"], "allowJs": false, "skipLibCheck": true, "esModuleInterop": false, diff --git a/vite.config.ts b/vite.config.ts index 60dd1a9..e19b2fe 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,4 +1,4 @@ -import { defineConfig } from "vite"; +import { defineConfig } from "vitest/config"; import react from "@vitejs/plugin-react"; import checker from "vite-plugin-checker"; @@ -10,4 +10,8 @@ export default defineConfig({ }), react(), ], + + test: { + includeSource: ["src/**/*.{js,ts}"], + }, });