diff options
| author | Paweł Bernaciak <pawelbernaciak@zohomail.eu> | 2024-01-20 11:03:44 +0100 |
|---|---|---|
| committer | Paweł Bernaciak <pawelbernaciak@zohomail.eu> | 2024-01-20 11:03:44 +0100 |
| commit | 363936641a31b0b508197d41bea1ce116931b5d4 (patch) | |
| tree | ff5faa88b40b79b71ce32e648ac0a1dcfeffb91c | |
| parent | 32180f5b46fe594b01c40ca1d837734b1be894d6 (diff) | |
| -rw-r--r-- | backend/Elements.Backend/Controllers/SuggestionController.cs | 8 | ||||
| -rw-r--r-- | frontend/.dockerignore | 1 | ||||
| -rw-r--r-- | frontend/Dockerfile | 12 | ||||
| -rw-r--r-- | frontend/package-lock.json | 71 | ||||
| -rw-r--r-- | frontend/package.json | 4 | ||||
| -rw-r--r-- | frontend/src/App.tsx | 29 | ||||
| -rw-r--r-- | frontend/src/components/Dialog.tsx | 54 | ||||
| -rw-r--r-- | frontend/src/components/ElementCreator.tsx | 203 | ||||
| -rw-r--r-- | frontend/src/components/ElementList.tsx | 76 | ||||
| -rw-r--r-- | frontend/src/components/ElementView.tsx | 58 | ||||
| -rw-r--r-- | frontend/src/main.tsx | 24 | ||||
| -rw-r--r-- | frontend/src/store.ts | 0 | ||||
| -rw-r--r-- | frontend/src/stores.ts | 12 | ||||
| -rw-r--r-- | frontend/src/types.ts | 96 |
14 files changed, 598 insertions, 50 deletions
diff --git a/backend/Elements.Backend/Controllers/SuggestionController.cs b/backend/Elements.Backend/Controllers/SuggestionController.cs index b1d28b8..9c39163 100644 --- a/backend/Elements.Backend/Controllers/SuggestionController.cs +++ b/backend/Elements.Backend/Controllers/SuggestionController.cs @@ -122,6 +122,12 @@ public class SuggestionController : ControllerBase //User already suggested something if (await _dbContext.Suggestions.AnyAsync(s => s.UserId.ToString() == currentUserId)) return BadRequest(); + + var exists = await _dbContext.Recipes.AnyAsync(r => + (r.FirstElementId == suggestion.FirstElementId && r.SecondElementId == suggestion.SecondElementId) || + (r.FirstElementId == suggestion.SecondElementId && r.SecondElementId == suggestion.FirstElementId)); + if (exists) + return BadRequest(); Suggestion newSuggestion = new() { @@ -130,7 +136,7 @@ public class SuggestionController : ControllerBase Icon = ConvertBitmapToPng(Convert.FromBase64String(suggestion.IconBitmap)), FirstElementId = suggestion.FirstElementId, SecondElementId = suggestion.SecondElementId, - VotingEnd = DateTime.UtcNow + TimeSpan.FromMinutes(5), + VotingEnd = DateTime.UtcNow + TimeSpan.FromMinutes(1), UserId = int.Parse(currentUserId) }; await _dbContext.Suggestions.AddAsync(newSuggestion); diff --git a/frontend/.dockerignore b/frontend/.dockerignore new file mode 100644 index 0000000..b512c09 --- /dev/null +++ b/frontend/.dockerignore @@ -0,0 +1 @@ +node_modules
\ No newline at end of file diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 0b93a16..4b54f33 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -2,17 +2,7 @@ FROM node:21-alpine as builder WORKDIR /app -COPY package.json ./ -COPY package-lock.json ./ -COPY src ./src/ -COPY index.html ./ -COPY public ./ -COPY .env ./ -COPY postcss.config.js ./ -COPY tailwind.config.js ./ -COPY tsconfig.json ./ -COPY tsconfig.node.json ./ -COPY vite.config.ts ./ +COPY . . RUN npm ci RUN npm run build diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 258779e..c53b51b 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -10,7 +10,9 @@ "dependencies": { "@react-oauth/google": "^0.11.1", "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "react-hot-toast": "^2.4.1", + "zustand": "^4.4.7" }, "devDependencies": { "@types/react": "^18.2.15", @@ -991,13 +993,13 @@ "version": "15.7.9", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.9.tgz", "integrity": "sha512-n1yyPsugYNSmHgxDFjicaI2+gCNjsBck8UX9kuofAKlc0h1bL+20oSF72KeNaW2DUlesbEVCFgyV2dPGTiY42g==", - "dev": true + "devOptional": true }, "node_modules/@types/react": { "version": "18.2.33", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.33.tgz", "integrity": "sha512-v+I7S+hu3PIBoVkKGpSYYpiBT1ijqEzWpzQD62/jm4K74hPpSP7FF9BnKG6+fg2+62weJYkkBWDJlZt5JO/9hg==", - "dev": true, + "devOptional": true, "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -1017,7 +1019,7 @@ "version": "0.16.5", "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.5.tgz", "integrity": "sha512-s/FPdYRmZR8SjLWGMCuax7r3qCWQw9QKHzXVukAuuIJkXkDRwp+Pu5LMIVFi0Fxbav35WURicYr8u1QsoybnQw==", - "dev": true + "devOptional": true }, "node_modules/@types/semver": { "version": "7.5.4", @@ -1835,8 +1837,7 @@ "node_modules/csstype": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", - "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==", - "dev": true + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" }, "node_modules/debug": { "version": "4.3.4", @@ -2727,6 +2728,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/goober": { + "version": "2.1.13", + "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.13.tgz", + "integrity": "sha512-jFj3BQeleOoy7t93E9rZ2de+ScC4lQICLwiAQmKMg9F6roKGaLSHoCDYKkWlSafg138jejvq/mTdvmnwDQgqoQ==", + "peerDependencies": { + "csstype": "^3.0.10" + } + }, "node_modules/gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", @@ -3997,6 +4006,21 @@ "react": "^18.2.0" } }, + "node_modules/react-hot-toast": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/react-hot-toast/-/react-hot-toast-2.4.1.tgz", + "integrity": "sha512-j8z+cQbWIM5LY37pR6uZR6D4LfseplqnuAO4co4u8917hBUvXlEqyP1ZzqVLcqoyUesZZv/ImreoCeHVDpE5pQ==", + "dependencies": { + "goober": "^2.1.10" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + } + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -4722,6 +4746,14 @@ "punycode": "^2.1.0" } }, + "node_modules/use-sync-external-store": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -4906,6 +4938,33 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zustand": { + "version": "4.4.7", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.4.7.tgz", + "integrity": "sha512-QFJWJMdlETcI69paJwhSMJz7PPWjVP8Sjhclxmxmxv/RYI7ZOvR5BHX+ktH0we9gTWQMxcne8q1OY8xxz604gw==", + "dependencies": { + "use-sync-external-store": "1.2.0" + }, + "engines": { + "node": ">=12.7.0" + }, + "peerDependencies": { + "@types/react": ">=16.8", + "immer": ">=9.0", + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + } + } } } } diff --git a/frontend/package.json b/frontend/package.json index 4334002..cb56e00 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -12,7 +12,9 @@ "dependencies": { "@react-oauth/google": "^0.11.1", "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "react-hot-toast": "^2.4.1", + "zustand": "^4.4.7" }, "devDependencies": { "@types/react": "^18.2.15", diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 7aae66c..49e6992 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,10 +1,13 @@ import { CredentialResponse, GoogleLogin } from '@react-oauth/google'; -import { FC, useEffect, useState } from 'react'; +import { FC, useEffect } from 'react'; import { LoginRequest, LoginResponse, User } from './types'; import ElementList from './components/ElementList'; +import { userStore } from './stores'; +import toast from 'react-hot-toast'; const App: FC = () => { - const [user, setUser] = useState<User | undefined>(undefined); + const user = userStore((store) => store.user); + const setUser = userStore((store) => store.setUser); useEffect(() => { const userString = localStorage.getItem('user'); @@ -12,8 +15,21 @@ const App: FC = () => { return; } - setUser(JSON.parse(userString)); - }, []); + const userObject = JSON.parse(userString) as User; + fetch(`/api/user/${userObject.id}`).then((resp) => { + if (resp.status == 401) { + toast.error( + 'Your authorization has expired. You have to log in again.', + ); + localStorage.removeItem('user'); + } else if (resp.status == 404) { + toast.error("Your account doesn't exist anymore."); + localStorage.removeItem('user'); + } else { + setUser(JSON.parse(userString)); + } + }); + }, [setUser]); const login = async (credentials: CredentialResponse) => { if (credentials.credential == null) { @@ -25,6 +41,7 @@ const App: FC = () => { const loginRequest: LoginRequest = { googleToken: credentials.credential, }; + const loginResponse = await fetch('/api/auth/login', { method: 'POST', credentials: 'include', @@ -48,8 +65,8 @@ const App: FC = () => { console.log('Error connecting to API. Code: ', userInfoResponse.status); return; } - const userResponse: User = await userInfoResponse.json(); + const userResponse: User = await userInfoResponse.json(); localStorage.setItem('user', JSON.stringify(userResponse)); setUser(userResponse); }; @@ -89,6 +106,6 @@ const App: FC = () => { <ElementList /> </div> ); -} +}; export default App; diff --git a/frontend/src/components/Dialog.tsx b/frontend/src/components/Dialog.tsx new file mode 100644 index 0000000..4fa6bf7 --- /dev/null +++ b/frontend/src/components/Dialog.tsx @@ -0,0 +1,54 @@ +import { FC, PropsWithChildren, useEffect, useRef } from 'react'; + +interface DialogProps { + visible: boolean; + closeDialog: () => void; +} + +const Dialog: FC<PropsWithChildren<DialogProps>> = ({ + visible, + closeDialog, + children, +}) => { + const dialogRef = useRef<HTMLDialogElement>(null); + + useEffect(() => { + if (visible) { + dialogRef.current?.showModal(); + } else { + dialogRef.current?.close(); + } + }, [visible]); + + const handleButtonClick = (e: React.MouseEvent<HTMLButtonElement>) => { + e.preventDefault(); + closeDialog(); + }; + + return ( + <dialog ref={dialogRef}> + <div className="p-4 flex flex-col max-w-[90vw] md:max-w-[50vw] bg-white shadow"> + <div className="flex w-full"> + <button className="ml-auto" onClick={handleButtonClick}> + <svg + xmlns="http://www.w3.org/2000/svg" + fill="none" + viewBox="0 0 24 24" + strokeWidth={1.5} + stroke="currentColor" + className="w-6 h-6"> + <path + strokeLinecap="round" + strokeLinejoin="round" + d="M6 18 18 6M6 6l12 12" + /> + </svg> + </button> + </div> + {children} + </div> + </dialog> + ); +}; + +export default Dialog; diff --git a/frontend/src/components/ElementCreator.tsx b/frontend/src/components/ElementCreator.tsx new file mode 100644 index 0000000..61f5aba --- /dev/null +++ b/frontend/src/components/ElementCreator.tsx @@ -0,0 +1,203 @@ +import { FC, useEffect, useState } from 'react'; +import { + Element, + Color, + ColorBitmap, + ElementState, + ElementSuggestion, + ColorCode, +} from '../types'; +import toast from 'react-hot-toast'; +import ElementView from './ElementView'; +import { userStore } from '../stores'; + +interface ElementCreatorProps { + firstElementId: number | undefined; + secondElementId: number | undefined; + closeDialog: () => void; +} + +const ElementCreator: FC<ElementCreatorProps> = ({ + firstElementId, + secondElementId, + closeDialog, +}) => { + const [elementName, setElementName] = useState<string>(''); + const [color, setColor] = useState<Color>(Color.Air); + const [firstElement, setFirstElement] = useState<Element | null>(null); + const [secondElement, setSecondElement] = useState<Element | null>(null); + const setUser = userStore((store) => store.setUser); + + const fetchElement = async (elementId: number): Promise<Element> => { + const elementResponse = await fetch(`/api/element/${elementId}`); + return await elementResponse.json(); + }; + + useEffect(() => { + if (firstElementId == undefined || secondElementId == undefined) { + return; + } + + setElementName(''); + setColor(Color.Air); + + fetchElement(firstElementId).then((elem) => { + setFirstElement(elem); + }); + fetchElement(secondElementId).then((elem) => { + setSecondElement(elem); + }); + }, [firstElementId, secondElementId]); + + const handleNameChange = (e: React.ChangeEvent<HTMLInputElement>) => { + setElementName(e.target.value); + }; + + const createHandleColorClick = (color: Color) => { + return (e: React.MouseEvent<HTMLButtonElement>) => { + e.preventDefault(); + setColor(color); + }; + }; + + const handleSubmitButton = async (e: React.MouseEvent<HTMLButtonElement>) => { + e.preventDefault(); + + if (elementName == '') { + toast.error('No name selected'); + return; + } + if (!(color in Color)) { + toast.error('Bad color value'); + return; + } + + const request: ElementSuggestion = { + name: elementName, + iconBitmap: ColorBitmap[color], + firstElementId: firstElementId!, + secondElementId: secondElementId!, + }; + + console.log(request); + + const createVoteResponse = await fetch(`/api/suggestion/create`, { + method: 'POST', + credentials: 'include', + body: JSON.stringify(request), + headers: { + 'Content-Type': 'application/json', + }, + }); + + if (createVoteResponse.status == 401) { + console.log('Session expired'); + toast.error('Your authorization has expired. You have to log in again.'); + localStorage.removeItem('user'); + setUser(undefined); + return; + } + console.log(createVoteResponse.status); + console.log('Vote started'); + closeDialog(); + }; + + return ( + <form className="flex flex-col items-center"> + <div className="flex items-center"> + {firstElement != null && secondElement != null && ( + <> + <ElementView + element={firstElement!} + onElementCombine={() => {}} + isPreview={false} + interactive={false} + /> + <svg + xmlns="http://www.w3.org/2000/svg" + fill="none" + viewBox="0 0 24 24" + strokeWidth={1.5} + stroke="currentColor" + className="w-6 h-6"> + <path + strokeLinecap="round" + strokeLinejoin="round" + d="M12 4.5v15m7.5-7.5h-15" + /> + </svg> + <ElementView + element={secondElement!} + onElementCombine={() => {}} + isPreview={false} + interactive={false} + /> + <svg + xmlns="http://www.w3.org/2000/svg" + fill="none" + viewBox="0 0 24 24" + strokeWidth={1.5} + stroke="currentColor" + className="w-6 h-6"> + <path + strokeLinecap="round" + strokeLinejoin="round" + d="M3.75 9h16.5m-16.5 6.75h16.5" + /> + </svg> + </> + )} + <ElementView + element={{ + name: elementName, + icon: ColorCode[color], + id: 0, + userId: 0, + state: ElementState.HasColor, + }} + onElementCombine={() => {}} + isPreview={true} + interactive={false} + /> + </div> + <div className="mb-5 w-full"> + <label + htmlFor="element-name" + className="block mb-2 text-sm font-medium text-gray-900 dark:text-white"> + Element name + </label> + <input + type="text" + id="element-name" + value={elementName} + onChange={handleNameChange} + className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" + required + /> + </div> + <div className="flex flex-wrap mb-3 gap-2 border p-2 rounded shadow justify-center"> + {(Object.keys(Color) as Array<keyof typeof Color>) + .filter((color) => Number.isNaN(Number(color))) + .map((color) => { + return ( + <button + key={color} + onClick={createHandleColorClick(Color[color])}> + <div + className="border border-gray-200 w-8 h-8" + style={{ backgroundColor: ColorCode[Color[color]] }}></div> + </button> + ); + })} + </div> + <button + onClick={handleSubmitButton} + type="submit" + className=" text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"> + Submit + </button> + </form> + ); +}; + +export default ElementCreator; diff --git a/frontend/src/components/ElementList.tsx b/frontend/src/components/ElementList.tsx index 20b27dd..04650c4 100644 --- a/frontend/src/components/ElementList.tsx +++ b/frontend/src/components/ElementList.tsx @@ -1,22 +1,35 @@ import { FC, useEffect, useState } from 'react'; -import {Element} from '../types'; +import { Element } from '../types'; import ElementView from './ElementView'; +import Dialog from './Dialog'; +import ElementCreator from './ElementCreator'; +import { userStore } from '../stores'; +import toast from 'react-hot-toast'; const ElementList: FC = () => { const [elements, setElements] = useState<Element[]>([]); + const [elementCreatorVisible, setElementCreatorVisible] = + useState<boolean>(false); + const [creatorFirstElementId, setCreatorFirstElementId] = useState< + number | undefined + >(undefined); + const [creatorSecondElementId, setCreatorSecondElementId] = useState< + number | undefined + >(undefined); + const user = userStore((store) => store.user); useEffect(() => { const initialElements: number[] = [1, 2, 3, 4]; const elementStateString = localStorage.getItem('elementState'); if (elementStateString != null) { - setElements(JSON.parse(elementStateString)); - return; + setElements(JSON.parse(elementStateString)); + return; } const fetchElements = async () => { const elems: Element[] = []; - + for (const elemId of initialElements) { const response = await fetch(`/api/element/${elemId}`); const elem: Element = await response.json(); @@ -32,14 +45,59 @@ const ElementList: FC = () => { useEffect(() => { if (elements.length != 0) { - localStorage.setItem('elementState', JSON.stringify(elements)); + localStorage.setItem('elementState', JSON.stringify(elements)); } - }, [elements]) + }, [elements]); + + const createOnElementCombine = (firstElementId: number) => { + return async (secondElementId: number) => { + const combineResponse = await fetch( + `/api/element/combine?firstElementId=${firstElementId}&secondElementId=${secondElementId}`, + ); + if (combineResponse.status == 404) { + console.log("Element doesn't exist"); + if (!user) { + toast("You have discovered a new element but need to log in to name it"); + return; + } + setCreatorFirstElementId(firstElementId); + setCreatorSecondElementId(secondElementId); + setElementCreatorVisible(true); + return; + } + + const newElem: Element = await combineResponse.json(); + if (elements.find((e) => e.id == newElem.id)) { + toast(`You have already discovered ${newElem.name}`); + return; + } + setElements((elems) => elems.concat(newElem)); + }; + }; return ( - <> - {elements.map(elem => <ElementView key={elem.id} element={elem} />)} - </> + <div className="p-3 flex gap-3"> + {elements.map((elem) => ( + <ElementView + key={elem.id} + interactive={true} + isPreview={false} + element={elem} + onElementCombine={createOnElementCombine(elem.id)} + /> + ))} + <Dialog + visible={elementCreatorVisible} + closeDialog={() => { + setElementCreatorVisible(false); + }}> + <ElementCreator + firstElementId={creatorFirstElementId} + secondElementId={creatorSecondElementId} + closeDialog={() => setElementCreatorVisible(false)} + /> + </Dialog> + </div> ); }; diff --git a/frontend/src/components/ElementView.tsx b/frontend/src/components/ElementView.tsx index 4f9d489..1b11ffb 100644 --- a/frontend/src/components/ElementView.tsx +++ b/frontend/src/components/ElementView.tsx @@ -2,15 +2,63 @@ import { FC } from 'react'; import { Element } from '../types'; interface ElementViewProps { + onElementCombine: (elementId: number) => void; element: Element; + interactive: boolean; + isPreview: boolean; } -const ElementView: FC<ElementViewProps> = ({ element }) => { +const ElementView: FC<ElementViewProps> = ({ + onElementCombine, + element, + interactive, + isPreview, +}) => { + const onDragStart = (e: React.DragEvent<HTMLDivElement>) => { + e.stopPropagation(); + + e.dataTransfer.setData('text/plain', element.name); + e.dataTransfer.setData('id', element.id.toString()); + }; + + const onDragOver = (e: React.DragEvent<HTMLDivElement>) => { + e.preventDefault(); + }; + + const onDrop = (e: React.DragEvent<HTMLDivElement>) => { + const elementId = e.dataTransfer.getData('id'); + onElementCombine(Number.parseInt(elementId)); + e.preventDefault(); + }; + return ( - <div className='flex flex-row m-2 rounded-md border border-gray-300 bg-gray-100 w-fit h-fit'> - <div className='flex flex-col items-center'> - <img src={`data:image/png;base64,${element.icon}`} width='80px' height='80px'/> - <p className='my-1 mx-2 text-sm'>{element.name}</p> + <div + draggable={interactive} + onDragStart={interactive ? onDragStart : undefined} + onDragOver={interactive ? onDragOver : undefined} + onDrop={interactive ? onDrop : undefined} + className="element flex flex-row rounded-md border border-gray-300 bg-gray-100 w-[96px] h-fit"> + <div draggable={false} className="flex flex-col items-center w-full"> + {isPreview ? ( + <div + style={{ + backgroundColor: element.icon, + }} + className="rounded-t w-full h-[96px]"></div> + ) : ( + <img + draggable={false} + className="rounded-t" + src={`data:image/png;base64,${element.icon}`} + width="96px" + height="96px" + /> + )} + <span + draggable={false} + className="my-1 mx-2 text-sm leading-tight text-center w-full"> + {element.name.length > 0 ? element.name : '\u00A0'} + </span> </div> </div> ); diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index 4e3e75d..38088a9 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -1,13 +1,15 @@ -import React from 'react' -import ReactDOM from 'react-dom/client' -import App from './App.tsx' -import './index.css' -import {GoogleOAuthProvider} from '@react-oauth/google'; +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import App from './App.tsx'; +import './index.css'; +import { GoogleOAuthProvider } from '@react-oauth/google'; +import { Toaster } from 'react-hot-toast'; ReactDOM.createRoot(document.getElementById('root')!).render( - <GoogleOAuthProvider clientId={import.meta.env.VITE_GOOGLE_CLIENT_ID}> - <React.StrictMode> - <App /> - </React.StrictMode> - </GoogleOAuthProvider>, -) + <GoogleOAuthProvider clientId={import.meta.env.VITE_GOOGLE_CLIENT_ID}> + <React.StrictMode> + <Toaster /> + <App /> + </React.StrictMode> + </GoogleOAuthProvider>, +); diff --git a/frontend/src/store.ts b/frontend/src/store.ts new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/frontend/src/store.ts diff --git a/frontend/src/stores.ts b/frontend/src/stores.ts new file mode 100644 index 0000000..d5a7ffe --- /dev/null +++ b/frontend/src/stores.ts @@ -0,0 +1,12 @@ +import { create } from 'zustand'; +import { User } from './types'; + +interface UserStore { + user: User | undefined; + setUser: (user: User | undefined) => void; +} + +export const userStore = create<UserStore>()((set) => ({ + user: undefined, + setUser: (user) => set({ user: user }), +})); diff --git a/frontend/src/types.ts b/frontend/src/types.ts index ecdd808..35ee7f5 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -20,7 +20,103 @@ export interface Element { icon: string; } +export interface ElementSuggestion { + name: string; + iconBitmap: string; + firstElementId: number; + secondElementId: number; +} + export enum ElementState { HasColor, HasIcon, } + +export enum Color { + Air, + Ground, + Fire, + Water, + Navy, + Silver, + Purple, + Maroon, + Gray, + Green, + Lime, + Yellow, + Olive, + White, + Tan, + Black, + Red, + Lavender, + Pink, + Magenta, +} + +export const ColorCode: { [key in Color]: string } = { + [Color.Air]: '#bbdefb', + [Color.Ground]: '#5d4037', + [Color.Fire]: '#ff7043', + [Color.Water]: '#2196f3', + [Color.Navy]: '#303f9f', + [Color.Silver]: '#bdbdbd', + [Color.Purple]: '#7b1fa2', + [Color.Maroon]: '#b71c1c', + [Color.Gray]: '#424242', + [Color.Green]: '#4caf50', + [Color.Lime]: '#76ff03', + [Color.Yellow]: '#ffee58', + [Color.Olive]: '#afb42b', + [Color.White]: '#ffffff', + [Color.Tan]: '#d3b8ae', + [Color.Black]: '#212121', + [Color.Red]: '#ef5350', + [Color.Lavender]: '#b39ddb', + [Color.Pink]: '#ff80ab', + [Color.Magenta]: '#e040fb', +}; + +export const ColorBitmap: { [key in Color]: string } = { + [Color.Air]: + '/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+/+73vv/u977/7ve+w==', + [Color.Ground]: + '/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKv+lKir/pSoq/6UqKg==', + [Color.Fire]: + '//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAP//pQD//6UA//+lAA==', + [Color.Water]: + '/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA/w==', + [Color.Navy]: + '/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wAAgA==', + [Color.Silver]: + '/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwA==', + [Color.Purple]: + '/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgP+AAID/gACA/4AAgA==', + [Color.Maroon]: + '/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAP+AAAD/gAAA/4AAAA==', + [Color.Gray]: + '/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgA==', + [Color.Green]: + '/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAP8AgAD/AIAA/wCAAA==', + [Color.Lime]: + '/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AA==', + [Color.Yellow]: + '////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AA==', + [Color.Olive]: + '/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAP+AgAD/gIAA/4CAAA==', + [Color.White]: + '/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////w==', + [Color.Tan]: + '/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jP/StIz/0rSM/9K0jA==', + [Color.Black]: + '/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAA==', + [Color.Red]: + '//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAA==', + [Color.Lavender]: + '/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+v/m5vr/5ub6/+bm+g==', + [Color.Pink]: + '///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ay///wMv//8DL///Ayw==', + [Color.Magenta]: + '//8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A/w==', +}; |
