From f47e1a4cc2223c4a23c8ef26e89d2c14dc371ce6 Mon Sep 17 00:00:00 2001 From: Matei Adriel <rafaeladriel11@gmail.com> Date: Thu, 25 Jul 2019 22:59:52 +0300 Subject: [PATCH] favicon --- README.md | 6 ++ docs/controls.md | 93 ------------------ docs/import.md | 13 --- docs/url.md | 13 --- package-lock.json | 44 +++++++++ package.json | 2 + src/assets/favicon.ico | Bin 0 -> 18729 bytes src/index.html | 22 +---- src/modules/core/components/App.tsx | 6 +- src/modules/core/components/Head.tsx | 32 ++++++ .../simulationRenderer/helpers/scaleCanvas.ts | 2 +- src/modules/splash/classes/Splash.scss | 2 +- webpack.config.js | 8 +- 13 files changed, 97 insertions(+), 146 deletions(-) delete mode 100644 docs/controls.md delete mode 100644 docs/import.md delete mode 100644 docs/url.md create mode 100644 src/assets/favicon.ico create mode 100644 src/modules/core/components/Head.tsx diff --git a/README.md b/README.md index 298323b..0d1b2e0 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,17 @@ This is a logic gate simulator made for infoeducatie 2019. +Many thanks to [Canara](http://canana.xyz/) for the logo! + ## Getting started Check out the [demo](https://mateiadrielrafael.github.io/logicGateSimulator/) Or read the [docs](./docs/main.md) (work in progess) +I've also made a [trello board](https://trello.com/b/LW3XSnGN/logic-gate-simulator) and a [discord-serber]() + +// TODO: make the server + ## Features - Simple & intuitive UI diff --git a/docs/controls.md b/docs/controls.md deleted file mode 100644 index b815ce9..0000000 --- a/docs/controls.md +++ /dev/null @@ -1,93 +0,0 @@ -# Controls - -## Moving around - -- To move around, just click anywhere in the enviroment, drag in the oposite of the direction you want to moe in. -- Release when you finished the desired movement. - -## Zooming - -- To zoom in, scroll upwards. -- To zoom out, scroll downwards. -- The zoom will be applied in the position pointed by the mouse. - -## Moving a component - -- To move a component, left click on it. -- The gate will follow your mouse -- Release when the gate got in the desired position - -## Deleting a component - -- To remove a component, right click on it. - -## Connection 2 pins - -- To connect 2 pins, first click on one of them. -- Click on the other pin - -> Note: You cannot connect 2 pins of the same type. - -## Deleting a wire - -- To delete a wire, click on it - -## Opening the command palette - -- To open the command palette, press ctrl + shift + p - -## Creating a simulation - -- To create a simulation, click the first button from the top of the sidebar, then type the desired name. - -## Saving a simulation - -- To save a simulation, follow one of the following actions: - 1. Press ctrl + s - 2. Open the command palette and type save, then press enter - 3. Click on the 'simulation' button, then click 'save' - -## Opening a simulation - -- To open a simulation, click 'open simulation', then click the name of the simulation - -## Deleting a simulation - -- To delete a simulation, click 'open simulation', and then click the 'delete' icon on the row of your desired simulation. - -## Rewind to the latest save (undo) - -- To rewind to the latest save, follow one of the following actions: - 1. Press ctrl + z - 2. Click 'simulation' and then click 'undo' - -## Downloading a simulation - -- To download a simulation, follow one of the following actions: - 1. Click 'simulation' and then type 'download' - 2. Open the command palette, type 'download' and then press enter - -> Note: You can also type 'download --save' or 'download -s' in the command palette to also save the simulation before downloading it - -## Deleting a simulation - -- To delete a simulation, press 'simulation' and then press 'delete' -- Press 'yes' - -## Refreshing the enviroment - -- To refresh the enviroment (reload all components), follow one of the following actions: - 1. Click 'simulation' and then click 'refresh' - 2. Press sfhit + delete - -> Note: this won't refresh the whole window. To refresh the whole window, use the ui built in your browser - -> Note 2: this can be useful if you just edited a custom logic gate and you want to see the changes without refreshing the whole window - -## Clearing a simulation - -> Note: cleaning = deleting all logic gates wich are not connected to anything - -- To clear a simulation follow one of the following actions: - 1. Click 'simulation'and then click 'clean' - 2. Press shift + delete diff --git a/docs/import.md b/docs/import.md deleted file mode 100644 index ccdd87b..0000000 --- a/docs/import.md +++ /dev/null @@ -1,13 +0,0 @@ -# importing a logic gate - -## Opening the import palette - -- To open the import palette, follow one of the following actions: - -1. Press ctrl + g -2. Press 'custom gates' and then press 'import new gate' - -## Importing a logic gate - -- Open the import palette -- Type a valid command (see **[the url parser](./url.md)**) diff --git a/docs/url.md b/docs/url.md deleted file mode 100644 index dac88a2..0000000 --- a/docs/url.md +++ /dev/null @@ -1,13 +0,0 @@ -# The url parser - -If the first word is 'gist', the parser will automatcally try to fetch the github gist with the id equl to the second word: - -**_Eg_**: - -``` -gist 8886faa6f99a7d2667ea8aa2f81ace04 -``` - - - -Else, the parser will just try to fetch directly from the full string diff --git a/package-lock.json b/package-lock.json index 430a299..fac7031 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1647,6 +1647,15 @@ "csstype": "^2.2.0" } }, + "@types/react-helmet": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@types/react-helmet/-/react-helmet-5.0.8.tgz", + "integrity": "sha512-ZTr12eDAYI0yUiMx1K82EHqRYa8J1BOOLus+0gL+AkksUiIPwLE0wLiXa9FNqD8r9GXAi+yRPZImkRh1JNlTkQ==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, "@types/react-router": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.0.3.tgz", @@ -4057,6 +4066,11 @@ } } }, + "exenv": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz", + "integrity": "sha1-KueOhdmJQVhnCwPUe+wfA72Ru50=" + }, "expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", @@ -8532,6 +8546,22 @@ "scheduler": "^0.13.6" } }, + "react-fast-compare": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz", + "integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==" + }, + "react-helmet": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-5.2.1.tgz", + "integrity": "sha512-CnwD822LU8NDBnjCpZ4ySh8L6HYyngViTZLfBBb3NjtrpN8m49clH8hidHouq20I51Y6TpCTISCBbqiY5GamwA==", + "requires": { + "object-assign": "^4.1.1", + "prop-types": "^15.5.4", + "react-fast-compare": "^2.0.2", + "react-side-effect": "^1.1.0" + } + }, "react-is": { "version": "16.8.6", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", @@ -8588,6 +8618,15 @@ "tiny-warning": "^1.0.0" } }, + "react-side-effect": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-1.1.5.tgz", + "integrity": "sha512-Z2ZJE4p/jIfvUpiUMRydEVpQRf2f8GMHczT6qLcARmX7QRb28JDBTpnM2g/i5y/p7ZDEXYGHWg0RbhikE+hJRw==", + "requires": { + "exenv": "^1.2.1", + "shallowequal": "^1.0.1" + } + }, "react-toastify": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-5.3.2.tgz", @@ -9297,6 +9336,11 @@ } } }, + "shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", diff --git a/package.json b/package.json index 2f0b86d..47bbd33 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "@types/deepmerge": "^2.2.0", "@types/gh-pages": "^2.0.0", "@types/mainloop.js": "^1.0.5", + "@types/react-helmet": "^5.0.8", "@types/react-router-dom": "^4.3.4", "babel-loader": "^8.0.6", "babel-plugin-transform-runtime": "^6.23.0", @@ -49,6 +50,7 @@ "react": "^16.8.6", "react-custom-scrollbars": "^4.2.1", "react-dom": "^16.8.6", + "react-helmet": "^5.2.1", "react-router-dom": "^5.0.1", "react-toastify": "^5.3.2", "rxjs": "^6.5.2", diff --git a/src/assets/favicon.ico b/src/assets/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df4658aa2bfae471bc0012298fdafa0a495b30a0 GIT binary patch literal 18729 zcmeAS@N?(olHy`uVBq!ia0y~yV2NX3VBW{U%)r3FRjGK8fq{XsILO_JVcj{ImkbOH zEa{HEjtmSN`?>!lvNA9*GX(gAxH2#>I5;>sIyyQ!IXO8yJG;2JxVpN!xw*Q#yLotc zczSwxd3kz!d-?cy`}+F$`T6?$`vwH~1qKEL1qB2L2Zn?Mg@y))hlhlRhekw%Mn;B5 zM@PiQM#aZRCnUrqCdMWu#U>}mrKBXLr6px#Bxh!(WM!r0<fP^1rsw5l78GO^73Gwa z<du~bR8$mJRTWiN7uVF3)Yg{P)s@!QS2Q+OHaAzdv{bdW*0#6Tb#~Twbv1N#HFS43 z_VhIM_BQwTxAgb7OqkF*abo-A$sJRtc21ktHGO*bj2S&MX7tRQ**j}i-<&!9bLUQ& zH*ezn`4bl`n7nY|ltqiCEM7cq$&zVHmrh@{Y{v5CGghpawQ}XGRjX#NUOi{^>N#uH z%w4;7?z(mJ*RP+yVZ(wA8y0NbxNy^^#hW)T-m+!M)~!pnZCkcu$BJFMR_)otFbalj z2&6Z3w=gg;GL!`Q1^*w}fFbxhyD9?%180FpWHAE+-(e7DJf6QIg@J)VqQo_#Bsf2< zq&%@Gm7yRpGp|H1FSSI$M9)yq?5`i^3kC+4CQlc~kczmscV9b;Mpr%msO-yO*rLcc zvByhB|Kh>d9xZ|CGIJD?FB_S?eR$(Y-XTs!nS}rU*PnlLn*YZ1ReN7=3cI>Ftkyn% z(zgZgVzX`S!(-=#+W+b5c(dixjf?M@{wTy9nx^l6OgZ;~#77~i>5Y^6Rx~mn@#a|7 zIYs3NkC#H6&T9RzHbG;JhKh|R{MPU&rcPl0nACMMM$+Mgg7l-K9R^KH<rSMfJEq@i z71yafA<^Tw=ZfZwl$XvY6a+s8^+z;4<q~WbJmUTJQTH@%7aleN{i|K(QF;>%cR1_` zS;ly>sI$Y7{bNw4n(Jv+CAK5o<-R@BxLtfU3+l(2T1M#!7@l?AQ{lWNMk!IMtKwsG zj-=ZW6M>J9<StHXYRQy(bkuNDs*Tbz&kphSj%hv~Gma_5#VAG>DJ0HntSD^CIoaEi z$?#~Y&8DRaLTY74yggIAHC24BbWAroA;#`8qe4)>b)xRM2?i6D;<^;0Wt0<>T=s}K zZ2RGG;7EJL$=-sGZ7rQVA1CqOd?d~&Ec!^5|Ikt<6(5_9>1R$%TP0wyQ6bJqDMrin zkV|95$)=o@a*V=^k5Y{eEmc$TdC@VQ^TaeOL4!o)xMNB&uiOr_^i)VT7Z^6SaEg7L z)Rwccxq(yU<D{N~jjauwLLVo!6l`p7;1u|1)K##tvw@TEqftxF#-0{V?vF+d1snSs zI5|IFYA@hqWEAFm^i=4f5Eql0$dPUVJw?TYLk@dN1oajwCOA3l*&?W?sFd(VIgVp` zf}p`QQ@c2h=@SGEwwc<*aZJA;XfVyxDvo2ign&VrsYM*e^aufiFjKQQj_ET549rYT z;y9+?5HJukHIDO`{$qkZo2g+O$8-xpgJ&lCaU9bt1PzXv=*DqOUolaCn~6@G$MhS5 z2GdNm;y9+ODI~nf2-qW_=j(VN;^K@7#TcoU8pB1JADwoYa5E-589!<*$dqF`)}VHT z`{5-Y7N56|`o#||-FRa9E?0T|CEk+-4Ze1PoY<xupCwwpXM&zWLY7GJ9s#`!<@i^^ zg?lFGy--YeC6v2IKyQc3zAGx%DimWc^f#<@o%7LYM}h=naI?hY)&fVSPfM!=k8!_j zN@4N2x~N<H5bMel)4Ps}=`Z0vrkJ258oozBZ$?AS%Ak;sPP-C}n3h=?9_4=7q;q2W zsUyPrE!;**@vDS<_e{_`(burjP35E04h8W~ON9!LaKCKY!!d))MNoeU_b27}Kivv( z9O5EQ`zpli_Ds;z=xX?=^QA&DCV=VZqwohGopvpdVLG;a0mw<2PrBU|k8{6dVm~2X z&(tS=iPdj{{=F7y{UzKniU~HHrg0qN7B2gK2xjb=pjXgU^HJ$cg<|XjiJy<0Cwz3; zb-<SC*j|Rmtp$zZPr8dA9_4<?<bOi^dQ-RfCDwle26?Pv`Yqghl;Y=bX~%hpSGeul zAri7@g5HO|nnH~w6^gL|tW3vd7CdS#aCAK(9^TX`eu;IeV!RBeYMh67NJmYf@&u3~ z%}+-=4IZ_YI37JAF5c7uQluO&!=V`GA%3N?LGx_g9s#`-oIiu6{RF9&{<Ku(HOP~0 zPrNOUJ#H;=Tzg`AP|k7gmrb)K>Zi^Cd2*|AyqAHDehascLIT%jkZ*ew;=7DMj57-H zT$`lymvHka#&;Ql7(R;eTpK0zmvHwe#&;Qj7-tmYxi(0E)F{P&G6pexl;Vpvi-XiC z#eXsaG0rH(7i|JXEst{iCqod!M>)P|qbNv?a{MO)5aWz;e9;CG{UzK?4*OElHR3$P zSsH6jp7Gl=L63vw=cK7KD->e|cs{8rYkzdwrJ(S{+sq9V3;`#m`{aNk{lEnM$QhvU zIH(wJv_Sx5kjp-wGzE}Boi#I8`~&IN_>?;77AP1toS4q}3gml6<@jT(EkTNUYb00S z11YljlsYF0r0Bzm>4vX*#4oW5D#Ty93i8?_hkZ*{8OE7dI6N>}Xt-!!MdHUMj}0}R z!O?pr=ykCDoU~{i$OOSps*%1RXKFq1UQ`8gX3B}_DqBI$d@(_v^A*UMf|uU7&9{2w zdYJJ@%hS^<q#m^%<zD2nuV;l_oQJqeSB+#?CCE&%pGHewfy^}glp1gpWM<Zr(+yc5 z=RG+wy>2Qf3%$r(w|McTii->kACrDwT7C-TDmI1qbs-=pOEuQ)42j({K`(>j(^IEZ zP+~ANc^(+K=fwf$kI6rkLXUEHi<@x#yc8S=QY7+e>FQaaENd|9CvUj#o);6CeGh(G zx_A=E&|`}6w^o51&+D=;L`Z)Lw^V1%N>B)!Own3!@XzsXKGO>(I`MmsgNzJ&{P`%T ze8||a?0NTdkdYa@=f(Gf9PluNllQ54TuDdcvaD~Pj%M%KP~rI4)GEH_828IdBG1{Y zt#3=eUcFjdyMNmB>Ec%FzP|kD^xNJhDl#%Q_Wq4~H?1wM=l9NEwQyq1v2H&7M<rDo zcJJJ`tLXc+LtBDWroU{BE)Ng8ZeGss_m$mk)ydQ1{T~lKQuSLNZ+3m&-S}PWW)vip zz5KU%>skGc$9$SUAC2ELL2skwt-BRp52UW)*}d<}gR8&qD*rA07~pC$VS9yQtWwdA zziCgu&2c)gd*^NK{B8VS!;df6d0IUG<09qm4Rhb^tKMa^c-Q(XXFgpn-#u}TzNuM! z%~9^|=?~_<*;83k>~%D5^2*u$_ukBT!OXg5<<Cc&aURnb%&o88zG(@Uc|zvXyVnoo zr>xeSbu4(#iv>zH>e2esx$kCv%dYzQH0;3X8Ety;e~xf>PdAXwwcES0$Sm{Y%d{2W zr_P$GANQ!Wg!96~W0PG&H)eKgOFP~R4azm??ypdcbt>NV_0EN*(@svCm(N=6zjESf zaruvn9(O9tdB1O4#oE+KFP~oDof!KrH)&r*hq##jLyMa=F*h$4y^F2iQ@KW8sEO@a z_ivCnA8Y^So$cQ`#k{oq?e2YjwW}tu70T;dP1*4Fwf5!j9iJj<wyxGsjrlxH|J>u& zqusU7<Kxb(Hc>YG|Hqp{JV|Q0{<_DlC5G=`Z$7bUY5KcJhGPHFOA_lIyS59u)z%tr z=#7ba79U~noptNe(ZW3&DmLc)|H><xv_&jz|I5?2u573&l-6I;9eezJ{%RKG^4D{p z9%Bska^BG^F6$Igyzi^RkLn9IeeeFSSf-!nw|SbrAIJ^9zx5aInPGkI4)<zx&s9^? z3Z(R{8a6z6b69q2%;7ut3~o-pvf^p?>59aUN$2lfjtq@vK5KLHa^i+1o<AQM#CeEk zpR?0heL?E=xwgHl4OUH8E0EB)sxWwzVEQ1>wftF}+>3^YiwmB1?*<ugYPvh`u27SE zSDcfJH(UOEq!Z^M?tIRy`IhXd{i@N=Jyy;9Vc9J%YjNfM57Ts4<!5oyx1^RCo)!=P zc<9m5uJ`Ae?o_Yiy6pe<4bSB%HH9MjOS%QCV~RY@zg{@gn|0Oqjm*(*KB-q*i~U<$ zM9O>rINzA?w0kzl;)BnlS1I;v{NmZZI_~TVarKW*yCgOoJ-eu9+P0DtSxawq&YoOx zk<q!<PDsyEC->Ect1ARgi;I6e^k`|`nwU?!BI^&Vs9N+)DXwHkz-0dxZ^o_jl}r<V zK2nH_*mEUo`N!OD*Sj~bDX!^!rJlz3$d#SD^hWi9C`ZQATkY5{H$3(JS&{fLX#RWt zP<4$Lj&uD#9h<Me^l@v+%Cjep=UvdveU;g}*JIVfim83#vKk?8bJiaGePO4`?_JyS zUcH#EpZd7<sJE}3+y7IGUg=yZn;sP^vUbzQMTc9m-kLp`>l(WAt1J7qq>cLVUdOn* zr(4O`hJ_xO>E3R&<7$xX(N!sXUMMVdiYfV+RJFCw+hC%8{3%dwdsQ13VtZhtbg506 zc=^65UE-IP7P;HJe01@zRGij=sIK6Z6&D$uLeE`K58?QbRP{BceV0+7e*7s=*6MnD zFGTdf?4zgBx31FkN`2(o&VJRRZWUKUxVEVMG3n2rmb&cOP_gm~`#rs&iLc+6oX}oW z)fM=$LNRt#NkM$EylBL|>xt`Kj+~zU=;NZ~X01I>C*>_&c764pBhvZ%MEb<V^snAr z&bpw;J2a1V@vJWYhZPqa8_S<(?<w2J7QB9S^Z}RMHJVcTI&rH$&0Xs4J8ji&rp2qe z{4Q2pOl-{0kJxo3t!nKmR-ZMer#FFOQ0o58<-5bmS4ACIu`VgtAg(0f!S(7qiK{uw z7NsXB#qJa778lbGwRjdO&ipQPvtW;ww$af?uI(&#xu0jO<1CgpRfs#fvqn=yUnlO5 zb?w5Ny|--buP*qp<W`sW!itNGjrQz&Zd{!(Thu05{OPBq9(y)aeC*5KwasV$#RC;f zUUhj*tho5FL4SG9)!cK3g?anT4fW!=j&OI2pZ|8l^wa|B-BNP-A@PQq0{T`GAD-B* zFEh<N^_?@Q<@EGFpj5Bz*Yl?8#ZSITS~^NUAG@|6T6+H1{*1T9$4_jKzHj1FcVv6b zNm+e4F@5&ycH36ni9Nib|Bj(iZkjXm)AlSKxt)()*$*wfnjQS#X7AGf7gL_wc%|P9 zp8vk6C-3JZ^EexwxO30f$NoOMb>^%%rMwdtV|^1P%3gaMe%icBN2>C%Yx}{aZ|`k5 z8@8)<ljHroFMKRHv%gm;$>08@n!e}9j@*)uQI~gSMFp?D^<a~?!m@kWCu{=d9#u-; z^Fm=qNzG2#+l$VpE-!qpUn(Hbu>4-x#_pV-ll0?ibmFd=rsS5ddf{XG^2t0t#-@Vn zxA(WK+T!t~TU?fD`LFp6`@?^7AIY_dxWee5AXXcz*^~Wqk~T<VnQ5GD|CiNgKc$An z%O9NaF_1@g)mDoqUE;C~%iHdq{ui_Vj*5w7YsRa!ZRa<xn5JKP{PfEYe<zjxZGTp= zG{5h_o-f5(>yx^j=2d*$D0AmRK<vlgH?~?n@Bgw_a87&Nya%CMT^0TJym)P0>aJXx zx+?H3qx+s_!vt@;JcXkrWmA+vZun;E_jlG6xee!a7cbELv7>QGRkveb#l`96S{vKf zTfSx7y(e3x;JWRfXo-uTRIB&=h}bhneR_ECEoQrm>;iiv`STrvj=CyT?|HG>dh1d{ zscSvo81g)hA2`hWs$!b{%*RJh2fM7yx6E~_c8E7;arzd;{HiZYuV&_B*Z4at4}YoO z_c))wVqJdM1Iv0blUYx_uT^~9R1takgG%L!`JGpOUbuXU<7U_EdY;hIgQunRf8EOK zy=$-e>RZF-Zr?ls*6Z&D0<N;IKUZ<{;*BK{m-}5`lzho_VmbTq=%I*neMZN+rx!2w z%>VLnhi1gyKF{ed?vzz;4lWhn)$?(Y{@W`jpPH3wF0-)-N;oLk|H|#e+ruIgb>cT2 z?Vf)0v~{odE{ogD9@8y$o)r&`d$8$f_r6Wh+f8(m&$!%>bJ%s{ROY@T8*5IA=*Nla z-#5`nJ}diT`C`XiN3!od%?W+msvErL1^4c+KFLOLId2(%?>VE9^qDXG_Nu)bu8QfW zUpG||zSFnL_CbbYJa^!%;_vGdMbh0PA00it^WrkLltsG*x3bGj(wjKDcza#oS5{r` zJuhDGn)>&s-N!BL1$R~Jy3eiKe`G_=Ndb`U>{7itNtyf>k9K)8pRu;K5Bl4x<Gkm^ z>0Mh_9Xz4Z_l@D2-q{Cl@>*W$r<5K&z2}(HY>8XU9@Cc<Ow|{hBkS8IuK(Qawp3@2 zQU<?8?4@$YFJk^CFH~1DF`HS&eF?pLYPY=OhqsJhJj^>6|9kmiy1ww^qo*G|tq3xI z+;QMG^SR*de_eW}-L>&uD8+OANX13*($~FiitP(-GvBaXl__U+Qv7Pdj#r)2XG^u% zIOXx5xW>@fu_oh%H|M`M89{q0EX{9S6?jsted8NLT+n?7zj@b!MA@=~_Pog66<Q#j z?XJFMs&;`^$A`TaKTH?=^(ob9PetUOIij_e3ug=8T2*^xx%=Uq45ldyt$41sR9u{1 zlI`4XzhB@s^R`OyWM|*pOs**ltaz?2nXD|IU#<6%qvN;uqo3RCSNHcFEBs*M`XJqX z@}sA>?yuWzr+oAJLH#Fl|4j&xQQN;nzSrP;?BxX(R}&Yg9Xq`>d;iaN`LCgOD{fkU zIm&WPuE1$=;9_05Y$Xw~Zy-0l(D?hc+qm}jr*o(OR@=!2RUh~nTbpHaW$vZc#a=wY z+bS}5KYd^odVSiz1B=r3z2xUQutfZ*V%1V}=U~;g%$hwf1it=x+BNz0o~66<W#(K6 zONpH?!5j81&*eh8yXB*$Z;$=IQm*%I#h=<+0k@b>t-CDHx~YHv3bAGrv$&F)U%vPM zFWy(`nEk8y6vtxQ2iX^wvkOk$G`n+!MDrB$xLg0yww`&arT+VD+XcA;*6tUAKfP5^ zoG&ZdF+KbGvUehRVmB_z2TuC?t)aMVdGj5e?YF{A+cIMIym+88t2Qd<@P5(1|2Cc3 z&c5T<qK*U1zFkQneTrIA`nl%+`}fuHE#J9)rFZfk+XF{c)m$D=UFNFDIA6B6Q(ShY z;lD?T_jI4!ds%Lku*>#=ac$3w@K-AhMN=BQj(XpA+Ba=U^sijLh&=uu=X{lUX574d zMZ<|za>1sLm-If@-?$n$<IU{4e&Mp)%zoWD-#S;^)wozI^6q9})t(m{Qa)ZkZ+vf6 z-Mae^+*Z~L)+9a7>)EmXWMGSzk&WM@rEmAASnjmhy>5P4%DHE^J#YLG;tVsj<qGg@ zQ#Xw(@!9nI^nbIBs+qy|uX;{?YtWCm<~k|Ycfy}0Tk9fm{akakJ7;$;pI@AQGOqf7 zptOhL#jlUnzX}RuJD#~GX7{(*zwKW(s90R#-&u0}*5lndADc|JbNPpfrWRa!<jTIJ zVSnY+vbp7<_7A6Q{nijv{ZTQ`-_)~+`|Fz%wR>WAo0VGcRLzY0e|K&AugkeVmiV)( z{8*4VY4#~26T3%CbHBZOk^3+AulaSan2F`@CVXc~=sEPBFCel_O*O8><kXMd4|7Z8 zUfNrH536_ldrrn~YLA5IUU9(}Hz)3|c)3O8YkqX)n>DiwXUzS^ptmQXY0>jfT4xUY z=$XFl|CX}Kr&k{zP78Ls#ccQbGs8-*f6*%r@%R+&dEv3cVC$M`D)VbC%x*FF$=Xlp zkvJ=MTfqLzX65%EFMSI?e_MS{{8#%w8!pHdy!*G((PhO0zjaz?H-rf4=hpB48uEX> zI@>Mg3{xkyqh(IPnQf|uaU~K>LDkg<<kq^KSaM^j)77+yMV-@k-DW;lG26r_O5>A% z;so*dN1fAW-DbX%m)g9-_TrM0u16)OEUCC?$l*8lE#sZZZhWrq{8n2v3kC0)a=U-; zl;nFe+hm?`-|6J|_(o$@#m;YT%7K>mvRY!~vK~EI_=(3e=3`KJ^#S+4e;wRd<8s!2 z;_-Ca^Wryq=Bf|3Gf!KjHCsIidGIjyYPyHeqo?|%3{57VLz4ql@9{L;d6)SqMf}0h z=@%<*X6Cl;S?j?2mhoJ<hP&{d>t9a#iAqhlSn;x^|FU@f+GK%w(xKbg3$j|2KFya~ z>BKxqMnBj7-{Jfc38&)CkG?e=|5e=>BbULHDt7PYMUOo(vC_8j{9h9LtR?SDzGU0| zdeH)3--TyF7C)5e6tA5)uetsYw`}KvkehM^uhN@~Ob&b%_Fc3FBrUI>`(NhK>l@tr zKPcK)^#<JNQVR@Qb+N#wXL{J{Cokh)X0$Bc^sOOwTcSgurTk^CcaKgN>`|$|Ki7I; zXrSv`#&qvrzZ;nHp6uaWsKtA%V9$%}9*h6W_g@s`bas8q7#C;L`K)4L=ah-7Oe7*7 zFMZq3zh|%4k!G)3%zRE(N(LFPW-kjeTXiYnNyqeU|G&;J4Pgp!t!7xi+TC-z>C{b} zZy%iw*yHm@{r~;2rcBRI_vIWGn|PhRZnf5m_h`VL7v4QzHK$Bdx&M|i-R4u%rBAkh z7FqGSHdbU_zk1prYLd-%_7A7REhc31hhNRq;5zDkyZ^sw%d{odcAuYGUoU;=ux|D4 z#@HIkp6NE_(dYgjzyIoo#Iwz|5BB}zTQDWncZE;L%0`JE@!HlkeE$pG+)u1=T3>Ub zCCts@lVh+JcW9OZsDQEmzn5=fsQy>SSnK@@_cLf@+PQb{*D@7IeZ2IlRb}38)sw;1 z2eSWubjY-vcbE6|qtgz1L~1X5?S45;MgJ|M`!j!T!M>O8XN5_w2s>;bp#O`Bb<X~6 zzj;nvNw4*oUa?V7=G4bq%2%@_WR7~@-gk4_l9{o!F6H08xHJ2u%wM$Xs=<!#>D&JQ zEw_p|wj-Z^!A%ao)O_2ZwQUD8_iTy!|1Bl#_~|LE$KNvEnbMX#bG-mtY3_FWxH~zC zAAU|d_<B#bpZtAW{=(*f8D+|!&t`^Z3;cTQD!+fr=Kp#5uQivyWqkjoo#|XkU4zqA zDHi#Um%cr=&DQngyUpxZnJ+bG_SsvOYqNNpmRDp}FFu^sy89bL*?|`J^QL>%IA1>U zj^AT(&-T)tr~ct@8P#n9+4+}kzE>Zxw{3xb+?R*3l?xW9wJ-kGApYwy!}3jee->5o zHg2!5G^+T2!n2y;cKPA{l|5@2S6vsV=$>9GYwSH|3%ku_c{Yn_AD8wr#@6iY5<fmY zPOS8VPvHf*4|A^@9h$u6_qCNt%mt$Qzh3m!Tog23R#SZ-`LAa~v81(h=tjm5qWWRh zUC+I@vA@||(P&>iEA8>hB<2U2aeim-?TJ0}^<KN6PTYfw%)XmHhHPZ~Afn$UKU@E* z+y~!!jt8#Go_1@QG0c1PbX(svSAMT8>>Ij8_MF;M!}<K$#ne3(dka&3%m3{8{$Hrz zHpjf9TWfaqh}RaF_t@W<mHhmPV@zdZ`pi7Jm1%E33+bm{FI}@n>xNvxiASvaQY%ZG zOta@tulTt_IraK7yG%R(FS{A@H_h3#8m#zx$&xp-Ze4Rf`?w=dxnla#&l)qbcZ+{~ z^yyR{$8!PW_%DgY3qqwtPi!)rxa!)T?uv`Y%al6aPW!Z-ea?(KOJz2m-1NSC)ioRW zkDC@ePKkc^t-<uK+kw?Q=4PQ=pH+5DKX2uA?P(6bMRI#=NK)CS;-{;kKHD5Qtt_kh z`O{YR4^<2yDW8gkS4DlkbNsZY#rN={t?YL$<TKgKo^7G;yt8ykMPbF`7i;?hIf}Nh z=e*p`aL>0+XLb0tXPR+e7RE+gQsi>__N^iHFW-UPC-djLo4U60+~cRK`vMd;ZDW7) z@_8edkIn2CU{TdAbJy9wDE4<SR@N$szpNL!KId$)tbY1J+iJ6~p7U#TelZ3tUFpf6 z`t{T`o9iDxIUZM+nR$!3VhP{WStWr66QbSsRuq;$);OTO;JW&D_75Jit4yt5&Rmms zch>c8@!BV!_)1EejLbLM9{9&6+;OJbcdyCaU8d&?_w2cHkn{ATjdpcX@4OZ#dC#iK z+*O)A?{<ad{Obof&$N7Fc;~gaNLY`v?DaL9?H@mRwyRluKW^7{HhXE{PEP+R<q+Y3 zb~T&+ue_7yY`Vy;WuAC@dfwex&rRa`nC`v$wR4|y(}Z0s1bR(<_opP@nfdNm_v+u5 zURxPBdgb%)SUR6UYs-q4(-%eWyH@(xRer}7SJ@c`OSiHYB#Lj9_`kkxd(GNnN&Vec zI*nf0{0|Q4Wf}f^lm`)9xWB=2r>(*cJuR1{syB~??ta>OE^*JCb1ycqXm7Ml2>vg) z;>Hd2^4(9f=N_)8T;D9TVad0K-M{i3j^<@@slA%EzLf9r(`|fSC){o`^L>qPI8}RD z#pjZ4{OdbMPn*k5+R(d&eb1$O1}*bviE9kxYF-}co_#z{snYdTLAAqz*pQBcUkmqY z?Pc1wR#^Ynj;C|tuPbuiRjyq)Pxh}?Ky$9|VU@j1+s;PrIkH*x)Pb%qE9(ST9DK09 zw7H5kXZGfboy(bp8cS=Jn#ol;&RuqV&x#%42e$3(ntr%px1@W{3-6DgOs>4i(&~F5 zx*>Pnqo-T>+(njc`?8klULsTAj^&**7C@A<%Jx~rY+;{sY>S$6$EEL?Z$&rc_B~SF zCatr1@3#itzy1r<@^=dxdUEjZ+w%D6(PaJp5`#sC<u`st3C6B>n=x(o*Qp+=Ig!?J zUlLDSbiP+@>vmsz&G5O~is<k6ce-dLp1yO$yXLlQ-2R_k#mW*B_H{4vx?yDgQRrmZ z#9;1nIh)wp|C!$xeBYWe&FyX8_h(5=Q#YjgJ$kyj&t=BC`!R8qJO3r7*Z&YydnbLc z;mT%Zu&nBVw@S;!-`Ujc+EutSz*FcTn;A#^tD6(OZWxJw6goHgbFumRb$e<)CqDl@ zBYo|9n+xxmvP#@97q);EB-QLb(cOCLx*_*emE|Ar@;NswyEJc2FlY2Lr8u8`4{GyX zzB{$re75!d<NNKZcz*RJINh4ITPyLj%#qWLeNBv)xli-YUz?Xx?^_?Cu>1Hg=f)`8 z3oSCsgtnb=+;e4L?2|v2_D&7YKdloo$z`*>7}NA`PC`>Rq&|K8bkDrEO6g+L<ZY|> zZruAkY2l<NoBt^-NSn_4r@1bKSNfat%V~@Kt=OjSh*%+G5xYXAYTbUJ6*rT8PbRKP zJY1(yoA;#Nd&*4d)BW@I-}|v=`Uf$k`n(tU>{({ZH7$Kib0S_=e7yF}y#DpQQ?G9K zTeGMCn!Rf4`hLbMdLQ2&>Ft<aD$8h|mak*Ku5RI^6yNzAEADFho>E+uc-ZUs=|z1G zlHA+htzWb6_m8E^TD_De^M772Gw7C7=;5}hz0+f58~*I#p1QU7{Qa!>6)Fqo3bv`3 zZ(PyFt1YeX|K;!Is2#QcPrll%8_Ydb#by(?vt33MUl6Z!m{FWx`j@}QXT`?U{YlDA zejfd6-;rw{ewj#YT9j$&VVV<hvO;om`oSwtol@^~7p?7jeU_c$&YopY6|QbbRDJxk ztU7a%@`d8s!pf&de;qqlXTd#HrR~>>hV1L#ObppU)=TQg^ILC^xWzq{-9PMp{#&-4 z0iK8Sb{i~xfAmQBwvZ!bQ}=GUoz=Q8!1Ks$$waS5zdh=fD{Wg{v&W^={QBW3FPD67 zy1%;Pty0{iH<<y9%4MdezyB^$+SXm+`N=JrOJd`)m6i^!IoJ91;uxjp{+0?p(6M{g zEas3SWq%j&ciBCkDJRCV%6RIQ!xOu1=si+({OG22U~;bSxjL<+-5t|ea*i<+hnZUb zUJ0^6=+5O1rnEbkpS)QPw!mPyAnTbKSD{=<*TaH5UK!Rwg124w^elSF!M6A6mp6++ zDkZlr`pCjlx#Z=|=Zja}(0P=4#kW^I!Q;?tkGj=bX5AH%2hDaHWR?VHeYWjAa=Ih8 zS1sYxi`@zJL87x=_w-b(y~yHIxstOgH9j;)?4!}6MmJ%D)DrKN!J!)?kDTU^Th;7& zdDep3kfUjW`iCo4@VULs?urWp>E-#oWFt$@%_|~%7lG~BwrV3wPvtVrDp#;cJ!P2^ zrd7G&5RUe4gRCu?QDDv!7iZ2H#zj!6C!5`b44zL`d#MVxaYAXYO2WAl#k*G}ZSI(^ z*l#ka!ScJQr~b;Wvr2JocP@D_J=4jW6bE)a&&+EcOyA~YPKyfwJLuMR3nsSOt0sFF zfF1ND@G*zPmW7#Bj$ms$%vT)TAU<oEIM^@EI|^A2%Vo@hYK^*N!NjHu=RP_n$TQpO zs*NbvO%2Yx$_baueM2DrexS=}kozK+5$r<7_a<Epp4qcjKmy@I%wmoiUqXaK!Im)J zSjD&O?nM`fF${6~yqDYF`K$(ch3!n12;*#%KyYAPdhe0UAz@mP4i2D8`R*Xz4*6xE z_*{CQy;m{einZ@mIgn$#_g|NCKCt58+p<tll>D8S#lyH*E_>Ct6(Cc8eZ0ZlBVF?W zVru{KxP&_on)O#DZLYg<k=<3gfA0Y+h&lFuR`GMiF?2J?WNaz}hwZPL%N$H;wHH&~ zg2VR9!<AMuwy!;TYbhu!Uv6G0$a1D?J&b!e+9ToKDz)tCU>Ba(?o~**X6$=S5A4GE zq9E>p)qUVFsGVlo)DU@k)|yywc-d_?X=;cxH;LR0kre}Ri{Y|+772dKgt}<moa{dg zhx<%pt-(se`Aq5>5^H_kmxB$`u9mVtuwkDq-?z}CX@5UxTN}kJc*?=}Li@)25U{}M z>D=={I^<1aZ`Z8{`C{j$g&&!DURQ@7$Oi{r_=^k|hF?`u_Nzc)w{A_=ABMxf9=W>a zh<_|<t#D+Rm%VEnICHMMV9?93CIiM3(C1+ID74HS<bdi~>vF-_Sv%)@6T_F>AK>y~ zr_&w<h9llHI>cELJTGtcg&28vi9o}??LOcVWu1UN$AQp2e-<fiTP>@<#fST26GP0= z?w@_f{Pt|95q!kTxT9<O{jXU!3?4n@`q;#9CTrKWsOY^?W<3=<7d>S5xm?2g;FR9S zOYV!=XDoZ^wWr0E0>&+?ms2;S&aGJZas|Y^Telzri9atbz6i1`H@8gthRLI+U2gma zzL!lKy!DTG&#&Z_Pq@*uO#7pdnAI}DhSR)~yI6CiAz{}s-9Qi=OllynbWH#MLTp3s z-HL|?r|ZSJG%>{N>3CASy&?DYG49jT^*~B0dT+Joy}aeNCq^+&prO0sW!SpHBd4df zg93T?taW!!nf6ue+_dN;Gf(uzlDA+<(MPO|3UP<Ncs*v9_!e_{YxK@zg8JcMrgaU8 ztM}fly0bRsan;8|&HA$0QuYT7j&}bwKd|lVqt>V1$J>ta8@!3l-}a5`y2YcXr__7p z6K=HM%Xupbwo|rOK4HeXlrIp;@Lu@@iH}0dm_drZ!xb5WxPj%H{$0|Jc`TxTXXd*Z zml&AJzCOzm_`XyhWDEOm&x3nj@7=j-muX+c%gsv!S<YNaD_s@+xMR9q&JU)~Tkdwh zx@Pfc>G@<(erdiJ6M9$5eb1MLsZ!5uU;ABEkdj*es5RO>_lwD)J#p@j-LI}K6#sbW z)6%!iZUP3YuU}lTYHMG`OXtgiXMSIqyJ}U`>yGJm)l!ZJ*4#_w30+%y#CyIl$Y96v zRjabrD#!ggo58`jdYACm_|UD_Vvlie@4J<k#lg7v*>2%b*X(<#dp6W$?p|)l(zEOG z+!d=LKX**8^EYX02<+b_9BP^^_wmyEt;YlmUZs{VT9tNIIquiTbqo^Uw;B8UhirZp zdzAZnS>-yuXQlI3{a%}OZO`h8#GjY4WHWgf7k{(*93q-6|Iw&{Jw742eAcR@x5{yB zA0BY~aKGLt{wP&|f8T*E8|11L<JfGkYcQ#;ElJDN&}C%)cxdh7u-9wd1PwCR8heLs zV0_UnK23k^wQX*K1}~G-r>%-(cG$!7z;=Vd+h`bX)-?krvAJ8GXDHmRDF1StTReV; zG4JJF?*o1>sN!{~2YGR;T$T)D^SknAD^`^rS+{qy+M`qf+sg)TT+{njMY(T@dj9MG z8HG5uT#%}J+n2vsxvJFV_x{M!(;F)uKJw0v2h}OJ=Pmjle%0#D3gi0V&CBJOL9udm z)+Gm~Z*#V$ugEHO$^R$!vi_#S9-f^`8(Gf0yk`-#mhbi}zx!dY1ODG;d6dery)WU~ z4r%x2cVFJ#wmyDCLxtogH)YNlmv3g6=aycYy-zm&i#8k2G4AVSFRhwl=L#!KeYN55 zy)SQXU0Z)O-ykkx-<CepNez~Bc><U6y*?Xv^NRkpz6!~*SZ7WN<J&Xmuey?WcW1Td z{s`+wsS?uH4z9TU_T|h==PPc_-ZTBn=~C$~alL(8;xcs@ljm(+p6+Fzod53I#r4;7 zG(aYAGnv+4IQ#9(l~%H!mYSFUzLCMN5ZAVGu}IIWJ&!#~t(KUVvd?*Gf3>SZ(s21f z7N41U{^zF5TXgS?Y|6sF85VInejM5wdt=L;d2>$w?P=dT)B1?R?~4VXuwR>H!We8d zd+!Rb_AhGhI^O>}|5Y*0?ZX{CAFsWeZr9d2Ov?Y&cuPQE+0SHFgQk0?|K6A~<GvNU z|7NJf?f7vi>Pi7qTTH&cujtDO_qO<c3A7KIJQ0-8qApf2wb^9&`(Ayq;N9;2OE1#1 zoc8qGx=_K?wkH!TdT)*IV)<3<AC0>HmL*<@yX6-+Yg^`*;H?t9;(Gf&B*?ybxy5_6 z3p;PQao>gWR})P@;qWfoh0)lG|LRI7_OH+0NSJPu7u4sxX0oV3Qa?D)JKf^;iuJY% zig6a!zZMCyp1Gm7t0Hr?ZoJT=)~Ba$ZfO%SNP4x!WzUssbuN2U7OoaNb|=%{`|9(C zCwa#NP4~`isqj2>+auvjmX}M$F~2XN_VH_%R6KlidfqV+gGI4Zw9YfGyxXIkm1*zQ z1xodiyjlr|zC;%7DT%Y18z}qM{fM`c-o67<o=&-aY1aCgFSdth8pc^zS1k`@^@;HJ zYu|XcNBPTattk@vI`J9SO`6pwA1-(~YieD1X~*=G&r)Fr8eTv5d$jaZjbhv++p9a6 z*lfJ^>DDf~IV<w&TlbS64;>YcTgK*mZ+GOLkb80yWb}37{g#_-aQNFN^myqBtp&Hf zF+5T|D$A=AuzP9P>+`G5)XiG;Gh~*&=Ep-f1!o%_=$XFmT(8xt9DA=$@oD<;rkflr zi|5Ntv%UOpl7znGZb|o$8*&bNmPB5-z_hgFTVvGzmHz`z+}XLicyV9uU&en+k8-EG z`<rZY(ENS(<(A)DD&%iJK62Fi`O;q2&}(&5#PoIIE5vnTUgTW4RQfG3a{rX;$B$H; zym;2aslKKBi1)0`lDv8WhuWS6A3wNS$-miuzFJ)0)%lS<|9I{PJ#O8+*j*}i!H$^+ zzqicEw?DJ@@~gi`Om1ABA2H#d$oZhhtxr$0_v!`Q5k9+2`*?m)+;iW$l<@kfz^hx> z1@u??-MApV^lg?I?~hr}t=?am_`7)VHm^^rws98LyH<Z>?TWe*BUQF-W@Xu3&zL<= z-lfR|y8aHV+Owf1(O+}Q)^$6lJa{mFQ|xo!d!AnP9+ILUGhg<Z?sIT_D?Gb!n|!JT zqrH!n`K@d715P#mGpIjyggf2cb$&2Im0X6}QmeY%OXPivPhWqu^lbI-i!&+`e|`#6 z<`LPvbf(F<>*>ksKd-Co5r6;I{m5yF<2k>YjGmn{oqWvtw#?_WuJ>!_hxFI-eX;hw zeM$bs$sH9B-*i;FYdmg!b}^;>|CCEk)wiENTKcy6pNsvmqui&bf0s&L&=F^z>^5I` z{b#j%=33z3T_S(vv_(#5r_e3!{usY|_b$EPQ#7L_FJ#&5!j^wN`p1rOr@MbQJ>gLI z-n6^uMs->2{+;PJKkp1|{}&*C3{=<q_8LvN9blg9mOlIYuWM(dJ+J-`wSU!d{2Rlg z)HT6nsSbhKvs`w{?%TKHoOSJ;U(Hz?`|Hj~*1u(Z42n3>UgHVZ#m_EODw8W;|JiQM zgF7qEM(^wC7oVnYeYcb8$+T-{XIwnFJ9_T%Pjz9c-z=~BTRd6)H^XU<N!`z)bElUD zo|&~Qpzwa&ywFV*nV+x787Rg@?AvoCg|TSng|joR=7)BK&nYqPyK#B`JF$;O2g}cj zDNO%8%OO>Em5_dFw#kXJ-oGz`vZ-Evv#Vg_E=l8Cfrj5+h|m4}v22p($3vf5b;|=C zj^!Qe`IYz9;&qzL!u<!9c7D9{<0-ekiX-FA-IB(?mNi}Z|HZMs*;yEr(t>>@6n4kl z?YTLp+%MklMSaD^)fMd>(>u#d6C2KaDl<+id9rPGVN2G%nV?L0H)y@QyRztuv@Hip ze_wo3k@)k_ycs7}Mwl;V?7Piubj17dbp7Ld{CR(hyh~eicjKyiy*waCb?-j0+{Zlm z>>N-DCRuZJ38Rtb&9f2u)8D#BK5FgWy|`M0>E)?%<7+1qs~x6+Or5;@#NpS6HUHIy z-JL#NGp?ejyns0*Vb9O{Pv76vvCi2lp9(6Ka!xnQd6)OAmg$`K)!NJ>-fHf5X1m30 zJ}>irXRM-VUF1!W;r%A54Kma2RovLQNodudNt=#xpB9(u4><AVaIXJv`=3vj*(xN1 zvPZb4h{=DgBd_=PeNqJp+`JUS_$m6Iz`fEq@we`gpujphdu;<#+PrsJO00(+s~xU^ zlE2$$7L8}msuHeO@`wCBDySbh_iWZQ23B9&KO$F3?_GN9J`<E~!e=Qv6n@sX&6)ht z_vW|7XF#En8~@<Q+};AS*}s;&($}cov!SMP*-OSL#-CMYyxt=p^6zL0C|R`!&ysbB z?0%gWC-i#ms{J!$J|6m%>Ke?fk^kynn85YQ(0{E@I>e{x-;dmPVChbA#hB-zKgB1i z$3^VBaD(G`-hT7?x!YZ;9p+Ue{@k?QlF`C=b5iZ&_r_Q2>yCKq@tdeJwCAmn&1$+C zvg5Bt_@08YEz5s0SeTanU;Om-9@pFbMWEoCrvKsTukQR=DQu!S{3pcqb>hG6sAS2{ z`@beL?Yz0GgWb<Ztxvhl`yZU&8}>SV_3zJOS@x$SLCPZc9hhFWrDWBaXQlU)^3_j* z1S?9!_t|7@{dY%ubHAAR_SdyrVm=+?J}oYHw^cs4`mgGpfAZH}Ony4S98?F+%Qj>1 zTN|Sn_r%5c98c}KH$}&}Pm9N`WRqXU=l1&h=4W$6e?`oE+6Stm#Aoq0IG>+1U(fKX z(BwUD-G74Oj8lJ0d+}y>&2HwiR?<b=*q?v`b&m<dyS2+~rB-{UAL+CUHDd+UnLl}b zIS)+yxp~Ub?yY~Ninhv&g2HvJ?^(_R6MGHB^m8k3^>-cNJ}rLFf_MA0bHQTzY~8ux z^197Rpyt=t(9KK*i{>iXuiV9!d1&UQ#plf;7gi+xbV^r_*>!zhkk&fIy)V;zo_$;F z1X5mlU~_3fTGsxnw}Nwdjdpd<wY%$b6cmc*uN|D5{+4s;C8<lZbH2TJ>>H#53WsxI zCZ-LOp7~u8)0a2B{pKS3oCOJcHq<<PW)f3*f1aP#8pX2j_s?FF3jnvxqE63}anRg; zTXE8!ij6U8Ge0fO044GJRy!`<{1=pJdgQ~sdpB?OcY%W4tgca5`|Zjv?4egD+_TxN z<y`IX5Y(oznt7Rpk!!YXp1-Q-)eZM-j9&-H8^?mBvT`%p7+Uw{`Y)Msw0q~>S8cvI z_F8hFn%>qabGwy!dq~jXs>x?IdFHEY%IQDxUj4Oq^=^%&n`_Ho|6jSNttBAg_OCUX zUPri>yRW_GeO73}gma&F*{`10_I25e!r8wzoIG`e`}Fi{Hy17A3^?HQ{8QJdOqcww z$mRUA*ZAz&P?I^oCTku8YtHuN0k^&eE(WzU3WcY3fs(*AV_y-4?Z@XzE=iKQI5$r5 z!gJpst+<GNA8s*-T(7ircy%woY`0{4ZzjJ6C>dwux+K28by@xE#j5W7nSO=K`fXOl z?3tjS%Wo3d5c94qt)DA1q&$yR$yC|<7}&Lj%iT2+wtfD0^vd&BzU9V!9@+L<()v2_ zFL)gk=jJt7i0S9v|GKe#O0W1d{oL=MLUfw-U51nS>@QxNT~knV`MF$(6(~NZx6P4L zT>frl;IBtVYs?>a9Qn5R5-45tURHi`#n$xK-mHv}@~BqTmv2>`K5l*LecRbrN@4Q3 z?%t^VD_Y!Y-<?}^;Kk<e+Vc8Oyl;Qpvy6Ab!LJ{eyEV=edU5!Bp@9AzxvjOA_AnaV zcynfEedu467w1-fcyT$tP*7hd{?-dyr?mcE!ER3{D@@5dCiv^m^cYZhZwroF-PZGL z_xIMId$yM@&J9$Q%Cj#L0_iBbxs&ha7ri^HDuhb>=N>Y-BKJTgE@EHFo@-ASk5yfq ztEXw5P{wlQtVNPR{2j1a#c{Vgc=AdwKlay}t8(|H$g0L~%H|)P_Laz-%VJ_&nYOQ7 zy_-wj^ZD9d#@F|2&j;=)sJiko(3r#H>q6_$OY^Vu?w_{rRrQvgpjegNBPJ$X68F>U z;or8q^EqyY{+_tHLNVUz+%%KU1{d?Hy<J+fT;@(c#P)8}-xHA_lQ!Bf&SX)U@$RkA z)K8bL&wJ<3;un83anFXDmkG~fdoJFL-G0?7?4-)8J+oD6ei^-c)LQd$ktM^*D)G2u z^Q4XziCy?@#P_)M^5VYF(X+e`Oqjj=uBOp4=>=<lD+|7;lbjBUsK*o5zMkOWzh_C_ z>ibvku2f{Z`%QT|$b-3;Yg$yQ3}<zzy1q|Oy3iT8{NtgQf!9|p6Ta{~HNR}h-k@FT z5Au!)x~~Jpt9U-&fsS{x8E=JXX*#`2lPP>+0SZ{z`xmA#rR@7`_i~$I?<Lv2@?A&w zJqG2<t;a8yN*HXtJzKIqY~d1)J+li>biS@ojIY{evbteiobux(!HYG-^xdm(|1w** ze(#o-?=yCV&kA$6ZS31!*n3I#*G2}}H+e6uzZ8S=Yn5C^665uEFE_nAuQkbJVX5&v z**7__7ONM7a_#w-zP`F9_nh8m-tAoO)~FNb_pSU(rFxOP{v5flHS;e&aXNhVUAC9c zj_j1(vp4>q<dr4|8g)1?KJT9E?JKTXJ@pIL`7RHbrV<}?@{IGI3Hpb+-(I{{8(G_a zN_lSGx-wz?l_}4Z<4%ZIuH<ZEt6q2V!mNsei=O2joBVe!|1Xtu6`kUG`%ftQ8k$^d z?lzvc(fUg1OZL^JTfRru@8z!pTXj>`*U03`-0s<Klizu6f2qE@V8d_E`jzo@k6LRc zCf~EUo5B6c<W#}KqxI&GZyr4NRPMIuM-lxwawqM!FPDDv>!|L_&hJZZf0?{)ZcTZ; zr>b%M$3vf7_g%VsBjR$r38&iq$^X8Ff3>kH`f~QU>eMqeN4b9%JrwTWZ!&e;^6cQi zp2hQZo<7JnogQNJSxo=Q>DKMDax!L^&ti}SImZ37we^pnuc}ke{5i@!Jzj6mwG!vW zdoF$09%a8u>DbBJXDgyWhT4D{rQCa}b~WmKOUT&zFP7DCT3uOFvNXt43H>Lhm$uI; z%IIki=XKF)-)Q$TU0611_mW97&sRMB^5W1>TVE@aBS(+j&6RxTsa|S4PkP^yNi(lk zB>pUVIOTY`^wUp?cf(%Chwwap+0MKZETtH)w{dsKWSw~#H*SY;J<e?{^;9+9|MAev zi%S=~`r5kWf7~RhaNG7}MJ1?Goql5avKRi-J*&&z&lT^Ppda2>u`^2f%-5x-<wMzg zpIXPAn6ACW-0a|;RO#f^rE8Qjbl!h-+83i3|LFRBy_<TkkDaOCQ&9Px>!;A}#*)l$ zsdxLhKy|I?C)GUWmz!2IWo+OA<v!<qM{*Qm|1EiWKPB`C_s>i1HJ#TTcKum&@_xot zDF3R%u7b$zi)U3l{FFD}dEWZ&OTF)<9<1}}?YX!bG;HuiF+ORF#fGw*myhJ{=mHt) zUhh!z%bM}l|E7#v=CPq4o%Vf6u5Y_>NAk{@pvn6_YITe2?f+uEcXei`#+SG6FCF|` z5)=z6Bg)VHn<4n}_Rmd=ALd@FUDYlADfPflVP9XC_a75>ne6r5<=^_zX&+D3!jqi` zY_B(XJ-)r<cZj6^lhX^#XU*fdwX5xOlbZD{tzL1x_k6z&{7!5({~Fg^*?4+a?J7{U z&}?@;Ym!oc@nL-prPyDg()v$MPxxEu8_bgVZZ_K|ro9ZzT7BZ5Qcno#YjECpw6N`? z)3oiL=AKtUc3M7V?K>DHS2JVXUWuzJ?ICjdPfiQSHE>?N@K~=zs&|!L+==Ol`8yg# z7Cn@{v{u-+AZC>!NN9e#NwQ$i#Ar9050e)3RXqGSJ+b=D1%Vl@>!o&S-<c#A>b++} zjbzyoK3>P2rW<y9i*H{dd__qA$!QL~4{c9A&TM<jl`rcV<iBTv{^EN@jphQu*;1SA za_VNTSXQAJ@Amc+SEIt2+G`D8e~SBN^Q_X2J25@b-FwyngE!9(a5GlbU0ZT&!mUTG zHIk*<7HRTqmgBcydAn?tW^dxxqukq<3+MP`iydCFa=X+D##t960zu7h&kg0y!jf#d zZ?a~veK_E~O6qZIjc3s(hhWKPcVugBcTCWG`Km|!lj=pO@)fyJR~dL8749<3>II2R zXFZ!PVKm<+(sO#@E3nANTHnkWh51`}7c`ehu6|ab7(Z!kG5g6WE3Y4}-u>kQmqFa! zk52nkexH(6aTfb#qT}o_oinRn{FCZUP20XS8^1ltE{iXwd_B(nbJC;7rDyZ5WTiPX z8}*dTJmIisg1#o-bkl=@i>=wE`VyC%P7!<5TI0F-oZd{+*-_s6mU&MuQBwm8m3v>7 z*%~2r_j8cPbe)_d+&?Eh`y+b(!?m<muD33=miMJ3tHhm{9#Z{=DR}bHD@(awPMSEi zLNPvQ?%ou};O3R$oYuQJZo8+ZsKuR_Ub0&!L2J83n%$>;Th_b*nf30EDfbL7-@P)m z;s;bOsTw<fblTUmu{>H>UNpihlj+5yGaA<3AhFM7Va4+E&aPX2&mimZsyx1Bpm=%y zVdFCUJyjFF&BzmfIjMbZg<|}%TWRw(-#>GY_r2f0{AH0LsECV5Umf%4Yu25+FZeF0 z%4dU&`~G(w7o*&rd)E{FHm>*V>N#_i`=`-C_j40$X8vE`Jf}_W<(@ZSp_ATar@kb- zI@-xsAazOAy!oTkKA%r>%M~rl%^zO9*nH!sk$pEv?90z(tC;-mNYw9N(OjZ=AZ5=4 zec`$JXI2^o-1=Jnc;4dIim_cAK-n#2`T89!kB@vg(yf=f=llwR#UGvar4(#g#N^1S zoh*Mz^wLs^)gYmb$Ab-2b(iN$UTrVYJdv|!g8s}m7d&GR&CQvd;~p$jc@vaIX7|4_ z4ZUz_8Q(*eCEkf`k6Rl~zF^kx(S302*pu6?vd3rjXdEcnGeQ66ocs$K6D}Y6o%8V0 zug%Mpx;Dt_Kk;^ZF1;q9Xvash<Q-e;F1ffU9(&wcbF!=9q|WQiKxzKVQ<H7uPE0>@ z&R%a-ox!o*vu7S2;(fX43@AYz7Tdm3eaF_N&Qn>p_ng`UYSGDAe-Cx{D9}G2^UL)! z|4~)}eHI_R>i(Ms#uu+FE?h4zd2rrcJ{Cd!C*FGP`W5LXJ6@mP{6#D_F+5iMP>1*@ z)%lal@3=`7JkD)f_oB`|>(Rm~4v$)EPG-NJr^S8!U0&+`$Sa?#eXXYmd+nK^zq7Xb zm}SuIH<x3k$L!jX`ozQFqtm`8<)6My%UZKBZ{Nwvuq%$cb_n_HnV|3b#wP2-ys}{a z?lY2A5_dT@;y7kF_1!lsx&8jA`Ee_joqqx+^YXEX>Ob)|jGu4zPV3B>$+5LR=j>SV zIw<0!(>{@sT^rZz%5J&+{`{AtpC4`N4sJZk{WIvs_pfawHhSxPYm}p;=3Ob(*;1jH z;PvB^(y!^tvGxC4<F_%~`}8WR;-k~PDFy$2o-7qjYFW3wMz1R9%E52k=U655pLlCN zpD*WLxv>0M;mVwaj<?zc9=A4VzI=0e@(H1|XD7o}=45XDw`3*j^g})3pO&uqeE$5i z&{+p(*Z;E2_rJ(dw)czDg$l)ZnIFHjn&vew4QG`vkUa1=!``V^{L|6S!{y)8LzXkn z+WGxmK>QMsTMRXvW^o)6?&r3}v;CZReChPts`}ew7VsXJ-SD`zrtn!svg!))jk;@c zWL_?w?k?S6uXvpM=c7yiX0toml$d{iaMrvwMSaJcM}ZeUI_<OA_W#|)mmM>!zvRWs zUlrVT<*U}43dMvw);B7$K1H3mbh)=?c47L#=3RBIa{5oY`IlQ~f9H+unYn-ew%~-z zJ3H&H$u#L7JkHJd`1HkVtAB5uuXXlr{m!TFwB9YS&tN(@o8wVy&BqrN)o(wZjk<T* ztn~B8Tie#BWLjT+)97w^g!|{Cn?J9wozB0Sd*;g7{PB6Ux_{^VudsO&)T;5QwPEFv zf8Ty>u8z|`sdJ}x+rGCy?gbdFdl{xQsX{S+Rq=+u@2);hU2eE}!=E2lcjtaLZ@aWX zJJvO+Q=Dm8QTy-P@5ATYN9+sy@az4Z-ly#6!|&(6w|*&os`=ZCRY!#NpLo~y@t2j^ z?TL=9-M6VIzp^rOVeW$9qGg}8y-%P19u_ul{kna>H*78rc%iE3Hz#A?f&CqiT5BBH z>@&A5U@|<)&Dh+zV_Edl9gkXT4o1{pvvD+4>K12WOWshjGNR<8(>?{(yBDW+>&J0O zs3av%e|1zs{|UES!QmBrfycNRn;rKkua%n!V%gbe1uaOrc#Qie(?eV3t)1p^91<lL z6GP_Dc-&gUc=qDfE~_|>8OI(w?uv2+wTl;jRERyB)GyAo>|n&ME4u$G6yv3`{2%xK zGEs=*n4z}F{8p3O5pKrICT~2_ot+=GHe^n@pM4>4^D$6EMk1!faIxh_rvoO3_h)TM zbeR08wV_jf?Zss#+Ho8+P841|I&Ile?w>-2db=Vn@2F5rNIL2&UM(e|&*Iaw<3&=S z^5fQ;PCoHipRBY!0tSVOF+EvXdjt$V{%Cd+d1hiB$1%e~K(EczGLB=$heG{ZThfkm zGYXp>I=W*Sh_SA=SK*9O9LEd;K|Mx=I4h1B7yfuEvtRC*F2|&%@}@+R<Iz(lMq#c) zsuD*|i!!OP?AfiMaKzi5>6lfXD|>5&q|1Q_xBS3_j_HCbJ-+`Jesr|xn9jn|W7{qz z-O^Iw>2l!4A>)!nrMMsggR%=EvRaQ+MH!P1t!!gvREj&MnE0w}%|wR@9n(K@%&_{% z5&NKHx+lksSsT9B|LB;`<1ypa-@xN?ipp_DiV0drMW=fR=toX82>t2lE^|;hZj*9? z)`3H+YDc{FRC?m=Us)*g9r5;K=`pu|EubuQ#Jf(Vhu`L>yyBy!98AXy*F8JdS)tj{ zQrMQ$DfTf)hVwB)wC<6f3eDCQ&DNYwnU6tYoWTO`g*)XxK4RdUEPeA5$B}Mn6(7Dg zvu}$W={8pJQG4_7lERU0Z<R9@CL*RhA0J5xPHwvGa@KiIg~K79-{rEBCfpw%aS9f9 zE-#YquK3vAvXFb%!w&KNvt$g_<x2%FgdFLv_wA9;+qR&$Vx`+;r8e~<#UtLOQUZp{ zqkpY)kp397vBLP-kLG<!3P-$oA9YLY>X^_{vC>mVu=ta8tzrVp$Dq{<oZD2n)fD1h ziN_t2`Ru~INg-|xhjL2Y!x)a6g8JKL@XkywV%;gIuXfXO=KmjO{-%kz?wJu5e`d~` zoL9ySu7diGE7a2Je*S%5@k)$OQ2$_|r0H_|zyG%1VQtbs;{D>&(zAVa;t%ew-~X?E Y=01-talh}+2c1Xb>FVdQ&MBb@0M%?W`2YX_ literal 0 HcmV?d00001 diff --git a/src/index.html b/src/index.html index 481ede9..2bd0c85 100644 --- a/src/index.html +++ b/src/index.html @@ -1,26 +1,6 @@ <!DOCTYPE html> <html lang="en"> - <head> - <title>Logic gate simulator</title> - - <link - rel="stylesheet" - href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" - /> - <link - rel="stylesheet" - href="https://fonts.googleapis.com/icon?family=Material+Icons" - /> - <meta - name="viewport" - content="minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no" - /> - - <link - href="https://fonts.googleapis.com/css?family=Righteous&display=swap" - rel="stylesheet" - /> - </head> + <head> </head> <body ondragstart="return false;" diff --git a/src/modules/core/components/App.tsx b/src/modules/core/components/App.tsx index 31707f6..a9588d0 100644 --- a/src/modules/core/components/App.tsx +++ b/src/modules/core/components/App.tsx @@ -13,10 +13,14 @@ import Sidebar from './Sidebar' import CreateSimulation from '../../create-simulation/components/CreateSimulation' import Input from '../../input/components/Input' import LogicGateModal from '../../logic-gates/components/LogicGateModal' +import Head from './Head' const App = () => { return ( <> + <Head /> + <CssBaseline /> + <Theme theme={muiTheme}> <CssBaseline /> <Canvas /> @@ -25,7 +29,7 @@ const App = () => { <Input /> <LogicGateModal /> </Theme> - <CssBaseline /> + <ToastContainer position="top-left" autoClose={5000} diff --git a/src/modules/core/components/Head.tsx b/src/modules/core/components/Head.tsx new file mode 100644 index 0000000..d9528bd --- /dev/null +++ b/src/modules/core/components/Head.tsx @@ -0,0 +1,32 @@ +import Helmet from 'react-helmet' +import React from 'react' + +const Head = () => { + return ( + <Helmet> + <title>Logic gate simulator</title> + + <link + rel="stylesheet" + href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" + /> + <link + rel="stylesheet" + href="https://fonts.googleapis.com/icon?family=Material+Icons" + /> + <meta + name="viewport" + content="minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no" + /> + + <link + href="https://fonts.googleapis.com/css?family=Righteous&display=swap" + rel="stylesheet" + /> + + <link rel="icon" href={require('../../../assets/favicon.ico')} /> + </Helmet> + ) +} + +export default Head diff --git a/src/modules/simulationRenderer/helpers/scaleCanvas.ts b/src/modules/simulationRenderer/helpers/scaleCanvas.ts index b1976bd..2757710 100644 --- a/src/modules/simulationRenderer/helpers/scaleCanvas.ts +++ b/src/modules/simulationRenderer/helpers/scaleCanvas.ts @@ -14,7 +14,7 @@ export const updateMouse = (e: MouseEventInfo) => { } export const handleScroll = (e: WheelEvent, camera: Camera) => { - const sign = e.deltaY / Math.abs(e.deltaY) + const sign = -e.deltaY / Math.abs(e.deltaY) const zoom = scrollStep ** sign const mouseFraction = Screen.scale.map( diff --git a/src/modules/splash/classes/Splash.scss b/src/modules/splash/classes/Splash.scss index b5277e9..3cc74c9 100644 --- a/src/modules/splash/classes/Splash.scss +++ b/src/modules/splash/classes/Splash.scss @@ -66,5 +66,5 @@ } .mail { - color: $primary * 2; + color: #aaaaff; } diff --git a/webpack.config.js b/webpack.config.js index 033eb1a..c11cab2 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -18,7 +18,7 @@ const babelRule = { } const fileRule = { - test: /\.(png|svg|jpg|gif)$/, + test: /\.(png|svg|jpg|gif|ico)$/, use: ['file-loader'] } @@ -74,8 +74,7 @@ const baseConfig = { '.jpg', '.gif' ] - }, - plugins: [] + } } const devConfig = { @@ -84,6 +83,8 @@ const devConfig = { new HtmlWebpackPlugin({ template: htmlTemplateFile, chunksSortMode: 'dependency' + // favicon: faviconPath, + // inject: true }) ], devtool: 'inline-source-map', @@ -118,6 +119,7 @@ const prodConfig = { minifyURLs: true }, inject: true + // favicon: faviconPath }), new HtmlWebpackInlineSourcePlugin() ],