From e88f8d50ff85932ca35a6d050296aeb1206f32e2 Mon Sep 17 00:00:00 2001 From: teddy Date: Tue, 11 Jun 2024 08:02:41 +0100 Subject: [PATCH] Project OOP refactorisation. --- .../argument_validation.cpython-38.pyc | Bin 7768 -> 12790 bytes .../array_keyboard_3d.cpython-38.pyc | Bin 0 -> 3759 bytes .../character_braille.cpython-38.pyc | Bin 0 -> 2406 bytes ...our_theme_braille_character.cpython-38.pyc | Bin 0 -> 5424 bytes .../__pycache__/export_3d.cpython-38.pyc | Bin 3111 -> 3428 bytes .../__pycache__/keyboard_3d.cpython-38.pyc | Bin 0 -> 14873 bytes model_gen/__pycache__/main.cpython-38.pyc | Bin 0 -> 564 bytes .../openscad_objects.cpython-38.pyc | Bin 4183 -> 6545 bytes .../product_braille.cpython-38.pyc | Bin 0 -> 6151 bytes .../system_commands.cpython-38.pyc | Bin 1093 -> 1089 bytes .../translate_braille_2_scad.cpython-38.pyc | Bin 10714 -> 15419 bytes .../translate_msg_2_braille.cpython-38.pyc | Bin 16588 -> 15861 bytes .../translation_braille.cpython-38.pyc | Bin 0 -> 9713 bytes .../__pycache__/utils_system.cpython-38.pyc | Bin 0 -> 1180 bytes model_gen/argument_validation.py | 928 ------------------ model_gen/array_keyboard_3d.py | 98 ++ model_gen/character_braille.py | 78 ++ model_gen/colour_theme_braille_character.py | 210 ++++ model_gen/controller_braille.py | 7 + model_gen/export_3d.py | 152 --- model_gen/keyboard_3d.py | 549 +++++++++++ model_gen/main.py | 94 +- model_gen/model_braille.py | 7 + model_gen/openscad_objects.py | 115 ++- model_gen/product_braille.py | 278 ++++++ model_gen/translate_braille_2_scad.py | 664 ------------- model_gen/translate_msg_2_braille.py | 801 --------------- model_gen/translation_braille.py | 433 ++++++++ .../{system_commands.py => utils_system.py} | 34 +- 29 files changed, 1779 insertions(+), 2669 deletions(-) create mode 100644 model_gen/__pycache__/array_keyboard_3d.cpython-38.pyc create mode 100644 model_gen/__pycache__/character_braille.cpython-38.pyc create mode 100644 model_gen/__pycache__/colour_theme_braille_character.cpython-38.pyc create mode 100644 model_gen/__pycache__/keyboard_3d.cpython-38.pyc create mode 100644 model_gen/__pycache__/main.cpython-38.pyc create mode 100644 model_gen/__pycache__/product_braille.cpython-38.pyc create mode 100644 model_gen/__pycache__/translation_braille.cpython-38.pyc create mode 100644 model_gen/__pycache__/utils_system.cpython-38.pyc delete mode 100644 model_gen/argument_validation.py create mode 100644 model_gen/array_keyboard_3d.py create mode 100644 model_gen/character_braille.py create mode 100644 model_gen/colour_theme_braille_character.py create mode 100644 model_gen/controller_braille.py delete mode 100644 model_gen/export_3d.py create mode 100644 model_gen/keyboard_3d.py create mode 100644 model_gen/model_braille.py create mode 100644 model_gen/product_braille.py delete mode 100644 model_gen/translate_braille_2_scad.py delete mode 100644 model_gen/translate_msg_2_braille.py create mode 100644 model_gen/translation_braille.py rename model_gen/{system_commands.py => utils_system.py} (83%) diff --git a/model_gen/__pycache__/argument_validation.cpython-38.pyc b/model_gen/__pycache__/argument_validation.cpython-38.pyc index 258fc504c4d4d57370311f6f49467aa0265c4aeb..2c5eea290f4190a9fcce79d79324162296d062e3 100644 GIT binary patch literal 12790 zcmeHNU2GiJb)K1>o!y=NA-SS{typVCmPAFS6*+MlRaULoqMbsa1(Ql8mI<@wT~UO{ zC39z~TEwt0L?H-_wjhEa4~>*2K~dCxNP#{CK~NN^&;~&siXt%7VjqgY4T35N`cxPJ zVIcj!b7y8}S4+uK>X)Jv_Ug|4Irq+;bH4L;&zH--g};B;S6Bc17nb!Od`SQ0@$fu; z!5tLJnzEFwoCSN)nR0APji{{hZrD>9bwuS<9yM2eO!=yaT2>uxI1O*NWlB}P>8Oet zxRIU8si)MS8p4>o8dX)b4Yh)LS`Dl1sQK!c+M#x$R#YEXyVP#fO6s`UqaH)8te#PO z)kjdPsK?d58`ji-`h=>fC(tseKG_&jAH8X-1L{evQ&sy_Va}3YMrD+HDc{(J5eKo8 zL+UU_46D+FHS+B0ANnuoM!nTgwWVfl^72aU^s=rU|5WYc$4@--%!yBax_127@n?Mh z`T9!h@{&GLJEQ)nu2t=G^GYo=T1(BRCKl&gmwo@Vo?BULG+VXL*B9nhy*0no^zY)} ztP#7Ne`T4^^@Xu^z8;O6&9O83E8zbUelOq`ylvyS?X_IX3SH%dx%EtNuw{oi)LoTX zch~YQC(N(g*KLf*DmTo9?z$UH%NQ3e89Zm#@}a9ITN#eDtuQ}fC9~YnQd!QzSnp4> z!A+T&MXR)}douUyVK&(4Hy`8jJFPIc)50Fz&{hTP%~w9@t>=PY3bg{-)70JtwSVtN z4HPn}n5M8{2gij*5j`my8@4_YX3=|a3p$=E_0U-rI;GI-p`(RPvmYH*4y|umsuE_T z^rW;=4z#i@FLc)Jbv_M-&Nr=FWTBz)cDbSTlAc)%=4OJHZVv=2%geeE1T)eeY*tRr zF4TjdcIdUGrG-PM+PjhgvrEljX`wN*w9;B$X$5U>u>m$yBaY636*PHdvmDO`ZA`XD z+uqfgW__`7_c!?CL+jddqwQav0dGltHUHV>RkC4i)2^)+Mr)H8PW`8=S6Cm( zweuJ=!!2nS>$H98I>T3KXP5PSv(?UV1Yaq`!sR+61x;YkMNYA=>M|da&FTu9-NkD& zm)eEoRNk`mZnSSUUN|v*K4|D*xJ8!#A-l^JE)T1Z6(64j3*6@yvwYx@!a&BT$P*ye9oF1j)lZif~3xK|n-=RkkC-%3A|V zuN7nkVM$rx4V7IhGzVK*vZ=~nvGfL8!a{IcC>KJ9l(8a3JfnXYy21DR(GMNv$0DAr zgIz}Z{Lf?^w8%QYHtRq*kI72K5bxYs38H&AbkTdD-)hMU*?0wvKPzig@h)iP8fg1s zvdTAPl~S1PS>?}Ul{fpYVy}5}URG)qLXv~MT0L~`2%VqyrIUlum&Y|(Ko7D=xPMF& z$S3cD2P`8ccLn9gtgh`K{(i(hy!{`PN&D~hyp~2<2(qG z3*ktM2-}lqj5Fs#jW)|yi2sNcd=^Rhdq>n<9+Cn+7PXaM&)62~9+X-h-`x#Pv}~#^ zJbO@C*>&&&Y!7b&s%p(|W$=9r_ZJ{vlaLC(i~AK@LO=ML&>;60pgxOXR=*i~!B-%A z#h4zT9rf#W#Q9KgYx!gi!}(m}2gw>S=l?ib<2_k}d>^mzUs!|6@SZgix;f!Q&;@T- zg);datr5Q;Fti~z7lb<0TTC4@&V?R&&h}lQj5Fow81ykK+!Pv6Y$+OF7aAK|(MWb` zFv`&RJK5(Qja!d&R}LH!x;f=t6ZzW0Jl8 z5a(hrpdfgXThEb4Fz0WvV<-4t-yIVLhR5|bu(L>g2L%Kf#wPV+>=Fs?MuCn(hl+(l z&q3MEK>9W11yA+Y`Lw$2bMwvl#g)YxRBsIpbFIs@%|flY)T+Tq7)5{m_1^xGoRK^t ziouo+-t1)?L1(0_Kf*dSxY=KgwI^8gV2!|xXn5*V1332CUa;XA{0)A=U!kzdfD@+# zkQm1Q9UyU`gCmXG12J7aT@X`=wQvMI-OmP$unI<{dNN#}FqP*H0CB?tdLI6dbUFcw zdmbNg0G~5Be)+HddKXyncoMLxMqnjCMe92TD%jToRL@301=S9)ih+tM8wy5wfG{{o zWG`6A<5cBnEkMNz&|r)W`#C*Ei@K+|Q0!`dQ|4xr1u%M>0uGxuui&0VwBMF~SNeZ~ zei!y^y8kEaR~5j+y-e?i1+j5O0IxU@)?wPo8ul~ld5D28aLKpIu@1PDonXvWtb{#D z4F(28j%}PhEwe9hwi*y21uQ@e3%9a6u@c}sqSvoCwZd&EX#+F2h3@x+?%P7w2!G*L zriWrzJ7}3bI=TW{1{NwpYg1^wC$y^3?s{o;wOaTX6IbhUc6k&@r0TD+4@9cqRzVNIwT!ePqEvLJV7?oz=rJM%tq7M^@ZJ)wXv3iQ z6eBZqNU0S~y8}I$ZokC#NLzX^%RLBO7TPjB=1rMv0o7x-6PhRZOXxpoQAG%@tb$fL z17hxRMvr>|DycF9nha$!h{^CJ1DA6p zI1LC}GGNJ2<(vmS>p@q-fnT>@w7#$h?nplLcVnm2ulgt`KRyB1_RB|QTp=~CkQz6M zarR9V2=-i@ zaxR{k%3M4%(RMCQOu4AM%*WHLo_@LQPQH2`{V1ohC?;Q?awpHfdZukpw(apLXZ)3R zcI@=o2{epNxnrk4dzR(diOI41sU<3-c2?J$a}7-scH|z#)OiyT$HXk3_pmE6A6V! zR#c@cPKnG@Mv(K;%EAI8ZT@^;N_c=|CV45QBPrm408l z2O>X>iNE6aWGDpR(`NjS-be=?X>(|f+uBlS8*s}%q{&a9;1|lmA|SZMCO_KI%D{PS z5ioF`9-|`wL@>Rp-GCdukn!dz+=%A^(2VI%2%}rE27f<2M&A~CY!mNY=51o0%Xu{1 zqj|2(OUCF;nHPg(nWF%Lh&Ha40A=*U{XejpqqfC=Vm_Y~^BG_dZy#WJ(ZHpQr>KNJIJ!FCE*Lnx*LZ(`?S2A$W3;~5?nhy}w`xMGk3}w~dnfF^Svr~+>(A9T zpH9u~YqIy79$E8<;rBP^J0kSE*l9b17rYlW?`zJB89xP^9>K^~FIJ0f(Lw}sGg-ko?J#?oeqV3>j}K#Va0#HI0e zDFNbpId`nDB2O6hftbsaf2+`ox%cOl9`rrU??m?CtRD6dKQCs8_|!rG2a7>TK&Ocm0wDKhD8sPoI%@n$RrF6 zFi-cvbgAaNS$yE+4>T;A##~AA-Y{FCC6&V)BS@+NLSVRA@Ocq$-C-W^^5(Mej4kEwfd9De?6%fydc{cj+B@k2K=atmc4@JG1=kg{n#Xk(%^ln&THjSD z+D_|o+X-52r>WYGR(Gkg@46^PTmgCgJV#{^;gm=RZaIvx!3$O{U7CNr_iSE5-#_te z7;mt=3extlADq38W>44s87`E>>VJ+0*axZmGm=!~y%^jkNum-=#PjwH?#hUHX&66) zNI_0qD|4I0Fn&g2_2$M4jeEaqOzc{Da*u^>nVD-`E5`PDFQuHce^(fk8Xo5j4bK}r zWOJM~z7f*(p$%658Sd}=8*a_KgKyWl0Dw#at_BS`$7!>*j*_v5pH^O-swMC;yHyC8qN zBl%mHM~b#13m;VebPXIUY1hsLF_JoTYPH66kX+zmLzMj;t;HE%+~g`AjdQ|y*w=q_ zlt{vWt>`5qG<`XN^S14;mSok&LW36?CrA9gNh4bAy#Z^8Focax_;&o*1|6kc!C! z6X_ZZ2h}hrJNj{)8o@AwJ0(7zabE}!;c$-H9`c&#j;^c~-nF~^y1ijHUz43$qymr~ zBvftKUpTuq6rG|I{CV{Dr~%BZa0tl)T&3l?o5(DT7l)Zf| zejfv0&3BVEe)V9=;F)_V{=A3cMzq&VaH>B=P`Te8GgQNdKcYR}hfddyoZuMVF%w+v zp1mR{t4z8Ofieo|jx`{!BE0$v^TYlzWa^8YQx)9AJ^99R>+;MzF2_p+*psrm1WRRaQ>61G3)xaX zR24uKGi*y#<;r7#uHXhL);8mX;6`9iz?`TW|Be7vqvX7ku2+GsdrS`uw{&WrSj#Z{ z3F&3u@!lFJk*4pMv&f8%Y3#}xNh(>nBPB)LmmMGPQ%zQHE_!ZlmDs`yUv zqN5J?+MX(*T~J4Q?Xs$%?W&sc)z~}s#iDvZRn<6Zo_a7Wg=PHNYU-M+rqv8)R@5%F z`yK0|uO^heWXa_$df}MNVUcv zwMq4`thLo$*9z)x6=21bdZf3%d(^#XPpe1OL3KZ7&nWwxRXf)Ck^ig?8*!+Db}Kl) zyb(OTu7hLW4IVvq{ISQ5KmKHJ?2%)S`TnWKM!ekC$Ajn8Pa9eVFE^E14dZs}p>u1^ zc-i-#)=L{}VJi+UG*+9c5jWc{|IA#?PH&Gk*4K3yMfHVtD{8NX_4Y=*z7aHfOOmz%BT+Qyn$ zeLUE{GguN4&_TT1Xa#GH&B5VXF)iac^-JycYFb>^ctBc+Vx79&NLu0;`aUkErL`;a z7HRQveXZG&TVqq(IMUQxyTa)oTY3u3?eN*-^RGssj^;zk)BF!x;c4Bx9L}F^FNhdL z^JjH?3CsYYrTMd0AbhRh+=6bd$I<*Vy3t%+4d>U|DqO8Eg{}EUPx|V@Op(5$>sK_D z{Z2~McTiXr-#%cwb{T(JS(W;3w5PI~GcfK5gH~5;Y};es0D@4 z&4skk)3VD@H!xF=bJ7G0YM7p6LFF>VG-_DQnN&}~)l=xpv|vJXz_qh`6}3$AJ%{?? zLK9}}veZ2X^BfPodM{|)S|eyTzr9BEAodxf8G!0S^vnQczDAt@s5{YXI|6t?4*~f5 zfO?pO{}XigrF^b4nW69EYP$ja-9C`XhIEV|u%_YDw06MO@x_hRRl=44?1&7c6ZxnR z()3SmI%F<3!x$Zbx~d$rkJ3OLkNXx-cL!Dv9W1v=nH1USpz>cI?CI=a1@cZ09PJzC zXnP>`Ms~b$(ZCFBJ%Diw0J!2*2`kc_cdK=<9{~~o8Uy>SZoUX zgCF3C3%_L(038E*F$X?~M;`=U5xo~LgKY9QHxi$N+F*;`6qKb$?Q>B3>>H?YMbCEv z<=hm&1f0#zjAzU?%u8v-xoYcUFiGAAmh{nB%+gqhr&YOW-+fbaml&3p^10@{ax2QctwtnvW)tE^h}`*=#UmfpEOhJ#=r4{N_m&-#vR0t>#Jc4&R}Dc z6){c=REz9K3&%@T$)feR#p@w7LclB{#^q8FJc?$HFt$9aSpr2R8AqT&h z6zLU3I&q^G4y}|FLC4q!&J@3=>mkG_!zKSHK~3&%^dV+f7+@$r@$zS54dys>=|S;x z%o!7<8=YgT>Iy_1qVK8k6{v$g1_6Rnp0-|pv0E};TvFO+R0+F8nBYWTB~%;+Iumg@ zDXGc57{?B#L`|k;@1oeSZrI72UrG2dGbCsfo4L+JhKsAsh;hIjndGrOYKHE?lFr>j zGjL!_@iIJ^UJP&|=#0$bX1!}E2abGUkF{d!L(1*itpiLmD5MsYyHt!hTHa%+%9gXw>e>c@6ML^g z8N+Hi1UD3l)QOizT=7P+04RJa~5*PCg@RG{bHF4@CWh6R|^GKPfID69J_! zQ?d71YHYBT_`Oyc%I@aRttLKHecY_T4vYoo4oW?07ZT(ea%#O+kJ^QV)Lt2(Hepr_ zQS<3JU~fuIf;QY_$kbTxUIpy<0#ftcaai|pj7`LqWCDDh+KaqJc3*)t*B>db5idRO{P(+UbWv$di-(p(E<3CeaRM}W4UjTxLK8WVJ8f|Gg1MY?7KeGeYfna-&6(RY_P1d^N??(Cs; z-dQW07b2!O1afn=u^sVM(l-c$4MY&e^br;{6zL=*3$y1sUriGsYcmFEpX9XTECh2U z8vQ<-5|Tc}T8_T@K{S!H6tsvoE)f@on!t@&PN~G<+PXaJ;<%)8>X^+(Uo6WA*Y#>x zGUDa@02KBUwH8saCXKsJ@5aQn^k@1o&QZ_43!{TIGnb)K6%g-O&cFPEhj~7t<7^&% zB(v6cG@rRZu+M%4RCtMZa~_qLa4)WV*8!N=0G>m!1L$Ys(0C*eW0_^Vf^62=#ExFV zOgQp`GYMn}hx(?Ti8+}1?`5)htIT1*iTw;?Zh7anb1y+=h^fv;&({hAISGb?=&0g0 zaJnPs;9>N2o`Zxi!nI{oUQ!)(vy$n{%*|*O1UtrDfom1_?qSD!}TO+3pbjXFpdgV_=~7D1(I(_!YAj2)42 zl*cF0_bc)^Kqd1?30-{^DkC|^Ob!Htvll1`*^f?N&gh?@0Y*C`$|PbT%GCdUVLU1_ z`iU$bL&kx1_~Igg%3|V}w6p|B9>bHKB4+F>4Y99tUj|C}BGfQnF0xep@$5rJXM8pY zH`l`jTF?^#1ahZ54&M@r5-hfLz-}F^;hR}wDGVrd3;aNXPijXy{<#eVL&2qnI@&2`bhhoFQ#l$i z5e5!+{G@gfUUHHxi0TkfKkpNds*VP9RN0OE^L?k^K(5qu{b+&dX2XlFP&l?S& z!0&H=|E~K@i;#cd%k0mFmrW=_f?y;d%wT3}WM*JyR$ygzU}sL?WNzRZ*k`4c%nLlN z+i5lMq0LEaSv{y{ji901-E=N%2F+|fnAh)>bRla6ErWbXn8&Jb2&=};*H*B|>>bka zj~@72JPu{d+C|>pJs5Do!eRRfl>48x?|pXfbAK}&$b*7^(SF3f4>@Z;Nf=9GS>&JY zWQjcR&tdbV zwO-M>rFBp1Ht1Ct>*zLLx4BxcX}tn^9dY^52pX{uBmE81Bf%W3+|(m#8-&$^`FH{P z8d`5@eNO9(T5oQUA4u0=^K9Xb7c8+BTYN);8*GW)fO?rNvlXaU*iE(y^-Z?M-h+CT zt+V%`USqe|2T;HF1F=c44y6j8wq@IL@$_F`prb5(sYMqfNut%Fd| zZi2fg`f)Czkg3MBO~`ciwV(GQTx{|)K|z#jP{dzBNb;H-8eK9n{$dzJnj>;(y*8Nf z!sH)I`@}gVBSJ0R?vC3xW#z;>B|QUrT-{S0_xwrv;~7=mUK_V_S-+T38U(wbVd(TD8#a@j0VeeTUZ}a5O@!ob34YD|wV()8S^mv$MN#5K0dI-rRZ|_7r z=|k5zT=y~zO4^I_y-+i6f-$|%?)Ha#9ky{BiopF4V-6l4O8uht3>TiGwJW^6JMq^g zL2m^7Ub+YBN#Bm+`B0UWckAm1dCUi>AsVb}XS-0ioQm5Anvh zi!Jz-asi9~0`y=dD)Mg98}KqGPrwwx^7S43BV0j?k5OxbxCcex2Z?bDp!MuE!-WLp z!ejsY==N2huh2L`PfmWQqoXzAzXWB35ew*nG)5Lka|D=E&`xX}kr01p#?y{-tvlMV z0(7CZW&fwBP2F|bAhkZ|L+oIb&G<#oGJ$TuRH1JQn#7vOcdy#_t|cO5&gAETf<>G9 z9VpB=wxKwZoEWF%*abqGK;?(Wm63a5jVfsHi31L?m(U^363pmXrv?&sWHa;Eki*cBnGhD=0&p@QPlLXL39si3Yix=}2-sHk4ns>l4I-^rXM9yvYJ@kqpD)BJahF zP9|utmAtbJ+wdUKdL@WeePl$Mn}2}LuPl~e&?=X!vAB#aBa}%Apf}y!@zI; zs}29ug+%k@4lFh1$@-Khz!www0<|^f4KRk^hru0NQ-(hToj*eHC5r2I?N8l|2|{4H zKw==zkJjJi__7kkX$oJTCg$5XL?1VJ6TpZU=yD%!73JgUx@FFn?`FN}`Ci4Vdk#JvXLXiT zg;G{T;DFjB(ZHQWoBo!i`m9uolWd3oX7TB` zvM`rP#PPV$zEaf${%lF`jVKRq+}4bh+FrC$c^f5Gzd=|8UL5V}x>+|pV;-Km`5(gU BuygleK%^5#zG-?D&{fn^kN1c%0 zad5JDFt`oX{s=;lkO(RqMMDQ#SGkE7dPylPQJnWwIjMw|#1H+X8dj59Si`nhE2)K~ z9@dM#qZ(o3TO!J$azsQ$R)%hPN;o^D=?}iHZ5YWjDS}i7%imnP{?)bR>&su(Zu4HY zpPH3mQ@r3t1ovYhl+03nbtj3l{n~3Vk8Cxa+<(x`;#6~$d-r0SHA{JQom+W76;kDu zDAfvP^XhZ1V!^Z2Oc^vaY3^<6UJ{|&lf@km>@IX92`R+Hc}S!yJwaEA zEXnc*1p3Y@c}Y4DBjFwSVMY4F8B$Ra_7+7SsC#Db_pTYpJB z5;hJX=d5(Xf>Lch?Zg>A;i|62a%B> zc|s5AAprQR18@-dh_iL<803Lj00BWP*=2gZb#jR!R znEV-Sth66mX>3~}K_r}0o5*p$jBjvpFVZX z`3wj>q`%P2DZql2y8zLU+7_&oaOIFfjLL(bYQea~onT2xy#$=;$!74$T5zMeGF`<@ z0ELyoBV6A!CN)coNX8)Pf!OEIWpE>qN)~ZhY)(&hQWKc;MG)(tP(9Q68c8__-cka4 zZIE_AS(K`t);6NBZBo!{#NJ|kAH*SfeCB70zGrmkJR+1la|-+^UYuHNV{J38Bbj@< zX{un(XOfs!AiS?9J9x z+u-w=hj3LhU^(Og)eq1f$;V-_Kt~tipVwvq&Rwq5v6H)zvU#b9-rGiBe77kV(2F7w zR_fHJ=b#R*{2yQD=!QTPbi>#b1fqk#ra(W{=?l#=!?jf$)0GX@g8A?5$&7tJ+cdfV zc4`C8-kNgouKvzjE^7~Z^LqK3d_`#%Lqqtfh&X0=G5Yn$%RGIbmbL{DSnC5RP5N^-~s2v(q?p-GW1t ztaNqW;(s~$#+5}AkT8Ymn63pqBu~gIA{=PxEApFH7(S>^V+F(+T(}a<-7c6n@Svkd zr=dCFQQ-`vb|brnv2|D+S?>IEJ{@gqp2F8a^F%V1*BFCL-BZ}FGxn^<)p*6V8N8^B zaSf~-F&jSQq5+6Rk->`x)&w~G1jVN)E`!J$;}<28O2M&N(m8`$(Cz{q^rv{tYH&~M zPTeijS{>>o-}U`sNAq-EVel$OjD_Vc*Mi&7>59CZ^}F!=801!ARql8Dg6k}f494A* rP++b#6%e^6;Xi;uGUcxA+jn!rUmXSHCTg}Acdz8rGxS5S&v*X@s^4-- literal 0 HcmV?d00001 diff --git a/model_gen/__pycache__/colour_theme_braille_character.cpython-38.pyc b/model_gen/__pycache__/colour_theme_braille_character.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4ade39b97651e9bbb70cb41794209921ca4c8847 GIT binary patch literal 5424 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 literal 0 HcmV?d00001 diff --git a/model_gen/__pycache__/export_3d.cpython-38.pyc b/model_gen/__pycache__/export_3d.cpython-38.pyc index 1031cdceb07a31d50c6bf8ed8d2225397a0a2e88..a7bfe7b392d9b50efe01c0ac4816eafb425196e3 100644 GIT binary patch literal 3428 zcma)8OLH7a5$@{8bWhJyBiXXF-i>C1MLP>CjOFz~VT8OAT!{5LkWCPcHk#H{Yt-6) zjH-HMkD{83d?kWA0U;3_;J(3u1HXV@PzNrY^cT#*WY$cNCH-82UwxRJ;AXM`;N~oR?UsqqlH`UkjYw$G^J9T^~t^0L? z^UTCe8-62g`pvZEx6-!XPCI@l?fP9Mw~~dl=l7uBrVg#YBK{(EY2%gVFVQA#!S@!` z_q2ZJEOvKT6c!Qn^33}TTR8E&A9(jRHa9-meDH~P|K9x#*WC`s#Zk^Sy&uyTA*0@B zF{MdV3C3hN`0JX?iE~9d(zjXJ(`N-yTd38 z4yFr(I2(-%9y|#0QIzpPNc%Op$OkMuI7p&^#wl;;7;T)h@C()iOI@z~i&1Po(qtsDPcruO`^eA7w~Apq!z7RT8d)`o!THbh&I$p3tCO+{O5%! zh%nCe(k?9O2>ZBpuETs==!_PQAm=30Y3-csYG3@KbbzlN*J%Aqo&B1+bIGH!F06~X zk~Ki~$HJveQD4?zwF%tDB_W!q!3>@K4fbB;?#%D_EHE1biq+`7pR&nRR_;#i~qBs8gFd zGid0-pmpH5a}EHBHh|;IbeO_Iheq(g4yLHl)(t5UHpIQojU61?1^L2EpHF9J|XJ?a{^GwDyg1v0N%|oqTojC#nIomY&EKLTiHt>M8iy2Nf1Z zVMar~KFC?LehAMPt?!0K_!H~_mYNknXgnxb3k)vn>12j3_AMBnwJJ@#U~5|pABDY- zq>Hl~Nt{Ii_~)=Vk_{CI5A%dZOgd^XNa^bjD-GA!uC}dkSxgc<4)`d?u5=+DPlGZ4 zKVbboVmQE>!ucTJ+9%^MiHk|U!EWKP(X-exp4~>|A=p$0uE*X%89FP&e9ABu1JvS7 zI){LEgk=9V`w&HaBxs+hEk45DcaeM#$vTqnBk_Rv7T#v!TNu$^`gQdQU_Zd}IF&Y} zK8P4x+SxcgP@S21WGxH6j3ykvEPuggHXUU{Sy$G@pf+RjB2kE*lJDT&Ye2T4@%Mme zErcHeu%~xPn{;jH8_03U9iryG1wgb_1DXQhKfeaRIam;W#*L8%&2vFXA4;02XhYsn}H)~ z(nP<#`U<*NSpG2dv#WozDv;fH&#tJ)o**n8bmR zLz)D0?|b^GewX0ig>1~WVO3v$re2|cTiQWD^Fa_u7mMA|1mBAN6z2FH4$(PEp)O8S z$SR!u47hSJWJ6UcU?CGzRnMt6lFM`BzFo^P9oDG`EAL!Sc{?RAb` CIiCLj literal 3111 zcmZuz&2JmW72nwpa`{bBvh`8BAkwrpi^Om(CkMk&ol4E2XcVKegMd}KU2)dbI=f41 zc4(W#>`6HUMO*aVw2*G?wJ3`IEpzQj|3Z3be{c8^BhC`@_Pu%YhO;xj-+S}4(WqK@ z-ud^Z{9l`v^&c``e_R-k(DFY*aI0@|#_fdlZS!{eu6cX?65dWyPW`^0R{E8++OMXy zel4x{>uICkU=-&j&9v2TrR{#(*j}=hcKRLYYf&d!-?kt(wk_^|W%CNJe&O}6arE>0 zSBy7!6ZUo9;_WZ2{wBANtls)8uI`H{lo9WavhGLJ!fChrlkVN!2fOb*xc^@F-rak< z)#{^gB2P!+LHFnUWhi*}qnPs~lB4Y1qcoPM)#}eg7$-^8-95l8JW9Hc#fVP^vTLS~ zM_Kg>pKl%ZN_ssXi16eji2@#{QI^A*>-Ff>cqC*n7$u{L2;^y$M!GqSGU}O|x!xdq zG)BxI1Wtf5u7Xr8k3htgHfIV(yMmiUD%DR#~>M4ht(>$6XbGWxCOW$t}$ z3(iX`&%?r3?uEbdeJLxvto%(2(Jp$cmyB7;!w80X|EkKFtxDS#^`1RHd#qgLJtIu` zhqKpYT6E8X#YhBAWX;6Tub6y>c+E4k_6;9 z8I2M_TdzH=c^GLYi8AeGAz)Mr$G{BN&frvN2Vc^w=xRD$0z=pGS-vzx9dn2VO;k#! z7@KP^onnA4BZ45L*>la}zgyxh4Ep-l`wxzv=8?#cBVxw!$60hB;uq2J!Dui6x@CS0 zCJaTGrg1hremn(@vM#cX@&2dVU34q7r1r2ujo$*v}8DuZuOSqfJkPw;w5PzLt zhp;MdGuL)a^X)CR!`@;$ws;$!4}swNf=&jr148HWq2P5igVZWc!yuJWF1mE`-x$ke zC}5Q=TRHI9Mt778+)^(vv(ic{t-R8F(ztbGN$=b$D!{TYge%4Q+&L~4jiOn!igvM9bYw*}R8zH7Tdm0|My#FNs-tX*Ql2U) z{DZ1OuLITfO^Z9+{X^^6Db|aP;+m{o)YXQ%c4;$fp|6vE_T||tRRIIM!>=1lSm#pQ z+7nIe)D?%oo|exhVG_$}uOZgZBWM?OnJ^ea2oC}%j5BTL z1KkopW+c8zJJ)r6Ngy5%q_{~j-=~;b5@%5WSP$i?u9<}QY?L5a*YnfS%OyFHn#e+S zUTE1Q6$BVveJz!Gq)&lu@cNamm{)*xgCvtwmk|vj0`v$zG0I|5x|9WsqEr|UC zBK7j2y{@6n^Xn3|$YJ>>bNm8ta}C%9T1j6bcdom@0t2S!md8XzxvKl;5M*dA zeoWemzuFm%Q4XGFNWr2+u5A)q5ZXN=+?T`%89LIHRpHb&A8U{PDbn6pAVr9GDCk{? z-a5Rm(5Bi4tpnn>xKG|2B#89lE`;_`f#fuah>svCH0|+VJjn6Uvmn+reA$Zr9=MA> zL-1Ia&2ZSLX2ehNQ=0V=31Z*3`Dt!gc^0E!$^f%Q=}9u}V_;4t#j5{`Xv$pX+Z_k#`{6@A=ps PpLOjvtJ^!n(B0 diff --git a/model_gen/__pycache__/keyboard_3d.cpython-38.pyc b/model_gen/__pycache__/keyboard_3d.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9dfef8bc30e4daa40db7a520bfe026f5b0ca0648 GIT binary patch literal 14873 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 literal 0 HcmV?d00001 diff --git a/model_gen/__pycache__/openscad_objects.cpython-38.pyc b/model_gen/__pycache__/openscad_objects.cpython-38.pyc index 8d6fa188da8696e46fa01268fccbda09b774bfaa..65e7d212e492cd115c3acc3fdacd445f8d8fe83f 100644 GIT binary patch literal 6545 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 delta 2228 zcmZ8iOK%%D5Y|d7?L!a8d9`lRAWc#r2HYOnYf!+FVJD~@3z3qb0t$g%Qd&m4q{H2{ zt6X%+9|&~mvFNersrdsv6#WA|6yUW$0r%9O&>3=F1u^8=nc+M>&J4*nU;cS}^J%*s zR^YGcKcoL{RVsh2e!a5wcpo&hGOkdERugAjHQ(CUr8Vllu8iw+gL>3|?Tj1r5)Ehw zoJTilleU2KX`6PyDxlS2W&850*_(f+jqn_^ti0;?PGj{$HQT%cV%9)qBXq*5@>ln2 zf8T9^eC{Br0@-dV{OItMBoiu&NA(#Ku2YWXAA_JO{P3aSpNCyXLrlF_4ar7 zCug~Vi*Bw8rkdz+3CQSt40O9~LaR-*sHI$}%V@{lD}JJQmVOJ1wmbeE$E{V>&f8~x*I8=6PfnSDpxPV7Jj)ZN-9b{M zy77!lD8FtTsVL@Dd;3KcXPjv7kj$9KiEbS-%8RsIFQq}DP9R3uO$t^<2=|DZzsr{% z%{{VI^NVPW(zEeMP(G8ojb6h9I)kBfux2-G-nGIVa52|GpU>jlu--#y8Gnzl6Qe4f zEQ}|N>h^#nY`K=*-IoQ?Zf`+E8OpH6Y*eV1h2$CR3$0S3pdmU~tIOzXg+ad-gC3zQ zFE^4imKe6vUn1n;|B7%R&!837&TPl9-f+G!Ov~slq$Y0eLJ0RHot3Vgo>XF*$g_)3 zPvnBwl&*;r+6s1)B~;eOLL0UFn4B)4t(*$PWpn|yg9xlxXtG0WlIX^eBq@xh>21k3 zEjqhULl3W~c$$G(u+J6iDjv@UG968hV=P@I> z4!VU(7T2Cjh*=xq>3JfvMOVo)p;vc0pDy7-VXDwUFP4$S1Ff4wLTLg6fi{gHXF?EN zFU3QmB#aD1$0Y7h$g{EkPztu7>`VuTT;x5)NUH0*uL=djv77M7UJ~I!EVJA?hUPO& z<#Nu(*zPQbNrNnmLsh+_g!V}UQ1%lX=yFGoPNjkquq$#7+bxxSIP5~VFD^M!jqkp;9;0rmEHYM7246Re1l?Gn8+eRCs1TrsO$w^`L~?P+ut^BJIh}{+OCdNfL~{XzfgM< zc!i_MM2F~nvOst9TIwrA&59JR`3XGLoRXYNVIL{;_~65-?jzYjg2CTMXWnuDK`LpH Zu&+MAcR#~t&%Nn8e$8)%*Tb!_{U4kd>}CJ} diff --git a/model_gen/__pycache__/product_braille.cpython-38.pyc b/model_gen/__pycache__/product_braille.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..00f3665670811ff6bac4f0269e028889b40c19e3 GIT binary patch literal 6151 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 diff --git a/model_gen/__pycache__/translate_braille_2_scad.cpython-38.pyc b/model_gen/__pycache__/translate_braille_2_scad.cpython-38.pyc index 469bda4e2356d45c1e3bb83783f9ab3bbfdb56a7..ac34c81fb83c164722550594ac44df475b5067de 100644 GIT binary patch literal 15419 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 Nh@La zk1Aoo78w%jWR-l5-lEooDIKt|5yJ~*>{6`=gOFsE9AKvg4iaN4ugF+j8zH7HdK)MYh(ANbppffi1WG^T2y(xJFSo1X_ z@c>kZT`*byZFOXeaR%B}XVGoKj=D6g2fRlc4|?jrYF|a9r)iy-oV;}9#to6WxxyP& zs(9u4`SVw1gnr9sDBZX;dG6c|VP35kOZQQpxP;4qE5iKhVkPvkL88^fmiICsSl%~~ z2?wN$j|agHiis@Q-Oc7+Y>8u=Yo$Q6eEYBSM>G&NUqM)X_SXMJEZV!BSfpKt6EfeD z9U}lDI$XC8;c(J)7?0=xu0<3+q{>fCKfXOQKc0lM|&*_WlK_=!YMpdBAc!);1PNNrxQ2_*h%1C z>|nI02jtPC98x3dMQVP8h$cLWwWPKBkm{{|q(&=`)NCCvt#y#{sBaK4{nnu{z3xys#vVf5Q#Eq(O6zbm&^m&8i$)nzT1TU! z%trk&mTtMsZXIV%Yb46HP9ThQkY$Exzh$y6yf1!hDmui}VI}H8{Xq%k_LTF-_V_~Mf^1EloE zlPooii=L>TWm(S$`g)G#Xim}KP%?Hji1$g{Atmb1Bt5Wp+-2m%BrVc5?O6@4UCx&STZFmiPTWW8;7@dv^$X~)d`lFZH)PecN z?4klzXAUT>u`T5>tkgWDv|f(Jz!#!bo@gDtjMeXhPf^bf9%aCrGjJAoAIsm@pXmIz zV#x;dV$7BGp5#sO`2Aa{yPk^%@#ew!-7yzrdoDT?(>~S>Ij-a}Mw3#O$kL9{SSGH| z;GQ=bXUq7sR+7U#-y`+$iNS}$e%ubz9+0=j0pqR#@OW>icYWtADB{l1|UU{xae%u7fU%-I!-X;uRXhDl~42sKg9Eg$!ZP$*U7kp zY#^pCWNhFgJvtg4ha^aP$5PNw+#A82^dR0m^g(KAC^`apAI6voGCb?sN4MIw?H>d7It3 z+68&Fpt;hEWj1|MTWh5?-IVsNcC>Bhh}V1Bx+kdzKf&_@SZeZ3HvcX=Uenk}YciUI z1&Ztbn4O@yOG;8pYq$AdvXfhCadMWmpRyO)wc#OLA!VXTb}H&#Gh637tIF%LT-sXICA-cGrV>|fbtc+bW?TQz8^Au&vI0WKjhRp(w7bpnTkpU9^ z7WP?5=;L3f%Rl}R{XUy+_KjTOm11=&2v@8AYgg-4HX_e2{0{J&#w{AcTqsr%id5xy z1{*&|RHE5aS}bz3B|FDo7wWxchU(}J5cSVg7x;AQc&3gt?UDE^l97Uri+lub%QZwb zWG-<6NxO8p14cUR;&mXK;!V z3GxSXfKBHFia+pgP|>1$r%JdgGE&guuV{poh*}I#-~Ev8(Y(-j z5f9}xe76xk!q*!?oMI3x3~;beYXi%|Sg3)FI%W)E;S{ zYfihbMtx;Z-BCZW`hbN$LN55DAEF0;i&;W*DRi-!eK{_Xg5m^DY9^J5f1N5c{+KGh zN$?^13V_v1bc0DZER9vEd33)jN!wWEzfEv|F}Zc3ZwcrchcsxES~f3cz-~m>0(syU zDHsB1E!PPr1J>Y^IT?0}qh6^-vBrvl&>BpBxg|ezlA+o7Cg^o^lQC8PU4kfrB;zFV z%rDhVE_@3&W!Oc=ZS7a%o7mUsKrFvTFx>clG-jr)IksbDZ)Gp#v-#up3A^9v{%>J_ Ba|!?e diff --git a/model_gen/__pycache__/translate_msg_2_braille.cpython-38.pyc b/model_gen/__pycache__/translate_msg_2_braille.cpython-38.pyc index 59f3c941ba092f46655fb388bc739ebcd3b3f1ee..d03c63ae68eeb9c92bc778a5c8a57a26568dab1c 100644 GIT binary patch literal 15861 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 diff --git a/model_gen/__pycache__/translation_braille.cpython-38.pyc b/model_gen/__pycache__/translation_braille.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b8de3b6098c023ccab6ebc6497739b7942f7fc81 GIT binary patch literal 9713 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 oUDtP$N1YqkCuk+pXZiK%T_mnTR57q1ANqW}N^ literal 0 HcmV?d00001 diff --git a/model_gen/__pycache__/utils_system.cpython-38.pyc b/model_gen/__pycache__/utils_system.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2d14135bc5d27d3c3b66e1d3bce0159ad4490cdb GIT binary patch literal 1180 zcmZuwOK%e~5VpOWN4HH|@j7uZQ4bBGRhx!~DukeExsg^1y+kWktF=iM_7T|*v{5+0 zogaXZ;Ml*kS5EweoS1RaQnek)T4d2J;_BL&Yh{&q0p zuZD^@pYrV|yRE0Yk6XOC)!gyCm*L0^a<$73#OF{6{w5Y8ktWYJx@l|%p7%OVBtINV z6`DBDG{UUgezpIIw?``E2U$PPr04wwrld1nYw!B?BbE16m~sr&bw7s)9fjfoM3~>X zxd6&A+Awqz+=Tsrd?yqbyRs^+u^E4ON_(g5|n!hoKo1WqA^7qYF=-$SBBll!}I1Ea0~Q=@r!(G|3#n4}}Bn zjHnv$n!bbFjS+R6~;*- z{WKRc3HmbgME`gXSWz+)QU&LFJwQcJ8p7_eRjO71MHJU_LyS^d>DB-k z@|A!zAfJ_pOo*N7FA(zgxmc`IRH8gh!%Q?Bh4QNsxS~8`(x7Sy_b}y|TSim`w+=%i zAWoT9Y1Og2(}&k;&eu<#J!#ba^IrL1d4|z*L+W_FrGFoQtvR(dXFuI9%s?+()Y$2a z8Lul0I-~YtV7~w>wTSKp&P6Q^KgtU^v9~ndM=GmK-GMo}$_Ce#%_;yvuP|Vp@y@kW z{o};Mc#oRBht}ry_U4w4Z)5f}xVjC80atwTJk@BKW;z$OzNnSv}oUqH( zT|9*") - raise ValueError(error_msg) - # suppress_console_outputs - if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors): - error_msg = error_msg_str(my_f, 'suppress_console_outputs', suppress_console_outputs, "", suppress_errors) - if suppress_errors: - print(error_msg) - return error_msg - else: - raise ValueError(error_msg) - # method - if not val_str(method, 'method', my_f, suppress_errors=suppress_errors, suppress_console_outputs=suppress_console_outputs): - error_msg = error_msg_str(my_f, 'method', method, "", suppress_errors, suppress_console_outputs) - if suppress_errors: - if not suppress_console_outputs: - print(error_msg) - return error_msg - else: - raise ValueError(error_msg) - my_f = method + '.' + my_f - # v_name - if not val_str(v_name, 'v_name', my_f, -1, -1, suppress_errors, suppress_console_outputs): - error_msg = error_msg_str(my_f, 'v_name', v_name, "", suppress_errors, suppress_console_outputs) - if suppress_errors: - if not suppress_console_outputs: - print(error_msg) - return error_msg - else: - raise ValueError(error_msg) - # v_type - if not val_str(v_type, 'v_type', my_f, -1, -1, suppress_errors, suppress_console_outputs): - error_msg = error_msg_str(my_f, 'v_type', v_type, "", suppress_errors, suppress_console_outputs) - if suppress_errors: - if not suppress_console_outputs: - print(error_msg) - return error_msg - else: - raise ValueError(error_msg) - # v_arg_type - if not val_str(v_arg_type, 'v_arg_type', my_f, -1, -1, suppress_errors, suppress_console_outputs): - error_msg = error_msg_str(my_f, 'v_arg_type', v_arg_type, "", suppress_errors, suppress_console_outputs) - if suppress_errors: - if not suppress_console_outputs: - print(error_msg) - return error_msg - else: - raise ValueError(error_msg) -# RETURNS - return f"Invalid {method} {v_type} {v_arg_type} {v_name}. Type = {str(type(v))}. Value = {v}" - -def val_bool(v_input, v_name, method, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'): -# FUNCTION - # validate that myinput is of type bool -# ARGUMENTS - # bool (hopefully) myinput - # str v_name - # str method - # optional bool suppress_errors - # optional bool suppress_console_outputs - # optional str v_arg_type -# ARGUMENT VALIDATION - # validate bool inputs first - v_type = "" - my_f = 'val_bool' - if str(type(suppress_errors)) != v_type: - raise ValueError(error_msg_str(my_f, 'suppress_errors', suppress_errors, v_type)) - if str(type(suppress_console_outputs)) != v_type: - error_msg = error_msg_str(my_f, 'suppress_console_outputs', suppress_console_outputs, v_type, suppress_errors) - if suppress_errors: - print(error_msg) - return False - raise ValueError(error_msg) - v_type = "" - # method - valid = True - if str(type(method)) != v_type: - valid = False - else: - if len(method) < 1: - valid = False - if not valid: - error_msg = error_msg_str(my_f, 'method', method, v_type, suppress_errors, suppress_console_outputs) - if suppress_errors: - if not suppress_console_outputs: - print(error_msg) - return False - raise ValueError(error_msg) - my_f = method + '.' + my_f - # v_name - valid = True - if str(type(v_name)) != v_type: - valid = False - else: - if len(v_name) < 1: - valid = False - if not valid: - error_msg = error_msg_str(my_f, 'v_name', v_name, v_type, suppress_errors, suppress_console_outputs) - if suppress_errors: - if not suppress_console_outputs: - print(error_msg) - return False - raise ValueError(error_msg) - # v_arg_type - valid = True - if str(type(v_arg_type)) != v_type: - valid = False - else: - if len(v_arg_type) < 1: - valid = False - if not valid: - error_msg = error_msg_str(my_f, 'v_arg_type', v_arg_type, v_type, suppress_errors, suppress_console_outputs) - if suppress_errors: - if not suppress_console_outputs: - print(error_msg) - return False - else: - raise ValueError(error_msg) - # v_input - v_type = "" - if (str(type(v_input)) != v_type): - error_msg = error_msg_str(method, v_name, v_input, v_type, suppress_errors, suppress_console_outputs) - if suppress_errors: - if not suppress_console_outputs: - print(error_msg) - return False - raise ValueError(error_msg) -# RETURNS - return True - - -def val_str(v_input, v_name, method, min_len = -1, max_len = -1, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'): -# FUNCTION - # validate that v_input is of type str -# ARGUMENTS - # str (hopefully) v_input - # str v_name - # str method - # optional int min_len - # optional int max_len - # optional bool suppress_errors - # optional bool suppress_console_outputs - # optional str v_arg_type -# ARGUMENT VALIDATION - my_f = 'val_str' - v_type = "" - # suppress_errors - val_bool(suppress_errors, 'suppress_errors', my_f) - # suppress_console_outputs - if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors): - print(error_msg_str(my_f, 'suppress_console_outputs', suppress_console_outputs, "", suppress_errors)) - return False - # method - valid = True - if str(type(method)) != v_type: - valid = False - else: - if len(method) < 1: - valid = False - if not valid: - error_msg = error_msg_str(my_f, 'method', method, v_type) - if suppress_errors: - if not suppress_console_outputs: - print(error_msg) - return False - raise ValueError(error_msg) - my_f = method + '.' + my_f - # v_name - valid = True - if str(type(v_name)) != v_type: - valid = False - else: - if len(v_name) < 1: - valid = False - if not valid: - error_msg = error_msg_str(my_f, 'v_name', v_name, v_type) - if suppress_errors: - if not suppress_console_outputs: - print(error_msg) - return False - raise ValueError(error_msg) - # v_arg_type - valid = True - if str(type(v_arg_type)) != v_type: - valid = False - else: - if len(v_arg_type) < 1: - valid = False - if not valid: - error_msg = error_msg_str(my_f, 'v_arg_type', v_arg_type, v_type) - if suppress_errors: - if not suppress_console_outputs: - print(error_msg) - return False - raise ValueError(error_msg) - # min_len - v_type = "" - if str(type(min_len)) != v_type: - error_msg = error_msg_str(my_f, 'min_len', min_len, v_type) - if suppress_errors: - if not suppress_console_outputs: - print(error_msg) - return False - raise ValueError(error_msg) - # max_len - v_type = "" - valid = True - if str(type(max_len)) != v_type: - valid = False - else: - if max_len != -1 and max_len < min_len: - valid = False - if not valid: - error_msg = error_msg_str(my_f, 'max_len', max_len, v_type) - if suppress_errors: - if not suppress_console_outputs: - print(error_msg) - return False - raise ValueError(error_msg) - # v_input -# VARIABLE INSTANTIATION - v_type = "" - valid = True -# METHODS - if str(type(v_input)) != v_type: - valid = False - else: - L = len(v_input) - if min_len != -1 and L < min_len: - valid = False - print(f"Minimum str length {min_len} not met.") - if max_len != -1 and L > max_len: - print(f"Maximum str length {max_len} not met.") - valid = False - if not valid: - error_msg = error_msg_str(method, v_name, v_input, v_type, suppress_errors, suppress_console_outputs, v_arg_type) - if suppress_errors: - if not suppress_console_outputs: - print(error_msg) - return False - raise ValueError(error_msg) -# RETURNS - return True - -# def val_none(v_input, v_name, method, v_arg_type = 'argument', suppress_errors = False, suppress_console_outputs = False): -# # FUNCTION -# # evaluate if v_input is None -# # ARGUMENTS -# # ARGUMENT VALIDATION -# # VARIABLE INSTANTIATION -# # METHODS -# # RETURNS - -def val_int(v_input, v_name, method, v_min: Optional[int] = None, v_max: Optional[int] = None, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'): -# FUNCTION - # validate that myinput is of type int, and if not None, limited by v_min and v_max -# ARGUMENTS - # int (hopefully) myinput - # str v_name - # str method - # optional int v_min - # optional int v_max - # optional bool suppress_errors - # optional bool suppress_console_outputs - # optional str v_arg_type -# ARGUMENT VALIDATION - my_f = 'val_int' - # suppress_errors - val_bool(suppress_errors, 'suppress_errors', my_f) - # suppress_console_outputs - if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors): - print(error_msg_str(my_f, 'suppress_console_outputs', suppress_console_outputs, "", suppress_errors)) - return False - # method - if not val_str(method, 'method', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False - my_f = method + '.' + my_f - # v_name - if not val_str(v_name, 'v_name', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False - # v_arg_type - if not val_str(v_arg_type, 'v_arg_type', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False - # v_min - if (v_min != None): - if not val_int(v_min, 'v_min', my_f, None, None, suppress_errors, suppress_console_outputs): - return False - # v_max - if (v_max != None): - if not val_int(v_max, 'v_max', my_f, None, None, suppress_errors, suppress_console_outputs): - return False - # v_input -# VARIABLE INSTANTIATION - mytype = "" # str(type(myinput)) - error_msg = error_msg_str(method, v_name, v_input, mytype, suppress_errors, suppress_console_outputs, v_arg_type) -# METHODS - if not mytype == str(type(v_input)): - if suppress_errors: - if not suppress_console_outputs: - print(error_msg) - return False - raise ValueError(error_msg) - if (v_min != None and v_max != None): - if (v_min > v_max): - if suppress_errors: - if not suppress_console_outputs: - print(error_msg + f"\nInverted minimum and maximum values {v_min} and {v_max}.") - return False - raise ValueError(error_msg + f"\nInverted minimum and maximum values {v_min} and {v_max}.") - if (v_min != None): - if (v_input < v_min): - if suppress_errors: - if not suppress_console_outputs: - print(error_msg + f"\nValue less than minimum {v_min}.") - return False - raise ValueError(error_msg + f"\nValue less than minimum {v_min}.") - if (v_max != None): - if (v_input > v_max): - if suppress_errors: - if not suppress_console_outputs: - print(error_msg + f"\nValue greater than maximum {v_max}.") - return False - raise ValueError(error_msg + f"\nValue greater than maximum {v_max}.") -# RETURNS - return True - - -def val_float(v_input, v_name, method, v_min = None, v_max = None, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'): -# FUNCTION - # validate that v_input is of type float, and if not None, limited by v_min and v_max -# ARGUMENTS - # float (hopefully) v_input - # str v_name - # str method - # optional float v_min - # optional float v_max - # optional bool suppress_errors - # optional bool suppress_console_outputs - # optional str v_arg_type -# ARGUMENT VALIDATION - my_f = 'val_float' - # suppress_errors - val_bool(suppress_errors, 'suppress_errors', my_f) - # suppress_console_outputs - if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors): - print(error_msg_str(my_f, 'suppress_console_outputs', suppress_console_outputs, "", suppress_errors)) - return False - # v_name - if not val_str(v_name, 'v_name', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False - # method - if not val_str(method, 'method', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False - my_f = method + '.' + my_f - # v_arg_type - if not val_str(v_arg_type, 'v_arg_type', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False - # v_min - if (v_min != None): - if not val_float(v_min, 'v_min', my_f, None, None, suppress_errors, suppress_console_outputs): - return False - # v_max - if (v_max != None): - if not val_float(v_max, 'v_max', my_f, None, None, suppress_errors, suppress_console_outputs): - return False - # v_input -# VARIABLE INSTANTIATION - mytype = "" # str(type(myinput)) - error_msg = error_msg_str(method, v_name, v_input, mytype, suppress_errors, suppress_console_outputs, v_arg_type) -# METHODS - if not mytype == str(type(v_input)): - if suppress_errors: - if not suppress_console_outputs: - print(error_msg) - return False - raise ValueError(error_msg) - if (v_min != None and v_max != None): - if (v_min > v_max): - if suppress_errors: - if not suppress_console_outputs: - print(error_msg + f"\nInverted minimum and maximum values {v_min} and {v_max}.") - return False - raise ValueError(error_msg + f"\nInverted minimum and maximum values {v_min} and {v_max}.") - if (v_min != None): - if (v_input < v_min): - if suppress_errors: - if not suppress_console_outputs: - print(error_msg + f"\nValue less than minimum {v_min}.") - return False - raise ValueError(error_msg + f"\nValue less than minimum {v_min}.") - if (v_max != None): - if (v_input > v_max): - if suppress_errors: - if not suppress_console_outputs: - print(error_msg + f"\nValue greater than maximum {v_max}.") - return False - raise ValueError(error_msg + f"\nValue greater than maximum {v_max}.") -# RETURNS - return True - -def input_bool(v_input, v_name, method, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'): -# FUNCTION - # input valid str, int, or bool representation of bool, or else None -# ARGUMENTS - # bool (hopefully) v_input - # str v_name - # str method - # optional str v_arg_type - # optional bool suppress_errors - # optional bool suppress_console_outputs -# ARGUMENT VALIDATION - my_f = 'input_bool' - # suppress_errors - val_bool(suppress_errors, 'suppress_errors', my_f) - # suppress_console_outputs - if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors): - print(error_msg_str(my_f, 'suppress_console_outputs', suppress_console_outputs, "", suppress_errors)) - return None - # v_name - if not val_str(v_name, 'v_name', my_f, 1, -1, suppress_errors, suppress_console_outputs): return None - # method - if not val_str(method, 'method', my_f, 1, -1, suppress_errors, suppress_console_outputs): return None - my_f = method + '.' + my_f - # v_arg_type - if not val_str(v_arg_type, 'v_arg_type', my_f, 1, -1, suppress_errors, suppress_console_outputs): return None -# METHODS - if not val_bool(v_input, v_name, my_f, suppress_errors, suppress_console_outputs): - if not val_int(v_input, v_name, my_f, 0, 1, suppress_errors, suppress_console_outputs): - error_msg = error_msg_str(method, v_name, v_input, "", suppress_errors, suppress_console_outputs, v_arg_type) - if not val_str(v_input, v_name, my_f, suppress_errors, suppress_console_outputs): - if suppress_errors: - if not suppress_console_outputs: - print(error_msg) - return None - raise ValueError(error_msg) - else: - my_truths = ['Y', 'YE', 'YES', 'YS', 'YESH', 'YEA', 'YEAH', 'TRUE', 'TRU', 'TRUTH', 'TURE', 'T'] - my_falths = ['N', 'NO', 'FALSE', 'F', 'FAIL', 'FALS'] - for i in range(len(my_truths)): - if my_truths[i] == v_input: - return True - for i in range(len(my_falths)): - if my_falths[i] == v_input: - return False - if suppress_errors: - if not suppress_console_outputs: - print(error_msg) - return None - raise ValueError(error_msg) - else: - return False if v_input == 0 else True -# RETURNS - return v_input - -def full_val_bool(v_input, v_name, method, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'): -# FUNCTION - # validate that bool input is bool or valid equivalent -# ARGUMENTS - # bool (hopefully) my_input - # str v_name - # str method - # optional bool suppress_errors - # optional bool suppress_console_outputs - # optional str v_arg_type -# ARGUMENT VALIDATION - my_f = 'full_val_bool' - val_bool(suppress_errors, 'suppress_errors', my_f) - if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors): - print(error_msg_str(my_f, 'suppress_console_outputs', suppress_console_outputs, "", suppress_errors)) - return False - # method - if not val_str(method, 'method', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False - my_f = method + '.' + my_f - # v_name - if not val_str(v_name, 'v_name', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False - # v_arg_type - if not val_str(v_arg_type, 'v_arg_type', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False -# RETURNS - return not (str(type(input_bool(v_input, v_name, method, suppress_errors, suppress_console_outputs, v_arg_type))) == "") - - -def input_int(v_input, v_name, method, v_min = None, v_max = None, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'): -# FUNCTION - # input int or valid equivalent, or else None -# ARGUMENTS - # int or str v_input - # str v_name - # str method - # v_min - # v_min - # bool suppress_errors - # bool suppress_console_outputs - # optional str v_arg_type -# ARGUMENT VALIDATION - my_f = 'input_int' - val_bool(suppress_errors, 'suppress_errors', my_f) - if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors): - print(error_msg_str(my_f, 'suppress_console_outputs', suppress_console_outputs, "", suppress_errors)) - return None - # method - if not val_str(method, 'method', my_f, 1, -1, suppress_errors, suppress_console_outputs): return None - my_f = method + '.' + my_f - # v_name - if not val_str(v_name, 'v_name', my_f, 1, -1, suppress_errors, suppress_console_outputs): return None - # v_arg_type - if not val_str(v_arg_type, 'v_arg_type', my_f, 1, -1, suppress_errors, suppress_console_outputs): return None - # v_min - if not str(type(v_min)) == "": - v_min = input_int(v_min, 'v_min', my_f, None, v_max, suppress_errors, suppress_console_outputs) - if str(type(v_min)) == "": return None - # v_max - if not str(type(v_max)) == "": - v_max = input_int(v_max, 'v_min', my_f, v_min, None, suppress_errors, suppress_console_outputs) - if str(type(v_max)) == "": return None -# METHODS - error_msg = error_msg_str(method, v_name, v_input, "", suppress_errors, suppress_console_outputs, v_arg_type) - # v_input - try: - my_int = int(v_input) - except: - if suppress_errors: - if not suppress_console_outputs: - print(error_msg) - return None - int(v_input) - if not str(type(v_min)) == "": - if my_int < v_min: - if suppress_errors: - if not suppress_console_outputs: - print(f"{error_msg}\nInt input less than minimum value. Value = {v_input}, minimum = {v_min}.") - return None - if not str(type(v_max)) == "": - if my_int > v_max: - if suppress_errors: - if not suppress_console_outputs: - print(f"{error_msg}\nInt input greater than maximum value. Value = {v_input}, maximum = {v_max}.") - return None -# RETURNS - return my_int - - -def full_val_int(v_input, v_name, method, v_min = None, v_max = None, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'): -# FUNCTION - # validate that v_input is int or equivalent, else False, limited by v_min and v_max -# ARGUMENTS - # int (hopefully) v_input - # str v_name - # str method - # optional float v_min - # optional float v_max - # optional bool suppress_errors - # optional bool suppress_console_outputs - # optional str v_arg_type -# ARGUMENT VALIDATION - my_f = 'full_val_int' - val_bool(suppress_errors, 'suppress_errors', my_f) - if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors): - print(error_msg_str(my_f, 'suppress_console_outputs', suppress_console_outputs, "", suppress_errors)) - return False - # v_name - if not val_str(v_name, 'v_name', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False - # method - if not val_str(method, 'method', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False - # v_min - if not str(type(v_min)) == "": - v_min = input_int(v_min, 'v_min', method, None, v_max, suppress_errors, suppress_console_outputs) - if str(type(v_min)) == "": return False - # v_max - if not str(type(v_max)) == "": - v_max = input_int(v_max, 'v_min', method, v_min, None, suppress_errors, suppress_console_outputs) - if str(type(v_max)) == "": return False -# RETURNS - return not (str(type(input_int(v_input, v_name, method, v_min, v_max, suppress_errors, suppress_console_outputs))) == "") - - -def input_float(v_input, v_name, method, v_min = None, v_max = None, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'): -# FUNCTION - # input float, else return None -# ARGUMENTS - # float/int/str(numeric) v_input - # str v_name - # str method - # optional float v_min - # optional float v_min - # optional bool suppress_errors - # optional bool suppress_console_outputs - # optional str v_arg_type -# ARGUMENT VALIDATION - my_f = 'input_float' - val_bool(suppress_errors, 'suppress_errors', my_f) - if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors): - print(error_msg_str(my_f, 'suppress_console_outputs', suppress_console_outputs, "", suppress_errors)) - return None - # method - if not val_str(method, 'method', my_f, 1, -1, suppress_errors, suppress_console_outputs): return None - my_f = method + '.' + my_f - # v_name - if not val_str(v_name, 'v_name', my_f, 1, -1, suppress_errors, suppress_console_outputs): return None - # v_arg_type - if not val_str(v_arg_type, 'v_arg_type', my_f, 1, -1, suppress_errors, suppress_console_outputs): return None - # v_min - if not str(type(v_min)) == "": - v_min = input_float(v_min, 'v_min', my_f, None, v_max, suppress_errors, suppress_console_outputs) - if str(type(v_min)) == "": return None - # v_max - if not str(type(v_max)) == "": - v_max = input_float(v_max, 'v_min', my_f, v_min, None, suppress_errors, suppress_console_outputs) - if str(type(v_max)) == "": return None -# METHODS - error_msg = error_msg_str(method, v_name, v_input, "", suppress_errors, suppress_console_outputs, v_arg_type) - # v_input - try: - my_float = float(v_input) - except: - if suppress_errors: - if not suppress_console_outputs: - print(error_msg) - return None - float(v_input) - if not str(type(v_min)) == "": - if v_input < v_min: - if suppress_errors: - if not suppress_console_outputs: - print(f"{error_msg}\nInt input less than minimum value. Value = {v_input}, minimum = {v_min}.") - return None - if not str(type(v_max)) == "": - if v_input > v_max: - if suppress_errors: - if not suppress_console_outputs: - print(f"{error_msg}\nInt input greater than maximum value. Value = {v_input}, maximum = {v_max}.") - return None -# RETURNS - return my_float - - -def full_val_float(v_input, v_name, method, v_min = None, v_max = None, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'): -# FUNCTION - # validate that v_input is numeric, and if not False, limited by v_min and v_max -# ARGUMENTS - # float (hopefully) v_input - # str v_name - # str method - # optional float v_min - # optional float v_max - # optional bool suppress_errors - # optional bool suppress_console_outputs -# ARGUMENT VALIDATION - my_f = 'full_val_float' - val_bool(suppress_errors, 'suppress_errors', my_f) - if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors): - print(error_msg_str(my_f, 'suppress_console_outputs', suppress_console_outputs, "", suppress_errors)) - return False - # method - if not val_str(method, 'method', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False - my_f = method + '.' + my_f - # v_name - if not val_str(v_name, 'v_name', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False - # v_arg_type - if not val_str(v_arg_type, 'v_arg_type', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False - # v_min - if not str(type(v_min)) == "": - v_min = input_float(v_min, 'v_min', method, None, v_max, suppress_errors, suppress_console_outputs) - if str(type(v_min)) == "": return False - # v_max - if not str(type(v_max)) == "": - v_max = input_float(v_max, 'v_min', method, v_min, None, suppress_errors, suppress_console_outputs) - if str(type(v_max)) == "": return False -# RETURNS - return not (str(type(input_float(v_input, v_name, method, v_min, v_max, suppress_errors, suppress_console_outputs))) == "") - - -def make_ordinal(n): -# FUNCTION - # Get ordinal representation of number -# ARGUMENTS - # int n -# ARGUMENT VALIDATION - full_val_int(n, 'n', 'make_ordinal', 0) -# VARIABLE INSTANTIATION - n = int(n) -# METHODS - if 11 <= (n % 100): - suffix= 'th' - else: - suffix = ['th', 'st', 'nd', 'rd', 'th'][min(n % 10, 4)] -# RETURNS - return str(n) + suffix - - -def val_type(v_input, v_type, v_name, method, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'): -# FUNCTION - # validate that v_input is of type v_type -# ARGUMENTS - # v_type (hopefully) v_input - # str v_type - # str v_name - # str method - # optional bool suppress_errors - # optional bool suppress_console_outputs - # str v_arg_type -# ARGUMENT VALIDATION - my_f = 'val_type' - val_bool(suppress_errors, 'suppress_errors', my_f) - if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors): - print(error_msg_str(my_f, 'suppress_console_outputs', suppress_console_outputs, "", suppress_errors)) - return False - # method - if not val_str(method, 'method', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False - my_f = method + '.' + my_f - # v_name - if not val_str(v_name, 'v_name', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False - # v_arg_type - if not val_str(v_arg_type, 'v_arg_type', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False - # v_type - if not val_str(v_type, 'v_type', my_f, 6, -1, suppress_errors, suppress_console_outputs): return False - # v_input - error_message = error_msg_str(method, v_name, v_input, v_arg_type) - mytype = str(type(v_input)) - # if not (v_type == 'int' or v_type == 'bool' or v_type == 'float' or v_type == 'complex' or v_type == 'str' or v_type == 'NoneType'): - if not mytype == v_type: # f"": - if suppress_errors: - if not suppress_console_outputs: - print(error_message) - return False - raise ValueError(error_message) -# RETURNS - return True - - -def val_list(v_input, v_name, method, v_type = '', min_len = -1, max_len = -1, suppress_errors = False, suppress_console_outputs: bool = False, v_arg_type = 'argument'): -# FUNCTION - # validate that v_input is of type list, and if defined: has v_len elements of type v_type -# ARGUMENTS - # list[v_type] (hopefully) v_input - # str v_name - variable name - # str method - parent method - # str v_type - type of list items - # int v_len - length of list - # optional bool suppress_errors - # optional bool suppress_console_outputs - # optional str v_arg_type -# ARGUMENT VALIDATION - my_f = 'val_list' - val_bool(suppress_errors, 'suppress_errors', my_f) - if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors): - print(error_msg_str(my_f, 'suppress_console_outputs', suppress_console_outputs, "", suppress_errors)) - return False - # method - if not val_str(method, 'method', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False - my_f = method + '.' + my_f - # v_name - if not val_str(v_name, 'v_name', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False - # v_arg_type - if not val_str(v_arg_type, 'v_arg_type', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False - # v_type - if not val_str(v_type, 'v_type', my_f, -1, -1, suppress_errors, suppress_console_outputs): return False - # min_len - if not full_val_int(min_len, 'min_len', my_f, None, None if max_len == -1 else max_len, suppress_errors, suppress_console_outputs): return False - # min_len = input_int(min_len, 'min_len', method, None, max_len, suppress_errors, suppress_console_outputs) - # if str(type(min_len)) == "": return False - # max_len - if not full_val_int(max_len, 'max_len', my_f, None if max_len == -1 else (None if min_len == -1 else min_len), None, suppress_errors, suppress_console_outputs): return False - # if not str(type(max_len)) == "": - # max_len = input_int(max_len, 'max_len', method, min_len, None, suppress_errors, suppress_console_outputs) - # if str(type(max_len)) == "": return False - # v_input - mytype = str(type(v_input)) - error_msg = error_msg_str(method, v_name, v_input, "") - if not mytype == "": - if suppress_errors: - if not suppress_console_outputs: - print(error_msg) - return False - raise ValueError(error_msg) - L = len(v_input) - if max_len > -1 and L > max_len: - if suppress_errors: - if not suppress_console_outputs: - print(error_msg + f'\nInvalid list length. Maximum = {max_len}, length = {L}') - return False - raise ValueError(error_msg + f'\nInvalid list length. Maximum = {max_len}, length = {L}') - if L < min_len: - if suppress_errors: - if not suppress_console_outputs: - print(error_msg + f"Invalid list length. Minimum = {min_len}, length = {L}") - return False - raise ValueError(error_msg + f'\nInvalid list length. Minimum = {min_len}, length = {L}') - if v_type != '' and L > 0: - for i in range(L): - mytype = str(type(v_input[i])) - if not mytype == v_type: - error_msg = error_msg + '\n' + error_msg_str(my_f, v_name, v_input, v_type, False, False, 'list element') - if suppress_errors: - if not suppress_console_outputs: - print(error_msg) - return False - raise ValueError(error_msg) -# RETURNS - return True - -def val_nested_list(v_input, depth_i, depth_max, v_name, method, v_type = '', v_min = -1, v_mins = [], v_max = -1, v_maxs: list = [], suppress_errors = False, suppress_console_outputs: bool = False, v_arg_type = 'argument'): -# FUNCTION - # validate that v_input is of type list, and if defined: has v_len elements of type v_type - # for nested list of nested-index i -# ARGUMENTS - # list[v_type] (hopefully) v_input - # int depth_i - current depth of nesting of lists - # int depth_max - maximum depth of nesting of lists - base 0 - # str v_name - # str method - # Optional[str] v_type - type of list items - # Optional[int] v_min - minimum sublist size - # Optional[list[int]] v_mins - minimum list sizes - # Optional[int] v_max - maximum sublist size - # Optional[list[int]] v_maxs - maximum list sizes - # optional bool suppress_errors - # optional bool suppress_console_outputs - # optional str v_arg_type -# ARGUMENT VALIDATION - my_f = 'val_nested_list' - val_bool(suppress_errors, 'suppress_errors', my_f) - if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors): - print(error_msg_str(my_f, 'suppress_console_outputs', suppress_console_outputs, "")) - return False - # method - if not val_str(method, 'method', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False - my_f = method + '.' + my_f - # v_name - if not val_str(v_name, 'v_name', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False - # v_arg_type - if not val_str(v_arg_type, 'v_arg_type', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False - # v_type - if not val_str(v_type, 'v_type', my_f, -1, -1, suppress_errors, suppress_console_outputs): return False - # v_min - if not val_int(v_min, 'v_min', my_f, -1, None, suppress_errors, suppress_console_outputs): return False - # v_max - if not val_int(v_max, 'v_max', my_f, -1, None, suppress_errors, suppress_console_outputs): return False - # v_mins - if not (val_list(v_mins, 'v_mins', my_f, "", depth_max + 1, depth_max + 1, True, True) or v_mins == []): - error_msg = error_msg_str(my_f, 'v_mins', v_mins, "") - if not suppress_console_outputs: - print(error_msg) - return False - raise ValueError(error_msg) - # v_maxs - if not (val_list(v_maxs, 'v_maxs', my_f, "", depth_max + 1, depth_max + 1, True, True) or v_maxs == []): - error_msg = error_msg_str(my_f, 'v_maxs', v_maxs, "") - if not suppress_console_outputs: - print(error_msg) - return False - raise ValueError(error_msg) - # v_input - mytype = v_type if depth_i == depth_max else "" - error_msg = error_msg_str(method, v_name, v_input, mytype, suppress_errors, suppress_console_outputs, v_arg_type) - if not val_list(v_input, v_name, method, mytype, v_min, v_max, suppress_errors, suppress_console_outputs, v_arg_type): - if not suppress_console_outputs: - print(error_msg) - return False -# METHODS - L = len(v_input) - if L == 0: - if v_min > -1: - if suppress_errors: - if not suppress_console_outputs: - print(error_msg + f'\nMinimum length {v_min} not met.') - return False - raise ValueError(error_msg + f'\nMinimum length {v_min} not met.') - elif depth_i < depth_max: - for i in range(L): - if not (v_mins == [] or v_maxs == []): - if not val_nested_list(v_input[i], depth_i + 1, depth_max, v_name, method, v_type, v_mins[depth_i + 1], v_mins, v_maxs[depth_i + 1], v_maxs, suppress_errors, suppress_console_outputs, v_arg_type): - if not suppress_console_outputs: - print(error_msg) - return False - elif not v_mins == []: - if not val_nested_list(v_input[i], depth_i + 1, depth_max, v_name, method, v_type, v_mins[depth_i + 1], v_mins, -1, v_maxs, suppress_errors, suppress_console_outputs, v_arg_type): - if not suppress_console_outputs: - print(error_msg) - return False - elif not v_maxs == []: - if not val_nested_list(v_input[i], depth_i + 1, depth_max, v_name, method, v_type, -1, v_mins, v_maxs[depth_i + 1], v_maxs, suppress_errors, suppress_console_outputs, v_arg_type): - if not suppress_console_outputs: - print(error_msg) - return False - else: - if not val_nested_list(v_input[i], depth_i + 1, depth_max, v_name, method, v_type, -1, v_mins, -1, v_maxs, suppress_errors, suppress_console_outputs, v_arg_type): - if not suppress_console_outputs: - print(error_msg) - return False -# RETURNS - return True \ No newline at end of file diff --git a/model_gen/array_keyboard_3d.py b/model_gen/array_keyboard_3d.py new file mode 100644 index 0000000..e486aea --- /dev/null +++ b/model_gen/array_keyboard_3d.py @@ -0,0 +1,98 @@ +# -*- coding: utf-8 -*- +""" +Created on Thursday May 30 2024 +@author: Edward Middleton-Smith +""" + +# import argument_validation as av +# from translate_msg_2_braille import product, gen_braille_inputs_4_openscad +# from translate_braille_2_scad import scrabble_dimensions, export_colour_theme, input_colour_themes, gen_openscad_braille, gen_path_braille_scrabble, input_product_size +# from character_braille import Size_Character_Braille, Style_Character_Braille, Colour_Theme_Character_Braille +from keyboard_3d import Size_Character_Braille, Style_Character_Braille, Colour_Theme_Character_Braille, Enum_Justification_Text, Keyboard_3D +# import model_gen.utils_system +from translation_braille import Translation_Braille + +import openpyscad as ops #, Assembly, Union +from typing import Optional, List +from pydantic import BaseModel, Field +from itertools import product + +class Array_Keyboard_3D(BaseModel): + sizes_characters: List[Size_Character_Braille] + styles_characters: List[Style_Character_Braille] + colour_themes: List[Colour_Theme_Character_Braille] + justifications_text: List[Enum_Justification_Text] + path_dir: str + max_characters_per_rows: List[int] + translations: List[Translation_Braille] + fn: int = Field(ge=0) + + keyboards: List[Keyboard_3D] = [] + has_files_openscad: bool = False + has_files_stl: bool = False + has_files_png: bool = False + + def __init__(self, **data): + super().__init__(**data) + if len(self.sizes_characters) == 0: + self.sizes_characters = Size_Character_Braille.get_defaults() + if len(self.styles_characters) == 0: + self.styles_characters = [Style_Character_Braille.get_default()] + if len(self.colour_themes) == 0: + self.colour_themes = Colour_Theme_Character_Braille.get_defaults() + if len(self.justifications_text) == 0: + self.justifications_text = [Enum_Justification_Text.get_default()] + self.make_combinations() + self.has_files_openscad = False + self.has_files_stl = False + self.has_files_png = False + + def make_combinations(self): + configuration_keyboards = product(self.sizes_characters, self.styles_characters, self.colour_themes, self.justifications_text, self.max_characters_per_rows, self.translations) + self.keyboards = [] + for configuration_keyboard in configuration_keyboards: + # self.keyboards.append(Keyboard_3D(*configuration_keyboard)) + # Keyboard_3D(size_characters=size_default, style_characters=style_default, + # colour_theme=colour_default, justification_text=justification_default, path_dir=path_dir, max_characters_per_row=10, translation=translation_extended_alphabet, fn=25) + self.keyboards.append( Keyboard_3D(size_characters=configuration_keyboard[0], style_characters=configuration_keyboard[1], colour_theme=configuration_keyboard[2], + justification_text=configuration_keyboard[3], path_dir=self.path_dir, max_characters_per_row=configuration_keyboard[4], translation=configuration_keyboard[5], fn=self.fn)) + + def update_configurations_styles(self, sizes_characters, style_characters, colour_themes, justifications_text): + self.sizes_characters = sizes_characters + self.styles_characters = style_characters + self.colour_themes = colour_themes + self.justifications_text = justifications_text + self.make_combinations() + + def make_combined_assembly(self, dx, dy, max_keyboards_per_row): + count_keyboards_in_row = 0 + count_rows = 0 + assembly = ops.Assembly() + for keyboard in self.keyboards: + assembly.add(keyboard.make_model_openpyscad().translate([dx * count_keyboards_in_row, dy * count_rows, 0])) + count_keyboards_in_row += 1 + if count_keyboards_in_row >= max_keyboards_per_row: + count_keyboards_in_row = 0 + count_rows += 1 + return assembly + + def make_files_openscad(self): + for keyboard in self.keyboards: + keyboard.make_file_openscad() + self.has_files_openscad = True + + def make_files_stl(self): + for keyboard in self.keyboards: + keyboard.make_file_stl() + self.has_files_stl = True + + def make_files_png(self): + for keyboard in self.keyboards: + keyboard.make_file_png() + self.has_files_png = True + + def make_files(self): + for keyboard in self.keyboards: + keyboard.make_file_openscad() + keyboard.make_file_stl() + keyboard.make_file_png() diff --git a/model_gen/character_braille.py b/model_gen/character_braille.py new file mode 100644 index 0000000..f573a9a --- /dev/null +++ b/model_gen/character_braille.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- +""" +Created on 29/05/2024 +@author: Edward Middleton-Smith +""" + +import pandas as pd +from typing import Optional, List +from pydantic import BaseModel, conlist, validator, field_validator, validator +from enum import Enum +# import argument_validation as av +import sys + + +class Character_Braille(BaseModel): + plaintext: str # English plaintext key + list_dots_braille: List[bool] # braille: list # list[list[int]] # Braille translation of plaintext + + def __init__(self, plaintext, list_dots_braille): + super().__init__(plaintext=plaintext, list_dots_braille=list_dots_braille) + + @validator('list_dots_braille') + def validate_list_dots_braille(cls, value): + """ + if (len(value) != 6): + raise ValueError('List must have 6 elements') + for row in value: + """ + if (len(value) != 6): + raise ValueError('List must have rows of 6 colunns') + if not all(isinstance(dot, bool) for dot in value): + raise ValueError('List must contain only boolean values') + return value + + @validator('plaintext') + def validate_plaintext(cls, value): + """ + known_translations = Character_Braille.get_Translation_Brailles() + if not known_translations['Character_Braille'].apply(lambda x: x.plaintext == value).any(): + raise ValueError('Plaintext not in known translations') + """ + return value + """ + @validator('matrix_braille_dots') + def validate_matrix_braille_dots(cls, value): + if (len(value) != 3): + raise ValueError('Matrix must have 3 rows') + for row in value: + if (len(row) != 2): + raise ValueError('Matrix must have rows of 2 colunns') + if not all(isinstance(item, bool) for item in row): + raise ValueError('Matrix must contain only boolean values') + return value + + @validator('plaintext') + def validate_plaintext(cls, value): + known_translations = Character_Braille.get_translation_Brailles() + if not known_translations['Character_Braille'].apply(lambda x: x.plaintext == value).any(): + raise ValueError('Plaintext not in known translations') + return value + """ + + def get_blank_character_Braille(): + return Character_Braille("BLANK_SPACE", [0, 0, 0, 0, 0, 0]) # , Enum_Braille_Proficiency_Level(0) + + def __repr__(self): + # return f"key = {self.key}, level = {self.level}, braille = {self.braille}, plaintext = {self.plaintext}" + return f'plaintext = {self.plaintext}, list_dots_braille = {self.list_dots_braille}' # , translation_proficiency_level = {self.translation_proficiency_level} + + # def query_lvl(self): + # return ' & '.join(["{}=='{}'".format(key, value) + # for key, value in self.__dict__.items() + # if not value is None]) + """ + def as_dict(self): + # return {'key': self.key, 'level': self.level, 'braille': self.braille, 'plaintext': self.plaintext} + return {'plaintext': self.plaintext, 'translation_proficiency_level': self.translation_proficiency_level, 'matrix_dots_braille': self.matrix_dots_braille} + """ diff --git a/model_gen/colour_theme_braille_character.py b/model_gen/colour_theme_braille_character.py new file mode 100644 index 0000000..f9d61ac --- /dev/null +++ b/model_gen/colour_theme_braille_character.py @@ -0,0 +1,210 @@ +# -*- coding: utf-8 -*- +""" +@author: Edward Middleton-Smith +""" + + +import openpyscad as ops # , Union, Difference +import numpy as np +from typing import Optional, List, Union +from prettytable import PrettyTable +from enum import Enum +from pydantic import BaseModel, Field, ValidationError, validate_arguments, validator +from abc import ABC, abstractmethod +# from color import Color +# from termcolor import colored +# from colorama import init, Fore, Style +import webcolors +from builtins import staticmethod +import os +import string +import pandas as pd + +# init() + +class BaseStyle(ABC): + """ + @abstractmethod + def minimum(): + pass + @abstractmethod + def maximum(): + pass + """ + @abstractmethod + def get_defaults(): + pass + @abstractmethod + def get_list_headings(): + pass + @abstractmethod + def as_row(self): + pass + + def input_from_console(cls): + # pass + options = cls.get_defaults() + count_options = len(options) + table_output = PrettyTable() + table_output.field_names = ['index'] + cls.get_list_headings() # ['index', 'name', 'dot spacing', 'block height', 'character spacing', 'base height', 'dot height', 'dot bottom radius', 'dot top radius'] + for index_option in range(count_options): + option = options[index_option] + table_output.add_row([index_option + 1] + option.as_row()) + print() + print("Please select product dimensions configuration from below :") + print(table_output) + while True: + option = str(input("Product dimensions configuration (by index):")) + print(option + " selected") + if option == "#!ERRORCODE!#": exit + for index_option in range(count_options): + if option == str(index_option + 1): # option == options[index_option].name or + return options[index_option] + """ + @abstractmethod + # @staticmethod + def get_classname(self): + "" + stack = inspect.stack() + return stack[2][0].f_locals["__qualname__"] + "" + return self.__class__.__name__ + """ + + def input_many_from_console(cls): + selected = [] + print(f'Inputting many {cls.__name__} objects') + print() + while True: + try: + count_inputs = int(input(f'Quantity of {cls.__name__} objects to enter:')) + except: continue + for index_input in range(count_inputs): + print(f'Inputting {cls.__name__} object {index_input + 1}') + selected_new = cls.input_from_console(cls) + selected.append(selected_new) + break + return selected + + +class Colour_Field(str): + def __new__(cls, value: Union[str, int, tuple]): + try: + # colour = colored('', value) + # colour = colour.split(Style.RESET_ALL)[0] + try: + hex_code = webcolors.normalize_hex(value) + return str.__new__(cls, hex_code) + except: + hex_code = webcolors.name_to_hex(value) + return str.__new__(cls, hex_code) + except ValueError: + raise ValidationError(f"Invalid colour value: {value}") + + @classmethod + def __get_pydantic_core_schema__(cls, handler): + return { + 'type': 'str', + } + +class Colour_Theme_Character_Braille(BaseModel, BaseStyle): +# ATTRIBUTE DECLARATION + name: str + colour_top: Colour_Field + colour_base: Colour_Field + + def __init__(self, name, colour_top, colour_base): + super().__init__(name=name, colour_top=colour_top, colour_base=colour_base) + """ +# METHODS + def __new__(cls, name, coltop, colbase, openscad_colours): + # FUNCTION + # Initialise class object + # ARGUMENTS + # str name - user reference to colour theme + # str coltop - a valid openSCAD colour e.g. '#010101' + # str colbase - a valid openSCAD colour e.g. 'blue' + # list[str] openscad_colours + # ARGUMENT VALIDATION + _m = 'export_colour_theme.__new__' + v_arg_type = 'class attribute' + av.val_str(name, 'name', _m, 1, v_arg_type = v_arg_type) + av.val_list(openscad_colours, 'openscad_colours', _m, "", 1, v_arg_type = v_arg_type) + if not validate_openscad_colour(coltop, openscad_colours): + raise ValueError(f"Invalid export_colour_theme attribute coltop. Type = {str(type(coltop))}. Value = {coltop}") + if not validate_openscad_colour(colbase, openscad_colours): + raise ValueError(f"Invalid export_colour_theme attribute colbase. Type = {str(type(colbase))}. Value = {colbase}") + # RETURNS + return super(export_colour_theme, cls).__new__(cls) + + def __init__(self, name, coltop, colbase, openscad_colours): + # FUNCTION + # Initialise class object + # ARGUMENTS + # str name - user reference to colour theme + # str coltop - a valid openSCAD colour e.g. '#010101' + # str colbase - a valid openSCAD colour e.g. 'blue' + # list[str] openscad_colours # redundant in this function - used for argument validation + # ARGUMENT VALIDATION + # see __new__() + # ATTRIBUTE INSTANTIATION + self.name = name + self.top = coltop + self.base = colbase + """ + def __repr__(self): + # FUNCTION + # Convert object to str representation + # RETURNS + return f"name = {self.name}, colour top = {self.colour_top}, colour base = {self.colour_base}" # , openscad_colours = {self.openscad_colours} + + def as_dict(self): + # FUNCTION + # Convert object attribute, value pairs to dictionary representation + # RETURNS + return {'name': self.name, 'colour top': self.colour_top, 'colour base': self.colour_base} # , 'openscad_colours': self.openscad_colours + + def as_row(self): + # FUNCTION + # Convert object values to list representation + # RETURNS + return [self.name, self.colour_top, self.colour_base] # , 'openscad_colours': self.openscad_colours + + def get_defaults(): + # openscad_colours = get_openscad_colours() + colour_themes = [] + colour_themes.append(Colour_Theme_Character_Braille("Blue", "#337AFF", "#337AFF")) #, openscad_colours)) + colour_themes.append(Colour_Theme_Character_Braille("Purple", "#8E44AD", "#8E44AD")) #, openscad_colours)) + colour_themes.append(Colour_Theme_Character_Braille("Red", "#F7322F", "#F7322F")) #, openscad_colours)) + colour_themes.append(Colour_Theme_Character_Braille("Black", "Black", "#17202A")) #, openscad_colours)) + colour_themes.append(Colour_Theme_Character_Braille("White", "White", "White")) #, openscad_colours)) + return colour_themes # , columns=['Name', 'Colour Top', 'Colour base']) # Colour_Theme_Character_Braille.__name__]) # colour_themes + + def get_defaults_DataFrame(): + return pd.DataFrame(data={Colour_Theme_Character_Braille.__name__: Colour_Theme_Character_Braille.get_defaults()}) # , columns=['Name', 'Colour Top', 'Colour base']) # Colour_Theme_Character_Braille.__name__]) # colour_themes + + def get_default(): + colours_default = Colour_Theme_Character_Braille.get_defaults_DataFrame() + return colours_default[Colour_Theme_Character_Braille.__name__].apply(lambda x: x if x.name == 'Blue' else None).dropna()[0] + + """ + def input_from_console(): + colour_themes = Colour_Theme_Character_Braille.get_defaults() + count_colours = len(colour_themes) + colour_table = PrettyTable() + colour_table.field_names = ['index', 'name', 'colour top', 'colour base'] + for col_i in range(count_colours): + colour_table.add_row([col_i + 1] + colour_themes[col_i].as_row()) + print() + print("Please select colour theme from below:") + print(colour_table) + while True: + colour_input = input("Colour theme (name or index): ") + print(str(colour_input) + " selected") + if colour_input == "#!ERRORCODE!#": exit + for i_colour in range(count_colours): + if colour_input == colour_themes[i_colour].name: + return colour_themes[i_colour] + """ + def get_list_headings(): + return ['name', 'colour top', 'colour base'] \ No newline at end of file diff --git a/model_gen/controller_braille.py b/model_gen/controller_braille.py new file mode 100644 index 0000000..e75a44f --- /dev/null +++ b/model_gen/controller_braille.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- +""" +@author: Edward Middleton-Smith +""" + +class Controller_Braille(): + # \ No newline at end of file diff --git a/model_gen/export_3d.py b/model_gen/export_3d.py deleted file mode 100644 index 07f3266..0000000 --- a/model_gen/export_3d.py +++ /dev/null @@ -1,152 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Created on Mon May 1 03:35:45 2023 - -@author: Edward Middleton-Smith - -Braille 3D Model Product Creation -""" - -# CLASSES -# ATTRIBUTE DECLARATION -# METHODS - # FUNCTION - # ARGUMENTS - # ARGUMENT VALIDATION - # ATTRIBUTE + VARIABLE INSTANTIATION - # METHODS - # RETURNS - -# NORMAL METHODS -# FUNCTION -# ARGUMENTS -# ARGUMENT VALIDATION -# VARIABLE INSTANTIATION -# METHODS -# RETURNS - - -import openpyscad as ops -import system_commands as sc -import argument_validation as av -from translate_msg_2_braille import product, gen_braille_inputs_4_openscad -from translate_braille_2_scad import scrabble_dimensions, export_colour_theme, input_colour_themes, gen_openscad_braille, gen_path_braille_scrabble, input_product_size -from typing import Optional - -def gen_product_permutations(my_product, szs_product, sz_perms = True, sz_index = 2): -# FUNCTION - # generate all colour / size permutations of product -# ARGUMENTS - # product my_product - # list[scrabble_dimensions] szs_product - different size profiles for products - # optional bool szs_perms - # optional int sz_index -# ARGUMENT VALIDATION - _m = 'gen_product_permutations' - av.val_type(my_product, "", 'my_product', _m) - av.val_list(szs_product, 'szs_product', _m, "", 1) - av.full_val_bool(sz_perms, 'sz_perms', _m) -# VARIABLE INSTANTIATION - mymsgs = [] # [msgin] - myszs = [] # [szs_scrabble[5]] -# METHODS - if not sz_perms: - my_size = input_product_size(szs_product, sz_index) - # create list of permutations of size profiles + letters - for j in range(len(szs_product) if sz_perms else 1): - for i in range(26 if my_product.name == 'Scrabble Alphabet of Tiles' else 1): - mymsgs.append(chr(65 + i) if my_product.name == 'Scrabble Character Tile' else my_product.msg) - myszs.append(szs_product[j] if sz_perms else my_size) -# RETURNS - return mymsgs, myszs - -def gen_3d_models(braille_dict, myproduct, mymsgs, myszs, line_length, path_folder, path_cmd, mystyle, col_themes): -# FUNCTION - # create 3D models - SCAD, STL, PNG - from product input -# ARGUMENTS - # list[braille_trans] braille_dict - # product myproduct - # list[str] mymsgs - # list[scrabble_dimensions] myszs - # int line_length - # str path_folder - # style mystyle - # list [export_colour_themes] col_themes -# ARGUMENT VALIDATION - _m = 'gen_3d_models' - av.val_type(braille_dict, "", 'braille_dict', _m) - av.val_type(myproduct, "", 'myproduct', _m) - av.val_list(mymsgs, 'mymsgs', _m, "", 1) - av.val_list(myszs, 'myszs', _m, "", 1) #: - # raise ValueError(av.error_msg_str(_m, 'myszs', myszs, "")) - av.val_int(line_length, 'line_length', _m, 1) - av.val_str(path_folder, 'path_folder', _m) - av.val_str(path_cmd, 'path_cmd', _m, 1) - # av.val_int(show_braille, 'show_braille', _m) - # av.val_int(show_let, 'show_let', _m) - # av.val_int(show_num, 'show_num', _m) - # av.val_type(show_braille, "", 'show_braille', _m) - # av.val_type(show_let, "", 'show_let', _m) - # av.val_type(show_num, "", 'show_num', _m) - av.val_type(mystyle, "", 'mystyle', _m) - av.val_list(col_themes, 'col_themes', _m, "", 1) -# VARIABLE INSTANTIATION -# METHODS - for col_y in range(len(col_themes)): - for msg_x in range(len(mymsgs)): - msg_x_str = mymsgs[msg_x] - cum, letters, numbers, braille, n_keys, n_rows = gen_braille_inputs_4_openscad(msg_x_str, line_length, braille_dict) - path_png, path_scad, path_stl = gen_openscad_braille(cum, letters, numbers, braille, n_keys, min(line_length, n_keys), n_rows, myszs[msg_x], mystyle, col_themes[col_y], msg_x_str, path_folder + myproduct.filename, quality = 100) - # sc.render_openscad(path_scad, path_stl, path_cmd) - # sc.render_openscad(path_scad, path_png, path_cmd) -# # RETURNS -# return col_themes - -def gen_snippet_assembly(dx, dy, len_line, col_themes, myszs, my_product, path_folder, path_cmd, my_style): #, szs_product -# FUNCTION - # create png exports of openscad assembly of series of permutations of openscad components -# ARGUMENTS - # int dx - spacing along x - # int dy - spacing along y - # int len_line - number of components on row (along x) - # list[export_colour_theme] col_themes - # list[scrabble_dimensions] myszs - # translate_msg_2_braille.product my_product - # str path_folder - # str path_cmd - # style my_style - # # list[scrabble_dimensions] szs_product -# ARGUMENT VALIDATION - _m = 'gen_snippet_assembly' - av.val_int(dx, 'dx', _m) - av.val_int(dy, 'dy', _m) - av.val_int(len_line, 'len_line', _m, 1) - av.val_list(col_themes, 'col_themes', _m, "") - # av.val_list(szs_product, 'szs_product', _m, "", 1) - av.val_list(myszs, 'myszs', _m, "", 1) - av.val_type(my_product, "", 'my_product', _m) - av.val_str(path_folder, 'path_folder', _m) - av.val_str(path_cmd, 'path_cmd', _m, 1) - av.val_type(my_style, "", 'my_style', _m) -# VARIABLE INSTANTIATION - # mystyles = ['__l_0n'] # ['_0n', '_0l_0n', '_0b_0n', '__l_0n'] - n_style = 1 # 3 - d_pcs = [dx, dy] -# METHODS - for sz_i in range(len(myszs)): - ass_braille = ops.Union() - for let_i in range(1): # 26): - col_i = 0 # let_i % n_col - style_i = 0 # let_i % n_style - # mypath = gen_path_braille_scrabble(szs_scrabble[sz_i], let_i, col_themes[col_i], 'scad') - mypath = gen_path_braille_scrabble(myszs[sz_i], col_themes[col_i], my_style, path_folder + my_product.filename, 'scad') - # mypath = f"C:\\Users\\edwar\\OneDrive\\Documents\\Programming\\Python Scripts\\Braille_Scrabble_{szs_scrabble[sz_i].name}_{Chr(let_i + 65)}_{col_themes[col_i].name}" - ass_braille.append(ops.Scad(mypath).rotate([0, 180 * let_i, 0]).translate([4 * (let_i % 2), 0, -5 * (let_i % 2)]).translate([d_pcs[0] * myszs[sz_i].dp * (let_i % len_line), d_pcs[1] * myszs[sz_i].dp * (let_i // len_line), 0])) # , convexity = 3) .translate([d_pcs * (let_i % len_line), d_pcs * (let_i // len_line), 0]) -# RETURNS - path_scad = gen_path_braille_scrabble(myszs[0], col_themes[col_i], my_style, path_folder + 'assy', 'scad') - path_stl = gen_path_braille_scrabble(myszs[0], col_themes[col_i], my_style, path_folder + 'assy', 'stl') - path_png = gen_path_braille_scrabble(myszs[0], col_themes[col_i], my_style, path_folder + 'assy', 'png') - ass_braille.write(path_scad) # , with_print=True - print(f"writing SCAD to {path_scad}") - # render_openscad(path_scad, path_stl) - sc.render_openscad(path_scad, path_png, path_cmd) \ No newline at end of file diff --git a/model_gen/keyboard_3d.py b/model_gen/keyboard_3d.py new file mode 100644 index 0000000..ed6f7c5 --- /dev/null +++ b/model_gen/keyboard_3d.py @@ -0,0 +1,549 @@ +# -*- coding: utf-8 -*- +""" +@author: Edward Middleton-Smith +""" + +# import argument_validation as av +from colour_theme_braille_character import Colour_Theme_Character_Braille, BaseStyle +from openscad_objects import ModelOpenSCAD # get_openscad_colours +# from translate_msg_2_braille import Character_Braille +from character_braille import Character_Braille +from translation_braille import Translation_Braille, Enum_Braille_Proficiency_Level +from utils_system import render_openscad, make_openscad, exec_oscmd + +import openpyscad as ops # Union, Difference +import numpy as np +from typing import Optional, List +from prettytable import PrettyTable +from enum import Enum +from pydantic import BaseModel, Field, ValidationError, validate_arguments, validator +# from color import Color +from builtins import staticmethod +import os +import string +from abc import ABC, abstractmethod +import inspect + + +""" +class EnumBaseStyleMeta(type(Enum), type(BaseStyle)): + pass +""" +class Enum_Visibility_Character_Braille(Enum): # BaseStyle, metaclass=EnumBaseStyleMeta): + EMBOSSED = -1 + HIDDEN = 0 + VISIBLE = 1 + def minimum(): + return min([e.value for e in Enum_Visibility_Character_Braille]) + def maximum(): + return max([e.value for e in Enum_Visibility_Character_Braille]) + def get_text_filename(self): + return '_0' if (self == Enum_Visibility_Character_Braille.HIDDEN) else '__' if (self == Enum_Visibility_Character_Braille.EMBOSSED) else '_1' + +class Style_Character_Braille(BaseModel, BaseStyle): + show_braille: Enum_Visibility_Character_Braille # = Enum_Visibility_Character_Braille.VISIBLE + show_letter: Enum_Visibility_Character_Braille # = Enum_Visibility_Character_Braille.VISIBLE + show_number: Enum_Visibility_Character_Braille # = Enum_Visibility_Character_Braille.VISIBLE + + """ + def __new__(cls, braille, letter, number): + _m = 'style.__new__' + av.val_type(braille, "", 'braille', _m) + av.val_type(braille, "", 'braille', _m) + av.val_type(braille, "", 'braille', _m) + return super(style, cls).__new__(cls) + + def __init__(self, braille, letter, number): + self.braille = braille + self.letter = letter + self.number = number + """ + + def get_text_filename(self): + return f"{self.show_braille.get_text_filename()}{self.show_letter.get_text_filename()}{self.show_number.get_text_filename()}" + + @staticmethod + def get_default(): + return Style_Character_Braille(show_braille=Enum_Visibility_Character_Braille.VISIBLE, show_letter=Enum_Visibility_Character_Braille.VISIBLE, show_number=Enum_Visibility_Character_Braille.VISIBLE) + + @staticmethod + def get_defaults(): + return [Style_Character_Braille.get_default()] + + def as_row(self): + return [self.show_braille.name, self.show_letter.name, self.show_number.name] + """ + def input_from_console(): + sizes = Size_Character_Braille.get_defaults() + count_sizes = len(sizes) + table_output = PrettyTable() + table_output.field_names = ['index', 'name', 'dot spacing', 'block height', 'character spacing', 'base height', 'dot height', 'dot bottom radius', 'dot top radius'] + for index_size in range(count_sizes): + size_index = sizes[index_size] + table_output.add_row([index_size + 1] + size_index.as_row()) + print() + print("Please select product dimensions configuration from below:") + print(table_output) + while True: + size_input = str(input("Product dimensions configuration (name or index): ")) + print(size_input + " selected") + if size_input == "#!ERRORCODE!#": exit + for index_size in range(count_sizes): + if size_input == sizes[index_size].name or size_input == str(index_size + 1): + return sizes[index_size] + + def input_many_from_console(): + sizes_selected = [] + print('Inputting many Size_Character_Braille objects') + print() + while True: + try: + count_sizes = int(input('Quantity of size objects to enter:')) + except: continue + for index_size in range(count_sizes): + print(f'Inputting size object {index_size + 1}') + size_new = Size_Character_Braille.input_from_console() + sizes_selected.append(size_new) + break + return sizes_selected + """ + + def get_list_headings(): + return ['show braille', 'show letter', 'show number'] + +class Size_Character_Braille(BaseModel, BaseStyle): +# ATTRIBUTE DECLARATION + name: str + spacing_dot: float = Field(ge = 0) # dp distance between dots + height_block: float = Field(ge = 0) # hblock height of + spacing_character: float = Field(ge = 0) # spacing between keys on keyboard + height_base: float = Field(ge = 0) # height of + height_dot: float = Field(ge = 0) # height of Braille dots + radius_bottom_dot: float = Field(ge = 0) # base radius of Braille dots + radius_top_dot : float = Field(ge = 0) # top radius of Braille dots + + width_character_braille: float = 0 + R_block_letter: List[float] = [0, 0, 0] + R_block_braille: List[float] = [0, 0, 0] + R_block_number: List[float] = [0, 0, 0] + size_font_alphabetic: float = 0 + size_font_numeric: float = 0 + sf_size_font_word_length: float = 0 + sf_size_font_number_length: float = 0 + + def __init__(self, name, spacing_dot, height_block, spacing_character, height_base, height_dot, radius_bottom_dot, radius_top_dot): + BaseModel.__init__(self, name=name, spacing_dot=spacing_dot, height_block=height_block, spacing_character=spacing_character, height_base=height_base, height_dot=height_dot, radius_bottom_dot=radius_bottom_dot, radius_top_dot=radius_top_dot) + self.width_character_braille = self.spacing_dot + 2 * self.spacing_character + self.radius_bottom_dot * 2 + self.R_block_letter = [self.width_character_braille, self.width_character_braille, self.height_block] # alphabet block dimensions [x, y] + self.R_block_braille = [self.width_character_braille, self.width_character_braille + self.spacing_dot, self.height_block] # braille block dimensions [x, y] + self.R_block_number = [self.width_character_braille, self.width_character_braille - 2 * self.spacing_character, self.height_block] #np.array(* i_s_num # number block dimensions [x, y] ' adjust to scalar coefficient rather than linear translation + + self.size_font_alphabetic = self.R_block_letter[0] - 4 * self.spacing_character + self.size_font_numeric = self.size_font_alphabetic * 0.75 + self.sf_size_font_word_length = 0.65 # scale factor for shrinking number text to fit more letters in single char space + self.sf_size_font_number_length = 0.75 # scale factor for shrinking message text to fit more letters in single char space + + """ +# METHODS + def __new__(cls, name, dp, hblock, s, base_height, hcyl, rcyl, rsphere): + # FUNCTION + # Initialise class object + # ARGUMENTS + # str name - name size scheme + # float dp - distance between braille pins + # float hblock - height of base of each key + # float s - spacing + # float base_height - height of base block - board + # float hcyl - height of braille pins + # float rcyl - base radius of braille pins + # float rsphere - tip radius of braille pins + # ARGUMENT VALIDATION + _m = 'scrabble_dimensions.__new__' + v_arg_type = 'class attribute' + av.val_str(name, 'name', _m, 1, v_arg_type = v_arg_type) + av.full_val_float(dp, 'dp', _m, 0, v_arg_type = v_arg_type) + av.full_val_float(hblock, 'hblock', _m, v_arg_type = v_arg_type) + av.full_val_float(s, 's', _m, 0, v_arg_type = v_arg_type) + av.full_val_float(base_height, 'base_height', _m, 0, v_arg_type = v_arg_type) + av.full_val_float(hcyl, 'hcyl', _m, 0, v_arg_type = v_arg_type) + av.full_val_float(rcyl, 'rcyl', _m, 0, v_arg_type = v_arg_type) + av.full_val_float(rsphere, 'rsphere', _m, 0, v_arg_type = v_arg_type) + # RETURNS + return super(scrabble_dimensions, cls).__new__(cls) + + def __init__(self, name, dp, hblock, s, base_height, hcyl, rcyl, rsphere): + # FUNCTION + # Construct class object + # ARGUMENTS + # str name + # float dp + # float hblock + # float s + # float base_height + # float hcyl + # float rcyl + # float rsphere + # ARGUMENT VALIDATION + # see __new__() + # ATTRIBUTE INSTANTIATION + self.name = name + self.dp = dp + self.hblock = hblock + self.s = s + self.base_height = base_height + self.hcyl = hcyl + self.rcyl = rcyl + self.rsphere = rsphere + """ + def __repr__(self): + # FUNCTION + # Convert object to str representation + # RETURNS + return f"name = {self.name}, spacing_dot = {self.spacing_dot}, height_block = {self.height_block}, spacing_character = {self.spacing_character}, height_base = {self.height_base}, height_dot = {self.height_dot}, radius_bottom_dot = {self.radius_bottom_dot}, radius_top_dot = {self.radius_top_dot}" + + def as_dict(self): + # FUNCTION + # Convert object attribute, value pairs to dictionary representation + # RETURNS + return {'name': self.name, 'spacing_dot': self.spacing_dot, 'height_block': self.height_block, 'spacing_character': self.spacing_character, 'height_base': self.height_base, 'height_dot': self.height_dot, 'radius_bottom_dot': self.radius_bottom_dot, 'radius_top_dot': self.radius_top_dot} + + def as_row(self): + return [self.name, self.spacing_dot, self.height_block, self.spacing_character, self.height_base, self.height_dot, self.radius_bottom_dot, self.radius_top_dot] + + def get_defaults(): + k = 2.3622 + s = 1 + sizes = [] + sizes.append(Size_Character_Braille('sz_1', 2.5, 2*s, s, 4*s, 1.2, 2/3, 1/2)) + sizes.append(Size_Character_Braille('sz_2', 4, 1.28, s, 4*s, 1.2, 3/2, 1)) + sizes.append(Size_Character_Braille('sz_3', 8, 2.5, s, 6*s, 1.2, 3/2, 1)) + sizes.append(Size_Character_Braille('sz_4', 10, 3, 1, 6*s, 1.2, 3/2, 1)) + sizes.append(Size_Character_Braille('sz_5', 10, 1, 1, 6*s, 1.2, 3/2, 1)) + sizes.append(Size_Character_Braille('keyboard', 2.5, 0.8, 0.5, 4, 1.2, 2/3, 0.5)) + sizes.append(Size_Character_Braille('poster', 2.5, 0.8, 0.5, 2, 1.2, 2/3, 0.5)) + sizes.append(Size_Character_Braille('poster_big', 2.5*k, 0.8, 0.5*k, 2, 1.2, 2/3*k, 0.5*k)) + # print('szs_scrabble') + return sizes + + def get_default(): + sizes_default = Size_Character_Braille.get_defaults() + return sizes_default['Character_Braille'].apply(lambda x: x if x.name == 'Keyboard' else None).dropna()[0] + + """ + def input_from_console(): + sizes = Size_Character_Braille.get_defaults() + count_sizes = len(sizes) + table_output = PrettyTable() + table_output.field_names = ['index', 'name', 'dot spacing', 'block height', 'character spacing', 'base height', 'dot height', 'dot bottom radius', 'dot top radius'] + for index_size in range(count_sizes): + size_index = sizes[index_size] + table_output.add_row([index_size + 1] + size_index.as_row()) + print() + print("Please select product dimensions configuration from below:") + print(table_output) + while True: + size_input = str(input("Product dimensions configuration (name or index): ")) + print(size_input + " selected") + if size_input == "#!ERRORCODE!#": exit + for index_size in range(count_sizes): + if size_input == sizes[index_size].name or size_input == str(index_size + 1): + return sizes[index_size] + + def input_many_from_console(): + sizes_selected = [] + print('Inputting many Size_Character_Braille objects') + print() + while True: + try: + count_sizes = int(input('Quantity of size objects to enter:')) + except: continue + for index_size in range(count_sizes): + print(f'Inputting size object {index_size + 1}') + size_new = Size_Character_Braille.input_from_console() + sizes_selected.append(size_new) + break + return sizes_selected + """ + def get_list_headings(): + return ['name', 'dot spacing', 'block height', 'character spacing', 'base height', 'dot height', 'dot bottom radius', 'dot top radius'] +""" +class Utils_Size_Character_Braille: + @staticmethod + @validate_arguments + def is_valid_size_input(size_input: str, sizes_valid: List[Size_Character_Braille]): + count_sizes_valid = len(sizes_valid) + for i_size_valid in range(count_sizes_valid): + if size_input == sizes_valid[i_size_valid].name: + return True + return False +""" + + +class Enum_Justification_Text(Enum): + LEFT = 0 + CENTRE = 1 + RIGHT = 2 + def minimum(): + return min([e.value for e in Enum_Visibility_Character_Braille]) + def maximum(): + return max([e.value for e in Enum_Visibility_Character_Braille]) + def input_from_console(cls): + print("Please select justification for text:") + print("0. Left") + print("1. Centre") + print("2. Right") + while True: + justification_input = input("Justification (0, 1, 2): ") + print(str(justification_input) + " selected") + if justification_input == "#!ERRORCODE!#": exit + try: + justification_input = int(justification_input) + except: continue + # if justification_input is not int: continue + if justification_input < Enum_Justification_Text.minimum() or justification_input > Enum_Justification_Text.maximum(): continue + return Enum_Justification_Text(justification_input) + def get_default(): + return Enum_Justification_Text(0) + + def input_many_from_console(): + return BaseStyle.input_many_from_console(Enum_Justification_Text) + +class Keyboard_3D(ModelOpenSCAD): #, BaseModel): + size_characters: Size_Character_Braille + style_characters: Style_Character_Braille + colour_theme: Colour_Theme_Character_Braille + justification_text: Enum_Justification_Text + max_characters_per_row: int + translation: Translation_Braille # List[List[Character_Braille]] + # fn: int = Field(ge=0, default=25) + + # filename: str = '' + + def __init__(self, **kwargs): # , size_characters, style_characters, colour_theme, justification_text, path_dir, max_characters_per_row, translation, fn=25, filename=''): + # print(f'size_characters, style_characters, colour_theme, justification_text, path_dir, max_characters_per_row, translation, fn, filename: {size_characters, style_characters, colour_theme, justification_text, path_dir, max_characters_per_row, translation, fn, filename}') + # BaseModel.__init__(self, size_characters=size_characters, style_characters=style_characters, colour_theme=colour_theme, justification_text=justification_text, path_dir=path_dir, max_characters_per_row=max_characters_per_row, translation=translation, fn=fn, filename=filename) + # BaseModel.__init__(self, size_characters=size_characters, style_characters=style_characters, justification_text=justification_text, max_characters_per_row=max_characters_per_row, translation=translation, filename='') + # self.filename = self.get_filename() + ModelOpenSCAD.__init__(self, **{**kwargs, 'filename': '', 'model': None}) # , path_dir=path_dir, filename=filename, colour_theme=colour_theme, fn=fn) + # BaseModel.__init__(self, size_characters=size_characters, style_characters=style_characters, justification_text=justification_text, max_characters_per_row=max_characters_per_row, translation=translation) + # BaseModel.__init__(self, **kwargs) # , size_characters=size_characters, style_characters=style_characters, colour_theme=colour_theme, justification_text=justification_text, path_dir=path_dir, max_characters_per_row=max_characters_per_row, translation=translation, fn=fn, filename=filename) + self.filename = self.get_filename() + + + def get_filename(self): #, sz_scheme, col_theme, my_style, path_file = "C:\\Users\\edwar\\OneDrive\\Documents\\Programming\\Python Scripts\\Braille_Scrabble", suffix = "stl", presuffix=""): + """ + av.val_str(path_file, 'path_file', _m) + av.val_str(suffix, 'suffix', _m) + av.val_str(presuffix, 'presuffix', _m) + """ + return f"{self.size_characters.name}_{self.colour_theme.name}{self.style_characters.get_text_filename()}" + + def get_path_file(self, suffix): + return f"{self.path_dir}/{self.filename}.{suffix}" + + @staticmethod + @validate_arguments + def make_from_styles_and_plaintext_and_proficiency_level(size_characters: Size_Character_Braille, style_characters: Style_Character_Braille, colour_theme: Colour_Theme_Character_Braille, justification_text: Enum_Justification_Text, path_dir: str, max_characters_per_row: int, plaintext: str, proficiency_level: Enum_Braille_Proficiency_Level): + braille_translation = Translation_Braille(plaintext, proficiency_level) + return Keyboard_3D(size_characters = size_characters, style_characters = style_characters, colour_theme = colour_theme, justification_text = justification_text, path_dir = path_dir, max_characters_per_row = max_characters_per_row, translation = braille_translation) + + def make_model_openpyscad(self): + # integer boolean conversions for position + show_braille = (self.style_characters.show_braille == Enum_Visibility_Character_Braille.VISIBLE) # or self.style_characters.show_braille == Enum_Visibility_Character_Braille.EMBOSSED) + show_letter = (self.style_characters.show_letter == Enum_Visibility_Character_Braille.VISIBLE) # or self.style_characters.show_letter == Enum_Visibility_Character_Braille.EMBOSSED) + show_number = (self.style_characters.show_number == Enum_Visibility_Character_Braille.VISIBLE) # or self.style_characters.show_number == Enum_Visibility_Character_Braille.EMBOSSED) + + # dimensions + """ + width_character_braille = self.size_characters.spacing_dot + 2 * self.size_characters.spacing_character + self.size_characters.radius_bottom_dot * 2 + R_base_letter = [width_character_braille, width_character_braille, self.size_characters.height_block] # alphabet block dimensions [x, y] + R_base_braille = [width_character_braille, width_character_braille + self.size_characters.spacing_dot, self.size_characters.height_block] # braille block dimensions [x, y] + R_base_number = [width_character_braille, width_character_braille - 2 * self.size_characters.spacing_character, self.size_characters.height_block] #np.array(* i_s_num # number block dimensions [x, y] ' adjust to scalar coefficient rather than linear translation + """ + + # _fn = self.fn + model_positive = ops.Union() + model_negative = ops.Union() + count_rows = 0 + count_characters_in_row = 0 + size_character = np.array([ + self.size_characters.spacing_character + self.size_characters.width_character_braille, + self.size_characters.R_base_braille[1] * show_braille + self.size_characters.R_base_letter[1] * show_letter + self.size_characters.R_base_number[1] * show_number + self.size_characters.spacing_character * (show_braille + show_letter + show_number), + 0 + ]) + origin_character = np.array([-self.size_characters.spacing_character, -self.size_characters.spacing_character, 0]) + for braille_translation in self.translation: + length_translation = len(braille_translation.braille_text) + if count_characters_in_row + length_translation > self.max_characters_per_row or (braille_translation.plaintext == 'NEWLINE' and braille_translation.list_dots_braille == [0, 0, 0, 0, 0, 0] and count_characters_in_row > 0): + count_rows += 1 + count_characters_in_row = 0 + for character in braille_translation.braille_text: + model_character_positive, model_character_negative = self.make_model_openscad_from_character(character) # character.make_model_openpyscad() + position_character = origin_character + np.array([ + (self.size_characters.spacing_character + size_character[0]) * count_characters_in_row, + (self.size_characters.spacing_character + size_character[1]) * count_rows, + 0 + ]) + model_character_positive.translate(position_character) + model_positive.append(model_character_positive) + model_character_negative.translate(position_character) + model_negative.append(model_character_negative) + count_characters_in_row += 1 + self.model = ops.Difference() + self.model.append(model_character_positive) + self.model.append(model_character_negative) + return self.model + + @validate_arguments + def make_model_openscad_from_character(self, character: Character_Braille): # origin_character: List[float] , show_braille: bool, show_letter: bool, show_number: bool + show_braille = (self.style_characters.show_braille == Enum_Visibility_Character_Braille.VISIBLE) # or self.style_characters.show_braille == Enum_Visibility_Character_Braille.EMBOSSED) + show_letter = (self.style_characters.show_letter == Enum_Visibility_Character_Braille.VISIBLE or self.style_characters.show_letter == Enum_Visibility_Character_Braille.EMBOSSED) + show_number = (self.style_characters.show_number == Enum_Visibility_Character_Braille.VISIBLE) # or self.style_characters.show_number == Enum_Visibility_Character_Braille.EMBOSSED) + + model_positive = ops.Union() + model_negative = ops.Union() + origin_block = np.array([0, 0, 0]) + if show_braille: + block = self.make_model_openscad_block_braille_from_character(character) + block.translate(origin_block) + model_positive.append(block) + origin_block += np.array([ + 0, + -self.size_characters.spacing_character - self.size_characters.R_block_braille[1], + 0 + ]) + if show_letter: + block = self.make_model_openscad_block_letter_from_character(character) + block.translate(origin_block) + if self.style_characters.show_letter == Enum_Visibility_Character_Braille.VISIBLE: + model_positive.append(block) + else: + model_negative.append(block) + origin_block += np.array([ + 0, + -self.size_characters.spacing_character - self.size_characters.R_block_letter[1], + 0 + ]) + if show_number: + block = self.make_model_openscad_block_number_from_character(character) + block.translate(origin_block) + model_positive.append(block) + return model_positive, model_negative + """ + @validator('origin_character') + def validate_origin_character(cls, value): + if len(value) != 3: + raise ValueError("origin_character must have 3 elements") + for element in value: + if not isinstance(element, (int, float)): + raise ValueError("origin_character must be a list of integers or floats") + return value + + @validator('R_block_braille') + def validate_R_block_braille(cls, value): + if len(value) != 3: + raise ValueError("R_block_braille must have 3 elements") + return value + + @validator('R_block_letter') + def validate_R_block_letter(cls, value): + if len(value) != 3: + raise ValueError("R_block_letter must have 3 elements") + return value + + @validator('R_block_number') + def validate_R_block_number(cls, value): + if len(value) != 3: + raise ValueError("R_block_number must have 3 elements") + return value + """ + @validate_arguments + def make_model_openscad_block_braille_from_character(self, character: Character_Braille): + model_block_braille = ops.Union() + if (self.style_characters.show_letter == Enum_Visibility_Character_Braille.HIDDEN): return model_block_braille + if (self.style_characters.show_letter == Enum_Visibility_Character_Braille.VISIBLE): + block = ops.Cube(self.size_characters.R_block_braille, center = False) + block.translate([0, -self.size_characters.R_block_braille[1], -self.size_characters.R_block_braille[2]]) + block.color(self.colour_theme.colour_base) + model_block_braille.append(block) + if (self.style_characters.show_braille == Enum_Visibility_Character_Braille.VISIBLE): + for index_dot_braille_y in range(3): + for index_dot_braille_x in range(2): + if (character.matrix_braille_dots[index_dot_braille_y][index_dot_braille_x]): + dot_braille = ops.Cylinder( + h = self.size_characters.height_cylinder, + r1 = self.size_characters.radius_bottom_cylinder, + r2 = self.size_characters.radius_top_cylinder, + center = True, + _fn = self.fn + ) + dot_braille.translate([ + index_dot_braille_x * self.size_characters.spacing_dot, + -index_dot_braille_y * self.size_characters.spacing_dot, + 0 + ]) + dot_braille.color(self.colour_theme.colour_top) + model_block_braille.append(dot_braille) + return model_block_braille + + @validate_arguments + def make_model_openscad_block_letter_from_character(self, character: Character_Braille): + font = '"Arial:style=Bold"' + model_block_letter = ops.Union() + if (self.style_characters.show_letter == Enum_Visibility_Character_Braille.HIDDEN): return model_block_letter + if (self.style_characters.show_letter == Enum_Visibility_Character_Braille.VISIBLE): + block = ops.Cube(self.size_characters.R_block_letter, center = False) + block.translate([0, -self.size_characters.R_block_letter[1], -self.size_characters.R_block_letter[2]]) + block.color(self.colour_theme.colour_base) + model_block_letter.append(block) + size_text = self.size_characters.size_font_alphabetic * self.size_characters.scale_text ** (len(character.plaintext) - 1) + model_letter = ops.Text(f'"{character.plaintext}"', size_text, font, halign = '"center"', valign = '"center"', _fn = self.fn) + model_letter.linear_extrude(self.size_characters.height_dot, center = False) + model_letter.color(self.colour_theme.colour_top) + model_letter.translate([ + self.size_characters.R_block_letter[0] / 2, + self.size_characters.R_block_letter[1] / 2 if (self.style_characters.show_letter == Enum_Visibility_Character_Braille.VISIBLE) else self.size_characters.R_block_braille[1] / 2, + 0 if (self.style_characters.show_letter == Enum_Visibility_Character_Braille.VISIBLE) else self.size_characters.height_dot - self.size_characters.height_block - self.size_characters.height_base + ]) + model_block_letter.append(model_letter) + return model_block_letter + + @validate_arguments + def make_model_openscad_block_number_from_character(self, character: Character_Braille): + model_block_number = ops.Union() + if (self.style_characters.show_number == Enum_Visibility_Character_Braille.HIDDEN or self.style_characters.show_number == Enum_Visibility_Character_Braille.EMBOSSED or len(character.plaintext) != 1): return model_block_number + font = '"Arial:style=Bold"' + number = string.ascii_lowercase.index(character.plaintext.lower()) + 1 + length_number = len(str(number)) + if (number < 1 or number > 26): return model_block_number + block = ops.Cube(self.size_characters.R_block_number, center = True) + block.translate([]) + block.color(self.colour_theme.colour_base) + model_block_number.append(block) + size_text = (self.size_characters.R_block_number[1] - self.size_characters.spacing_character * (len(number) + 1)) / (len(number) ** self.size_characters.sf_size_font_number_length) + model_number = ops.Text(f'"{number}"', size_text, font, halign = '"center"', valign = '"center"', _fn = self.fn) + model_number.linear_extrude(self.size_characters.height_dot, center = True) + model_number.color(self.colour_theme.colour_top) + model_number.translate([ + self.size_characters.R_block_number[0] / 2 if (length_number == 1) else self.size_characters.R_block_number[0] / 2 + 1.6 * size_text * (number - (length_number - 1) / 2), + self.size_characters.R_block_number[1] * 0.25, + self.size_characters.height_dot / 2 + ]) + model_block_number.append(model_number) + return model_block_number + + def make_file_openscad(self): + if self.model is None: + self.make_model_openpyscad() + self.model.write(self.get_path_file('scad')) + + def make_file_stl(self): + if not os.path.exists(self.get_path_file('scad')): + self.make_file_openscad() + render_openscad(self.get_path_file('scad'), self.get_path_file('stl')) + + def make_file_png(self): + if not os.path.exists(self.get_path_file('scad')): + self.make_file_openscad() + render_openscad(self.get_path_file('scad'), self.get_path_file('png')) + diff --git a/model_gen/main.py b/model_gen/main.py index 3d39e57..d498e0f 100644 --- a/model_gen/main.py +++ b/model_gen/main.py @@ -1,88 +1,24 @@ # -*- coding: utf-8 -*- """ -Created on Mon Apr 24 14:26:02 2023 - @author: Edward Middleton-Smith - -Braille 3D Model Product Creation """ -from translate_msg_2_braille import get_braille_translations, gen_product_inputs, input_product -from translate_braille_2_scad import gen_scrabble_sizes, elem_visibility, input_colour_themes, style -from export_3d import gen_product_permutations, gen_3d_models, gen_snippet_assembly -import argument_validation as av +# from translate_msg_2_braille import get_braille_translations, gen_product_inputs, input_product +# from translate_braille_2_scad import gen_scrabble_sizes, elem_visibility, input_colour_themes, style +# from export_3d import gen_product_permutations, gen_3d_models, gen_snippet_assembly +# import argument_validation as av +from product_braille import Product_Braille + +""" # PARAMETERS path_folder_cmd = 'C:\\"Program Files"\\OpenSCAD\\openscad' # 'C:\\"Program Files (x86)"\\OpenSCAD\\openscad' # local environment variable path for openscad commands path_folder = "C:\\Users\\edwar\\OneDrive\\Documents\\Programming\\Python Scripts\\" # file export parent directory -my_option = -1 # index of product option - if not valid, user console input will be required -my_select = '' # character selection for Braille tile(s) (if chosen) -size_permutations = False # generate models for all size options? -size_option = -1 # size option as int index - not required if size_permutations -colour_permutations = False # generate models for all colour options? -colour_option = '' # colour option as str or int index - not required if colour_permutations -show_braille = elem_visibility.VISIBLE # how should Braille be shown? -show_let = elem_visibility.VISIBLE # EMBOSSED # how should plaintext be shown? -show_num = elem_visibility.HIDDEN # how should ordinality be shown? -# assembly component spacing -dx = 5 # horizontnal -dy = 10 # vertical +""" -# METHODS - -def generate(my_option = -1, my_select = '', size_permutations = False, size_option = -1, colour_permutations = False, colour_option = 'Purple', show_braille = elem_visibility.VISIBLE, show_let = elem_visibility.VISIBLE, show_num = elem_visibility.HIDDEN, dx = 5, dy = 10, path_folder_cmd = 'C:\\"Program Files"\\OpenSCAD\\openscad', path_folder = "C:\\Users\\edwar\\OneDrive\\Documents\\Programming\\Python Scripts\\"): -# FUNCTION - # generate Braille model(s) -# ARGUMENTS - # int my_option - index of product option - if not valid, user console input will be required - # str my_select - character selection for Braille tile(s) (if chosen) - # bool size_permutation - - # int size_option - index of product_sizes option - ignored if size_permutations - # # bool colour_permutation - # elem_visibility show_braille - # elem_visibility show_let - # elem_visibility show_num - # float dx - # float dy - # str path_folder_cmd - # str path_folder -# VARIABLE INSTANTIATION - _m ='generate' -# ARGUMENT VALIDATION - av.val_int(my_option, 'my_option', _m) - av.val_str(my_select, 'my_select', _m) - av.val_bool(size_permutations, 'size_permutations', _m) - av.val_int(size_option, 'size_option', _m) - av.val_bool(colour_permutations, 'colour_permutations', _m) - # av.val_type(show_braille, "", 'show_braille', _m) - # av.val_type(show_let, "", 'show_let', _m) - # av.val_type(show_num, "", 'show_num', _m) - av.val_type(show_braille, "", 'show_braille', _m) - av.val_type(show_let, "", 'show_let', _m) - av.val_type(show_num, "", 'show_num', _m) - av.val_int(dx, 'dx', _m) - av.val_int(dy, 'dy', _m) - av.val_str(path_folder_cmd, 'path_folder_cmd', _m) - av.val_str(path_folder, 'path_folder', _m) -# METHODS - mystyle = style(show_braille, show_let, show_num) - # Get Braille dictionary + delimiters - braille_translations = get_braille_translations() - # Get list of products that can be generated - products = gen_product_inputs(braille_translations) - # input product selection from user and translate to braille - my_product = input_product(braille_translations, products, my_option, my_select) # my_option) - # get list of product size configurations - sizes_product = gen_scrabble_sizes() - # generate product size (and content for Scrabble tile array) permutations - mymsgs, myszs = gen_product_permutations(my_product, sizes_product, size_permutations, size_option) - # get product colour selection - colour_themes = input_colour_themes(colour_permutations, colour_option) - # generate openscad, stl, and png files of selected product(s) - gen_3d_models(braille_translations, my_product, mymsgs, myszs, my_product.line_length, path_folder, path_folder_cmd, mystyle, colour_themes) - # generate assembly of products for promotional content, as scad + png - gen_snippet_assembly(dx, dy, my_product.line_length, colour_themes, myszs, my_product, path_folder, path_folder_cmd, mystyle) - -# generate() -# generate(1, 'A') -generate(my_option, my_select, size_permutations, size_option, colour_permutations, colour_option, show_braille, show_let, show_num, dx, dy, path_folder_cmd, path_folder) -# generate(my_option, my_select, size_permutations, size_option, colour_permutations, colour_option, elem_visibility.VISIBLE, elem_visibility.VISIBLE, elem_visibility.VISIBLE, dx, dy, path_folder_cmd, path_folder) \ No newline at end of file +if __name__ == '__main__': + print() + print('Welcome to your 3D Braille Model Generator') + print("At any time, answer the following error code to exit (excl. speech marks): '#!ERRORCODE!#'") + print() + product = Product_Braille.input_from_console() + product.make_files() diff --git a/model_gen/model_braille.py b/model_gen/model_braille.py new file mode 100644 index 0000000..96e6d6c --- /dev/null +++ b/model_gen/model_braille.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- +""" +@author: Edward Middleton-Smith +""" + +class Model_Braille(): + # \ No newline at end of file diff --git a/model_gen/openscad_objects.py b/model_gen/openscad_objects.py index 9b7a65a..6328381 100644 --- a/model_gen/openscad_objects.py +++ b/model_gen/openscad_objects.py @@ -7,29 +7,16 @@ Created on Thu Apr 27 12:03:30 2023 Procedural OpenSCAD Generation https://github.com/taxpon/openpyscad/blob/develop/openpyscad/base.py """ +#import argument_validation as av +from colour_theme_braille_character import Colour_Theme_Character_Braille -# CLASSES -# ATTRIBUTE DECLARATION -# METHODS - # FUNCTION - # ARGUMENTS - # ARGUMENT VALIDATION - # ATTRIBUTE + VARIABLE INSTANTIATION - # METHODS - # RETURNS - -# NORMAL METHODS -# FUNCTION -# ARGUMENTS -# ARGUMENT VALIDATION -# VARIABLE INSTANTIATION -# METHODS -# RETURNS - - -import openpyscad as ops -import argument_validation as av - +# import openpyscad as ops +from openpyscad import Union +from typing import Optional +from pydantic import BaseModel, Field, validator +# from pydantic.fields import ModelField +from abc import ABC, abstractmethod +import os def bool_2_str(mybool): # FUNCTION @@ -103,7 +90,7 @@ def triprism(a, L, centre = True): # RETURNS return ops.Polygon([[0,0], [0, a], [a, 0]]).linear_extrude(L, center = bool_2_str(centre)).translate([-a/2 if centre else 0, -a/3 if centre else 0, 0]) -def gen_openscad_colours(): +def get_openscad_colours(): return [ # openscad_colours = [ "Lavender", "Thistle", @@ -246,4 +233,84 @@ def gen_openscad_colours(): "SlateGray", "DarkSlateGray", "Black" - ] \ No newline at end of file + ] + +""" +def base_fillet_cube(a, b, c, f, q, centre = "true"): + # fillets removed as they print horribly + # now just cube + my_dif = ops.Difference(); + my_dif.append(ops.Cube([a, b, c], center = "true", _fn = q)); + return my_dif.translate([0 if (centre == "true") else a/2, 0 if (centre == "true") else b/2, 0 if (centre == "true") else c/2]) + + +def triprism(a, L, centre = "true"): + return ops.Polygon([[0,0], [0, a], [a, 0]]).linear_extrude(L, center = "true").translate([0, 0, 0 if (centre == "true") else L/2]); +""" + +""" +def __get_pydantic_core_schema__(cls, handler): + return handler.generate_schema(ops.Union) + +ops.Union.__get_pydantic_core_schema__ = classmethod(__get_pydantic_core_schema__) +class Union_Field(ModelField): + def __init__(self, **kwargs): + super().__init__(**kwargs) + @classmethod + def __get_validators__(cls): + yield cls.validate + @classmethod + def validate(cls, value): + if not isinstance(value, Union): + raise ValueError(f'Union_Field: {value} is not a valid Union. Type: {type(value)}') + return value +""" + +class ObjectOpenSCAD(BaseModel, ABC): + path_dir: str + filename: str + + def __init__(self, **kwargs): # , path_dir, filename + # print(f'ObjectOpenSCAD: {path_dir}, {filename}') + # BaseModel.__init__(self, path_dir=path_dir, filename=filename) + # super().__init__(path_dir=path_dir, filename=filename, **kwargs) + BaseModel.__init__(self, **kwargs) + + @validator('path_dir') + def validate_path_dir(cls, value): + if not os.path.exists(value): + raise ValueError("Path not found: " + value) + return value + + @abstractmethod + def write(self): + pass + +class ModelOpenSCAD(ObjectOpenSCAD): # , BaseModel): + colour_theme: Colour_Theme_Character_Braille + fn: int = 25 + + model: Optional[Union] = None #= Field(default_factory=Union) # : Optional[ops.Union] = None + + def __init__(self, **kwargs): # , path_dir, filename, colour_theme, fn): + # print(f'ModelOpenSCAD: {path_dir}, {filename}, {colour_theme}, {fn}') + ObjectOpenSCAD.__init__(self, **kwargs) # , path_dir=path_dir, filename=filename) + BaseModel.__init__(self, **{**kwargs, 'model': None}) # , colour_theme=colour_theme, fn=fn) + self.model = Union() + + def write(self): + self.model.write(self.path_dir + self.filename + '.scad') + + class Config: + arbitrary_types_allowed = True + +class AssemblyOpenSCAD(ObjectOpenSCAD): # , BaseModel): + dx: int + dy: int + max_models_per_row: int + fn: int = Field(ge=0) + + def __init__(self, path_dir, filename, dx, dy, max_models_per_row, fn=25): + ObjectOpenSCAD.__init__(self, path_dir, filename) + BaseModel.__init__(self, dx, dy, max_models_per_row, fn) + self.assembly = ops.Assembly() \ No newline at end of file diff --git a/model_gen/product_braille.py b/model_gen/product_braille.py new file mode 100644 index 0000000..f5c549b --- /dev/null +++ b/model_gen/product_braille.py @@ -0,0 +1,278 @@ +# -*- coding: utf-8 -*- +""" +@author: Edward Middleton-Smith +""" + +import openpyscad as ops +import numpy as np +# import argument_validation as av +# from openscad_objects import get_openscad_colours +from character_braille import Character_Braille +from keyboard_3d import Keyboard_3D, Size_Character_Braille, Style_Character_Braille, Enum_Justification_Text +from array_keyboard_3d import Array_Keyboard_3D +from colour_theme_braille_character import Colour_Theme_Character_Braille +from translation_braille import Translation_Braille, Enum_Braille_Proficiency_Level + +from typing import Optional, Union, List +from prettytable import PrettyTable +from enum import Enum +from pydantic import BaseModel, Field, ValidationError, validate_arguments +# from color import Color + +class Product_Braille(BaseModel): + name: str + """ + line_length: int # number of Braille characters per line on keyboard + msg: str # pre-translated English (with necessary modifications for input to this programme e.g. splitting up undesired translations with hidden delimiter character @?NOTHING) + msg_prefix: str # additional pre-translated str as above to pre-append to product for adding header to creation of product messages from dictionary queries + filename: str # filename - name without spaces + """ + keyboards: Array_Keyboard_3D + + def __init__(self, name, keyboards, **kwargs): + BaseModel.__init__(self, name=name, keyboards=keyboards, **kwargs) + """ + def __new__(cls, name, line_length, msg, msg_prefix = '', filename = ''): + # FUNCTION + # Initialise class object + # ARGUMENTS + # str name + # int line_length + # str msg + # str msg_prefix + # ARGUMENT VALIDATION + _m = 'product.__new__' + v_arg_type = 'class attribute' + av.val_str(name, 'name', _m, 1, -1, v_arg_type = v_arg_type) + av.val_int(line_length, 'line_length', _m, 1, v_arg_type = v_arg_type) + av.val_str(msg, 'msg', _m, -1, -1, v_arg_type = v_arg_type) + av.val_str(msg_prefix, 'msg_prefix', _m, -1, -1, v_arg_type = v_arg_type) + av.val_str(filename, 'filename', _m, -1, -1, v_arg_type = v_arg_type) + # if not av.val_str(name): + # raise ValueError(av.error_msg_str('product.__new__', 'name', name, 'attribute')) + # if not av.val_int(line_length, 1): + # raise ValueError(av.error_msg_str('product.__new__', 'line_length', line_length, 'attribute')) + # if not av.val_str(msg): + # raise ValueError(av.error_msg_str('product.__new__', 'msg', msg, 'attribute')) + # if not av.val_str(msg_prefix): + # raise ValueError(av.error_msg_str('product.__new__', 'msg_prefix', msg_prefix, 'attribute')) + # RETURNS + return super(product, cls).__new__(cls) + + def __init__(self, name, line_length, msg, msg_prefix = '', filename = ''): + # FUNCTION + # Construct class object + # ARGUMENTS + # str name + # int line_length + # str msg + # str msg_prefix + # ARGUMENT VALIDATION + # see __new__() + # ATTRIBUTE + VARIABLE INSTANTIATION + self.name = name + self.line_length = line_length + self.msg = msg + self.msg_prefix = msg_prefix # for procedurally-generated messages from difficulty selection + self.filename = name.replace(' ', '_') if filename == '' else filename + def __repr__(self): + return f"name = {self.name}, line_length = {self.line_length}, msg = {self.msg}, msg_prefix = {self.msg_prefix}, filename = {self.filename}" + + size_characters: Size_Character_Braille + style_characters: Style_Character_Braille + colour_theme: Colour_Theme_Character_Braille + style_keyboard: Style_Keyboard_Braille + path_dir: str + # filename: str + characters: List[Character_Braille] + max_characters_per_row: int + + """ + + def get_defaults(): + sizes_default = Size_Character_Braille.get_defaults() + size_default = sizes_default[5] + print(f'type of size_default: {str(type(size_default))}') + style_default = Style_Character_Braille.get_default() + print(f'type of style_default: {str(type(style_default))}') + colour_default = Colour_Theme_Character_Braille.get_default() + print(f'type of colour_default: {str(type(colour_default))}') + # colour_default = colours_default[0] + justification_default = Enum_Justification_Text(0) + print(f'type of justification_default: {str(type(justification_default))}') + proficiency_level_default = Enum_Braille_Proficiency_Level(1) + print(f'type of proficiency_level_default: {str(type(proficiency_level_default))}') + path_dir = "C:\\Users\\edwar\\OneDrive\\Documents\\Programming\\Python Scripts\\Braille\\models_3d" + print(f'type of path_dir: {str(type(path_dir))}') + defaults = [] + + translation_extended_alphabet = Translation_Braille("abcdefg@?NOTHINGhijKLMNOPQRS@?NOTHINGTUVXYZANDFOROFTHEWITHCHGHSHTHWHEDEROUOWWEABBCCDDENFF?GGINBY", proficiency_level_default) + print(f'type of translation_extended_alphabet: {str(type(translation_extended_alphabet))}') + # keyboard_extended_alphabet = Keyboard_3D(size_characters=size_default, style_characters=style_default, colour_theme=colour_default, justification_text=justification_default, path_dir=path_dir, max_characters_per_row=10, translation=translation_extended_alphabet, fn=25) + defaults.append(Product_Braille("Extended Alphabet", + # [keyboard_extended_alphabet] + Array_Keyboard_3D( + sizes_characters = [size_default], + styles_characters = [style_default], + colour_themes = [colour_default], + justifications_text = [justification_default], + path_dir= path_dir, + max_characters_per_rows = [10], + translations = [translation_extended_alphabet], + fn = 25 + ) + )) + defaults.append(Product_Braille("Upper Groupsigns", + # [keyboard_extended_alphabet] + Array_Keyboard_3D( + sizes_characters = [size_default], + styles_characters = [style_default], + colour_themes = [colour_default], + justifications_text = [justification_default], + path_dir= path_dir, + max_characters_per_rows = [10], + translations = [Translation_Braille("uppe@?nothingr@?BLANK_SPACEGRO@?NOTHINGUPSIGNsand:a@?nothingn@?nothingd@?BLANK_SPACEfor:fo@?nothingr@?BLANK_SPACEof:o@?nothingf@?BLANK_SPACEthe:t@?nothingh@?nothinge@?BLANK_SPACEwith:wi@?nothingt@?nothingh@?BLANK_SPACE"+"@?NEWLINECH:C@?NOTHINGH@?BLANK_SPACE" + "GH:G@?NOTHINGH@?BLANK_SPACE" + "SH:S@?NOTHINGH@?BLANK_SPACE@?BLANK_SPACE" + "TH:T@?NOTHINGH@?BLANK_SPACE" + "WH:W@?NOTHINGH@?BLANK_SPACE" + "ED:E@?NOTHINGD@?BLANK_SPACE@?BLANK_SPACE" + "ER:E@?NOTHINGR@?BLANK_SPACE" + "OU:O@?NOTHINGU@?BLANK_SPACE" + "OW:O@?NOTHINGW@?BLANK_SPACE@?BLANK_SPACE"+"st:s@?nothingt@?BLANK_SPACEar:a@?nothingr@?BLANK_SPACEble:bl@?nothinge@?BLANK_SPACE@?BLANK_SPACEing:i@?nothingng", proficiency_level_default)], + fn = 25 + ) + )) + # defaults.append(Product_Braille("Upper Wordsigns", [Keyboard_3D(size_default, style_default, colour_default, justification_default, path_dir, 24, gen_difficulty_msgstr(braille_dict, difficulty(3)), 25)])) + defaults.append(Product_Braille("Alphabet", + # [keyboard_extended_alphabet] + Array_Keyboard_3D( + sizes_characters = [size_default], + styles_characters = [style_default], + colour_themes = [colour_default], + justifications_text = [justification_default], + path_dir= path_dir, + max_characters_per_rows = [10], + translations = [Translation_Braille("ABCDEFG@?NOTHINGHIJKLMNOPQRSTUVWXYZ", proficiency_level_default)], + fn = 25 + ) + )) + # defaults.append(Product_Braille("Travel", [Keyboard_3D(size_default, style_default, colour_default, justification_default, path_dir, 5, Translation_Braille("ABCDEFG@?NOTHINGHIJ", proficiency_level_default), 25)])) + defaults.append(Product_Braille("Demo", + # [keyboard_extended_alphabet] + Array_Keyboard_3D( + sizes_characters = [size_default], + styles_characters = [style_default], + colour_themes = [colour_default], + justifications_text = [justification_default], + path_dir= path_dir, + max_characters_per_rows = [9], + translations = [Translation_Braille("BRAILLE", proficiency_level_default)], + fn = 25 + ) + )) + defaults.append(Product_Braille("Scrabble Alphabet of Tiles", + # [keyboard_extended_alphabet] + Array_Keyboard_3D( + sizes_characters = [size_default], + styles_characters = [style_default], + colour_themes = [colour_default], + justifications_text = [justification_default], + path_dir= path_dir, + max_characters_per_rows = [1], + translations = [Translation_Braille("uppe@?nothingr@?BLANK_SPACEGRO@?NOTHINGUPSIGNsand:a@?nothingn@?nothingd@?BLANK_SPACEfor:fo@?nothingr@?BLANK_SPACEof:o@?nothingf@?BLANK_SPACEthe:t@?nothingh@?nothinge@?BLANK_SPACEwith:wi@?nothingt@?nothingh@?BLANK_SPACE"+"@?NEWLINECH:C@?NOTHINGH@?BLANK_SPACE" + "GH:G@?NOTHINGH@?BLANK_SPACE" + "SH:S@?NOTHINGH@?BLANK_SPACE@?BLANK_SPACE" + "TH:T@?NOTHINGH@?BLANK_SPACE" + "WH:W@?NOTHINGH@?BLANK_SPACE" + "ED:E@?NOTHINGD@?BLANK_SPACE@?BLANK_SPACE" + "ER:E@?NOTHINGR@?BLANK_SPACE" + "OU:O@?NOTHINGU@?BLANK_SPACE" + "OW:O@?NOTHINGW@?BLANK_SPACE@?BLANK_SPACE"+"st:s@?nothingt@?BLANK_SPACEar:a@?nothingr@?BLANK_SPACEble:bl@?nothinge@?BLANK_SPACE@?BLANK_SPACEing:i@?nothingng", proficiency_level_default)], + fn = 25 + ) + )) + defaults.append(Product_Braille("Scrabble Character Tile", + # [keyboard_extended_alphabet] + Array_Keyboard_3D( + sizes_characters = [size_default], + styles_characters = [style_default], + colour_themes = [colour_default], + justifications_text = [justification_default], + path_dir= path_dir, + max_characters_per_rows = [1], + translations = [Translation_Braille("uppe@?nothingr@?BLANK_SPACEGRO@?NOTHINGUPSIGNsand:a@?nothingn@?nothingd@?BLANK_SPACEfor:fo@?nothingr@?BLANK_SPACEof:o@?nothingf@?BLANK_SPACEthe:t@?nothingh@?nothinge@?BLANK_SPACEwith:wi@?nothingt@?nothingh@?BLANK_SPACE"+"@?NEWLINECH:C@?NOTHINGH@?BLANK_SPACE" + "GH:G@?NOTHINGH@?BLANK_SPACE" + "SH:S@?NOTHINGH@?BLANK_SPACE@?BLANK_SPACE" + "TH:T@?NOTHINGH@?BLANK_SPACE" + "WH:W@?NOTHINGH@?BLANK_SPACE" + "ED:E@?NOTHINGD@?BLANK_SPACE@?BLANK_SPACE" + "ER:E@?NOTHINGR@?BLANK_SPACE" + "OU:O@?NOTHINGU@?BLANK_SPACE" + "OW:O@?NOTHINGW@?BLANK_SPACE@?BLANK_SPACE"+"st:s@?nothingt@?BLANK_SPACEar:a@?nothingr@?BLANK_SPACEble:bl@?nothinge@?BLANK_SPACE@?BLANK_SPACEing:i@?nothingng", proficiency_level_default)], + fn = 25 + ) + )) + return defaults + + def input_from_console(): # (braille_dict, products, my_option: Optional[int] = -1, my_select: Optional[str] = ''): + products = Product_Braille.get_defaults() + count_products = len(products) + print('Braille Products:') + for i in range(count_products): + print(f"{i + 1}. {products[i].name}") + print() + known_translations = Translation_Braille.get_defaults() # Character_Braille.get_Translation_Brailles() + while True: + index_selected = input(f"Please enter your selection (1 - {count_products}) from the products above\n") #, 'select_i' + print(index_selected + " selected") + if index_selected == '#!ERRORCODE!#': + exit + try: + index_selected = int(index_selected) + # if index_selected is not int: + except: + print('not int') + continue + if index_selected < 1 or index_selected > count_products: + print('out of range') + continue + product_selected = products[index_selected - 1] + if index_selected == count_products: + while True: + plaintext = str(input("Please enter a character selection for your Scrabble tile\n")) + print(plaintext + " selected") + if plaintext == '#!ERRORCODE!#': + exit + if plaintext is not str: + continue + """ + if len(plaintext) != 1: + continue + """ + if not known_translations.apply(lambda x: x.plaintext == plaintext).any(): + continue + translation = known_translations.apply(lambda x: x if x.plaintext == plaintext else None).dropna().values[0] + product_selected.keyboard = Keyboard_3D(product_selected.keyboard.size_characters, product_selected.keyboard.style_characters, product_selected.keyboard.colour_theme, product_selected.keyboard.justification_text, product_selected.keyboard.path_dir, translation, product_selected.keyboard.max_characters_per_row) + break + """ + for keyboard in product_selected.keyboards: + keyboard.size_characters = Size_Character_Braille.input_from_console() + keyboard.style_characters = Style_Character_Braille.input_from_console() + keyboard.colour_theme = Colour_Theme_Character_Braille.input_from_console() + keyboard.justification_text = Enum_Justification_Text.input_from_console() + """ + sizes_characters = Size_Character_Braille.input_many_from_console(Size_Character_Braille) + styles_characters = Style_Character_Braille.input_many_from_console(Style_Character_Braille) + colour_themes = Colour_Theme_Character_Braille.input_many_from_console(Colour_Theme_Character_Braille) + justifications_text = Enum_Justification_Text.input_many_from_console() + product_selected.keyboards.update_configurations_styles(sizes_characters, styles_characters, colour_themes, justifications_text) + print(product_selected.__repr__() + " selected") + return product_selected + + """ + def append_ifnotNone(v_list, v_item): + # FUNCTION + # append v_item to v_list if v_item is not None + # ARGUMENTS + # list v_list + # v_item + # ARGUMENT VALIDATION + if (not av.val_list(v_list, 'v_list', 'append_ifnotNone', suppress_errors = True)) or v_item == None: + # RETURNS + return v_list + v_list.append(v_item) + return v_list#.append(v_item) + """ + + + def make_combined_assembly(self, dx, dy, max_keyboards_per_row): + self.keyboards.make_combined_assembly(dx, dy, max_keyboards_per_row) + + def make_files_openscad(self): + self.keyboards.make_files_openscad() + + def make_files_stl(self): + self.keyboards.make_files_stl() + + def make_files_png(self): + self.keyboards.make_files_png() + + def make_files(self): + self.keyboards.make_files() diff --git a/model_gen/translate_braille_2_scad.py b/model_gen/translate_braille_2_scad.py deleted file mode 100644 index c538439..0000000 --- a/model_gen/translate_braille_2_scad.py +++ /dev/null @@ -1,664 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Created on Wed Apr 26 17:11:57 2023 - -@author: Edward Middleton-Smith - -Braille 3D Model Product Creation - -Plaintext message translation into Braille for 3D modelling - -Procedural OpenSCAD Generation -Braille Scrabble Pieces -""" - -# CLASSES -# ATTRIBUTE DECLARATION -# METHODS - # FUNCTION - # ARGUMENTS - # ARGUMENT VALIDATION - # ATTRIBUTE + VARIABLE INSTANTIATION - # METHODS - # RETURNS - -# NORMAL METHODS -# FUNCTION -# ARGUMENTS -# ARGUMENT VALIDATION -# VARIABLE INSTANTIATION -# METHODS -# RETURNS - - -import openpyscad as ops -import numpy as np -import argument_validation as av -from openscad_objects import gen_openscad_colours -from typing import Optional -from prettytable import PrettyTable -from enum import Enum - - -class elem_visibility(Enum): - EMBOSSED = -1 - HIDDEN = 0 - VISIBLE = 1 - def mini(): - # FUNCTION - # Get minimum value in enumerator - # RETURNS - return min([e.value for e in elem_visibility]) - def maxi(): - # FUNCTION - # Get maximum value in enumerator - # RETURNS - return max([e.value for e in elem_visibility]) - -class style(): -# ATTRIBUTE DECLARATION - braille: elem_visibility - letter: elem_visibility - number: elem_visibility - - def __new__(cls, braille, letter, number): - _m = 'style.__new__' - av.val_type(braille, "", 'braille', _m) - av.val_type(braille, "", 'braille', _m) - av.val_type(braille, "", 'braille', _m) - return super(style, cls).__new__(cls) - - def __init__(self, braille, letter, number): - self.braille = braille - self.letter = letter - self.number = number - - def gen_filetxt(mystyle): - # FUNCTION - # generate filename text for style settings - # ARGUMENTS - # style mystyle - # ARGUMENT VALIDATION - av.val_type(mystyle, "", 'mystyle', 'get_style_filetxt') - # VARIABLE INSTANTIATION - style_txt = '_0b' if (mystyle.braille == elem_visibility.HIDDEN) else '' - style_txt += '_0l' if (mystyle.letter == elem_visibility.HIDDEN) else '' - style_txt += '__l' if (mystyle.letter == elem_visibility.EMBOSSED) else '' - style_txt += '_0n' if (mystyle.number == elem_visibility.HIDDEN) else '' - # RETURNS - return style_txt - -def base_fillet_cube(a, b, c, f, q, centre = "true"): - # fillets removed as they print horribly - # now just cube - my_dif = ops.Difference(); - my_dif.append(ops.Cube([a, b, c], center = "true", _fn = q)); - return my_dif.translate([0 if (centre == "true") else a/2, 0 if (centre == "true") else b/2, 0 if (centre == "true") else c/2]) - - -def triprism(a, L, centre = "true"): - return ops.Polygon([[0,0], [0, a], [a, 0]]).linear_extrude(L, center = "true").translate([0, 0, 0 if (centre == "true") else L/2]); - - -class scrabble_dimensions: -# ATTRIBUTE DECLARATION - name: str - dp: float # distance between dots - hblock: float # height of - s: float # spacing between keys on keyboard - base_height: float # height of - hcyl: float # height of Braille dots - rcyl: float # base radius of Braille dots - rsphere: float # top radius of Braille dots - -# METHODS - def __new__(cls, name, dp, hblock, s, base_height, hcyl, rcyl, rsphere): - # FUNCTION - # Initialise class object - # ARGUMENTS - # str name - name size scheme - # float dp - distance between braille pins - # float hblock - height of base of each key - # float s - spacing - # float base_height - height of base block - board - # float hcyl - height of braille pins - # float rcyl - base radius of braille pins - # float rsphere - tip radius of braille pins - # ARGUMENT VALIDATION - _m = 'scrabble_dimensions.__new__' - v_arg_type = 'class attribute' - av.val_str(name, 'name', _m, 1, v_arg_type = v_arg_type) - av.full_val_float(dp, 'dp', _m, 0, v_arg_type = v_arg_type) - av.full_val_float(hblock, 'hblock', _m, v_arg_type = v_arg_type) - av.full_val_float(s, 's', _m, 0, v_arg_type = v_arg_type) - av.full_val_float(base_height, 'base_height', _m, 0, v_arg_type = v_arg_type) - av.full_val_float(hcyl, 'hcyl', _m, 0, v_arg_type = v_arg_type) - av.full_val_float(rcyl, 'rcyl', _m, 0, v_arg_type = v_arg_type) - av.full_val_float(rsphere, 'rsphere', _m, 0, v_arg_type = v_arg_type) - # RETURNS - return super(scrabble_dimensions, cls).__new__(cls) - - def __init__(self, name, dp, hblock, s, base_height, hcyl, rcyl, rsphere): - # FUNCTION - # Construct class object - # ARGUMENTS - # str name - # float dp - # float hblock - # float s - # float base_height - # float hcyl - # float rcyl - # float rsphere - # ARGUMENT VALIDATION - # see __new__() - # ATTRIBUTE INSTANTIATION - self.name = name - self.dp = dp - self.hblock = hblock - self.s = s - self.base_height = base_height - self.hcyl = hcyl - self.rcyl = rcyl - self.rsphere = rsphere - - def __repr__(self): - # FUNCTION - # Convert object to str representation - # RETURNS - return f"name = {self.name}, dp = {self.dp}, hblock = {self.hblock}, s = {self.s}, base_height = {self.base_height}, hcyl = {self.hcyl}, rcyl = {self.rcyl}, rsphere = {self.rsphere}" - - def as_dict(self): - # FUNCTION - # Convert object attribute, value pairs to dictionary representation - # RETURNS - return {'name': self.name, 'dp': self.dp, 'hblock': self.hblock, 's': self.s, 'base_height': self.base_height, 'hcyl': self.hcyl, 'rcyl': self.rcyl, 'rsphere': self.rsphere} - - -# colour themes: # ToDo: include in arguments to generator!! -class export_colour_theme: -# ATTRIBUTE DECLARATION - name: str - coltop: str - colbase: str - -# METHODS - def __new__(cls, name, coltop, colbase, openscad_colours): - # FUNCTION - # Initialise class object - # ARGUMENTS - # str name - user reference to colour theme - # str coltop - a valid openSCAD colour e.g. '#010101' - # str colbase - a valid openSCAD colour e.g. 'blue' - # list[str] openscad_colours - # ARGUMENT VALIDATION - _m = 'export_colour_theme.__new__' - v_arg_type = 'class attribute' - av.val_str(name, 'name', _m, 1, v_arg_type = v_arg_type) - av.val_list(openscad_colours, 'openscad_colours', _m, "", 1, v_arg_type = v_arg_type) - if not validate_openscad_colour(coltop, openscad_colours): - raise ValueError(f"Invalid export_colour_theme attribute coltop. Type = {str(type(coltop))}. Value = {coltop}") - if not validate_openscad_colour(colbase, openscad_colours): - raise ValueError(f"Invalid export_colour_theme attribute colbase. Type = {str(type(colbase))}. Value = {colbase}") - # RETURNS - return super(export_colour_theme, cls).__new__(cls) - - def __init__(self, name, coltop, colbase, openscad_colours): - # FUNCTION - # Initialise class object - # ARGUMENTS - # str name - user reference to colour theme - # str coltop - a valid openSCAD colour e.g. '#010101' - # str colbase - a valid openSCAD colour e.g. 'blue' - # list[str] openscad_colours # redundant in this function - used for argument validation - # ARGUMENT VALIDATION - # see __new__() - # ATTRIBUTE INSTANTIATION - self.name = name - self.top = coltop - self.base = colbase - - def __repr__(self): - # FUNCTION - # Convert object to str representation - # RETURNS - return f"name = {self.name}, colour top = {self.top}, colour base = {self.base}" # , openscad_colours = {self.openscad_colours} - - def as_dict(self): - # FUNCTION - # Convert object attribute, value pairs to dictionary representation - # RETURNS - return {'name': self.name, 'colour top': self.top, 'colour base': self.base} # , 'openscad_colours': self.openscad_colours - - def as_row(self): - # FUNCTION - # Convert object values to list representation - # RETURNS - return [self.name, self.top, self.base] # , 'openscad_colours': self.openscad_colours - - -def gen_scrabble_sizes(s: Optional[float] = 0.5): - # default scrabble sizes - # s = 1/2 - # def __init__(self, name, dp, hblock, s, base_height, hcyl, rcyl, rsphere): - k = 2.3622 - szs_scrabble = [] - szs_scrabble.append(scrabble_dimensions('sz_1', 2.5, 2*s, s, 4*s, 1.2, 2/3, 1/2)) - szs_scrabble.append(scrabble_dimensions('sz_2', 4, 1.28, s, 4*s, 1.2, 3/2, 1)) - szs_scrabble.append(scrabble_dimensions('sz_3', 8, 2.5, s, 6*s, 1.2, 3/2, 1)) - szs_scrabble.append(scrabble_dimensions('sz_4', 10, 3, 1, 6*s, 1.2, 3/2, 1)) - szs_scrabble.append(scrabble_dimensions('sz_5', 10, 1, 1, 6*s, 1.2, 3/2, 1)) - szs_scrabble.append(scrabble_dimensions('keyboard', 2.5, 0.8, 0.5, 4, 1.2, 2/3, 0.5)) - szs_scrabble.append(scrabble_dimensions('poster', 2.5, 0.8, 0.5, 2, 1.2, 2/3, 0.5)) - szs_scrabble.append(scrabble_dimensions('poster_big', 2.5*k, 0.8, 0.5*k, 2, 1.2, 2/3*k, 0.5*k)) - # print('szs_scrabble') - # print(szs_scrabble) - return szs_scrabble # pd.DataFrame([x.as_dict() for x in szs_scrabble]) - - -def input_product_size(szs_product, v_size = 2): -# FUNCTION - # input valid product size from user -# ARGUMENTS - # list[scrabble_dimensions] szs_product - # int v_size -# ARGUMENT VALIDATION - _m = 'get_product_size' - av.val_list(szs_product, 'szs_product', _m, "") - av.val_int(v_size, 'v_size', _m) -# VARIABLE INSTANTIATION - n = len(szs_product) -# METHODS - if v_size > 0 and v_size <= n: - return szs_product[v_size - 1] - my_table = PrettyTable() - my_table.field_names = ['index', 'name', 'dp', 'hblock', 's', 'base_height', 'hcyl', 'rcyl', 'rsphere'] - for i in range(n): - prod = szs_product[i] - my_table.add_row([i + 1, prod.name, prod.dp, prod.hblock, prod.s, prod.base_height, prod.hcyl, prod.rcyl, prod.rsphere]) - print() - print("Please select product dimensions configuration from below:") - print(my_table) - # loopy = False - while True: - my_input = input("Product dimensions configuration (name or index): ") - if my_input == "#!ERRORCODE!#": exit - for i in range(n): - if validate_input_product_size(my_input, szs_product): - # loopy = True -# RETURNS - return get_product_size(my_input, szs_product) - - -def get_product_size(product_option, szs_product): -# FUNCTION - # get valid product size from list of scrabble_dimensions -# ARGUMENTS - # str/int product_option - # list[scrabble_dimensions] szs_product -# ARGUMENT VALIDATION - _m = 'get_product_size' - error_msg = av.error_msg_str(_m, product_option, 'product_option', 'scrabble_dimensions identifier') - if not (av.val_int(product_option, 'product_option', _m, suppress_errors = True, suppress_console_outputs = True) or av.val_str(product_option, 'product_option', _m, suppress_errors = True, suppress_console_outputs = True)): - raise ValueError(error_msg) - av.val_list(szs_product, 'szs_product', _m, "") -# VARIABLE INSTANTIATION - n = len(szs_product) -# METHODS - if av.full_val_int(product_option, 'product_option', _m, suppress_errors = True): - product_option = av.input_int(product_option, 'product_option', _m) - return szs_product[product_option - 1] - for col_i in range(n): - my_product = szs_product[col_i] - if product_option == my_product.name: - return my_product -# RETURNS - raise ValueError(error_msg) - - -def validate_input_product_size(product_option, szs_product): -# FUNCTION - # evaluate if product_option relates to a szs_product -# ARGUMENTS - # str/int product_option - # list[scrabble_dimensions] szs_product -# ARGUMENT VALIDATION - _m = 'validate_input_product_size' - if not (av.val_int(product_option, 'product_option', _m, suppress_errors = True, suppress_console_outputs = True) or av.val_str(product_option, 'product_option', _m, suppress_errors = True, suppress_console_outputs = True)): return False - av.val_list(szs_product, 'szs_product', _m, "") -# VARIABLE INSTANTIATION - n = len(szs_product) -# METHODS - if av.full_val_int(product_option, 'product_option', _m, suppress_errors = True): - product_option = av.input_int(product_option, 'product_option', _m) - return (0 < product_option and product_option <= n) - for prod_i in range(n): - if product_option == szs_product[prod_i].name: - return True -# RETURNS - return False - - -def validate_openscad_colour(mycolour, openscad_colours): -# FUNCTION - # validate argument openscad colour as string -# ARGUMENTS - # str mycolour - to be validated - # list[str] openscad_colours - to search through -# ARGUMENT VALIDATION - _m = 'validate_openscad_colour' - av.val_str(mycolour, 'mycolour', _m) - av.val_list(openscad_colours, 'openscad_colours', _m, "") -# VARIABLE INSTANTIATION - N = len(mycolour) -# METHODS - if (N == 7): - if (mycolour[0] == '#' and mycolour[0:5].isnumeric): - return True - for i in range(len(openscad_colours)): - if (mycolour == openscad_colours[i]): - return True -# RETURNS - return False - - -# inputs -# path_scad = "C:/Users/edwar/OneDrive/Documents/OpenSCAD" -# path_stl = "C:/Users/edwar/OneDrive/Documents/OpenSCAD/STL" -# filename = "Braille_Scrabble_" -# cum = [0, 1] -# letters = ["B"] -# braille = [[2]] -# braille = [[[1, 1, 0, 0, 0, 0]]] -# lmsg = 1 -# N = 1 -# n_row_keys = 1 -# maxln = 2 - -def gen_col_themes(): -# FUNCTION - # create colour themes for image export of 3D models -# REQUIRES - # class export_colour_theme - # function gen_openscad_colours -# VARIABLE INSTANTIATION - openscad_colours = gen_openscad_colours() - col_themes = [] - col_themes.append(export_colour_theme("Blue", "#337AFF", "#337AFF", openscad_colours)) - col_themes.append(export_colour_theme("Purple", "#8E44AD", "#8E44AD", openscad_colours)) - col_themes.append(export_colour_theme("Red", "#F7322F", "#F7322F", openscad_colours)) - col_themes.append(export_colour_theme("Black", "Black", "#17202A", openscad_colours)) - col_themes.append(export_colour_theme("White", "White", "White", openscad_colours)) -# RETURNS - # list[export_colour_theme] col_themes - colour themes with name, top colour, base colour - return col_themes - - -def input_colour_themes(colour_permutations = False, colour_option = None): -# FUNCTION - # get valid colour option using parameter, else user console input -# ARGUMENTS - # bool colour_permutations - # int colour_option -# ARGUMENT VALIDATION - _m = 'input_colour_themes' - av.val_bool(colour_permutations, 'colour_permutations', _m) - if not (av.val_int(colour_option, 'colour_option', _m, suppress_errors = True, suppress_console_outputs = True) or av.val_str(colour_option, 'colour_option', _m, suppress_errors = True, suppress_console_outputs = True) or str(type(colour_option)) == ""): - raise ValueError(av.error_msg_str(_m, 'colour_option', colour_option, "export_colour_theme identifier")) -# VARIABLE INSTANTIATION - colour_themes = gen_col_themes() - if colour_permutations: return colour_themes - n = len(colour_themes) -# METHODS - if not validate_input_colour(colour_option, colour_themes): - colour_table = PrettyTable(field_names=['index', 'name', 'colour top', 'colour base']) - for col_i in range(n): - colour_table.add_row([col_i + 1] + colour_themes[col_i].as_row()) # .insert(0, str(col_i + 1)) - print(colour_table) - while not validate_input_colour(colour_option, colour_themes): - colour_option = input("Please input colour selection by name or index above.") -# RETURNS - return [get_colour_theme(colour_option, colour_themes)] - - -def validate_input_colour(colour_option, colour_themes): -# FUNCTION - # evaluate if colour_option relates to a colour_theme -# ARGUMENTS - # str/int colour_option - # list[export_colour_themes] colour_themes -# ARGUMENT VALIDATION - _m = 'validate_input_colour' - if not (av.val_int(colour_option, 'colour_option', _m, suppress_errors = True, suppress_console_outputs = True) or av.val_str(colour_option, 'colour_option', _m, suppress_errors = True, suppress_console_outputs = True)): return False - av.val_list(colour_themes, 'colour_themes', _m, "") -# VARIABLE INSTANTIATION - n = len(colour_themes) -# METHODS - if av.full_val_int(colour_option, 'colour_option', _m, suppress_errors = True, suppress_console_outputs = True): - colour_option = av.input_int(colour_option, 'colour_option', _m) - return (0 < colour_option and colour_option <= n) - for col_i in range(n): - if colour_option == colour_themes[col_i].name: - return True -# RETURNS - return False - - -def get_colour_theme(colour_option, colour_themes): -# FUNCTION - # get valid colour_option from colour_themes -# ARGUMENTS - # str/int colour_option - # list[export_colour_themes] colour_themes -# ARGUMENT VALIDATION - _m = 'get_colour_theme' - error_msg = av.error_msg_str(_m, colour_option, 'colour_option', 'export_colour_theme identifier') - if not (av.val_int(colour_option, 'colour_option', _m, suppress_errors = True, suppress_console_outputs = True) or av.val_str(colour_option, 'colour_option', _m, suppress_errors = True, suppress_console_outputs = True)): - raise ValueError(error_msg) - av.val_list(colour_themes, 'colour_themes', _m, "") -# VARIABLE INSTANTIATION - n = len(colour_themes) -# METHODS - if av.full_val_int(colour_option, 'colour_option', _m, suppress_errors = True, suppress_console_outputs = True): - colour_option = av.input_int(colour_option, 'colour_option', _m) - return colour_themes[colour_option - 1] - for col_i in range(n): - my_colour = colour_themes[col_i] - if colour_option == my_colour.name: - return my_colour -# ERROR HANDLING - raise ValueError(error_msg) - - -def gen_path_braille_scrabble(sz_scheme, col_theme, my_style, path_file = "C:\\Users\\edwar\\OneDrive\\Documents\\Programming\\Python Scripts\\Braille_Scrabble", suffix = "stl", presuffix=""): -# FUNCTION - # generate file path for braille scrabble design -# ARGUMENTS - # scrabble_dimensions sz_scheme - # int letter - index in the alphabet with base 0 - # export_colour_theme col_theme - # style my_style - # string path_file - path of folder + filename (message text) - # string suffix - file type - # string presuffix - text before file type -# ARGUMENT VALIDATION - _m = 'gen_path_braille_scrabble' - av.val_type(sz_scheme, "", 'sz_scheme', _m) - av.val_type(col_theme, "", 'col_theme', _m) - av.val_type(my_style, "", 'my_style', _m) - av.val_str(path_file, 'path_file', _m) - av.val_str(suffix, 'suffix', _m) - av.val_str(presuffix, 'presuffix', _m) -# RETURNS - return f"{path_file}_{sz_scheme.name}_{col_theme.name}{my_style.gen_filetxt()}.{suffix}" - - -def gen_openscad_braille(cum, letters, numbers, braille, n_keys, n_row_keys, n_rows, mydims, mystyle, col_theme, filename, path_file="C:/Users/edwar/OneDrive/Documents/Programming/Python Scripts/Braille", quality = 25): -# FUNCTION - # generate openscad model of Braille product -# ARGUMENTS - # list[int] cum - # list[str] letters - array of plaintext for output - # list[int] numbers - ordinality of translated keys in alphabet / number line (where appropriate) - # list[list[int]] braille - translated keys - # int n_keys - number of keys in Braille message - # int n_row_keys - number of Braille keys per row on keyboard - # int n_rows - number of rows of keys on keyboard - # scrabble_dimensions mydims - sizing parameters - # style mystyle - # export_colour_themes col_theme - # str filename - excl. path - # str path_file -# ARGUMENT VALIDATION - _m = 'gen_openscad_braille' - av.val_list(cum, 'cum', _m, "") - av.val_list(letters, 'letters', _m, "") - av.val_nested_list(numbers, 0, 1, 'numbers', _m, "") - av.val_nested_list(braille, 0, 2, 'braille', _m, "", -1, [-1, -1, 6], -1, [-1, -1, 6]) - av.val_int(n_keys, 'n_keys', _m) - av.val_int(n_row_keys, 'n_row_keys', _m) - av.val_int(n_rows, 'n_rows', _m) - # av.val_int(show_braille, 'show_braille', _m) - # av.val_int(show_let, 'show_let', _m) - # av.val_int(show_num, 'show_num', _m) - # av.val_type(show_braille, "", 'show_braille', _m) - # av.val_type(show_let, "", 'show_let', _m) - # av.val_type(show_num, "", 'show_num', _m) - av.val_type(mystyle, "", 'mystyle', _m) - # if not (av.val_type(col_theme, "", 'col_theme', _m, True) or av.val_type(col_theme, "", 'col_theme', _m, True)): - # raise ValueError(av.error_msg_str(_m, 'col_theme', col_theme, "")) - av.val_type(col_theme, "", 'col_theme', _m) - av.val_str(filename, 'filename', _m) - av.val_str(path_file, 'path_file', _m) -# VARIABLE INSTANTIATION - # integer boolean conversions for position - i_s_braille = int(mystyle.braille == elem_visibility.VISIBLE) - i_s_let = int(mystyle.letter == elem_visibility.VISIBLE) - i_s_num = int(mystyle.number == elem_visibility.VISIBLE) - print(f'i_s_b = {i_s_braille}\ni_s_let = {i_s_let}\ni_s_num = {i_s_num}\n') - # dimensions - dp = mydims.dp # horizontal and vertical spacing between dots = 2.2 - 2.8mm - h_block = mydims.hblock # block height - s = mydims.s # inter-block spacing - h_base = mydims.base_height # thickness of base block - # derived from: horizontal distance between corresponding braille dots in adjacent cells = 5.1 - 6.8mm - # and also conforms to: vertical distance between corresponding braille dots in adjacent cells = 10 - 15mm - hcyl = mydims.hcyl # braille dot height - rcyl = mydims.rcyl #3/2; # braille dot base-radius - rsphere = mydims.rsphere #3/2*4/5; # braille dot top-radius - xb = dp + 2 * s + rcyl * 2 - R_base_letter = [xb, xb] # alphabet block dimensions [x, y] - R_base_braille = [xb, xb + dp] # braille block dimensions [x, y] - R_base_number = np.array([xb, xb - 2 * s]) * i_s_num # number block dimensions [x, y] ' adjust to scalar coefficient rather than linear translation - htxt = hcyl # height of text - stxt = xb - 4 * s - snum = stxt * 0.75 - ntxtsfn = 0.65 # scale factor for shrinking number text to fit more letters in single char space - ntxtsfm = 0.75 # scale factor for shrinking message text to fit more letters in single char space - font = '"Arial:style=Bold"' - _fn = quality - - # keyboard layout - #maxln = 10; - #nln = min(maxln, N); # renamed n_row_keys - # temp = 1 + (N - 1) % nln - - # yn = (N + nln - temp) / nln # - 0 ** (temp) - # print(f"number of rows = {yn}") - - R_board = [n_row_keys * R_base_letter[0] + (n_row_keys + 3) * s, - n_rows * (R_base_braille[1] * i_s_braille + R_base_letter[1] * i_s_let + R_base_number[1] * i_s_num + s * (i_s_braille + i_s_let + i_s_num)) + 3 * s, # - 3 * s, - h_base] # +R_base_number[1] - print(f"R_board = {R_board}") - obj_dif = ops.Difference() - obj_uni = ops.Union() - - # obj_uni.append(base_fillet_cube(R_board[0], R_board[1], R_board[2], h_block, centre = "false").translate([-2 * s - rcyl, 2 * s + rcyl - R_board[1], -h_block - R_board[2]]).color(col_theme.base)) - obj_uni.append(ops.Cube([R_board[0], R_board[1], R_board[2]], h_block, centre = "false").translate([-3 * s - rcyl, 3 * s + rcyl - R_board[1], -h_block - R_board[2]]).color(col_theme.base)) - -# METHODS - for ab_i in range(len(braille)): # alpha-braille iterator - char = braille[ab_i] - print(f"char = braille[{ab_i}]") # " = {char}") - for char_j in range(len(char)): - char_old = [0, 0, 0, 0, 0, 0] if (ab_i == 0 and char_j == 0) else braille[0][char_j - 1] if (char_j > 0) else braille[ab_i - 1][len(braille[ab_i - 1]) - 1] - char_new = char[char_j] - print(f"char_new = {char_new}") - ab_n = (cum[ab_i] + char_j) % n_row_keys - ab_len = ((cum[ab_i] + char_j) - ab_n) / n_row_keys - ab_p = [ab_n * (R_base_braille[0] + s), -ab_len * (R_base_braille[1] * i_s_braille + R_base_letter[1] * i_s_let + R_base_number[1] * i_s_num + s * (i_s_braille + i_s_let + i_s_num)), 0] - # Bases - if (letters[ab_i] != " "): - if (mystyle.braille == elem_visibility.VISIBLE): - obj_uni.append(ops.Cube([R_base_braille[0], R_base_braille[1], h_block]).color(col_theme.base).translate([-(s + rcyl), s + rcyl - R_base_braille[1], -h_block]).translate(ab_p)) - if (mystyle.letter == elem_visibility.VISIBLE): - obj_uni.append(ops.Cube([R_base_letter[0], R_base_letter[1], h_block]).color(col_theme.base).translate([-(s + rcyl), s + rcyl -R_base_letter[1], 0]).translate([0, -(R_base_braille[1] + s) * i_s_braille, -h_block]).translate(ab_p)) # should this be: rcyl - R_base_letter[1] ?????!?!?!?!!!! - - # Braille message - # Dots - if (mystyle.braille == elem_visibility.VISIBLE): - for dot_y in range(3): - for dot_x in range(2): - if (char_new[dot_y + 3 * dot_x] == 1): - obj_uni.append(ops.Cylinder(hcyl, None, rcyl, rsphere, _fn = _fn, center = 'true').color(col_theme.top).translate([dot_x * dp, -dot_y * dp, 0]).translate(ab_p)) - # Text - if (mystyle.letter == elem_visibility.VISIBLE): - obj_uni.append(ops.Text(f'"{letters[ab_i]}"', stxt * ntxtsfm ** (len(letters[ab_i]) - 1), font, halign = '"center"', valign = '"center"', _fn = _fn).linear_extrude(htxt, center = "false").translate([R_base_letter[0] / 2, R_base_letter[1] / 2, 0]).color(col_theme.top).translate([-(s + rcyl), s + rcyl -R_base_letter[1], 0]).translate([0, - (R_base_braille[1] + s) * i_s_braille, 0]).translate(ab_p)) - # Text ordinality - num_new = numbers[ab_i] - if (num_new != [-1] and mystyle.number == elem_visibility.VISIBLE): - print(f"num_new = {num_new}, type = {type(num_new)}") - for num_x in range(len(num_new)): - snum = (R_base_number[1] - s * (len(num_new) + 1)) / (len(num_new) ** ntxtsfn) - # Base - obj_uni.append(ops.Cube([R_base_number[0], R_base_number[1], h_block]).color(col_theme.base).translate([0, -R_base_number[1], 0]).translate([-(s + rcyl), s + rcyl -(R_base_letter[1] + s) * i_s_let, 0]).translate([0, -(R_base_braille[1] + s) * i_s_braille, -h_block]).translate(ab_p)) - # Number (text) - obj_uni.append(ops.Text(f'"{num_new[num_x]}"', snum, font, halign = '"center"', valign = '"center"', _fn = _fn).linear_extrude(htxt, center = "true").color(col_theme.top).translate([R_base_number[0] / 2 if (len(num_new) == 1) else R_base_number[0] / 2 + 1.6 * snum * (num_x - (len(num_new) - 1) / 2), R_base_number[1] * 0.25, htxt / 2]).translate([-s, s -R_base_number[1], 0]).translate([0, -(R_base_letter[1] - s) * i_s_let, 0]).translate([s-(s + rcyl), s - (R_base_braille[1] + s) * i_s_braille, -h_block * 0]).translate(ab_p)) - - obj_dif.append(obj_uni) - # remove excess plastic if no numbers on final row regardless of mystyle.number - remove_num_space = True - for ab_i in range(n_row_keys): - remove_num_space &= numbers[len(numbers) - ab_i - 1] == [-1] - # Trimming tools for no numbers: - if remove_num_space: - obj_dif.append(ops.Cube([R_board[0], R_base_number[1] + s, R_board[2]], center = "true").translate([R_board[0] / 2 - 3 * s - rcyl, 3 * s + rcyl + (R_base_number[1] + s) / 2 - R_board[1], -R_board[2] / 2 - h_block])) - # obj_dif.append(triprism(h_block, R[0], centre = "true").rotate([0, 90, 0]).translate([R[0] / 2 - 1.6, (12+4) * s - R[1], -1/1000 - R[2] - h_block])) - - # embossed characters - for ab_i in range(len(braille)): - char = braille[ab_i] - print(f"char = braille[{ab_i}]") # " = {char}") - for char_j in range(len(char)): - # what is the purpose of char_old? - char_old = [0, 0, 0, 0, 0, 0] if (ab_i == 0 and char_j == 0) else braille[0][char_j - 1] if (char_j > 0) else braille[ab_i - 1][len(braille[ab_i - 1]) - 1] - char_new = char[char_j] - ab_n = (cum[ab_i] + char_j) % n_row_keys - ab_len = ((cum[ab_i] + char_j) - ab_n) / n_row_keys - ab_p = [ab_n * (R_base_braille[0] + s), -ab_len * (R_base_braille[1] * i_s_braille + R_base_letter[1] * i_s_let + R_base_number[1] * i_s_num + s * (i_s_braille + i_s_let + i_s_num)), 0] - - # Text - if (mystyle.letter == elem_visibility.EMBOSSED): - obj_dif.append(ops.Text(f'"{letters[ab_i]}"', stxt * ntxtsfm ** (len(letters[ab_i]) - 1) * 1.15, font, halign = '"center"', valign = '"center"', _fn = _fn).linear_extrude(htxt, center = "false").mirror([1, 0, 0]).translate([R_base_letter[0] / 2, R_base_letter[1] * 3 / 4, - R_board[2]]).color(col_theme.top).translate([0, -R_base_braille[1], 0]).translate([-(s + rcyl), s + rcyl - (R_base_braille[1] + s) * i_s_braille * 0, -h_block]).translate(ab_p)) - - # my_prefix = '_0b' if (mystyle.braille == elem_visibility.HIDDEN) else '' - # my_prefix += '_0l' if (mystyle.letter == elem_visibility.HIDDEN) else '' - # my_prefix += '__l' if (mystyle.letter == elem_visibility.EMBOSSED) else '' - # my_prefix += '_0n' if (mystyle.number == elem_visibility.HIDDEN) else '' - # my_prefix = mystyle.gen_filetxt() - - path_png = gen_path_braille_scrabble(mydims, col_theme, mystyle, path_file, 'png') - path_scad = gen_path_braille_scrabble(mydims, col_theme, mystyle, path_file, 'scad') - path_stl = gen_path_braille_scrabble(mydims, col_theme, mystyle, path_file, 'stl') -# RETURNS - obj_dif.write(path_scad) - print("writing SCAD") - # obj_dif.write(path_png) - return path_png, path_scad, path_stl - - -# def get_shownum(braille): -# shownum = 1 -# for n_x in range(len(braille)): -# shownum &= not (not braille[n_x]) -# return 0 # 1 if shownum else 0 diff --git a/model_gen/translate_msg_2_braille.py b/model_gen/translate_msg_2_braille.py deleted file mode 100644 index 4bc6d90..0000000 --- a/model_gen/translate_msg_2_braille.py +++ /dev/null @@ -1,801 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Created on Mon Apr 24 14:26:02 2023 - -@author: Edward Middleton-Smith - -Braille 3D Model Product Creation - -Braille Dictionary Conversion / Creation -Plaintext message translation into Braille for 3D modelling -""" - -# CLASSES -# ATTRIBUTE DECLARATION -# METHODS - # FUNCTION - # ARGUMENTS - # ARGUMENT VALIDATION - # ATTRIBUTE + VARIABLE INSTANTIATION - # METHODS - # RETURNS - -# NORMAL METHODS -# FUNCTION -# ARGUMENTS -# ARGUMENT VALIDATION -# VARIABLE INSTANTIATION -# METHODS -# RETURNS - - -import pandas as pd -from typing import Optional -from enum import Enum -import argument_validation as av -import sys - -class difficulty(Enum): - ALPHABETPUNCTUATION = 1 - SIMPLEWORDGROUPSIGNS = 2 - LOWERCONTRACTIONS = 3 - def mini(): - # FUNCTION - # Get minimum value in enumerator - # RETURNS - return min([e.value for e in difficulty]) - def maxi(): - # FUNCTION - # Get maximum value in enumerator - # RETURNS - return max([e.value for e in difficulty]) - -class braille_trans(): -# ATTRIBUTE DECLARATION - key: str # search key in input messages for Braille translation - includes additional characters for literal processing - level: difficulty # stage of learning at which this translation is discovered - braille: list # list[list[int]] # Braille translation of plaintext - plaintext: str # English plaintext key -# METHODS - # def argvalinit(key: str, level: difficulty, braille: list, plaintext: Optional[str] = None): - # # run before instantiating braille_trans - # # av.val_list(braille, 'list')= - # # _m = 'braille_trans.argvalinit' - # # if not av.val_str(key, 'key', method, min_len = -1, max_len = -1, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument') - # if not (av.val_str(key) and (str(type(level)) == "" or av.val_int(level, difficulty.mini(), difficulty.maxi())) and av.val_list(braille, "") and (av.val_str(plaintext, -1, -1, True) or plaintext == None)): - # print(f'Invalid braille_trans instantiation. key = {key}, level = {level}, braille = {braille}, plaintext = {plaintext}') - # return None - # return braille_trans(key, level, braille, plaintext) - - def __new__(cls, key: str, level: difficulty, braille: list, plaintext: Optional[str] = None): - # FUNCTION - # Initialise class object - # ARGUMENTS - # str key - # difficulty level - # list[list[int]] braille - # optional str plaintext - # VARIABLE DECLARATION - _m = 'braille_trans.__new__' - v_arg_type = 'class attribute' - # ARGUMENT VALIDATION - av.val_str(key, 'key', _m, 1, -1, v_arg_type = v_arg_type) - av.val_type(level, "", 'level', _m, v_arg_type = v_arg_type) - av.val_nested_list(braille, 0, 1, 'braille', _m, "", -1, [-1, 6], -1, [-1, 6], v_arg_type = v_arg_type) - if not (av.val_str(plaintext, 'plaintext', _m, -1, -1, True, True, v_arg_type) or str(type(plaintext)) == ""): - raise ValueError(av.error_msg_str(_m, 'plaintext', plaintext, "", v_arg_type = v_arg_type)) - # if not av.val_str(key): - # raise ValueError(av.error_msg_str('braille_trans.__new__', 'key', key, 'attribute')) - # if not av.val_type(level, ""): - # raise ValueError(av.error_msg_str('braille_trans.__new__', 'level', level, 'attribute')) - # if not av.val_nested_list(braille, 0, 2, "", 6, [1, 6], 6, [-1, 6]): - # raise ValueError(av.error_msg_str('braille_trans.__new__', 'braille', braille, 'attribute')) - # if not (av.val_str(plaintext) or str(type(plaintext)) == ""): - # raise ValueError(av.error_msg_str('braille_trans.__new__', 'plaintext', plaintext, 'attribute')) - # RETURNS - return super(braille_trans, cls).__new__(cls) - - def __init__(self, key: str, level: difficulty, braille: list, plaintext: Optional[str] = None): - # FUNCTION - # Construct class object - # ARGUMENTS - # str key - # difficulty level - # list[list[int]] braille - # optional str plaintext - # ARGUMENT VALIDATION - # see __new__() - # ATTRIBUTE + VARIABLE INSTANTIATION - self.key = key - self.level = level - self.braille = braille - self.plaintext = self.key if (plaintext is None) else plaintext - - def __repr__(self): - return f"key = {self.key}, level = {self.level}, braille = {self.braille}, plaintext = {self.plaintext}" - - # def query_lvl(self): - # return ' & '.join(["{}=='{}'".format(key, value) - # for key, value in self.__dict__.items() - # if not value is None]) - - def as_dict(self): - return {'key': self.key, 'level': self.level, 'braille': self.braille, 'plaintext': self.plaintext} - -class product(): -# ATTRIBUTE DECLARATION - name: str - line_length: int # number of Braille characters per line on keyboard - msg: str # pre-translated English (with necessary modifications for input to this programme e.g. splitting up undesired translations with hidden delimiter character @?NOTHING) - msg_prefix: str # additional pre-translated str as above to pre-append to product for adding header to creation of product messages from dictionary queries - filename: str # filename - name without spaces -# METHODS - # def argvalinit(name: str, line_length: int, msg: str, msg_prefix: Optional[str] = ''): - # # run before instantiating product - # if not (av.val_str(name) and av.val_int(line_length, 0) and av.val_str(msg) and av.val_str(msg_prefix)): - # print(f'Invalid product instantiation. name = {name}, line_length = {line_length}, msg = {msg}, msg_prefix = {msg_prefix}') - # return None - # return product(name, line_length, msg, msg_prefix) - - def __new__(cls, name, line_length, msg, msg_prefix = '', filename = ''): - # FUNCTION - # Initialise class object - # ARGUMENTS - # str name - # int line_length - # str msg - # str msg_prefix - # ARGUMENT VALIDATION - _m = 'product.__new__' - v_arg_type = 'class attribute' - av.val_str(name, 'name', _m, 1, -1, v_arg_type = v_arg_type) - av.val_int(line_length, 'line_length', _m, 1, v_arg_type = v_arg_type) - av.val_str(msg, 'msg', _m, -1, -1, v_arg_type = v_arg_type) - av.val_str(msg_prefix, 'msg_prefix', _m, -1, -1, v_arg_type = v_arg_type) - av.val_str(filename, 'filename', _m, -1, -1, v_arg_type = v_arg_type) - # if not av.val_str(name): - # raise ValueError(av.error_msg_str('product.__new__', 'name', name, 'attribute')) - # if not av.val_int(line_length, 1): - # raise ValueError(av.error_msg_str('product.__new__', 'line_length', line_length, 'attribute')) - # if not av.val_str(msg): - # raise ValueError(av.error_msg_str('product.__new__', 'msg', msg, 'attribute')) - # if not av.val_str(msg_prefix): - # raise ValueError(av.error_msg_str('product.__new__', 'msg_prefix', msg_prefix, 'attribute')) - # RETURNS - return super(product, cls).__new__(cls) - - def __init__(self, name, line_length, msg, msg_prefix = '', filename = ''): - # FUNCTION - # Construct class object - # ARGUMENTS - # str name - # int line_length - # str msg - # str msg_prefix - # ARGUMENT VALIDATION - # see __new__() - # ATTRIBUTE + VARIABLE INSTANTIATION - self.name = name - self.line_length = line_length - self.msg = msg - self.msg_prefix = msg_prefix # for procedurally-generated messages from difficulty selection - self.filename = name.replace(' ', '_') if filename == '' else filename - - def __repr__(self): - return f"name = {self.name}, line_length = {self.line_length}, msg = {self.msg}, msg_prefix = {self.msg_prefix}, filename = {self.filename}" - -def get_braille_translations(): -# FUNCTION - # return list of braille translations - # longer keys get priority in translation -# VARIABLE INSTANTIATION - temp_dict = [braille_trans("A", difficulty(1), [[1, 0, 0, 0, 0, 0]]), - braille_trans("B", difficulty(1), [[1, 1, 0, 0, 0, 0]]), - braille_trans("C", difficulty(1), [[1, 0, 0, 1, 0, 0]]), - braille_trans("D", difficulty(1), [[1, 0, 0, 1, 1, 0]]), - braille_trans("E", difficulty(1), [[1, 0, 0, 0, 1, 0]]), - braille_trans("F", difficulty(1), [[1, 1, 0, 1, 0, 0]]), - braille_trans("G", difficulty(1), [[1, 1, 0, 1, 1, 0]]), - braille_trans("H", difficulty(1), [[1, 1, 0, 0, 1, 0]]), - braille_trans("I", difficulty(1), [[0, 1, 0, 1, 0, 0]]), - braille_trans("J", difficulty(1), [[0, 1, 0, 1, 1, 0]]), - braille_trans("K", difficulty(1), [[1, 0, 1, 0, 0, 0]]), - braille_trans("L", difficulty(1), [[1, 1, 1, 0, 0, 0]]), - braille_trans("M", difficulty(1), [[1, 0, 1, 1, 0, 0]]), - braille_trans("N", difficulty(1), [[1, 0, 1, 1, 1, 0]]), - braille_trans("O", difficulty(1), [[1, 0, 1, 0, 1, 0]]), - braille_trans("P", difficulty(1), [[1, 1, 1, 1, 0, 0]]), - braille_trans("Q", difficulty(1), [[1, 1, 1, 1, 1, 0]]), - braille_trans("R", difficulty(1), [[1, 1, 1, 0, 1, 0]]), - braille_trans("S", difficulty(1), [[0, 1, 1, 1, 0, 0]]), - braille_trans("T", difficulty(1), [[0, 1, 1, 1, 1, 0]]), - braille_trans("U", difficulty(1), [[1, 0, 1, 0, 0, 1]]), - braille_trans("V", difficulty(1), [[1, 1, 1, 0, 0, 1]]), - braille_trans("W", difficulty(1), [[0, 1, 0, 1, 1, 1]]), - braille_trans("X", difficulty(1), [[1, 0, 1, 1, 0, 1]]), - braille_trans("Y", difficulty(1), [[1, 0, 1, 1, 1, 1]]), - braille_trans("Z", difficulty(1), [[1, 0, 1, 0, 1, 1]]), - braille_trans("@?NUM", difficulty(1), [[0, 0, 1, 1, 1, 1]], 'NUMBER'), - #" ", difficulty(1), [[0, 0, 0, 0, 0, 0]]), - braille_trans(",", difficulty(1), [[0, 1, 0, 0, 0, 0]]), - braille_trans(";", difficulty(1), [[0, 1, 1, 0, 0, 0]]), - braille_trans(":", difficulty(1), [[0, 1, 0, 0, 1, 0]]), - braille_trans(".", difficulty(1), [[0, 1, 0, 0, 1, 1]]), - braille_trans("!", difficulty(1), [[0, 1, 1, 0, 1, 0]]), - braille_trans("(", difficulty(1), [[0, 1, 1, 0, 1, 1]]), - braille_trans(")", difficulty(1), [[0, 1, 1, 0, 1, 1]]), - braille_trans("?", difficulty(1), [[0, 1, 1, 0, 0, 1]]), - braille_trans('"@?BO', difficulty(1), [[0, 1, 1, 0, 0, 1]], '"'), - braille_trans('"@?BC', difficulty(1), [[0, 0, 1, 0, 1, 1]], '"'), - braille_trans("'", difficulty(1), [[0, 0, 1, 0, 0, 0]]), - braille_trans("@?ABBREV1", difficulty(1), [[0, 0, 0, 1, 0, 0]], "ABBREV"), - braille_trans("@?ABBREV2", difficulty(1), [[0, 0, 0, 1, 1, 0]], "ABBREV"), - braille_trans("@?ABBREV3", difficulty(1), [[0, 0, 0, 1, 1, 1]], "ABBREV"), - braille_trans("@?ABBREV4", difficulty(1), [[0, 0, 0, 0, 1, 0]], "ABBREV"), - braille_trans("...", difficulty(1), [[0, 0, 1, 0, 0, 0], [0, 0, 1, 0, 0, 0], [0, 0, 1, 0, 0, 0]]), - braille_trans("-", difficulty(1), [[0, 0, 1, 0, 0, 1]]), - braille_trans("-@?S", difficulty(1), [[0, 0, 1, 0, 0, 1], [0, 0, 1, 0, 0, 1]], "-"), - braille_trans("-@?L", difficulty(1), [[0, 0, 1, 0, 0, 1], [0, 0, 1, 0, 0, 1], [0, 0, 1, 0, 0, 1], [0, 0, 1, 0, 0, 1]], "-"), - braille_trans("/@?B", difficulty(1), [[0, 0, 0, 1, 0, 0], [0, 1, 1, 0, 1, 1]], "/"), - braille_trans("\@?B", difficulty(1), [[0, 0, 0, 1, 0, 0], [0, 1, 1, 0, 1, 1]], "\\"), - braille_trans("[@?BPH", difficulty(1), [[0, 0, 0, 1, 1, 0], [0, 1, 1, 0, 1, 1]], "["), - braille_trans("]@?BPH", difficulty(1), [[0, 0, 0, 1, 1, 0], [0, 1, 1, 0, 1, 1]], "]"), - braille_trans("<", difficulty(1), [[0, 0, 0, 1, 1, 1], [0, 1, 1, 0, 1, 1]]), - braille_trans(">", difficulty(1), [[0, 0, 0, 1, 1, 1], [0, 1, 1, 0, 1, 1]]), - braille_trans("/", difficulty(1), [[0, 0, 0, 1, 1, 1], [0, 0, 1, 1, 0, 0]]), - braille_trans("{", difficulty(1), [[0, 0, 0, 1, 0, 1], [0, 1, 1, 0, 1, 1]]), - braille_trans("}", difficulty(1), [[0, 0, 0, 1, 0, 1], [0, 1, 1, 0, 1, 1]]), - braille_trans("[@?BSQ", difficulty(1), [[0, 0, 0, 0, 0, 1], [0, 1, 1, 0, 1, 1]], "["), - braille_trans("]@?BSQ", difficulty(1), [[0, 1, 1, 0, 1, 1], [0, 0, 0, 0, 0, 1]], "]"), - braille_trans("'@?BO", difficulty(1), [[0, 0, 0, 0, 0, 1], [0, 1, 1, 0, 0, 1]], "'"), - braille_trans("'@?BC", difficulty(1), [[0, 1, 1, 0, 0, 1], [0, 0, 0, 0, 0, 1]], "'"), - # oldbrailledict_2 = { - # Simple Upper Wordsigns - braille_trans("BUT", difficulty(2), [[1, 1, 0, 0, 0, 0]]), - braille_trans("CAN", difficulty(2), [[1, 0, 0, 1, 0, 0]]), - braille_trans("DO", difficulty(2), [[1, 0, 0, 1, 1, 0]]), - braille_trans("EVERY", difficulty(2), [[1, 0, 0, 0, 1, 0]]), - braille_trans("FROM", difficulty(2), [[1, 1, 0, 1, 0, 0]]), - braille_trans("GO", difficulty(2), [[1, 1, 0, 1, 1, 0]]), - braille_trans("HAVE", difficulty(2), [[1, 1, 0, 0, 1, 0]]), - braille_trans("JUST", difficulty(2), [[0, 1, 0, 1, 1, 0]]), - braille_trans("KNOWLEDGE", difficulty(2), [[1, 0, 1, 0, 0, 0]]), - braille_trans("LIKE", difficulty(2), [[1, 1, 1, 0, 0, 0]]), - braille_trans("MORE", difficulty(2), [[1, 0, 1, 1, 0, 0]]), - braille_trans("NOT", difficulty(2), [[1, 0, 1, 1, 1, 0]]), - braille_trans("PEOPLE", difficulty(2), [[1, 1, 1, 1, 0, 0]]), - braille_trans("QUITE", difficulty(2), [[1, 1, 1, 1, 1, 0]]), - braille_trans("RATHER", difficulty(2), [[1, 1, 1, 0, 1, 0]]), - braille_trans("SO", difficulty(2), [[0, 1, 1, 1, 0, 0]]), - braille_trans("THAT", difficulty(2), [[0, 1, 1, 1, 1, 0]]), - braille_trans("US", difficulty(2), [[1, 0, 1, 0, 0, 1]]), - braille_trans("VERY", difficulty(2), [[1, 1, 1, 0, 0, 1]]), - braille_trans("WILL", difficulty(2), [[0, 1, 0, 1, 1, 1]]), - braille_trans("IT", difficulty(2), [[1, 0, 1, 1, 0, 1]]), - braille_trans("YOU", difficulty(2), [[1, 0, 1, 1, 1, 1]]), - braille_trans("AS", difficulty(2), [[1, 0, 1, 0, 1, 1]]), - braille_trans("CHILD", difficulty(2), [[1, 0, 0, 0, 0, 1]]), - braille_trans("SHALL", difficulty(2), [[1, 0, 0, 1, 0, 1]]), - braille_trans("THIS", difficulty(2), [[1, 0, 0, 1, 1, 1]]), - braille_trans("WHICH", difficulty(2), [[1, 0, 0, 0, 1, 1]]), - braille_trans("OUT", difficulty(2), [[1, 1, 0, 0, 1, 1]]), - braille_trans("STILL", difficulty(2), [[0, 0, 1, 1, 0, 0]]), - # Simple Upper Groupsigns - braille_trans("AND", difficulty(2), [[1, 1, 1, 1, 0, 1]]), - braille_trans("FOR", difficulty(2), [[1, 1, 1, 1, 1, 1]]), - braille_trans("OF", difficulty(2), [[1, 1, 1, 0, 1, 1]]), - braille_trans("THE", difficulty(2), [[0, 1, 1, 1, 0, 1]]), - braille_trans("WITH", difficulty(2), [[0, 1, 1, 1, 1, 1]]), - braille_trans("CH", difficulty(2), [[1, 0, 0, 0, 0, 1]]), - braille_trans("GH", difficulty(2), [[1, 1, 0, 0, 0, 1]]), - braille_trans("SH", difficulty(2), [[1, 0, 0, 1, 0, 1]]), - braille_trans("TH", difficulty(2), [[1, 0, 0, 1, 1, 1]]), - braille_trans("WH", difficulty(2), [[1, 0, 0, 0, 1, 1]]), - braille_trans("ED", difficulty(2), [[1, 1, 0, 1, 0, 1]]), - braille_trans("ER", difficulty(2), [[1, 1, 0, 1, 1, 1]]), - braille_trans("OU", difficulty(2), [[1, 1, 0, 0, 1, 1]]), - braille_trans("OW", difficulty(2), [[0, 1, 0, 1, 0, 1]]), - braille_trans("ST", difficulty(2), [[0, 0, 1, 1, 0, 0]]), - braille_trans("AR", difficulty(2), [[0, 0, 1, 1, 1, 0]]), - braille_trans("ING", difficulty(2), [[0, 0, 1, 1, 0, 1]]), - braille_trans("BLE", difficulty(2), [[0, 0, 1, 1, 1, 1]]), - # oldbrailledict_3 = { - # Lower Contractions - # Initial Groupsigns - braille_trans("BE", difficulty(3), [[0, 1, 1, 0, 0, 0]]), - braille_trans("COM", difficulty(3), [[0, 0, 1, 0, 0, 1]]), - braille_trans("CON", difficulty(3), [[0, 1, 0, 0, 1, 0]]), - braille_trans("DIS", difficulty(3), [[0, 1, 0, 0, 1, 1]]), - # Initial-Medial-Terminal Groupsigns - braille_trans("EN", difficulty(3), [[0, 1, 0, 0, 0, 1]]), - braille_trans("IN", difficulty(3), [[0, 0, 1, 0, 1, 0]]), - # Medial Groupsigns - braille_trans("EA", difficulty(3), [[0, 1, 0, 0, 0, 0]]), - braille_trans("BB", difficulty(3), [[0, 1, 1, 0, 0, 0]]), - braille_trans("CC", difficulty(3), [[0, 1, 0, 0, 1, 0]]), - braille_trans("DD", difficulty(3), [[0, 1, 0, 0, 1, 1]]), - braille_trans("FF", difficulty(3), [[0, 1, 1, 0, 1, 0]]), - braille_trans("GG", difficulty(3), [[0, 1, 1, 0, 1, 1]]), - # Wordsigns - braille_trans("ENOUGH", difficulty(3), [[0, 1, 0, 0, 0, 1]]), - braille_trans("TO", difficulty(3), [[0, 1, 1, 0, 1, 0]]), - braille_trans("WERE", difficulty(3), [[0, 1, 1, 0 , 1, 1]]), - braille_trans("HIS", difficulty(3), [[0, 1, 1, 0, 0, 1]]), - braille_trans("INTO", difficulty(3), [[0, 0, 1, 0, 1, 0], [0, 1, 1, 0, 1, 0]]), #(sequenced) - braille_trans("BY", difficulty(3), [[0, 0, 1, 0, 1, 1]]), #(sequenced) - braille_trans("WAS", difficulty(3), [[0, 0 , 1, 0 , 1, 1]]), - - # Modifiers - braille_trans("@?LET", difficulty(3), [[0, 0, 0, 0, 1, 1]], "LET"), - braille_trans("@?CAPS", difficulty(3), [[0, 0, 0, 0, 0, 1]], "CAPS"), - braille_trans("@?EMPH", difficulty(3), [[0, 0, 0, 1, 0, 1]], "EMPH"), - ] - # remove None 's - rejected inputs - valid = False - while not valid: - try: - temp_dict.remove(None) - except: - valid = True - braille_dict = pd.DataFrame([x.as_dict() for x in temp_dict]) # , columns=['key', 'level', 'msg', 'msg_prefix']) -# RETURNS - # print('Braille Dictionary Creation') - # print(f"type(temp_dict) = {type(temp_dict)}") - # print("temp_dict = ") - # for i in range(len(temp_dict)): - # print(f"{temp_dict[i]}") - # print('') - # print(f"type(braille_dict) = {type(braille_dict)}") - # print(f"braille_dict = {braille_dict}") - - return braille_dict # temp_dict # braille_dict - -def get_delimiters(): -# FUNCTION - # delimiters and special character codes for plaintext message before braille translation -# VARIABLE INSTANTIATION - txtdict = {"@?NUM" : "NUMBER", - "@?NOTHING" : "", - #" " : "", - '"@?BO' : '"', - '"@?BC' : '"', - "-@?S" : "-", - "-@?L" : "-", - "/@?B" : "/", - "[@?BPH" : "[", - "]@?BPH" : "]", - "[@?BSQ" : "[", - "]@?BSQ" : "]", - "'@?BO" : "'", - "'@?BC" : "'", - "@?LET" : "LET", - "@?CAPS" : "CAPS", - "@?EMPH" : "EMPH", - "@?ABBREV1" : "ABBREV", - "@?ABBREV2" : "ABBREV", - "@?ABBREV3" : "ABBREV", - "@?ABBREV4" : "ABBREV", - } -# RETURNS - return txtdict - -def gen_difficulty_msgstr(braille_dict, level: difficulty = difficulty(1)): -# FUNCTION - # generate keyboard message for specified difficulty -# ARGUMENTS - # list[braille_trans] braille_dict - # difficulty level -# ARGUMENT VALIDATION - _m = 'gen_difficulty_msgstr' - av.val_type(braille_dict, "", 'braille_dict', _m) - av.val_type(level, "", 'level', _m) -# VARIABLE INSTANTIATION - str_out = '' - # n = len(braille_dict) -# METHODS - # print(f"len(braille_dict) = {n}") - # print(f"braille_dict.columns =") - # for i in braille_dict.columns: - # print(braille_dict.columns[i]) - # temp_dict = braille_dict['key'] - dict_iterator = braille_dict[braille_dict['level'] == level] - # print(f"dict_iterator.index = {dict_iterator.index}") - for bd_i in range(len(dict_iterator.index)): - bd_n = dict_iterator['key'][dict_iterator.index[bd_i]] - # print(f"bd_i = {bd_i}") - # print(f"bd_n = {bd_n}") - str_out += "@?NOTHING" + bd_n - # for i in range(n): - # bd_i = braille_dict.loc[i][0] - # # print(f"bd_i = {bd_i}") - # # print(f"type(bd_i) = {str(type(bd_i))}") - # if (bd_i.level == difficulty): - # str_out += "@?NOTHING" + bd_i.key -# RETURNS - return str_out - -# def get_braille_by_key(braille_dict: pd.DataFrame, key: str): -# # FUNCTION -# # Find key in braille dictionary -# return None -# # ARGUMENTS -# # ARGUMENT VALIDATION -# # VARIABLE INSTANTIATION -# # METHODS -# # RETURNS - - -def input_product(braille_dict, products, my_option: Optional[int] = -1, my_select: Optional[str] = ''): -# FUNCTION - # Get product input from user - repeat until valid input received -# ARGUMENTS - # list[braille_trans] braile_dict - # list[product] products - # optional int my_option - if option provided in code -# ARGUMENT VALIDATION - _m = 'input_product' - av.val_type(braille_dict, "", 'braille_dict', _m) - av.val_list(products, 'products', _m, "", 1) - av.val_int(my_option, 'my_option', _m) -# VARIABLE INSTANTIATION - N = len(products) - select_i = my_option - valid = (my_option > 0 and my_option <= N) - # temp_dict = braille_dict['key'] -# METHODS - if valid: - if my_option == N: - temp = braille_dict[braille_dict['key'] == my_select] - if len(temp.index) == 1: - products[N - 1].msg_prefix = my_select - else: - valid = False - while not valid: - print() - print('Welcome to your 3D Braille Model Generator') - print("At any time, answer the following error code to exit (excl. speech marks): '#!ERRORCODE!#'") - print() - print('Braille Products:') - for i in range(N): - print(f"{i + 1}. {products[i].name}") - print() - select_i = av.input_int(input(f"Please enter your selection (1 - {N}) from the products above\n"), 'select_i', _m, 1, N) - if select_i == '#!ERRORCODE!#': - sys.exit - valid = not (str(type(select_i)) == "") - if valid and select_i == N: - valid = False - while not valid: - select_A = input("Please enter a character selection for your Scrabble tile\n") - if select_A == '#!ERRORCODE!#': - sys.exit - temp = braille_dict[braille_dict['key'] == select_A].index - if not len(temp) == 1: - print(f"temp = {temp}") - valid = False - else: - valid = True - products[N - 1].msg_prefix = select_A -# RETURNS - return products[select_i - 1] - -def append_ifnotNone(v_list, v_item): -# FUNCTION - # append v_item to v_list if v_item is not None -# ARGUMENTS - # list v_list - # v_item -# ARGUMENT VALIDATION - if (not av.val_list(v_list, 'v_list', 'append_ifnotNone', suppress_errors = True)) or v_item == None: -# RETURNS - return v_list - v_list.append(v_item) - return v_list#.append(v_item) - - -def gen_product_inputs(braille_dict): -# FUNCTION - # Generate product inputs -# ARGUMENTS - # [pandas.DataFrame] braille_dict - braille dictionary -# VARIABLE INSTANTIATION - products = [] -# ARGUMENT VALIDATION - av.val_type(braille_dict, "", 'braille_dict', 'gen_product_inputs') -# METHODS - products.append(product("Extended Alphabet", 10, "abcdefg@?NOTHINGhijKLMNOPQRS@?NOTHINGTUVXYZANDFOROFTHEWITHCHGHSHTHWHEDEROUOWWEABBCCDDENFF?GGINBY")) - products.append(product("Upper Groupsigns", 10, "uppe@?nothingr GRO@?NOTHINGUPSIGNsand:a@?nothingn@?nothingd for:fo@?nothingr of:o@?nothingf the:t@?nothingh@?nothinge with:wi@?nothingt@?nothingh "+"@?NEWLINECH:C@?NOTHINGH " + "GH:G@?NOTHINGH " + "SH:S@?NOTHINGH " + "TH:T@?NOTHINGH " + "WH:W@?NOTHINGH " + "ED:E@?NOTHINGD " + "ER:E@?NOTHINGR " + "OU:O@?NOTHINGU " + "OW:O@?NOTHINGW "+"st:s@?nothingt ar:a@?nothingr ble:bl@?nothinge ing:i@?nothingng")) - products.append(product("Upper Wordsigns", 24, gen_difficulty_msgstr(braille_dict, difficulty(3)))) - products.append(product("Alphabet", 10, "ABCDEFG@?NOTHINGHIJKLMNOPQRSTUVWXYZ")) - # products.append(product("Travel", 5, "ABCDEFG@?NOTHINGHIJ")) - products.append(product("Demo", 9, "BRAILLE")) - products.append(product("Scrabble Alphabet of Tiles", 1, '', filename = 'Scrabble_Tile_Set')) - products.append(product("Scrabble Character Tile", 1, '', filename = 'Scrabble_Tile')) -# RETURNS - return products - -def gen_braille_inputs_4_openscad(msgin, line_length, brailledict): # , hyphenate = False -# FUNCTION - # Convert message to Braille for openSCAD generation -# ARGUMENTS - # str msgin - partially translated message containing only brailledict keys and blankspace - # int line_length - number of Braille characters per row on keyboard - # pandas.DataFrame brailledict - Braille translations with diffculty - # # bool hyphenate - hyphenate words that cross lines or start on new line -# ARGUMENT VALIDATION - _m = 'gen_braille_inputs_4_openscad' - av.val_str(msgin, 'msgin', _m, 1) - av.val_int(line_length, 'line_length', _m) - av.val_type(brailledict, "", 'brailledict', _m) -# VARIABLE INSTANTIATION - # dict txtdict - delimiters for Braille translation - msgin = msgin.upper() - braille = [] - letters = [] - n_rows = 1 - start_of_word = 0 # position within cum - numbers = [] - cum = [0, ] # 0-based cumulative starting position of Braille translation of message segments - #lmsg = [0] * len(msgin) # length of braille message - last_is_num = False - new_word = True - iter_lim = len(msgin) - print(f"iteration limit = {iter_lim}") #len(msgin)) - msg_i_0 = 0 - maxstrlen = max_key_len(brailledict) -# METHODS - print(f"msgin = {msgin}") - while (msg_i_0 < iter_lim): - found = False - print(f"msg_i_0 = {msg_i_0}") - for phrase_len in range(min(len(msgin) - msg_i_0, maxstrlen), 0, -1): - if found: - continue - phrase = msgin[msg_i_0 : msg_i_0 + phrase_len] # message segment to search for in Braille translation keys - print(f'phrase = {phrase}') - - # generate braille if a code has been found - if (phrase_len == 0): - if (ord(phrase) >= 48 and ord(phrase) <= 57): # numbers - b_num_pre = brailledict[brailledict['key'] == "@?NUM"]['braille'].values[0] - b_num = brailledict[brailledict['key'] == ("J" if (ord(phrase) == 48) else chr(ord(phrase)+16))]['braille'].values[0] - if last_is_num == True: - braille[len(braille) - 1].append(b_num[0]) - new_cum = 1 - # temp = temp2 - else: - braille.append([b_num_pre[0], b_num[0]]) - new_cum = 2 - # temp = [temp1[0], temp2[0]] - print('braille(numeric phrase) = ', braille[len(braille) - 1]) - last_is_num = True - else: - # new_cum = len(brailledict[brailledict['key'] == phrase].index) - found = (len(brailledict[brailledict['key'] == phrase].index) == 1) - if found: - last_is_num = False - # temp = brailledict.get(phrase) - else: - # new_cum = len(brailledict[brailledict['key'] == phrase].index) - found = (len(brailledict[brailledict['key'] == phrase].index) == 1) - if found: - last_is_num = False - # temp = brailledict.get(phrase) - #print("tempsearch = ", temp) - - # organise placement of braille phrase onto end of whole message - if found or last_is_num: # (temp != None): # - # found = True - # last_is_num = False - new_num = [-1] - if (len(phrase) == 1): - if (ord(phrase) >= 65 and ord(phrase) <= 90): # letters - new_num = [ord(phrase) - 64] - elif (ord(phrase) >= 48 and ord(phrase) <= 57): # numbers - new_num = [ord(phrase) - 48] - # last_is_num = True - if found: - braille.append(brailledict[brailledict['key'] == phrase]['braille'].values[0]) - new_cum = len(braille[len(braille) - 1]) - numbers.append(new_num) - new_cum = cum[len(cum) - 1] + new_cum - cum.append(new_cum) - n_rows_0 = n_lines_at_pos(cum[start_of_word], line_length) - n_rows_next = n_lines_at_pos(new_cum, line_length) - if ((not new_word) and n_rows_0 < n_rows_next and not (cum[start_of_word] % line_length == 0)): - delta_cum_new_line = n_rows_next * line_length + 1 - cum[start_of_word] - for msg_j in range(len(cum) - start_of_word - 1): - cum[start_of_word + msg_j] += delta_cum_new_line - #if (cum[len(cum)-1] % line_length > 0): - # cum[len(cum)-1] = cum[len(cum)-1] + line_length - (1+(cum[len(cum)-1]-1) % line_length) - # print("clean_rows",cum[len(cum)-1]) - # print("phrase_len=",phrase_len) - msg_i_0 += phrase_len - letters.append(brailledict[brailledict['key'] == phrase]['plaintext'].values[0]) - elif phrase == "@?NOTHING": - msg_i_0 += 9 - print('found nothing') - found = True - elif phrase == "@?NEWLINE": - msg_i_0 += 9 - print('forced newline') - cum[len(cum) - 1] += (line_length - (cum[len(cum) - 1] % line_length)) % line_length - found = True - new_word = True - elif phrase == " ": # and (cum[len(cum)-1] % line_length > 0)): # no space at start of line # or letters[len(cum)-1] == " " or msgin[ni+1] == " ") - msg_i_0 += 1 - cum[len(cum) - 1] = cum[len(cum) - 1] + 1 - print('space') - new_word = True - # unfound character?? - if phrase_len == 0 and not (found or (ord(phrase) >= 48 and ord(phrase) <= 57)): - print(f"Unfound phrase: {phrase}") - msg_i_0 += 1 - new_word = True - # word start position - if new_word: - start_of_word = len(cum) - 1 # position within cum -# OUTPUTS - # console output - n_keys = max(cum) - n_rows = n_rows_0 - cum = cum[0 : len(cum) - 1] - # letters = letters[1:len(letters)] # why does element 0 exist? - # print(f"message length b = {n_keys}") - # print(f"braille = {braille}") - # print(f"cum = {cum}") - # print(f"numbers = {numbers}") - # print(f"letters = {letters}") - - ## file output - f = open('Braille.txt','a') - f.truncate() - f.write(f'cum = {str(cum)};\n') - - f.write('msgstr = [') - for i in range(len(letters)): - f.write('"') - f.write(str(letters[i])) - if i < len(letters) - 1: - f.write('", ') - f.write('"];\n') - - f.write('numbers = [') - for i in range(len(numbers)): - #f.write('"') - f.write(str(numbers[i])) - if i < len(numbers) - 1: - f.write(', ') - f.write('];\n') - - f.write(f"inA = {str(braille)};\n") - f.write(f"lmsg = {str(len(braille))};\n") - f.write(f"N = {str(n_keys)};\n") - f.write(f"nln = {str(min(line_length, n_keys))};\n") - f.write(f"maxln = {str(n_rows)};\n") - f.close() -# RETURNS - return cum, letters, numbers, braille, n_keys, n_rows - - -def n_lines_at_pos(position, line_length): -# FUNCTION - # calculate number of rows of keyboard required for message of length (in Braille keys) position -# ARGUMENTS - # int position - quantity of Braille keys in message up to (+ incl.) position - # int line_length - number of Braille keys per line / row -# ARGUMENT VALIDATION - _m = 'n_lines_at_pos' - av.val_int(position, 'position', _m, 0) - av.val_int(line_length, 'line_length', _m, 1) -# RETURNS - return 1 + (position // line_length) - - -def max_key_len(mydict: pd.DataFrame, min_dict_len: Optional[int] = 1): -# FUNCTION - # find maximum key length in braille dictionary -# ARGUMENTS - # pandas.DataFrame mydict -# ARGUMENT VALIDATION - _m = 'max_key_len' - av.val_int(min_dict_len, 'min_dict_len', _m) - av.val_type(mydict, "", 'mydict', _m) -# VARIABLE INSTANTIATION - n = len(mydict.index) - max_len = 0 -# METHODS - for i in range(n): - max_len = max(max_len, len(mydict.iloc[i]['key'])) - if max_len < min_dict_len: - return -1 -# RETURNS - return max_len - - -# ToDo: Finish this! -# def remove_words_in_word(word, maxstrlen=9): -# ln = len(word) -# minmax = min(ln, maxstrlen) -# fix = False -# skip = False -# for length in np.arange(minmax, 1, -1): -# for start in range(ln-length): -# tempstr = word[start:start+length] -# if (tempstr == "@?NOTHING"): -# skip = True -# if skip: -# continue -# tempfind = brailledict.get(tempstr) -# if not (tempbool == None): -# tempword = word[:start] -# for li in range(length): -# ## add "@?NOTHING" - -# def get_translated_input(my_option: Optional[int] = -1): # REDUNDANT -# # FUNCTION -# # Get product selection input from user + convert to Braille -# # VARIABLE INSTANTIATION -# braille_translations = get_braille_translations() -# products = gen_product_inputs(braille_translations) -# delimiters = get_delimiters() -# # METHODS -# my_product = input_product(braille_translations, products, my_option) -# # cum, letters, numbers, braille, ltmsg, n_rows = gen_braille_inputs_4_openscad(my_product.msg, my_product.line_length, braille_translations, max_key_len(braille_translations), delimiters) -# # RETURNS -# return my_product, braille_translations, max_key_len(braille_translations), delimiters - -# get_translated_input() ' requires translate_msg_2_braille is replaced by __main__ in type validation strings - - - # def process_old_dict(old_dict, difficulty): - # # FUNCTION - # # create new list of braille_trans dataclass items - # # ARGUMENTS - # # old_dict - old dictionary of keys, values - # # difficulty - level field of dataclass - # # ARGUMENT VALIDATION - # print(f"type(old_dict) = {type(old_dict)}") - # print(f"type(difficulty) = {type(difficulty)}") - # # VARIABLE INSTANTIATION - # new_dict = [] - # # METHODS - # for i in range(len(old_dict)): - # temp_key, temp_value = old_dict.popitem() - # new_dict.append(braille_trans(temp_key, difficulty, temp_value)) - # # RETURNS - # return new_dict - - -# class braille_dictionary(): - -# def __init__(self, keys, hardnesses, braille_translations): -# return self.push(keys, hardnesses, braille_translations) - -# def push(self, keys, hardnesses, braille_translations): -# N_in = len(keys) -# if not (N_in == len(hardnesses) == len(braille_translations)): -# return False -# for i in range(N_in - 1): -# for j in range(i + 1): -# if (keys[i + 1] == keys[j]): -# return False -# for i in range(N_in): -# self.keys.append(keys[i]) -# self.hards.append(hardnesses[i]) -# self.brailles.append(braille_translations[i]) -# return True - -# def exists_key(self, key): -# try: -# i = self.keys.index(key) -# except ValueError: -# return True -# else: -# return False - -# def get_key_index(self, key): -# if self.exists_key(key): -# return self.keys.index(key) -# else: -# return -1 \ No newline at end of file diff --git a/model_gen/translation_braille.py b/model_gen/translation_braille.py new file mode 100644 index 0000000..74528c8 --- /dev/null +++ b/model_gen/translation_braille.py @@ -0,0 +1,433 @@ +# -*- coding: utf-8 -*- +""" +Created on 29/05/2024 +@author: Edward Middleton-Smith +""" + +from character_braille import Character_Braille + +import pandas as pd +from typing import Optional, List +from pydantic import BaseModel, conlist, validator +from enum import Enum +# import argument_validation as av +import sys + +class Enum_Braille_Proficiency_Level(Enum): + ALPHABET_PUNCTUATION = 1 + SIMPLE_WORD_AND_GROUPSIGNS = 2 + LOWER_CONTRACTIONS = 3 + def minimum(): + return min([e.value for e in Enum_Braille_Proficiency_Level]) + def maximum(): + return max([e.value for e in Enum_Braille_Proficiency_Level]) + + +# Matrix_Braille_Dots = Annotated(List[List[bool]], conlist(conlist(bool, min_items=2, max_items=2), min_items=3, max_items=3)) +class Translation_Braille(BaseModel): + plaintext: str # English plaintext key + translation_proficiency_level: Enum_Braille_Proficiency_Level # stage of learning at which this translation is discovered + braille_text: List[Character_Braille] = [] # Braille translation of plaintext + search_key: Optional[str] = None + + def __init__(self, plaintext, translation_proficiency_level, braille_text=[], search_key= None): + super().__init__(plaintext=plaintext, translation_proficiency_level=translation_proficiency_level, braille_text=braille_text, search_key=search_key) + self.plaintext = self.plaintext.upper() + if braille_text == []: + self.braille_text = self.translate_text_to_Braille() + if search_key is None: + self.search_key = plaintext + + def __repr__(self): + return f"{self.plaintext} - {self.translation_proficiency_level} - {self.braille_text}" + + def translate_text_to_Braille(self): + known_translations = Translation_Braille.get_defaults_DataFrame() + # print(f'known_translations: {known_translations}') + delimiters = Translation_Braille.get_delimiters() + braille_text = [] + max_key_length = known_translations.apply(lambda x: len(x[3]), axis=1).max() # [Translation_Braille.__name__] + length_plaintext = len(self.plaintext) + # dict_iterator = braille_dict[braille_dict['level'] == level] + index_key_start = 0 + while index_key_start < length_plaintext: + found_key = False + for key_length in range(min(max_key_length, length_plaintext - index_key_start), 0, -1): + key = self.plaintext[index_key_start : index_key_start + key_length] + """if key in delimiters: + character_braille = Character_Braille.get_blank_Character_Braille() + character_braille.plaintext = delimiters[key] + braille_text.append(character_braille) + index_key_start += key_length + continue + el""" + if key == "@?NOTHING": + index_key_start += key_length + found_key = True + break + elif key == "@?NEWLINE": + character_braille = Character_Braille("NEWLINE", [0, 0, 0, 0, 0, 0]) + braille_text.append(character_braille) + index_key_start += key_length + found_key = True + break + if known_translations.apply(lambda x: x[3] == key and x[1].value <= self.translation_proficiency_level.value, axis=1).any(): + translation_Braille = known_translations.apply(lambda x: x if (x[3] == key and x[1].value <= self.translation_proficiency_level.value) else None, axis=1).dropna().values.tolist()[0] + # print(f'translation_Braille: {translation_Braille}') + # character_braille = known_translations[index_Character_Braille] + braille_text.append(translation_Braille[2]) + # print(f'braille_text: {braille_text}') + index_key_start += key_length + found_key = True + break + #elif key_length == 1: + if not found_key: + raise KeyError("Key not found starting from: ", key) + + + """ + for key in range(len(dict_iterator.index)): + bd_n = dict_iterator['key'][dict_iterator.index[bd_i]] + str_out += "@?NOTHING" + bd_n + """ + return braille_text + + def get_delimiters(): + return { + "@?NUM" : "NUMBER", + "@?NOTHING" : "", + #" " : "", + '"@?BO' : '"', + '"@?BC' : '"', + "-@?S" : "-", + "-@?L" : "-", + "/@?B" : "/", + "[@?BPH" : "[", + "]@?BPH" : "]", + "[@?BSQ" : "[", + "]@?BSQ" : "]", + "'@?BO" : "'", + "'@?BC" : "'", + "@?LET" : "LET", + "@?CAPS" : "CAPS", + "@?EMPH" : "EMPH", + "@?ABBREV1" : "ABBREV", + "@?ABBREV2" : "ABBREV", + "@?ABBREV3" : "ABBREV", + "@?ABBREV4" : "ABBREV", + } + + def get_defaults_DataFrame(): + df = pd.DataFrame(data=[ + ["A", Enum_Braille_Proficiency_Level(1), [[1, 0, 0, 0, 0, 0]], None], + ["B", Enum_Braille_Proficiency_Level(1), [[1, 1, 0, 0, 0, 0]], None], + ["C", Enum_Braille_Proficiency_Level(1), [[1, 0, 0, 1, 0, 0]], None], + ["D", Enum_Braille_Proficiency_Level(1), [[1, 0, 0, 1, 1, 0]], None], + ["E", Enum_Braille_Proficiency_Level(1), [[1, 0, 0, 0, 1, 0]], None], + ["F", Enum_Braille_Proficiency_Level(1), [[1, 1, 0, 1, 0, 0]], None], + ["G", Enum_Braille_Proficiency_Level(1), [[1, 1, 0, 1, 1, 0]], None], + ["H", Enum_Braille_Proficiency_Level(1), [[1, 1, 0, 0, 1, 0]], None], + ["I", Enum_Braille_Proficiency_Level(1), [[0, 1, 0, 1, 0, 0]], None], + ["J", Enum_Braille_Proficiency_Level(1), [[0, 1, 0, 1, 1, 0]], None], + ["K", Enum_Braille_Proficiency_Level(1), [[1, 0, 1, 0, 0, 0]], None], + ["L", Enum_Braille_Proficiency_Level(1), [[1, 1, 1, 0, 0, 0]], None], + ["M", Enum_Braille_Proficiency_Level(1), [[1, 0, 1, 1, 0, 0]], None], + ["N", Enum_Braille_Proficiency_Level(1), [[1, 0, 1, 1, 1, 0]], None], + ["O", Enum_Braille_Proficiency_Level(1), [[1, 0, 1, 0, 1, 0]], None], + ["P", Enum_Braille_Proficiency_Level(1), [[1, 1, 1, 1, 0, 0]], None], + ["Q", Enum_Braille_Proficiency_Level(1), [[1, 1, 1, 1, 1, 0]], None], + ["R", Enum_Braille_Proficiency_Level(1), [[1, 1, 1, 0, 1, 0]], None], + ["S", Enum_Braille_Proficiency_Level(1), [[0, 1, 1, 1, 0, 0]], None], + ["T", Enum_Braille_Proficiency_Level(1), [[0, 1, 1, 1, 1, 0]], None], + ["U", Enum_Braille_Proficiency_Level(1), [[1, 0, 1, 0, 0, 1]], None], + ["V", Enum_Braille_Proficiency_Level(1), [[1, 1, 1, 0, 0, 1]], None], + ["W", Enum_Braille_Proficiency_Level(1), [[0, 1, 0, 1, 1, 1]], None], + ["X", Enum_Braille_Proficiency_Level(1), [[1, 0, 1, 1, 0, 1]], None], + ["Y", Enum_Braille_Proficiency_Level(1), [[1, 0, 1, 1, 1, 1]], None], + ["Z", Enum_Braille_Proficiency_Level(1), [[1, 0, 1, 0, 1, 1]], None], + ['NUMBER', Enum_Braille_Proficiency_Level(1), [[0, 0, 1, 1, 1, 1]], "@?NUM"], + #" ", Enum_Braille_Proficiency_Level(1), [[0, 0, 0, 0, 0, 0]], None], + [",", Enum_Braille_Proficiency_Level(1), [[0, 1, 0, 0, 0, 0]], None], + [";", Enum_Braille_Proficiency_Level(1), [[0, 1, 1, 0, 0, 0]], None], + [":", Enum_Braille_Proficiency_Level(1), [[0, 1, 0, 0, 1, 0]], None], + [".", Enum_Braille_Proficiency_Level(1), [[0, 1, 0, 0, 1, 1]], None], + ["!", Enum_Braille_Proficiency_Level(1), [[0, 1, 1, 0, 1, 0]], None], + ["(", Enum_Braille_Proficiency_Level(1), [[0, 1, 1, 0, 1, 1]], None], + [")", Enum_Braille_Proficiency_Level(1), [[0, 1, 1, 0, 1, 1]], None], + ["?", Enum_Braille_Proficiency_Level(1), [[0, 1, 1, 0, 0, 1]], None], + ['"', Enum_Braille_Proficiency_Level(1), [[0, 1, 1, 0, 0, 1]], '"@?BO'], + ['"', Enum_Braille_Proficiency_Level(1), [[0, 0, 1, 0, 1, 1]], '"@?BC'], + ["'", Enum_Braille_Proficiency_Level(1), [[0, 0, 1, 0, 0, 0]], None], + ["ABBREV", Enum_Braille_Proficiency_Level(1), [[0, 0, 0, 1, 0, 0]], "@?ABBREV1"], + ["ABBREV", Enum_Braille_Proficiency_Level(1), [[0, 0, 0, 1, 1, 0]], "@?ABBREV2"], + ["ABBREV", Enum_Braille_Proficiency_Level(1), [[0, 0, 0, 1, 1, 1]], "@?ABBREV3"], + ["ABBREV", Enum_Braille_Proficiency_Level(1), [[0, 0, 0, 0, 1, 0]], "@?ABBREV4"], + ["...", Enum_Braille_Proficiency_Level(1), [[0, 0, 1, 0, 0, 0], [0, 0, 1, 0, 0, 0], [0, 0, 1, 0, 0, 0]], None], + ["-", Enum_Braille_Proficiency_Level(1), [[0, 0, 1, 0, 0, 1]], None], + ["-", Enum_Braille_Proficiency_Level(1), [[0, 0, 1, 0, 0, 1], [0, 0, 1, 0, 0, 1]], "-@?S"], + ["-", Enum_Braille_Proficiency_Level(1), [[0, 0, 1, 0, 0, 1], [0, 0, 1, 0, 0, 1], [0, 0, 1, 0, 0, 1], [0, 0, 1, 0, 0, 1]], "-@?L"], + ["/", Enum_Braille_Proficiency_Level(1), [[0, 0, 0, 1, 0, 0], [0, 1, 1, 0, 1, 1]], "/@?B"], + ["\\", Enum_Braille_Proficiency_Level(1), [[0, 0, 0, 1, 0, 0], [0, 1, 1, 0, 1, 1]], "\@?B"], + ["[", Enum_Braille_Proficiency_Level(1), [[0, 0, 0, 1, 1, 0], [0, 1, 1, 0, 1, 1]], "[@?BPH"], + ["]", Enum_Braille_Proficiency_Level(1), [[0, 0, 0, 1, 1, 0], [0, 1, 1, 0, 1, 1]], "]@?BPH"], + ["<", Enum_Braille_Proficiency_Level(1), [[0, 0, 0, 1, 1, 1], [0, 1, 1, 0, 1, 1]], None], + [">", Enum_Braille_Proficiency_Level(1), [[0, 0, 0, 1, 1, 1], [0, 1, 1, 0, 1, 1]], None], + ["/", Enum_Braille_Proficiency_Level(1), [[0, 0, 0, 1, 1, 1], [0, 0, 1, 1, 0, 0]], None], + ["{", Enum_Braille_Proficiency_Level(1), [[0, 0, 0, 1, 0, 1], [0, 1, 1, 0, 1, 1]], None], + ["}", Enum_Braille_Proficiency_Level(1), [[0, 0, 0, 1, 0, 1], [0, 1, 1, 0, 1, 1]], None], + ["[", Enum_Braille_Proficiency_Level(1), [[0, 0, 0, 0, 0, 1], [0, 1, 1, 0, 1, 1]], "[@?BSQ"], + ["]", Enum_Braille_Proficiency_Level(1), [[0, 1, 1, 0, 1, 1], [0, 0, 0, 0, 0, 1]], "]@?BSQ"], + ["'", Enum_Braille_Proficiency_Level(1), [[0, 0, 0, 0, 0, 1], [0, 1, 1, 0, 0, 1]], "'@?BO"], + ["'", Enum_Braille_Proficiency_Level(1), [[0, 1, 1, 0, 0, 1], [0, 0, 0, 0, 0, 1]], "'@?BC"], + # oldbrailledict_2 = { + # Simple Upper Wordsigns + ["BUT", Enum_Braille_Proficiency_Level(2), [[1, 1, 0, 0, 0, 0]], None], + ["CAN", Enum_Braille_Proficiency_Level(2), [[1, 0, 0, 1, 0, 0]], None], + ["DO", Enum_Braille_Proficiency_Level(2), [[1, 0, 0, 1, 1, 0]], None], + ["EVERY", Enum_Braille_Proficiency_Level(2), [[1, 0, 0, 0, 1, 0]], None], + ["FROM", Enum_Braille_Proficiency_Level(2), [[1, 1, 0, 1, 0, 0]], None], + ["GO", Enum_Braille_Proficiency_Level(2), [[1, 1, 0, 1, 1, 0]], None], + ["HAVE", Enum_Braille_Proficiency_Level(2), [[1, 1, 0, 0, 1, 0]], None], + ["JUST", Enum_Braille_Proficiency_Level(2), [[0, 1, 0, 1, 1, 0]], None], + ["KNOWLEDGE", Enum_Braille_Proficiency_Level(2), [[1, 0, 1, 0, 0, 0]], None], + ["LIKE", Enum_Braille_Proficiency_Level(2), [[1, 1, 1, 0, 0, 0]], None], + ["MORE", Enum_Braille_Proficiency_Level(2), [[1, 0, 1, 1, 0, 0]], None], + ["NOT", Enum_Braille_Proficiency_Level(2), [[1, 0, 1, 1, 1, 0]], None], + ["PEOPLE", Enum_Braille_Proficiency_Level(2), [[1, 1, 1, 1, 0, 0]], None], + ["QUITE", Enum_Braille_Proficiency_Level(2), [[1, 1, 1, 1, 1, 0]], None], + ["RATHER", Enum_Braille_Proficiency_Level(2), [[1, 1, 1, 0, 1, 0]], None], + ["SO", Enum_Braille_Proficiency_Level(2), [[0, 1, 1, 1, 0, 0]], None], + ["THAT", Enum_Braille_Proficiency_Level(2), [[0, 1, 1, 1, 1, 0]], None], + ["US", Enum_Braille_Proficiency_Level(2), [[1, 0, 1, 0, 0, 1]], None], + ["VERY", Enum_Braille_Proficiency_Level(2), [[1, 1, 1, 0, 0, 1]], None], + ["WILL", Enum_Braille_Proficiency_Level(2), [[0, 1, 0, 1, 1, 1]], None], + ["IT", Enum_Braille_Proficiency_Level(2), [[1, 0, 1, 1, 0, 1]], None], + ["YOU", Enum_Braille_Proficiency_Level(2), [[1, 0, 1, 1, 1, 1]], None], + ["AS", Enum_Braille_Proficiency_Level(2), [[1, 0, 1, 0, 1, 1]], None], + ["CHILD", Enum_Braille_Proficiency_Level(2), [[1, 0, 0, 0, 0, 1]], None], + ["SHALL", Enum_Braille_Proficiency_Level(2), [[1, 0, 0, 1, 0, 1]], None], + ["THIS", Enum_Braille_Proficiency_Level(2), [[1, 0, 0, 1, 1, 1]], None], + ["WHICH", Enum_Braille_Proficiency_Level(2), [[1, 0, 0, 0, 1, 1]], None], + ["OUT", Enum_Braille_Proficiency_Level(2), [[1, 1, 0, 0, 1, 1]], None], + ["STILL", Enum_Braille_Proficiency_Level(2), [[0, 0, 1, 1, 0, 0]], None], + # Simple Upper Groupsigns + ["AND", Enum_Braille_Proficiency_Level(2), [[1, 1, 1, 1, 0, 1]], None], + ["FOR", Enum_Braille_Proficiency_Level(2), [[1, 1, 1, 1, 1, 1]], None], + ["OF", Enum_Braille_Proficiency_Level(2), [[1, 1, 1, 0, 1, 1]], None], + ["THE", Enum_Braille_Proficiency_Level(2), [[0, 1, 1, 1, 0, 1]], None], + ["WITH", Enum_Braille_Proficiency_Level(2), [[0, 1, 1, 1, 1, 1]], None], + ["CH", Enum_Braille_Proficiency_Level(2), [[1, 0, 0, 0, 0, 1]], None], + ["GH", Enum_Braille_Proficiency_Level(2), [[1, 1, 0, 0, 0, 1]], None], + ["SH", Enum_Braille_Proficiency_Level(2), [[1, 0, 0, 1, 0, 1]], None], + ["TH", Enum_Braille_Proficiency_Level(2), [[1, 0, 0, 1, 1, 1]], None], + ["WH", Enum_Braille_Proficiency_Level(2), [[1, 0, 0, 0, 1, 1]], None], + ["ED", Enum_Braille_Proficiency_Level(2), [[1, 1, 0, 1, 0, 1]], None], + ["ER", Enum_Braille_Proficiency_Level(2), [[1, 1, 0, 1, 1, 1]], None], + ["OU", Enum_Braille_Proficiency_Level(2), [[1, 1, 0, 0, 1, 1]], None], + ["OW", Enum_Braille_Proficiency_Level(2), [[0, 1, 0, 1, 0, 1]], None], + ["ST", Enum_Braille_Proficiency_Level(2), [[0, 0, 1, 1, 0, 0]], None], + ["AR", Enum_Braille_Proficiency_Level(2), [[0, 0, 1, 1, 1, 0]], None], + ["ING", Enum_Braille_Proficiency_Level(2), [[0, 0, 1, 1, 0, 1]], None], + ["BLE", Enum_Braille_Proficiency_Level(2), [[0, 0, 1, 1, 1, 1]], None], + # oldbrailledict_3 = { + # Lower Contractions + # Initial Groupsigns + ["BE", Enum_Braille_Proficiency_Level(3), [[0, 1, 1, 0, 0, 0]], None], + ["COM", Enum_Braille_Proficiency_Level(3), [[0, 0, 1, 0, 0, 1]], None], + ["CON", Enum_Braille_Proficiency_Level(3), [[0, 1, 0, 0, 1, 0]], None], + ["DIS", Enum_Braille_Proficiency_Level(3), [[0, 1, 0, 0, 1, 1]], None], + # Initial-Medial-Terminal Groupsigns + ["EN", Enum_Braille_Proficiency_Level(3), [[0, 1, 0, 0, 0, 1]], None], + ["IN", Enum_Braille_Proficiency_Level(3), [[0, 0, 1, 0, 1, 0]], None], + # Medial Groupsigns + ["EA", Enum_Braille_Proficiency_Level(3), [[0, 1, 0, 0, 0, 0]], None], + ["BB", Enum_Braille_Proficiency_Level(3), [[0, 1, 1, 0, 0, 0]], None], + ["CC", Enum_Braille_Proficiency_Level(3), [[0, 1, 0, 0, 1, 0]], None], + ["DD", Enum_Braille_Proficiency_Level(3), [[0, 1, 0, 0, 1, 1]], None], + ["FF", Enum_Braille_Proficiency_Level(3), [[0, 1, 1, 0, 1, 0]], None], + ["GG", Enum_Braille_Proficiency_Level(3), [[0, 1, 1, 0, 1, 1]], None], + # Wordsigns + ["ENOUGH", Enum_Braille_Proficiency_Level(3), [[0, 1, 0, 0, 0, 1]], None], + ["TO", Enum_Braille_Proficiency_Level(3), [[0, 1, 1, 0, 1, 0]], None], + ["WERE", Enum_Braille_Proficiency_Level(3), [[0, 1, 1, 0 , 1, 1]], None], + ["HIS", Enum_Braille_Proficiency_Level(3), [[0, 1, 1, 0, 0, 1]], None], + ["INTO", Enum_Braille_Proficiency_Level(3), [[0, 0, 1, 0, 1, 0], [0, 1, 1, 0, 1, 0]], None], #(sequenced) + ["BY", Enum_Braille_Proficiency_Level(3), [[0, 0, 1, 0, 1, 1]], None], #(sequenced) + ["WAS", Enum_Braille_Proficiency_Level(3), [[0, 0 , 1, 0 , 1, 1]], None], + + # Modifiers + ["LET", Enum_Braille_Proficiency_Level(3), [[0, 0, 0, 0, 1, 1]], "@?LET"], + ["CAPS", Enum_Braille_Proficiency_Level(3), [[0, 0, 0, 0, 0, 1]], "@?CAPS"], + ["EMPH", Enum_Braille_Proficiency_Level(3), [[0, 0, 0, 1, 0, 1]], "@?EMPH"], + [" ", Enum_Braille_Proficiency_Level(1), [[0, 0, 0, 0, 0, 0]], "@?BLANK_SPACE"], + ], columns=['plaintext', 'translation_proficiency_level', 'lists_dots_braille', 'search_key']) # Translation_Braille.__name__]) + df.loc[df["search_key"].isnull(), "search_key"] = df["plaintext"] + return df + + def get_defaults(): + # return [Translation_Braille(plaintext, translation_proficiency_level, lists_dots_braille, search_key) for [plaintext, translation_proficiency_level, lists_dots_braille, search_key] in Translation_Braille.get_defaults_DataFrame()] + return pd.DataFrame(data={Translation_Braille.__name__: Translation_Braille.get_defaults_DataFrame().apply(lambda x: Translation_Braille(x[0], x[1], [Character_Braille(x[0] if index_y == 0 else '', x[2][index_y]) for index_y in range(len(x[2]))], x[3]), axis=1)}) + """ + def get_defaults(): + return pd.DataFrame(data={Translation_Braille.__name__: [ + Character_Braille("A", Enum_Braille_Proficiency_Level(1), [[1, 0, 0, 0, 0, 0]]), + Character_Braille("B", Enum_Braille_Proficiency_Level(1), [[1, 1, 0, 0, 0, 0]]), + Character_Braille("C", Enum_Braille_Proficiency_Level(1), [[1, 0, 0, 1, 0, 0]]), + Character_Braille("D", Enum_Braille_Proficiency_Level(1), [[1, 0, 0, 1, 1, 0]]), + Character_Braille("E", Enum_Braille_Proficiency_Level(1), [[1, 0, 0, 0, 1, 0]]), + Character_Braille("F", Enum_Braille_Proficiency_Level(1), [[1, 1, 0, 1, 0, 0]]), + Character_Braille("G", Enum_Braille_Proficiency_Level(1), [[1, 1, 0, 1, 1, 0]]), + Character_Braille("H", Enum_Braille_Proficiency_Level(1), [[1, 1, 0, 0, 1, 0]]), + Character_Braille("I", Enum_Braille_Proficiency_Level(1), [[0, 1, 0, 1, 0, 0]]), + Character_Braille("J", Enum_Braille_Proficiency_Level(1), [[0, 1, 0, 1, 1, 0]]), + Character_Braille("K", Enum_Braille_Proficiency_Level(1), [[1, 0, 1, 0, 0, 0]]), + Character_Braille("L", Enum_Braille_Proficiency_Level(1), [[1, 1, 1, 0, 0, 0]]), + Character_Braille("M", Enum_Braille_Proficiency_Level(1), [[1, 0, 1, 1, 0, 0]]), + Character_Braille("N", Enum_Braille_Proficiency_Level(1), [[1, 0, 1, 1, 1, 0]]), + Character_Braille("O", Enum_Braille_Proficiency_Level(1), [[1, 0, 1, 0, 1, 0]]), + Character_Braille("P", Enum_Braille_Proficiency_Level(1), [[1, 1, 1, 1, 0, 0]]), + Character_Braille("Q", Enum_Braille_Proficiency_Level(1), [[1, 1, 1, 1, 1, 0]]), + Character_Braille("R", Enum_Braille_Proficiency_Level(1), [[1, 1, 1, 0, 1, 0]]), + Character_Braille("S", Enum_Braille_Proficiency_Level(1), [[0, 1, 1, 1, 0, 0]]), + Character_Braille("T", Enum_Braille_Proficiency_Level(1), [[0, 1, 1, 1, 1, 0]]), + Character_Braille("U", Enum_Braille_Proficiency_Level(1), [[1, 0, 1, 0, 0, 1]]), + Character_Braille("V", Enum_Braille_Proficiency_Level(1), [[1, 1, 1, 0, 0, 1]]), + Character_Braille("W", Enum_Braille_Proficiency_Level(1), [[0, 1, 0, 1, 1, 1]]), + Character_Braille("X", Enum_Braille_Proficiency_Level(1), [[1, 0, 1, 1, 0, 1]]), + Character_Braille("Y", Enum_Braille_Proficiency_Level(1), [[1, 0, 1, 1, 1, 1]]), + Character_Braille("Z", Enum_Braille_Proficiency_Level(1), [[1, 0, 1, 0, 1, 1]]), + Character_Braille('NUMBER', Enum_Braille_Proficiency_Level(1), [[0, 0, 1, 1, 1, 1]], "@?NUM"), + #" ", Enum_Braille_Proficiency_Level(1), [[0, 0, 0, 0, 0, 0]]), + Character_Braille(",", Enum_Braille_Proficiency_Level(1), [[0, 1, 0, 0, 0, 0]]), + Character_Braille(";", Enum_Braille_Proficiency_Level(1), [[0, 1, 1, 0, 0, 0]]), + Character_Braille(":", Enum_Braille_Proficiency_Level(1), [[0, 1, 0, 0, 1, 0]]), + Character_Braille(".", Enum_Braille_Proficiency_Level(1), [[0, 1, 0, 0, 1, 1]]), + Character_Braille("!", Enum_Braille_Proficiency_Level(1), [[0, 1, 1, 0, 1, 0]]), + Character_Braille("(", Enum_Braille_Proficiency_Level(1), [[0, 1, 1, 0, 1, 1]]), + Character_Braille(")", Enum_Braille_Proficiency_Level(1), [[0, 1, 1, 0, 1, 1]]), + Character_Braille("?", Enum_Braille_Proficiency_Level(1), [[0, 1, 1, 0, 0, 1]]), + Character_Braille('"', Enum_Braille_Proficiency_Level(1), [[0, 1, 1, 0, 0, 1]], '"@?BO'), + Character_Braille('"', Enum_Braille_Proficiency_Level(1), [[0, 0, 1, 0, 1, 1]], '"@?BC'), + Character_Braille("'", Enum_Braille_Proficiency_Level(1), [[0, 0, 1, 0, 0, 0]]), + Character_Braille("ABBREV", Enum_Braille_Proficiency_Level(1), [[0, 0, 0, 1, 0, 0]], "@?ABBREV1"), + Character_Braille("ABBREV", Enum_Braille_Proficiency_Level(1), [[0, 0, 0, 1, 1, 0]], "@?ABBREV2"), + Character_Braille("ABBREV", Enum_Braille_Proficiency_Level(1), [[0, 0, 0, 1, 1, 1]], "@?ABBREV3"), + Character_Braille("ABBREV", Enum_Braille_Proficiency_Level(1), [[0, 0, 0, 0, 1, 0]], "@?ABBREV4"), + Character_Braille("...", Enum_Braille_Proficiency_Level(1), [[0, 0, 1, 0, 0, 0], [0, 0, 1, 0, 0, 0], [0, 0, 1, 0, 0, 0]]), + Character_Braille("-", Enum_Braille_Proficiency_Level(1), [[0, 0, 1, 0, 0, 1]]), + Character_Braille("-", Enum_Braille_Proficiency_Level(1), [[0, 0, 1, 0, 0, 1], [0, 0, 1, 0, 0, 1]], "-@?S"), + Character_Braille("-", Enum_Braille_Proficiency_Level(1), [[0, 0, 1, 0, 0, 1], [0, 0, 1, 0, 0, 1], [0, 0, 1, 0, 0, 1], [0, 0, 1, 0, 0, 1]], "-@?L"), + Character_Braille("/", Enum_Braille_Proficiency_Level(1), [[0, 0, 0, 1, 0, 0], [0, 1, 1, 0, 1, 1]], "/@?B"), + Character_Braille("\\", Enum_Braille_Proficiency_Level(1), [[0, 0, 0, 1, 0, 0], [0, 1, 1, 0, 1, 1]], "\@?B"), + Character_Braille("[", Enum_Braille_Proficiency_Level(1), [[0, 0, 0, 1, 1, 0], [0, 1, 1, 0, 1, 1]], "[@?BPH"), + Character_Braille("]", Enum_Braille_Proficiency_Level(1), [[0, 0, 0, 1, 1, 0], [0, 1, 1, 0, 1, 1]], "]@?BPH"), + Character_Braille("<", Enum_Braille_Proficiency_Level(1), [[0, 0, 0, 1, 1, 1], [0, 1, 1, 0, 1, 1]]), + Character_Braille(">", Enum_Braille_Proficiency_Level(1), [[0, 0, 0, 1, 1, 1], [0, 1, 1, 0, 1, 1]]), + Character_Braille("/", Enum_Braille_Proficiency_Level(1), [[0, 0, 0, 1, 1, 1], [0, 0, 1, 1, 0, 0]]), + Character_Braille("{", Enum_Braille_Proficiency_Level(1), [[0, 0, 0, 1, 0, 1], [0, 1, 1, 0, 1, 1]]), + Character_Braille("}", Enum_Braille_Proficiency_Level(1), [[0, 0, 0, 1, 0, 1], [0, 1, 1, 0, 1, 1]]), + Character_Braille("[", Enum_Braille_Proficiency_Level(1), [[0, 0, 0, 0, 0, 1], [0, 1, 1, 0, 1, 1]], "[@?BSQ"), + Character_Braille("]", Enum_Braille_Proficiency_Level(1), [[0, 1, 1, 0, 1, 1], [0, 0, 0, 0, 0, 1]], "]@?BSQ"), + Character_Braille("'", Enum_Braille_Proficiency_Level(1), [[0, 0, 0, 0, 0, 1], [0, 1, 1, 0, 0, 1]], "'@?BO"), + Character_Braille("'", Enum_Braille_Proficiency_Level(1), [[0, 1, 1, 0, 0, 1], [0, 0, 0, 0, 0, 1]], "'@?BC"), + # oldbrailledict_2 = { + # Simple Upper Wordsigns + Character_Braille("BUT", Enum_Braille_Proficiency_Level(2), [[1, 1, 0, 0, 0, 0]]), + Character_Braille("CAN", Enum_Braille_Proficiency_Level(2), [[1, 0, 0, 1, 0, 0]]), + Character_Braille("DO", Enum_Braille_Proficiency_Level(2), [[1, 0, 0, 1, 1, 0]]), + Character_Braille("EVERY", Enum_Braille_Proficiency_Level(2), [[1, 0, 0, 0, 1, 0]]), + Character_Braille("FROM", Enum_Braille_Proficiency_Level(2), [[1, 1, 0, 1, 0, 0]]), + Character_Braille("GO", Enum_Braille_Proficiency_Level(2), [[1, 1, 0, 1, 1, 0]]), + Character_Braille("HAVE", Enum_Braille_Proficiency_Level(2), [[1, 1, 0, 0, 1, 0]]), + Character_Braille("JUST", Enum_Braille_Proficiency_Level(2), [[0, 1, 0, 1, 1, 0]]), + Character_Braille("KNOWLEDGE", Enum_Braille_Proficiency_Level(2), [[1, 0, 1, 0, 0, 0]]), + Character_Braille("LIKE", Enum_Braille_Proficiency_Level(2), [[1, 1, 1, 0, 0, 0]]), + Character_Braille("MORE", Enum_Braille_Proficiency_Level(2), [[1, 0, 1, 1, 0, 0]]), + Character_Braille("NOT", Enum_Braille_Proficiency_Level(2), [[1, 0, 1, 1, 1, 0]]), + Character_Braille("PEOPLE", Enum_Braille_Proficiency_Level(2), [[1, 1, 1, 1, 0, 0]]), + Character_Braille("QUITE", Enum_Braille_Proficiency_Level(2), [[1, 1, 1, 1, 1, 0]]), + Character_Braille("RATHER", Enum_Braille_Proficiency_Level(2), [[1, 1, 1, 0, 1, 0]]), + Character_Braille("SO", Enum_Braille_Proficiency_Level(2), [[0, 1, 1, 1, 0, 0]]), + Character_Braille("THAT", Enum_Braille_Proficiency_Level(2), [[0, 1, 1, 1, 1, 0]]), + Character_Braille("US", Enum_Braille_Proficiency_Level(2), [[1, 0, 1, 0, 0, 1]]), + Character_Braille("VERY", Enum_Braille_Proficiency_Level(2), [[1, 1, 1, 0, 0, 1]]), + Character_Braille("WILL", Enum_Braille_Proficiency_Level(2), [[0, 1, 0, 1, 1, 1]]), + Character_Braille("IT", Enum_Braille_Proficiency_Level(2), [[1, 0, 1, 1, 0, 1]]), + Character_Braille("YOU", Enum_Braille_Proficiency_Level(2), [[1, 0, 1, 1, 1, 1]]), + Character_Braille("AS", Enum_Braille_Proficiency_Level(2), [[1, 0, 1, 0, 1, 1]]), + Character_Braille("CHILD", Enum_Braille_Proficiency_Level(2), [[1, 0, 0, 0, 0, 1]]), + Character_Braille("SHALL", Enum_Braille_Proficiency_Level(2), [[1, 0, 0, 1, 0, 1]]), + Character_Braille("THIS", Enum_Braille_Proficiency_Level(2), [[1, 0, 0, 1, 1, 1]]), + Character_Braille("WHICH", Enum_Braille_Proficiency_Level(2), [[1, 0, 0, 0, 1, 1]]), + Character_Braille("OUT", Enum_Braille_Proficiency_Level(2), [[1, 1, 0, 0, 1, 1]]), + Character_Braille("STILL", Enum_Braille_Proficiency_Level(2), [[0, 0, 1, 1, 0, 0]]), + # Simple Upper Groupsigns + Character_Braille("AND", Enum_Braille_Proficiency_Level(2), [[1, 1, 1, 1, 0, 1]]), + Character_Braille("FOR", Enum_Braille_Proficiency_Level(2), [[1, 1, 1, 1, 1, 1]]), + Character_Braille("OF", Enum_Braille_Proficiency_Level(2), [[1, 1, 1, 0, 1, 1]]), + Character_Braille("THE", Enum_Braille_Proficiency_Level(2), [[0, 1, 1, 1, 0, 1]]), + Character_Braille("WITH", Enum_Braille_Proficiency_Level(2), [[0, 1, 1, 1, 1, 1]]), + Character_Braille("CH", Enum_Braille_Proficiency_Level(2), [[1, 0, 0, 0, 0, 1]]), + Character_Braille("GH", Enum_Braille_Proficiency_Level(2), [[1, 1, 0, 0, 0, 1]]), + Character_Braille("SH", Enum_Braille_Proficiency_Level(2), [[1, 0, 0, 1, 0, 1]]), + Character_Braille("TH", Enum_Braille_Proficiency_Level(2), [[1, 0, 0, 1, 1, 1]]), + Character_Braille("WH", Enum_Braille_Proficiency_Level(2), [[1, 0, 0, 0, 1, 1]]), + Character_Braille("ED", Enum_Braille_Proficiency_Level(2), [[1, 1, 0, 1, 0, 1]]), + Character_Braille("ER", Enum_Braille_Proficiency_Level(2), [[1, 1, 0, 1, 1, 1]]), + Character_Braille("OU", Enum_Braille_Proficiency_Level(2), [[1, 1, 0, 0, 1, 1]]), + Character_Braille("OW", Enum_Braille_Proficiency_Level(2), [[0, 1, 0, 1, 0, 1]]), + Character_Braille("ST", Enum_Braille_Proficiency_Level(2), [[0, 0, 1, 1, 0, 0]]), + Character_Braille("AR", Enum_Braille_Proficiency_Level(2), [[0, 0, 1, 1, 1, 0]]), + Character_Braille("ING", Enum_Braille_Proficiency_Level(2), [[0, 0, 1, 1, 0, 1]]), + Character_Braille("BLE", Enum_Braille_Proficiency_Level(2), [[0, 0, 1, 1, 1, 1]]), + # oldbrailledict_3 = { + # Lower Contractions + # Initial Groupsigns + Character_Braille("BE", Enum_Braille_Proficiency_Level(3), [[0, 1, 1, 0, 0, 0]]), + Character_Braille("COM", Enum_Braille_Proficiency_Level(3), [[0, 0, 1, 0, 0, 1]]), + Character_Braille("CON", Enum_Braille_Proficiency_Level(3), [[0, 1, 0, 0, 1, 0]]), + Character_Braille("DIS", Enum_Braille_Proficiency_Level(3), [[0, 1, 0, 0, 1, 1]]), + # Initial-Medial-Terminal Groupsigns + Character_Braille("EN", Enum_Braille_Proficiency_Level(3), [[0, 1, 0, 0, 0, 1]]), + Character_Braille("IN", Enum_Braille_Proficiency_Level(3), [[0, 0, 1, 0, 1, 0]]), + # Medial Groupsigns + Character_Braille("EA", Enum_Braille_Proficiency_Level(3), [[0, 1, 0, 0, 0, 0]]), + Character_Braille("BB", Enum_Braille_Proficiency_Level(3), [[0, 1, 1, 0, 0, 0]]), + Character_Braille("CC", Enum_Braille_Proficiency_Level(3), [[0, 1, 0, 0, 1, 0]]), + Character_Braille("DD", Enum_Braille_Proficiency_Level(3), [[0, 1, 0, 0, 1, 1]]), + Character_Braille("FF", Enum_Braille_Proficiency_Level(3), [[0, 1, 1, 0, 1, 0]]), + Character_Braille("GG", Enum_Braille_Proficiency_Level(3), [[0, 1, 1, 0, 1, 1]]), + # Wordsigns + Character_Braille("ENOUGH", Enum_Braille_Proficiency_Level(3), [[0, 1, 0, 0, 0, 1]]), + Character_Braille("TO", Enum_Braille_Proficiency_Level(3), [[0, 1, 1, 0, 1, 0]]), + Character_Braille("WERE", Enum_Braille_Proficiency_Level(3), [[0, 1, 1, 0 , 1, 1]]), + Character_Braille("HIS", Enum_Braille_Proficiency_Level(3), [[0, 1, 1, 0, 0, 1]]), + Character_Braille("INTO", Enum_Braille_Proficiency_Level(3), [[0, 0, 1, 0, 1, 0], [0, 1, 1, 0, 1, 0]]), #(sequenced) + Character_Braille("BY", Enum_Braille_Proficiency_Level(3), [[0, 0, 1, 0, 1, 1]]), #(sequenced) + Character_Braille("WAS", Enum_Braille_Proficiency_Level(3), [[0, 0 , 1, 0 , 1, 1]]), + + # Modifiers + Character_Braille("LET", Enum_Braille_Proficiency_Level(3), [[0, 0, 0, 0, 1, 1]], "@?LET"), + Character_Braille("CAPS", Enum_Braille_Proficiency_Level(3), [[0, 0, 0, 0, 0, 1]], "@?CAPS"), + Character_Braille("EMPH", Enum_Braille_Proficiency_Level(3), [[0, 0, 0, 1, 0, 1]], "@?EMPH"), + ]}, columns=[Translation_Braille.__name__]) + # remove None 's - rejected inputs + valid = False + while not valid: + try: + temp_dict.remove(None) + except: + valid = True + braille_dict = pd.DataFrame([x.as_dict() for x in temp_dict]) # , columns=['key', 'level', 'msg', 'msg_prefix']) + # RETURNS + # print('Braille Dictionary Creation') + # print(f"type(temp_dict) = {type(temp_dict)}") + # print("temp_dict = ") + # for i in range(len(temp_dict)): + # print(f"{temp_dict[i]}") + # print('') + # print(f"type(braille_dict) = {type(braille_dict)}") + # print(f"braille_dict = {braille_dict}") + + return braille_dict # temp_dict # braille_dict + """ \ No newline at end of file diff --git a/model_gen/system_commands.py b/model_gen/utils_system.py similarity index 83% rename from model_gen/system_commands.py rename to model_gen/utils_system.py index 2d38715..50c8d2f 100644 --- a/model_gen/system_commands.py +++ b/model_gen/utils_system.py @@ -30,18 +30,24 @@ File Operations OpenSCAD, Cura Engine import os -def render_openscad(path_scad, path_stl, path_cmd = 'C:\\"Program Files (x86)"\\OpenSCAD\\openscad'): -# FUNCTION +def render_openscad(path_scad, path_stl, path_cmd = 'C:\\"Program Files"\\openscad\\openscad'): # 'C:\\"Program Files (x86)"\\OpenSCAD\\openscad' # render openscad file and store as file type defined by path_stl -# ARGUMENTS - # str path_scad - filepath of openscad model - # str path_stl - filepath to store (stl) -# VARIABLE INSTANTIATION cmd = f'{path_cmd} -o "{path_stl}" "{path_scad}"' # METHODS + print(os.path.exists(path_scad)) exec_oscmd(cmd) + +def exec_oscmd(cmd): + # execute os system command + # - validation conducted by os system following python execution - NOT SAFE + print() + print('command') + print(cmd) +# METHODS + # os.system('cd C:\\"Program Files (x86)"\\OpenSCAD\\') # pre-command for openscad commands, alt: os.system('C:\\"Program Files (x86)"\\OpenSCAD\\openscad ...') + os.system(cmd) -def make_openscad(path_scad, path_stl, path_cmd = 'C:\\"Program Files (x86)"\\OpenSCAD\\openscad'): +def make_openscad(path_scad, path_cmd = 'C:\\"Program Files (x86)"\\OpenSCAD\\openscad'): # FUNCTION # render openscad file and store as file type defined by path_stl # ARGUMENTS @@ -51,20 +57,6 @@ def make_openscad(path_scad, path_stl, path_cmd = 'C:\\"Program Files (x86)"\\Op cmd = f'{path_cmd} "{path_scad}"' # METHODS exec_oscmd(cmd) - -def exec_oscmd(cmd): -# FUNCTION - # execute os system command - # - validation conducted by os system following python execution - NOT SAFE -# ARGUMENTS - # str cmd - command -# RETURNS - print() - print('command') - print(cmd) -# METHODS - # os.system('cd C:\\"Program Files (x86)"\\OpenSCAD\\') # pre-command for openscad commands, alt: os.system('C:\\"Program Files (x86)"\\OpenSCAD\\openscad ...') - os.system(cmd) def slice_model(path_stl, path_gcode):