From 49afe60631dc8fc82a2a719e2c859ba605b6b4bc Mon Sep 17 00:00:00 2001 From: zhouyr9 Date: Mon, 12 Jan 2026 16:35:58 +0800 Subject: [PATCH] update --- data/KSP_data/log_book.xlsx | Bin 20901 -> 26911 bytes .../KSP_wiki/utils/sync_to_overview.py | 6 +- .../KSP_wiki/vessel_log/Stellaria_history.py | 36 +++++++++++- src/log_tool/analysis_via_history_message.py | 53 ++++++++++++------ src/model_manager/__init__.py | 0 5 files changed, 73 insertions(+), 22 deletions(-) create mode 100644 src/model_manager/__init__.py diff --git a/data/KSP_data/log_book.xlsx b/data/KSP_data/log_book.xlsx index 91659d3561426ec9a398bc6e6c02c2e4aead268a..1f24825d31a49fbaf3aea2adfb482717c5c30c86 100644 GIT binary patch delta 21463 zcmYhib9kN4^FJKhYHZs^lQd3a+qQjT+l_78Y3!syW7}q<=d|zd^?82(oNLdVy$7$E z+1Yz{PH`b(-2onVCbQh0YBWtnGEm zaf+^@|5BfZQ1#%%bB{9x9Qi?vQ=ceBs{gK;hZie06PZEZEFqmD`j9n^;?gf_dQpfO zzNC0uv9}*3th55k0Ok01yCFl}jtkr_o+AP4J;4>H9p~N5(I5Jz?zLh=yvH04N@I4jwVn!m7`??jRu| z@gMr#Wbl^nrrY4I_n#55cYuPu-8dJNCBf0RxA)(p%-)P(b911Co%pQBf`?iZ%rk?! zrd}?fTlG)Jzs64#r;5Gz$*UaQZ=5TArAbKL?;yh9pRKZOU8q=5$Q$bHaxyc1Wh6-S z)e?yEStFz)LanpTwCq49*-KzH_JLD?!y@3yW|xA4fcPa{L16)k)C}!+xl!Kz=HA1q zR4s*yBSc3D;?AgG$zBuor*X1U$9mM@Pa|U_iU1mLMa&OPa4@T7IzHVs0Aj*d%&=z=Lhn zY=nyVt!a!}oexDyxxn8qp{}cJw&57REqb){yPY`c1gO!NQi&d|f{952pz%;7(G<=w zt<5$WO_0#19x+JSJFpsE9Ve=YdQe&ytf`sI7fq;zAvzAAq>yvC%}>6Rc>m)Bmrz6M zD!Zx+JoO1K^deV$fVf(kPLTX6+u{P83;Ll}jlTGa?*x~8rZ-+zomNa-8jd6OM}Z@< zZ(#ZITp?upSQuVvf6crlA7R5EXdZbA*}TUf6~(cL0P_ADo$t z6=9*oW95H7!^owI*o=g+++^Kn?AgGAi}fe$DvCg7xcV51{KRweQ4}sc0CM)k^KH%B z3HLX<-YBbj%!CNC-s=QEF5B2x!)#lvSA+8Ta95`R7SVh{#Mmb<3B-6Q=hjvE-lHLb zIX2%VHLncTw(6c!hTXjZKmL4}l|A_#`@3>=n!9LsRS3(++y>le*feW&F@Aecnwd&n z3Vdl<^)slK_A2{*lQpo)VR{C^&4<0F^*%Sd?sXilT(^hOZ+f~Dp7fho)m4sIeFIUi z{N3FGurc!$Eu-nOQnes~#P>pMb5LXCchjev?P{ALg6_G&c^5~{R9uWU;@+b6UPL$z zem6K`tKqqtSH;VS%Mf?WgJXyVZlkYk6zjpt0jbF!7%1W!3Ys#(Ayg@I*W{lRhK{li zaagD7(?U83jCBA<-+PMvujd-S z*OJQ+?+G@XD%xvD9D2PpbS|(S#dxfUK6LX$S9;&|L)o5*66V-q242|^CG;up#(uQ4 zQtiF$lJGBiFylZ4-CaPty9Ws!?%6lPpAn&32~XvREvB@d_R78YCe1=&Hcr85fx&IK z+QGwPgMdh8C9xn90g~5ZGnr9Bujn2K=(nJm$yXpksw#A=am&A`#x2F-1Y$;)Uu3B~ zZ18cCXws-+GJvfa%skC_4AT?FRgicytDUyw(MwYYs2wY{WCr?uKC)&g8WGsbY#w95 zd4b6grCn_?Ag$WiB5uQ=X=(pjZD))#rn6F57w-tdGN-l00JuL}an@fTT(e@AQ_3Zo z;L6G=hJR@OFsIyr{v0t>*n!WlFX|^OZ)C zRNq$1_PL|4EzV{Vk_Wd-*{4C6(x+EZNeSE5^?;OoqGZyi@ zSbiHbrDuwQ6VP5aM@R2XX5$s`a>4o{mkRlwomGqaILS5EjC1($>!2Vx-H-^AMFI03 zd?L5OQe^LdROJ^kEcC0DEWSP<1S%L@#W0zB!#8kTKzKgy!A3TMX{C8l+rFb;47Os~ zU{|%x!3p{O7Sp(G^8;>t2hwye>hkPndq9TzekL?o0dS+c*K<4|5udr5&$bu--2vJM z_TbP)|O^I|BUnkUY62Y?;j`P0DiBp z$S(i@qkZoiRrQwN=birN>)I1hFW~cahRJ>ckUReP_;7cHe6CNp&1B!+{Z9IM5a#o- zcXs3`Aox-%>QTHNi6Cbk0D97nhV$ux`|LUsnT3tdS!BsAcgJpJ+vv5r9Im94%C z0JjNSd1t2DHp5=gyc^*EIb+yj>gav5gzmr=eSY)ucfPFW<&hnCZ;ron`p3chTLVKa z*IwV`K4=SDxgRCf&*?$GfQug{PQmsbc^AJ%=G){bTs-wR&zG-Zp^xyB{$Ox?FdP_O zqk{&m$#Zibc%XUZFxXbQM^b@7wdMjG9L8VCU4*o)GKtpznT>mPk7_W3~!s((P$k6UB z2@0!WRP3oKyx2Cy_PKZaQ`m_p(cZfMrd|H~>T$LY$RBDZIqb~hl}X4g*AS2;2u#Y4 zV>^fO0n?+MMScW9FYfo*jcpyP1OD|6#P;9EJ5I+ttOq;1t7X2n1KWjR^F$l(6Ew(a zEElUS`}2%qKQqDz8I=iZ3a5H~)_hWn!kze?Cg!JW<&8Uj&>%0(x?Pjhst(egy(uDb zGd{3=(+vS`5r_oo(3ot>cGo#@{9`{DdBXLjKl;zGw3E(<4B%J3WS2*@j+%?u|1ab{IORs#!hk?fS!Je3qMzlIOdx6bbz=X zKLNLi>D>BGQ>syCx3L;;O9!TcTH+gW8$e*|ww>T}TNpm_>Ei*GM%ksGPRQz@t{|uA z0_%5zJ!dbrPLqA>Um$~T`GiwSYA3EmbG0}tkGNziS%qn6t0N>#^Es(-{WHwTovy^k zmBz0d6SNT)u(2`l^>E@Pwxt4_)mH51c7CTejr%{)=G7n&2y+`9p>2;Zt;Pkne7y`5xy2T*-{ZDl8TpbTLXc#VIx^W%_9SR#`^BQ(fN zY`Jd--6k-`$&T)tN)p#zDjv0BZ=d zPk%^W*Y080F7N(ksoptTl(nYMAAg9m{QTp6OUlJX5?mXCO>k zxN$Vc;xA*dEkRuR>C|9QLht(n>Ox$04xbt{Gb^)Zyc{q5s;F*hr&Nx|A8vI@IgP-K zsFcTI3hw^AKYF-=>&Qepkf{XR6}xg1sY5_4?8n71#xqz%tMysY9_aC{9$OPB`HC%f zJNtHM(vNqmr5Rlg;B=50lx7Keed|0L_GM%}4Rosg-M-{I`hXcgIIW%vmq^TGV|r<~ z%(MQE-O^B!KfJbdmjvSxUyy;zFI9r?XYE8+#EX8sL5s8N6!SJ>Dd8v#OsU_u_kJO>?{hcaj z{_s1I)PUE}vq$-(8ED{CZWtXH6!OGf_H8!7JHF1eKeSfJ;_mR*2MMnBZMm0eAYRB6 zfuujb`j(fZXJ!}zN_EU7)>aTo?;`zOx!)Pi$9^VUB_Ewzuw}B}>JEeH0bEMq#+@&Z zd7jv_rs?{jINl+wQ*t|Dr;=`y`2LIuAaVqeI@pY)d8+@)cB7tYH~!vRnjfhEVS_QH zYMWr%;QdRk(8p3DGdnSi4G8B@hhWTa(?Wir(7vz&VN}2;z!Jlykv-ETF^?jW9T2)ILImoUIcFqNCsP2mEIuDo6+RnRl&c4gz^F z3UV4x0Iu;)wzyKosPl9Xi@_=5*?0d@p3VgmMXKpUSNr9Cpx%3>UhO2>? zcB==k-TQ1dk5bO9gXgi}IxRJr3+mz-^uZUt)whW?1r+N3KSO8p>4(K3MZsiLKK26~ z{WOZpc$`BIio0MNCSFQA4&<&~%3Es+m|18yv^#$u+q~bycPY35Vv_I&Eb?u-g#%a9 z@L*EG>IbhO9V_*g`ESRtT*|!SyuNA2V{bc%K3dfJUi}vk;?h7u8ckP-Jp6%xd|UQU zhh_(12SuM3k9@mU#slT~z>xx@aqt^0lEow)A#a@_fmXZgOB#k`eSsZ$hGtWOQg*M! zGjk{5qZzAtkr%)sx*b&=vd=Z+to_1#_okfxZLMWrL(f?66#5)yV3gCxxgFSkC7!Ra zvw*j?WzpVNcjv5qEBZFSl}Oy`oaC4~jK$a94LSe2+{>5mG6Sx{N-%QUvb^?GKRsoh zAW9ENKIN~s#kY))Ti0M6Hs=HeEIsi!^F?gZ<^OzVEP)2Fk?Zfam2xv6FM&ys95cMT zZb8HC+9)tk-44ZiH;}c53)Koy@apFabw*X}R}wtgl&0+T6VpI&S!py--5$hxcg&9~ zpl6}!s&o@xMMKk;3swIB2%hI$HMttxsP?l6x_HMKh z*U8?9<}LtocP6dJ1RgBU1j&P!1_+&donoCBvgbjL6l>G?CSH;|Y(;;^W84}r@i)Q& zV7>AQ-;$0}nqQXMG@b00y5X(X9JYvSzw#+6OCl1@7}wZ~$l!G80menE&I?7ib-fzLSl;@iWFnLk5h4IEe2P-eOXR*U{XiMGjGlubQ{&?aIg!Inz=F0$$?5w@^ZsIz7(QrCE4)}X~@Y~6?+ zcq0ucb6pJXnP$ z8!=)Pz*yh1o4kVaJ$1y?9xto$GvPeL9cv-kbb6Hhg%x^V@I*ynxIo1R$`@KC{i4E^{KY+&xWhQ>^xL^Xz9;gH&zQU-O70q_6< z(p4?)3Hj@QN+p2hYI)KyWz8<@fQRu-ao`%c=y8e7t?IEbV}K%y1!a*6h)kv7^A-K| z%aHT>ow5AvE~u%G(eU)Go3sC(O5YIw2(-{6^P77tM?Rdnr;{MT{z$gacNn)+DhZwh z1I9I%w=>c45=rJSclh>yxKpT?bM@1Rbd6OG+r> zQum+-_T7GS(0F&ZyXcZ41E@oU?esbu!S<_+?Bp}ru zu@bNyBv;n2xrrP4Dc41AhOlC$y9i_@<@^_wmbyRC9S46IX=8r`NWW+?JJFmqg!~qY zC;ba0`WgT}kOqbD|6qk?-TOPWS)2tqJQ6)nce2v(0Xcc#FAP9T!LuFy`bwbcBLJJ5 zWLa~Q5GZjjlgrZN{de(?(&}_0(0u#9LbX)h&9_gxF?{-kY6MJ&6`yCmwgbbP{wloU z6JfCZFS}Ukw+X3S5?DC^&^7K0+ZrU`)qhi?YY&EY9>JygZ%B$jBHTu<(-_UaJ_ifA zhx}R*QB`ow+4p~p)?0lM+Yth%uo1z;zT5xFx4`1spO|o}8X|~(f=#VcYaWfkh-$;j z5Li2!&Cb#5Avu*OF0S~H%O@O(5}lgngz-^K!ffg(S)7OikoXM<6(2(96`x3=TPi!? zSIGUFeRQEA+gNcOGZT{P73JxEL4UJPQWUK(6nPs$nTj6gM2w?a@i}c#ZoTGbdfH;y zpP8=@p4}eHv+8E}A)g2sIk0`$cZv59$RGW}RCANsIk$HAP)fYf!8=45=W>(S#(Jy$ z*U0ogU;#idtblk~#PR_l&AGRZbeYs7bke9m(JF)i!%vOC=}cE2xZaYY0mdkcJu)!8 zictcy4=y;kg{JYt4uUhgjF1O}Mhp`=)hFqKk?_yqEI$8u-PCgRu=W0K4(@ZC!W8BzMKfK~Y>J@iK3-bUk_qV8=x; z^Wb|K7=t`*%=WdAyV7{q0ZEvc8Ga}rb|5iffHd%*R(EXTNKyCplZul;az(YS(fC-X z_^O{c9no?yKtv%Zxedp<_o(vWqCFD@f&*zDHHIJaR696>c@OF3J3aI~0U`W`Fp$ov zVYUJxNVsaB*~ucu%bI$y|JliMcz~w%i618B6)9qY7Kd_xi62H`yfm4iK3|W;=JkJy zv{I)#;ipDVF^FBG4)Ftt^^V2&j=;PJBPAi{nF!5kYkM75H|{@_898Lo*U<*ovbqL|+uZh&dv z3>4*yY&tx<(MwO40tYXnIQcS|)FVm+9mrvo^?INPm~?zJrhOTnUYjY>Ls{nsFYv7*mH3aVfH5={AL;nxq`bNDJABxC1pz%IInU4SI z66?`iRQCsHOCtDgwDNy6L08tje_EY$(~GfQ<*^Y4M*7v^@n(>;Ghwm=#3+qv3QW z{B8*Or>U}&$`ICnmYAncwn0|iPdaMIJ>S_hj&_S|1JQ`uM=guQ{X2tnMks6hzvua! z1U?Ex%8VJ;2JN&-m%9L{BQ{BUbtdPT6#waDavlL3{nd$FePAf*5`NZg@05SUkcI)_ zZy-p<*$tOS;nU|7Mad#M^~W5H;njMpV#E$O^;d5*jMDAv{m86u>>{i9fFCjB*_pwa z&_{+<71q?7?U7Oc-Nab(*`UpTYNPxS&Tt;-8qp8vE!xkDO%R~`PSrnDIL#TgS69`t zSFa3d>M7=p<$KI6wxj>Sja&-X#GgM5wS<|-pcF_DX4?E7tO$(7Vs4}fS}LCaDQA4F z@KSTEFvK;8R;Xaj2 zl`9!UaJ-}sa16QoxqRR6|%$W0IVS{J^3eBJv`bNbqUu7=@4{ZcFT z8?eJoPqjYz3|z(gAAs1ZIjFpU`44zt!BrZ+$MJQ<$2!Tzgj5FV^0ZdxvDN_P)B4wh zXJyPawEwe#Ov5Vy>LVQ(>!5@cB7o8Qgzb@pvA10wq>0r2zkZM0tFsZYjWnAy&0G#E zw&VFfSDM{8VSls>(kC|W?v4rT6u|+DIZzz*mk>Y=vWz2sYV|i;0Nh`vi;oPw<*Qd^ z07DS}tRQv? z-Lcu^Z_n6)23y02|CAaHE+oy~tHT&ET7VS&b(CaV*SfvOuB-*Z6{Ge(u3XjUUWf}$ zUtx(D+&+gygdhoj?P0LXL_k@X5gRCaf5V81c8bgpU&nx+Nat7-ejtnTG^ta@ zrqR19WoB+FOBM$Jl8rr3@DQeMp`?`N1oK3j+=ZnO6(b{AVQ>bnlU1s*2=X{bjpzfF zl^xhej9OATXn2|3ZCVULIs+P<$(+iR=}YV^@925$aI}u|OG^u}3Gk(S&3E`DHcS~# znVT$rX1L=K#ALA68EhX9BA#NKNj}5vtIRAzLRZJmfZ_xAv%zU0Wyq$6ud!6m@)wnv z+Dam75)*AfDITnpLk@~6>M$7MrbWkEIC|fEU!Qykp4K>O%Nd#UrQN5keR&Cj(RAPI zi-RX*@jtc&OaJt^u5}gPcD;RbWa`jKZCY$EcoVj1Utndzd?k))L zxEA0&f)?-|0V>f3vpfcm;6;@a=Mp%_3e#9POB>fd$S+aZVq_wuPFB$Eq zozcUVeg7UJR*-(HR~tWiqXX_II=MyK{P?TcbUHdF^(E=N|8Vx4#*l#EDxxzW22!s{ zuENX`Kkmn_(tIp)>l3rArZi}r_&J8fmN5OodZC~C*l@O`^m>r;x}E#fSM1-!Mhw;` z@(jsn6o)f-w)FZ-=}#;;PQtNRGZ?k!_$9i%5k*CH!$0OEB+ar9*Y3@2hTGcW?e2Qv zlMsG{bR$4^70k6tNsE6`^9nHq*aycj)m?X-`%pz?eZ;;R`#YnBdZ17ldbqyjPl%D! z_mj{WLj7Uf+1A@g`W0tw++w(gvo{!S(FW!8XU;&izLn;t;#+6kEnXn6C@W|_gSmadWFxeWchwLAsz)q)I=_ocR=dzA%%a&p>u2tpObkO+1G~bW05;v=zf1LfQIqLR;=DkBm%>?|T!$?*L!0D^^`|yt}kU&$s%SwUO7j z_q}&`LnN%EBhZrN;dHtFGVFPHXH4E`U!e4lnLICZOJ#sqfBagrc(=d`r1{ZIR6KYv&6p zu{dp9>H{ePMspx!PsFfnhuLq^AO!=2xARhhLUgFPg1t~DnWUioE1({p>=M1b%wx~T zwsS!8Q$^XXjcYN+HM9g+sSHxn>Dr><=%tW{9B;FyH;{RvvX;}Lm5*eS|N zTKyG9CwQm6(qi{MP66kV;6>rl?p#Uj*?M@A0LE7ImXe}Io#xuLUd{l8P7N8$3Dvq- z(+%=#{topi12IZv<^$ErbhSu5H;P-7^GpBIAB20W*poW8( zRfi%VCH0$Nq>4rq4guVh7ePf3^%i&=>40D`NZAuEUL^zX!Y98-aQp#Kr#h4w7Nup- zyt!+&CoB|41pA)}qO{9reIkifbmE8`(gcvqYKmOmsq~V zsDhA)1lE%aN@JVhmgsYpRvcgi*ndg}ka-U(1w&{hwrH78LxcrV>>46j#&Yp?RRAi6 ztw2y+18`DN4&6Hf{e^Jf3Qgf0Z)cIE%T&M^iZxy7m^h)qAdL;bVoTUq6P zk5G#j8B`&XBVa)XOO=|@kGzzEH49glJ@(mybg-X9}lnRCXB;`HQkz6-jhCNn~zK7ukhe|>A zgRdSgPB;?H4g&WifLWLn_q{MVkbd6H4e466HLb@U)&1Cius21B~KYXDr@`;vT8H%m9HqL-NZaxc- zR;1u|lQ6C3W#g~G(<@^mx;SpMu^1F+j4e1YWK>5h9X{vvh+Kb!X)I+nZKYNXHf!Xk z7oUPXgXW3wS~C*XXuj?v7Jlwt@PlfA64FS26YA0jH%z>*%qvKL^(rJv+10P}j~eq# zfmT_Ea7r{zQfGtXi`?A|6fp)ghM}MaC{W>3AY>(i8_wZ|sXN>UDdE>Tgu$KfP(kOJ z_+R^xaeBHYG?F5tT5SLERCRXUo^Q=uExk&fDWnfbiW78+6y9-XRQ-h;z4_3Jv#2bl z3Fe)0XR?{I0GabbKq?)g8HkeLzmgKFD-&$!j!T2=AvMQrQ8YG>nFRsRy7kB9-~I;B z-1x!X`^Y-BIuP#1&U|MA`X0TGgo;?YHI1$qHAEl=%VLoN)lYsW(G%ise_yE7DiNrx zCq4JaEX{L~GvtkH*&u@o{@MK84IyAeMLs-SyNfG@c^QmEHUq%U?57aZG(W+Ia}^oEG#AWgiayJu;g zDI0KQ|M?@Z@2y$8s(~hQueVwg?C7zs4+};tLM4^~rJo#Ar*P~hNC{5QkeCB|^yN^0 zX~_r4pjvfMs3Xg>g*b@WjqfXaNB<(C)AJkAkpIt!=8BY(--NHw;yU2;Z4GQrIx1-zMWccqE*&@k*)o&-c&wr<6P-CvV zgee`5@HHMBA6%y8^n}0ilQ3Kt#2A&6505uJhrxe0(owu5VxV%>nWBED&RI}jC!Ds; z)V^0e`dU(e;LHnXd4oZB7<2ME=gUN6()Ef&t)Hqu^8=3{f?o0at)!natzt74&Hh3q z_5!C~9wH-AeA`(r+R{Q_`q~qYld3wZX!V+%HpmnLE7Ty2LwIDGsi*(!2=3R#j7Cjb z8M5%<5@AB0SP7|R!?y8Si}(rszcTkte$5I@7=ZAeLUMJ=C>9w-mK=B-MEne?%+-n4 zlthx*Y<1GhwFh|@zrXJ$cW9`fH>aqWWw5tXSfxhM)~Evho6s*REQWr%fljZ6`f5rj zo&Kq_Aa?bC{UJ$grQvlI9aX_*-Kb&X5T7I2z3^h4TmjQ#`g z`|OtsuEq)17^Q511)4Oa7O+3W7g1C-W!s_hSxv;+J3KU0bHUzf_D2Ba3kUbuz1dn! zTOt9eS^?_gc7C#Cj!>0$@k)j8)+@Jh);WhC`dhImF5r_i2}6gjkQR@a=bS@-H8<=o z{s#SI?o&0L8=iw7R{bX%t!HMDhmR3}!d&Bz`0_r4^GNYsH8uPnK3+d@Y-9Hban#2^ zBH*s`*hvwts?J%AT?O(T<>+ZFJ#-?(KJN<5?Qkf)%}*%2K%ol4}}h!$}e6M-70 zcP3h8hrGf{+%I+{;P#^pQ~o;q46Z|Ik@f`ZIknZJa_;m?lOPSdzqMja&__3*EeyZB zEFnF&dtcAq1FcIZYb5BI@6(^(N=am>CFZ@#?TL7?Svd=mWzHw+;9v&}VI)VwTKE(> zuo8;KgF>k-?2C8mh3|UA+#)1_d{$D>*%rjqZMATa(4Y3@cHWC2tJiMqIPX12=9ofH zUROUa@jn14tQ9uq9GtN;?DReW8#5u!9r_j?ITKbP&_r<@I19IBn0r? zto&X0~eol$Po?{E;{~Ix1!QY)L!2J9vF%S*d9x)QLrj zj0JA}aE`nq*mt@yKuMwiiakWkD%kB}rmtWl#0_pe3GV4>Ci%f}Wh2jpA}SgG@TqK-{{HAsO^ z*jh1Qvn8F)o0%adF$CXRGJFt%m24@#E`Iq@|HfGW6Eqh|Oil8^r-eEKA5!d|y6fSN z-3EM2_u}mXFl{_I5)8n6uBjGhYYI?5XJ!>vP)o0zo|yasUM#Gkc^>5o;v-vuE6SVa z((4wZVOXPu7)KqFt$|@k*Frk2XUJAUQ6H`}x}+I-_nkxqy3aeh_AtQ5{Y8sN9qX{N zKFEXQi*+Sv7q)|(37JzERsJFz2*bIF#Kew;p+I*dfL$3LvjKB`WZ5c`NC`fMV9L!a zRK+8-3D*GLwFXt}I-nX8RNrA~HW7OZgY~cSKF%7u#2#@ws%!D~&ARFnYtI(2Fndc2 zv2%0$zr``h$#)^LUJBH4w#9hY19%ThoB&aH2YAM~w zPS;%}!Eqb!J+&N`5NCB4V}9FvDLf=*)6S4%IjCaA50Qk-3*t`;CFzQ>vM1F1x<^w* zh6$Yw?YbB12@}T})Z|ZnB!-@#$BM* z==M?t@awXf8_mOOV#*XYP8H9^N50<6U_QCaW065uB4jtS{MOHAEKlfa8D8ofqTKpf zI96@FPdgtK30W4^CqzTsl{wH z32xW3Z_q?8RQXqLyH=@TK;NMC#4I_We{fTenWrW9Xy6f@pYCGAP`wEzK-red`E>`?Wh=~`}B_|G|6!-NL+Y54B z<$~W|TM0*-GQRmUd*tRF5iSNzYzGA5J7Ma5bKt03Uur*C{HU-az$A&II}9zW8$y6w(7`KD zZV)!IBazt%&!vdHoet^HuzS_+Cr!+aezd7@)^fDHOfZdugXQ{;bp4+tr}`%_@aNQ3>m_W-a1 zPk(H(fc>fe&;DZ&)*Mw$6?HYmtN!$6l^eb8|KESW(qpR1aKXjicnE$vOPaYut0qtZ z+f#W<|F)-U9g8fUW%<2yoyXAB$1XwEx*+lh1Qxpk4=2sMZCl*Hf$gbQne#EuQ|z(T z%l^BZbBKTi3z}xd^&S1jSX*QNFMU#~jv3?w8jhOtsmvU$%r3x#C3prmIIATQ1eNuC zzs`ghf!X9X$kMiz%Z!{~6~cqkYI6kOz=Nd{K;&+0LrfBoAuuW@tYMe3EcizqG>L*Z8UK=AZkVDw=a{!+rm zKjJQ%iy;=i4osVnEUFu(ZywX#wHfJ0j?7O#!SG@10Nx;d)Ey$ZVa>ya~H^mD25qp zct#dUQussCCo%I|Ml%nNneoDcn#GMUT!aGA zngwlyP4iUr>3_J;qg^$G29$!EkAo7`snXqWaB`y$2? z_#;G&SGUxFkhS{QWGDNr;LBZ6=sxmT9f6+#b8bkW04;&L5$j_|#K=vYAh_0bmkB_W zCc?Mz%xRr>Y%J|C@Q0SRHY;9ijqT7qlm03&k-uB*uk^u~udkux*a(1uWNWEsLZuEP0i%8v7Jl zX0ILc*6XRp8Kd@z8fIua=_yzCttpdcMytVWD&9d_`@VPnW=)Rro~eGVg5F4@+d{u| z#OO5qg+7}?3daqo6CFV`6S!IHtTzc4k*)e!-^Kh>z%j=7#`N=Urh`S(`*{lAm=q*} z_%gy-1Z$}Qf6e(^`$o0xC+Hh1BH0$H1K!lW2dd#j#EEDRRb}K{s_z8iU~qr4eHzKG z_H5^YNP{TA5Y>Ixi&2wJt6+O=sn$#wTN52QuO{AXr5_H^Os1+KhJ(J?F)-qOK^;9n z(+<|*#GT#2xfxxtpiXdFIh5P%Q{uyC9X|)C1-HovB6%@Gp{egKU9l< zvs>wpQaBZsih?j}hpwoRAW>)Z1!}y@{Sf^H2120AR?G>qG-b$*c&Oj_p1nii5`*+C`JmyL??)zVn@70jG-SBePD$pgFd9u zw6*@a6VLw8NtlB+T9Ck(Id6}~Xd#CP8=%#*<*H+i1(hlRKY1SUmc-l}P%bM^?wlTJ z0=YlX5!4{blYBZ;$4p(^0ltsmSpE^=Fw|gL=tO!rb{kP)C5ez1g?pgfrmY}W8N1C2UbU`l$$o5_Y0 zEMa4%ZBE&M6Z*Eei&U$@mtw=g5Tc6-2)RfX3Y)YHPV>lR;y zIj`s3E|aqrO!NpbgP*%_HLZi(v^?Hj5^QAn$%;(&B)~77HfH0%f-sR^cPyim+4A+) zh(cFtWcMBc%XPGRq8-gVk#AwzdA>n%<~KQ*0H(wNH2A~AT<*5TWa`LSRA4wfK(+JH zMGbpDtHEeB>(b3)DVzTkpTmk_?W^WZ9m#YqEu|jSHLoL?hDEvkpdn--=dNjYo=z3V zon)UU(S9m;{dU!QqFE;TDW^u<*iwUpFkux=997r6FhQ*?Qd-=J+1gE@Zz=aiE^e%& zVWx}xU~!($DwFKWU@Y&e7@r<8AZH@!LIrE80q*uiG%dJ0b(c0DOqsgRl!^fZXC0Qr zpCRL%iK-oyTKAUl*MS)Pj%Y{a@B1hDhjyF!1?=e%nX=;POj3shw{L>3m(vGnB}jQ* zI)|dOcm3rZRYr^mXPU`8I#R0|Y{5QF48s|bXhxF`KIx0VHw;)~l*SsRau#jspg ziZ5zr5M^Cu(8WEIBxr8#s}@{zUVf11an2uwp|H1Cxc)` z0%-cH=}p?jpeW-fePv)fV_eB(I<$!2USFn9>@<~H=@T--%Ex8)^`?7#N_k!{jwrE^ zS(yshJ)4iN+&m#&Dl1#BnBYc{l$fLTqruBQc=^~X3?3KD! zwbM)ik266*M)j$gb<6T>Kep3UGwl1(KBumbBk9w28Z=}y?RJ9zR&jQ&XzEw{#i-$OehF&twd?qPzU2hWlCw+;6O4|9qc100Xf#} zegCChGD+1%|Da7hx!fRQ=sV3G_h9qJLku1yJ4wa4AaYtm-O@owyK+}jriza00l|Jd zz8+5CDziJjCL7%)xeD#jnoFai4^NS}d6U#L=>)BO_(T*l(^990HS3b@6OEJ!qn#1} zMsl4Wvv@r`Dpxb>kmRJPXYNb6*$=xn`Y);<_Y)H37rV4cr&z5&Ytd*f`vV~wIar~E z

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 delta 15471 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 diff --git a/src/KSP_tools/KSP_wiki/utils/sync_to_overview.py b/src/KSP_tools/KSP_wiki/utils/sync_to_overview.py index ef13a36..eeb2341 100644 --- a/src/KSP_tools/KSP_wiki/utils/sync_to_overview.py +++ b/src/KSP_tools/KSP_wiki/utils/sync_to_overview.py @@ -27,8 +27,8 @@ from openpyxl.worksheet.worksheet import Worksheet from openpyxl.cell.cell import Cell, MergedCell # Paths and constants -PROJECT_ROOT = Path(__file__).resolve().parents[2] -LOG_BOOK_PATH = PROJECT_ROOT / "local_content_dir" / "log_book.xlsx" +PROJECT_ROOT = Path(__file__).resolve().parents[4] +LOG_BOOK_PATH = PROJECT_ROOT / "data" / "KSP_data" / "log_book.xlsx" OVERVIEW_SHEET_NAME = "Overview" HEADER_ROW_INDEX = 1 @@ -695,6 +695,6 @@ def main(sheet: str, workbook: Optional[str] = None) -> None: if __name__ == "__main__": # Configure these values here and call main directly. # Edit these lines to change which sheet / workbook are processed. - sheet_name = "XH-01" + sheet_name = "ST-01" workbook_path = str(LOG_BOOK_PATH) main(sheet_name, workbook_path) diff --git a/src/KSP_tools/KSP_wiki/vessel_log/Stellaria_history.py b/src/KSP_tools/KSP_wiki/vessel_log/Stellaria_history.py index 25f1600..dc2bf82 100644 --- a/src/KSP_tools/KSP_wiki/vessel_log/Stellaria_history.py +++ b/src/KSP_tools/KSP_wiki/vessel_log/Stellaria_history.py @@ -13,7 +13,7 @@ operating_history_raw = """ Uncrewed mission to Earth-Sun Lagrange Point 2 to test long-duration operations 2054-11-28 Test Mission Complete, all systems nominal. Returning to LEO. -2055-12-01 Start maintenance +2054-12-01 Start maintenance 2055-02-28 Maintenance complete, all systems operational, ready for commissioning. 2055-03-20 Picking up crew for Inner Solar System Exploration Mission 1 @@ -37,7 +37,7 @@ operating_history_raw = """ 2056-04-12 Earth Arrival 2056-04-15 Start maintenance -2056-06-01 Maintenance complete. +2056-05-31 Maintenance complete. 2056-06-02 Picking up crew for Mars One Construction Mission 2 2056-06-04 Picking up Mars One construction cargo @@ -205,7 +205,7 @@ operating_history = [ { 'log_name': "Maintenance", 'start_time': "2056-04-15", - 'end_time': "2056-06-01", + 'end_time': "2056-05-31", 'mission_detail': "", 'sub_log': [] }, @@ -312,4 +312,34 @@ operating_history = [ 'sub_log': [ "2059-05-31 Parked into Iapetus orbit, orbital science completed", "2059-06-15 Start Iapetus Surface operation", + ] + }, + { + 'log_name': "Saturn Exploration Mission 1 return to Earth", + 'start_time': "2059-07-01", + 'end_time': "2059-11-24", + 'mission_detail': "Saturn-Earth transfer, using standard trajectory with 162km/s of departure burn", + 'sub_log': [ + "2059-07-01 Wrapping up Saturn Exploration Mission. Saturn Departure for Earth", + "2059-11-24 Back from Saturn, Earth Arrival", + ] + }, + { + 'log_name': "Upgrades at Star Port", + 'start_time': "2059-11-25", + 'end_time': "2060-02-10", + 'mission_detail': "Upgrades complete, ST-01 now fully meets Stellaria specifications.", + 'sub_log': [] + }, + { + 'log_name': "Outer Solar System Exploration Mission 1 outbound to Neptune", + 'start_time': "2060-02-11", + 'end_time': None, + 'mission_detail': "Earth-Neptune transfer, using 160km/s departure burn", + 'sub_log': [ + "2060-02-11 Out of Star Port, config for Outer Solar System Exploration", + "2060-02-12 Pick up Outer Solar System Exploration Crew 1 and supply", + "2060-02-12 Earth Departure for Neptune", + ] + }, ] \ No newline at end of file diff --git a/src/log_tool/analysis_via_history_message.py b/src/log_tool/analysis_via_history_message.py index 4481cdd..707b66a 100644 --- a/src/log_tool/analysis_via_history_message.py +++ b/src/log_tool/analysis_via_history_message.py @@ -1,6 +1,7 @@ from typing import Optional import pandas as pd from langchain_openai import ChatOpenAI +import warnings from src.PostgresSQL.db_handler import PgHandler from src.config.load_config import project_config @@ -15,12 +16,14 @@ LLM = ChatOpenAI( def load_history_by_year_month(year: int, month: Optional[int] = None, table_name: str = '王适意_personal_chat', schema: str = 'public', - db_config: Optional[dict] = None) -> pd.DataFrame: - """从 Postgres 中读取历史消息并按年/月过滤。 + db_config: Optional[dict] = None, + week: Optional[int] = None) -> pd.DataFrame: + """从 Postgres 中读取历史消息并按年/月或年/周过滤。 参数: - year: 年份(四位数) - month: 可选的月份(1-12),若提供则只返回该月的数据 + - week: 可选的每年的第几周(ISO week)。如果提供则优先按周过滤,会 bypass month,但会发出警告。 - table_name: 数据库表名,默认 '王适意_personal_chat' - schema: schema,默认 'public' - db_config: 可选的数据库连接参数字典(含 host, port, user, password, database) @@ -33,7 +36,7 @@ def load_history_by_year_month(year: int, month: Optional[int] = None, port = int(cfg.get('port') or cfg.get('db_port') or 5432) user = cfg.get('user') or cfg.get('db_user') password = cfg.get('password') or cfg.get('db_password') - database = cfg.get('database') or cfg.get('db_name') + database = cfg.get('tg_message_db_name') pg = PgHandler(host=host, port=port, user=user, password=password, database=database) try: @@ -66,21 +69,39 @@ def load_history_by_year_month(year: int, month: Optional[int] = None, df = df.copy() df['dt'] = dt - # 过滤年份和可选月份 - df = df[df['dt'].dt.year == int(year)] - if month is not None: - df = df[df['dt'].dt.month == int(month)] + + # 如果同时提供 month 和 week,警告并以 week 为准(week 优先) + if week is not None and month is not None: + warnings.warn('Both "month" and "week" provided; "week" will take precedence and "month" will be ignored.', UserWarning) + + # 过滤年份和可选月份/周 + # 当提供 week 时,按 ISO week 过滤,并且考虑 ISO week 的 year(isocalendar year)以确保正确匹配 + if week is not None: + # Pandas >= 1.1 提供 dt.isocalendar() + try: + iso = df['dt'].dt.isocalendar() + # iso is a DataFrame-like with 'year' and 'week' columns + df = df[(iso['year'] == int(year)) & (iso['week'] == int(week))] + except Exception: + # 备选:使用 datetime.isocalendar() per-row(较慢) + df = df[df['dt'].apply(lambda x: x.isocalendar()[0] == int(year) and x.isocalendar()[1] == int(week))] + else: + # 默认按 calendar 年过滤 + df = df[df['dt'].dt.year == int(year)] + if month is not None: + df = df[df['dt'].dt.month == int(month)] df = df.sort_values('dt').reset_index(drop=True) return df + def do_analysis_on_history_messages(df: pd.DataFrame): data = df.to_dict(orient='records') to_model_data = [ { - 'message_datetime': item.get('message_datetime'), - 'message_from': item.get('message_from'), - 'message_text': item.get('message_text'), + 'msg_time': item.get('message_datetime'), + 'msg_from': item.get('message_from'), + 'msg_text': f"转发来自{item['forward_from']}的消息: {item.get('message_text')}" if item.get('forward_from') else item.get('message_text'), 'file_type': item.get('file_type'), } for item in data @@ -89,8 +110,8 @@ def do_analysis_on_history_messages(df: pd.DataFrame): prompt = f""" 你是一个聊天记录分析专家,擅长根据用户的聊天记录,分析用户的行为,然后撰写报告。 你的报告应当包含以下内容: -1. 以天为单位,分析用户在这一天内的主要活动和重大事件。每一天的总结应当独立成段。 -2. 按照月时间维度,输出总结。 +1. 以天为单位,分析用户在这一天内的主要活动和重大事件。每一天的总结应当独立成段。每一天的重大事件应当按照时间顺序排列。 +2. 输出总结报告。 你的总结应当包括但不限于以下内容: - 用户在这个月内的主要活动和重大事件。 @@ -113,7 +134,7 @@ def do_analysis_on_history_messages(df: pd.DataFrame): if __name__ == "__main__": - df_month = load_history_by_year_month(2025, month=1) - summary = do_analysis_on_history_messages(df_month) - print(f"Loaded {len(df_month)} messages for May 2023") - + # df = load_history_by_year_month(2025, month=1) + df = load_history_by_year_month(2025, week=2) + summary = do_analysis_on_history_messages(df) + print(f"done") diff --git a/src/model_manager/__init__.py b/src/model_manager/__init__.py new file mode 100644 index 0000000..e69de29