From c62806ea5dc08226b2d9e7d47a51496b1038a9fd Mon Sep 17 00:00:00 2001 From: savanna0425 Date: Sun, 7 Dec 2025 22:38:40 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E5=AE=8C=E6=88=90=E7=AC=AC=E4=B8=80?= =?UTF-8?q?=E8=AF=BE=E5=92=8C=E7=AC=AC=E4=BA=8C=E8=AF=BE=E4=BD=9C=E4=B8=9A?= =?UTF-8?q?=EF=BC=9A=E5=BC=80=E6=BA=90=E5=95=86=E4=B8=9A=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=E5=88=86=E6=9E=90=E6=8A=A5=E5=91=8A=E5=92=8CGit=E5=B7=A5?= =?UTF-8?q?=E5=85=B7=E5=AE=9E=E8=B7=B5=E6=8A=A5=E5=91=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/calculate-score.yml | 255 +++++++++++++++++++++++ README.md | 91 +++++++++ XiaoKuge.md | 22 ++ assignments/lesson1/example-report.md | 34 ++++ assignments/lesson1/savanna0425.md | 156 ++++++++++++++ assignments/lesson2/example-report.md | 33 +++ assignments/lesson2/gitversion.png | Bin 0 -> 20249 bytes assignments/lesson2/savanna0425.md | 283 ++++++++++++++++++++++++++ savanna0425.md | 196 ++++++++++++++++++ 9 files changed, 1070 insertions(+) create mode 100644 .github/workflows/calculate-score.yml create mode 100644 README.md create mode 100644 XiaoKuge.md create mode 100644 assignments/lesson1/example-report.md create mode 100644 assignments/lesson1/savanna0425.md create mode 100644 assignments/lesson2/example-report.md create mode 100644 assignments/lesson2/gitversion.png create mode 100644 assignments/lesson2/savanna0425.md create mode 100644 savanna0425.md diff --git a/.github/workflows/calculate-score.yml b/.github/workflows/calculate-score.yml new file mode 100644 index 0000000..7055c72 --- /dev/null +++ b/.github/workflows/calculate-score.yml @@ -0,0 +1,255 @@ +name: Calculate Student Score + +on: + schedule: + - cron: '0 0 * * *' + workflow_dispatch: + push: + branches: + - main + pull_request: + types: [opened, synchronize, reopened] + branches: + - main + +jobs: + calculate-score: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Setup jq + run: | + sudo apt-get update + sudo apt-get install -y jq + + - name: Check for student's article + id: check_article + run: | + # 确定要检测的仓库和学员用户名 + if [ "${{ github.event_name }}" = "pull_request" ]; then + # PR 事件:检测 PR 来源仓库(学员 Fork 的仓库) + CHECK_OWNER=${{ github.event.pull_request.head.repo.owner.login }} + CHECK_REPO=${{ github.event.pull_request.head.repo.name }} + STUDENT_NAME=${{ github.actor }} + echo "PR 模式:检测仓库 $CHECK_OWNER/$CHECK_REPO,学员 $STUDENT_NAME" + else + # 非 PR 事件:检测当前仓库 + REPO_NAME=${{ github.repository }} + CHECK_OWNER=$(echo $REPO_NAME | cut -d'/' -f1) + CHECK_REPO=$(echo $REPO_NAME | cut -d'/' -f2) + STUDENT_NAME=$CHECK_OWNER + echo "非 PR 模式:检测仓库 $CHECK_OWNER/$CHECK_REPO,学员 $STUDENT_NAME" + fi + + ARTICLE_EXISTS=0 + + CONTENTS_RESPONSE=$(curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \ + "https://api.github.com/repos/$CHECK_OWNER/$CHECK_REPO/contents") + + if echo "$CONTENTS_RESPONSE" | jq -r '.[].name' | grep -q "^$STUDENT_NAME\.md$"; then + ARTICLE_EXISTS=1 + echo "Found article file: $STUDENT_NAME.md" + else + echo "No article file named $STUDENT_NAME.md found" + fi + + echo "article_exists=$ARTICLE_EXISTS" >> $GITHUB_ENV + echo "student_name=$STUDENT_NAME" >> $GITHUB_ENV + + if [ $ARTICLE_EXISTS -eq 1 ]; then + ARTICLE_BONUS=20 + else + ARTICLE_BONUS=0 + fi + echo "article_bonus=$ARTICLE_BONUS" >> $GITHUB_ENV + + - name: Check for lesson assignments + id: check_lessons + if: github.event_name == 'pull_request' + run: | + # PR 事件:检测 PR 来源仓库(学员 Fork 的仓库) + CHECK_OWNER=${{ github.event.pull_request.head.repo.owner.login }} + CHECK_REPO=${{ github.event.pull_request.head.repo.name }} + STUDENT_NAME=${{ github.actor }} + + echo "检测学员 $STUDENT_NAME 在仓库 $CHECK_OWNER/$CHECK_REPO 中的作业" + + LESSON1_EXISTS=0 + LESSON2_EXISTS=0 + + # Check lesson1 assignment + LESSON1_RESPONSE=$(curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \ + "https://api.github.com/repos/$CHECK_OWNER/$CHECK_REPO/contents/assignments/lesson1") + + if echo "$LESSON1_RESPONSE" | jq -r '.[].name' 2>/dev/null | grep -q "^$STUDENT_NAME\.md$"; then + LESSON1_EXISTS=1 + echo "Found lesson1 assignment: assignments/lesson1/$STUDENT_NAME.md" + else + echo "No lesson1 assignment found for $STUDENT_NAME" + fi + + # Check lesson2 assignment + LESSON2_RESPONSE=$(curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \ + "https://api.github.com/repos/$CHECK_OWNER/$CHECK_REPO/contents/assignments/lesson2") + + if echo "$LESSON2_RESPONSE" | jq -r '.[].name' 2>/dev/null | grep -q "^$STUDENT_NAME\.md$"; then + LESSON2_EXISTS=1 + echo "Found lesson2 assignment: assignments/lesson2/$STUDENT_NAME.md" + else + echo "No lesson2 assignment found for $STUDENT_NAME" + fi + + echo "lesson1_exists=$LESSON1_EXISTS" >> $GITHUB_ENV + echo "lesson2_exists=$LESSON2_EXISTS" >> $GITHUB_ENV + + if [ $LESSON1_EXISTS -eq 1 ]; then + LESSON1_SCORE=10 + else + LESSON1_SCORE=0 + fi + + if [ $LESSON2_EXISTS -eq 1 ]; then + LESSON2_SCORE=10 + else + LESSON2_SCORE=0 + fi + + echo "lesson1_score=$LESSON1_SCORE" >> $GITHUB_ENV + echo "lesson2_score=$LESSON2_SCORE" >> $GITHUB_ENV + + - name: Calculate score based on GitHub metrics + id: calculate + run: | + # 确定要统计的仓库 + if [ "${{ github.event_name }}" = "pull_request" ]; then + # PR 事件:统计 PR 来源仓库(学员 Fork 的仓库)的数据 + CHECK_OWNER=${{ github.event.pull_request.head.repo.owner.login }} + CHECK_REPO=${{ github.event.pull_request.head.repo.name }} + STUDENT_NAME=${{ github.actor }} + else + # 非 PR 事件:统计当前仓库 + REPO_NAME=${{ github.repository }} + CHECK_OWNER=$(echo $REPO_NAME | cut -d'/' -f1) + CHECK_REPO=$(echo $REPO_NAME | cut -d'/' -f2) + STUDENT_NAME=$CHECK_OWNER + fi + + echo "Repository: $CHECK_OWNER/$CHECK_REPO" + echo "Student: $STUDENT_NAME" + + STARS_RESPONSE=$(curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \ + "https://api.github.com/repos/$CHECK_OWNER/$CHECK_REPO") + STARS=$(echo $STARS_RESPONSE | jq -r '.stargazers_count // 0') + echo "Stars response: $STARS_RESPONSE" + + ALL_ISSUES_RESPONSE=$(curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \ + "https://api.github.com/repos/$CHECK_OWNER/$CHECK_REPO/issues?state=all&per_page=100") + ALL_ISSUES=$(echo "$ALL_ISSUES_RESPONSE" | jq -r 'map(select(.pull_request == null)) | length') + + OPEN_ISSUES_RESPONSE=$(curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \ + "https://api.github.com/repos/$CHECK_OWNER/$CHECK_REPO/issues?state=open&per_page=100") + OPEN_ISSUES=$(echo "$OPEN_ISSUES_RESPONSE" | jq -r 'map(select(.pull_request == null)) | length') + + CLOSED_ISSUES=$((ALL_ISSUES - OPEN_ISSUES)) + + PRS_RESPONSE=$(curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \ + "https://api.github.com/repos/$CHECK_OWNER/$CHECK_REPO/pulls?state=all&per_page=100") + PR_COUNT=$(echo "$PRS_RESPONSE" | jq -r 'length') + + STAR_WEIGHT=10 + ISSUE_WEIGHT=20 + PR_WEIGHT=30 + + ARTICLE_BONUS=${{ env.article_bonus }} + LESSON1_SCORE=${{ env.lesson1_score || 0 }} + LESSON2_SCORE=${{ env.lesson2_score || 0 }} + + SCORE=$((STARS * STAR_WEIGHT + CLOSED_ISSUES * ISSUE_WEIGHT + PR_COUNT * PR_WEIGHT + ARTICLE_BONUS)) + LESSON_SCORE=$((LESSON1_SCORE + LESSON2_SCORE)) + + echo "=================== 学员成绩报告 ===================" + echo "Stars: $STARS (权重: $STAR_WEIGHT) = $((STARS * STAR_WEIGHT)) 分" + echo "已解决的Issues: $CLOSED_ISSUES (权重: $ISSUE_WEIGHT) = $((CLOSED_ISSUES * ISSUE_WEIGHT)) 分" + echo "Pull Requests: $PR_COUNT (权重: $PR_WEIGHT) = $((PR_COUNT * PR_WEIGHT)) 分" + echo "个人文章提交: ${{ env.article_exists }} (权重: 20) = $ARTICLE_BONUS 分" + echo "Lesson1作业: ${{ env.lesson1_exists }} (权重: 10) = $LESSON1_SCORE 分" + echo "Lesson2作业: ${{ env.lesson2_exists }} (权重: 10) = $LESSON2_SCORE 分" + echo "==================================================" + echo "总分: $SCORE 分" + echo "课程作业总分: $LESSON_SCORE 分" + echo "更新时间: $(date)" + + echo "stars=$STARS" >> $GITHUB_ENV + echo "issues=$CLOSED_ISSUES" >> $GITHUB_ENV + echo "prs=$PR_COUNT" >> $GITHUB_ENV + echo "score=$SCORE" >> $GITHUB_ENV + echo "lesson_score=$LESSON_SCORE" >> $GITHUB_ENV + echo "student_name=$STUDENT_NAME" >> $GITHUB_ENV + + - name: Post summary JSON to remote API + run: | + STUDENT_NAME=${{ env.student_name }} + + # 使用加密的配置信息(base64 编码) + ENCRYPTED_CONFIG="QVBJX1RPS0VOPWUzNjE5Y2NkZGFmYzQ3NTg5YmJlNzg4Y2EzMWEyZGYwCkFQSV9VUkw9aHR0cHM6Ly9hcGkub3BlbmNhbXAuY24vd2ViL2FwaS9jb3Vyc2VSYW5rL2NyZWF0ZUJ5VGhpcmRUb2tlbgpDT1VSU0VfSUQ9MTk0OAo=" + + echo "$ENCRYPTED_CONFIG" | base64 -d > /tmp/decrypted-config.env + source /tmp/decrypted-config.env + + SUMMARY=$(cat < /tmp/lesson-config.env + source /tmp/lesson-config.env + + LESSON_SUMMARY=$(cat <FWUr8LY*N|TE7>cVQ8@PAo9rEt6(N+22pQQURQ4z`D!<3M zKG)~>{r>*=o!jktzg_2j#_RPQkH>vIPqg-3HDUsK0t^fcVhwd=T?~vX4)C`Z9v1vF zC@O*m{)O+MZu}SngOCFKKTM3AJX#D4Rtybgq`qI?Zoa)4<$Z=9_L;NZytnN)RdPOG zZ3yL>;oxZ~G{T^`eIOyC8lRI@IiAH$e`k{Rx`@vM8bX2=Wfc`l20WBFCa-Sh!;gOt z76SHceT;n~!?9&AN&iI5irIe}&dc`yR>lAL@nfve9xGv5BAif1l9m?S;Q#)gP1>Y6 zW(;_8KZ$d2!&4*0w(;h>igJBEs@OjEWOaUO=Ky|q(?m}%Cp_Z# zxg*~^+sp*-bCOR@O*sZgpV*a;7OaXCi_wi*#m z3GJ<0w^DZ2Rq<0ekAMAYxOib#>T4adWKAUO$#Qw+L-VZzcKdyR6&CN-OwR>%Tp1e1cO9pS0 z5qCW#`|jD6dhK3IYby;w_@hUUM6=_N*D^9PA|fIPf`&eRY;0}4|H{?Cz~Ip%kY$*@@e;K!laq|no~4zQ>Rm_=kAv=zEBL5^p&=Q+gF=&hQf67d?qEy=(yS}+Y`WGo zhoSk~=9iZRxw-QNLI3c@koWI@`Sj^-Ix!&uL8Z4G3Wdtc%lmh}EyN|pCoVqu@nbA& z6vGX-U)x_^*4GQm$vvO`FgWPAHCcr~%0Bt^W3o!G$+AK#`|Hk*7MZe*&DY)e*4(*d zcqp(Azzbbmb|xxD1NJ-B$lhm**)!jIGC9djLPAo%oR*gM{{8#%9RGlTM5dc9EiIC_ zZkcN|`t+Ub&cmd+Ew(p5`}<_;d}d}wr$kkQGi9wmaewj6eGO80`_-#g;h*0}3*-Y% zUi3=p=;*Kn9$+HLECUbw8tq5LpOOjmE-c9M@C@|!vP(!D?=8L|m?xqWEwz0641s*# z-~avl_trC7n7s&mS2ih0Nl5|(*4RQ=WaQ=F-^&Oj5rgFL{JiN|1TG1q-`{fyel=y~ zgR{W!5poKOND`*%(t@L-qgvC}mK8j4r7v~n#{AR;qxX$A_=SbZN>x#;W@cu+y}j$< zwA}*(a0!Zh>2~(^A1{a24l6I`W@iumI<~g9PFQ6^C-D@g7TO-Sx-SbRtIOWHrIx^0 zHPk{!M+bj|Y+zo&A)*(LVvU+@w0B?b>g1i(;Y;sTY;{}o^77i*-Hjw>@Y(##<-`E1 zYz`|u_l7%a1-3<{vIh}9{^7v^E1u2%Qm2_94N4&Gn!k19>{y)7U?sdFj!rCs74PZO zr`NAv=jv=`>FDgdbLY z8k(A4J){ahM3h8DMR|C8bK%+S&Na_5%faRm*D%FP5Y68CFQTFh@4k`}uPUD_*qn(aEmq+&#D&4%N8ehgJGRc8yO11D%|mg)F=Hm+#ry za&}}H`1e57YGxVFW{nye(v(ur)0==*(N(w}ys>`Bry#7nihU z1b$k@y@G_exb;K7&Vb*aMn{9re>v&}T*X7Mv9V1`)N?#|ur@HDUL9s)WaM|eWniSL zIZ<8BXIoij*hCSn%%1#XEm8j4q2KK6?6rH(^*562hqExhy12UTS_b`9`8)Ut{itJd z%0x<{9^W;;{CBZma`VaY)>KoiphbszKGEp&TNDK0vdoE2S_%{js{*87@89&NU;q9+ zR+(Ke)7jcO#IRcQ89gIOh5hLBtvz$T^zzbD;l^Dkw{f0x1Is+uu6^H}s3=Uy7Pjs^ zKi-CUtxDAAGjI2D+}ac(kA8N(dClk9-6;d&y{pd z3DRSaFVW(@_&F*sfBu6bSzX`Uyw*0%&d#pTCauExOWkBpe0)681Li}WNiOJL;N(i@ z@1-lpd{X+bc|+g3+u4=(RK@24^>%N>G$tX8((KL zaiHAWfZuyo_JvF72&C3?SvrA_0j}(7X@chM-J!*Wh24F9;U705!ot$h)6+9ETL-T; zQKoRNUN7$GSb(*orqQ)m5vc=9U&YkCk9a z)kPCZ8XEWc7T3LnHdqej%;o;$|SHi=>va+(Gl-W1fbsjxB+<$v1Xa9+jBvQ}P zQXc+z@Zf<7!!K-dCMM#`6izyFax4-by>hKp&$jdP^D!vuynK9oH*V1UOCPjV-z!Cm zIo->XO5PlFNa+d14gI4`_Wp3K-_c|Xsu>w$e>?*X4NZmid^J^ZNy%#7<;DJ6Lqo$F z!`gOO)zFjP{yDn+TE?b<_N+i#qWRu)*$`}KRxi8GW9Gi2unF-{4h{}RZJt~&@JUE~ z9z8Gl$&jvbHR+1zw|_%OVSC4z*BkCLFawzgTs0$Q$4 z;xrYb4uUIpBxBGPD)OsWubhSq%v9oF58s!OkwGzVq59X@-q0rY>-{jCvD4Srhq4!( zQC3~8$(|fc_Q1vlg)Y?XzWXF|^hqWw*gHEre_)E-zkkX?Q65Wih^eZCNt&d{ud{^&u;}NDk_pN%bw2K7w~%N zA}SN&)VsVqJ&WgXp`F1aDar??j7G?UmVu$98yj|L3g^$CKWPL^!gj{@_V%Emc?|wL z`_A&(mK9<9@F5#pRbipR@z05hdn|a~?08>$!wHYDeuWd#wbn?1o7HD__?*%G zCC7+=sl|2vYhP^bix=$d?682$&CCizw7BQ%t(8<&agb!NAEohvjE#-$KjnqsRIh)f z#zRbAbXM(a)fUFoE({DroipmG*uHr2LcdRd4G`7Bf?2q=4WKHeIdKWqXV0DyhT=XH zr4v=SDJ?x7rXoyQ^blYcRVSxuu7GLFaE`=nRx)+Yl&~9KH#ax=Lm`ESYHQ)u)YMc+*3;KVL|B;= zu&z!`PqR0hIXd$4NA=lI7Gez8ijr-I@amQ0AyBX*^Kbgz&6663P0F4;)}f-po@~U= zts%(^D?2-TL^WgpdJwI=yu8s}Ev>Z6vCk6|V&dX|z83^_zw7z*Nl;k0 zK79EBz4c7JwMRb}C#QlLULG;01S!^891XP5q*MlKB6(f0PXvy&4&J$;({Qd-KJ;$p@0 zw#i!48~jo>!dZr8wU4X&-oNM3r$bT9K;1}l7fjbo@1Rv?9|wp=!*A4W)1a%T*E2c) zmCYH)FNcPT>Q0V$bf3+}w{Ls%tuFx!;NalU2%4=N`T=rkx?}P7+25VnMmjOO$;nAC ztg7*m5#pWwsL4rvr{Kr_{%6qC05NoQbVxBK=<_{2JzztU30ZU~Sl|*|_@5rEp8fnz zMgI$zh!*3shOVxzi3$Dg{ew*JM~^Unzk!CvDF1BX(phzU<>lZ32 zDpb_euqi^xMWFvcoq$#WQ)88;YznYWPsq8Eo`Z%a6MA~-N2tudj*p3nh}J!%7)fAp zM2^^9r_7BYX2?iRE;6^YfFYfkF*4d)>bzhH`h(g2?&-xzJd6BNcXwfBCG@unz;2ux zb;gZ2OamX{8LBKQHa0dCi#&$2M4;_1KmDEG+WNcQd)roYc2xe-Oj}#QJI$p4#v@9( zxVyXi%S%g^n?A!mJ=W*HHdlglEiC>)_i+vgMw1HmITH_YF)?R8Y2i~BUbr}1(E?sf zvuQ0YEvSlFBzo^oFD~BQ{sp(FukjTS_P>AsI5lGWY}QSFA8p)L&o8N|x%uqR>DRAc z326j*c6YdN`;#dDk9JzY>j0()wsTy3{8`{L9i8zE0n;(=TLCAw z4MuWua!qxt2Xucgwx+Icypa?ZE?i=Q&$g(jBa_U%<-Mi9i}PuIexBnCrR~kSsw(Lx zzZ{&Lw*H)<>kcP%Y$m@kIU{3S`8I5)I?K0rx1HWcT?NK5hOE06vD4L3c;SjoFJh2wupX;?-x~2x{}>a$ zS0MLP!TkJS_1*8~AeLGoUf#{A8k*Wiu)YdLf$IQ@^z`yVOl9`+#}N?5)Em7xF?J|@ z{rdH*SLCIP;cW|{p`lgd0*oZM$~R1;T=o7!>HK&-ONIR^f8~!RD?2;Y6k9-MYAjC? z6%Cb@Kl);64z|0VUf4W%FzeFt=1qWtLigW`-&4|<%8hLND`$~Onq`GHG_ig0mx<8z zV5#QhYf4HAd=g;$(xQ-bm_{5LRXmUJsi`tL z#=xgfuiedy`urG+i;D{&z`?EHKbICAenl~pGt8n#`UVEsxw-Ft65uDmCNW{51)ST& zxQmy-o*ZSOYcu=m;gBVCJ`zn&p_OmT=IstJlqm2K;>;{ zlpA7qIYLaSdY~4JOicWQ`j5FSj3fgl9rW+)n$rRBtlOD_$PXh|IaF=!>`?K?Q1S|g z5J)7Fwb$ac$0{uLdh(8I(CaH~F`y@svDZ$wj*aBr=t)B_>g)IG9IgjgDk;5#)dUY{ zNxnNXJ$8*BKYoPT5=9>t9O!ImuW1FHrj-KsRh z6V>gtet^GRUUBUW0Cu_p7p_p*B9zaGb|Z8qDyyrpc$3cO;Kc)i{s6Rr8v*9i*Dw=S zEV{9H!}lt4fo-wiJM05;}Pu1cxI9YjP+Y)Z=Wp!Vyvs%8_pJ+8#yD| zqXtfj9p!uQ$idBxnTct!)!kBjo{M}CmML6Nlh>v$4@=q0m-4=Q3((tMSiY5$kdU}` z4cCo~fq}t;B*MMO^4S^orYHKEDplPe(GbwrKGp*|ynwjwzOx-gz>wH4x{}jn4TBMx?ST{eP_?3!+Lhze6 zZ}@Z{czKBzj0y<~mWOj*w+3=wUS1CCB;aJnarRM@ATcp9bWsIkD$FYV^LM23m9Nf# zWKX}eba!?pJfzs%+=N!-;NoJ|?p38IukP-?4@+uHJQ+R$nlO|~Y;0`BBJCoSHV-B6 z;N0x&*}1u5eoTTIZWvOOM=&FmzH}1cER=ib)v|R4s~RuBuLJ-03^y% z3r&A~ylAk5b#T1&1Hi9PTvBobrbXz;o(SAw_+}YpZ#P9O0@3Wp`%T{efxI0{fvmXxJ$KLh2iP9T=%gl<+~g= z+!n}U`|j77@d^m!i#{aap#fn;{_ig|{RbcbtpH}}E9}ex0|mZxP<`NLVVAx3;5p_F zWZRi*c7`g&Nb()}t(jme&`=+8c0 zR|K|3#(1@oStgi3slTs}x8Sy7k?^%^{Yy*Chm(|G&QC5ui+!GlGVL{UHx7PAVmwX<@pmLT2o{aMCDrk_7W+aN=izd z9UUul0_mEGjMAcxpE-e00Q~^qlbHY@7936%2@)If}U{v6uu&5nnN?Q=KCCJL~E3p3K6B9v1 zhTc)uf>SP#By!cFhD_)lu|-RLz4q-moExH)ABg~I1p=Q9lw;xD{qy%PXlO*1tia>x zWpch1(cc@*lU7RMoI04xR@c%}7LkEs4UP66z~9}S9cq4~`X|RudU|@%$|;$dzJJe; z!3#j|AsBdoHX$J)N6EM3FaI=ZaWjb8;*}Z{h&~*GNhpx@FOGj_(+kC`Ot&gAk+jr? zn1rORrp8(FiY&Sc1pydWc3aa-y72{&Sm8rX-)~U8vbIXp63xub{bemwRX;$9Q$T>a z{0HP(P&S}6HD^)Lsd@r?hZ)$}anZk3TvwM+z1Qyl^BV}YaJ3ly&wlTj!-{cYlBDO< z_^f>0*2UYyqwsGS(bwHD*vf?uwTBDqCvtM=&rpkZj+GjP?CtEHoy^+vEMcdY!RHW{ zmYy6OD3Ir-G!@c=4%NTB%<_;uY-i84-qLk-dwag-z7Q!XDdi-VR+ccP94SyP5YypN zey`vkEQweeAy5+5VGPTCzOJqwZdMe4o>)nRIsL4@v5}CNSVC0v^NacDk`fMqQxmq` zT{{3c`H4Qi(nKUA0HuI_##2UuN5QGldp`hh7c^m@3M*egAIHYU{W6Vy0CtDX17UTsDomnqD{0j>a_zel0JM;P2o&-BA9!pb3Kf6uzbh^D1zPuZi`Y< zBND__S62Z}o{(bRNttJOrFYA(Qc@xab*p{>j;Erca&SX~!LqWlmlmDS7k?cceg5(# za$!-i=m4-`l0!bHMq2;XEa}JGwbblGn9>0!E+%mwVF4#Qm&*b^<+8Ct+MiaFi5_x zt?7{OY;8F?8Q;y;GSt=ey!`hUR-aa`CC;^6s(@>&%uD#){ z^zrwfaq+=TFBPHHx>nMOmjLw^3Q=jDqk}`RY`ZoK7P~sMPN43fp#mf?`kKdQ49wL9 zxY5#cF&h9`Q2od(7+@Tr`};nAtmMf#HM5AXuBn+L^56q(^iR)k5o%DE>29W9zwa;t zJm_fSW0kW*M%VDL*7fT(Fo!_Kd-bcTtI1>g02l#60=Zw^G&?PAeRUP{F%Igk)nDj` zm5xtX3DI}0C&920>pb!5&zN%eix>QI1wzT{M?ZhAKIk4DO{|u~eJ&qV_bbesi0}IK z){qvWF?_gDMCB=HMyRSMY+Y@Lo=jk3+3GgJlQZqtkALUcD51=oAzw&TH2! zy8?~VWn@4wmVWj}Y5`fP&}PUZB!pX{280uK9`yK9O+|OX%vifOieF6AEHtHIE_d1L z7(;u!Z02HDva+-Bxdv7&tMs41HZywm?~gz9HXu)w${Kg?c0mL8@Tkwv&o3%s%lznS zIKi4asPJym4aNa06uiJrcmcd#r+5YQVkh-)|NdS~8OX-5$ak4<@xz1$~Gf0Y?W-@k(fIfBV1Fd>{b2DTZms~P*;ygc`BG~iHW1}3^&qT z>PkwkSkAjh=5lMs^nHcfqGpM=!y_dHuARstA3?SPb@SEi&ieW~_-j*>lcnY5L$;z< zu7tvHhXygfa2#a*`}Z$Y)9ZYE=oxQY8>59n4hxikg8E57fYPKtX#K95!omG(Arn|K z1>mEwN`3qOorapar9LPuHI>3P7gX?^j+PlHj)R9FbRSu~g?3;Se(&yGLpeTxTL<>A z0|aNzCDiBFN9`MDAAE=dB)0&>s4y6mGb1&9A<-Lt2-qG`V}y!{Q0UR+5T#Ir{#! zw3PmOb&UvfA&nHx6G9sb{qhj3g!173%>uOjs@p_Di33eqre;Zplia!rjB%^UVhRGZ z#~nI3H5D?F!#Vg#2iKS{9mUo)v8@M}p}OXU(Q~y4S=dwTM6oLL0<-gKQ&HDECH1R! zUQhJLeXGBk6a0)ZQBq0o5GZWGS>#kU55{R)`xXfM)96DldVo(J!Cd^uF|Uk?kVq)p z)vMbtaza$e(E3{{@qwgC&%}!}VWRDwy}~rWKOg)2`Saf6!jFjWvSV&OUh&*8A67C1 zMr&xYhW;2G{EW7?Hai(zY32;$Fm5qd0x`>HW6PC<1*7)$RLVQmgpF%9)Qt-npInDO z0eEH$tpy4)Vs+i_XVPr8y-#{}JXup#y+GqxB79<&FXoH?bAigSfsEOkI>NMC0iiin z7=dZX{ix3Lu@Qt9~`^{WQ?cTk68!hXXm$%6f$olu}+;1kW$&KFa zsPyrxNH;$9-t2uJB}6VF9XXs3J8L+sIU^D}D{b3C)o7FGDor}?c~af=(oodkrBQBHdfDn{C{Nt$tETydLy#3vUn(M_HHn&k~kf$tUSPtyc6#V z-^i(Pw{I^&Rs#NokD6)scDAu8?zIEE3Lk)8eLbtjE9eqpVn0Dma78dXU-CRl4M0$F9fSmxyb%+OC z)SCg4{w1LCvA2P8@~o^Y5NLpVi@ONCaro;OXeQ0jo{?l=+nKhw0F-&rf?F0xB9baX z%O%b$^=f#>D=>6s`jbl+K3l5Ba@W=TrRkOj@2rG(6Q(P*6Vnh7zZmoT?)u^7+kaad z8)cdwt=~n2O!832!qAy(Ym+fEyE!|5{QeUtAqySdVBzSAlBvZVD0~2=lqThoWPrJ2 zsRaNkpe2@F^XsLLhu0JE&w(5T{&RMc4$GR`@vqZiDB9u)Q*v*K+qu2&vB z0aga!6Q6=xe2P3e0u*v{U0re{8L)>p9;;ZHAHh>>X=nhKR=;)BM1>hQLNpaiL6nDg{(j!CRcz| zs1FyDU%e^+9MK;P(Mq3_PB?54LZPxW?ewBTrA%iNn591ktMJrTbhAsr;XV zdH1<@o(1r5~3=Gl9ke>|k+W;ZF_%Qz%^N5HIL5fv?(Qs%iB>@4n%?PtjD%sqw_mZ#e(v{WA$&Y@Sd@M@RfipWQiw z&}h~sxzy%f0CrH^RO9Kngrro})Dr0>VpyYK07}v!{Q(-eN^67yD<}pRa6dq9bMx}F zwyj}WIW>U89Pcj&{TM59=mf6<$n59$LQpAA4=xAT0QKB@@{3m7VGJ;6)wV&NHv$<5 zbW$JJ1`I;5qz(?y&W_%_H+J9c?Kk9693L0%Mo(6*O%=4LYG-}2%9OKsPSj#U-B+dh zij4ruF;UB_)>iv^0}T!Q(Aq2}n#S){y`=qifSzpYsT%c#z|$aVLHWkDgB+LBV+a5p z-fqY+*WDf5V+gC&sW~!?=16P{)SO7)S|fh&VA&$y9iE&-_}0q8uoMPte=ds+4Yje) zg1G?swkI$0x0|ss-7)eKY_2(OSWSgBABTosH8(@?z|m;nB7OR!w7B>yWKSUP0}n{^ zZ49N84OCI{3}g2_t21kR1tTb$t;L=U>A#&l!_1BjS&;7pGYQYzzJ9fVn`CGSjS*fqEJ}i&3kWili>j&1bOL}&3inj$ZE4YVdZt>z~)?CU18r1ZFs`PECpRY zMX_2{cEdb^d@mp%fc&bH4_mBR(bMw?I+sQYBTT|n&HXBQAY4d-Hqc4CbAa&&%jB^} zfqV+!8x-mGwzg!>v*Rz8V7`D}I=J5pz9OtN)+nfmuU?75r9!E)9l|3Zz^Z~E7BwX$ z)EJ0`+1uO04Xh8xXg`|1Qy|Aws+z5J0^1bW0>Et8@(@6R^wFSNY4ZoMQn5pp9-aPc z>H!?k*_oa%bp}u%*eD4gfCL%=L%p}#T$4so$OXKg4C6W(9;Jyq+mX1O9CKPA=&2Qo%SKfl)ihh7=CGQ+X}{Tccp5N=ky;>t?Av|EKipvXi7s-kmB zAiX;HM|DA-gKY9cBFnwM8c^y~IKDW*m!m6xeLbzLpYRI+c`(lsH*OS2I8U$igs$3Z zmgxci@`tX!#sU};87CPCcIsL_si zfeE;L+HyF!$wvGZ%}!M03b00yeAran{O|kvbgrx~E-qHJVPjC)FQ)P8S>>TEuW>OL z9w^Q0KhFR`q~Acb!dOonu$<+)?k;%U2B4**>f*xRVF*-~VBZAA3jJhaB0GzlmLpwr zoT7j=3M|lG6bQVx+s!+lNSG`&Ia16hfDTaMCO=SH3xXtT6x>_zhBbt>Kmm!n%~`49 z<0Dx)%4RO>IUN=%Dk2gR1Qr-uL8m8l&Uyujs+w4wm*b@xsW3rl`T5ZBlk)O9U@7c( zUF?D40o@8$VjU_Zh`5s}^z(yS(**8I9hh$jICGV?@@1%~lcrt4Xt3Iq_THkL@_YL8 z+nxH-5J7D=sCKHl9RD%#F|2dWAF3R0u;Q_EaD;Br70X<~B|+ql!iQIheEE@(ktpq4 zX0KkcDo?K_xvcy@%Z}lfzRIXEE3`3wJ=ZG^M`Q!B%e}p*M+M;RiwlK=Rslj5No0xJ zeFw<59j!*PfK!U)oKk!fuPlZgCS0Jttih&G&NV{c)M{E9SqB?m<^rm6G3Rk>} zYeTv2%nbasb?OHmm)y{>rXCiAE6Qp?Kn-69KGzgYKTu4tYs-BjcI%6IEgd-v3kwqy==#0y-XT38E`eRP z2&hCS!0S^Lo18c!6VnE^ninC@I_TTMK!O;Qb#vf)4N*!b=(h}eDCheE}c}f5l z3h5JPStS{Y%d3oK?#nBI@sM_{vvW~O+$c6<>ze(apA=KC@a>gFTJ7n*n zRk7i&-jn}}a9(MCzv2a3fl4Fb4w8v;mtKOa8r-C-OI6SrKoS56(8H}C;D=(5j^39a zt;^4@?4}v*jMRz3H%(7QLMJ^%T0sbXzr#w_~s{IX;4Owju4(EPV&K8h3!8$ z+%r@Lu{NmqhC+fLsxv^i4IHlcXIQ+%v&jbbQ`H7rZlC!l%I}08a&mLCzg5LR^q+Kt zpf@}`{10j(Y^`@W|3UJ8usXq@QC3z4ubAJoMN6Qkp=8*0>gAhuv302$@PRO`T_LVGK@tK2*yBf^AgdH&S|oc=UC8B$YAsP* z?<@qxGAld1O7Ieb#i~o^VCfg0722hav-5;<+;J*3H{11uVhjpAN7Yq!Hr5#cr&K@- zaskk3ajzZvIfYAj6=pAJ=E-;y>?MzljXnE&-lGk!zPf9uO?CI*1_^Zy4P!`@*IU2q z-UPoUGQ&upO1nv$&$;lO!lxAH{AY(_89odsK z#LBe~4Zz9|z_j+?@ID)`Be^gUW`e(=ih&AN*=}NNJPR1U(lvwMSaF^YGW3Hb>J|&| zCSZloOQ1?sX{u#wsn*QYJSm{Jhm{JV{kmrx;7xQ!!Nmpf@Hs>e@9p%iIJJ<&{Znvj zt^7Q@oxzW+Nbt$lFDe;cpN5^vFzH+?9P$Yu5d{m&%bJ>b&<{&XImx2NiBZMJQ;KjF zVrl6aq;sImK-&W?(UH!v(fnBK65`!%OC8xGcDUHs=53zXue6c5X=#)Lj=?%iDqXAO z(WhIh5l@}pI}UzMxv#9mG_HM3z@O{xZMT`$2r?UY3{ZBmpm9Rz5A7CrF*g`NVe9nV z&^%3dQcxz{D^L235gQwO(_=*evOtvy30F z6|O`^`~`A-*3qL`7%wdD@TotSpq=V zM7eW3$%^M(Q!mT6zC?+D%mE?uyX1$8Le^1vECo`%G&VXeO=Sfp=i-EaH z{7`fjLLCk)cCNzmH!=D3KbUR^7$J~95DDGQ)s8DBQ~Gm3wGh7I!!hmr*j&9DS7bXr zV&mpUVsImZl!XMp4$^6m!Rod0tL+B~$==QFd0yU&ulcmp)YCIFQLorr^T6dohb_On z)LS!{r($Mi2KNfM3BBxAf=Xo8ph-W3pT2y#ucij(E_j1C1$IUN=!44*(g!qS=wd|t zlXpZwk`NPXghI}0PZZZK&QT9FmPkyyR`NjdN==fXT4^w(ohqj+H2Mhbw8i*Z?*Y_4 zPk3u{^S#!z3^+K$TfcbV08VAPT$w||DlJZ>kkpVZ0;&Ev1s}!AKRIdGm0CaR0_3Ff z)7{%dCo4Ty><-OFs1tS7_3W;K+5?>pa^l6Fb&%&H!v&Z44AM?G7sXDlJ=5J<9I=k1 z!5ivS<_{p|NiAd%2svUvP~ADeaUm3Ug_-vMDkAp^8?{pAj+Sr-nSGsgV(DvJQJPe!H#nUfw7n})1Do9Mo;APV}g-m~yP+&J@9^H2s$%Gkt&J=ELuvks!)S3oL) zPpX;lCen)~UehLx`iWe(c03Z%&vSA;rFtAdcPOUq-rC3r+~ zu$>weF=eKlX@z68aNinvTT?$EDNw~&kVx9kG@g|Ik1BmV<_N9fqxD=XVNVCGH6Bu0 zvQ?oUb_%|gvh1&U7uj$ot`<3Q<%%AoaH%5Sfd)wjya`DLyw8p?vabEZ)jj?(36x0A z*7F|z3U1Xm0HibDt-1h6G;Bqync^xJ@%UNtL2`-x=sI9xlGD=v`5C(T#P-SfAK3=T z-3C2mjrtxW%kB0ecC+E=5$yVi2pm_^Fo45P?LOscm_LTY87A4^T9o_frr7pKMtV0q zAu7mXJ+SMOF zPIp_EO-xOd)_?*6c>T8@borp;H#(;PlEb8gdafVjk;_YY46rm6etvlybO|Md9B~NU zM6uU8%_nOJ@^?^4iNEXBruYgJ!B&RHq=Zew>v(K6*h(P1-IS3zItv`IGcY%Q3i1%} z0$!JwUl+&eN6Fw20!S`kLQx=2I($v@B#kS)Ym8VEPOC)S z?*_E(WfJYfC&kVMsZY|TTNx*}FXV57{sFcjSh;OwWgC!pgM$oUu1mVikWo{Ac<~NO z%*F40!18dU3e;G5Sl+vr*k|+i&(G0HdfNYLlkijZY z*{0zXj^;I`3uG>VlnLlsL0Rwf@WKM)5g8`1cvps=L(rsw>_%+V*Vjwl4WOf?Jzex& z?(u{)7^uyFnm6|MiN^9UyfdUFmNXOigY4JOfF) z!*~CA`{HNu1dv&|@V>&7LexT*c@)mNA;L9Mxsglnftd&yze3Pgl$HXze%IHh!b%3o zGhsa$)OtGv7VYNwR!b7)P~nzAe+@JmN##y4s6m8ko`Y;qkzFp_U z|KnK3PpG2S!tf~|f(|iFh=ley8k8v)$(te~=#j0=2In{!^GYRyMOR?9;SD$$ zunHnK0vSwr_4R~~{Ch}a71kL+6!qiUA@sbQq$Gt44OTKOP`UU@wB_sstI=@w$E9k{_6!y4J=7u`^^EF=KbZYOaws>J~hiW&xbIXP^^FwzLN{eQ!#PL1XWpGX;K7s`?&ar=xSzF;U1>yZ><{4vvfW zz6}|-x-sRB2*R-uNX3trL>_&Bq&T3GyLa#AFkOK*(v-aN`sszwjT<+N;HVBT4REgD zeo$j{)hp;ohs%uc+_$F4e;_Zxannj?0F>|;e+&AS?(ZUbfHWK&B@hi7BuoH-&+1C& z(+f!xIQR7mBFDD%6nF@zU@Ra|Lt-m6HP!K!7998D)Bv1B`4h@rc_adWYOm8stB;NwCAu= zVA3DJHoAk&B8;J;=_ou!NH5G68`&}B@M;s}L+c_yAvtqzRH0YkQdN0YU6t;BXlsk+ zoxOIjpDriv$?MFcFAbnK0%2rgQp~%xvm@)dJ^+OtHkzbuhxfe%$D= zO{YkvyiHX?NJ#kD(=%nz*7E7`)U|@Z&n^LEjDS?$z72YF`~a=JrWw*OLY^%kiN4R~ z5IDUwV?t}|4fXgVSYbW)J>hf$BO@baOPkNGiMct`X~esUw=Z7Aou{GGf$gDMckeRa z^x@Y?fm|n?dgD8;052=bs`Jqr&I>vSyzx+VNA82@3?t;`=EkY- ze0)w04>37F=g0l>=H$4| zx7=C!2&Ijxi5os0zD%2)i;qt;6vdH;iDDIhh-474fioQ(E3_{y-`0IK9F9?$T%E(f zAZbMZF2E5c2<~u_0X_hTmH*y>uunfC=fhmej{`)Bd2T%yB`$r&_}Lte}&pWnL&0f&%paD#=2LQ0^5J zQ{iCN(A#MD#rE*LI^fJdzJFIsSsyD>+V~kQTnN)pI9c`bWkq%N6c>~tI6wxC4P0CZK+y(B({@wiXo zN$k7e6hg=+=-)zrznVtVdthEkK2C5F7yhtoFajU=9OxWfs|&TAZzQ?4uy*5?k%H+c z8BV2CCZzH2{pT~QG2AlIi2|fa>$(+M`JRKy5cB*3z!*Gg+bzA(kw#nP zEBD0^qN!}P^U&anMEe2!SAN)rmWx^`e*e+|#1nO=Fm(ezN1cLwh?7m;5fv4M1n-BH zD2U|aeH};3%)JzvX6*ZILg|`Sb>|?=gkb~Z$GMV(+eU>pfVlqt+L@hzEWz9yeL9Cp zlfyU+t@f3))I{!*Le2y@qdHqxrt9eDwg-~U{_@+zZ)iWUqaxo#LDsu*7J+=6D2tsu zEy>NTY8_CWcL+5hBp^6YlcU*$uY${0O%Fh7?T<$ z8SFEbl`G!OLk|V7$^Eq`TN2K23^<`X;52(z{r{^vqgbI~jWIB3WB?BXlL#@3{ZG+^ zj5>B>d;8*GRmtQMLXJR>?(711BUO}n21y9GWJ@^r5FQ!&nNaCaMi~wR-MJGF<+`K1 zx}ziSTqp+ds=nS~)r$2q1!5L@@M7EJ3NCZVXLk<|zW~7++|Z<0w8{-239T~}_5k9A zQ?>rG&!IWP!Kt8w6(mU{1ryVq$Ig10?r;BQWT-uXMh)+M*kA+(5GE$(K%}m@wqiCI zfaP<56iGX9lGnb0;EcQ@WjjFT?`o`~f-OM10X371qwn>@M&YiTX{`IzNHPRL1}+@A zo7a38mcV?gxLPIw96*&OVZ%8at^b*eE-o3k2Z+)fl9dgMW;-tlY5g=O|0spP4uYuDs!VFhzpvkgQ!_PGY{T#U= zu;U8m0gO}R21NUwUF^1UYN)EJF2RYM&bS+{b4`ASHq^0G;2$LYvu2*2oCI^uz=>v% z!}94moQ;KXTCtUe@%Vt^AfJ5$FeFWs`K8q`mYy166FZpU_((c9U;IT2Wc^!A;4D<`{{s`zNLyqP>SLLQRu=}B= z8ZHWn0jApA*@^q5yTXCTwW7`7moTxk+;pE%z?rnr%!B{>_1Ksgu;|jkJFhf?v-9tI zd%>CSgdzsn(wYGN%1^j45~>Qkwr5}1M(8VfA;e6^$Vl`Rk5lq9E0Fi|lX>@^&oXeh zyYv+N6Zp*!lQz#X2;OU?!0#!5aR8^pFMdtj!$-j})u~AgAc4d}7a5ge;I&#~nu$?; z{r(-7P=Am?cHM|SBTy0J4E06bto-4@|K2>D5i=dTu6G|r_Y_QBp1R6(sN;NaqF2UxUdVO-jM zNfrmiLEji3Ph6WI_MWmeB}<)yn;WM%0Z!clU|6Pq1IKW4w74HM7&Y+}$Hft)ZQ)_& zus`HDuvTg+t}1EXAInV=a_eIt*o_XSnOzvpW7^R1Xos4Nrwwb!K}kQpKbjF?P9 zuyhvDQXNd09ru9A0kDh{{5$}s1_Y+4si_rPA-!7KGB`Mhxrja=S-E#f&k3iNb$@`Q zGYp{zV3_dJBa0rza9YCX;N+xyV+}*X0BVY=T5T|ddEmV3l^5{<>4q5GXJ29a4}hNP z^tam%sUtd+dna2IoB#O{z9#KHQ`=T`?!$;7K&J0)L^M)X=GaL2Xn%sRlq0qbr%}{X zlXiXjD?Mggw$J)ALSfD4r>B4? z6-3AfEbh7{rKKVGnxOMEr>sN`z_BVzE}SJh9+{is;%PZik0vX1R)m(xk!nBC}KQFTMZD9B`)=|OmRNU$|<9}WwP@WYZ)KCWHo<>B%0^3t!o z6E;9=q!6--2dfiI=oC&z14htQ1CF=CQ~U@KSV@{2u9GgX9E^M}Pp0Q2D| zYPL2v+uGZmWb@Is5-o>(CS`_KVr*|^{wE7-PhxlCSj2yD!xMStx!V!_U+LA_Rh|~Aih<}16KYA z#}|e_KScZNfN%b*+EZr1@BV~z@`7%U;0;j-K3YK_5QXgG0>i8&dEg@zzy1RLc<^C< z4Djyur$ATHKl1@~l4qm2vGFIkk2K88B$v9b%|Lq5%ur!TR7{MJl=Kp08LMfL>&56` zJ#eB?%!8X(6WlyXdi~x!;NO=^7hF*D9-}-s+(MmVw%o==X@=|Kp3Cl|qjAT@Gj(y*bm*Z-YOAc&qgS@`A#(n74}tH9~=SfXP4pN>Ts*eI*-L zC+c(v4{hL#z_tmdVYON94F|;BWCxwpRik$ctp7p;BRZVtxsF#G0(tqsK-nYdP#RL1 z?&4zh9Op$)q|{SNzZqp*lam8(%bWqnha=x1pS%nU3xl-M#Jj-;75{xa&6oQ`=}4T zdGRQ;!YYeCD@5c5=$u>LI-Oj^S;CVN*9~7_q@vn=BV)!0JW=e+8A{@HVsm+lFEY1 zpUg?*dTK2#UK14D17ihD+>!IvDw6-G{p)3_2h(Ua2&%AE1z9haJP>k;bT?v>x4e7H zZ-poctg}CEu(OndG^|sm+WhG=lob#Z@pY!)*DxgE2Y}FLEz5dBuQ)n|4XM>7*>Qxd zUzA!P!|(rukvh8imDPTKp)J)%84}@5=3v%Pi1&t=Sir$b z$k7}p6AHrkXg!f46%I86E8u-J4SX16vdQsrI1`qk>RB!YzxJ{_HwF2Mj~nn~HfC#j zH`v%h`q$vs93&ZTmmR}Pl~_Cdgwd-AKYld4cR z)-dNbC}#)1e^)qJqXXHEO;syV!4ZP_fX4JBBPj-&uwNKof!WWQMi8J8((@xV}^DnddRE5HP`VzhwdK Date: Sun, 7 Dec 2025 22:41:21 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=AC=AC=E4=BA=8C?= =?UTF-8?q?=E8=AF=BE=E4=BD=9C=E4=B8=9A=EF=BC=9A=E8=A1=A5=E5=85=85=E5=AE=9E?= =?UTF-8?q?=E9=99=85Git=E5=91=BD=E4=BB=A4=E4=BD=BF=E7=94=A8=E8=BF=87?= =?UTF-8?q?=E7=A8=8B=E8=AE=B0=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assignments/lesson2/savanna0425.md | 79 ++++++++++++++++++++++-------- 1 file changed, 59 insertions(+), 20 deletions(-) diff --git a/assignments/lesson2/savanna0425.md b/assignments/lesson2/savanna0425.md index 8720396..f89a9a2 100644 --- a/assignments/lesson2/savanna0425.md +++ b/assignments/lesson2/savanna0425.md @@ -78,14 +78,7 @@ cat ~/.ssh/id_ed25519.pub ## 3. 版本信息截图 -由于当前环境限制,无法直接插入截图,但可以通过以下命令查看版本信息: - -```bash -$ git --version -git version 2.39.5 (Apple Git-154) -``` - -**说明**:在实际提交时,请通过截图工具(如macOS的截图快捷键 Command+Shift+4)截取终端显示结果,并插入到本文档中。 +见gitversion.png ## 4. Git命令使用过程总结 @@ -264,20 +257,66 @@ git push -u origin main 1. **安装验证**:执行 `git --version` 确认Git已安装(版本2.39.5) 2. **创建作业文件**:在 `assignments/lesson2/` 目录下创建 `savanna0425.md` 3. **编写报告**:完成Git安装过程、问题解决、命令使用等内容的撰写 -4. **准备提交**:文件已创建,等待执行git命令提交 +4. **初始化Git仓库**:由于本地目录不是git仓库,执行 `git init` 初始化 +5. **配置远程仓库**:执行 `git remote add origin https://github.com/savanna0425/github101.git` +6. **配置用户信息**:执行 `git config user.name "savanna0425"` 和 `git config user.email` +7. **添加文件**:执行 `git add .` 添加所有文件到暂存区 +8. **提交更改**:执行 `git commit -m "完成第一课和第二课作业:开源商业模式分析报告和Git工具实践报告"` +9. **合并远程更改**:执行 `git pull origin main --allow-unrelated-histories --no-rebase` 合并远程仓库内容 +10. **推送到远程**:执行 `git push origin main` 成功推送到远程仓库 + +#### 实际执行的Git命令记录 + +```bash +# 1. 初始化Git仓库 +git init + +# 2. 添加远程仓库 +git remote add origin https://github.com/savanna0425/github101.git + +# 3. 配置用户信息 +git config user.name "savanna0425" +git config user.email "savanna0425@users.noreply.github.com" + +# 4. 查看仓库状态 +git status + +# 5. 添加所有文件到暂存区 +git add . + +# 6. 提交更改 +git commit -m "完成第一课和第二课作业:开源商业模式分析报告和Git工具实践报告" + +# 7. 查看提交历史 +git log --oneline +# 输出:c62806e 完成第一课和第二课作业:开源商业模式分析报告和Git工具实践报告 + +# 8. 拉取并合并远程仓库内容 +git pull origin main --allow-unrelated-histories --no-rebase + +# 9. 推送到远程仓库 +git push origin main +# 输出:To https://github.com/savanna0425/github101.git +# 17b6cdd..a425c9a main -> main +``` + +#### 遇到的问题及解决 + +**问题1:推送被拒绝** +- **错误信息**:`! [rejected] main -> main (fetch first)` +- **原因**:远程仓库已有内容,本地仓库是新建的,历史不相关 +- **解决方法**:使用 `git pull origin main --allow-unrelated-histories --no-rebase` 合并远程内容 + +**问题2:需要指定合并策略** +- **错误信息**:`fatal: Need to specify how to reconcile divergent branches.` +- **解决方法**:使用 `--no-rebase` 参数指定使用merge策略 #### 下一步操作 -1. 如果仓库还未初始化,需要先执行 `git init` 或克隆Fork的仓库 -2. 执行 `git add assignments/lesson2/savanna0425.md` -3. 执行 `git commit -m "完成第二课作业:Git工具实践报告"` -4. 执行 `git push origin main` 推送到远程仓库 -5. 在GitHub上创建Pull Request +1. ✅ 初始化Git仓库 - 已完成 +2. ✅ 添加文件到暂存区 - 已完成 +3. ✅ 提交到本地仓库 - 已完成 +4. ✅ 推送到远程仓库 - 已完成 +5. **创建Pull Request**:在GitHub上向原始仓库(upstreamlabs/github101)提交PR --- -## CI 自动评分与运行指引 -- 课程作业检测仅在 PR 到 main 时执行,请通过 Pull Request 提交本文件。 -- 文件命名:assignments/lesson2/{你的GitHub用户名}.md。 -- 自动评分工作流: [.github/workflows/calculate-score.yml](../../.github/workflows/calculate-score.yml)。 -- 首次 Fork 后:进入 Actions → 选择 "Calculate Student Score" → 点击 "Run workflow" 并选择 main → 在日志中查看成绩。 -