From c502d0e4b176f1b3bfef134e408280f839976682 Mon Sep 17 00:00:00 2001 From: Jai0212 Date: Fri, 22 Nov 2024 01:41:54 -0500 Subject: [PATCH] added ability to upload multiple model and fixed graphs --- .DS_Store | Bin 6148 -> 6148 bytes backend/ml_model/model_with_score.pkl | Bin 3762 -> 3760 bytes .../jj@gmail.com/decision_tree_model_1.pkl | Bin 0 -> 2019 bytes .../jj@gmail.com/decision_tree_model_2.pkl | Bin 0 -> 2178 bytes .../jj@gmail.com/decision_tree_model_3.pkl | Bin 0 -> 2019 bytes .../jj@gmail.com/decision_tree_model_4.pkl | Bin 0 -> 2182 bytes .../jj@gmail.com/decision_tree_model_5.pkl | Bin 0 -> 2019 bytes database/output.csv | 352 ++++++++++++++++++ .../ChartComponenet/ChartComponent.css | 5 +- .../ChartComponenet/ChartComponent.jsx | 54 ++- .../ControlButtons/ControlButtons.css | 2 +- .../ChartComponenet2/ChartComponent2.jsx | 44 ++- .../ControlButtons2/ControlButtons2.jsx | 68 ++-- .../ModelTester/Dashboard2/Dashboard2.jsx | 16 +- package-lock.json | 6 - 15 files changed, 479 insertions(+), 68 deletions(-) create mode 100644 backend/uploads/jj@gmail.com/decision_tree_model_1.pkl create mode 100644 backend/uploads/jj@gmail.com/decision_tree_model_2.pkl create mode 100644 backend/uploads/jj@gmail.com/decision_tree_model_3.pkl create mode 100644 backend/uploads/jj@gmail.com/decision_tree_model_4.pkl create mode 100644 backend/uploads/jj@gmail.com/decision_tree_model_5.pkl delete mode 100644 package-lock.json diff --git a/.DS_Store b/.DS_Store index 73b296179c78597c20c3235184c5b07ca1f3c063..eecf827e50d4c9a3d88c1319e497123a4eed8dc3 100644 GIT binary patch delta 31 ncmZoMXfc@J&&abeU^g=(&t@JLH|EI`*vlt2*llL#_{$Ffn?4Ea delta 85 zcmZoMXfc@J&&azmU^g=(?`9qrH)czIh7yKUhGHNY52Py?5*czC3K(*LY&{@d>6w$C eoRpKF#K6EHz`($i4y5(|gTchYn$7GSfB6BFR~W1S diff --git a/backend/ml_model/model_with_score.pkl b/backend/ml_model/model_with_score.pkl index 48b47a9257bf175a47f00f3187754c15b37f79b7..8006993ba39911cf2157d0deb0d155a2d62da4b6 100644 GIT binary patch literal 3760 zcmbVP3v3ic7`~RfKIp@OKno(EpuDt-JW3SvFRhAra)P1(p{(1zz3$q(-D7W0DPnRa z79?(bF}~viqY|ScL8Hb%gh)U@4N&Bz?Hy9U7A3}D#YfbCc4yApB5C7fa^L*(|Ns2o zKl9JtZp#1k8|6NyJxIpcftV3iqQoAYXo@P5saIR3qEw4=R7xb21hI$QpvYQ6GxYg5 zUq@%Ph^Cli4H^Fsp$intre-N7S`gdcsOcK9ixTmuX5l2xG$;v+*u^nvnHW~$mP$hQ zfS9I>2`LtjDhbgsCBb~VB6k+4L`X2tuA-CoD_Wy!i4jwhEes<%%2{p-KA&Am*N!NX zl{ArX$S$WcwGnkpjn0&sk{&i_PWmh`Iuy%t zT$G}5Rmw3ciy69M8M-EmGUkYRF%qIK#V|9Bf!nGlWAWx{*)WyrSTbs9l4(lK#4Z(0 zMK<(=WhP|{H`5L{hQuz^!>-9167;o@y1WLmirh}d1@nUWEkqq=2f|i!T%j)cw@oLj zA91z)?7S5u6bjw)H#X-d2o`BrU5_VJDm5x%qiH1L2{A%+t$5N(i1Y}GSSg4^9jXqeoYWDyj7Hn}nuo`X9z1-MM_mO!uRJy&G(5)oclk=Y zAR$Xpi58bSt*$7aTdu?nu*-6f8JXqV0a~iK#{<2kOJ}k0XuaY>!TfV+=V1=hR_6pj zD#1LO6c)5v5)2?OEFDoclDb8LBk^#YN;-F?k+{-myWd^Yru=&n>e$dYyMI)PSfZ?I z(J-+~Os9aERLIH%Z-u2|$*KmmDdP1==$Sa-*%cvnrF#REu-H>GFs9*!)EmV{L$nO6 z`iO=5O0!siygUb^)_BW<9!t=-lBf&SaIgsRZo~@2MbtBrbEN<2S%sF1)u!Mm#Cr4` zhqwggs}V)ILUNL4OFX6N#GbyAB!dFhbpQhSvZpJGHmvUOJna}4JHh#AMcz5Apn86(!3<=z>ADj0x)BF|s&rA2hMD9Q_b)&$=+}L#7 zGyYtg0flHR}&SrN_Uf&;E}ob0^%oDGena|I4%f#cZDQ>zRLd zcwMBmJq_RH`lp(*{{7kffLwic>=%xlp8s6g*KII6JBI_|_U!p{UhMxd*9ymH;pRhc zPk!n5G>pyFr0N7Nma;(^LofdfoLKzJhoR0iT*w_9oGfs$xAR**X#K3C%l8AX6W4E0 zpZyQ4+Wz~V1!?f+cSY9!0!D;Ctb6jO(Fd(h|L^+w&Pm`1@N;s*jmgIEEq}Ls+t2Gi zkn!jH+mrvM-A6jl79NC4nVkzW`yBtzCtFv%`*PcP>$f-lr;k1V+6H;wdGF6)#;eN1 zj|*pE#ZR#1_T(;!fwZHNm#em}kW`-O(`wVxgz(gwin97x?JaIrW3uH7N< zKA%VR*`M!U4G%~$70mh%W%I)sdciL&7&+`zo!kcVJ&HR8E)HXZix~FI|Js5_FW-H5 z-#Pb}+x02`%pMrU13D-OTv#~C&2HS>vv7o-+8AixKD~E z@xA*$-j?V~>?)!*t*-qEQ~UA@+AnMABGW5`wEsh?R&V%A$$-V z+Vvd}zJzA79oE%s?wn(E!RU_n4$pfO-%4s;y>)SCJ3ON-#C`y#&S{-8r?rFa(;kNB zu6G%w`BVpdy$hZ-etX9FZ9DTj#c&(5JHhhX2d|u&jXez;0*kO`p!R{{ zA20i02VAvw^TXW(yWp{7)3Kk1;X9UMe+OuFBpd7sk-e{r_bDd*vc!*{N!3%UClOQz U67*Av%!2QCcGZ76^!jA=KXPgWUjP6A literal 3762 zcmbVPd2AF_7~fvd7O3ScYAFb)1+-}+A`18oEm&c(AcCBA9A>AT3A?k~nOU$1TEp37 zyzqIW{-FsdVj^Cch*pt;8p|at6}BzV%4O7G42>G~d$aGYGl*H^%VdA=``&kd-|WmZ zWInw)&*!XFq}a|1g#${E*aOX_K}9n363bAO5>XCHrm2|39yCRfHB$@gbC6#_xmt~; z800B3>JdT>1{}QARH1+OR^NC2U4qAC=$iU>oF|ZP$W|!E|X6B%rPqD$Z|xKf)Q16 z3H1qu^{^GzHCdD~N6d=_A?i{HGeaL(Ry`Vu)R)L%Ln#SGgO(;4hEz}N-lCz%VcoQh zsBB>|?JP%-*gf??LgXpp_pK!rX-mj@GMg0p)BNdciF%ct6|m|f3ROv;Ii56bNStQa zX)8%pRn_!AaXCMJu*j0eYV1&Ut)d4ML##r#QmrD^8sTWfL{dQsJ5Ns*&j}e@k*ka0 zs1=D?rbwHR&4xiF>Xm9CjY=(Y$27uD*F2F-yd)AIjie%THL-D84 zq;RCwUj7~!7Y>gohoibh{6n!l&Mf`Y(onQC!p^vN+}OW+pL^r=_p1?_Z`?%L1j9}+Yk14Z8&-kbvdT|8@uM;?# z$u^kEWmcvTSf##s#iNH|j^}i)z{xDO>A@Ku?1l|fzic|RtrbRk_~imGhdXwNoAXHRzD z72Kc)GX<_+?&del`p@%oThX>ZPRxtL1dsk*0w+_&e-z8VfBru3-XDcY{l3i5V218C z`+S+g`vtW->o2xLD|bk7*wSSD{TRQ$`#ibtfZLq`X#3y&AAf4$$Stq$hp|bUbTeJx zwKsB=u9pUp(WD&o+M40%P3z4O0b9 z^1ck=3=ek0=!}^ke78RSzyH5Ce)aI3pR9@luT#SOtpazGD*oS}JhXD#%kh7Gex=g? zX=BffmK{fc*E!+$wxoaOovz0+DHz2!@5{U`(bw4ZL|xig{uAEX^<#c3oZY_z@?Otr zUewwSn;+VDW8JyausvORZOEAYP*80hm|74A`de+CfN2{?;&m2|y&uBsE1=Jky28`I zpDHc4p5A1(oQ3AWvR&4^7hZUtt}hs#g{^PUbq?k_Yd1`PUT#?Z$}w1UQw!W)dXm{c z%p%rd&)+w03a`(KIyJPUpMDEU$fVpDJm|a?biy4@ z!(!mHt-2Fh8(%uw_|h488Gny9ehqXwqD$<2k-e{r%M^otTjJ+WS;@^MWdskiO!~1z PDxqt_{_856NwnlI3DXmi diff --git a/backend/uploads/jj@gmail.com/decision_tree_model_1.pkl b/backend/uploads/jj@gmail.com/decision_tree_model_1.pkl new file mode 100644 index 0000000000000000000000000000000000000000..0d82400dfdccfdec8cc995cd39b8a09a182446e8 GIT binary patch literal 2019 zcma)7&1)n@6z`eLBs1A;m<_BOC5WJ41R30*G7CZvj<9IM2%;kDZdub)Gu3Q=SzW!m zfnCtUCI$*o_xZ1Q77u#Vix5yGpq{+sxOh-sRaYf5$p*J+=GA-kK7RGyuckj~e7(Qq znddHSs%DanSq$o8aU*6_q+KZ(>yj|0MZpSCkG;misED%kZL|-xHJU_Bzq7f}4R!C6ogx)4&mP-!7g1V4IDJf`@$E+a67lNkh%vur4 z1cI7c*T!2cnsP}df`$_75VLu;I)mq_6`g#-s4N8{9;#KXYaf#0*|cRv&~%(7q>xlH z)Gz9+QIeMkeH(Fwg3*G(OiFWpTNne{VVDyd=bX+solmkflUW*tB*a4w)ddTJq%^^k zVGZnSS|<5+H_QaMO?5jS-`zHs(ugr5sk0tPSfPcUzK?~)FC_5;x>Bz~HVB{vsk5GRBCDj?q%X2N6RS9J9(#9YNJ2; za_dmu_|0Fl`<2-0J3q&m=G?wh9{APjz+ZJHBcJa(b-^wgR=T{Edf@Nxe*gDR@BQf8 ze^u+X(YFgv-^khLAFJ5?Z=K(K-b0Jad*t{fgIs{eoS8$W!E@2|e=a~0ou literal 0 HcmV?d00001 diff --git a/backend/uploads/jj@gmail.com/decision_tree_model_2.pkl b/backend/uploads/jj@gmail.com/decision_tree_model_2.pkl new file mode 100644 index 0000000000000000000000000000000000000000..5a69f38c379bb6dead158db7f4b95c3eac204ddc GIT binary patch literal 2178 zcmbtW%ZnUE81I?w*`0l4Gl}M*ED}&~av6+KSwZN*2?T8z!55+?Wo=K*RAYB_TV0*F zprD7$x=<%m;#L0wJ>}$K5m699FM_ygqTopn!IOAM{HnTYcV;(%h($ABeUJK{zv`ZM z{0}ZRJ+t0cZP`e(0ZEiRQoNoJ%vncpLOLi)a8Zy#$)jgT6c=&Eo(FkPOXFcoxVo%P zzN@r@`H07YaIjF)AH^(IvRULwEIa!LCh5-ds%3HRl)=CuuCP@0x3am)r; ziVA@R0se^g8mD;)nXf}y5hu7HYQm){-v)*Q^HG!|oa7Ww7#&D6mWhnT5sIKjsLLjS z7*3%whyiV7Wty*dqKuPHS|%dKoa1#Rmk=jW#tOm9NI)}X!x$<##|D+jWfgjtRIj$C zHq^7K9o9nslA`y@#z3s+L?5X?v#K`VtF$w+_Ll1R`%mA5Wq!gysI|>=Frns%umRzy z4`K0$pb^i?ywL0{w3O)0oM{d02pp2jY^R^5iqMw}3}vOrOHm*_m!`!BQuH3Wq7$X} zxiss*+%N0#RB})3NzT*B^;&L-HM>zdJjB{{e@xC65l*m199``->&|ivU6BVSXAhbA zvZ3({jXyk%XDtOZY7m2?(BGeS4booSoCpA^gf(3hpqwt69sr(Dl$A`Va1kbE;I-e= zqG`a)i;q3BJ0ALAzbzLMG88DHaWYVHksDN7Zq8x{u8N?5W14B3rUR+cGtu$fy;1U5 zbuGvM?bRGkW4NVkghm+>8C->-fWGP~Ufw$x`uH?v^jJb~tmrFr7&d{v3bY0EoIW|6 z80jrf9tX?wG!0JxMR2kW^fllg0*bYV^3+sIrtoTFuZ~q2b^+`y4Ui|dVB8KH3wH93 zuUNl(_nD8_7pJcVcUgT!PIsN1Lrh~z@0h=X@z=}GeYkx!IOs%%c6QFsSh;Vh^INgk zf{K0<*q5rcI?=ToPv6MNb;B}Nzvb+v{a&|zy*oZX=NuWj(sk^t-8j9grxG9S{;=`o zKi|FdZQ%5kd}XKp$=vn+cKN&hROegWih7>w%e)o1c~q?5UHR$_czz0|^J?y#zti~t zw|~=ldH*^7?dmu0wAl+dDdA&ui?;=Uy}qGny4m|QX@BzZXXD=jL;m_P_~mD_f7SPFLdAC2lIy|tl@y*og7+VI3ZBpR*}q`c??FYsw|eKr`E_)!-1Bs4<(h0E j`?5tB2-p7=;B$7W^JwQ`1#`}Vx9*D|3WYqPYU8e5e#~XtR!fHcnEs%C=%3H-CeuWyBkc=%6=hqdu_7L0sJhJtz$^N@UVxj2JmsaYL-$f(Q&R@_(nw61*!$Fph6 zte|`lMT3Tl=J=EXdfBJ(76Q#Er(P&0f`xSRvm zIt#tp3arD^u;|v@##!+1RLy~0O_+w%pIU)V@sKSnaNv&Zwx_dAK&a}ehRmt_HYtsGRb60^jz$cAO!q7 z`~_X8f0rqa^Khswb2DmUiiZO*_o^0k8R?oN_%5h z{8i`b^&fA1`uMj_tAf9~YgBzBC)YovQtp3g{Hk^R=@|PYR=?j2ZyP`^k93WCt9Wz1 z0@vQemtPCZ#5esc{2JYj^{@Z_;rZ_!<5$=hHu3+Lf8m?g@VVlcJ{NfVmhpwZW!Oek!{f|G=>zZ@%JH4(rKaD@xz{i-{ zALWR)MrBGVq_G=mS(iVH@cG^O;NB|(vEn#^lU}7N%?0+&M=`r#`w87 W-g&U|0N`db)gKpFb}kjsvd(|xYPvT7 literal 0 HcmV?d00001 diff --git a/backend/uploads/jj@gmail.com/decision_tree_model_4.pkl b/backend/uploads/jj@gmail.com/decision_tree_model_4.pkl new file mode 100644 index 0000000000000000000000000000000000000000..36a147c3474bdf4a21dd0dd1d223e3740b916455 GIT binary patch literal 2182 zcmbtWO^X~w819+v*`57Jm;{on5=8tUo6C@xC>s!aaD<=@BZzuXW2L62W~#Bfx~Z;? zE=JHpHZBw%O!*5u3!cQ|;(zd@2Z`jO_>r3+7~iU{>Y3iG7_n%ky54%9_w%W)`OyFD z{jO)m2Wm@p(riK!B~KLZBm{HT7o3njiV|EDq)_tY3nYq*IAgDZe5j@IG$vf#QfEI> z+Q4eWV?j7*D7iwI;90(-WVgtZSb$tfe@qIYGJgV1P2Qf%bOEx%W zlPpDrz=FW~gti)|c?r?)KwJ?gxFBl5q$z=Q41m=r$`MX-iWiiQq#4UZ#^MM?kmN`n zvq2z+Q^*W_KxtW-<~#i;EMPv*Tj~6QQAHDnwvi*mx~A|ShJ3954&xrxeHa1M;3bz zk@>QtIShqA-sH5F0v$Dx!BFVmA9f4E-rieq0HK5}ofI>^-5YG@nqEl}xB`9Xe*{ zb-$%`Q-Gz{pSd`14?Q#5l4}W>3KY>enJBr=4Xf>H#c~JEilD$_nrWS`BdO9oG4AcT zQSwxEEXV{M+&P}ca8lU}%`zl1I0{n%b=6tCaj-G;Qj;^fEupuo=$mvJc42-C<{r#f zG;+Go(nFD(p!qgU!$)C8fZT%lDy+}JjJ1XGe4``{z8c@#yQ&NaK=z&{$n*QqZpV#f zN0!F?N3i=z=Wg=(Z$V8avwv>jaE>t@i*xd7=?|_y`P1Dm#=ius4ZDxk_$4d%55@lw ze0}M;{Xc)b9jr9)rw4ASPvqkG%P#ExzSC>Q^?Tsti&*{sPxxkiHV6L|@9Jc6HQwd5 zW;dF8{@~y8w-=7*>g(!RnLAn6zbWt5^?%U(n{jz{{11x%zx8+gsPgL7{>?XS`5I12 zxQq_@S^(MGHx*6yhF@0D+qU)J2d|m&t)1@#pFZ&-Jl_Q0eU-xVv(=kZrNX;kCwH^w zIh?ao*}qf!sgQGhXQ?Tl@9WgcvFsuHu|?Mi*Z&vbIy>Kgy8o1d%}${&KXp0y@q!s; F|8GIN&kFzm literal 0 HcmV?d00001 diff --git a/backend/uploads/jj@gmail.com/decision_tree_model_5.pkl b/backend/uploads/jj@gmail.com/decision_tree_model_5.pkl new file mode 100644 index 0000000000000000000000000000000000000000..05d1ec5822962db7f2a6e30e56eb514973d0a715 GIT binary patch literal 2019 zcmb_d&x;&I6rP#wnVm^C%VZ&Dl|=*vR|rG0M43RKhl~)kVFXbTHI_9!HB(KxtJ~`8 z#03R&$gT^8sCoV?p2dS6^&%`NvY?*4>`^?Zuez&tXEq54rfKHYt9n1a_ug02AA4W! zFW1WFBiPix$igU(Qt=w@56x~gjhKXc@Z23R z0Xm_K6q9HH+M7ip0^QEDI8wNYJ7bnB(4B;SKqf3x9DLL%akUNyS0Ap&bNJ1dfkNt%#c zQN>U{XQD<)Rv`3k#1%?La|UxE%ld6%bm)X(MrfRII%jkyNkyts5rrhgB1ihH1wjN& zurkbneHBHLZTG@dvR+ceDxy--ZO|)3vM?37l0~Sno4Q#Vf?gJr%H$pdwYxB^k6{;H zh0UNIcz1z6p_>!6oiXFmc%=_}pH!zyy8a=IMx&Si!KeHQdE8Wv-qz`GxI9bxzP<`N*3pl*snn)B1a65>KWkuWWUGBj>h^twM%r)TiN_XhO&>RPY~ zIeD^{M0icbjLcG^QoIUNg?%+uymfLg{K_I{%vgfj4)C}6G-#uI2W1!K4dXeT8|ec* z*U|D_o&-;!Bj@xmgZ71*aO7#Zg z&$kZM&0qXAdtQmHfwOarX)c^Q$%PHU@T4GdFVn`P(Y?{A*{o828ZPs{LpGmJ3wM^?_5}zQgDGQJs5(|BHX)yZ7<^ z*>`=a;E`k(%auYaW! z`$yEMARYK$Jo6I1-}pa$mEik_JwF~*W#@hmkL;Y^>*e#iU&$XI;(r{^KrhC+OYEN+ exy7XU7~|*SQt$cR7T{qsHy; { // Step 1: Identify unique feature1 values and assign colors dynamically const uniqueFeature1Groups = Array.from( - new Set(chartData.map((item) => item.feature1)) + new Set(chartData.map((item) => item.feature1)) ); const colorPalette = [ "rgba(54, 162, 235, 0.7)", @@ -35,7 +29,7 @@ const ChartComponent = forwardRef(({ chartData, sliderValue }, ref) => { // Step 2: Sort and prepare data for the chart const sortedChartData = [...chartData].sort((a, b) => - a.feature1.localeCompare(b.feature1) + a.feature1.localeCompare(b.feature1) ); const labels = sortedChartData.map((item) => item.feature2); // Only feature2 labels @@ -55,10 +49,10 @@ const ChartComponent = forwardRef(({ chartData, sliderValue }, ref) => { data: accuracyData.map((d) => ({ x: d.label, y: d.accuracy })), backgroundColor: accuracyData.map((d) => d.color), // Bars are filled with the color for each feature1 group borderColor: accuracyData.map( - (d) => (d.accuracy > sliderValue ? "rgba(255, 0, 0, 1)" : d.color) // Red border if above threshold, else use the same color as fill + (d) => (d.accuracy > sliderValue ? "rgba(255, 0, 0, 1)" : d.color) // Red border if above threshold, else use the same color as fill ), borderWidth: accuracyData.map( - (d) => (d.accuracy > sliderValue ? 3 : 1) // Increased border width if above threshold, else default + (d) => (d.accuracy > sliderValue ? 3 : 1) // Increased border width if above threshold, else default ), borderCapStyle: "round", borderJoinStyle: "round", @@ -102,11 +96,33 @@ const ChartComponent = forwardRef(({ chartData, sliderValue }, ref) => { offset: true, display: false, }, + title: { + display: true, // Display the x-axis title + text: 'Demographics', // Set the x-axis label + font: { + size: 16, // Font size for the title + weight: 'bold', // Make the title bold + }, + padding: { + top: 8, // Space above the title + }, + }, }, y: { min: 0, max: 1, beginAtZero: true, + title: { + display: true, // Display the y-axis title + text: 'Accuracy', // Set the y-axis label + font: { + size: 16, // Font size for the title + weight: 'bold', // Make the title bold + }, + padding: { + bottom: 8, // Space below the title + }, + }, }, }, responsive: true, @@ -159,10 +175,10 @@ const ChartComponent = forwardRef(({ chartData, sliderValue }, ref) => { ctx.save(); ctx.fillStyle = "rgba(200, 200, 200, 0.3)"; ctx.fillRect( - left, - chartArea.top, - right - left, - chartArea.bottom - chartArea.top + left, + chartArea.top, + right - left, + chartArea.bottom - chartArea.top ); ctx.restore(); }, @@ -181,10 +197,10 @@ const ChartComponent = forwardRef(({ chartData, sliderValue }, ref) => { })); return ( -
- -
+
+ +
); }); -export default ChartComponent; \ No newline at end of file +export default ChartComponent; diff --git a/frontend/src/pages/DashboardPage/ControlButtons/ControlButtons.css b/frontend/src/pages/DashboardPage/ControlButtons/ControlButtons.css index 57aa68b3..69b9e981 100644 --- a/frontend/src/pages/DashboardPage/ControlButtons/ControlButtons.css +++ b/frontend/src/pages/DashboardPage/ControlButtons/ControlButtons.css @@ -77,7 +77,7 @@ input[type="file"] { /* Style for the Download Graph button */ .file-import-container button:nth-child(3) { - background-color: #45a049; + background-color: #0088cc; color: #fafafa; } diff --git a/frontend/src/pages/ModelTester/ChartComponenet2/ChartComponent2.jsx b/frontend/src/pages/ModelTester/ChartComponenet2/ChartComponent2.jsx index eb9eb807..b47b00f0 100644 --- a/frontend/src/pages/ModelTester/ChartComponenet2/ChartComponent2.jsx +++ b/frontend/src/pages/ModelTester/ChartComponenet2/ChartComponent2.jsx @@ -2,7 +2,7 @@ import React, { useEffect, useRef, useImperativeHandle, forwardRef } from "react import Chart from "chart.js/auto"; import './ChartComponent2.css'; -const ChartComponent2 = forwardRef(({ chartData }, ref) => { +const ChartComponent2 = forwardRef(({ chartData, generationalResults }, ref) => { const chartRef = useRef(null); const myChartRef = useRef(null); @@ -27,11 +27,49 @@ const ChartComponent2 = forwardRef(({ chartData }, ref) => { ticks: { autoSkip: false, // Ensure all x-axis labels are shown }, + title: { + display: true, // Show the title + text: 'Model Name', // Set the x-axis title + font: { + size: 15, // Increase the font size + weight: 'bold', + }, + } }, y: { min: 0, max: 1, beginAtZero: true, // Ensure y-axis starts at zero + title: { + display: true, // Show the title + text: 'Bias', // Set the y-axis title + font: { + size: 15, // Increase the font size + weight: 'bold', // Make the text bold + }, + }, + }, + }, + plugins: { + tooltip: { + callbacks: { + label: (tooltipItem) => { + const index = tooltipItem.dataIndex; // Get the index of the hovered bar + + // Access the generational result for the hovered bar + const generationalResult = generationalResults[index]; + + // Build the custom tooltip content using generationalResults data + return [ + `Bias: ${tooltipItem.raw}`, // Bias value of the hovered bar + `Race: ${generationalResult.race}`, + `Gender: ${generationalResult.gender}`, + `Age: ${generationalResult.age_groups}`, + `State: ${generationalResult.state}`, + `Variance: ${generationalResult.variance}`, + ]; + }, + }, }, }, }, @@ -42,7 +80,7 @@ const ChartComponent2 = forwardRef(({ chartData }, ref) => { myChartRef.current.destroy(); // Cleanup on component unmount } }; - }, [chartData]); + }, [chartData, generationalResults]); useImperativeHandle(ref, () => ({ downloadChart() { @@ -60,4 +98,4 @@ const ChartComponent2 = forwardRef(({ chartData }, ref) => { ); }); -export default ChartComponent2; \ No newline at end of file +export default ChartComponent2; diff --git a/frontend/src/pages/ModelTester/ControlButtons2/ControlButtons2.jsx b/frontend/src/pages/ModelTester/ControlButtons2/ControlButtons2.jsx index e0cded55..7bcaa927 100644 --- a/frontend/src/pages/ModelTester/ControlButtons2/ControlButtons2.jsx +++ b/frontend/src/pages/ModelTester/ControlButtons2/ControlButtons2.jsx @@ -70,8 +70,8 @@ const ControlButton2 = ({ setUploadedFiles }) => { if (!files.length) return; // If no files are selected, exit - if (uploadedFiles.length === 5) { - alert("You can only upload 5 models at a time."); + if (uploadedFiles.length === 5 || uploadedFiles.length + files.length > 5) { + alert("You can only upload 5 models."); return; } @@ -80,33 +80,41 @@ const ControlButton2 = ({ setUploadedFiles }) => { for (let i = 0; i < files.length; i++) { const file = files[i]; - if (!file.name.endsWith(".pkl")) { - alert("Please upload a model in .pkl format."); - return; - } if (!currUser || !file) { alert("Error: Missing required data."); return; } - if (uploadedFiles.includes(file.name)) { + if (!file.name.endsWith(".pkl")) { + alert("Please upload a model in .pkl format."); + return; + } + + if (newUploadedFiles.includes(file.name)) { alert(`File with name ${file.name} already uploaded.`); - continue; + return; } if (file.name === "model.pkl") { alert("You cannot upload a file named model.pkl."); - continue; + return; } - const formData = new FormData(); - formData.append("curr_user", currUser); - formData.append("model_file", file); - formData.append("dashboard", file.name); + newUploadedFiles.push(file.name); + } + + // Prepare for the file upload + const uploadedFilesToPush = [...uploadedFiles]; + + try { + // Make a POST request to upload models + const uploadPromises = Array.from(files).map(async (file) => { + const formData = new FormData(); + formData.append("curr_user", currUser); + formData.append("model_file", file); + formData.append("dashboard", file.name); - try { - // Make a POST request to upload model const response = await fetch(`${VITE_BACKEND_URL}/api/upload-model`, { method: "POST", body: formData, @@ -121,25 +129,27 @@ const ControlButton2 = ({ setUploadedFiles }) => { const responseData = await response.json(); console.log("Success:", responseData.message); - alert("Model uploaded successfully!"); - // Add the file to the list of uploaded files - newUploadedFiles.push(file.name); + uploadedFilesToPush.push(file.name); // Add to local list of uploaded files + }); - // Update the state with the new list of uploaded files - setUploadedFiles(newUploadedFiles); - setUploadedFilesState(newUploadedFiles); // Update local state + // Wait for all files to be uploaded + await Promise.all(uploadPromises); - // Save the new list to localStorage - localStorage.setItem("uploadedFiles", JSON.stringify(newUploadedFiles)); + // Update the state with the new list of uploaded files + setUploadedFiles(uploadedFilesToPush); + setUploadedFilesState(uploadedFilesToPush); // Update local state - // Reset the file input after uploading - event.target.value = null; + // Save the new list to localStorage + localStorage.setItem("uploadedFiles", JSON.stringify(uploadedFilesToPush)); - } catch (error) { - console.error("Error during model upload:", error); - alert("Error during model upload: " + error.message); - } + // Reset the file input after uploading + event.target.value = null; + + alert("Model(s) uploaded successfully!"); + } catch (error) { + console.error("Error during model upload:", error); + alert("Error during model upload: " + error.message); } }; diff --git a/frontend/src/pages/ModelTester/Dashboard2/Dashboard2.jsx b/frontend/src/pages/ModelTester/Dashboard2/Dashboard2.jsx index fa739e7a..26e1240e 100644 --- a/frontend/src/pages/ModelTester/Dashboard2/Dashboard2.jsx +++ b/frontend/src/pages/ModelTester/Dashboard2/Dashboard2.jsx @@ -10,18 +10,18 @@ const Dashboard2 = () => { const [currUser, setCurrUser] = useState(""); const backgroundColours = [ - "#00CC00", // Darker bright green 1 - "#66CC66", // Darker bright green 2 - "#66FF66", // Bright green 3 (unchanged) - "#99CC99", // Darker bright green 4 - "#99FF99", // Bright green 5 (unchanged) + "#FF5733", // Vibrant Red + "#33FF57", // Vibrant Green + "#3357FF", // Vibrant Blue + "#F3F33B", // Bright Yellow + "#F33BF3", // Bright Purple ]; const [graphData, setGraphData] = useState({ labels: ["Model 1", "Model 2", "Model 3", "Model 4", "Model 5"], datasets: [ { - label: "Models", + label: "Bias", data: [0, 0, 0, 0, 0], backgroundColor: backgroundColours, }, @@ -30,8 +30,6 @@ const Dashboard2 = () => { const [uploadedFiles, setUploadedFiles] = useState([]); - const tempUploadedFiles = ['model1', 'model2', 'model3', 'model4', 'model5']; - const [generationResults, setGenerationResults] = useState([]); const fetchEmailAndDemographics = async () => { @@ -188,7 +186,7 @@ const Dashboard2 = () => {
{Object.keys(graphData).length > 0 && ( - + )}
diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 5f69a815..00000000 --- a/package-lock.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "Cash-App-Bias-Busters", - "lockfileVersion": 3, - "requires": true, - "packages": {} -}