From e60db0c12b39fa1edc4e67accdb5ecbf630acec9 Mon Sep 17 00:00:00 2001 From: dragdra Date: Tue, 2 Sep 2025 17:58:21 +0900 Subject: [PATCH] =?UTF-8?q?[2-14~18]=20JPEG=ED=8F=AC=EB=A9=A7=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=EC=B6=94=EA=B0=80=20[1-25~27]=20=EB=A8=B8=EB=A6=BF?= =?UTF-8?q?=EB=A7=90=20'DIAT'=201,2=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=A4=91?= =?UTF-8?q?=20=ED=95=9C=EA=B3=B3=EC=9D=B4=EB=9D=BC=EB=8F=84=20=EB=AF=B8?= =?UTF-8?q?=EC=A0=81=EC=9A=A9=EC=9D=BC=20=EB=95=8C=20=EC=98=A4=EB=8B=B5?= =?UTF-8?q?=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 250901_DIW_2508D_TEST.xlsx | Bin 0 -> 15607 bytes 250902_DIW_2508C_TEST.xlsx | Bin 0 -> 8172 bytes 250902_DIW_2508D_TEST.xlsx | Bin 0 -> 13281 bytes DIW_2508A.json | 22 +- DIW_2508B.json | 22 +- DIW_2508C.json | 23 +- DIW_2508D.json | 22 +- diwScoring2.py | 1352 ++++++++++++++------------- zzz.xbook | 2 +- 회차별채점자료/2508/DIW_2508A.json | 30 +- 회차별채점자료/2508/DIW_2508B.json | 22 +- 회차별채점자료/2508/DIW_2508C.json | 23 +- 회차별채점자료/2508/DIW_2508D.json | 22 +- 회차별채점자료/2508/_DIW_2508A.json | 840 +++++++++++++++++ 회차별채점자료/2508/_DIW_2508B.json | 841 +++++++++++++++++ 회차별채점자료/2508/_DIW_2508C.json | 840 +++++++++++++++++ 회차별채점자료/2508/_DIW_2508D.json | 841 +++++++++++++++++ 17 files changed, 4154 insertions(+), 748 deletions(-) create mode 100644 250901_DIW_2508D_TEST.xlsx create mode 100644 250902_DIW_2508C_TEST.xlsx create mode 100644 250902_DIW_2508D_TEST.xlsx create mode 100644 회차별채점자료/2508/_DIW_2508A.json create mode 100644 회차별채점자료/2508/_DIW_2508B.json create mode 100644 회차별채점자료/2508/_DIW_2508C.json create mode 100644 회차별채점자료/2508/_DIW_2508D.json diff --git a/250901_DIW_2508D_TEST.xlsx b/250901_DIW_2508D_TEST.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..2d4a373b95fb9ea0b1d930768afdb89d4595638d GIT binary patch literal 15607 zcmaKT1z1(v*60QSDd~_#8c7N1kPhjP4r!#NC6x|o5Rh)98$m!Ck&^E2?uLKuy*=mL z)+Zri4*xJ2iF|@N| zcD1&W8<0b3Wkp3;XjXQvO$;H;MiUbVNo^cpcJi;GxAwc*--Q#hadYb?%480vpsD#J ze#pFH&Cb^KNO+9$O0f4wMo7lWyOL+KzG3Br=-FhX585)V$9?>tp>qFRsx8|bVU{p+ z8i*Hhso+(jXs2l_QUqZ7{2-8SA4~P zsSv^`HF5xm&HxJnVg9EIMz#(nU>*9R2jtsWQ3LhiSLb+lC*YJ4P=@8npFBfqXOd}T z%Dl{K&!3$hjxWZ3|8U{)b;3XzH5V^336@|U#5DJz?r5NNE$@NjRTJ-&a&wBI-S+Mtfqnu~F3^60W~vCy~JNvY93Ary(CE-jmpj zrwj%TpC2oDPPgE)wj###&ck!C+ZWyir|`D)_Xtk&j5_H~GUd*ciNf0|M6e8h^*>FF z9p}FJp*~2zl%z}3%uM>cfhmTwGy%Su#kG3bWyzU3e)M|ds%`)2&inFr*Ad|??<;)u zU7j?9{%xK_ozIjQ2q4gBS`Y{uFpsMhi=(-TwF&g^XJ7;EYH7cn;>PjXFCBC>JF`aV zeC}IQh5gpTdAcgmZ&#koA5$aT%FQ^+&%0UjIYw{%qupq^ugUyyjGNc};*#qd+-}Ev z%&#{Bf?|(c4JKKp#~Nx`<`!PDQDMGdCCDp1XhF_-saLIK0czv+?7_xrn|U9KDC>&T zJEpUsO~^tywpBGftL|rEmGM~8*uYbd(Oh^?RY}WMpS)_7jQs+)S2f%u3kLhu3!3_% zs-sJ*j+?1DL6d<^UJ^E68&)C>a_@fIycKz^pheZz_7+PsA@w(1L%*ba-uHOM!he-M z%NoW-WP8NNo1)S0>~Yqhd%~)77w~UYC2R1Y%2-w{4(gcZ9zkO zTkhWc|0|P6mVGfiHvu7HfX9|)wl;Z_0l@#N#5>(=8-ArFsFuALx zAF*KzA*KX;vQ#97%|?0_pAm3T)menOfbCh^gxEbF9(4Z2Hc8-BhKBT%-vx#Q;nL@~ zYj20Ft{>(|44tVp&SWKM;KC$4p64j!Wb7DojcYk9{>)E;jnx;6g76|BfrUz{#O;|jb;&NjG#gHPG6K$ z|5y|nX0#p`fZHD$iP=mVz%7%sn`y5Bcblr$CjEWmeXr?lomappyA|WdbIB2WnH6-J zJfTfCj)z%Enn>UL)GgBr133iqN!gI$59>(_Un>oQ{x=WbVjcn`ntPROJnFKc+y&SZp{T# z4|lI7sr*WlG?^&zB4vFmUr^QEg#I{q+K#kgtWAy7t2%7L6@ry2LS(b4aw-!yzFJyO zSI4itvRRtpD9AW)$*;d&)rZ0^TI(RYRTJA(O~Wm7QvTCUp0pR0&x}8sq{bzkg!B4L z*Lj69hgBs(w2n}u>4Ejvlo?*`)K5|M$ivE!wr!W29j=5+Jd<$so}XS>uTKmOU9W#v zD$CmEk04QF=_{CVlBz(?vAb}e=c#SaK1`#`EGD@Yu6)* zzRI_*f1)c|;&nE=d}R~EC-w5PTL&hLqc|*O95DhOKHG}oUUVb^HcVe^kJth1d*fVU zpHEjP-;Pl0>2dpu1$n&189xNb>;0m}!U-uug@1zYu)Mz?W9bq$e#Pi(?Wf9SJc|EA zH2Av!yMyS2D)n*66b*|1^pa{{17Q=5foz+*O$rn3{j}bQKo!1##Bo;Q0%>L7+hq5; zR`H^HjWNqS;>GJwrl#Fu%NR`dX@RN&T6x>fNC)dGgKJboSZo z0;njU#%e)foiI0|0xSz^uetQC1={+YY|M`f+;9~XB+n_>RlK=P0TQ+yFY zplcxz=rOc`xY#J#%`# z*7Z%N`1$UvSM@i(>FRO(%JVhr=b;^C9g9!Ai>Cr_H_j#xw3@7H=L7hf^>u&ZiRL)Z zdhG^yGG4O?P37vA2I`)Q-?>d~?_6ZJ1uRbwyt_X=*t&joY*KHVynD4js^;?US!iYD zmoxWE&sonY!J9F`Zxr5)pAu$|jy!5Txu+kMo*dn5+by>p%mmhEdY^3BxTXoZGzjXR zDvawg*U{KJ<<0kS^I_d!G5pYkb7rvY9larNP}x~vC;do>%2v<`Qbj37edC!!*{L+2hXmb z@h@~;kbpGf*~h-{o)sFfP@Wb_T)V{Rk@q@uy4M@AJbb5FknrG}aQtf6=~0&+=~-d6 z9_bD7i}VSMCi?^w}Iy=7rrQ2v|%xsa?5_ZZKYE*tlW4V@X+Vx4gD{M&qDM0S)oA@Tq#*2jTV@uIxxtd)ukl7f#>{V>H@VX7Y(nr586rN(*r z0zL}OI0*R8K7H_ttxbiMI~H3!q)=E55aUDj3w2|L>U7&z{Wm`Xr$yN&J}g+^Ys_|&|2izNZhkn zMojSr?YnR5Pmxvp2~1+NwkL&agM<(KCsSC%999C_Y=ZK6s@jDOooP|CW;Pzfn~HMu zW#A$pSMt4hBx%WA6d;u(ih_z`>H_#eZ->mCbePkdW< zD(Rw-(9vW$=zaoDz{GB14aG`1Sg3RwW1y^MoEQUJM{>+5c#6+&78w&9m!-3Jv00R0i7!MbwFEf@2a4Q9lsZu5`Oz~4# zUYq~KC_*&H%K=MGoZo7X0+0Yg$q^Zx6q=Z2xJTKH>5JGXeK=Z7tG802KGpeROt8P+ z`?Jgm@T}}gg(`BR%ZyNvGri|GbhmVAy(pkz+G@R!9?6u@8j(T)$9PqKIbK}8cz9KQ z6yA^cMiL7pBc`WHp@bF?WBo6%n9-8sgR%&CJBnFvh}OuFo1DV#;13ZXLVsm46W3!@ z=dT_orA}qggDsjhY+Q~fKav?g@W$OTFjoYxi-QaX zN5qW%!NQ|3l;P@C0h=i*!1`5Cyk=2P1_!U9XB@&hl8FI~Hf*rG;fxO(uFlA>?WYppV z$j?bi9(yzM&vb@=I}JUV&}e#o)n-U`QgoXAEMoYCWUah>_}B4}|8kqjp*N!o*O!Ld z$*pvAR&Q-wj(2Ry zggmZ}wl1%elLv%8r+Hsq-tH}TB6erU>CF_~H+s3;tsbB5E$zNIIc#$y z4cNR{?pV!RFV!c#+wa;QXDRh+xU{>pIA1=kWNG%iakal~o}LZ-Qd*jtw|;(qxZdls zZ+muce|NRI9_rH2ykm2Bd>k>p-P}*6x4OI9HJith@G31;ci+qH^hW;|y6sl(9&VuM z-L}K|Day_5koIl%*5PnEFj+|7^R{+&mXDAO z^=@-%ZRxak`%CFS$@%`tX>Z!OH&2!41>IN{i_or6Uh|Aj>1c0tee(GHjUjQooY!F= z*_LX+Vn^+^_Xs`u^?klkG0WY>EGw$4%zUvw$Is!WvI3L)b&Yisx5L}(2r|9Y`6656 z`;c{^`RaySzAEi))#mB@E{+`(Bbm*bS&Lhhs_V7=!M#|^Z=TJ=8MB`g?7dr}9jJFx zOVcjf9;T5AUU-z12`SxQxx2dEy}Ge`x%+5L*`1EGTA5UfekpwJO23)xZ1%BIiX^l9 zvRLwIvispyvI|#jUI+I#Rx%||R{iix!z6Z2TQMhjPNicRN9PNzH}+m#51X?rzOLmc zH%oBj^4m27&);dCF_B!Rklx7eWlb4-IXuREb2V0ql`?x*g0Sx5b-JfWKEvI1tn?IZ4Cvqw3~+w zzFwM6N`YkSB+Rm7iU_V`wTCEke@_lYEh&KEAWEd^tx z;StRq+Ib|i-4ZR}FEN@k`ya+hmFZ<(fiQzg>?NjF}fMJ#e;;I^LRi zyKNG)YbuW3d|GI+CA!#OsS@Sl?os^fYRsyE`!IQmchp@|&Fw}L*DbFrRU17?7oE4C zcF22u^3;F(l99imCVn_w=nNI#zh+o<{Ec2tzgb@4vBxg~;&(Q>M$Y4(j@WiFz zfvSDw-qza*{%Et}nBKj@1J<9}ra6|`rmKrW+zG`ly?0uX5o@)8xhYCus{Z1&8$sRi{x|Idkaa4fG19Ic{+C1)rE?cHQpY^b!uAUYBM=8NjQ_1xVv9H zC?mouWwyVE?0z4K%~U^x;}f_UQQ6K9X}-fc_S5R{md^`Jo7*s-Rdx~x_`Ey(G)Z#h zKt-YWyuevqQEtHkS74}nF)vk%R%LfaFZD7kQmx1FNukP{V%dT__30jg4}5Qw#YO#y zy|$2S((5(r?ePQx)encaPQXMy&a|){ z1FQGt;-RDaML}Nt@@Ri$&wPsN;Q)Q)a`md~Df??$F5G?o`d*wAcwcTZ?avX+{ph`v z8z}|_g(swTsjA2I6`a`zHGdbLK8Y2S@Jk>dDni>QqY-%EjPs_=44siak)`~ z(Me^xR8$zkPy>0CbG4!D$xi>KdEea!EO@-&gbC_W=d${jx;){+2&Pd77cb z=8YM+CF>Tdn+cA~sxFX6o~g)Q_mpU;9EyXXU6tOm9=Vnk>Egp>de3!oj762ugUu*4 zlO^p1LyvXx$dR|QTa$g4y+47;T^J{Vq)Iq7jpK~wsU1f5Z2jt<6>a}{uXg@})N~g# z*hAi0*Oc2w`ln0>>5XqOq=xEqHg=8_OBN{rbj03z|5dBDio#=`uDO&C!ZiI%*k^Oe0QR1Mb@(*|cq54^c@!}1vI2}e0nNSlX@e`FFGNXzgPP{;A>j+q+qX`X0CWdRZ zvoNf?c#^}5uJbqqx{v6=4_U)Z*oVHXI$DpJ6~69E0tUedkOj6Ci$=*hg152R!$^D| z*a_iNfXG-^^-{-*rhiM@E|D&zYeKZQJ)DHxv}w&&R<+NUj+D@rT$`K$m^mkB(DcZzbioydcLO_Ti2rqW`h^mgWtO zYV})~$0G~ODO{mT=|QNva23xU5$H@fJ%mM_W+V8DxU$Skih%DG?AuLCBZ}`E_VR(E z_=kqDcn!*!j8I|uT$sW1?*rsds{*tsS|A&di_^f*rOMs|0H? znt$ACnwRg)OwLE5<#dh6v-danDQElxD@6E6jh+mRt2J!s#&>bV9yzvB>;!c|E$T?- zUsmiGzD0iQfhblggBJITiyUnI3T(x~6^*BF^$>Zt<^ZJ`1O>A{UHrylLU)dSRiF-N`>ph58*#hd{29xbQ1#KF z-R((B_B;Hj9XK0$9ykj*rc)wJR47JfEOC}`i3+@v<312)l!8M2b5u#~4;-Odux15TzR&!<%nW&Ay@{8wjTId0&5&)D=Ob$i!|B~Un3?=$GA z7*Q`^R6wc*4td_PyneMujEs|6g()cA@+jw0#0gLb?@OZ{JR3fUKTrZP**MSNK#6?*scg` zOs8oor7Zh9Ull86B2#Uu7b3wX=VRi_PQcW1l~Uuwk4*VU#@36-B>Y=DjKpVk{y|{L zwB;@WZS#jp;e%CAyTwWEjuEf98^wPTvueK004yk+}Y>$x2B|B{<4+lN`(09~Q z`Qe^5f`n^&7@wyFsT7B88w)I~$xM~(2jTm!pJi2K#Dp9n6RVus)4(0A<=na0h)MiFaySJCW(C_;9jxnz9NbX?tn*_b*WbMq~F8~SKYx3o>_3|{0Pwm zHymkM0CDy;eW=`XNYltb(ov{Me!9ucTG4o?mb1#(jaYvmIyG| zZK47x5t{b<WBdOFLwkS%N6ZDVQa+55{9i z#@X?B8Vu?oRl<4dQAoV1n%=}tn4JJYUFr?uc$Vo4rg3P^=sg`#VuUpX1n-dt3!Wo2 zXZ|;|>V87k1vW)J(9CoqnlQ?Bz*WOe->N}XN-s#GL=u`h+XUk<0la+H&JuO0sDQeB z$caF^GV|N+0fg&2JwU-kImx#i=l9E6{miFQ+*c}}g54s5U6;C3 zpBjFZqXiKSBgxr_lq4yB8(ake=AZLyRJlxlo5ivua9*K8IHHi03td>jSvVq56bylD zG0C8jJR(?Ru)AOdjx?4366B2U)M~_a{I|>=a2uGi0OM|zop<~ z8q7+t)`aYdOd;G@d_^9=qBL6KhA1a_RJ5$ixm82;Til+kwCbOb2ogRrZm5hfc7$3( zD%DDw^sUy^U|1wSfmG^_RH~D~vylFgXnsg9@$g&0e6#cqYU)=+K_76&bNH_GIM=2n zshU|zL*<_$@m{GUg=z{Aa=DEZZ0%#7lk6B2T%t~xXvA~S!+p5q@eD|kL~n7 z0_ub@+*A)}*Z9$H(3-WNgn0^TmHb#$zu8>lqfW%!7?|N6!r{d%gx+;91**)oxBWmF zLZ&p3hhfb#XAOKl@X@yKi{-e-`!y2;uhqVW1C`N|OVqyJ1MI$r5%BM@eZ3=p{f-R$ zo`r}3ln(T4J(#Op^Q*OJu6<<%wT3lXbG=;BJ`ZR9=VVgfU>oIz8vC^88f694c9Zne z-4flG8e9tU3U!Z(0K7R|+qs-naA;V`4O#VZTF;4af-6EnUIyXaqIQx5K<~*Zhukp( zP!;vyvgmz=aKeXz(C2gY{L<)K25|ZY6rDeiMD$52qhBO0Jzp47-~`uhB%v1bkPh>e ztWB`l*)Uj>mbex)+h>)*5kLo*lw0@6^+W_842i+zLm(ANu-V^ZP9(kNS|C_&we4U9 zMmqB6@EFNQ-3a`@{KIfN=MMmv5(8L~G*Ah3M&kgmKf(2m1 zj{N+ZYfkg+`+*|JC`1#<(-FmUb;cRv8;Y2y;`5W z-tD-?tDLEwFc2?1C*d99tEDs;dAicu0Yv5nM z;|)e7tNaJccQwj71X{w-a^}38qV%zvG5z;Ywb6a;2Q9lk^5sPP-Qrw-Lp~pM9Kn@4 zIt8>5EBSm5^ZXastrggylqFCK??9nKwa-WBsFBW2?d1Fy2fV?=QC^6}ci@EcxP|lj zw-Ss0qUvV6Oj7O&>AYaE@dk$~Y4HZ3sW$5>IgqOHTTa5k#Y)=vpTC{D{E=V|x&l)SM{(2j;{Lb!uhhlpsv?)9UAc*da(4je*Yg@6!RX?p*cJ`kI^L!r-L z3rf{R0WR_zrf=EA8Q9F1g9V3I1vYoe5;w^=H5lmWB~N9ilkX}wW7QEHhm#gOB=!GV za`*xZWhW12H#VZ&j0to<`8-gb3S(Yn>f_P0vMa^_uyD3UtagoPZTPs9XRlYC#GOb__% z+fu6o1aq+J^G7{+Idy9w<_`*m3$188FF z2S$s~ZBryJCxnlCfw~OtV!L%l2%31SzZ;>wq&|&yCbSzx?9^p3$1qJ~6-qKc^${2a z=#xHfG4AsR0vD^UY_j0!J&-o!d<+JHqq}ukX-(jWk4(WePb;(_J3k=-MDg7z0^O?C z9?I)Vlq)<294PFpZs1*L>P@!~9ey=^Zwr!cGX{=KyNr%~tBP9gRQv95<{Cq#p~aUV zCetk;0w}P}zH8p|XPDq24l4|THE4EGxtwu{c&!4Vu}Icr;;mZ!hBQ;LQYengmYucr zP8GsS0_Z2rf1xG19zQ>&*inE#%dkdA&gbOc*+1=4r@P3QkoKdVqz17ZhQ@ zn(TFVJp$Mt9&l56T2p4yOUMD>Iz!`oR*-ZysW4;PE{6(UuY%jixkD=10;l{UG#94`&_h2|ZXj|T?UQ zPu*wQ4798OKU0Or$iGT)KTCLXo))ds*sJ$|Nt^;NKYc4dopU{Akuz=O2wxh!nc-z(O9d z*TRN^8w6&d529KyVhTy>a`Ed900EeB8{>io33Pi~fb$yV3luBGQ>#e+CyYdpBcXa1 zLOphCr-k36!WIOzUW7#KRvL3C(1#F=-6~-Qhg=APS3`nN8OpPP99CY!;;2&NI7+0o zbb={fB629kaSTq{Ho6goVWQ^4BB)X$0IM%LKL)N*-YCG|<;mQwhY4Oqg2#qTyZ3aT zjd8pd`=;q|fT1r)MEd5l=Str+YFN4;u43AjVwz52(q?rD4Owp3*FNG0msG$e+2 zH1>elki`g!zSg|ntdKtXP+tFd(d((5(5Su8wXV>Jnc?!Y)?3vDufo|+l58>H(oByu zqfk8);XwrlcCQBPxeC+yTMZi*@6)V(0!>8Vh%Aedjt9$IXC6NiS4I6^wYm~6V=I`v zngsHWqy`pKl?ju>l(VH$405)9&4gKn<{XDYRE|lJ4=i$Gwm)>mgI5M?q7n*Avi7VF zg(wdbCm$ABl?1u!Eaj;@6EeiNDh(zPGsofJ43dX|FN{bR-YRJj_fsqZczFbKvdOPivs%oAPI5l%QHqm2i;?!0r#f1-R?PaiQFnP;sa_?ODT527c-Br zbT|M9;d&o9C!N77OCuYXk0TQ1JDh{jp~J^4`z{U1Lb@|Ljb4|ROS5}I%q8=>UROsu zZF>o7>>kZzFZA@A-rXNWB!3wwO)Z_jQ+UP2^@xBY zEB(?EZ-J`AtNTB`6RfUtB3Oa}fn?zR=XZka;Qw&XiIt0(V#Nr!mx+~8dk6Af;5L+| zh$}8UQ$*S=+?{Ok6WeYtFiO8YKYbiDh&ufYQu-0zJ@fB|C%y@sa28u}MM0N|CH|uld$Kukv#y@4raGCGbdURlZQfj)r zMbW=xjuJQZ=G^$B{^E=R8?2YQd|W+eSNH2QlcpE6pGgoFza*pOo$M6pTi@81c-%8% z#+sqn62zH{Cxu*6(Dr8;KAQX-7k{s|gp~4-x_^ZMeyLu9Td?);`ZY)L+x94S8GN!x z6^9U{D8%v$?u=N|FgaM)r}l=-rsmjDrjxI=YOmC>^RN$(h-DJjR_s35K0oT4Yo+zW z!G0+v)28v5?@-!y|FEy*V(sL4+T+W1?F%aGB@Q8i3+@3d#_q@XE|=}NWXngm>J zFMc#JG`#ux5u4597y|Dt0~X)!sV>?M9+`;lvLO5`y7L=%Ea(I zqf~~m3s%#?goo<-G$o37y&@@R*9iMLY2Q#HdlJE-?&)4p`&&vsqdfJ^rk8~4UllB- z_KAj$?mle#A!I+VSw)LKi#$ugZQP0)DRg|6ylT;#BR|FhL!vh)fvYMuyPE@VH-%g9h4=D~Xq@l!-$7 zIq3Z6XX|be4kAdOOXcjbKj?BFwO{ue)z)zR=+fjnVcz_iPioiT(yi&@lMd1y3nhd4n)lI8Wc=-|Th#m6z z0>*PgNyC(xtcQdvy>AP<2<27}JH9g9teCjE{aAT8C+(zW((vLb?P;B*u^Q5C?j6S5 zA&Jga!$ny$7AINkyTlf@`l)$w>cE;$&H{$iow~2CiTW4#(`=Z{rFDa2@}DpNB6XfK zHt^ZHI6S`gvAU)GsQB5Z1GAlun9dd&g92w^SdcdZw)I=oLn3d4rC~@Ox!m zdwH0&3+Ygb-lNZj8>ZNO2BM=(1BWc6;XfV`#G*aD)h*t%8OA=kBUTjfv=zyZ`4uCT z5?jJaarpH~7TwZpu4Cj2C*LHJk%;YummNHs0lGO3SvIWUIPm@pjGbm21HoG>7vblD zU#T_KaqQvBT@f@Tp12ZO`27IAO^;+e-v1tWuH^2fkTZVoH~!~0(Fq|9#4SK9V*_yw zgf&Rt!Nlq<3p4odl<0aJ;I@&lcgJ8V>%+k(LF^`ncyO06>Y3;hSnwg@Db1x*Irfn# z1a1QSSTm#+!n@qrHK7HMZ!wfDv_|V-q-v-mEc&BFN=6t-IRk$Qi%lDemT55x3NsU! z)_ya_%X^#sDoAHMB}ZVIMd5|5Pbu$9dl3sMS$4F8zF*#K=f|j=;;S;0aoU8g!>f1B z3(`Xw6dHI*;yuHeBstzBU1yQQo25n+Rqomwm-gnW$RB5nsKe}ESKV>G??K=3`s4PH z`>&dDKcJ{r?-H@M+5O`|GbtBk#?X?1iLl ze&!rwo8}ff=hUDth$!jQ+c8|!+GVh)F7t6GVlW~u<$mcAaN)k(OKjkcEyS0ZJpRao z%}ZYJOtbggDHb-*{e>yH6>U_Aijl0-%Jxf`a3^E~?&Ixht>JYXc#BeXJ>As-ykEk` zipUIjtxsAN?@vO15v6xx5G2L;)Y&4mFVjUXBQE)j1m&sl%tRwgDnI^lMoCS8(*1gp z8_tCFih3VE@*&5F{4BtFwY8`TV$P`(dVqCt`GTger=)sMG5%UdfW=>(awbmdqT#E8)zUqF-|I)Z*7d)O2kN;}t>V!bMa;jt^o}=V>*3{M+ z*T1W6gVol~SHMw(fWru(4ub~gf4U74s2wppXdhTH#7p0MfC8wcF=5mQr-D#4SQ%fJ zuO`yjU1QL-D2H$a{kSr^ynPjxMe7_*#Hl!I?$FspM2E*&+4MkB&xoZ*jWF;sS2Z_* zUsA<4-i?95ujSar;0!fN>|Jh*9O3Ra-uAc$PNb^VAhq0sfTm(()3qdP?g@D({>Gwnrju*(Wn} zqt^pZ-{NL*#!-CiO&Qmx>+mJ7bLjrwDfZc3gn0n#s{7nWbhZ~wnT@cbTIQsP*sP~t zCi@#a&M=mlJF1iQ)4_}>US`b4*mU8KKs*c*Lz5hduC1(Iwk2!mY%0S2I(ZmTB(ioq zd*;&mx?*_m#Z0e)Xeng%Jq0&r$I`vK*AANkN6@^|iQ~7;ZYGyw?)*I&@1)6Uy(hY~ z5qE9%>%DO03A|T&7j?BgfwYH##R2{Ai=lvFA%A=TOaH&uME~6V=bcRGUJ%F!rtLp> z|8+z2&+UKSS^Q@^c)OE4VMCfPMh| J8J`yn{U6*b=@9?` literal 0 HcmV?d00001 diff --git a/250902_DIW_2508C_TEST.xlsx b/250902_DIW_2508C_TEST.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..4301f78fac4f9c6c2445c1b69fccef6f8f04e240 GIT binary patch literal 8172 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 literal 0 HcmV?d00001 diff --git a/250902_DIW_2508D_TEST.xlsx b/250902_DIW_2508D_TEST.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..5c837fdfda29feac33c2ba9b44d69343c6234a28 GIT binary patch literal 13281 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�!kRE71tiwydnHCg8YFX( z&gmun2p7jbFQH*6^qsK>sOyJ%)MSYv#APF#nm3=_W155?LW{phbI}L>WW5%9Kzzkb z8Yg+6d7UMQ!FfXwU1vSLcgC2&bTD?6<%WL70Z@roS;=UCZZA9uTKq~1M4x6NrwXJ& zN3B&5iGUPX2YV(D15?-+(o7*TY(BX}-abu*_k zj@t0nNWYx?#(@M-Sts5H7&ekO7f!;tr53B?h2{VrXiT7T3s zJ7Oc=FQY#_M5dXrpk81pyQAN}>RT1G#PJ>EmVljHAIuKjfsCxxflE&VNiHS9DGRiJ z^xkfXd>&FgM?4RVIbN~;u_^lp`jR$-ZV#Cg=+64+4`k$>(>ksng0=3txfc8??#vnT z4o2LvUAj774TJp;s-Szd#)6JS5|w#$uoCJaE{gR(gZp{2k4X%VFcUo@K<11Lj48Jo zXFz*Oj7(!VQX+@_felTB1BZVveUmNPq*LAm_5(H3$8PkV2DXb9D_SoKg0p{|Y&88TzQHMVnn{03ykz^6 z>sDYyU^1N_2^h=U(8TccKUj_JYBAtD*h>)w`=m&6T?n>|OYa-iH?5KKIr$<73YJ2q zC{Ov3XvDD8oJC@%4{{Zlr zJC{Zh=#JcT(b`NZfJEJrhqlTLo}Uu-MbtsKLPI1uRuD@H$eRmL&C;(3l(cV^EI$ z{)*0-*gJE0cxT^Bt2JR@m1AHjBtUwcT}Hr6it>1X4+uXjR7IOZX|wVhjr$*IrNKOK zTt&gIZ`-Q&SwxIvXog0rE>&m!?M&AMs`shI(hc{i1mp%^vaJi3&R8{b&vuTygu#S4 z%8K6a^*@%Icv-S3Tw2!pAx4%iS`2*Tkw9h~SwE>U>#Vi)``C=gzakg94ofg%zcP~X z9~v18wA~6gK~2;3!FeDKUh`6;4H=RB`I7BGm}ABz{!qa2oKnO$W|IqNck&VBg0j>% zCTk7Nohq%RJ!N4@In=oE)xzO}7C5D`557q)K+CnjS#D?+kD4m?v;BUby(8n^%dbTh z2Wuy1qrnIVlZ%^FzGrV+*v>6Z7}HzEQx-P+D~?oUKNsyDt&v^i!Q4M2X3%Y*!|jZT zFJsDLRvVN3S}RVv&=GMTG?dF7zGOQW<`B+2bpsQPROG_eOTHB+OeXRZTvA5*#q^yi z(xObs-U>|*sUI))lAe3n`#~Qa2M5x5%-k_JCiMlgB4Lvnhd{Mb{^}0Ksv>dD=q1Cs z0P!XDTgS%@U%uZ7H^RB3{up|Lr8!#h$AJ|$#d733o0~!@t6H+q(7f#YC#;@+vVWwF z&_Ce)@v2p#4ZKRhSVUY!?d;eI%B51=OM(Z1q$BW06ZG5sf3ySY`yMvm|nuS1C;^_lnL_}j(KMI7#aL!x z2(n?X?@<%eqIFZsm_tBLQA>Rz9p@nKqW$1}fN<+PhAj!7XV*Jec85PiDYf6A$S8RMjN~!dtb;6)EgPapDG(lZBC<;08&X(g zpjJ|As1mU6vivqh6XXYWd+|U#0u*FapzzBbKz0jfC5K^%a9q;&s)uutmtctiDYhTo zi2ssjn9@aShmC2W1S=jLc})sjIM}MbiS2j~nMNACF0#rOCKM8go15>9=tZd(E<+B( z2kHPTT@y}Jw(}S+j><%&Bu`*ZIfPZM1_5%lK#_A;3O`gr!hE za>L~@LB!y{?UD!4E6Ru6?2aL*OucM)04_b&!%j+UpwfKX>$ZOg`{UgvQ>;J6Cp6@b zQb5tv9-#)eILPx55$ONLT88nI^s3Ch0j0 znfs>p)5R1IZ8|u{CX=c7jv91@*_nh3l9vF&h^kpHN%C;eY=UDp%Sm=4L#%=Wr-8sy zrr!}S61NLt_>snea<~PCIf8~<15_oTMp-KCo32kV!dE;RR6s45r(E48`Dz%_FrUzr zet+5|M-Wz`hJ7kP@rT|qvP%#d#RFsyZBG)=pWGo?(5vz<)kg zbE@ymx(8#TtYV(V2;`9>cQ+-a!JYiR>}ld|^s;Q&#F#Xf1H?!D@s^*7bXNmw+QL!x3S^s-#oH#F9;d!WpRcFD4v92nA)bZM8& z1V{wmM8Qr*?8AFE5<1__l00I`?Pb=HPIM)gqkrZArxq26zCj-NU?Of)qu?eXOM$J0 zMzfvoP&PB>lW$iGU(Ut%=NYDRIUHY`DK|%FeFpX)hP=}2efst^IPePin8O)b5W_@w zDFwEWOYwQm(n*JXh)y%{v2z9cqTh#SPKWp%j|Pj&;iHR`FIEqG$f|gTK`vU~mwWpW zq`$RGRt-abfXaG#9#}rlc?N_1sAhc6_zHPI8k~YXmPd@n@jB+pk|xBpKrZJAtYk1d zf%Lx8^Ba;{ecyH*zmP|R9mtM3Gzcd0TWPSX=KV58LqveO*c<<}&jCqlmnP?dZ>0DnEE=i0ay7*?X`Bx=y&ceb}bceTL1J8$S)@9*}--y7bWUO{Jx z=B~3lpY7*de|frjw)f%E!CPo{-sfuV;&Ltha<1drVb$K=9?#g%*%5x0ZMW-pZm@E6 z{nroYv-^%>&4>sHj>!M>`+L5d@9$r0&P2}e;9rugNL$khChQKLBMpR(`m%)>PWytC zL}Lb&k~!HOFHR=dA~53Cl2e|eM7N}G17#KGKMAGZo>Fc zD~RG{sn|$9()W6XHbn(%C6q06C|9O^{^k=}>|OLJHg&oXlg(Ys`V0<<-`p|9ehU;X zagEeJXtUbj;cE0zQ5k&pgwpCqU^=U?Z}5R= zuZqI}c9}9WtNK!gYlBSJky}*dkIMjkFTp-}@0r1IIteCToP+khfFiaPP*jSX;+w)y zVRLtRy-PB771-$g*HY(bfx1R~4Gt`1^9cG9E%47)XI>*1SF|ab_vc$b)sjIHRv!E2 zHK@C!^ADulkI9rzBF%Q7vsM@(V0AR`X~|FeDdn(Enp8-x+fC5NG`QbfFUQl!kji3z z8efLqVFn)@Z=tL1$*qxdiDzypR>Sjo_=bA!XWb|{d&cw+2}DdH+vc~U2H4FNXDJic z2>t=7-FkYL zYGnT^cq0U@K(KZVH~Bd3IFqD#Gk(0(g*Sc8y1!8EJEvIn%=aT(d$jF7^W=gp?N^5r zRSH4Kwfj#i8Fef^FDdPOIP~`9oDi-jgH2IcfSltZ*%F1l&L-MGf+^ zg)Gd~U!whvr4>{t+~Gs+@tSa451G){^@wqA37oQmW;|BdHaYWbIZZXdxI$!jY{vO~ z*F5OumnV5{l9l_zi(~J&n6b=+i0F(23?$ho2+Z&)bn!7UZ!$*|&3Dv4gf&N9wte zGr$)|6>UO$=5i0z{d`MVeL2oE!g2lPT{q#+dV}rcgf8f?%5~uFX3?MaNyZ&8PZse7 zpM#%g&gP?2uJ${Z_E4&>?R7PB!dERkJo{GB=M`PGEt;e_SdZ#$%(XEti>~nJ_h<~x zn@%gCgaUL)-tSr;HcT(bF^AQrx`{n!?l#o9pc-5h&9>vRQZ$T6ED>B8rFEM(HwoB0 z-8;Alu)SoB(Z~qsBIsnJ;XsZg(oGt?cFAJ)%nE=sJjnl=unJOCGwF(pzJ4O&sD_w* zstEiLzn@VGvm_cYk(qcfw8u>w-G@Vwgv)Vh_;JH-jA;LgT0_j&Ub-Z4G*KZlsa$|z zukn69+wxqIOPrKzU>ePM?AD@6m+-St!$PNgJDzA_)Yprk?ic(+5u2;0(I;Vz%+H<@ zJEDB@Kzk;C--F6Jqz}P4Ck}M5+ZJ{L@$ytJoV*U1{QLS(N@NptE0D`XKwblBjbQ9# zVe8Dzb@QH?&|nALtCjTc8qVTDAHE;XXR$|$a)$Uc4{wSPHBv4US}|Sd7>7mSDJDud zOKUB;EmTk&^`86^|B1EUL_MNHEpx2(V7zqsIEYptY*bQq#!RMC4N!%$as(y#8E=g?pxsjk!8_G zx58SyMQMmZg9GPjokK3S*2-g{cle-t%SC0qV(vm`JMWrAl1j;xejLOI6N%8j=Y7_H z;+lk1>?LJMZ_64VscEL{y1J!;810H_B6P4-qc^rrjA~u+)W~pch;&raTmzGnwEcd& z#`R&;C{<23K1Et$K)pR$=L%cg%Dv@)@$h0z;n@UC@DuXBV@75Qtgog&gitJa&Y5?~ z;?ViW)p+@5^GTWL2hs#oG^|(bg#2wN&`r2gv=_eOn4^u02voi|mymJPnwnyVzvDH) zop=^H_2fDN!h#`R$(1jT{=AQxq!LL3M$D%wDkY4<vA}@ z&#b2&*KL0{rG@oM#?`b(1YDkeQL(qdop(+rdn8QMP*5}!JC3PhGNsw@o-y z=!sciV_=56e<-ePG%PDAYhHGUm`q6~)A@CNNTFXfT|Sk}UoMzGy?OlTKX=QM(d_af5mAT;Q{{ zK8fTH?>jd;yVQA;&+3*yC7>~9<<#9m#YQSn)q<>HWX9dAO&NApq*at63f2rv_T=OY zX+5wrImV8c^)5Y+N|2g6! zxRO32kfIAHcXzq?;nN`<~I2te%kzuNyii}1Jl z-`Dg1t-b`9|1X#I{|5N`dgea>wSf%xZUO%5WzD}){=RGSZUaP|8aEvt@!um|8GUi z2mkW?pQGS!<-a$ge=9d}-75c&ZRu~EznAyFaXxY*ApDobuAz(yJlSz`E@L6|0p~L! I?@jCf0mQF43IG5A literal 0 HcmV?d00001 diff --git a/DIW_2508A.json b/DIW_2508A.json index aee84eb..9ea62c4 100644 --- a/DIW_2508A.json +++ b/DIW_2508A.json @@ -255,27 +255,27 @@ "item": "문구 (시니어클럽)/③ 정렬 (가운데 정렬)" }, "25": { - "path": "//SECTION[1]//TEXT[CHAR[text()='{searchValue}']]/@CharShape", + "path": "//TEXT[CHAR[text()='{searchValue}']]/@CharShape", "searchValue": "DIAT", "value": "굴림", "points": 1, - "category": "FontName", + "category": "FontName.Header", "item": "문구 (DIAT)/① 글꼴 (굴림)" }, "26": { - "path": "//CHARSHAPE[@Id=//SECTION[1]//TEXT[CHAR[text()='{searchValue}']]/@CharShape]/@Height", + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]/@Height", "searchValue": "DIAT", "value": "900", "points": 1, - "category": "OneAnswer", + "category": "OneAnswer.Header", "item": "문구 (DIAT)/② 크기 (9pt)" }, "27": { - "path": "//PARASHAPE[@Id=//SECTION[1]//CHAR[text()='{searchValue}']/parent::TEXT/parent::P/@ParaShape]/@Align", + "path": "//PARASHAPE[@Id=//CHAR[text()='{searchValue}']/parent::TEXT/parent::P/@ParaShape]/@Align", "searchValue": "DIAT", "value": "Right", "points": 1, - "category": "OneAnswer", + "category": "OneAnswer.Header", "item": "문구 (DIAT)/③ 정렬 (오른쪽 정렬)" }, "28": { @@ -436,7 +436,7 @@ "item": "문구 (노인일자리)/⑩ 정렬 (가운데 정렬)" }, "14": { - "path": "//BINITEM[@BinData=//PICTURE/IMAGE/@BinItem][@Format='JPG']", + "path": "//BINITEM[@BinData=//PICTURE/IMAGE/@BinItem][@Format='JPG' or @Format='JPEG']", "value": true, "points": 2, "category": "Boolean", @@ -444,28 +444,28 @@ "desc": "첨부 이미지 파일명 손상으로 정상적인 채점이 불가한 경우가 발견되어서 이미지 첨부 여부로 채점 방식 변경 (7/3)" }, "15": { - "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/SIZE/@Width", + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/SIZE/@Width", "value": "85", "points": 2, "category": "mmSize", "item": "② 크기-너비 (85 mm)" }, "16": { - "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/SIZE/@Height", + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/SIZE/@Height", "value": "40", "points": 2, "category": "mmSize", "item": "③ 크기-높이 (40 mm)" }, "17": { - "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@HorzOffset", + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@HorzOffset", "value": "0", "points": 2, "category": "mmSize", "item": "④ 위치 (어울림 : 가로-쪽의 왼쪽 0.0mm)" }, "18": { - "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@VertOffset", + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@VertOffset", "value": "22", "points": 2, "category": "mmSize", diff --git a/DIW_2508B.json b/DIW_2508B.json index 45dde3b..bb67be2 100644 --- a/DIW_2508B.json +++ b/DIW_2508B.json @@ -255,27 +255,27 @@ "item": "문구 (기능경진대회운영위원회)/③ 정렬 (가운데 정렬)" }, "25": { - "path": "//SECTION[1]//TEXT[CHAR[text()='{searchValue}']]/@CharShape", + "path": "//TEXT[CHAR[text()='{searchValue}']]/@CharShape", "searchValue": "DIAT", "value": "굴림", "points": 1, - "category": "FontName", + "category": "FontName.Header", "item": "문구 (DIAT)/① 글꼴 (굴림)" }, "26": { - "path": "//CHARSHAPE[@Id=//SECTION[1]//TEXT[CHAR[text()='{searchValue}']]/@CharShape]/@Height", + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]/@Height", "searchValue": "DIAT", "value": "900", "points": 1, - "category": "OneAnswer", + "category": "OneAnswer.Header", "item": "문구 (DIAT)/② 크기 (9pt)" }, "27": { - "path": "//PARASHAPE[@Id=//SECTION[1]//CHAR[text()='{searchValue}']/parent::TEXT/parent::P/@ParaShape]/@Align", + "path": "//PARASHAPE[@Id=//CHAR[text()='{searchValue}']/parent::TEXT/parent::P/@ParaShape]/@Align", "searchValue": "DIAT", "value": "Right", "points": 1, - "category": "OneAnswer", + "category": "OneAnswer.Header", "item": "문구 (DIAT)/③ 정렬 (오른쪽 정렬)" }, "28": { @@ -436,7 +436,7 @@ "item": "문구 (기능경진대회)/⑩ 정렬 (가운데 정렬)" }, "14": { - "path": "//BINITEM[@BinData=//PICTURE/IMAGE/@BinItem][@Format='JPG']", + "path": "//BINITEM[@BinData=//PICTURE/IMAGE/@BinItem][@Format='JPG' or @Format='JPEG']", "value": true, "points": 2, "category": "Boolean", @@ -444,28 +444,28 @@ "desc": "첨부 이미지 파일명 손상으로 정상적인 채점이 불가한 경우가 발견되어서 이미지 첨부 여부로 채점 방식 변경 (7/3)" }, "15": { - "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/SIZE/@Width", + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/SIZE/@Width", "value": "85", "points": 2, "category": "mmSize", "item": "② 크기-너비 (85 mm)" }, "16": { - "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/SIZE/@Height", + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/SIZE/@Height", "value": "40", "points": 2, "category": "mmSize", "item": "③ 크기-높이 (40 mm)" }, "17": { - "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@HorzOffset", + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@HorzOffset", "value": "0", "points": 2, "category": "mmSize", "item": "④ 위치 (어울림 : 가로-쪽의 왼쪽 0.0mm)" }, "18": { - "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@VertOffset", + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@VertOffset", "value": "22", "points": 2, "category": "mmSize", diff --git a/DIW_2508C.json b/DIW_2508C.json index bc8af8c..3df41c9 100644 --- a/DIW_2508C.json +++ b/DIW_2508C.json @@ -255,27 +255,28 @@ "item": "문구 (밝은미소구강센터)/③ 정렬 (가운데 정렬)" }, "25": { - "path": "//SECTION[1]//TEXT[CHAR[text()='{searchValue}']]/@CharShape", + "path": "//TEXT[CHAR[text()='{searchValue}']]/@CharShape", + "page": 1, "searchValue": "DIAT", "value": "궁서", "points": 1, - "category": "FontName", + "category": "FontName.Header", "item": "문구 (DIAT)/① 글꼴 (궁서)" }, "26": { - "path": "//CHARSHAPE[@Id=//SECTION[1]//TEXT[CHAR[text()='{searchValue}']]/@CharShape]/@Height", + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]/@Height", "searchValue": "DIAT", "value": "900", "points": 1, - "category": "OneAnswer", + "category": "OneAnswer.Header", "item": "문구 (DIAT)/② 크기 (9pt)" }, "27": { - "path": "//PARASHAPE[@Id=//SECTION[1]//CHAR[text()='{searchValue}']/parent::TEXT/parent::P/@ParaShape]/@Align", + "path": "//PARASHAPE[@Id=//CHAR[text()='{searchValue}']/parent::TEXT/parent::P/@ParaShape]/@Align", "searchValue": "DIAT", "value": "Right", "points": 1, - "category": "OneAnswer", + "category": "OneAnswer.Header", "item": "문구 (DIAT)/③ 정렬 (오른쪽 정렬)" }, "28": { @@ -436,7 +437,7 @@ "item": "문구 (구강건강관리)/⑩ 정렬 (가운데 정렬)" }, "14": { - "path": "//BINITEM[@BinData=//PICTURE/IMAGE/@BinItem][@Format='JPG']", + "path": "//BINITEM[@BinData=//PICTURE/IMAGE/@BinItem][@Format='JPG' or @Format='JPEG']", "value": true, "points": 2, "category": "Boolean", @@ -444,28 +445,28 @@ "desc": "첨부 이미지 파일명 손상으로 정상적인 채점이 불가한 경우가 발견되어서 이미지 첨부 여부로 채점 방식 변경 (7/3)" }, "15": { - "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/SIZE/@Width", + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/SIZE/@Width", "value": "80", "points": 2, "category": "mmSize", "item": "② 크기-너비 (80 mm)" }, "16": { - "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/SIZE/@Height", + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/SIZE/@Height", "value": "40", "points": 2, "category": "mmSize", "item": "③ 크기-높이 (40 mm)" }, "17": { - "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@HorzOffset", + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@HorzOffset", "value": "0", "points": 2, "category": "mmSize", "item": "④ 위치 (어울림 : 가로-쪽의 왼쪽 0.0mm)" }, "18": { - "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@VertOffset", + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@VertOffset", "value": "22", "points": 2, "category": "mmSize", diff --git a/DIW_2508D.json b/DIW_2508D.json index 50150c5..684479e 100644 --- a/DIW_2508D.json +++ b/DIW_2508D.json @@ -255,27 +255,27 @@ "item": "문구 (중앙문화지역센터)/③ 정렬 (가운데 정렬)" }, "25": { - "path": "//SECTION[1]//TEXT[CHAR[text()='{searchValue}']]/@CharShape", + "path": "//TEXT[CHAR[text()='{searchValue}']]/@CharShape", "searchValue": "DIAT", "value": "궁서", "points": 1, - "category": "FontName", + "category": "FontName.Header", "item": "문구 (DIAT)/① 글꼴 (궁서)" }, "26": { - "path": "//CHARSHAPE[@Id=//SECTION[1]//TEXT[CHAR[text()='{searchValue}']]/@CharShape]/@Height", + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]/@Height", "searchValue": "DIAT", "value": "900", "points": 1, - "category": "OneAnswer", + "category": "OneAnswer.Header", "item": "문구 (DIAT)/② 크기 (9pt)" }, "27": { - "path": "//PARASHAPE[@Id=//SECTION[1]//CHAR[text()='{searchValue}']/parent::TEXT/parent::P/@ParaShape]/@Align", + "path": "//PARASHAPE[@Id=//CHAR[text()='{searchValue}']/parent::TEXT/parent::P/@ParaShape]/@Align", "searchValue": "DIAT", "value": "Right", "points": 1, - "category": "OneAnswer", + "category": "OneAnswer.Header", "item": "문구 (DIAT)/③ 정렬 (오른쪽 정렬)" }, "28": { @@ -436,7 +436,7 @@ "item": "문구 (매력적인 강원도)/⑩ 정렬 (가운데 정렬)" }, "14": { - "path": "//BINITEM[@BinData=//PICTURE/IMAGE/@BinItem][@Format='JPG']", + "path": "//BINITEM[@BinData=//PICTURE/IMAGE/@BinItem][@Format='JPG' or @Format='JPEG']", "value": true, "points": 2, "category": "Boolean", @@ -444,28 +444,28 @@ "desc": "첨부 이미지 파일명 손상으로 정상적인 채점이 불가한 경우가 발견되어서 이미지 첨부 여부로 채점 방식 변경 (7/3)" }, "15": { - "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/SIZE/@Width", + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/SIZE/@Width", "value": "85", "points": 2, "category": "mmSize", "item": "② 크기-너비 (85 mm)" }, "16": { - "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/SIZE/@Height", + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/SIZE/@Height", "value": "40", "points": 2, "category": "mmSize", "item": "③ 크기-높이 (40 mm)" }, "17": { - "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@HorzOffset", + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@HorzOffset", "value": "0", "points": 2, "category": "mmSize", "item": "④ 위치 (어울림 : 가로-쪽의 왼쪽 0.0mm)" }, "18": { - "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@VertOffset", + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@VertOffset", "value": "22", "points": 2, "category": "mmSize", diff --git a/diwScoring2.py b/diwScoring2.py index ceb2e6e..56381f1 100644 --- a/diwScoring2.py +++ b/diwScoring2.py @@ -218,6 +218,7 @@ class XMLScorer: category = criterion.get('category', None) item = criterion.get('item', None) option = criterion.get('option', None) + page = criterion.get('page', None) similar_text = None # search_value가 있는 경우 @@ -247,683 +248,724 @@ class XMLScorer: 'points': 0, # 점수 } - if (category or "") == "PageSetting": - items = root.xpath(xpath) - error_range = criterion.get('tolerance', 0) - - right_answer = { - 'Top' : float(right_answer.get("Top", 0)), - 'Bottom' : float(right_answer.get("Bottom", 0)), - 'Left' : float(right_answer.get("Left", 0)), - 'Right' : float(right_answer.get("Right", 0)), - 'Header' : float(right_answer.get("Header", 0)), - 'Footer' : float(right_answer.get("Footer", 0)), - 'Gutter' : float(right_answer.get("Gutter", 0)), - } - right_answer = { - k: self.convert_mm_to_pt(v) - for k, v in right_answer.items() - } - - for item in items: - user_answer = { - 'Top' : float(item.get("Top", 0)), - 'Bottom' : float(item.get("Bottom", 0)), - 'Left' : float(item.get("Left", 0)), - 'Right' : float(item.get("Right", 0)), - 'Header' : float(item.get("Header", 0)), - 'Footer' : float(item.get("Footer", 0)), - 'Gutter' : float(item.get("Gutter", 0)), + try: + if (category or "") == "PageSetting": + items = root.xpath(xpath) + error_range = criterion.get('tolerance', 0) + + right_answer = { + 'Top' : float(right_answer.get("Top", 0)), + 'Bottom' : float(right_answer.get("Bottom", 0)), + 'Left' : float(right_answer.get("Left", 0)), + 'Right' : float(right_answer.get("Right", 0)), + 'Header' : float(right_answer.get("Header", 0)), + 'Footer' : float(right_answer.get("Footer", 0)), + 'Gutter' : float(right_answer.get("Gutter", 0)), } - - self.evaluate_answer(scoring, user_answer, right_answer, points, method="tolerance", tolerance=error_range) - - if scoring['points'] > 0: - break - - elif (category or "") == "BasicSetting": - # FontName, FontSize, Alignment, LineSpacing - # 해당 속성의 요소(텍스트)가 문서 내부에 존재하면 정답처리 - - matches = set() - - # P 태그 순회 - for p_tag in root.xpath(".//P"): - parashape = p_tag.get("ParaShape") - - for text_tag in p_tag.xpath(".//TEXT"): - charshape = text_tag.get("CharShape") - - if parashape is not None and charshape is not None: - matches.add((parashape, charshape)) - - # 출력 - for para, char in matches: - # print(f"ParaShape = {para}, CharShape = {char}") - font_id = root.xpath(f"//CHARSHAPE[@Id='{char}']/FONTID/@Hangul") - font_name = root.xpath(f"//FONTFACE[@Lang='Hangul']/FONT[@Id='{font_id[0]}']/@Name") - - user_answer = { - 'FontName': font_name[0], - 'FontSize': root.xpath(f"//CHARSHAPE[@Id='{char}']/@Height")[0], - 'Alignment': root.xpath(f"//PARASHAPE[@Id='{para}']/@Align")[0], - 'LineSpacing': root.xpath(f"//PARASHAPE[@Id='{para}']/PARAMARGIN/@LineSpacing")[0] + right_answer = { + k: self.convert_mm_to_pt(v) + for k, v in right_answer.items() } - # 정답과 수험자 답안 비교 - self.evaluate_answer(scoring, user_answer, right_answer, points, method="equal") - - if scoring['points'] > 0: - break - - # 1, 2페이지 모두 정답이어야 함 - elif (category or "") == "PageNumber": - items = root.xpath(xpath) if xpath else [] - - all_match = True - for item in chain(items): - user_answer = item - if right_answer != user_answer: - all_match = False - break - - if all_match: - self.evaluate_answer(scoring, user_answer, right_answer, points, method="equal") - else: - self.evaluate_answer(scoring, user_answer, right_answer, 0, method="equal") - - - # 오타 감점 부분은 미리 계산 하고, 이후 점수만 계산 - elif (category or "") == "오타감점": - points = self.get_typo_score() - self.total_score += points - self.partial_score += points - scoring['points'] = points - - # 테이블의 경우 모든 셀에 요구사항이 적용되어야 정답처리 - elif (category or "") == "TableAnswer": - items = root.xpath(xpath) if xpath else [] - items2 = root.xpath(xpath2) if xpath2 else [] - - def is_all_match(item_list): - return item_list and all(item == right_answer for item in item_list) - ## 위 코드와 동일한 기능(풀어서 설명) - # 리스트가 비어 있으면 False 반환 - # if not item_list: - # return False - - # # 리스트의 모든 항목이 right_answer와 같은지 검사 - # for item in item_list: - # if item != right_answer: - # return False # 하나라도 다르면 False 반환 - - # return True # 전부 일치하면 True 반환 - - if is_all_match(items): - user_answer = right_answer - elif is_all_match(items2): - user_answer = right_answer - else: - user_answer = "" - points = 0 - - self.evaluate_answer(scoring, user_answer, right_answer, points) - - # [1-16] ◈ 행사안내 ◈ - # 특수문자와 글자의 속성이 같고 문서 내부에 '행사안내'와 같은 문자가 있을 경우 - # 유사도 문제로 의도치 않은 다른 부분의 텍스트 속성이 채점되는것을 방지하고자 - # 해당 문자를 포함하는 모든 문단의 속성을 판단해 - # 정렬값이 정답과 일치하는 경우 정답으로 채점 - elif (category or "") == "Align": - match_str = criterion.get('match_str', None) - - xpath = xpath.replace('{match_str}', match_str) - items = root.xpath(xpath) - - for item in items: - user_answer = item - self.evaluate_answer(scoring, user_answer, right_answer, points) - if scoring['points'] > 0: - break - - elif (category or "") == "majorGridlines": - # 줄/칸 전환여부 확인 - # table_col_count = root.xpath("//SECTION[2]//TABLE/@ColCount") - table_col_count = root.xpath("//TABLE/@ColCount") - - # print("🟡테이블 열 개수: ", int(table_col_count[0]) if table_col_count else 0) - - chart_ser_count = chart_tree.xpath("count(//c:ser)", namespaces=namespaces) if chart_xpath else 0 - - # print("🟡차트 데이터 개수: ", int(chart_ser_count) if isinstance(chart_ser_count, (int, float)) else 0) - - isXYtransposed = False - if table_col_count and chart_ser_count: - if int(chart_ser_count) > int(table_col_count[0])-1: - isXYtransposed = True - - # 값 축 주눈금선 존재하는지 여부 확인 - items = chart_tree.xpath(chart_xpath, namespaces=namespaces) if chart_xpath else [] - - for item in items: - # item이 존재하면 True, 없으면 False - user_answer = (item is not None) and isXYtransposed - - # 정답과 수험자 답안 비교 - self.evaluate_answer(scoring, user_answer, right_answer, points) - if scoring['points'] > 0: - break - - - # 정답이 하나인 경우 - # elif (category or "") == "OneAnswer": - elif (category or "") in ["OneAnswer", "ChartOneAnswer"]: - items = root.xpath(xpath) if xpath else [] - items2 = root.xpath(xpath2) if xpath2 else [] - - # 차트 XML에서 정답을 찾는 경우 - # 차트 종류가 - # 세로막대형이면 x축이 카테고리(catAx) y축이 값(valAx) - # 가로막대형이면 x축이 값(valAx) y축이 카테고리(catAx) - if category == "ChartOneAnswer": - # 하드코딩이라 [2-45문항] 변경시 수정 필요 - # chart_type = self.scoring_criteria["2"]["45"]["chart_type"].replace(" ","") - - # chart_type 변수의 경우 45번 문항을 먼저 채점하므로 - # xy축의 변경이 필요한 53~58번 문항 채점시에 chart_type변수에 차트모양의 정보는 입력 되어있음 - - # 가로 차트일 경우에만 x축과 y축을 바꿔줌 - # 세로, 꺾은선, 원형 차트의 경우 그대로 사용 - if "가로" in chart_type: - if "catAx" in chart_xpath: - chart_xpath = chart_xpath.replace("catAx", "valAx") - elif "valAx" in chart_xpath: - chart_xpath = chart_xpath.replace("valAx", "catAx") - - chart_items = chart_tree.xpath(chart_xpath, namespaces=namespaces) if chart_xpath else [] - - for item in chain(items, items2, chart_items): - user_answer = item.replace(" ", "") if isinstance(item, str) else item - right_answer = right_answer.replace(" ", "") - - self.evaluate_answer(scoring, user_answer, right_answer, points) - if scoring['points'] > 0: - break - - # [2-6] 테두리 이중실선 1.00mm - elif (category or "") == "LineShape": - line_shapes = root.xpath(xpath) if xpath else [] - - user_answer = { - 'Style': None, - 'Width': None - } - - for line_shape in line_shapes: - style = line_shape.get("Style") - width = line_shape.get("Width") - - user_answer['Style'] = style - user_answer['Width'] = width - - self.evaluate_answer(scoring, user_answer, right_answer, points) - if scoring['points'] > 0: - break - - # 사용자 입력값이 mm단위인 경우 - elif (category or "") == "mmSize": - items = root.xpath(xpath) - # 오차범위 설정 - # 한글 프로그램 내부에서 드물게 0mm이지만 1pt로 저장되는 경우가 있음 - # - # XML파일의 요소 옵션값은 내부적으로 1=0.01pt - # 이 경우를 대비하여 tolerance를 10으로 설정 (1pt=약0.04mm 만큼의 오차 혀용) - error_range = criterion.get('tolerance', 10) - - # JSON 파일 value키값에 mm나 공백이 입력될 경우 제거 - # 예) "80.2 mm" >> 80.2 로 변환 - float_string = right_answer.strip().replace("mm", "") - right_answer = self.convert_mm_to_pt(float(float_string)) - - if not items: - scoring['points'] = 0 - else: for item in items: - user_answer = float(item) + user_answer = { + 'Top' : float(item.get("Top", 0)), + 'Bottom' : float(item.get("Bottom", 0)), + 'Left' : float(item.get("Left", 0)), + 'Right' : float(item.get("Right", 0)), + 'Header' : float(item.get("Header", 0)), + 'Footer' : float(item.get("Footer", 0)), + 'Gutter' : float(item.get("Gutter", 0)), + } self.evaluate_answer(scoring, user_answer, right_answer, points, method="tolerance", tolerance=error_range) + + if scoring['points'] > 0: + break + + elif (category or "") == "BasicSetting": + # FontName, FontSize, Alignment, LineSpacing + # 해당 속성의 요소(텍스트)가 문서 내부에 존재하면 정답처리 + + matches = set() + + # P 태그 순회 + for p_tag in root.xpath(".//P"): + parashape = p_tag.get("ParaShape") + + for text_tag in p_tag.xpath(".//TEXT"): + charshape = text_tag.get("CharShape") + + if parashape is not None and charshape is not None: + matches.add((parashape, charshape)) + + # 출력 + for para, char in matches: + # print(f"ParaShape = {para}, CharShape = {char}") + font_id = root.xpath(f"//CHARSHAPE[@Id='{char}']/FONTID/@Hangul") + font_name = root.xpath(f"//FONTFACE[@Lang='Hangul']/FONT[@Id='{font_id[0]}']/@Name") + + user_answer = { + 'FontName': font_name[0], + 'FontSize': root.xpath(f"//CHARSHAPE[@Id='{char}']/@Height")[0], + 'Alignment': root.xpath(f"//PARASHAPE[@Id='{para}']/@Align")[0], + 'LineSpacing': root.xpath(f"//PARASHAPE[@Id='{para}']/PARAMARGIN/@LineSpacing")[0] + } + + # 정답과 수험자 답안 비교 + self.evaluate_answer(scoring, user_answer, right_answer, points, method="equal") if scoring['points'] > 0: break - - elif (category or "") == "ParaShape": - items = root.xpath(xpath) - for item in items: - user_answer = { - 'Left': float(item.get('Left', 0)) / 200, - 'Indent': float(item.get('Indent', 0)) / -200, - } - - # 정답과 수험자 답안 비교 - self.evaluate_answer(scoring, user_answer, right_answer, points, method="equal") - - if scoring['points'] > 0: - break - - # Boolean 타입 정답인 경우 - elif (category or "") == "Boolean": - items = root.xpath(xpath) if xpath else False - items2 = root.xpath(xpath2) if xpath2 else False - chart_items = chart_tree.xpath(chart_xpath, namespaces=namespaces) if chart_xpath else False - - user_answer = bool( items or items2 or chart_items ) - - self.evaluate_answer(scoring, user_answer, right_answer, points) - - # 채점기준표 파일에 작성된 rgb값을 그대로 읽어와 HML파일 요소의 int형 rgb값과 비교 - elif (category or "") == "Color": - items = root.xpath(xpath) if xpath else [] - items2 = root.xpath(xpath2) if xpath2 else [] - - rgb_text = right_answer - - # 정규식을 이용해 숫자만 리스트로 추출 - numbers = re.findall(r'\d+', rgb_text) - r, g, b = map(int, numbers) if len(numbers) == 3 else None - - # 콤마(,)로 구분된 문자열을 정수형으로 변환 - # r, g, b = map(int, rgb_text.split(',')) - - rgb_int = (b << 16) + (g << 8) + r - - # items, items2를 순차적으로 순회 - for item in chain(items, items2): - user_answer = int(item) - self.evaluate_answer(scoring, user_answer, rgb_int, points, method="equal") - if scoring['points'] > 0: - break - - # 문단 첫글자 장식 채점 - elif (category or "") == "TwoLineSize": - items = root.xpath(xpath) - error_range = criterion.get('tolerance', 0) - for item in items: - user_answer = { - "Height": int(item.get('Height', 0)), - "Width": int(item.get('Width', 0)) - } - self.evaluate_answer(scoring, user_answer, right_answer, points, method="tolerance", tolerance=error_range) - - if scoring['points'] > 0: - break - - # 폰트명 - elif (category or "") in ["FontName", "TableFontName"]: - charshape_list = root.xpath(xpath) - - # 문자속성이 없는 경우 - if not charshape_list: - user_answer = "" - self.evaluate_answer(scoring, user_answer, right_answer, points, method="equal") - else: - require_all_match = (category == "TableFontName") - any_match = False + # 1, 2페이지 모두 정답이어야 함 + elif (category or "") == "PageNumber": + items = root.xpath(xpath) if xpath else [] + all_match = True - matched_user_answer = None # 일치하는 user_answer를 기억 - - for charshape_id in charshape_list: - font_id = root.xpath(f"//CHARSHAPE[@Id='{charshape_id}']/FONTID/@Hangul") - if not font_id: + for item in chain(items): + user_answer = item + if right_answer != user_answer: all_match = False - continue - - font_name = root.xpath(f"//FONTFACE[@Lang='Hangul']/FONT[@Id='{font_id[0]}']/@Name") - - if not font_name: - all_match = False - continue - - # 공백 제거 - user_answer = font_name[0].replace(" ", "") - right_answer = right_answer.replace(" ","") - - # 접두어 제거 - if right_answer in ["견고딕", "중고딕"]: - user_answer = user_answer.replace("한양", "") - - if user_answer == right_answer: - any_match = True - matched_user_answer = user_answer - else: - all_match = False - if require_all_match: - break - - if require_all_match: - score = points if all_match else 0 - self.evaluate_answer(scoring, user_answer, right_answer, score) - else: - score = points if any_match else 0 - self.evaluate_answer(scoring, matched_user_answer if any_match else "", right_answer, score) - - # 폰트 속성 - elif (category or "") == "FontAttribute": - # 하이퍼링크 처리 - - # 1. 하이퍼링크를 포함하는 P요소를 가져옴 - # 2. 그 P요소의 자손 CHAR태그에 있는 텍스트를 하나의 문자열로 변환 - # 3. P요소의 문자열과 채점하려는 문자열이 일치하는지 확인 - hyperlink_xpath = criterion.get('hyperlink_ptag', None) - hyperlink_ptag = root.xpath(hyperlink_xpath) if hyperlink_xpath else None - - p_tag_text_list = extract_char_text_from_p(hyperlink_ptag) if hyperlink_ptag else [] - hyperlink_text = search_value.replace(" ", "") if search_value else "" - - # search_value가 hyperlink문자열에 포함되어 있는지 확인 - # search_value가 hyperlink인 경우와 아닌경우를 구분해 채점 - search_in_hyperlink = False - if hyperlink_text and any(hyperlink_text in text for text in p_tag_text_list): - search_in_hyperlink = True - else: - search_in_hyperlink = False - - # hyperlink가 아닌 경우(일반적인 텍스트 일 경우) - # 하이퍼링크를 포함한 P태그가 없거나 search_value값이 하이퍼링크텍스트에 포함되어 있지 않을 경우 - if not hyperlink_ptag or not search_in_hyperlink: - charshape_list = root.xpath(xpath) - if not charshape_list: - charshape = None - user_answer = None - else: - for charshape in charshape_list: - font_attribute = charshape.find(right_answer) - if font_attribute is not None: - user_answer = font_attribute.tag - else: - user_answer = None + break - self.evaluate_answer(scoring, user_answer, right_answer, points, method="equal") + if all_match: + self.evaluate_answer(scoring, user_answer, right_answer, points, method="equal") + else: + self.evaluate_answer(scoring, user_answer, right_answer, 0, method="equal") + + + # 오타 감점 부분은 미리 계산 하고, 이후 점수만 계산 + elif (category or "") == "오타감점": + points = self.get_typo_score() + self.total_score += points + self.partial_score += points + scoring['points'] = points + + # 테이블의 경우 모든 셀에 요구사항이 적용되어야 정답처리 + elif (category or "") == "TableAnswer": + items = root.xpath(xpath) if xpath else [] + items2 = root.xpath(xpath2) if xpath2 else [] + + def is_all_match(item_list): + return item_list and all(item == right_answer for item in item_list) + ## 위 코드와 동일한 기능(풀어서 설명) + # 리스트가 비어 있으면 False 반환 + # if not item_list: + # return False + + # # 리스트의 모든 항목이 right_answer와 같은지 검사 + # for item in item_list: + # if item != right_answer: + # return False # 하나라도 다르면 False 반환 + + # return True # 전부 일치하면 True 반환 + + if is_all_match(items): + user_answer = right_answer + elif is_all_match(items2): + user_answer = right_answer + else: + user_answer = "" + points = 0 + + self.evaluate_answer(scoring, user_answer, right_answer, points) + + # [1-16] ◈ 행사안내 ◈ + # 특수문자와 글자의 속성이 같고 문서 내부에 '행사안내'와 같은 문자가 있을 경우 + # 유사도 문제로 의도치 않은 다른 부분의 텍스트 속성이 채점되는것을 방지하고자 + # 해당 문자를 포함하는 모든 문단의 속성을 판단해 + # 정렬값이 정답과 일치하는 경우 정답으로 채점 + elif (category or "") == "Align": + match_str = criterion.get('match_str', None) + + xpath = xpath.replace('{match_str}', match_str) + items = root.xpath(xpath) + + for item in items: + user_answer = item + self.evaluate_answer(scoring, user_answer, right_answer, points) + if scoring['points'] > 0: + break + + elif (category or "") == "majorGridlines": + # 줄/칸 전환여부 확인 + # table_col_count = root.xpath("//SECTION[2]//TABLE/@ColCount") + table_col_count = root.xpath("//TABLE/@ColCount") + + # print("🟡테이블 열 개수: ", int(table_col_count[0]) if table_col_count else 0) + + chart_ser_count = chart_tree.xpath("count(//c:ser)", namespaces=namespaces) if chart_xpath else 0 + + # print("🟡차트 데이터 개수: ", int(chart_ser_count) if isinstance(chart_ser_count, (int, float)) else 0) + + isXYtransposed = False + if table_col_count and chart_ser_count: + if int(chart_ser_count) > int(table_col_count[0])-1: + isXYtransposed = True + + # 값 축 주눈금선 존재하는지 여부 확인 + items = chart_tree.xpath(chart_xpath, namespaces=namespaces) if chart_xpath else [] + + for item in items: + # item이 존재하면 True, 없으면 False + user_answer = (item is not None) and isXYtransposed + + # 정답과 수험자 답안 비교 + self.evaluate_answer(scoring, user_answer, right_answer, points) + if scoring['points'] > 0: + break + + + # 정답이 하나인 경우 + # elif (category or "") in ["OneAnswer", "ChartOneAnswer"]: + elif "OneAnswer" in (category or ""): + if "Header" in category: + def has_elements(ptags, xpath): + for p in ptags: + charshape_list = p.xpath(xpath) if xpath else [] + if charshape_list: + return True + return False + + page1_ptags = pages.get('Page_1', []) + page2_ptags = pages.get('Page_2', []) + header_xpath = "//HEADER//P" + has_page1_element = has_elements(page1_ptags, header_xpath) + has_page2_element = has_elements(page2_ptags, header_xpath) + + if not has_page1_element or not has_page2_element: + user_answer = "" + self.evaluate_answer(scoring, user_answer, right_answer, points, method="equal") + continue + + items = root.xpath(xpath) if xpath else [] + items2 = root.xpath(xpath2) if xpath2 else [] + + # 차트 XML에서 정답을 찾는 경우 + # 차트 종류가 + # 세로막대형이면 x축이 카테고리(catAx) y축이 값(valAx) + # 가로막대형이면 x축이 값(valAx) y축이 카테고리(catAx) + if "ChartOneAnswer" in category: + # 하드코딩이라 [2-45문항] 변경시 수정 필요 + # chart_type = self.scoring_criteria["2"]["45"]["chart_type"].replace(" ","") + + # chart_type 변수의 경우 45번 문항을 먼저 채점하므로 + # xy축의 변경이 필요한 53~58번 문항 채점시에 chart_type변수에 차트모양의 정보는 입력 되어있음 + + # 가로 차트일 경우에만 x축과 y축을 바꿔줌 + # 세로, 꺾은선, 원형 차트의 경우 그대로 사용 + if "가로" in chart_type: + if "catAx" in chart_xpath: + chart_xpath = chart_xpath.replace("catAx", "valAx") + elif "valAx" in chart_xpath: + chart_xpath = chart_xpath.replace("valAx", "catAx") + + chart_items = chart_tree.xpath(chart_xpath, namespaces=namespaces) if chart_xpath else [] + + for item in chain(items, items2, chart_items): + user_answer = item.replace(" ", "") if isinstance(item, str) else item + right_answer = right_answer.replace(" ", "") + + self.evaluate_answer(scoring, user_answer, right_answer, points) + if scoring['points'] > 0: + break + + # [2-6] 테두리 이중실선 1.00mm + elif (category or "") == "LineShape": + line_shapes = root.xpath(xpath) if xpath else [] + + user_answer = { + 'Style': None, + 'Width': None + } + + for line_shape in line_shapes: + style = line_shape.get("Style") + width = line_shape.get("Width") + + user_answer['Style'] = style + user_answer['Width'] = width + + self.evaluate_answer(scoring, user_answer, right_answer, points) + if scoring['points'] > 0: + break + + # 사용자 입력값이 mm단위인 경우 + elif (category or "") == "mmSize": + items = root.xpath(xpath) + # 오차범위 설정 + # 한글 프로그램 내부에서 드물게 0mm이지만 1pt로 저장되는 경우가 있음 + # + # XML파일의 요소 옵션값은 내부적으로 1=0.01pt + # 이 경우를 대비하여 tolerance를 10으로 설정 (1pt=약0.04mm 만큼의 오차 혀용) + error_range = criterion.get('tolerance', 10) + + # JSON 파일 value키값에 mm나 공백이 입력될 경우 제거 + # 예) "80.2 mm" >> 80.2 로 변환 + float_string = right_answer.strip().replace("mm", "") + right_answer = self.convert_mm_to_pt(float(float_string)) + + if not items: + scoring['points'] = 0 + else: + for item in items: + user_answer = float(item) + + self.evaluate_answer(scoring, user_answer, right_answer, points, method="tolerance", tolerance=error_range) if scoring['points'] > 0: break - - # 하이퍼링크인 경우 - # elif hyperlink_ptag and search_in_hyperlink: - else: - p_elements = hyperlink_ptag + + elif (category or "") == "ParaShape": + items = root.xpath(xpath) - for p in p_elements: - # 수험자가 입력한 텍스트 중 하이퍼링크가 들어간 문단의 모든 텍스트를 가져와 - # 채점하고자 하는 (정답) 하이퍼링크 텍스트와 시작 위치를 비교 - # (예시) - # [수험자입력] 1. 사전등록 : 서울 국제 도서 박람회 흠페이지(http://www.ind.or.kr) 참조 - # [정답] 서울 국제 도서 박람회 흠페이지(http://www.ind.or.kr) 참조 - # 수험자 텍스트의 "1. 사전등록" 부분을 제외하고 난 뒤 - # 남은 "서울 국제 도서 박람회 흠페이지(http://www.ind.or.kr) 참조"의 정답 부분과 유사도를 비교 - - text_list = p.xpath(".//CHAR/text()") - full_text = ''.join(text_list).replace(" ", "") - # print("full_text: ", full_text) - - # 채점하고자 하는 문자열 (search_value)의 첫 문자 - first_char = search_value[0] - - # 수험자 답안에서 첫 문자 인덱스 위치 - user_answer_first_index = full_text.find(first_char) - - if user_answer_first_index != -1: - # 수험자 답안에서 첫 문자 인덱스 위치부터 search_value 길이만큼 잘라서 비교 - trimmed_full_text = full_text[user_answer_first_index:] - else: - trimmed_full_text = full_text - - # 두 문자열의 유사도 계산 - similarity = difflib.SequenceMatcher(None, trimmed_full_text, hyperlink_text).ratio() - - # 두 문자열의 유사도에 따라 하이퍼링크 확인 - # 유사도가 낮은 경우 오답처리 - if similarity < 0.7: - self.evaluate_answer(scoring, user_answer, right_answer, 0, method="equal") - - # 유사도가 높은 경우 - else: - inside_field = False - charshape_list = [] - - for elem in p.iter(): - # 시작 지점 확인 - # FIELDBEGIN태그와 FIELDEND태그 사이 - if elem.tag == "FIELDBEGIN": - inside_field = True - elif elem.tag == "FIELDEND": - inside_field = False - - # 하이퍼링크 텍스트가 CharShape 속성값이 앞의 텍스트와 다른 경우 - # http://www.ihd.or.kr 주소가 TEXT 부모태그를 가지는 경우 - # [예시] - # - # http://www.ihd.or.kr) - # - # 해당 부모 TEXT태그의 CharShape속성을 확인 - elif inside_field and elem.tag == "TEXT": - charshape = elem.get("CharShape") - print('charshape : ', charshape) - if charshape: - charshape_list.append(charshape) - - # 하이퍼링크 텍스트가 CharShape 속성값이 앞의 텍스트와 같은 경우 - # http://www.ihd.or.kr 주소가 TEXT부모태그 없이 CHAR로만 있는경우 - # [예시] - # http://www.ihd.or.kr) - # FIELDBEGIN밖의 TEXT태그의 CharShape속성을 확인해야 한다 - elif inside_field and elem.tag == "CHAR": - parent = elem.getparent() - - charshape = parent.get("CharShape") - print('charshape : ', charshape) - if charshape: - charshape_list.append(charshape) - - - # 하이퍼링크에 해당하는 P태그 내 존재하는 charshape ID값 모두를 비교해 해당 속성(ITALIC, BOLD, UNDERLINE) 확인 - # 모든 charshape ID값이 정답과 일치하는 경우에만 점수 부여 - all_attributes_match = True - if charshape_list: - for charshape_id in charshape_list: - charshape = root.xpath(f"//CHARSHAPE[@Id='{charshape_id}']") - - # 속성 태그가 존재하는지 확인 - font_attribute = charshape[0].find(right_answer) - if font_attribute is None: - user_answer = None - all_attributes_match = False - break - - else: - user_answer = font_attribute.tag - - if all_attributes_match: - self.evaluate_answer(scoring, user_answer, right_answer, points, method="equal") - else: - self.evaluate_answer(scoring, user_answer, right_answer, 0, method="equal") - - elif (category or "") == "LineSpacing": - page1_ptags = pages.get('Page_1', []) - - # 줄간격이 하나라도 일치하지 않을 경우 오답처리 - linespacing_match = True - for p in page1_ptags: - parashape_id = p.get('ParaShape') - xpath = xpath.replace('{parashape_id}', parashape_id) - linespacing = root.xpath(xpath) - user_answer = linespacing[0] + for item in items: + user_answer = { + 'Left': float(item.get('Left', 0)) / 200, + 'Indent': float(item.get('Indent', 0)) / -200, + } - # print("🟡줄간격: ", user_answer) - if user_answer != right_answer: - linespacing_match = False - break - - # 문단 첫 글자 크기에 따라 채점 기준 추가 (050624) - # 1. 기본 줄간격 160% 일 때 26pt - # 2. 해당 문제의 정답 줄간격 (180% = 28pt / 200% = 30pt ) - # 두 경우의 글자 크기가 아니라면 오답처리 - firstword = criterion.get('first_word', None) - result = root.xpath(f"//CHARSHAPE[@Id=//RECTANGLE//TEXT[CHAR[text()='{firstword}']]/@CharShape]/@Height") - firstword_size = result[0] if result else None - - if (right_answer == '180' and firstword_size not in ['2600', '2800', None]) or (right_answer == '200' and firstword_size not in ['2600', '3000', None]): - linespacing_match = False - - if linespacing_match is True: - self.evaluate_answer(scoring, user_answer, right_answer, points, method="equal") - else: - self.evaluate_answer(scoring, user_answer, right_answer, 0, method="equal") - - - # 특수문자 갯수 채점 - elif (category or "") == "SpecialChar": - ch1 = criterion.get('char1', None) - ch2 = criterion.get('char2', None) - ch3 = criterion.get('char3', None) - xpath = xpath.replace('{char1}', ch1) - xpath2 = xpath2.replace('{char2}', ch2) - xpath3 = xpath3.replace('{char3}', ch3) - ch1_str = root.xpath(xpath) - ch2_str = root.xpath(xpath2) - ch3_str = root.xpath(xpath3) - sum_char = 0 - - # char1 요소에서 특수문자 갯수 세기 (최대 2점) - for text in ch1_str or []: - ch1_count = text.count(ch1) - sum_char += ch1_count - if sum_char >= 2: - sum_char = 2 - break - - # char2 요소에서 특수문자 갯수 세기 (최대 1점) - # char1과 char2가 다른 경우 (예: ▶ 행사안내 ◀) - if (ch1 != ch2) and ch2_str: - for text in ch2_str or []: - ch2_count = text.count(ch2) - if ch2_count > 1: - ch2_count = 1 - sum_char += ch2_count - - # char3 요소에서 특수문자 갯수 세기 (최대 1점) - if ch3_str: - for text in ch3_str or []: - ch3_count = text.count(ch3) - if ch3_count > 1: - ch3_count = 1 - sum_char += ch3_count - - user_answer = sum_char - - self.evaluate_answer(scoring, user_answer, right_answer, points, method="partial_score") - - # 쪽 테두리 (이중 실선, 머리말 포함) 설정 - elif (category or "") == "PageBorder": - user_answer = { - "header_inside": False, - "all_double_slim": False - } - - # 머릿말 포함 객체가 하나라도 있으면 정답 - header_inside_elements = root.xpath(xpath) - for header_inside in header_inside_elements: - # print("머릿말포함: ",header_inside) - if "true" in header_inside: - user_answer["header_inside"] = True - break - - # BORDERFILL요소의 자녀 - # LEFTBORDER, RIGHTBORDER, TOPBORDER, BOTTOMBORDER 요소의 Type속성이 - # 모두 DoubleSlim이면 정답 - border_tags = ["LEFTBORDER", "RIGHTBORDER", "TOPBORDER", "BOTTOMBORDER"] - - borderfill_elements = root.xpath(xpath2) - for borderfill in borderfill_elements: - all_double_slim = True - - for tag in border_tags: - element = borderfill.find(tag) - - if (element is None) or (element.get("Type") != "DoubleSlim"): - all_double_slim = False - break - - #모든 BORDER 태그의 Type 속성이 'DoubleSlim'인 객체가 있다면 반복문 탈출 - if all_double_slim: - user_answer["all_double_slim"] = True - break - - self.evaluate_answer(scoring, user_answer, right_answer, points, method="equal") - - # 다단 확인 [2-3]문항 - elif (category or "") == "TwoColumn": - page2_ptags = pages.get('Page_2', []) - - for p in page2_ptags: - column_count = p.xpath(xpath) - user_answer = column_count[0] if column_count else '0' - - if user_answer == right_answer: + # 정답과 수험자 답안 비교 self.evaluate_answer(scoring, user_answer, right_answer, points, method="equal") + + if scoring['points'] > 0: + break + + # Boolean 타입 정답인 경우 + elif (category or "") == "Boolean": + items = root.xpath(xpath) if xpath else False + items2 = root.xpath(xpath2) if xpath2 else False + chart_items = chart_tree.xpath(chart_xpath, namespaces=namespaces) if chart_xpath else False - # P태그들 중 하나라도 다단이 존재할 경우 정답처리 + user_answer = bool( items or items2 or chart_items ) + + self.evaluate_answer(scoring, user_answer, right_answer, points) + + # 채점기준표 파일에 작성된 rgb값을 그대로 읽어와 HML파일 요소의 int형 rgb값과 비교 + elif (category or "") == "Color": + items = root.xpath(xpath) if xpath else [] + items2 = root.xpath(xpath2) if xpath2 else [] + + rgb_text = right_answer + + # 정규식을 이용해 숫자만 리스트로 추출 + numbers = re.findall(r'\d+', rgb_text) + r, g, b = map(int, numbers) if len(numbers) == 3 else None + + # 콤마(,)로 구분된 문자열을 정수형으로 변환 + # r, g, b = map(int, rgb_text.split(',')) + + rgb_int = (b << 16) + (g << 8) + r + + # items, items2를 순차적으로 순회 + for item in chain(items, items2): + user_answer = int(item) + self.evaluate_answer(scoring, user_answer, rgb_int, points, method="equal") if scoring['points'] > 0: break - - # 한자 - elif (category or "") == "Hanja": - # 점수 계산 - score = 0 - max_score = points - - word_list = criterion.get('word', []) - # 부분점수 (최대점수에서 한자 갯수만큼 나눈 몫) - score_per_pair = max_score // len(word_list) - - # 한자가 5개 고정일 경우 - # score_per_pair = 2 - for kor, chn in word_list: - # XPath 구문 구성 및 실행 - exec_xpath = xpath.replace('{kor}', kor).replace('{chn}', chn) - matched = root.xpath(exec_xpath) + # 문단 첫글자 장식 채점 + elif (category or "") == "TwoLineSize": + items = root.xpath(xpath) + error_range = criterion.get('tolerance', 0) + for item in items: + user_answer = { + "Height": int(item.get('Height', 0)), + "Width": int(item.get('Width', 0)) + } + self.evaluate_answer(scoring, user_answer, right_answer, points, method="tolerance", tolerance=error_range) - if matched: - score += score_per_pair + if scoring['points'] > 0: + break + + # 폰트명 + elif "FontName" in (category or ""): + # 'DIAT' 머릿말 문항 1,2페이지 둘 중 하나라도 없으면 0점 처리 + if "Header" in category: + def has_charshape(ptags, xpath): + for p in ptags: + charshape_list = p.xpath(xpath) if xpath else [] + if charshape_list: + return True + return False + + page1_ptags = pages.get('Page_1', []) + page2_ptags = pages.get('Page_2', []) + header_xpath = "//HEADER//P" + has_page1_element = has_charshape(page1_ptags, header_xpath) + has_page2_element = has_charshape(page2_ptags, header_xpath) + + if not has_page1_element or not has_page2_element: + user_answer = "" + self.evaluate_answer(scoring, user_answer, right_answer, points, method="equal") + continue + + charshape_list = root.xpath(xpath) - # 최대 점수 초과 방지 - user_answer = min(score, max_score) - - self.evaluate_answer(scoring, user_answer, right_answer, points, method="partial_score") - - elif (category or "") == "ChartType": - chart_type_list = { - '꺾은선형': "//c:lineChart[c:grouping[@val='standard']]", - '묶은가로막대형': "//c:barChart[c:barDir[@val='bar'] and c:grouping[@val='clustered']]", - '누적가로막대형': "//c:barChart[c:barDir[@val='bar'] and c:grouping[@val='stacked']]", - '묶은세로막대형': "//c:barChart[c:barDir[@val='col'] and c:grouping[@val='clustered']]", - '누적세로막대형': "//c:barChart[c:barDir[@val='col'] and c:grouping[@val='stacked']]", - '원형': "//c:pieChart", - '분산형': "//c:scatterChart" - } - chart_type = criterion.get('chart_type').replace(" ","") - - # 입력한 chart_type에 해당하는 xpath를 가져옴 - chart_xpath = chart_type_list[chart_type] + # 문자속성이 없는 경우 + if not charshape_list: + user_answer = "" + self.evaluate_answer(scoring, user_answer, right_answer, points, method="equal") + else: + require_all_match = ("TableFontName" in category) + any_match = False + all_match = True + matched_user_answer = None # 일치하는 user_answer를 기억 - # xpath를 사용하여 차트 요소가 있는지 확인 - user_answer = bool(chart_tree.xpath(chart_xpath, namespaces=namespaces)) - self.evaluate_answer(scoring, user_answer, right_answer, points) - - # 문항 채점 결과를 리스트에 입력 - onePersonResult['score_results'].append(scoring) - print(f'scoring: {scoring}') + for charshape_id in charshape_list: + font_id = root.xpath(f"//CHARSHAPE[@Id='{charshape_id}']/FONTID/@Hangul") + if not font_id: + all_match = False + continue + + font_name = root.xpath(f"//FONTFACE[@Lang='Hangul']/FONT[@Id='{font_id[0]}']/@Name") + + if not font_name: + all_match = False + continue + + # 공백 제거 + user_answer = font_name[0].replace(" ", "") + right_answer = right_answer.replace(" ","") + + # 접두어 제거 + if right_answer in ["견고딕", "중고딕"]: + user_answer = user_answer.replace("한양", "") + + if user_answer == right_answer: + any_match = True + matched_user_answer = user_answer + else: + all_match = False + if require_all_match: + break + + if require_all_match: + score = points if all_match else 0 + self.evaluate_answer(scoring, user_answer, right_answer, score) + else: + score = points if any_match else 0 + self.evaluate_answer(scoring, matched_user_answer if any_match else "", right_answer, score) + + # 폰트 속성 + elif (category or "") == "FontAttribute": + # 하이퍼링크 처리 + + # 1. 하이퍼링크를 포함하는 P요소를 가져옴 + # 2. 그 P요소의 자손 CHAR태그에 있는 텍스트를 하나의 문자열로 변환 + # 3. P요소의 문자열과 채점하려는 문자열이 일치하는지 확인 + hyperlink_xpath = criterion.get('hyperlink_ptag', None) + hyperlink_ptag = root.xpath(hyperlink_xpath) if hyperlink_xpath else None + + p_tag_text_list = extract_char_text_from_p(hyperlink_ptag) if hyperlink_ptag else [] + hyperlink_text = search_value.replace(" ", "") if search_value else "" + + # search_value가 hyperlink문자열에 포함되어 있는지 확인 + # search_value가 hyperlink인 경우와 아닌경우를 구분해 채점 + search_in_hyperlink = False + if hyperlink_text and any(hyperlink_text in text for text in p_tag_text_list): + search_in_hyperlink = True + else: + search_in_hyperlink = False + + # hyperlink가 아닌 경우(일반적인 텍스트 일 경우) + # 하이퍼링크를 포함한 P태그가 없거나 search_value값이 하이퍼링크텍스트에 포함되어 있지 않을 경우 + if not hyperlink_ptag or not search_in_hyperlink: + charshape_list = root.xpath(xpath) + if not charshape_list: + charshape = None + user_answer = None + else: + for charshape in charshape_list: + font_attribute = charshape.find(right_answer) + if font_attribute is not None: + user_answer = font_attribute.tag + else: + user_answer = None + + self.evaluate_answer(scoring, user_answer, right_answer, points, method="equal") + + if scoring['points'] > 0: + break + + # 하이퍼링크인 경우 + # elif hyperlink_ptag and search_in_hyperlink: + else: + p_elements = hyperlink_ptag + + for p in p_elements: + # 수험자가 입력한 텍스트 중 하이퍼링크가 들어간 문단의 모든 텍스트를 가져와 + # 채점하고자 하는 (정답) 하이퍼링크 텍스트와 시작 위치를 비교 + # (예시) + # [수험자입력] 1. 사전등록 : 서울 국제 도서 박람회 흠페이지(http://www.ind.or.kr) 참조 + # [정답] 서울 국제 도서 박람회 흠페이지(http://www.ind.or.kr) 참조 + # 수험자 텍스트의 "1. 사전등록" 부분을 제외하고 난 뒤 + # 남은 "서울 국제 도서 박람회 흠페이지(http://www.ind.or.kr) 참조"의 정답 부분과 유사도를 비교 + + text_list = p.xpath(".//CHAR/text()") + full_text = ''.join(text_list).replace(" ", "") + # print("full_text: ", full_text) + + # 채점하고자 하는 문자열 (search_value)의 첫 문자 + first_char = search_value[0] + + # 수험자 답안에서 첫 문자 인덱스 위치 + user_answer_first_index = full_text.find(first_char) + + if user_answer_first_index != -1: + # 수험자 답안에서 첫 문자 인덱스 위치부터 search_value 길이만큼 잘라서 비교 + trimmed_full_text = full_text[user_answer_first_index:] + else: + trimmed_full_text = full_text + + # 두 문자열의 유사도 계산 + similarity = difflib.SequenceMatcher(None, trimmed_full_text, hyperlink_text).ratio() + + # 두 문자열의 유사도에 따라 하이퍼링크 확인 + # 유사도가 낮은 경우 오답처리 + if similarity < 0.7: + self.evaluate_answer(scoring, user_answer, right_answer, 0, method="equal") + + # 유사도가 높은 경우 + else: + inside_field = False + charshape_list = [] + + for elem in p.iter(): + # 시작 지점 확인 + # FIELDBEGIN태그와 FIELDEND태그 사이 + if elem.tag == "FIELDBEGIN": + inside_field = True + elif elem.tag == "FIELDEND": + inside_field = False + + # 하이퍼링크 텍스트가 CharShape 속성값이 앞의 텍스트와 다른 경우 + # http://www.ihd.or.kr 주소가 TEXT 부모태그를 가지는 경우 + # [예시] + # + # http://www.ihd.or.kr) + # + # 해당 부모 TEXT태그의 CharShape속성을 확인 + elif inside_field and elem.tag == "TEXT": + charshape = elem.get("CharShape") + print('charshape : ', charshape) + if charshape: + charshape_list.append(charshape) + + # 하이퍼링크 텍스트가 CharShape 속성값이 앞의 텍스트와 같은 경우 + # http://www.ihd.or.kr 주소가 TEXT부모태그 없이 CHAR로만 있는경우 + # [예시] + # http://www.ihd.or.kr) + # FIELDBEGIN밖의 TEXT태그의 CharShape속성을 확인해야 한다 + elif inside_field and elem.tag == "CHAR": + parent = elem.getparent() + + charshape = parent.get("CharShape") + print('charshape : ', charshape) + if charshape: + charshape_list.append(charshape) + + + # 하이퍼링크에 해당하는 P태그 내 존재하는 charshape ID값 모두를 비교해 해당 속성(ITALIC, BOLD, UNDERLINE) 확인 + # 모든 charshape ID값이 정답과 일치하는 경우에만 점수 부여 + all_attributes_match = True + if charshape_list: + for charshape_id in charshape_list: + charshape = root.xpath(f"//CHARSHAPE[@Id='{charshape_id}']") + + # 속성 태그가 존재하는지 확인 + font_attribute = charshape[0].find(right_answer) + if font_attribute is None: + user_answer = None + all_attributes_match = False + break + + else: + user_answer = font_attribute.tag + + if all_attributes_match: + self.evaluate_answer(scoring, user_answer, right_answer, points, method="equal") + else: + self.evaluate_answer(scoring, user_answer, right_answer, 0, method="equal") + + elif (category or "") == "LineSpacing": + page1_ptags = pages.get('Page_1', []) + + # 줄간격이 하나라도 일치하지 않을 경우 오답처리 + linespacing_match = True + for p in page1_ptags: + parashape_id = p.get('ParaShape') + xpath = xpath.replace('{parashape_id}', parashape_id) + linespacing = root.xpath(xpath) + user_answer = linespacing[0] + + # print("🟡줄간격: ", user_answer) + if user_answer != right_answer: + linespacing_match = False + break + + # 문단 첫 글자 크기에 따라 채점 기준 추가 (050624) + # 1. 기본 줄간격 160% 일 때 26pt + # 2. 해당 문제의 정답 줄간격 (180% = 28pt / 200% = 30pt ) + # 두 경우의 글자 크기가 아니라면 오답처리 + firstword = criterion.get('first_word', None) + result = root.xpath(f"//CHARSHAPE[@Id=//RECTANGLE//TEXT[CHAR[text()='{firstword}']]/@CharShape]/@Height") + firstword_size = result[0] if result else None + + if (right_answer == '180' and firstword_size not in ['2600', '2800', None]) or (right_answer == '200' and firstword_size not in ['2600', '3000', None]): + linespacing_match = False + + if linespacing_match is True: + self.evaluate_answer(scoring, user_answer, right_answer, points, method="equal") + else: + self.evaluate_answer(scoring, user_answer, right_answer, 0, method="equal") + + + # 특수문자 갯수 채점 + elif (category or "") == "SpecialChar": + ch1 = criterion.get('char1', None) + ch2 = criterion.get('char2', None) + ch3 = criterion.get('char3', None) + xpath = xpath.replace('{char1}', ch1) + xpath2 = xpath2.replace('{char2}', ch2) + xpath3 = xpath3.replace('{char3}', ch3) + ch1_str = root.xpath(xpath) + ch2_str = root.xpath(xpath2) + ch3_str = root.xpath(xpath3) + sum_char = 0 + + # char1 요소에서 특수문자 갯수 세기 (최대 2점) + for text in ch1_str or []: + ch1_count = text.count(ch1) + sum_char += ch1_count + if sum_char >= 2: + sum_char = 2 + break + + # char2 요소에서 특수문자 갯수 세기 (최대 1점) + # char1과 char2가 다른 경우 (예: ▶ 행사안내 ◀) + if (ch1 != ch2) and ch2_str: + for text in ch2_str or []: + ch2_count = text.count(ch2) + if ch2_count > 1: + ch2_count = 1 + sum_char += ch2_count + + # char3 요소에서 특수문자 갯수 세기 (최대 1점) + if ch3_str: + for text in ch3_str or []: + ch3_count = text.count(ch3) + if ch3_count > 1: + ch3_count = 1 + sum_char += ch3_count + + user_answer = sum_char + + self.evaluate_answer(scoring, user_answer, right_answer, points, method="partial_score") + + # 쪽 테두리 (이중 실선, 머리말 포함) 설정 + elif (category or "") == "PageBorder": + user_answer = { + "header_inside": False, + "all_double_slim": False + } + + # 머릿말 포함 객체가 하나라도 있으면 정답 + header_inside_elements = root.xpath(xpath) + for header_inside in header_inside_elements: + # print("머릿말포함: ",header_inside) + if "true" in header_inside: + user_answer["header_inside"] = True + break + + # BORDERFILL요소의 자녀 + # LEFTBORDER, RIGHTBORDER, TOPBORDER, BOTTOMBORDER 요소의 Type속성이 + # 모두 DoubleSlim이면 정답 + border_tags = ["LEFTBORDER", "RIGHTBORDER", "TOPBORDER", "BOTTOMBORDER"] + + borderfill_elements = root.xpath(xpath2) + for borderfill in borderfill_elements: + all_double_slim = True + + for tag in border_tags: + element = borderfill.find(tag) + + if (element is None) or (element.get("Type") != "DoubleSlim"): + all_double_slim = False + break + + #모든 BORDER 태그의 Type 속성이 'DoubleSlim'인 객체가 있다면 반복문 탈출 + if all_double_slim: + user_answer["all_double_slim"] = True + break + + self.evaluate_answer(scoring, user_answer, right_answer, points, method="equal") + + # 다단 확인 [2-3]문항 + elif (category or "") == "TwoColumn": + page2_ptags = pages.get('Page_2', []) + + for p in page2_ptags: + column_count = p.xpath(xpath) + user_answer = column_count[0] if column_count else '0' + + if user_answer == right_answer: + self.evaluate_answer(scoring, user_answer, right_answer, points, method="equal") + + # P태그들 중 하나라도 다단이 존재할 경우 정답처리 + if scoring['points'] > 0: + break + + # 한자 + elif (category or "") == "Hanja": + # 점수 계산 + score = 0 + max_score = points + + word_list = criterion.get('word', []) + # 부분점수 (최대점수에서 한자 갯수만큼 나눈 몫) + score_per_pair = max_score // len(word_list) + + # 한자가 5개 고정일 경우 + # score_per_pair = 2 + + for kor, chn in word_list: + # XPath 구문 구성 및 실행 + exec_xpath = xpath.replace('{kor}', kor).replace('{chn}', chn) + matched = root.xpath(exec_xpath) + + if matched: + score += score_per_pair + + # 최대 점수 초과 방지 + user_answer = min(score, max_score) + + self.evaluate_answer(scoring, user_answer, right_answer, points, method="partial_score") + + elif (category or "") == "ChartType": + chart_type_list = { + '꺾은선형': "//c:lineChart[c:grouping[@val='standard']]", + '묶은가로막대형': "//c:barChart[c:barDir[@val='bar'] and c:grouping[@val='clustered']]", + '누적가로막대형': "//c:barChart[c:barDir[@val='bar'] and c:grouping[@val='stacked']]", + '묶은세로막대형': "//c:barChart[c:barDir[@val='col'] and c:grouping[@val='clustered']]", + '누적세로막대형': "//c:barChart[c:barDir[@val='col'] and c:grouping[@val='stacked']]", + '원형': "//c:pieChart", + '분산형': "//c:scatterChart" + } + chart_type = criterion.get('chart_type').replace(" ","") + + # 입력한 chart_type에 해당하는 xpath를 가져옴 + chart_xpath = chart_type_list[chart_type] + + # xpath를 사용하여 차트 요소가 있는지 확인 + user_answer = bool(chart_tree.xpath(chart_xpath, namespaces=namespaces)) + self.evaluate_answer(scoring, user_answer, right_answer, points) + + finally: + # 문항 채점 결과를 리스트에 입력 + onePersonResult['score_results'].append(scoring) + print(f'scoring: {scoring}') onePersonResult['partial_scores'].append({ 'section': section_id, @@ -1278,13 +1320,13 @@ def main(): # 채점하고자 하는 유형은 주석 해제 exam_types = [ # 'A', - 'B', + # 'B', # 'C', - # 'D', + 'D', ] - test_mode = False - # test_mode = True #/TEST 폴더 채점시 + # test_mode = False + test_mode = True #/TEST 폴더 채점시 output_excel_paths = [] for exam_type in exam_types: diff --git a/zzz.xbook b/zzz.xbook index 3751ad3..0b62787 100644 --- a/zzz.xbook +++ b/zzz.xbook @@ -1 +1 @@ -[{"kind":2,"language":"xpath","value":"//a:t[text()='클라우드 보안투자']/ancestor::a:r//a:ea/@typeface"},{"kind":2,"language":"xpath","value":"boolean(//FONTFACE[@Lang='Hangul']/FONT[@Id=//CHARSHAPE/FONTID/@Hangul]/@Name='바탕' and //CHARSHAPE/@Height='1000' and //PARASHAPE/PARAMARGIN/@LineSpacing='160' and //PARASHAPE/@Align='Justify')"},{"kind":2,"language":"xpath","value":"//FONTFACE[@Lang='Hangul']/FONT[@Id=//CHARSHAPE/FONTID/@Hangul]/@Name='바탕'"},{"kind":2,"language":"xpath","value":"//CHAR[contains(text(),'각도')][contains(text(),'角度')]角度"},{"kind":2,"language":"xpath","value":"//CHAR[contains(text(),'예방')][contains(text(),'豫防')]"},{"kind":2,"language":"xpath","value":"//CHAR[contains(text(),'예방')]"},{"kind":2,"language":"xpath","value":"//c:majorGridlines"},{"kind":2,"language":"xpath","value":"//P[.//FIELDBEGIN[@Type='Hyperlink'] and .//CHAR[contains(., 'http')]]"},{"kind":2,"language":"xpath","value":"//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true')]/@HorzOffset"},{"kind":2,"language":"xpath","value":"//CHAR[contains(string(.), '※')]/descendant-or-self::text()"},{"kind":2,"language":"xpath","value":"//P[@ParaShape=\"17\"]/TEXT[@CharShape='7']//CHAR[string(.)]"},{"kind":2,"language":"xpath","value":"//CHAR[contains(string(.), '기타')]/text()"}] \ No newline at end of file +[{"kind":2,"language":"xpath","value":"//a:t[text()='클라우드 보안투자']/ancestor::a:r//a:ea/@typeface"},{"kind":2,"language":"xpath","value":"boolean(//FONTFACE[@Lang='Hangul']/FONT[@Id=//CHARSHAPE/FONTID/@Hangul]/@Name='바탕' and //CHARSHAPE/@Height='1000' and //PARASHAPE/PARAMARGIN/@LineSpacing='160' and //PARASHAPE/@Align='Justify')"},{"kind":2,"language":"xpath","value":"//FONTFACE[@Lang='Hangul']/FONT[@Id=//CHARSHAPE/FONTID/@Hangul]/@Name='바탕'"},{"kind":2,"language":"xpath","value":"//RECTANGLE//CHAR[text()='구강건강관거리']/ancestor::RECTANGLE/SHAPEOBJECT/SIZE/@Width"},{"kind":2,"language":"xpath","value":"//CHAR[contains(text(),'예방')][contains(text(),'豫防')]"},{"kind":2,"language":"xpath","value":"//TEXT[CHAR[text()='DIAT']]"},{"kind":2,"language":"xpath","value":"//HEADER//P"},{"kind":2,"language":"xpath","value":"//P[.//FIELDBEGIN[@Type='Hyperlink'] and .//CHAR[contains(., 'http')]]"},{"kind":2,"language":"xpath","value":"//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true')]/@HorzOffset"},{"kind":2,"language":"xpath","value":"//CHAR[contains(string(.), '※')]/descendant-or-self::text()"},{"kind":2,"language":"xpath","value":"//P[@ParaShape=\"17\"]/TEXT[@CharShape='7']//CHAR[string(.)]"},{"kind":2,"language":"xpath","value":"//CHAR[contains(string(.), '기타')]/text()"}] \ No newline at end of file diff --git a/회차별채점자료/2508/DIW_2508A.json b/회차별채점자료/2508/DIW_2508A.json index 59679dc..9ea62c4 100644 --- a/회차별채점자료/2508/DIW_2508A.json +++ b/회차별채점자료/2508/DIW_2508A.json @@ -255,27 +255,27 @@ "item": "문구 (시니어클럽)/③ 정렬 (가운데 정렬)" }, "25": { - "path": "//SECTION[1]//TEXT[CHAR[text()='{searchValue}']]/@CharShape", + "path": "//TEXT[CHAR[text()='{searchValue}']]/@CharShape", "searchValue": "DIAT", "value": "굴림", "points": 1, - "category": "FontName", + "category": "FontName.Header", "item": "문구 (DIAT)/① 글꼴 (굴림)" }, "26": { - "path": "//CHARSHAPE[@Id=//SECTION[1]//TEXT[CHAR[text()='{searchValue}']]/@CharShape]/@Height", + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]/@Height", "searchValue": "DIAT", "value": "900", "points": 1, - "category": "OneAnswer", + "category": "OneAnswer.Header", "item": "문구 (DIAT)/② 크기 (9pt)" }, "27": { - "path": "//PARASHAPE[@Id=//SECTION[1]//CHAR[text()='{searchValue}']/parent::TEXT/parent::P/@ParaShape]/@Align", + "path": "//PARASHAPE[@Id=//CHAR[text()='{searchValue}']/parent::TEXT/parent::P/@ParaShape]/@Align", "searchValue": "DIAT", "value": "Right", "points": 1, - "category": "OneAnswer", + "category": "OneAnswer.Header", "item": "문구 (DIAT)/③ 정렬 (오른쪽 정렬)" }, "28": { @@ -436,7 +436,7 @@ "item": "문구 (노인일자리)/⑩ 정렬 (가운데 정렬)" }, "14": { - "path": "//BINITEM[@BinData=//PICTURE/IMAGE/@BinItem][@Format='JPG']", + "path": "//BINITEM[@BinData=//PICTURE/IMAGE/@BinItem][@Format='JPG' or @Format='JPEG']", "value": true, "points": 2, "category": "Boolean", @@ -444,28 +444,28 @@ "desc": "첨부 이미지 파일명 손상으로 정상적인 채점이 불가한 경우가 발견되어서 이미지 첨부 여부로 채점 방식 변경 (7/3)" }, "15": { - "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/SIZE/@Width", + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/SIZE/@Width", "value": "85", "points": 2, "category": "mmSize", "item": "② 크기-너비 (85 mm)" }, "16": { - "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/SIZE/@Height", + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/SIZE/@Height", "value": "40", "points": 2, "category": "mmSize", "item": "③ 크기-높이 (40 mm)" }, "17": { - "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@HorzOffset", + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@HorzOffset", "value": "0", "points": 2, "category": "mmSize", "item": "④ 위치 (어울림 : 가로-쪽의 왼쪽 0.0mm)" }, "18": { - "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@VertOffset", + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@VertOffset", "value": "22", "points": 2, "category": "mmSize", @@ -608,10 +608,10 @@ "33": { "path": "//TEXT[CHAR[contains(text(),'{searchValue}')]]/@CharShape", "searchValue": "노인일자리 창출 현황(예산:십억원)", - "value": "맑은 고딕", + "value": "굴림체", "points": 1, "category": "FontName", - "item": "제목 문구 (노인일자리 창출 현황(예산:십억원))/① 글씨체 (맑은 고딕)" + "item": "제목 문구 (노인일자리 창출 현황(예산:십억원))/① 글씨체 (굴림체)" }, "34": { "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]/@Height", @@ -672,11 +672,11 @@ "41": { "path": "//TABLE//TEXT/@CharShape", "path2": "//FONTFACE[@Lang='Hangul']/FONT[@Id=//CHARSHAPE[@Id=//TABLE/ROW/descendant::TEXT/@CharShape]/FONTID/@Hangul]/@Name", - "value": "굴림체", + "value": "맑은 고딕", "points": 1, "category": "TableFontName", "category_tmp": "FontName", - "item": "글자모양/① 글씨체 (굴림체)", + "item": "글자모양/① 글씨체 (맑은 고딕)", "desc": "테이블 폰트명 문항은 테이블의 모든 셀이 정답폰트와 일치해야 함, 하나만 일치해도 정답으로 채점할 경우 category값을 FontName으로 변경" }, "42": { diff --git a/회차별채점자료/2508/DIW_2508B.json b/회차별채점자료/2508/DIW_2508B.json index 45dde3b..bb67be2 100644 --- a/회차별채점자료/2508/DIW_2508B.json +++ b/회차별채점자료/2508/DIW_2508B.json @@ -255,27 +255,27 @@ "item": "문구 (기능경진대회운영위원회)/③ 정렬 (가운데 정렬)" }, "25": { - "path": "//SECTION[1]//TEXT[CHAR[text()='{searchValue}']]/@CharShape", + "path": "//TEXT[CHAR[text()='{searchValue}']]/@CharShape", "searchValue": "DIAT", "value": "굴림", "points": 1, - "category": "FontName", + "category": "FontName.Header", "item": "문구 (DIAT)/① 글꼴 (굴림)" }, "26": { - "path": "//CHARSHAPE[@Id=//SECTION[1]//TEXT[CHAR[text()='{searchValue}']]/@CharShape]/@Height", + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]/@Height", "searchValue": "DIAT", "value": "900", "points": 1, - "category": "OneAnswer", + "category": "OneAnswer.Header", "item": "문구 (DIAT)/② 크기 (9pt)" }, "27": { - "path": "//PARASHAPE[@Id=//SECTION[1]//CHAR[text()='{searchValue}']/parent::TEXT/parent::P/@ParaShape]/@Align", + "path": "//PARASHAPE[@Id=//CHAR[text()='{searchValue}']/parent::TEXT/parent::P/@ParaShape]/@Align", "searchValue": "DIAT", "value": "Right", "points": 1, - "category": "OneAnswer", + "category": "OneAnswer.Header", "item": "문구 (DIAT)/③ 정렬 (오른쪽 정렬)" }, "28": { @@ -436,7 +436,7 @@ "item": "문구 (기능경진대회)/⑩ 정렬 (가운데 정렬)" }, "14": { - "path": "//BINITEM[@BinData=//PICTURE/IMAGE/@BinItem][@Format='JPG']", + "path": "//BINITEM[@BinData=//PICTURE/IMAGE/@BinItem][@Format='JPG' or @Format='JPEG']", "value": true, "points": 2, "category": "Boolean", @@ -444,28 +444,28 @@ "desc": "첨부 이미지 파일명 손상으로 정상적인 채점이 불가한 경우가 발견되어서 이미지 첨부 여부로 채점 방식 변경 (7/3)" }, "15": { - "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/SIZE/@Width", + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/SIZE/@Width", "value": "85", "points": 2, "category": "mmSize", "item": "② 크기-너비 (85 mm)" }, "16": { - "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/SIZE/@Height", + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/SIZE/@Height", "value": "40", "points": 2, "category": "mmSize", "item": "③ 크기-높이 (40 mm)" }, "17": { - "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@HorzOffset", + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@HorzOffset", "value": "0", "points": 2, "category": "mmSize", "item": "④ 위치 (어울림 : 가로-쪽의 왼쪽 0.0mm)" }, "18": { - "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@VertOffset", + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@VertOffset", "value": "22", "points": 2, "category": "mmSize", diff --git a/회차별채점자료/2508/DIW_2508C.json b/회차별채점자료/2508/DIW_2508C.json index bc8af8c..3df41c9 100644 --- a/회차별채점자료/2508/DIW_2508C.json +++ b/회차별채점자료/2508/DIW_2508C.json @@ -255,27 +255,28 @@ "item": "문구 (밝은미소구강센터)/③ 정렬 (가운데 정렬)" }, "25": { - "path": "//SECTION[1]//TEXT[CHAR[text()='{searchValue}']]/@CharShape", + "path": "//TEXT[CHAR[text()='{searchValue}']]/@CharShape", + "page": 1, "searchValue": "DIAT", "value": "궁서", "points": 1, - "category": "FontName", + "category": "FontName.Header", "item": "문구 (DIAT)/① 글꼴 (궁서)" }, "26": { - "path": "//CHARSHAPE[@Id=//SECTION[1]//TEXT[CHAR[text()='{searchValue}']]/@CharShape]/@Height", + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]/@Height", "searchValue": "DIAT", "value": "900", "points": 1, - "category": "OneAnswer", + "category": "OneAnswer.Header", "item": "문구 (DIAT)/② 크기 (9pt)" }, "27": { - "path": "//PARASHAPE[@Id=//SECTION[1]//CHAR[text()='{searchValue}']/parent::TEXT/parent::P/@ParaShape]/@Align", + "path": "//PARASHAPE[@Id=//CHAR[text()='{searchValue}']/parent::TEXT/parent::P/@ParaShape]/@Align", "searchValue": "DIAT", "value": "Right", "points": 1, - "category": "OneAnswer", + "category": "OneAnswer.Header", "item": "문구 (DIAT)/③ 정렬 (오른쪽 정렬)" }, "28": { @@ -436,7 +437,7 @@ "item": "문구 (구강건강관리)/⑩ 정렬 (가운데 정렬)" }, "14": { - "path": "//BINITEM[@BinData=//PICTURE/IMAGE/@BinItem][@Format='JPG']", + "path": "//BINITEM[@BinData=//PICTURE/IMAGE/@BinItem][@Format='JPG' or @Format='JPEG']", "value": true, "points": 2, "category": "Boolean", @@ -444,28 +445,28 @@ "desc": "첨부 이미지 파일명 손상으로 정상적인 채점이 불가한 경우가 발견되어서 이미지 첨부 여부로 채점 방식 변경 (7/3)" }, "15": { - "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/SIZE/@Width", + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/SIZE/@Width", "value": "80", "points": 2, "category": "mmSize", "item": "② 크기-너비 (80 mm)" }, "16": { - "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/SIZE/@Height", + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/SIZE/@Height", "value": "40", "points": 2, "category": "mmSize", "item": "③ 크기-높이 (40 mm)" }, "17": { - "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@HorzOffset", + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@HorzOffset", "value": "0", "points": 2, "category": "mmSize", "item": "④ 위치 (어울림 : 가로-쪽의 왼쪽 0.0mm)" }, "18": { - "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@VertOffset", + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@VertOffset", "value": "22", "points": 2, "category": "mmSize", diff --git a/회차별채점자료/2508/DIW_2508D.json b/회차별채점자료/2508/DIW_2508D.json index 50150c5..684479e 100644 --- a/회차별채점자료/2508/DIW_2508D.json +++ b/회차별채점자료/2508/DIW_2508D.json @@ -255,27 +255,27 @@ "item": "문구 (중앙문화지역센터)/③ 정렬 (가운데 정렬)" }, "25": { - "path": "//SECTION[1]//TEXT[CHAR[text()='{searchValue}']]/@CharShape", + "path": "//TEXT[CHAR[text()='{searchValue}']]/@CharShape", "searchValue": "DIAT", "value": "궁서", "points": 1, - "category": "FontName", + "category": "FontName.Header", "item": "문구 (DIAT)/① 글꼴 (궁서)" }, "26": { - "path": "//CHARSHAPE[@Id=//SECTION[1]//TEXT[CHAR[text()='{searchValue}']]/@CharShape]/@Height", + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]/@Height", "searchValue": "DIAT", "value": "900", "points": 1, - "category": "OneAnswer", + "category": "OneAnswer.Header", "item": "문구 (DIAT)/② 크기 (9pt)" }, "27": { - "path": "//PARASHAPE[@Id=//SECTION[1]//CHAR[text()='{searchValue}']/parent::TEXT/parent::P/@ParaShape]/@Align", + "path": "//PARASHAPE[@Id=//CHAR[text()='{searchValue}']/parent::TEXT/parent::P/@ParaShape]/@Align", "searchValue": "DIAT", "value": "Right", "points": 1, - "category": "OneAnswer", + "category": "OneAnswer.Header", "item": "문구 (DIAT)/③ 정렬 (오른쪽 정렬)" }, "28": { @@ -436,7 +436,7 @@ "item": "문구 (매력적인 강원도)/⑩ 정렬 (가운데 정렬)" }, "14": { - "path": "//BINITEM[@BinData=//PICTURE/IMAGE/@BinItem][@Format='JPG']", + "path": "//BINITEM[@BinData=//PICTURE/IMAGE/@BinItem][@Format='JPG' or @Format='JPEG']", "value": true, "points": 2, "category": "Boolean", @@ -444,28 +444,28 @@ "desc": "첨부 이미지 파일명 손상으로 정상적인 채점이 불가한 경우가 발견되어서 이미지 첨부 여부로 채점 방식 변경 (7/3)" }, "15": { - "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/SIZE/@Width", + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/SIZE/@Width", "value": "85", "points": 2, "category": "mmSize", "item": "② 크기-너비 (85 mm)" }, "16": { - "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/SIZE/@Height", + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/SIZE/@Height", "value": "40", "points": 2, "category": "mmSize", "item": "③ 크기-높이 (40 mm)" }, "17": { - "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@HorzOffset", + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@HorzOffset", "value": "0", "points": 2, "category": "mmSize", "item": "④ 위치 (어울림 : 가로-쪽의 왼쪽 0.0mm)" }, "18": { - "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@VertOffset", + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@VertOffset", "value": "22", "points": 2, "category": "mmSize", diff --git a/회차별채점자료/2508/_DIW_2508A.json b/회차별채점자료/2508/_DIW_2508A.json new file mode 100644 index 0000000..d8f0f4d --- /dev/null +++ b/회차별채점자료/2508/_DIW_2508A.json @@ -0,0 +1,840 @@ +{ + "0": { + "0": { + "path": "", + "path2": "", + "points": 0, + "category": "파일저장", + "item": "파일명 (수검번호.hwp/hwpx)" + }, + "1": { + "path": "//PAGEMARGIN", + "value": { + "Top": 20, + "Bottom": 20, + "Left": 20, + "Right": 20, + "Header": 10, + "Footer": 10, + "Gutter": 0 + }, + "tolerance": 1, + "points": 4, + "category": "PageSetting", + "item": "A4용지, 왼쪽/오른쪽/위쪽/아래쪽 (각20mm), 머리말/꼬리말 (10mm), 제본(0mm)" + }, + "2": { + "path": "", + "value": { + "FontName": "바탕", + "FontSize": "1000", + "Alignment": "Justify", + "LineSpacing": "160" + }, + "points": 4, + "category": "BasicSetting", + "item": "글꼴 (바탕, 10pt), 양쪽정렬, 줄간격 (160%)" + }, + "3": { + "path": "", + "value": null, + "points": 40, + "category": "오타감점", + "item": "오타 1개 -1점 / 2503회부터 오타 1개 -1점으로 변경" + } + }, + "1": { + "1": { + "path": "//TEXTART[@Text='{searchValue}']/TEXTARTSHAPE/@FontName", + "searchValue": "노인일자리참여자모집", + "value": "휴먼옛체", + "points": 1, + "category": "OneAnswer", + "item": "문구 (노인일자리참여자모집)/① 글씨체 (휴먼옛체)" + }, + "2": { + "path": "//TEXTART[@Text='{searchValue}']/descendant::WINDOWBRUSH/@FaceColor", + "searchValue": "노인일자리참여자모집", + "value": "199,58,82", + "points": 2, + "category": "Color", + "item": "문구 (노인일자리참여자모집)/② 채우기 : 색상(RGB:199,58,82)" + }, + "3": { + "path": "//TEXTART[@Text='{searchValue}']/SHAPEOBJECT/SIZE/@Width", + "searchValue": "노인일자리참여자모집", + "value": "120", + "tolerance": 1, + "points": 2, + "category": "mmSize", + "item": "문구 (노인일자리참여자모집)/③ 크기-너비 (120 mm)" + }, + "4": { + "path": "//TEXTART[@Text='{searchValue}']/SHAPEOBJECT/SIZE/@Height", + "searchValue": "노인일자리참여자모집", + "value": "20", + "tolerance": 1, + "points": 2, + "category": "mmSize", + "item": "문구 (노인일자리참여자모집)/④ 크기-높이 (20 mm)" + }, + "5": { + "path": "//TEXTART[@Text='{searchValue}']/SHAPEOBJECT/POSITION/@TreatAsChar", + "searchValue": "노인일자리참여자모집", + "value": "true", + "points": 2, + "category": "OneAnswer", + "item": "문구 (노인일자리참여자모집)/⑤ 위치 (글자처럼 취급)" + }, + "6": { + "path": "//PARASHAPE[@Id=//P[.//TEXTART[@Text='{searchValue}']]/@ParaShape]/@Align", + "searchValue": "노인일자리참여자모집", + "value": "Center", + "points": 2, + "category": "OneAnswer", + "item": "문구 (노인일자리참여자모집)/⑥ 정렬 (가운데 정렬)" + }, + "7": { + "path": "//TEXTART[@Text='{searchValue}']", + "searchValue": "노인일자리참여자모집", + "value": true, + "points": 2, + "category": "Boolean", + "item": "문구 (노인일자리참여자모집)/⑦ 글맵시모양 (육안확인)" + }, + "8": { + "path": "//RECTANGLE[.//CHAR[text()='{searchValue}']]/SHAPEOBJECT/SIZE", + "searchValue": "어", + "value": { + "Height": 2800, + "Width": 2800 + }, + "tolerance": 200, + "points": 1, + "category": "TwoLineSize", + "item": "어/① 모양 (2줄)" + }, + "9": { + "path": "//TEXT[CHAR[text()='{searchValue}']]/@CharShape", + "searchValue": "어", + "value": "중고딕", + "points": 1, + "category": "FontName", + "item": "어/② 글씨체 (중고딕)" + }, + "10": { + "path": "//RECTANGLE[.//CHAR[text()='{searchValue}']]//WINDOWBRUSH/@FaceColor", + "searchValue": "어", + "value": "137,221,202", + "points": 2, + "category": "Color", + "item": "어/③ 면색 : 색상(RGB:137,221,202)" + }, + "11": { + "path": "//RECTANGLE[.//CHAR[text()='{searchValue}']]//OUTSIDEMARGIN/@Right", + "searchValue": "어", + "value": "3.0", + "tolerance": 1, + "points": 2, + "category": "mmSize", + "item": "어/④ 본문과의 간격 : 3.0mm" + }, + "12": { + "path": "//CHARSHAPE[@Id=//CHAR[contains(text(),'{searchValue}')]/parent::TEXT/@CharShape]", + "searchValue": "어르신들에게 다양한 일자리와 봉사활동 기회", + "value": "BOLD", + "points": 2, + "category": "FontAttribute", + "item": "문구 (어르신들에게 다양한 일자리와 봉사활동 기회)/① BOLD" + }, + "13": { + "path": "//CHARSHAPE[@Id=//CHAR[contains(text(),'{searchValue}')]/parent::TEXT/@CharShape]", + "searchValue": "어르신들에게 다양한 일자리와 봉사활동 기회", + "value": "UNDERLINE", + "points": 2, + "category": "FontAttribute", + "item": "문구 (어르신들에게 다양한 일자리와 봉사활동 기회)/② UNDERLINE" + }, + "14": { + "path": "//CHAR[contains(string(.),'{char1}')]/text()", + "path2": "//CHAR[contains(string(.),'{char2}')]/text()", + "path3": "//CHAR[contains(string(.),'{char3}')]/text()", + "char1": "▶", + "char2": "◀", + "char3": "※", + "value": 3, + "points": 3, + "category": "SpecialChar", + "item": "① ▶, ② ◀, ③ ※" + }, + "15": { + "path": "//CHAR[contains(text(),'{searchValue}')]/parent::TEXT/@CharShape", + "searchValue": "모집안내", + "value": "궁서체", + "points": 1, + "category": "FontName", + "item": "문구 (▶ 모집안내 ◀)/① 글씨체 (궁서체)" + }, + "16": { + "path": "//PARASHAPE[@Id=//CHAR[contains(text(),'{match_str}')]/ancestor::P/@ParaShape]/@Align", + "match_str": "모집안내", + "value": "Center", + "points": 1, + "category": "Align", + "item": "문구 (▶ 모집안내 ◀)/② 정렬 (가운데 정렬)" + }, + "17": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]", + "hyperlink_ptag": "//P[.//FIELDBEGIN[@Type='Hyperlink']]", + "searchValue": "공익활동형, 사회서비스형, 공동체사업단", + "value": "BOLD", + "points": 1, + "category": "FontAttribute", + "item": "문구 (공익활동형, 사회서비스형, 공동체사업단)/① BOLD" + }, + "18": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]", + "hyperlink_ptag": "//P[.//FIELDBEGIN[@Type='Hyperlink']]", + "searchValue": "공익활동형, 사회서비스형, 공동체사업단", + "value": "ITALIC", + "points": 1, + "category": "FontAttribute", + "item": "문구 (공익활동형, 사회서비스형, 공동체사업단)/② ITALIC" + }, + "19": { + "path": "//PARASHAPE[@Id=//CHAR[contains(text(),'{searchValue}')]/ancestor::P/following-sibling::P[1]/@ParaShape]/PARAMARGIN", + "searchValue": "기타사항", + "value": { + "Left": 15, + "Indent": 12 + }, + "points": 2, + "category": "ParaShape", + "item": "문구 (※ 기타… 이하 문단)/왼쪽여백 (15), 내어쓰기 (12)", + "desc": "내부적으로 내어쓰기는 음수값 / JSON value값은 양수로 입력" + }, + "20": { + "path": "//CHARSHAPE[@Id=//CHAR[contains(text(),'{searchValue}')]/parent::TEXT/@CharShape]/@Height", + "searchValue": "2025. 08. 23", + "value": "1300", + "points": 1, + "category": "OneAnswer", + "item": "문구 (2025. 08. 23)/① 크기 (1300)", + "desc": "1pt당 100" + }, + "21": { + "path": "//PARASHAPE[@Id=//CHAR[contains(text(),'{searchValue}')]/ancestor::P/@ParaShape]/@Align", + "searchValue": "2025. 08. 23", + "value": "Center", + "points": 1, + "category": "OneAnswer", + "item": "문구 (2025. 08. 23)/② 정렬 (가운데 정렬)" + }, + "22": { + "path": "//TEXT[CHAR[text()='{searchValue}']]/@CharShape", + "searchValue": "시니어클럽", + "value": "궁서", + "points": 1, + "category": "FontName", + "item": "문구 (시니어클럽)/① 글씨체 (궁서)" + }, + "23": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]/@Height", + "searchValue": "시니어클럽", + "value": "2400", + "points": 1, + "category": "OneAnswer", + "item": "문구 (시니어클럽)/② 크기 (2400)" + }, + "24": { + "path": "//PARASHAPE[@Id=//CHAR[text()='{searchValue}']/ancestor::P/@ParaShape]/@Align", + "searchValue": "시니어클럽", + "value": "Center", + "points": 1, + "category": "OneAnswer", + "item": "문구 (시니어클럽)/③ 정렬 (가운데 정렬)" + }, + "25": { + "path": "//SECTION[1]//TEXT[CHAR[text()='{searchValue}']]/@CharShape", + "searchValue": "DIAT", + "value": "굴림", + "points": 1, + "category": "FontName", + "item": "문구 (DIAT)/① 글꼴 (굴림)" + }, + "26": { + "path": "//CHARSHAPE[@Id=//SECTION[1]//TEXT[CHAR[text()='{searchValue}']]/@CharShape]/@Height", + "searchValue": "DIAT", + "value": "900", + "points": 1, + "category": "OneAnswer", + "item": "문구 (DIAT)/② 크기 (9pt)" + }, + "27": { + "path": "//PARASHAPE[@Id=//SECTION[1]//CHAR[text()='{searchValue}']/parent::TEXT/parent::P/@ParaShape]/@Align", + "searchValue": "DIAT", + "value": "Right", + "points": 1, + "category": "OneAnswer", + "item": "문구 (DIAT)/③ 정렬 (오른쪽 정렬)" + }, + "28": { + "path": "//PAGENUM/@FormatType", + "value": "HangulSyllable", + "points": 2, + "category": "PageNumber", + "item": "① 쪽 번호 매기기 (가,나,다 순으로)", + "desc1": { + "가,나,다": "HangulSyllable", + "1,2,3": "Digit", + "갑,을,병": "DecagonCircle", + "A,B,C": "LatinCapital", + "a,b,c": "LatinSmall", + "①,②,③": "CircledDigit", + "一,二,三": "Ideograph", + "㉠,㉡,㉢": "CircledHangulJamo", + "ⓐ,ⓑ,ⓒ": "CircledLatinSmall", + "i,ii,iii": "RomanSmall", + "I,II,III": "RomanCapital", + "desc": "정답에 맞는 값 value에 입력" + }, + "desc2": "1, 2페이지 모두 정답이어야 점수 부여" + }, + "29": { + "path": "//PAGENUM/@Pos", + "value": "BottomCenter", + "points": 2, + "category": "PageNumber", + "item": "가운데 아래", + "desc": "1, 2페이지 모두 정답이어야 점수 부여", + "desc2": { + "가운데 아래": "BottomCenter", + "오른쪽 아래": "BottomRight" + } + }, + "30": { + "path": "//PARASHAPE[@Id='{parashape_id}']/PARAMARGIN/@LineSpacing", + "value": "180", + "first_word": "어", + "points": 2, + "category": "LineSpacing", + "item": "문제 1 줄간격 180% 설정", + "desc": "1페이지 문단의 줄간격이 정답이 아닌 문단이 있으면 False(감점), first_word 속성에 [문단 첫글자 장식]에 해당하는 글자를 입력해준다." + } + }, + "2": { + "1": { + "path": "//PAGEBORDERFILL[@Type='Both' or @Type='Even']/@HeaderInside", + "path2": "//BORDERFILL[@Id=//PAGEBORDERFILL[@Type='Both' or @Type='Even']/@BorferFill]", + "value": { + "header_inside": true, + "all_double_slim": true + }, + "points": 4, + "category": "PageBorder", + "item": "문제2 쪽테두리(이중 실선, 머리말 포함) 설정" + }, + "2": { + "path": "count(//SECTION)>1", + "value": true, + "points": 3, + "category": "Boolean", + "item": "① 구역나누기", + "desc": "섹션이 1개 이상이면 점수부여" + }, + "3": { + "path": "TEXT/COLDEF/@Count", + "value": "2", + "points": 3, + "category": "TwoColumn", + "item": "② 다단 2단" + }, + "4": { + "path": "//RECTANGLE//CHAR[text()='{searchValue}']/ancestor::RECTANGLE/SHAPEOBJECT/SIZE/@Width", + "searchValue": "노인일자리", + "value": "60", + "points": 2, + "category": "mmSize", + "item": "문구 (노인일자리)/① 크기-너비 (60 mm)" + }, + "5": { + "path": "//RECTANGLE//CHAR[text()='{searchValue}']/ancestor::RECTANGLE/SHAPEOBJECT/SIZE/@Height", + "searchValue": "노인일자리", + "value": "12", + "points": 2, + "category": "mmSize", + "item": "문구 (노인일자리)/② 크기-높이 (12 mm)" + }, + "6": { + "path": "//RECTANGLE[.//CHAR[text()='{searchValue}']]//LINESHAPE", + "searchValue": "노인일자리", + "value": { + "Style": "DoubleSlim", + "Width": "283" + }, + "points": 2, + "category": "LineShape", + "item": "문구 (노인일자리)/③ 테두리 : 이중 실선(1.00mm)", + "desc": "1mm = 283pt value['Width']에 pt값 입력" + }, + "7": { + "path": "//RECTANGLE[.//CHAR[text()='{searchValue}']]/@Ratio", + "searchValue": "노인일자리", + "value": "50", + "points": 2, + "category": "OneAnswer", + "item": "문구 (노인일자리)/④ 글상자 모서리 (반원)", + "desc": "모서리 비율 반원:50 / 둥근모양:20" + }, + "8": { + "path": "//RECTANGLE[.//CHAR[text()='{searchValue}']]//WINDOWBRUSH/@FaceColor", + "searchValue": "노인일자리", + "value": "211,251,193", + "points": 2, + "category": "Color", + "item": "문구 (노인일자리)/⑤ 채우기 : 색상(RGB:211,251,193)" + }, + "9": { + "path": "//RECTANGLE[.//CHAR[text()='{searchValue}']]/SHAPEOBJECT/POSITION/@TreatAsChar", + "searchValue": "노인일자리", + "value": "true", + "points": 1, + "category": "OneAnswer", + "item": "문구 (노인일자리)/⑥ 글상자 위치 (글자처럼 취급)" + }, + "10": { + "path": "//PARASHAPE[@Id=//RECTANGLE//CHAR[text()='{searchValue}']/ancestor::P[last()]/@ParaShape]/@Align", + "searchValue": "노인일자리", + "value": "Center", + "points": 1, + "category": "OneAnswer", + "item": "문구 (노인일자리)/⑦ 글상자 정렬 (가운데 정렬)" + }, + "11": { + "path": "//TEXT[CHAR[text()='{searchValue}']]/@CharShape", + "searchValue": "노인일자리", + "value": "맑은고딕", + "points": 1, + "category": "FontName", + "item": "문구 (노인일자리)/⑧ 글씨체 (맑은고딕)" + }, + "12": { + "path": "//CHARSHAPE[@Id=//RECTANGLE//TEXT[./CHAR[text()='{searchValue}']]/@CharShape]/@Height", + "searchValue": "노인일자리", + "value": "2200", + "points": 1, + "category": "OneAnswer", + "item": "문구 (노인일자리)/⑨ 글씨크기 (2200)", + "desc": "1pt당 100" + }, + "13": { + "path": "//PARASHAPE[@Id=//RECTANGLE//P[.//CHAR[text()='{searchValue}']]/@ParaShape]/@Align", + "searchValue": "노인일자리", + "value": "Center", + "points": 1, + "category": "OneAnswer", + "item": "문구 (노인일자리)/⑩ 정렬 (가운데 정렬)" + }, + "14": { + "path": "//BINITEM[@BinData=//PICTURE/IMAGE/@BinItem][@Format='JPG' or @Format='JPEG']", + "value": true, + "points": 2, + "category": "Boolean", + "item": "① 파일명 \"그림A.jpg\" 삽입", + "desc": "첨부 이미지 파일명 손상으로 정상적인 채점이 불가한 경우가 발견되어서 이미지 첨부 여부로 채점 방식 변경 (7/3)" + }, + "15": { + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/SIZE/@Width", + "value": "85", + "points": 2, + "category": "mmSize", + "item": "② 크기-너비 (85 mm)" + }, + "16": { + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/SIZE/@Height", + "value": "40", + "points": 2, + "category": "mmSize", + "item": "③ 크기-높이 (40 mm)" + }, + "17": { + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@HorzOffset", + "value": "0", + "points": 2, + "category": "mmSize", + "item": "④ 위치 (어울림 : 가로-쪽의 왼쪽 0.0mm)" + }, + "18": { + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@VertOffset", + "value": "22", + "points": 2, + "category": "mmSize", + "item": "⑤ 위치 (어울림 : 세로-쪽의 위 22 mm)" + }, + "19": { + "path": "//TEXT[CHAR[text()='{searchValue}']]/@CharShape", + "searchValue": "1. 필요성", + "value": "돋움", + "points": 1, + "category": "FontName", + "item": "문구① (1. 필요성)/① 글씨체 (돋움)" + }, + "20": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]/@Height", + "searchValue": "1. 필요성", + "value": "1200", + "points": 1, + "category": "OneAnswer", + "item": "문구① (1. 필요성)/② 크기 (1200)" + }, + "21": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]", + "searchValue": "1. 필요성", + "value": "BOLD", + "points": 1, + "category": "FontAttribute", + "item": "문구① (1. 필요성)/③ 진하게" + }, + "22": { + "path": "//TEXT[CHAR[text()='{searchValue}']]/@CharShape", + "searchValue": "2.주요 노인일자리사업", + "value": "돋움", + "points": 1, + "category": "FontName", + "item": "문구② (2.주요 노인일자리사업)/① 글씨체 (돋움)" + }, + "23": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]/@Height", + "searchValue": "2.주요 노인일자리사업", + "value": "1200", + "points": 1, + "category": "OneAnswer", + "item": "문구② (2.주요 노인일자리사업)/② 크기 (1200)" + }, + "24": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]", + "searchValue": "2.주요 노인일자리사업", + "value": "BOLD", + "points": 1, + "category": "FontAttribute", + "item": "문구② (2.주요 노인일자리사업)/③ 진하게" + }, + "25": { + "path": "boolean(//TEXT[CHAR[contains(text(),'{option}')]]/FOOTNOTE)", + "path2": "boolean(//CHAR[substring(., string-length(.) - string-length('{option}') + 1) = '{option}']/following-sibling::FOOTNOTE/descendant::CHAR)", + "option": "세계보건기구", + "value": true, + "points": 2, + "category": "Boolean", + "item": "문구 (세계보건기구)/① 각주 설정 및 문구 입력" + }, + "26": { + "path": "//CHAR[contains(text(),'{searchValue}')]/parent::TEXT/@CharShape", + "searchValue": "국제 공중보건을 책임지는 유엔 전문 기구", + "value": "궁서", + "points": 1, + "category": "FontName", + "item": "문구 (세계보건기구)/② 글씨체 (궁서)" + }, + "27": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[contains(text(),'{searchValue}')]]/@CharShape]/@Height", + "searchValue": "국제 공중보건을 책임지는 유엔 전문 기구", + "value": "900", + "points": 1, + "category": "OneAnswer", + "item": "문구 (세계보건기구)/③ 크기 (9pt)" + }, + "28": { + "path": "//P[TEXT[CHAR[contains(text(), '{searchValue}')]]]//AUTONUMFORMAT/@Type", + "searchValue": "국제 공중보건을 책임지는 유엔 전문 기구", + "value": "CircledDigit", + "points": 2, + "category": "OneAnswer", + "item": "문구 (전당)/④ 각주 번호모양", + "desc": { + "가,나,다": "HangulSyllable", + "1,2,3": "Digit", + "갑,을,병": "DecagonCircle", + "A,B,C": "LatinCapital", + "a,b,c": "LatinSmall", + "①,②,③": "CircledDigit", + "一,二,三": "Ideograph", + "㉠,㉡,㉢": "CircledHangulJamo", + "ⓐ,ⓑ,ⓒ": "CircledLatinSmall", + "i,ii,iii": "RomanSmall", + "I,II,III": "RomanCapital", + "甲,乙,丙": "DecagonCircleHanja", + "+,++,+++": "UserChar", + "정답에 맞는 값 value에 입력": "" + } + }, + "29": { + "path": "boolean(//CHAR[contains(text(),'Improvement')])", + "ignoreWord": "Improvement", + "value": true, + "points": 3, + "category": "Boolean", + "item": "Improvement/영단어 미입력, 대소문자/오타 시 전체 감점", + "desc": "유사도 검사를 진행하지 않고 영단어가 모두 일치해야 하므로 xpath구문 내 단어도 수정필요" + }, + "30": { + "path": "//CHAR[contains(text(),'{kor}')][contains(text(),'{chn}')]", + "word": [ + ["영위", "營爲"], + ["소득", "所得"], + ["필수적", "必須的"], + ["창출", "創出"], + ["증진", "增進"] + ], + "value": 10, + "points": 10, + "category": "Hanja", + "item": "① 영위(營爲), ② 소득(所得), ③ 필수적(必須的), ④ 창출(創出), ⑤ 증진(增進)" + }, + "31": { + "path": "boolean(//CHAR[contains(translate(text(), ' ', ''),'계를유지')])", + "value": true, + "points": 3, + "category": "Boolean", + "item": "문구 (…사회적 고립을 예방하고 대인관계는 유지하며…)>'는' → '를' 글자바꿈" + }, + "32": { + "path": "boolean(//CHAR[contains(translate(text(), ' ', ''),'존감회복')])", + "value": true, + "points": 3, + "category": "Boolean", + "item": "문구 (…어르신들의 회복과 자존감 행복한 노후생활을…)>'회복과 / 자존감' 순서바꿈" + }, + "33": { + "path": "//TEXT[CHAR[contains(text(),'{searchValue}')]]/@CharShape", + "searchValue": "노인일자리 창출 현황(예산:십억원)", + "value": "굴림체", + "points": 1, + "category": "FontName", + "item": "제목 문구 (노인일자리 창출 현황(예산:십억원))/① 글씨체 (굴림체)" + }, + "34": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]/@Height", + "searchValue": "노인일자리 창출 현황(예산:십억원)", + "value": "1200", + "points": 1, + "category": "OneAnswer", + "item": "제목 문구 (노인일자리 창출 현황(예산:십억원))/② 크기 (1200)" + }, + "35": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]", + "searchValue": "노인일자리 창출 현황(예산:십억원)", + "value": "BOLD", + "points": 1, + "category": "FontAttribute", + "item": "제목 문구 (노인일자리 창출 현황(예산:십억원))/③ 진하게" + }, + "36": { + "path": "//PARASHAPE[@Id=//P[.//CHAR[text()='{searchValue}']]/@ParaShape]/@Align", + "searchValue": "노인일자리 창출 현황(예산:십억원)", + "value": "Center", + "points": 1, + "category": "OneAnswer", + "item": "제목 문구 (노인일자리 창출 현황(예산:십억원))/④ 정렬 (가운데 정렬)" + }, + "37": { + "path": "//BORDERFILL[@Id=//TABLE/ROW[1]/CELL/@BorderFill]/FILLBRUSH/WINDOWBRUSH/@FaceColor", + "path2": "//BORDERFILL[@Id=//CELLZONE[@StartRowAddr='0' and @EndRowAddr='0' and @StartColAddr='0' and @EndColAddr=(ancestor::TABLE[1]/@ColCount)-1]/@BorderFill]/FILLBRUSH/WINDOWBRUSH/@FaceColor", + "value": "233,215,77", + "points": 2, + "category": "Color", + "item": "위쪽 제목 셀/① 색상(RGB:233,215,77)" + }, + "38": { + "path": "//CHARSHAPE[@Id=//TABLE/ROW[1]/descendant::TEXT/@CharShape]", + "value": "BOLD", + "points": 1, + "category": "FontAttribute", + "item": "위쪽 제목 셀/② 진하게", + "desc": "글자 속성이라 CELLZONE으로 적용 되지 않음" + }, + "39": { + "path": "//BORDERFILL[@Id=//TABLE/ROW[1]/CELL/@BorderFill]/BOTTOMBORDER/@Type", + "path2": "//BORDERFILL[@Id=//CELLZONE[@StartRowAddr='0' and @EndRowAddr='0' and @StartColAddr='0' and @EndColAddr=(ancestor::TABLE[1]/@ColCount)-1]/@BorderFill]/BOTTOMBORDER/@Type", + "value": "DoubleSlim", + "points": 2, + "category": "TableAnswer", + "item": "제목 셀 아래선/① 이중실선" + }, + "40": { + "path": "//BORDERFILL[@Id=//TABLE/ROW[1]/CELL/@BorderFill]/BOTTOMBORDER/@Width", + "path2": "//BORDERFILL[@Id=//CELLZONE[@StartRowAddr='0' and @EndRowAddr='0' and @StartColAddr='0' and @EndColAddr=(ancestor::TABLE[1]/@ColCount)-1]/@BorderFill]/BOTTOMBORDER/@Width", + "value": "0.5mm", + "points": 2, + "category": "TableAnswer", + "item": "제목 셀 아래선/② 0.5mm" + }, + "41": { + "path": "//TABLE//TEXT/@CharShape", + "path2": "//FONTFACE[@Lang='Hangul']/FONT[@Id=//CHARSHAPE[@Id=//TABLE/ROW/descendant::TEXT/@CharShape]/FONTID/@Hangul]/@Name", + "value": "맑은 고딕", + "points": 1, + "category": "TableFontName", + "category_tmp": "FontName", + "item": "글자모양/① 글씨체 (맑은 고딕)", + "desc": "테이블 폰트명 문항은 테이블의 모든 셀이 정답폰트와 일치해야 함, 하나만 일치해도 정답으로 채점할 경우 category값을 FontName으로 변경" + }, + "42": { + "path": "//CHARSHAPE[@Id=//TABLE//TEXT/@CharShape]/@Height", + "value": "1000", + "points": 1, + "category": "TableAnswer", + "item": "글자모양/② 크기 (1000)" + }, + "43": { + "path": "//PARASHAPE[@Id=//TABLE/ROW//P/@ParaShape]/@Align", + "value": "Center", + "points": 1, + "category": "TableAnswer", + "item": "글자모양/③ 정렬 (가운데 정렬)" + }, + "44": { + "path": "boolean(//TABLE[1]/ROW[last()]/CELL[position()=last()]//FIELDBEGIN[starts-with(@Command, '={option}')]) and boolean(//TABLE[1]/ROW[last()]/CELL[position()=last()-1]//FIELDBEGIN[starts-with(@Command, '={option}')])", + "option": "SUM", + "value": true, + "points": 4, + "category": "Boolean", + "item": "블록 계산식/합계", + "desc": "option값에 합계는 SUM / 평균은 AVG" + }, + "45": { + "chart_xpath": "", + "chart_type": "묶은 가로 막대형", + "value": true, + "points": 2, + "category": "ChartType", + "item": "① 종류 (묶은 가로 막대형)", + "desc": "chart_type을 입력받아 차트타입에 맞는 xml요소가 있는지 내부적으로 검사, chart_type만 한글로 입력해주면 된다. (공백무시)" + }, + "46": { + "chart_xpath": "//c:valAx/c:majorTickMark/@val", + "value": "out", + "points": 2, + "category": "ChartOneAnswer", + "item": "② 값 축 주 눈금선", + "desc": "chart xml파일에서 답안을 가져오는 문항은 path키값 대신 chart_xpath키값을 이용해 xapth구문을 작성한다" + }, + "47": { + "path": "//OLE[@BinItem=//BINITEM[@Format='OLE']/@BinData]//SIZE/@Width", + "value": "80", + "points": 2, + "category": "mmSize", + "item": "③ 크기-너비 (80 mm)" + }, + "48": { + "path": "//OLE[@BinItem=//BINITEM[@Format='OLE']/@BinData]//SIZE/@Height", + "value": "90", + "points": 2, + "category": "mmSize", + "item": "④ 크기-높이 (90 mm)" + }, + "49": { + "chart_xpath": "boolean(//c:chart and not(//c:pt[not(ancestor::c:tx)]/c:v[text()='합계' or text()='평균']))", + "value": true, + "points": 2, + "category": "Boolean", + "item": "⑤ 차트 데이터(표에서 블록계산식을 제외한 나머지 값만 이용)", + "desc": "차트가 존재하고 블록계산식(합계, 평균) 데이터가 없는 경우 정답 처리" + }, + "50": { + "chart_xpath": "//a:t[text()='{searchValue}']/ancestor::a:r//a:ea/@typeface", + "searchValue": "노인 일자리 창출", + "value": "궁서체", + "points": 1, + "category": "OneAnswer", + "item": "제목 문구 (노인 일자리 창출)/① 글씨체 (궁서체)" + }, + "51": { + "chart_xpath": "//a:t[text()='{searchValue}']/ancestor::a:r/a:rPr/@sz", + "searchValue": "노인 일자리 창출", + "value": "1300", + "points": 1, + "category": "OneAnswer", + "item": "제목 문구 (노인 일자리 창출)/② 크기 (1300)" + }, + "52": { + "chart_xpath": "//a:t[text()='{searchValue}']/ancestor::a:r/a:rPr/@{option}", + "option": "b", + "searchValue": "노인 일자리 창출", + "value": "1", + "points": 1, + "category": "OneAnswer", + "item": "제목 문구 (노인 일자리 창출)/③ 기울임", + "desc": "option값 - 기울임(Italic):i / 굵게(Bold):b" + }, + "53": { + "chart_xpath": "//c:catAx/c:txPr//a:ea/@typeface", + "value": "굴림", + "points": 1, + "category": "ChartOneAnswer", + "item": "X축/① 글꼴 (굴림)" + }, + "54": { + "chart_xpath": "//c:catAx/c:txPr//a:defRPr/@sz", + "value": "900", + "points": 1, + "category": "ChartOneAnswer", + "item": "X축/② 크기 (9pt)" + }, + "55": { + "chart_xpath": "//c:catAx/c:txPr//a:defRPr/@{option}", + "option": "i", + "value": "1", + "points": 1, + "category": "ChartOneAnswer", + "item": "X축/③ 기울임", + "desc": "option값 - 기울임(Italic):i / 굵게(Bold):b" + }, + "56": { + "chart_xpath": "//c:valAx/c:txPr//a:ea/@typeface", + "value": "굴림", + "points": 1, + "category": "ChartOneAnswer", + "item": "Y축/① 글꼴 (굴림)" + }, + "57": { + "chart_xpath": "//c:valAx/c:txPr//a:defRPr/@sz", + "value": "900", + "points": 1, + "category": "ChartOneAnswer", + "item": "Y축/② 크기 (9pt)" + }, + "58": { + "chart_xpath": "//c:valAx/c:txPr//a:defRPr/@{option}", + "option": "i", + "value": "1", + "points": 1, + "category": "ChartOneAnswer", + "item": "Y축/③ 기울임", + "desc": "option값 - 기울임(Italic):i / 굵게(Bold):b" + }, + "59": { + "chart_xpath": "//c:legend//a:ea/@typeface", + "value": "굴림", + "points": 1, + "category": "OneAnswer", + "item": "범례/① 글꼴 (굴림)" + }, + "60": { + "chart_xpath": "//c:legend//a:defRPr/@sz", + "value": "900", + "points": 1, + "category": "OneAnswer", + "item": "범례/② 크기 (9pt)" + }, + "61": { + "chart_xpath": "//c:legend//a:defRPr/@{option}", + "option": "i", + "value": "1", + "points": 1, + "category": "OneAnswer", + "item": "범례/③ 기울임", + "desc": "option값 - 기울임(Italic):i / 굵게(Bold):b" + } + } +} diff --git a/회차별채점자료/2508/_DIW_2508B.json b/회차별채점자료/2508/_DIW_2508B.json new file mode 100644 index 0000000..d6109db --- /dev/null +++ b/회차별채점자료/2508/_DIW_2508B.json @@ -0,0 +1,841 @@ +{ + "0": { + "0": { + "path": "", + "path2": "", + "points": 0, + "category": "파일저장", + "item": "파일명 (수검번호.hwp/hwpx)" + }, + "1": { + "path": "//PAGEMARGIN", + "value": { + "Top": 20, + "Bottom": 20, + "Left": 20, + "Right": 20, + "Header": 10, + "Footer": 10, + "Gutter": 0 + }, + "tolerance": 1, + "points": 4, + "category": "PageSetting", + "item": "A4용지, 왼쪽/오른쪽/위쪽/아래쪽 (각20mm), 머리말/꼬리말 (10mm), 제본(0mm)" + }, + "2": { + "path": "", + "value": { + "FontName": "바탕", + "FontSize": "1000", + "Alignment": "Justify", + "LineSpacing": "160" + }, + "points": 4, + "category": "BasicSetting", + "item": "글꼴 (바탕, 10pt), 양쪽정렬, 줄간격 (160%)" + }, + "3": { + "path": "", + "value": null, + "points": 40, + "category": "오타감점", + "item": "오타 1개 -1점 / 2503회부터 오타 1개 -1점으로 변경" + } + }, + "1": { + "1": { + "path": "//TEXTART[@Text='{searchValue}']/TEXTARTSHAPE/@FontName", + "searchValue": "기능경진대회참가안내", + "value": "돋움체", + "points": 1, + "category": "OneAnswer", + "item": "문구 (기능경진대회참가안내)/① 글씨체 (돋움체)" + }, + "2": { + "path": "//TEXTART[@Text='{searchValue}']/descendant::WINDOWBRUSH/@FaceColor", + "searchValue": "기능경진대회참가안내", + "value": "84,139,241", + "points": 2, + "category": "Color", + "item": "문구 (기능경진대회참가안내)/② 채우기 : 색상(RGB:84,139,241)" + }, + "3": { + "path": "//TEXTART[@Text='{searchValue}']/SHAPEOBJECT/SIZE/@Width", + "searchValue": "기능경진대회참가안내", + "value": "120", + "tolerance": 1, + "points": 2, + "category": "mmSize", + "item": "문구 (기능경진대회참가안내)/③ 크기-너비 (120 mm)" + }, + "4": { + "path": "//TEXTART[@Text='{searchValue}']/SHAPEOBJECT/SIZE/@Height", + "searchValue": "기능경진대회참가안내", + "value": "20", + "tolerance": 1, + "points": 2, + "category": "mmSize", + "item": "문구 (기능경진대회참가안내)/④ 크기-높이 (20 mm)" + }, + "5": { + "path": "//TEXTART[@Text='{searchValue}']/SHAPEOBJECT/POSITION/@TreatAsChar", + "searchValue": "기능경진대회참가안내", + "value": "true", + "points": 2, + "category": "OneAnswer", + "item": "문구 (기능경진대회참가안내)/⑤ 위치 (글자처럼 취급)" + }, + "6": { + "path": "//PARASHAPE[@Id=//P[.//TEXTART[@Text='{searchValue}']]/@ParaShape]/@Align", + "searchValue": "기능경진대회참가안내", + "value": "Center", + "points": 2, + "category": "OneAnswer", + "item": "문구 (기능경진대회참가안내)/⑥ 정렬 (가운데 정렬)" + }, + "7": { + "path": "//TEXTART[@Text='{searchValue}']", + "searchValue": "기능경진대회참가안내", + "value": true, + "points": 2, + "category": "Boolean", + "item": "문구 (기능경진대회참가안내)/⑦ 글맵시모양 (육안확인)" + }, + "8": { + "path": "//RECTANGLE[.//CHAR[text()='{searchValue}']]/SHAPEOBJECT/SIZE", + "searchValue": "2", + "value": { + "Height": 2800, + "Width": 2800 + }, + "tolerance": 200, + "points": 1, + "category": "TwoLineSize", + "item": "2/① 모양 (2줄)" + }, + "9": { + "path": "//TEXT[CHAR[text()='{searchValue}']]/@CharShape", + "searchValue": "2", + "value": "맑은 고딕", + "points": 1, + "category": "FontName", + "item": "2/② 글씨체 (맑은 고딕)" + }, + "10": { + "path": "//RECTANGLE[.//CHAR[text()='{searchValue}']]//WINDOWBRUSH/@FaceColor", + "searchValue": "2", + "value": "240,223,102", + "points": 2, + "category": "Color", + "item": "2/③ 면색 : 색상(RGB:240,223,102)" + }, + "11": { + "path": "//RECTANGLE[.//CHAR[text()='{searchValue}']]//OUTSIDEMARGIN/@Right", + "searchValue": "2", + "value": "3.0", + "tolerance": 1, + "points": 2, + "category": "mmSize", + "item": "2/④ 본문과의 간격 : 3.0mm" + }, + "12": { + "path": "//CHARSHAPE[@Id=//CHAR[contains(text(),'{searchValue}')]/parent::TEXT/@CharShape]", + "searchValue": "지역사회의 기능 수준 향상과 기술 및 기능 개발 촉진", + "value": "BOLD", + "points": 2, + "category": "FontAttribute", + "item": "문구 (지역사회의 기능 수준 향상과 기술 및 기능 개발 촉진)/① BOLD" + }, + "13": { + "path": "//CHARSHAPE[@Id=//CHAR[contains(text(),'{searchValue}')]/parent::TEXT/@CharShape]", + "searchValue": "지역사회의 기능 수준 향상과 기술 및 기능 개발 촉진", + "value": "UNDERLINE", + "points": 2, + "category": "FontAttribute", + "item": "문구 (지역사회의 기능 수준 향상과 기술 및 기능 개발 촉진)/② UNDERLINE" + }, + "14": { + "path": "//CHAR[contains(string(.),'{char1}')]/text()", + "path2": "//CHAR[contains(string(.),'{char2}')]/text()", + "path3": "//CHAR[contains(string(.),'{char3}')]/text()", + "char1": "▶", + "char2": "◀", + "char3": "※", + "value": 3, + "points": 3, + "category": "SpecialChar", + "item": "① ▶, ② ◀, ③ ※" + }, + "15": { + "path": "//CHAR[contains(text(),'{searchValue}')]/parent::TEXT/@CharShape", + "searchValue": "접수안내", + "value": "굴림", + "points": 1, + "category": "FontName", + "item": "문구 (▶ 접수안내 ◀)/① 글씨체 (굴림)" + }, + "16": { + "path": "//PARASHAPE[@Id=//CHAR[contains(text(),'{match_str}')]/ancestor::P/@ParaShape]/@Align", + "match_str": "접수안내", + "value": "Center", + "points": 1, + "category": "Align", + "item": "문구 (▶ 접수안내 ◀)/② 정렬 (가운데 정렬)" + }, + "17": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]", + "hyperlink_ptag": "//P[.//FIELDBEGIN[@Type='Hyperlink']]", + "searchValue": "누구나 참가 가능", + "value": "BOLD", + "points": 1, + "category": "FontAttribute", + "item": "문구 (누구나 참가 가능)/① BOLD" + }, + "18": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]", + "hyperlink_ptag": "//P[.//FIELDBEGIN[@Type='Hyperlink']]", + "searchValue": "누구나 참가 가능", + "value": "ITALIC", + "points": 1, + "category": "FontAttribute", + "item": "문구 (누구나 참가 가능)/② ITALIC" + }, + "19": { + "path": "//PARASHAPE[@Id=//CHAR[contains(text(),'{searchValue}')]/ancestor::P/following-sibling::P[1]/@ParaShape]/PARAMARGIN", + "searchValue": "기타사항", + "value": { + "Left": 15, + "Indent": 12 + }, + "points": 2, + "category": "ParaShape", + "item": "문구 (※ 기타… 이하 문단)/왼쪽여백 (15pt), 내어쓰기 (12pt)", + "desc": "내부적으로 내어쓰기는 음수값 / JSON value값은 양수로 입력" + }, + "20": { + "path": "//CHARSHAPE[@Id=//CHAR[contains(text(),'{searchValue}')]/parent::TEXT/@CharShape]/@Height", + "searchValue": "2025. 08. 23.", + "value": "1300", + "points": 1, + "category": "OneAnswer", + "item": "문구 (2025. 08. 23.)/① 크기 (1300)", + "desc": "1pt당 100" + }, + "21": { + "path": "//PARASHAPE[@Id=//CHAR[contains(text(),'{searchValue}')]/ancestor::P/@ParaShape]/@Align", + "searchValue": "2025. 08. 23.", + "value": "Center", + "points": 1, + "category": "OneAnswer", + "item": "문구 (2025. 08. 23.)/② 정렬 (가운데 정렬)" + }, + "22": { + "path": "//TEXT[CHAR[text()='{searchValue}']]/@CharShape", + "searchValue": "기능경진대회운영위원회", + "value": "궁서", + "points": 1, + "category": "FontName", + "item": "문구 (기능경진대회운영위원회)/① 글씨체 (궁서)" + }, + "23": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]/@Height", + "searchValue": "기능경진대회운영위원회", + "value": "2400", + "points": 1, + "category": "OneAnswer", + "item": "문구 (기능경진대회운영위원회)/② 크기 (2400)" + }, + "24": { + "path": "//PARASHAPE[@Id=//CHAR[text()='{searchValue}']/ancestor::P/@ParaShape]/@Align", + "searchValue": "기능경진대회운영위원회", + "value": "Center", + "points": 1, + "category": "OneAnswer", + "item": "문구 (기능경진대회운영위원회)/③ 정렬 (가운데 정렬)" + }, + "25": { + "path": "//SECTION[1]//TEXT[CHAR[text()='{searchValue}']]/@CharShape", + "searchValue": "DIAT", + "value": "굴림", + "points": 1, + "category": "FontName", + "item": "문구 (DIAT)/① 글꼴 (굴림)" + }, + "26": { + "path": "//CHARSHAPE[@Id=//SECTION[1]//TEXT[CHAR[text()='{searchValue}']]/@CharShape]/@Height", + "searchValue": "DIAT", + "value": "900", + "points": 1, + "category": "OneAnswer", + "item": "문구 (DIAT)/② 크기 (9pt)" + }, + "27": { + "path": "//PARASHAPE[@Id=//SECTION[1]//CHAR[text()='{searchValue}']/parent::TEXT/parent::P/@ParaShape]/@Align", + "searchValue": "DIAT", + "value": "Right", + "points": 1, + "category": "OneAnswer", + "item": "문구 (DIAT)/③ 정렬 (오른쪽 정렬)" + }, + "28": { + "path": "//PAGENUM/@FormatType", + "value": "HangulSyllable", + "points": 2, + "category": "PageNumber", + "item": "① 쪽 번호 매기기 (가,나,다 순으로)", + "desc1": { + "가,나,다": "HangulSyllable", + "1,2,3": "Digit", + "갑,을,병": "DecagonCircle", + "A,B,C": "LatinCapital", + "a,b,c": "LatinSmall", + "①,②,③": "CircledDigit", + "一,二,三": "Ideograph", + "㉠,㉡,㉢": "CircledHangulJamo", + "ⓐ,ⓑ,ⓒ": "CircledLatinSmall", + "i,ii,iii": "RomanSmall", + "I,II,III": "RomanCapital", + "desc": "정답에 맞는 값 value에 입력" + }, + "desc2": "1, 2페이지 모두 정답이어야 점수 부여" + }, + "29": { + "path": "//PAGENUM/@Pos", + "value": "BottomCenter", + "points": 2, + "category": "PageNumber", + "item": "가운데 아래", + "desc": "1, 2페이지 모두 정답이어야 점수 부여", + "desc2": { + "가운데 아래": "BottomCenter", + "오른쪽 아래": "BottomRight" + } + }, + "30": { + "path": "//PARASHAPE[@Id='{parashape_id}']/PARAMARGIN/@LineSpacing", + "value": "190", + "first_word": "2", + "points": 2, + "category": "LineSpacing", + "item": "문제 1 줄간격 190% 설정", + "desc": "1페이지 문단의 줄간격이 정답이 아닌 문단이 있으면 False(감점), first_word 속성에 [문단 첫글자 장식]에 해당하는 글자를 입력해준다." + } + }, + "2": { + "1": { + "path": "//PAGEBORDERFILL[@Type='Both' or @Type='Even']/@HeaderInside", + "path2": "//BORDERFILL[@Id=//PAGEBORDERFILL[@Type='Both' or @Type='Even']/@BorferFill]", + "value": { + "header_inside": true, + "all_double_slim": true + }, + "points": 4, + "category": "PageBorder", + "item": "문제2 쪽테두리(이중 실선, 머리말 포함) 설정" + }, + "2": { + "path": "count(//SECTION)>1", + "value": true, + "points": 3, + "category": "Boolean", + "item": "① 구역나누기", + "desc": "섹션이 1개 이상이면 점수부여" + }, + "3": { + "path": "TEXT/COLDEF/@Count", + "value": "2", + "points": 3, + "category": "TwoColumn", + "item": "② 다단 2단" + }, + "4": { + "path": "//RECTANGLE//CHAR[text()='{searchValue}']/ancestor::RECTANGLE/SHAPEOBJECT/SIZE/@Width", + "searchValue": "기능경진대회", + "value": "60", + "points": 2, + "category": "mmSize", + "item": "문구 (기능경진대회)/① 크기-너비 (60 mm)" + }, + "5": { + "path": "//RECTANGLE//CHAR[text()='{searchValue}']/ancestor::RECTANGLE/SHAPEOBJECT/SIZE/@Height", + "searchValue": "기능경진대회", + "value": "12", + "points": 2, + "category": "mmSize", + "item": "문구 (기능경진대회)/② 크기-높이 (12 mm)" + }, + "6": { + "path": "//RECTANGLE[.//CHAR[text()='{searchValue}']]//LINESHAPE", + "searchValue": "기능경진대회", + "value": { + "Style": "DoubleSlim", + "Width": "283" + }, + "points": 2, + "category": "LineShape", + "item": "문구 (기능경진대회)/③ 테두리 : 이중 실선(1.00mm)", + "desc": "1mm = 283pt value['Width']에 pt값 입력" + }, + "7": { + "path": "//RECTANGLE[.//CHAR[text()='{searchValue}']]/@Ratio", + "searchValue": "기능경진대회", + "value": "50", + "points": 2, + "category": "OneAnswer", + "item": "문구 (기능경진대회)/④ 글상자 모서리 (반원)", + "desc": "모서리 비율 반원:50 / 둥근모양:20" + }, + "8": { + "path": "//RECTANGLE[.//CHAR[text()='{searchValue}']]//WINDOWBRUSH/@FaceColor", + "searchValue": "기능경진대회", + "value": "202,86,167", + "points": 2, + "category": "Color", + "item": "문구 (기능경진대회)/⑤ 채우기 : 색상(RGB:202,86,167)" + }, + "9": { + "path": "//RECTANGLE[.//CHAR[text()='{searchValue}']]/SHAPEOBJECT/POSITION/@TreatAsChar", + "searchValue": "기능경진대회", + "value": "true", + "points": 1, + "category": "OneAnswer", + "item": "문구 (기능경진대회)/⑥ 글상자 위치 (글자처럼 취급)" + }, + "10": { + "path": "//PARASHAPE[@Id=//RECTANGLE//CHAR[text()='{searchValue}']/ancestor::P[last()]/@ParaShape]/@Align", + "searchValue": "기능경진대회", + "value": "Center", + "points": 1, + "category": "OneAnswer", + "item": "문구 (기능경진대회)/⑦ 글상자 정렬 (가운데 정렬)" + }, + "11": { + "path": "//TEXT[CHAR[text()='{searchValue}']]/@CharShape", + "searchValue": "기능경진대회", + "value": "견고딕", + "points": 1, + "category": "FontName", + "item": "문구 (기능경진대회)/⑧ 글씨체 (견고딕)" + }, + "12": { + "path": "//CHARSHAPE[@Id=//RECTANGLE//TEXT[./CHAR[text()='{searchValue}']]/@CharShape]/@Height", + "searchValue": "기능경진대회", + "value": "2200", + "points": 1, + "category": "OneAnswer", + "item": "문구 (기능경진대회)/⑨ 글씨크기 (2200)", + "desc": "1pt당 100" + }, + "13": { + "path": "//PARASHAPE[@Id=//RECTANGLE//P[.//CHAR[text()='{searchValue}']]/@ParaShape]/@Align", + "searchValue": "기능경진대회", + "value": "Center", + "points": 1, + "category": "OneAnswer", + "item": "문구 (기능경진대회)/⑩ 정렬 (가운데 정렬)" + }, + "14": { + "path": "//BINITEM[@BinData=//PICTURE/IMAGE/@BinItem][@Format='JPG' or @Format='JPEG']", + "value": true, + "points": 2, + "category": "Boolean", + "item": "① 파일명 \"그림B.jpg\" 삽입", + "desc": "첨부 이미지 파일명 손상으로 정상적인 채점이 불가한 경우가 발견되어서 이미지 첨부 여부로 채점 방식 변경 (7/3)" + }, + "15": { + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/SIZE/@Width", + "value": "85", + "points": 2, + "category": "mmSize", + "item": "② 크기-너비 (85 mm)" + }, + "16": { + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/SIZE/@Height", + "value": "40", + "points": 2, + "category": "mmSize", + "item": "③ 크기-높이 (40 mm)" + }, + "17": { + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@HorzOffset", + "value": "0", + "points": 2, + "category": "mmSize", + "item": "④ 위치 (어울림 : 가로-쪽의 왼쪽 0.0mm)" + }, + "18": { + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@VertOffset", + "value": "22", + "points": 2, + "category": "mmSize", + "item": "⑤ 위치 (어울림 : 세로-쪽의 위 22 mm)" + }, + "19": { + "path": "//TEXT[CHAR[text()='{searchValue}']]/@CharShape", + "searchValue": "1. 대회목적", + "value": "돋움", + "points": 1, + "category": "FontName", + "item": "문구① (1. 대회목적)/① 글씨체 (돋움)" + }, + "20": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]/@Height", + "searchValue": "1. 대회목적", + "value": "1200", + "points": 1, + "category": "OneAnswer", + "item": "문구① (1. 대회목적)/② 크기 (12pt)" + }, + "21": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]", + "searchValue": "1. 대회목적", + "value": "BOLD", + "points": 1, + "category": "FontAttribute", + "item": "문구① (1. 대회목적)/③ 진하게" + }, + "22": { + "path": "//TEXT[CHAR[text()='{searchValue}']]/@CharShape", + "searchValue": "2. 기능경진대회 종목", + "value": "돋움", + "points": 1, + "category": "FontName", + "item": "문구② (2. 기능경진대회 종목)/① 글씨체 (돋움)" + }, + "23": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]/@Height", + "searchValue": "2. 기능경진대회 종목", + "value": "1200", + "points": 1, + "category": "OneAnswer", + "item": "문구② (2. 기능경진대회 종목)/② 크기 (1200)" + }, + "24": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]", + "searchValue": "2. 기능경진대회 종목", + "value": "BOLD", + "points": 1, + "category": "FontAttribute", + "item": "문구② (2. 기능경진대회 종목)/③ 진하게" + }, + "25": { + "path": "boolean(//TEXT[CHAR[contains(text(),'{option}')]]/FOOTNOTE)", + "path2": "boolean(//CHAR[substring(., string-length(.) - string-length('{option}') + 1) = '{option}']/following-sibling::FOOTNOTE/descendant::CHAR)", + "option": "벽체", + "value": true, + "points": 2, + "category": "Boolean", + "item": "문구 (벽체)/① 각주 설정 및 문구 입력" + }, + "26": { + "path": "//CHAR[contains(text(),'{searchValue}')]/parent::TEXT/@CharShape", + "searchValue": "건물의 벽을 이루는 구조 부분", + "value": "돋움", + "points": 1, + "category": "FontName", + "item": "문구 (벽체)/② 글씨체 (돋움)" + }, + "27": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[contains(text(),'{searchValue}')]]/@CharShape]/@Height", + "searchValue": "건물의 벽을 이루는 구조 부분", + "value": "900", + "points": 1, + "category": "OneAnswer", + "item": "문구 (벽체)/③ 크기 (9pt)" + }, + "28": { + "path": "//P[TEXT[CHAR[contains(text(), '{searchValue}')]]]//AUTONUMFORMAT/@Type", + "searchValue": "건물의 벽을 이루는 구조 부분", + "value": "CircledLatinCapital", + "points": 2, + "category": "OneAnswer", + "item": "문구 (전당)/④ 각주 번호모양", + "desc": { + "가,나,다": "HangulSyllable", + "1,2,3": "Digit", + "갑,을,병": "DecagonCircle", + "A,B,C": "LatinCapital", + "a,b,c": "LatinSmall", + "①,②,③": "CircledDigit", + "一,二,三": "Ideograph", + "㉠,㉡,㉢": "CircledHangulJamo", + "Ⓐ,Ⓑ,Ⓒ": "CircledLatinCapital", + "ⓐ,ⓑ,ⓒ": "CircledLatinSmall", + "i,ii,iii": "RomanSmall", + "I,II,III": "RomanCapital", + "甲,乙,丙": "DecagonCircleHanja", + "+,++,+++": "UserChar", + "정답에 맞는 값 value에 입력": "" + } + }, + "29": { + "path": "boolean(//CHAR[contains(text(),'Interior')])", + "ignoreWord": "Interior", + "value": true, + "points": 3, + "category": "Boolean", + "item": "Interior/영단어 미입력, 대소문자/오타 시 전체 감점", + "desc": "유사도 검사를 진행하지 않고 영단어가 모두 일치해야 하므로 xpath구문 내 단어도 수정필요" + }, + "30": { + "path": "//CHAR[contains(text(),'{kor}')][contains(text(),'{chn}')]", + "word": [ + ["우대", "優待"], + ["저변", "底邊"], + ["분야", "分野"], + ["조리", "調理"], + ["역할", "役割"] + ], + "value": 10, + "points": 10, + "category": "Hanja", + "item": "① 우대(優待), ② 저변(底邊), ③ 분야(分野), ④조리(調理), ⑤ 역할(役割)" + }, + "31": { + "path": "boolean(//CHAR[contains(translate(text(), ' ', ''),'적인실력')])", + "value": true, + "points": 3, + "category": "Boolean", + "item": "문구 (…기술에 대한 실력을 전문적인 평가하는 대회이다.…)>'실력을 / 전문적인' 순서바꿈" + }, + "32": { + "path": "boolean(//CHAR[contains(translate(text(), ' ', ''),'준의상향')])", + "value": true, + "points": 3, + "category": "Boolean", + "item": "문구 (…기술 수준의 하향평준화를 도모하고.…)>'하' → '상' 글자바꿈" + }, + "33": { + "path": "//TEXT[CHAR[contains(text(),'{searchValue}')]]/@CharShape", + "searchValue": "지역별 대회 참가자 현황", + "value": "굴림체", + "points": 1, + "category": "FontName", + "item": "제목 문구 (지역별 대회 참가자 현황)/① 글씨체 (굴림체)" + }, + "34": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]/@Height", + "searchValue": "지역별 대회 참가자 현황", + "value": "1200", + "points": 1, + "category": "OneAnswer", + "item": "제목 문구 (지역별 대회 참가자 현황)/② 크기 (1200)" + }, + "35": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]", + "searchValue": "지역별 대회 참가자 현황", + "value": "BOLD", + "points": 1, + "category": "FontAttribute", + "item": "제목 문구 (지역별 대회 참가자 현황)/③ 진하게" + }, + "36": { + "path": "//PARASHAPE[@Id=//P[.//CHAR[text()='{searchValue}']]/@ParaShape]/@Align", + "searchValue": "지역별 대회 참가자 현황", + "value": "Center", + "points": 1, + "category": "OneAnswer", + "item": "제목 문구 (지역별 대회 참가자 현황)/④ 정렬 (가운데 정렬)" + }, + "37": { + "path": "//BORDERFILL[@Id=//TABLE/ROW[1]/CELL/@BorderFill]/FILLBRUSH/WINDOWBRUSH/@FaceColor", + "path2": "//BORDERFILL[@Id=//CELLZONE[@StartRowAddr='0' and @EndRowAddr='0' and @StartColAddr='0' and @EndColAddr=(ancestor::TABLE[1]/@ColCount)-1]/@BorderFill]/FILLBRUSH/WINDOWBRUSH/@FaceColor", + "value": "144,210,67", + "points": 2, + "category": "Color", + "item": "위쪽 제목 셀/① 색상(RGB:144,210,67)" + }, + "38": { + "path": "//CHARSHAPE[@Id=//TABLE/ROW[1]/descendant::TEXT/@CharShape]", + "value": "BOLD", + "points": 1, + "category": "FontAttribute", + "item": "위쪽 제목 셀/② 진하게", + "desc": "글자 속성이라 CELLZONE으로 적용 되지 않음" + }, + "39": { + "path": "//BORDERFILL[@Id=//TABLE/ROW[1]/CELL/@BorderFill]/BOTTOMBORDER/@Type", + "path2": "//BORDERFILL[@Id=//CELLZONE[@StartRowAddr='0' and @EndRowAddr='0' and @StartColAddr='0' and @EndColAddr=(ancestor::TABLE[1]/@ColCount)-1]/@BorderFill]/BOTTOMBORDER/@Type", + "value": "DoubleSlim", + "points": 2, + "category": "TableAnswer", + "item": "제목 셀 아래선/① 이중실선" + }, + "40": { + "path": "//BORDERFILL[@Id=//TABLE/ROW[1]/CELL/@BorderFill]/BOTTOMBORDER/@Width", + "path2": "//BORDERFILL[@Id=//CELLZONE[@StartRowAddr='0' and @EndRowAddr='0' and @StartColAddr='0' and @EndColAddr=(ancestor::TABLE[1]/@ColCount)-1]/@BorderFill]/BOTTOMBORDER/@Width", + "value": "0.5mm", + "points": 2, + "category": "TableAnswer", + "item": "제목 셀 아래선/② 0.5mm" + }, + "41": { + "path": "//TABLE//TEXT/@CharShape", + "path2": "//FONTFACE[@Lang='Hangul']/FONT[@Id=//CHARSHAPE[@Id=//TABLE/ROW/descendant::TEXT/@CharShape]/FONTID/@Hangul]/@Name", + "value": "중고딕", + "points": 1, + "category": "TableFontName", + "category_tmp": "FontName", + "item": "글자모양/① 글씨체 (중고딕)", + "desc": "테이블 폰트명 문항은 테이블의 모든 셀이 정답폰트와 일치해야 함, 하나만 일치해도 정답으로 채점할 경우 category값을 FontName으로 변경" + }, + "42": { + "path": "//CHARSHAPE[@Id=//TABLE//TEXT/@CharShape]/@Height", + "value": "1000", + "points": 1, + "category": "TableAnswer", + "item": "글자모양/② 크기 (1000)" + }, + "43": { + "path": "//PARASHAPE[@Id=//TABLE/ROW//P/@ParaShape]/@Align", + "value": "Center", + "points": 1, + "category": "TableAnswer", + "item": "글자모양/③ 정렬 (가운데 정렬)" + }, + "44": { + "path": "boolean(//TABLE[1]/ROW[last()]/CELL[position()=last()]//FIELDBEGIN[starts-with(@Command, '={option}')]) and boolean(//TABLE[1]/ROW[last()]/CELL[position()=last()-1]//FIELDBEGIN[starts-with(@Command, '={option}')])", + "option": "SUM", + "value": true, + "points": 4, + "category": "Boolean", + "item": "블록 계산식/합계", + "desc": "option값에 합계는 SUM / 평균은 AVG" + }, + "45": { + "chart_xpath": "", + "chart_type": "꺾은선형", + "value": true, + "points": 2, + "category": "ChartType", + "item": "① 종류 (꺾은선형)", + "desc": "chart_type을 입력받아 차트타입에 맞는 xml요소가 있는지 내부적으로 검사, chart_type만 한글로 입력해주면 된다. (공백무시)" + }, + "46": { + "chart_xpath": "//c:valAx/c:majorTickMark/@val", + "value": "out", + "points": 2, + "category": "ChartOneAnswer", + "item": "② 값 축 주 눈금선", + "desc": "chart xml파일에서 답안을 가져오는 문항은 path키값 대신 chart_xpath키값을 이용해 xapth구문을 작성한다" + }, + "47": { + "path": "//OLE[@BinItem=//BINITEM[@Format='OLE']/@BinData]//SIZE/@Width", + "value": "80", + "points": 2, + "category": "mmSize", + "item": "③ 크기-너비 (80 mm)" + }, + "48": { + "path": "//OLE[@BinItem=//BINITEM[@Format='OLE']/@BinData]//SIZE/@Height", + "value": "90", + "points": 2, + "category": "mmSize", + "item": "④ 크기-높이 (90 mm)" + }, + "49": { + "chart_xpath": "boolean(//c:chart and not(//c:pt[not(ancestor::c:tx)]/c:v[text()='합계' or text()='평균']))", + "value": true, + "points": 2, + "category": "Boolean", + "item": "⑤ 차트 데이터(표에서 블록계산식을 제외한 나머지 값만 이용)", + "desc": "차트가 존재하고 블록계산식(합계, 평균) 데이터가 없는 경우 정답 처리" + }, + "50": { + "chart_xpath": "//a:t[text()='{searchValue}']/ancestor::a:r//a:ea/@typeface", + "searchValue": "지역별 대회 참가자 현황", + "value": "궁서체", + "points": 1, + "category": "OneAnswer", + "item": "제목 문구 (지역별 대회 참가자 현황)/① 글씨체 (궁서체)" + }, + "51": { + "chart_xpath": "//a:t[text()='{searchValue}']/ancestor::a:r/a:rPr/@sz", + "searchValue": "지역별 대회 참가자 현황", + "value": "1300", + "points": 1, + "category": "OneAnswer", + "item": "제목 문구 (지역별 대회 참가자 현황)/② 크기 (1300)" + }, + "52": { + "chart_xpath": "//a:t[text()='{searchValue}']/ancestor::a:r/a:rPr/@{option}", + "option": "b", + "searchValue": "지역별 대회 참가자 현황", + "value": "1", + "points": 1, + "category": "OneAnswer", + "item": "제목 문구 (지역별 대회 참가자 현황)/③ 기울임", + "desc": "option값 - 기울임(Italic):i / 굵게(Bold):b" + }, + "53": { + "chart_xpath": "//c:catAx/c:txPr//a:ea/@typeface", + "value": "돋움체", + "points": 1, + "category": "ChartOneAnswer", + "item": "X축/① 글꼴 (돋움체)" + }, + "54": { + "chart_xpath": "//c:catAx/c:txPr//a:defRPr/@sz", + "value": "900", + "points": 1, + "category": "ChartOneAnswer", + "item": "X축/② 크기 (9pt)" + }, + "55": { + "chart_xpath": "//c:catAx/c:txPr//a:defRPr/@{option}", + "option": "i", + "value": "1", + "points": 1, + "category": "ChartOneAnswer", + "item": "X축/③ 기울임", + "desc": "option값 - 기울임(Italic):i / 굵게(Bold):b" + }, + "56": { + "chart_xpath": "//c:valAx/c:txPr//a:ea/@typeface", + "value": "돋움체", + "points": 1, + "category": "ChartOneAnswer", + "item": "Y축/① 글꼴 (돋움체)" + }, + "57": { + "chart_xpath": "//c:valAx/c:txPr//a:defRPr/@sz", + "value": "900", + "points": 1, + "category": "ChartOneAnswer", + "item": "Y축/② 크기 (9pt)" + }, + "58": { + "chart_xpath": "//c:valAx/c:txPr//a:defRPr/@{option}", + "option": "i", + "value": "1", + "points": 1, + "category": "ChartOneAnswer", + "item": "Y축/③ 기울임", + "desc": "option값 - 기울임(Italic):i / 굵게(Bold):b" + }, + "59": { + "chart_xpath": "//c:legend//a:ea/@typeface", + "value": "돋움체", + "points": 1, + "category": "OneAnswer", + "item": "범례/① 글꼴 (돋움체)" + }, + "60": { + "chart_xpath": "//c:legend//a:defRPr/@sz", + "value": "900", + "points": 1, + "category": "OneAnswer", + "item": "범례/② 크기 (9pt)" + }, + "61": { + "chart_xpath": "//c:legend//a:defRPr/@{option}", + "option": "i", + "value": "1", + "points": 1, + "category": "OneAnswer", + "item": "범례/③ 기울임", + "desc": "option값 - 기울임(Italic):i / 굵게(Bold):b" + } + } +} diff --git a/회차별채점자료/2508/_DIW_2508C.json b/회차별채점자료/2508/_DIW_2508C.json new file mode 100644 index 0000000..4be4d45 --- /dev/null +++ b/회차별채점자료/2508/_DIW_2508C.json @@ -0,0 +1,840 @@ +{ + "0": { + "0": { + "path": "", + "path2": "", + "points": 0, + "category": "파일저장", + "item": "파일명 (수검번호.hwp/hwpx)" + }, + "1": { + "path": "//PAGEMARGIN", + "value": { + "Top": 20, + "Bottom": 20, + "Left": 20, + "Right": 20, + "Header": 10, + "Footer": 10, + "Gutter": 0 + }, + "tolerance": 1, + "points": 4, + "category": "PageSetting", + "item": "A4용지, 왼쪽/오른쪽/위쪽/아래쪽 (각20mm), 머리말/꼬리말 (10mm), 제본(0mm)" + }, + "2": { + "path": "", + "value": { + "FontName": "바탕", + "FontSize": "1000", + "Alignment": "Justify", + "LineSpacing": "160" + }, + "points": 4, + "category": "BasicSetting", + "item": "글꼴 (바탕, 10pt), 양쪽정렬, 줄간격 (160%)" + }, + "3": { + "path": "", + "value": null, + "points": 40, + "category": "오타감점", + "item": "오타 1개 -1점 / 2503회부터 오타 1개 -1점으로 변경" + } + }, + "1": { + "1": { + "path": "//TEXTART[@Text='{searchValue}']/TEXTARTSHAPE/@FontName", + "searchValue": "치아건강특별강연회", + "value": "굴림", + "points": 1, + "category": "OneAnswer", + "item": "문구 (치아건강특별강연회)/① 글씨체 (굴림)" + }, + "2": { + "path": "//TEXTART[@Text='{searchValue}']/descendant::WINDOWBRUSH/@FaceColor", + "searchValue": "치아건강특별강연회", + "value": "183,29,167", + "points": 2, + "category": "Color", + "item": "문구 (치아건강특별강연회)/② 채우기 : 색상(RGB:183,29,167)" + }, + "3": { + "path": "//TEXTART[@Text='{searchValue}']/SHAPEOBJECT/SIZE/@Width", + "searchValue": "치아건강특별강연회", + "value": "125", + "tolerance": 1, + "points": 2, + "category": "mmSize", + "item": "문구 (치아건강특별강연회)/③ 크기-너비 (125 mm)" + }, + "4": { + "path": "//TEXTART[@Text='{searchValue}']/SHAPEOBJECT/SIZE/@Height", + "searchValue": "치아건강특별강연회", + "value": "20", + "tolerance": 1, + "points": 2, + "category": "mmSize", + "item": "문구 (치아건강특별강연회)/④ 크기-높이 (20 mm)" + }, + "5": { + "path": "//TEXTART[@Text='{searchValue}']/SHAPEOBJECT/POSITION/@TreatAsChar", + "searchValue": "치아건강특별강연회", + "value": "true", + "points": 2, + "category": "OneAnswer", + "item": "문구 (치아건강특별강연회)/⑤ 위치 (글자처럼 취급)" + }, + "6": { + "path": "//PARASHAPE[@Id=//P[.//TEXTART[@Text='{searchValue}']]/@ParaShape]/@Align", + "searchValue": "치아건강특별강연회", + "value": "Center", + "points": 2, + "category": "OneAnswer", + "item": "문구 (치아건강특별강연회)/⑥ 정렬 (가운데 정렬)" + }, + "7": { + "path": "//TEXTART[@Text='{searchValue}']", + "searchValue": "치아건강특별강연회", + "value": true, + "points": 2, + "category": "Boolean", + "item": "문구 (치아건강특별강연회)/⑦ 글맵시모양 (육안확인)" + }, + "8": { + "path": "//RECTANGLE[.//CHAR[text()='{searchValue}']]/SHAPEOBJECT/SIZE", + "searchValue": "현", + "value": { + "Height": 2800, + "Width": 2800 + }, + "tolerance": 200, + "points": 1, + "category": "TwoLineSize", + "item": "현/① 모양 (2줄)" + }, + "9": { + "path": "//TEXT[CHAR[text()='{searchValue}']]/@CharShape", + "searchValue": "현", + "value": "돋움체", + "points": 1, + "category": "FontName", + "item": "현/② 글씨체 (돋움체)" + }, + "10": { + "path": "//RECTANGLE[.//CHAR[text()='{searchValue}']]//WINDOWBRUSH/@FaceColor", + "searchValue": "현", + "value": "149,180,174", + "points": 2, + "category": "Color", + "item": "현/③ 면색 : 색상(RGB:149,180,174)" + }, + "11": { + "path": "//RECTANGLE[.//CHAR[text()='{searchValue}']]//OUTSIDEMARGIN/@Right", + "searchValue": "현", + "value": "3.0", + "tolerance": 1, + "points": 2, + "category": "mmSize", + "item": "현/④ 본문과의 간격 : 3.0mm" + }, + "12": { + "path": "//CHARSHAPE[@Id=//CHAR[contains(text(),'{searchValue}')]/parent::TEXT/@CharShape]", + "searchValue": "평생 건강한 치아를 유지하기", + "value": "BOLD", + "points": 2, + "category": "FontAttribute", + "item": "문구 (평생 건강한 치아를 유지하기)/① BOLD" + }, + "13": { + "path": "//CHARSHAPE[@Id=//CHAR[contains(text(),'{searchValue}')]/parent::TEXT/@CharShape]", + "searchValue": "평생 건강한 치아를 유지하기", + "value": "ITALIC", + "points": 2, + "category": "FontAttribute", + "item": "문구 (평생 건강한 치아를 유지하기)/② ITALIC" + }, + "14": { + "path": "//CHAR[contains(string(.),'{char1}')]/text()", + "path2": "//CHAR[contains(string(.),'{char2}')]/text()", + "path3": "//CHAR[contains(string(.),'{char3}')]/text()", + "char1": "◎", + "char2": "◎", + "char3": "※", + "value": 3, + "points": 3, + "category": "SpecialChar", + "item": "① ◎ , ② ◎ , ③ ※" + }, + "15": { + "path": "//CHAR[contains(text(),'{searchValue}')]/parent::TEXT/@CharShape", + "searchValue": "행사안내", + "value": "굴림체", + "points": 1, + "category": "FontName", + "item": "문구 (◎ 행사안내 ◎)/① 글씨체 (굴림체)" + }, + "16": { + "path": "//PARASHAPE[@Id=//CHAR[contains(text(),'{match_str}')]/ancestor::P/@ParaShape]/@Align", + "match_str": "행사안내", + "value": "Center", + "points": 1, + "category": "Align", + "item": "문구 (◎ 행사안내 ◎)/② 정렬 (가운데 정렬)" + }, + "17": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]", + "hyperlink_ptag": "//P[.//FIELDBEGIN[@Type='Hyperlink']]", + "searchValue": "경복궁역 8번 출구 도보 5분", + "value": "ITALIC", + "points": 1, + "category": "FontAttribute", + "item": "문구 (경복궁역 8번 출구 도보 5분)/① ITALIC" + }, + "18": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]", + "hyperlink_ptag": "//P[.//FIELDBEGIN[@Type='Hyperlink']]", + "searchValue": "경복궁역 8번 출구 도보 5분", + "value": "UNDERLINE", + "points": 1, + "category": "FontAttribute", + "item": "문구 (경복궁역 8번 출구 도보 5분)/② UNDERLINE" + }, + "19": { + "path": "//PARASHAPE[@Id=//CHAR[contains(text(),'{searchValue}')]/ancestor::P/following-sibling::P[1]/@ParaShape]/PARAMARGIN", + "searchValue": "기타사항", + "value": { + "Left": 15, + "Indent": 12 + }, + "points": 2, + "category": "ParaShape", + "item": "문구 (※ 기타… 이하 문단)/왼쪽여백 (15pt), 내어쓰기 (12pt)", + "desc": "내부적으로 내어쓰기는 음수값 / JSON value값은 양수로 입력" + }, + "20": { + "path": "//CHARSHAPE[@Id=//CHAR[contains(text(),'{searchValue}')]/parent::TEXT/@CharShape]/@Height", + "searchValue": "2025. 8. 23.", + "value": "1400", + "points": 1, + "category": "OneAnswer", + "item": "문구 (2025. 8. 23.)/① 크기 (1400)", + "desc": "1pt당 100" + }, + "21": { + "path": "//PARASHAPE[@Id=//CHAR[contains(text(),'{searchValue}')]/ancestor::P/@ParaShape]/@Align", + "searchValue": "2025. 8. 23.", + "value": "Center", + "points": 1, + "category": "OneAnswer", + "item": "문구 (2025. 8. 23.)/② 정렬 (가운데 정렬)" + }, + "22": { + "path": "//TEXT[CHAR[text()='{searchValue}']]/@CharShape", + "searchValue": "밝은미소구강센터", + "value": "견고딕", + "points": 1, + "category": "FontName", + "item": "문구 (밝은미소구강센터)/① 글씨체 (견고딕)" + }, + "23": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]/@Height", + "searchValue": "밝은미소구강센터", + "value": "2400", + "points": 1, + "category": "OneAnswer", + "item": "문구 (밝은미소구강센터)/② 크기 (2400)" + }, + "24": { + "path": "//PARASHAPE[@Id=//CHAR[text()='{searchValue}']/ancestor::P/@ParaShape]/@Align", + "searchValue": "밝은미소구강센터", + "value": "Center", + "points": 1, + "category": "OneAnswer", + "item": "문구 (밝은미소구강센터)/③ 정렬 (가운데 정렬)" + }, + "25": { + "path": "//SECTION[1]//TEXT[CHAR[text()='{searchValue}']]/@CharShape", + "searchValue": "DIAT", + "value": "궁서", + "points": 1, + "category": "FontName", + "item": "문구 (DIAT)/① 글꼴 (궁서)" + }, + "26": { + "path": "//CHARSHAPE[@Id=//SECTION[1]//TEXT[CHAR[text()='{searchValue}']]/@CharShape]/@Height", + "searchValue": "DIAT", + "value": "900", + "points": 1, + "category": "OneAnswer", + "item": "문구 (DIAT)/② 크기 (9pt)" + }, + "27": { + "path": "//PARASHAPE[@Id=//SECTION[1]//CHAR[text()='{searchValue}']/parent::TEXT/parent::P/@ParaShape]/@Align", + "searchValue": "DIAT", + "value": "Right", + "points": 1, + "category": "OneAnswer", + "item": "문구 (DIAT)/③ 정렬 (오른쪽 정렬)" + }, + "28": { + "path": "//PAGENUM/@FormatType", + "value": "HangulSyllable", + "points": 2, + "category": "PageNumber", + "item": "① 쪽 번호 매기기 (가,나,다 순으로)", + "desc1": { + "가,나,다": "HangulSyllable", + "1,2,3": "Digit", + "갑,을,병": "DecagonCircle", + "A,B,C": "LatinCapital", + "a,b,c": "LatinSmall", + "①,②,③": "CircledDigit", + "一,二,三": "Ideograph", + "㉠,㉡,㉢": "CircledHangulJamo", + "ⓐ,ⓑ,ⓒ": "CircledLatinSmall", + "i,ii,iii": "RomanSmall", + "I,II,III": "RomanCapital", + "desc": "정답에 맞는 값 value에 입력" + }, + "desc2": "1, 2페이지 모두 정답이어야 점수 부여" + }, + "29": { + "path": "//PAGENUM/@Pos", + "value": "BottomRight", + "points": 2, + "category": "PageNumber", + "item": "오른쪽 아래", + "desc": "1, 2페이지 모두 정답이어야 점수 부여", + "desc2": { + "가운데 아래": "BottomCenter", + "오른쪽 아래": "BottomRight" + } + }, + "30": { + "path": "//PARASHAPE[@Id='{parashape_id}']/PARAMARGIN/@LineSpacing", + "value": "200", + "first_word": "현", + "points": 2, + "category": "LineSpacing", + "item": "문제 1 줄간격 200% 설정", + "desc": "1페이지 문단의 줄간격이 정답이 아닌 문단이 있으면 False(감점), first_word 속성에 [문단 첫글자 장식]에 해당하는 글자를 입력해준다." + } + }, + "2": { + "1": { + "path": "//PAGEBORDERFILL[@Type='Both' or @Type='Even']/@HeaderInside", + "path2": "//BORDERFILL[@Id=//PAGEBORDERFILL[@Type='Both' or @Type='Even']/@BorferFill]", + "value": { + "header_inside": true, + "all_double_slim": true + }, + "points": 4, + "category": "PageBorder", + "item": "문제2 쪽테두리(이중 실선, 머리말 포함) 설정" + }, + "2": { + "path": "count(//SECTION)>1", + "value": true, + "points": 3, + "category": "Boolean", + "item": "① 구역나누기", + "desc": "섹션이 1개 이상이면 점수부여" + }, + "3": { + "path": "TEXT/COLDEF/@Count", + "value": "2", + "points": 3, + "category": "TwoColumn", + "item": "② 다단 2단" + }, + "4": { + "path": "//RECTANGLE//CHAR[text()='{searchValue}']/ancestor::RECTANGLE/SHAPEOBJECT/SIZE/@Width", + "searchValue": "구강건강관리", + "value": "60", + "points": 2, + "category": "mmSize", + "item": "문구 (구강건강관리)/① 크기-너비 (60 mm)" + }, + "5": { + "path": "//RECTANGLE//CHAR[text()='{searchValue}']/ancestor::RECTANGLE/SHAPEOBJECT/SIZE/@Height", + "searchValue": "구강건강관리", + "value": "12", + "points": 2, + "category": "mmSize", + "item": "문구 (구강건강관리)/② 크기-높이 (12 mm)" + }, + "6": { + "path": "//RECTANGLE[.//CHAR[text()='{searchValue}']]//LINESHAPE", + "searchValue": "구강건강관리", + "value": { + "Style": "DoubleSlim", + "Width": "283" + }, + "points": 2, + "category": "LineShape", + "item": "문구 (구강건강관리)/③ 테두리 : 이중 실선(1.00mm)", + "desc": "1mm = 283pt value['Width']에 pt값 입력" + }, + "7": { + "path": "//RECTANGLE[.//CHAR[text()='{searchValue}']]/@Ratio", + "searchValue": "구강건강관리", + "value": "20", + "points": 2, + "category": "OneAnswer", + "item": "문구 (구강건강관리)/④ 글상자 모서리 (반원)", + "desc": "모서리 비율 반원:50 / 둥근모양:20" + }, + "8": { + "path": "//RECTANGLE[.//CHAR[text()='{searchValue}']]//WINDOWBRUSH/@FaceColor", + "searchValue": "구강건강관리", + "value": "187,140,209", + "points": 2, + "category": "Color", + "item": "문구 (구강건강관리)/⑤ 채우기 : 색상(RGB:187,140,209)" + }, + "9": { + "path": "//RECTANGLE[.//CHAR[text()='{searchValue}']]/SHAPEOBJECT/POSITION/@TreatAsChar", + "searchValue": "구강건강관리", + "value": "true", + "points": 1, + "category": "OneAnswer", + "item": "문구 (구강건강관리)/⑥ 글상자 위치 (글자처럼 취급)" + }, + "10": { + "path": "//PARASHAPE[@Id=//RECTANGLE//CHAR[text()='{searchValue}']/ancestor::P[last()]/@ParaShape]/@Align", + "searchValue": "구강건강관리", + "value": "Center", + "points": 1, + "category": "OneAnswer", + "item": "문구 (구강건강관리)/⑦ 글상자 정렬 (가운데 정렬)" + }, + "11": { + "path": "//TEXT[CHAR[text()='{searchValue}']]/@CharShape", + "searchValue": "구강건강관리", + "value": "맑은 고딕", + "points": 1, + "category": "FontName", + "item": "문구 (구강건강관리)/⑧ 글씨체 (맑은 고딕)" + }, + "12": { + "path": "//CHARSHAPE[@Id=//RECTANGLE//TEXT[./CHAR[text()='{searchValue}']]/@CharShape]/@Height", + "searchValue": "구강건강관리", + "value": "2300", + "points": 1, + "category": "OneAnswer", + "item": "문구 (구강건강관리)/⑨ 글씨크기 (2300)", + "desc": "1pt당 100" + }, + "13": { + "path": "//PARASHAPE[@Id=//RECTANGLE//P[.//CHAR[text()='{searchValue}']]/@ParaShape]/@Align", + "searchValue": "구강건강관리", + "value": "Center", + "points": 1, + "category": "OneAnswer", + "item": "문구 (구강건강관리)/⑩ 정렬 (가운데 정렬)" + }, + "14": { + "path": "//BINITEM[@BinData=//PICTURE/IMAGE/@BinItem][@Format='JPG' or @Format='JPEG']", + "value": true, + "points": 2, + "category": "Boolean", + "item": "① 파일명 \"그림C.jpg\" 삽입", + "desc": "첨부 이미지 파일명 손상으로 정상적인 채점이 불가한 경우가 발견되어서 이미지 첨부 여부로 채점 방식 변경 (7/3)" + }, + "15": { + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/SIZE/@Width", + "value": "80", + "points": 2, + "category": "mmSize", + "item": "② 크기-너비 (80 mm)" + }, + "16": { + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/SIZE/@Height", + "value": "40", + "points": 2, + "category": "mmSize", + "item": "③ 크기-높이 (40 mm)" + }, + "17": { + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@HorzOffset", + "value": "0", + "points": 2, + "category": "mmSize", + "item": "④ 위치 (어울림 : 가로-쪽의 왼쪽 0.0mm)" + }, + "18": { + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@VertOffset", + "value": "22", + "points": 2, + "category": "mmSize", + "item": "⑤ 위치 (어울림 : 세로-쪽의 위 22 mm)" + }, + "19": { + "path": "//TEXT[CHAR[text()='{searchValue}']]/@CharShape", + "searchValue": "1. 구강건강관리", + "value": "돋움체", + "points": 1, + "category": "FontName", + "item": "문구① (1. 구강건강관리)/① 글씨체 (돋움체)" + }, + "20": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]/@Height", + "searchValue": "1. 구강건강관리", + "value": "1200", + "points": 1, + "category": "OneAnswer", + "item": "문구① (1. 구강건강관리)/② 크기 (12pt)" + }, + "21": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]", + "searchValue": "1. 구강건강관리", + "value": "BOLD", + "points": 1, + "category": "FontAttribute", + "item": "문구① (1. 구강건강관리)/③ 진하게" + }, + "22": { + "path": "//TEXT[CHAR[text()='{searchValue}']]/@CharShape", + "searchValue": "2. 관련 연구", + "value": "돋움체", + "points": 1, + "category": "FontName", + "item": "문구② (2. 관련 연구)/① 글씨체 (돋움체)" + }, + "23": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]/@Height", + "searchValue": "2. 관련 연구", + "value": "1200", + "points": 1, + "category": "OneAnswer", + "item": "문구② (2. 관련 연구)/② 크기 (1200)" + }, + "24": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]", + "searchValue": "2. 관련 연구", + "value": "BOLD", + "points": 1, + "category": "FontAttribute", + "item": "문구② (2. 관련 연구)/③ 진하게" + }, + "25": { + "path": "boolean(//TEXT[CHAR[contains(text(),'{option}')]]/FOOTNOTE)", + "path2": "boolean(//CHAR[substring(., string-length(.) - string-length('{option}') + 1) = '{option}']/following-sibling::FOOTNOTE/descendant::CHAR)", + "option": "구강미생물", + "value": true, + "points": 2, + "category": "Boolean", + "item": "문구 (구강미생물)/① 각주 설정 및 문구 입력" + }, + "26": { + "path": "//CHAR[contains(text(),'{searchValue}')]/parent::TEXT/@CharShape", + "searchValue": "구강 내 존재하는 미생물(세균)들을 의미함", + "value": "굴림체", + "points": 1, + "category": "FontName", + "item": "문구 (구강미생물)/② 글씨체 (굴림체)" + }, + "27": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[contains(text(),'{searchValue}')]]/@CharShape]/@Height", + "searchValue": "구강 내 존재하는 미생물(세균)들을 의미함", + "value": "900", + "points": 1, + "category": "OneAnswer", + "item": "문구 (구강미생물)/③ 크기 (9pt)" + }, + "28": { + "path": "//P[TEXT[CHAR[contains(text(), '{searchValue}')]]]//AUTONUMFORMAT/@Type", + "searchValue": "구강 내 존재하는 미생물(세균)들을 의미함", + "value": "DecagonCircle", + "points": 2, + "category": "OneAnswer", + "item": "문구 (전당)/④ 각주 번호모양", + "desc": { + "가,나,다": "HangulSyllable", + "1,2,3": "Digit", + "갑,을,병": "DecagonCircle", + "A,B,C": "LatinCapital", + "a,b,c": "LatinSmall", + "①,②,③": "CircledDigit", + "一,二,三": "Ideograph", + "㉠,㉡,㉢": "CircledHangulJamo", + "ⓐ,ⓑ,ⓒ": "CircledLatinSmall", + "i,ii,iii": "RomanSmall", + "I,II,III": "RomanCapital", + "甲,乙,丙": "DecagonCircleHanja", + "+,++,+++": "UserChar", + "정답에 맞는 값 value에 입력": "" + } + }, + "29": { + "path": "boolean(//CHAR[contains(text(),'Fluoride')])", + "ignoreWord": "Fluoride", + "value": true, + "points": 3, + "category": "Boolean", + "item": "Fluoride/영단어 미입력, 대소문자/오타 시 전체 감점", + "desc": "유사도 검사를 진행하지 않고 영단어가 모두 일치해야 하므로 xpath구문 내 단어도 수정필요" + }, + "30": { + "path": "//CHAR[contains(text(),'{kor}')][contains(text(),'{chn}')]", + "word": [ + ["각도", "角度"], + ["활용", "活用"], + ["청결", "淸潔"], + ["예방", "豫防"], + ["융합", "融合"] + ], + "value": 10, + "points": 10, + "category": "Hanja", + "item": "① 각도(角度), ② 활용(活用), ③ 청결(淸潔), ④ 예방(豫防), ⑤ 융합(融合)" + }, + "31": { + "path": "boolean(//CHAR[contains(translate(text(), ' ', ''),'질은치아')])", + "value": true, + "points": 3, + "category": "Boolean", + "item": "문구 (…칫솔질은 창아와 잇몸 경계에 45도…)>'창' → '치' 글자바꿈" + }, + "32": { + "path": "boolean(//CHAR[contains(translate(text(), ' ', ''),'구강건조')])", + "value": true, + "points": 3, + "category": "Boolean", + "item": "문구 (…건조증 구강 예방에 특별한 주의가 필요하다.…)>'건조증 / 구강' 순서바꿈" + }, + "33": { + "path": "//TEXT[CHAR[contains(text(),'{searchValue}')]]/@CharShape", + "searchValue": "치주질환 통계표(단위:명", + "value": "중고딕", + "points": 1, + "category": "FontName", + "item": "제목 문구 (치주질환 통계표(단위:명)/① 글씨체 (중고딕)" + }, + "34": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]/@Height", + "searchValue": "치주질환 통계표(단위:명", + "value": "1200", + "points": 1, + "category": "OneAnswer", + "item": "제목 문구 (치주질환 통계표(단위:명)/② 크기 (1200)" + }, + "35": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]", + "searchValue": "치주질환 통계표(단위:명", + "value": "BOLD", + "points": 1, + "category": "FontAttribute", + "item": "제목 문구 (치주질환 통계표(단위:명)/③ 진하게" + }, + "36": { + "path": "//PARASHAPE[@Id=//P[.//CHAR[text()='{searchValue}']]/@ParaShape]/@Align", + "searchValue": "치주질환 통계표(단위:명", + "value": "Center", + "points": 1, + "category": "OneAnswer", + "item": "제목 문구 (치주질환 통계표(단위:명)/④ 정렬 (가운데 정렬)" + }, + "37": { + "path": "//BORDERFILL[@Id=//TABLE/ROW[1]/CELL/@BorderFill]/FILLBRUSH/WINDOWBRUSH/@FaceColor", + "path2": "//BORDERFILL[@Id=//CELLZONE[@StartRowAddr='0' and @EndRowAddr='0' and @StartColAddr='0' and @EndColAddr=(ancestor::TABLE[1]/@ColCount)-1]/@BorderFill]/FILLBRUSH/WINDOWBRUSH/@FaceColor", + "value": "210,191,27", + "points": 2, + "category": "Color", + "item": "위쪽 제목 셀/① 색상(RGB:210,191,27)" + }, + "38": { + "path": "//CHARSHAPE[@Id=//TABLE/ROW[1]/descendant::TEXT/@CharShape]", + "value": "BOLD", + "points": 1, + "category": "FontAttribute", + "item": "위쪽 제목 셀/② 진하게", + "desc": "글자 속성이라 CELLZONE으로 적용 되지 않음" + }, + "39": { + "path": "//BORDERFILL[@Id=//TABLE/ROW[1]/CELL/@BorderFill]/BOTTOMBORDER/@Type", + "path2": "//BORDERFILL[@Id=//CELLZONE[@StartRowAddr='0' and @EndRowAddr='0' and @StartColAddr='0' and @EndColAddr=(ancestor::TABLE[1]/@ColCount)-1]/@BorderFill]/BOTTOMBORDER/@Type", + "value": "DoubleSlim", + "points": 2, + "category": "TableAnswer", + "item": "제목 셀 아래선/① 이중실선" + }, + "40": { + "path": "//BORDERFILL[@Id=//TABLE/ROW[1]/CELL/@BorderFill]/BOTTOMBORDER/@Width", + "path2": "//BORDERFILL[@Id=//CELLZONE[@StartRowAddr='0' and @EndRowAddr='0' and @StartColAddr='0' and @EndColAddr=(ancestor::TABLE[1]/@ColCount)-1]/@BorderFill]/BOTTOMBORDER/@Width", + "value": "0.5mm", + "points": 2, + "category": "TableAnswer", + "item": "제목 셀 아래선/② 0.5mm" + }, + "41": { + "path": "//TABLE//TEXT/@CharShape", + "path2": "//FONTFACE[@Lang='Hangul']/FONT[@Id=//CHARSHAPE[@Id=//TABLE/ROW/descendant::TEXT/@CharShape]/FONTID/@Hangul]/@Name", + "value": "바탕체", + "points": 1, + "category": "TableFontName", + "category_tmp": "FontName", + "item": "글자모양/① 글씨체 (바탕체)", + "desc": "테이블 폰트명 문항은 테이블의 모든 셀이 정답폰트와 일치해야 함, 하나만 일치해도 정답으로 채점할 경우 category값을 FontName으로 변경" + }, + "42": { + "path": "//CHARSHAPE[@Id=//TABLE//TEXT/@CharShape]/@Height", + "value": "1000", + "points": 1, + "category": "TableAnswer", + "item": "글자모양/② 크기 (1000)" + }, + "43": { + "path": "//PARASHAPE[@Id=//TABLE/ROW//P/@ParaShape]/@Align", + "value": "Center", + "points": 1, + "category": "TableAnswer", + "item": "글자모양/③ 정렬 (가운데 정렬)" + }, + "44": { + "path": "boolean(//TABLE[1]/ROW[last()]/CELL[position()=last()]//FIELDBEGIN[starts-with(@Command, '={option}')]) and boolean(//TABLE[1]/ROW[last()]/CELL[position()=last()-1]//FIELDBEGIN[starts-with(@Command, '={option}')])", + "option": "AVG", + "value": true, + "points": 4, + "category": "Boolean", + "item": "블록 계산식/평균", + "desc": "option값에 합계는 SUM / 평균은 AVG" + }, + "45": { + "chart_xpath": "", + "chart_type": "꺾은선형", + "value": true, + "points": 2, + "category": "ChartType", + "item": "① 종류 (꺾은선형)", + "desc": "chart_type을 입력받아 차트타입에 맞는 xml요소가 있는지 내부적으로 검사, chart_type만 한글로 입력해주면 된다. (공백무시)" + }, + "46": { + "chart_xpath": "//c:valAx/c:majorTickMark/@val", + "value": "out", + "points": 2, + "category": "ChartOneAnswer", + "item": "② 값 축 주 눈금선", + "desc": "chart xml파일에서 답안을 가져오는 문항은 path키값 대신 chart_xpath키값을 이용해 xapth구문을 작성한다" + }, + "47": { + "path": "//OLE[@BinItem=//BINITEM[@Format='OLE']/@BinData]//SIZE/@Width", + "value": "80", + "points": 2, + "category": "mmSize", + "item": "③ 크기-너비 (80 mm)" + }, + "48": { + "path": "//OLE[@BinItem=//BINITEM[@Format='OLE']/@BinData]//SIZE/@Height", + "value": "90", + "points": 2, + "category": "mmSize", + "item": "④ 크기-높이 (90 mm)" + }, + "49": { + "chart_xpath": "boolean(//c:chart and not(//c:pt[not(ancestor::c:tx)]/c:v[text()='합계' or text()='평균']))", + "value": true, + "points": 2, + "category": "Boolean", + "item": "⑤ 차트 데이터(표에서 블록계산식을 제외한 나머지 값만 이용)", + "desc": "차트가 존재하고 블록계산식(합계, 평균) 데이터가 없는 경우 정답 처리" + }, + "50": { + "chart_xpath": "//a:t[text()='{searchValue}']/ancestor::a:r//a:ea/@typeface", + "searchValue": "치주질환 통계표", + "value": "궁서체", + "points": 1, + "category": "OneAnswer", + "item": "제목 문구 (치주질환 통계표)/① 글씨체 (궁서체)" + }, + "51": { + "chart_xpath": "//a:t[text()='{searchValue}']/ancestor::a:r/a:rPr/@sz", + "searchValue": "치주질환 통계표", + "value": "1300", + "points": 1, + "category": "OneAnswer", + "item": "제목 문구 (치주질환 통계표)/② 크기 (1300)" + }, + "52": { + "chart_xpath": "//a:t[text()='{searchValue}']/ancestor::a:r/a:rPr/@{option}", + "option": "b", + "searchValue": "치주질환 통계표", + "value": "1", + "points": 1, + "category": "OneAnswer", + "item": "제목 문구 (치주질환 통계표)/③ 기울임", + "desc": "option값 - 기울임(Italic):i / 굵게(Bold):b" + }, + "53": { + "chart_xpath": "//c:catAx/c:txPr//a:ea/@typeface", + "value": "궁서", + "points": 1, + "category": "ChartOneAnswer", + "item": "X축/① 글꼴 (궁서)" + }, + "54": { + "chart_xpath": "//c:catAx/c:txPr//a:defRPr/@sz", + "value": "900", + "points": 1, + "category": "ChartOneAnswer", + "item": "X축/② 크기 (9pt)" + }, + "55": { + "chart_xpath": "//c:catAx/c:txPr//a:defRPr/@{option}", + "option": "i", + "value": "1", + "points": 1, + "category": "ChartOneAnswer", + "item": "X축/③ 기울임", + "desc": "option값 - 기울임(Italic):i / 굵게(Bold):b" + }, + "56": { + "chart_xpath": "//c:valAx/c:txPr//a:ea/@typeface", + "value": "궁서", + "points": 1, + "category": "ChartOneAnswer", + "item": "Y축/① 글꼴 (궁서)" + }, + "57": { + "chart_xpath": "//c:valAx/c:txPr//a:defRPr/@sz", + "value": "900", + "points": 1, + "category": "ChartOneAnswer", + "item": "Y축/② 크기 (9pt)" + }, + "58": { + "chart_xpath": "//c:valAx/c:txPr//a:defRPr/@{option}", + "option": "i", + "value": "1", + "points": 1, + "category": "ChartOneAnswer", + "item": "Y축/③ 기울임", + "desc": "option값 - 기울임(Italic):i / 굵게(Bold):b" + }, + "59": { + "chart_xpath": "//c:legend//a:ea/@typeface", + "value": "궁서", + "points": 1, + "category": "OneAnswer", + "item": "범례/① 글꼴 (궁서)" + }, + "60": { + "chart_xpath": "//c:legend//a:defRPr/@sz", + "value": "900", + "points": 1, + "category": "OneAnswer", + "item": "범례/② 크기 (9pt)" + }, + "61": { + "chart_xpath": "//c:legend//a:defRPr/@{option}", + "option": "i", + "value": "1", + "points": 1, + "category": "OneAnswer", + "item": "범례/③ 기울임", + "desc": "option값 - 기울임(Italic):i / 굵게(Bold):b" + } + } +} diff --git a/회차별채점자료/2508/_DIW_2508D.json b/회차별채점자료/2508/_DIW_2508D.json new file mode 100644 index 0000000..2c6a978 --- /dev/null +++ b/회차별채점자료/2508/_DIW_2508D.json @@ -0,0 +1,841 @@ +{ + "0": { + "0": { + "path": "", + "path2": "", + "points": 0, + "category": "파일저장", + "item": "파일명 (수검번호.hwp/hwpx)" + }, + "1": { + "path": "//PAGEMARGIN", + "value": { + "Top": 20, + "Bottom": 20, + "Left": 20, + "Right": 20, + "Header": 10, + "Footer": 10, + "Gutter": 0 + }, + "tolerance": 1, + "points": 4, + "category": "PageSetting", + "item": "A4용지, 왼쪽/오른쪽/위쪽/아래쪽 (각20mm), 머리말/꼬리말 (10mm), 제본(0mm)" + }, + "2": { + "path": "", + "value": { + "FontName": "바탕", + "FontSize": "1000", + "Alignment": "Justify", + "LineSpacing": "160" + }, + "points": 4, + "category": "BasicSetting", + "item": "글꼴 (바탕, 10pt), 양쪽정렬, 줄간격 (160%)" + }, + "3": { + "path": "", + "value": null, + "points": 40, + "category": "오타감점", + "item": "오타 1개 -1점 / 2503회부터 오타 1개 -1점으로 변경" + } + }, + "1": { + "1": { + "path": "//TEXTART[@Text='{searchValue}']/TEXTARTSHAPE/@FontName", + "searchValue": "강원도지역문화체험안내", + "value": "맑은고딕", + "points": 1, + "category": "OneAnswer", + "item": "문구 (강원도지역문화체험안내)/① 글씨체 (맑은고딕)" + }, + "2": { + "path": "//TEXTART[@Text='{searchValue}']/descendant::WINDOWBRUSH/@FaceColor", + "searchValue": "강원도지역문화체험안내", + "value": "230,47,199", + "points": 2, + "category": "Color", + "item": "문구 (강원도지역문화체험안내)/② 채우기 : 색상(RGB:230,47,199)" + }, + "3": { + "path": "//TEXTART[@Text='{searchValue}']/SHAPEOBJECT/SIZE/@Width", + "searchValue": "강원도지역문화체험안내", + "value": "125", + "tolerance": 1, + "points": 2, + "category": "mmSize", + "item": "문구 (강원도지역문화체험안내)/③ 크기-너비 (125 mm)" + }, + "4": { + "path": "//TEXTART[@Text='{searchValue}']/SHAPEOBJECT/SIZE/@Height", + "searchValue": "강원도지역문화체험안내", + "value": "20", + "tolerance": 1, + "points": 2, + "category": "mmSize", + "item": "문구 (강원도지역문화체험안내)/④ 크기-높이 (20 mm)" + }, + "5": { + "path": "//TEXTART[@Text='{searchValue}']/SHAPEOBJECT/POSITION/@TreatAsChar", + "searchValue": "강원도지역문화체험안내", + "value": "true", + "points": 2, + "category": "OneAnswer", + "item": "문구 (강원도지역문화체험안내)/⑤ 위치 (글자처럼 취급)" + }, + "6": { + "path": "//PARASHAPE[@Id=//P[.//TEXTART[@Text='{searchValue}']]/@ParaShape]/@Align", + "searchValue": "강원도지역문화체험안내", + "value": "Center", + "points": 2, + "category": "OneAnswer", + "item": "문구 (강원도지역문화체험안내)/⑥ 정렬 (가운데 정렬)" + }, + "7": { + "path": "//TEXTART[@Text='{searchValue}']", + "searchValue": "강원도지역문화체험안내", + "value": true, + "points": 2, + "category": "Boolean", + "item": "문구 (강원도지역문화체험안내)/⑦ 글맵시모양 (육안확인)" + }, + "8": { + "path": "//RECTANGLE[.//CHAR[text()='{searchValue}']]/SHAPEOBJECT/SIZE", + "searchValue": "자", + "value": { + "Height": 2800, + "Width": 2800 + }, + "tolerance": 200, + "points": 1, + "category": "TwoLineSize", + "item": "자/① 모양 (2줄)" + }, + "9": { + "path": "//TEXT[CHAR[text()='{searchValue}']]/@CharShape", + "searchValue": "자", + "value": "돋움", + "points": 1, + "category": "FontName", + "item": "자/② 글씨체 (돋움)" + }, + "10": { + "path": "//RECTANGLE[.//CHAR[text()='{searchValue}']]//WINDOWBRUSH/@FaceColor", + "searchValue": "자", + "value": "231,215,17", + "points": 2, + "category": "Color", + "item": "자/③ 면색 : 색상(RGB:231,215,17)" + }, + "11": { + "path": "//RECTANGLE[.//CHAR[text()='{searchValue}']]//OUTSIDEMARGIN/@Right", + "searchValue": "자", + "value": "3.0", + "tolerance": 1, + "points": 2, + "category": "mmSize", + "item": "자/④ 본문과의 간격 : 3.0mm" + }, + "12": { + "path": "//CHARSHAPE[@Id=//CHAR[contains(text(),'{searchValue}')]/parent::TEXT/@CharShape]", + "searchValue": "독특한 문화를 경험하실 수 있도록", + "value": "BOLD", + "points": 2, + "category": "FontAttribute", + "item": "문구 (독특한 문화를 경험하실 수 있도록)/① BOLD" + }, + "13": { + "path": "//CHARSHAPE[@Id=//CHAR[contains(text(),'{searchValue}')]/parent::TEXT/@CharShape]", + "searchValue": "독특한 문화를 경험하실 수 있도록", + "value": "ITALIC", + "points": 2, + "category": "FontAttribute", + "item": "문구 (독특한 문화를 경험하실 수 있도록)/② ITALIC" + }, + "14": { + "path": "//CHAR[contains(string(.),'{char1}')]/text()", + "path2": "//CHAR[contains(string(.),'{char2}')]/text()", + "path3": "//CHAR[contains(string(.),'{char3}')]/text()", + "char1": "▶", + "char2": "◀", + "char3": "※", + "value": 3, + "points": 3, + "category": "SpecialChar", + "item": "① ▶, ② ◀, ③ ※" + }, + "15": { + "path": "//CHAR[contains(text(),'{searchValue}')]/parent::TEXT/@CharShape", + "searchValue": "행사안내", + "value": "궁서", + "points": 1, + "category": "FontName", + "item": "문구 (▶ 행사안내 ◀)/① 글씨체 (궁서)" + }, + "16": { + "path": "//PARASHAPE[@Id=//CHAR[contains(text(),'{match_str}')]/ancestor::P/@ParaShape]/@Align", + "match_str": "행사안내", + "value": "Center", + "points": 1, + "category": "Align", + "item": "문구 (▶ 행사안내 ◀)/② 정렬 (가운데 정렬)" + }, + "17": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]", + "hyperlink_ptag": "//P[.//FIELDBEGIN[@Type='Hyperlink']]", + "searchValue": "강원도 춘천시 중앙문화지역센터 및 인근 공원", + "value": "ITALIC", + "points": 1, + "category": "FontAttribute", + "item": "문구 (강원도 춘천시 중앙문화지역센터 및 인근 공원)/① ITALIC" + }, + "18": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]", + "hyperlink_ptag": "//P[.//FIELDBEGIN[@Type='Hyperlink']]", + "searchValue": "강원도 춘천시 중앙문화지역센터 및 인근 공원", + "value": "UNDERLINE", + "points": 1, + "category": "FontAttribute", + "item": "문구 (강원도 춘천시 중앙문화지역센터 및 인근 공원)/② UNDERLINE" + }, + "19": { + "path": "//PARASHAPE[@Id=//CHAR[contains(text(),'{searchValue}')]/ancestor::P/following-sibling::P[1]/@ParaShape]/PARAMARGIN", + "searchValue": "기타사항", + "value": { + "Left": 15, + "Indent": 12 + }, + "points": 2, + "category": "ParaShape", + "item": "문구 (※ 기타… 이하 문단)/왼쪽여백 (15pt), 내어쓰기 (12pt)", + "desc": "내부적으로 내어쓰기는 음수값 / JSON value값은 양수로 입력" + }, + "20": { + "path": "//CHARSHAPE[@Id=//CHAR[contains(text(),'{searchValue}')]/parent::TEXT/@CharShape]/@Height", + "searchValue": "2025. 8. 23.", + "value": "1400", + "points": 1, + "category": "OneAnswer", + "item": "문구 (2025. 8. 23.)/① 크기 (1400)", + "desc": "1pt당 100" + }, + "21": { + "path": "//PARASHAPE[@Id=//CHAR[contains(text(),'{searchValue}')]/ancestor::P/@ParaShape]/@Align", + "searchValue": "2025. 8. 23.", + "value": "Center", + "points": 1, + "category": "OneAnswer", + "item": "문구 (2025. 8. 23.)/② 정렬 (가운데 정렬)" + }, + "22": { + "path": "//TEXT[CHAR[text()='{searchValue}']]/@CharShape", + "searchValue": "중앙문화지역센터", + "value": "궁서체", + "points": 1, + "category": "FontName", + "item": "문구 (중앙문화지역센터)/① 글씨체 (궁서체)" + }, + "23": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]/@Height", + "searchValue": "중앙문화지역센터", + "value": "2500", + "points": 1, + "category": "OneAnswer", + "item": "문구 (중앙문화지역센터)/② 크기 (2500)" + }, + "24": { + "path": "//PARASHAPE[@Id=//CHAR[text()='{searchValue}']/ancestor::P/@ParaShape]/@Align", + "searchValue": "중앙문화지역센터", + "value": "Center", + "points": 1, + "category": "OneAnswer", + "item": "문구 (중앙문화지역센터)/③ 정렬 (가운데 정렬)" + }, + "25": { + "path": "//SECTION[1]//TEXT[CHAR[text()='{searchValue}']]/@CharShape", + "searchValue": "DIAT", + "value": "궁서", + "points": 1, + "category": "FontName", + "item": "문구 (DIAT)/① 글꼴 (궁서)" + }, + "26": { + "path": "//CHARSHAPE[@Id=//SECTION[1]//TEXT[CHAR[text()='{searchValue}']]/@CharShape]/@Height", + "searchValue": "DIAT", + "value": "900", + "points": 1, + "category": "OneAnswer", + "item": "문구 (DIAT)/② 크기 (9pt)" + }, + "27": { + "path": "//PARASHAPE[@Id=//SECTION[1]//CHAR[text()='{searchValue}']/parent::TEXT/parent::P/@ParaShape]/@Align", + "searchValue": "DIAT", + "value": "Right", + "points": 1, + "category": "OneAnswer", + "item": "문구 (DIAT)/③ 정렬 (오른쪽 정렬)" + }, + "28": { + "path": "//PAGENUM/@FormatType", + "value": "Digit", + "points": 2, + "category": "PageNumber", + "item": "① 쪽 번호 매기기 (가,나,다 순으로)", + "desc1": { + "가,나,다": "HangulSyllable", + "1,2,3": "Digit", + "갑,을,병": "DecagonCircle", + "A,B,C": "LatinCapital", + "a,b,c": "LatinSmall", + "①,②,③": "CircledDigit", + "一,二,三": "Ideograph", + "㉠,㉡,㉢": "CircledHangulJamo", + "ⓐ,ⓑ,ⓒ": "CircledLatinSmall", + "i,ii,iii": "RomanSmall", + "I,II,III": "RomanCapital", + "desc": "정답에 맞는 값 value에 입력" + }, + "desc2": "1, 2페이지 모두 정답이어야 점수 부여" + }, + "29": { + "path": "//PAGENUM/@Pos", + "value": "BottomCenter", + "points": 2, + "category": "PageNumber", + "item": "가운데 아래", + "desc": "1, 2페이지 모두 정답이어야 점수 부여", + "desc2": { + "가운데 아래": "BottomCenter", + "오른쪽 아래": "BottomRight" + } + }, + "30": { + "path": "//PARASHAPE[@Id='{parashape_id}']/PARAMARGIN/@LineSpacing", + "value": "200", + "first_word": "자", + "points": 2, + "category": "LineSpacing", + "item": "문제 1 줄간격 200% 설정", + "desc": "1페이지 문단의 줄간격이 정답이 아닌 문단이 있으면 False(감점), first_word 속성에 [문단 첫글자 장식]에 해당하는 글자를 입력해준다." + } + }, + "2": { + "1": { + "path": "//PAGEBORDERFILL[@Type='Both' or @Type='Even']/@HeaderInside", + "path2": "//BORDERFILL[@Id=//PAGEBORDERFILL[@Type='Both' or @Type='Even']/@BorferFill]", + "value": { + "header_inside": true, + "all_double_slim": true + }, + "points": 4, + "category": "PageBorder", + "item": "문제2 쪽테두리(이중 실선, 머리말 포함) 설정" + }, + "2": { + "path": "count(//SECTION)>1", + "value": true, + "points": 3, + "category": "Boolean", + "item": "① 구역나누기", + "desc": "섹션이 1개 이상이면 점수부여" + }, + "3": { + "path": "TEXT/COLDEF/@Count", + "value": "2", + "points": 3, + "category": "TwoColumn", + "item": "② 다단 2단" + }, + "4": { + "path": "//RECTANGLE//CHAR[text()='{searchValue}']/ancestor::RECTANGLE/SHAPEOBJECT/SIZE/@Width", + "searchValue": "매력적인 강원도", + "value": "68", + "points": 2, + "category": "mmSize", + "item": "문구 (매력적인 강원도)/① 크기-너비 (68 mm)" + }, + "5": { + "path": "//RECTANGLE//CHAR[text()='{searchValue}']/ancestor::RECTANGLE/SHAPEOBJECT/SIZE/@Height", + "searchValue": "매력적인 강원도", + "value": "12", + "points": 2, + "category": "mmSize", + "item": "문구 (매력적인 강원도)/② 크기-높이 (12 mm)" + }, + "6": { + "path": "//RECTANGLE[.//CHAR[text()='{searchValue}']]//LINESHAPE", + "searchValue": "매력적인 강원도", + "value": { + "Style": "DoubleSlim", + "Width": "283" + }, + "points": 2, + "category": "LineShape", + "item": "문구 (매력적인 강원도)/③ 테두리 : 이중 실선(1.00mm)", + "desc": "1mm = 283pt value['Width']에 pt값 입력" + }, + "7": { + "path": "//RECTANGLE[.//CHAR[text()='{searchValue}']]/@Ratio", + "searchValue": "매력적인 강원도", + "value": "50", + "points": 2, + "category": "OneAnswer", + "item": "문구 (매력적인 강원도)/④ 글상자 모서리 (반원)", + "desc": "모서리 비율 반원:50 / 둥근모양:20" + }, + "8": { + "path": "//RECTANGLE[.//CHAR[text()='{searchValue}']]//WINDOWBRUSH/@FaceColor", + "searchValue": "매력적인 강원도", + "value": "130,159,32", + "points": 2, + "category": "Color", + "item": "문구 (매력적인 강원도)/⑤ 채우기 : 색상(RGB:130,159,32)" + }, + "9": { + "path": "//RECTANGLE[.//CHAR[text()='{searchValue}']]/SHAPEOBJECT/POSITION/@TreatAsChar", + "searchValue": "매력적인 강원도", + "value": "true", + "points": 1, + "category": "OneAnswer", + "item": "문구 (매력적인 강원도)/⑥ 글상자 위치 (글자처럼 취급)" + }, + "10": { + "path": "//PARASHAPE[@Id=//RECTANGLE//CHAR[text()='{searchValue}']/ancestor::P[last()]/@ParaShape]/@Align", + "searchValue": "매력적인 강원도", + "value": "Center", + "points": 1, + "category": "OneAnswer", + "item": "문구 (매력적인 강원도)/⑦ 글상자 정렬 (가운데 정렬)" + }, + "11": { + "path": "//TEXT[CHAR[text()='{searchValue}']]/@CharShape", + "searchValue": "매력적인 강원도", + "value": "굴림체", + "points": 1, + "category": "FontName", + "item": "문구 (매력적인 강원도)/⑧ 글씨체 (굴림체)" + }, + "12": { + "path": "//CHARSHAPE[@Id=//RECTANGLE//TEXT[./CHAR[text()='{searchValue}']]/@CharShape]/@Height", + "searchValue": "매력적인 강원도", + "value": "2300", + "points": 1, + "category": "OneAnswer", + "item": "문구 (매력적인 강원도)/⑨ 글씨크기 (2300)", + "desc": "1pt당 100" + }, + "13": { + "path": "//PARASHAPE[@Id=//RECTANGLE//P[.//CHAR[text()='{searchValue}']]/@ParaShape]/@Align", + "searchValue": "매력적인 강원도", + "value": "Center", + "points": 1, + "category": "OneAnswer", + "item": "문구 (매력적인 강원도)/⑩ 정렬 (가운데 정렬)" + }, + "14": { + "path": "//BINITEM[@BinData=//PICTURE/IMAGE/@BinItem][@Format='JPG' or @Format='JPEG']", + "value": true, + "points": 2, + "category": "Boolean", + "item": "① 파일명 \"그림D.jpg\" 삽입", + "desc": "첨부 이미지 파일명 손상으로 정상적인 채점이 불가한 경우가 발견되어서 이미지 첨부 여부로 채점 방식 변경 (7/3)" + }, + "15": { + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/SIZE/@Width", + "value": "85", + "points": 2, + "category": "mmSize", + "item": "② 크기-너비 (85 mm)" + }, + "16": { + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/SIZE/@Height", + "value": "40", + "points": 2, + "category": "mmSize", + "item": "③ 크기-높이 (40 mm)" + }, + "17": { + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@HorzOffset", + "value": "0", + "points": 2, + "category": "mmSize", + "item": "④ 위치 (어울림 : 가로-쪽의 왼쪽 0.0mm)" + }, + "18": { + "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG' or @Format='JPEG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@VertOffset", + "value": "22", + "points": 2, + "category": "mmSize", + "item": "⑤ 위치 (어울림 : 세로-쪽의 위 22 mm)" + }, + "19": { + "path": "//TEXT[CHAR[text()='{searchValue}']]/@CharShape", + "searchValue": "1. 지역적 특성", + "value": "맑은 고딕", + "points": 1, + "category": "FontName", + "item": "문구① (1. 지역적 특성)/① 글씨체 (맑은 고딕)" + }, + "20": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]/@Height", + "searchValue": "1. 지역적 특성", + "value": "1200", + "points": 1, + "category": "OneAnswer", + "item": "문구① (1. 지역적 특성)/② 크기 (12pt)" + }, + "21": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]", + "searchValue": "1. 지역적 특성", + "value": "BOLD", + "points": 1, + "category": "FontAttribute", + "item": "문구① (1. 지역적 특성)/③ 진하게" + }, + "22": { + "path": "//TEXT[CHAR[text()='{searchValue}']]/@CharShape", + "searchValue": "2. 문화유산과 전통", + "value": "맑은 고딕", + "points": 1, + "category": "FontName", + "item": "문구② (2. 문화유산과 전통)/① 글씨체 (맑은 고딕)" + }, + "23": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]/@Height", + "searchValue": "2. 문화유산과 전통", + "value": "1200", + "points": 1, + "category": "OneAnswer", + "item": "문구② (2. 문화유산과 전통)/② 크기 (1200)" + }, + "24": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]", + "searchValue": "2. 문화유산과 전통", + "value": "BOLD", + "points": 1, + "category": "FontAttribute", + "item": "문구② (2. 문화유산과 전통)/③ 진하게" + }, + "25": { + "path": "boolean(//TEXT[CHAR[contains(text(),'{option}')]]/FOOTNOTE)", + "path2": "boolean(//CHAR[substring(., string-length(.) - string-length('{option}') + 1) = '{option}']/following-sibling::FOOTNOTE/descendant::CHAR)", + "option": "목축업", + "value": true, + "points": 2, + "category": "Boolean", + "item": "문구 (목축업)/① 각주 설정 및 문구 입력" + }, + "26": { + "path": "//CHAR[contains(text(),'{searchValue}')]/parent::TEXT/@CharShape", + "searchValue": "소나 말, 양 따위의 가축을 기르는 일을 경영함.", + "value": "중고딕", + "points": 1, + "category": "FontName", + "item": "문구 (목축업)/② 글씨체 (중고딕)" + }, + "27": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[contains(text(),'{searchValue}')]]/@CharShape]/@Height", + "searchValue": "소나 말, 양 따위의 가축을 기르는 일을 경영함.", + "value": "900", + "points": 1, + "category": "OneAnswer", + "item": "문구 (목축업)/③ 크기 (9pt)" + }, + "28": { + "path": "//P[TEXT[CHAR[contains(text(), '{searchValue}')]]]//AUTONUMFORMAT/@Type", + "searchValue": "소나 말, 양 따위의 가축을 기르는 일을 경영함.", + "value": "Digit", + "points": 2, + "category": "OneAnswer", + "item": "문구 (전당)/④ 각주 번호모양", + "desc": { + "가,나,다": "HangulSyllable", + "1,2,3": "Digit", + "1),2),3)": "Digit", + "갑,을,병": "DecagonCircle", + "A,B,C": "LatinCapital", + "a,b,c": "LatinSmall", + "①,②,③": "CircledDigit", + "一,二,三": "Ideograph", + "㉠,㉡,㉢": "CircledHangulJamo", + "ⓐ,ⓑ,ⓒ": "CircledLatinSmall", + "i,ii,iii": "RomanSmall", + "I,II,III": "RomanCapital", + "甲,乙,丙": "DecagonCircleHanja", + "+,++,+++": "UserChar", + "정답에 맞는 값 value에 입력": "" + } + }, + "29": { + "path": "boolean(//CHAR[contains(text(),'Tourism')])", + "ignoreWord": "Tourism", + "value": true, + "points": 3, + "category": "Boolean", + "item": "Tourism/영단어 미입력, 대소문자/오타 시 전체 감점", + "desc": "유사도 검사를 진행하지 않고 영단어가 모두 일치해야 하므로 xpath구문 내 단어도 수정필요" + }, + "30": { + "path": "//CHAR[contains(text(),'{kor}')][contains(text(),'{chn}')]", + "word": [ + ["해변", "海邊"], + ["특산물", "特産物"], + ["조화", "調和"], + ["기여", "寄與"], + ["전통", "傳統"] + ], + "value": 10, + "points": 10, + "category": "Hanja", + "item": "① 해변(海邊), ② 특산물(特産物), ③ 조화(調和), ④ 기여(寄與), ⑤ 전통(傳統)" + }, + "31": { + "path": "boolean(//CHAR[contains(translate(text(), ' ', ''),'다양한나')])", + "value": true, + "points": 3, + "category": "Boolean", + "item": "문구 (…청정 자연에서 자생하는 다상한 나물도…)>'상' → '양' 글자바꿈" + }, + "32": { + "path": "boolean(//CHAR[contains(translate(text(), ' ', ''),'답게만들')])", + "value": true, + "points": 3, + "category": "Boolean", + "item": "문구 (…강원도의 자연경관을 더욱 만들고, 아름답게 해안 지역은…)>'만들고, / 아름답게' 순서바꿈" + }, + "33": { + "path": "//TEXT[CHAR[contains(text(),'{searchValue}')]]/@CharShape", + "searchValue": "강원도 지역별 면적(단위:%)", + "value": "돋움체", + "points": 1, + "category": "FontName", + "item": "제목 문구 (강원도 지역별 면적(단위:%))/① 글씨체 (돋움체)" + }, + "34": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]/@Height", + "searchValue": "강원도 지역별 면적(단위:%)", + "value": "1200", + "points": 1, + "category": "OneAnswer", + "item": "제목 문구 (강원도 지역별 면적(단위:%))/② 크기 (1200)" + }, + "35": { + "path": "//CHARSHAPE[@Id=//TEXT[CHAR[text()='{searchValue}']]/@CharShape]", + "searchValue": "강원도 지역별 면적(단위:%)", + "value": "BOLD", + "points": 1, + "category": "FontAttribute", + "item": "제목 문구 (강원도 지역별 면적(단위:%))/③ 진하게" + }, + "36": { + "path": "//PARASHAPE[@Id=//P[.//CHAR[text()='{searchValue}']]/@ParaShape]/@Align", + "searchValue": "강원도 지역별 면적(단위:%)", + "value": "Center", + "points": 1, + "category": "OneAnswer", + "item": "제목 문구 (강원도 지역별 면적(단위:%))/④ 정렬 (가운데 정렬)" + }, + "37": { + "path": "//BORDERFILL[@Id=//TABLE/ROW[1]/CELL/@BorderFill]/FILLBRUSH/WINDOWBRUSH/@FaceColor", + "path2": "//BORDERFILL[@Id=//CELLZONE[@StartRowAddr='0' and @EndRowAddr='0' and @StartColAddr='0' and @EndColAddr=(ancestor::TABLE[1]/@ColCount)-1]/@BorderFill]/FILLBRUSH/WINDOWBRUSH/@FaceColor", + "value": "87,215,182", + "points": 2, + "category": "Color", + "item": "위쪽 제목 셀/① 색상(RGB:87,215,182)" + }, + "38": { + "path": "//CHARSHAPE[@Id=//TABLE/ROW[1]/descendant::TEXT/@CharShape]", + "value": "BOLD", + "points": 1, + "category": "FontAttribute", + "item": "위쪽 제목 셀/② 진하게", + "desc": "글자 속성이라 CELLZONE으로 적용 되지 않음" + }, + "39": { + "path": "//BORDERFILL[@Id=//TABLE/ROW[1]/CELL/@BorderFill]/BOTTOMBORDER/@Type", + "path2": "//BORDERFILL[@Id=//CELLZONE[@StartRowAddr='0' and @EndRowAddr='0' and @StartColAddr='0' and @EndColAddr=(ancestor::TABLE[1]/@ColCount)-1]/@BorderFill]/BOTTOMBORDER/@Type", + "value": "DoubleSlim", + "points": 2, + "category": "TableAnswer", + "item": "제목 셀 아래선/① 이중실선" + }, + "40": { + "path": "//BORDERFILL[@Id=//TABLE/ROW[1]/CELL/@BorderFill]/BOTTOMBORDER/@Width", + "path2": "//BORDERFILL[@Id=//CELLZONE[@StartRowAddr='0' and @EndRowAddr='0' and @StartColAddr='0' and @EndColAddr=(ancestor::TABLE[1]/@ColCount)-1]/@BorderFill]/BOTTOMBORDER/@Width", + "value": "0.5mm", + "points": 2, + "category": "TableAnswer", + "item": "제목 셀 아래선/② 0.5mm" + }, + "41": { + "path": "//TABLE//TEXT/@CharShape", + "path2": "//FONTFACE[@Lang='Hangul']/FONT[@Id=//CHARSHAPE[@Id=//TABLE/ROW/descendant::TEXT/@CharShape]/FONTID/@Hangul]/@Name", + "value": "굴림", + "points": 1, + "category": "TableFontName", + "category_tmp": "FontName", + "item": "글자모양/① 글씨체 (굴림)", + "desc": "테이블 폰트명 문항은 테이블의 모든 셀이 정답폰트와 일치해야 함, 하나만 일치해도 정답으로 채점할 경우 category값을 FontName으로 변경" + }, + "42": { + "path": "//CHARSHAPE[@Id=//TABLE//TEXT/@CharShape]/@Height", + "value": "1000", + "points": 1, + "category": "TableAnswer", + "item": "글자모양/② 크기 (1000)" + }, + "43": { + "path": "//PARASHAPE[@Id=//TABLE/ROW//P/@ParaShape]/@Align", + "value": "Center", + "points": 1, + "category": "TableAnswer", + "item": "글자모양/③ 정렬 (가운데 정렬)" + }, + "44": { + "path": "boolean(//TABLE[1]/ROW[last()]/CELL[position()=last()]//FIELDBEGIN[starts-with(@Command, '={option}')]) and boolean(//TABLE[1]/ROW[last()]/CELL[position()=last()-1]//FIELDBEGIN[starts-with(@Command, '={option}')])", + "option": "AVG", + "value": true, + "points": 4, + "category": "Boolean", + "item": "블록 계산식/AVG", + "desc": "option값에 합계는 SUM / 평균은 AVG" + }, + "45": { + "chart_xpath": "", + "chart_type": "묶은 가로 막대형", + "value": true, + "points": 2, + "category": "ChartType", + "item": "① 종류 (묶은 가로 막대형)", + "desc": "chart_type을 입력받아 차트타입에 맞는 xml요소가 있는지 내부적으로 검사, chart_type만 한글로 입력해주면 된다. (공백무시)" + }, + "46": { + "chart_xpath": "//c:valAx/c:majorTickMark/@val", + "value": "out", + "points": 2, + "category": "ChartOneAnswer", + "item": "② 값 축 주 눈금선", + "desc": "chart xml파일에서 답안을 가져오는 문항은 path키값 대신 chart_xpath키값을 이용해 xapth구문을 작성한다" + }, + "47": { + "path": "//OLE[@BinItem=//BINITEM[@Format='OLE']/@BinData]//SIZE/@Width", + "value": "80", + "points": 2, + "category": "mmSize", + "item": "③ 크기-너비 (80 mm)" + }, + "48": { + "path": "//OLE[@BinItem=//BINITEM[@Format='OLE']/@BinData]//SIZE/@Height", + "value": "90", + "points": 2, + "category": "mmSize", + "item": "④ 크기-높이 (90 mm)" + }, + "49": { + "chart_xpath": "boolean(//c:chart and not(//c:pt[not(ancestor::c:tx)]/c:v[text()='합계' or text()='평균']))", + "value": true, + "points": 2, + "category": "Boolean", + "item": "⑤ 차트 데이터(표에서 블록계산식을 제외한 나머지 값만 이용)", + "desc": "차트가 존재하고 블록계산식(합계, 평균) 데이터가 없는 경우 정답 처리" + }, + "50": { + "chart_xpath": "//a:t[text()='{searchValue}']/ancestor::a:r//a:ea/@typeface", + "searchValue": "강원도 지역별 면적", + "value": "바탕체", + "points": 1, + "category": "OneAnswer", + "item": "제목 문구 (강원도 지역별 면적)/① 글씨체 (바탕체)" + }, + "51": { + "chart_xpath": "//a:t[text()='{searchValue}']/ancestor::a:r/a:rPr/@sz", + "searchValue": "강원도 지역별 면적", + "value": "1300", + "points": 1, + "category": "OneAnswer", + "item": "제목 문구 (강원도 지역별 면적)/② 크기 (1300)" + }, + "52": { + "chart_xpath": "//a:t[text()='{searchValue}']/ancestor::a:r/a:rPr/@{option}", + "option": "b", + "searchValue": "강원도 지역별 면적", + "value": "1", + "points": 1, + "category": "OneAnswer", + "item": "제목 문구 (강원도 지역별 면적)/③ 기울임", + "desc": "option값 - 기울임(Italic):i / 굵게(Bold):b" + }, + "53": { + "chart_xpath": "//c:catAx/c:txPr//a:ea/@typeface", + "value": "돋움", + "points": 1, + "category": "ChartOneAnswer", + "item": "X축/① 글꼴 (돋움)" + }, + "54": { + "chart_xpath": "//c:catAx/c:txPr//a:defRPr/@sz", + "value": "900", + "points": 1, + "category": "ChartOneAnswer", + "item": "X축/② 크기 (9pt)" + }, + "55": { + "chart_xpath": "//c:catAx/c:txPr//a:defRPr/@{option}", + "option": "i", + "value": "1", + "points": 1, + "category": "ChartOneAnswer", + "item": "X축/③ 기울임", + "desc": "option값 - 기울임(Italic):i / 굵게(Bold):b" + }, + "56": { + "chart_xpath": "//c:valAx/c:txPr//a:ea/@typeface", + "value": "돋움", + "points": 1, + "category": "ChartOneAnswer", + "item": "Y축/① 글꼴 (돋움)" + }, + "57": { + "chart_xpath": "//c:valAx/c:txPr//a:defRPr/@sz", + "value": "900", + "points": 1, + "category": "ChartOneAnswer", + "item": "Y축/② 크기 (9pt)" + }, + "58": { + "chart_xpath": "//c:valAx/c:txPr//a:defRPr/@{option}", + "option": "i", + "value": "1", + "points": 1, + "category": "ChartOneAnswer", + "item": "Y축/③ 기울임", + "desc": "option값 - 기울임(Italic):i / 굵게(Bold):b" + }, + "59": { + "chart_xpath": "//c:legend//a:ea/@typeface", + "value": "돋움", + "points": 1, + "category": "OneAnswer", + "item": "범례/① 글꼴 (돋움)" + }, + "60": { + "chart_xpath": "//c:legend//a:defRPr/@sz", + "value": "900", + "points": 1, + "category": "OneAnswer", + "item": "범례/② 크기 (9pt)" + }, + "61": { + "chart_xpath": "//c:legend//a:defRPr/@{option}", + "option": "i", + "value": "1", + "points": 1, + "category": "OneAnswer", + "item": "범례/③ 기울임", + "desc": "option값 - 기울임(Italic):i / 굵게(Bold):b" + } + } +}