From ad0e57a28501446143ad84cdea722b5db4a41767 Mon Sep 17 00:00:00 2001 From: Jonathan Harris <jonathan@marginal.org.uk> Date: Thu, 25 Feb 2016 05:39:34 +0000 Subject: [PATCH] Add "entitlement" field to collation --- collate.py | 21 +++++++++------------ coriolis.py | 3 +++ loadout.py | 5 +++-- modules.p | Bin 20543 -> 20629 bytes outfitting.py | 33 +++++++++++++++++++++++---------- 5 files changed, 38 insertions(+), 24 deletions(-) diff --git a/collate.py b/collate.py index f3910af5..e3df2c1e 100755 --- a/collate.py +++ b/collate.py @@ -68,29 +68,28 @@ def addmodules(data): outfile = 'outfitting.csv' modules = {} - schemakeys = ['category', 'name', 'mount', 'guidance', 'ship', 'class', 'rating'] + fields = ['id', 'category', 'name', 'mount', 'guidance', 'ship', 'class', 'rating', 'entitlement'] # slurp existing if isfile(outfile): with open(outfile) as csvfile: - reader = csv.DictReader(csvfile) + reader = csv.DictReader(csvfile, restval='') for row in reader: - key = int(row.pop('id')) # index by int for easier lookup and sorting - modules[key] = row + modules[int(row['id'])] = row # index by int for easier lookup and sorting size_pre = len(modules) for key,module in data['lastStarport'].get('modules').iteritems(): # sanity check if int(key) != module.get('id'): raise AssertionError('id: %s!=%s' % (key, module['id'])) - new = outfitting.lookup(module, ship_map) + new = outfitting.lookup(module, ship_map, True) if new: old = modules.get(int(key)) if old: # check consistency with existing data - for thing in schemakeys: - if new.get(thing,'') != old.get(thing): raise AssertionError('%s: %s "%s"!="%s"' % (key, thing, new.get(thing), old.get(thing))) + for thing in fields: + if str(new.get(thing,'')) != old.get(thing): raise AssertionError('%s: %s "%s"!="%s"' % (key, thing, new.get(thing), old.get(thing))) else: - modules[int(key)] = { k: new[k] for k in schemakeys if k in new } + modules[int(key)] = new if len(modules) > size_pre: @@ -100,12 +99,10 @@ def addmodules(data): os.rename(outfile, outfile+'.bak') with open(outfile, 'wb') as csvfile: - writer = csv.DictWriter(csvfile, ['id', 'category', 'name', 'mount', 'guidance', 'ship', 'class', 'rating']) + writer = csv.DictWriter(csvfile, fields, extrasaction='ignore') writer.writeheader() for key in sorted(modules): - row = modules[key] - row['id'] = key - writer.writerow(row) + writer.writerow(modules[key]) print 'Added %d new modules' % (len(modules) - size_pre) diff --git a/coriolis.py b/coriolis.py index 9dc6af02..a1a70200 100755 --- a/coriolis.py +++ b/coriolis.py @@ -326,5 +326,8 @@ if __name__ == "__main__": } else: modules[key] = { 'mass': m.get('mass', 0) } # Some modules don't have mass + + modules[('Planetary Approach Suite', None, '1', 'I')] = { 'mass': 0 } # not in data at time of writing + cPickle.dump(modules, open('modules.p', 'wb'), protocol = cPickle.HIGHEST_PROTOCOL) diff --git a/loadout.py b/loadout.py index 194f030a..7c07791b 100644 --- a/loadout.py +++ b/loadout.py @@ -86,10 +86,11 @@ def export(data, filename=None): else: if slot.lower().startswith('slot'): loadout[slot[-1]].append(cr + name) - elif __debug__: print 'Loadout: Unknown slot %s' % slot + elif __debug__ and not slot.lower().startswith('planetaryapproachsuite'): + print 'EDShipyard: Unknown slot %s' % slot except AssertionError as e: - if __debug__: print 'Loadout: %s' % e + if __debug__: print 'EDShipyard: %s' % e continue # Silently skip unrecognized modules except: if __debug__: raise diff --git a/modules.p b/modules.p index c6358e9c5b6a96c86f87847f5c7ea0dfb8b4af2a..200e1af97ab4dca64cca3a3c66d04f57b9466af5 100644 GIT binary patch literal 20629 zcmZ{scbr^h^~TeaNr40sQfL!kVSx!t?~vVWDx1KP<c3}*yR(_u?C$K`-3<f;qavVU zMNzO2yI2q#HdO42V8O1aAT|^Wg31q3f6w=xGxxohg#6)0p7*@xJ>@y)eeZkk?2ZZ7 zG{(2KMvJ=R+Q?vewANGHP_0!4dW)+nLzTEZT8|qO&W^^P7>(~3y{0iSnlxA*8EH)F z>K<v04qQ1_87OXy%R?i5mAJUJHaJ`vEq2z2M&tUxKqYQW*34s~@hdcQN_EnzrBB_@ zzXvpR>W0eDNIf2DOqIy7rhJ-2+9!=m{z+uf`bxQHw6?8M+%OjRm3u1EJUCn*sf|_| zg=nvh+lMPlPO{a9>+z_To1Uz;Myt)JPU>1Z(poJ<d#sUBajiU1Tv6UKP-)CeWoAic zn$}skthVI5N||+@>-ios?zm`tr!?*<>B*9wp7^|>r(Pd!%+~M;Hathe<1{?Ct2QuD zJg*!pD5J#<J>?-qv9Xr~kG44MosYwu?)nu9-SXPVXk6PoM!4si)@53Bp0pOFb-~KG zJeb(mH!9^@^?zOSK0)*Ryyltf#s)@fOFCsieW<ZOa>~RiDP1U~6BHXFFNk#(85B)% z>3wZzrH1zNp&4dq_kjFr?5}Y-PF@et_*|K|Zzn15kpsKo!GWfaI2Q9(&i0shRur~n z<)N*O#ikp!9b~$zL_`E+`oV%)Wjvu5gawBPBJ{J@S879j^|+_fTkIGZsBdqyL{m2@ z2xD=jacG+M!z4aO;?vew`f5tf_C~98IRy`QUHfMPzC4D6YlcLz-Wnb@j<6XRbYz~i zbJo_jR7bC<@V{<FsTz2>#PnBNs)2_`37aH?7OktraXpsxyYjs)n$o>}w5mjkMoJnS zKSuLT2zkVqV{^f+;+TY&YvedznCKpFaXVhnbgescZLN<Q8>WgHCrIEVW5tOQ*dc+v zlyvomVn<I;MOB^jgp*7USvpx_v)vAb5j#%F2j#%k<<XvMaamjub$7>)Q_WDad72xF z9VeTirwiJt1xnG(r07p6u2#8jZ=8{a;!L09JVVb?Lh*33nIwD>W3jj0grhmT<haqH zMV$%D)T8Rdqe-{x?7A?T+NWMOI5yB&zG~@>H;>-af9*3FC!?u@<tveBtXQ@5aqDtX z0brQ=ZmjH@FxFc2*kax)89@u(w?j2wTuH}WvaVbc$A-#7YIV_2ZM3o4!h+Fj-010@ z<#<cIxW3%8wQ-h)l`7PA`S70dY0F?mt;Z{Qt$73m)=5S@OX^;wL*1V(s9g{RCRUKT za|DSMRZ86B-z|vvw|Ub&G1qj@O|!6Ga`Peb>M<2_T8)W0-7>hmrPA0Swca^4+TziI zb+v)oXgS_qTosplvt2%l<}R<52kS$<n>D?-;>zIx)koaelrDLmbhOE|LNvLfw^u{w zr$ZNL=oSrmtrElwGa1teY;mezBw<m#DNJlG7DTw(GUa=TFt!!E(7r%aFBPO+qzZLB zUYE62JG;hJMU?ArIC8?wHJ_2l&gu$5D_6BoJudktHjrJfm&+wFPLV5Ytj1#_>N6va zvPP8>%-*a~QW8b8S61Yt_Oj)1eR!l=8*cQZ{`N}hJV{YYZd=9GE?hxpj_X6(-8<`J zG_t`;d4#^$Cuy}5I{g+ZCf%W{?A@NJs`RMGC(Mz>5U!RFCB8_Qfb`p<O39w-*4sHY z%Kp4HHFiKkr%Pign%-I89G8phwyxRK7)-~9TnX*U3$mVDF<RKUeY8H(qkVC+dQx%O zSUfUXTw5N|GQ*mrwues*>0z%UJBlWGjg_5scaJAM*Io6<sypXiEt%QX73tA~EKTT3 z{wYho!IFoOe1N=Y7#WocGSn8$Tv>^i^j4OvrHUJ4sYBZ&ai}spYn}ES**P}UQ<bS# zn5ne$E6voXxg&=2*LE|Wg|702@W-ipHU8W;E$`0`{An?&;m;Ingz|^9iXKGb1yTle zeJ@4-HG)LMqz+u_T9@)on29eG)GjFub1QZTqJTVHNWCZ@E{+>25PHmuCA?F@Kw1Sp zy+n|XS4k%lk&wDh5Uj&jO+@8O)5=Oyw{G0{=PfNfx?WoFs3n@dq1IcuqBcaExFJo< zjT(m`-tSoDWrFa9g}qU}oFG3mIUnS9g1pF>LXam}-yhR?jbl<J>1mrP)mqO$rMS90 zw51$3ULl<#^lB}0la`s8ST<#Kd5q)oD^sgprLplED@C(I5!J`ynxtNxO1(x>_~xZb z&|WL3S*l);uM<R?eUl|9H`~N$-ug=O*jZdwDGz!9y<SGDfXK@mBuRMKM;yAvA>VA# z_eO^nn|B!Urd+vJ%Np^nbgKzRi#mF@Q6;^cetYWMbQDXEwYS-FD0;K&_RSEZ-XaLU zNsyc*XKy7zTPNldR3t&OLxLvW%D>xG1(4ah_1mOurz&%LCIGi<SXrW-?bI;afRlmc z-_Bb1CToQT-^yC^LdB(INSLMGgR*zHG7bVV9A)nmM8cwK$m_d=DPvI~dDhs-srcQR zq4*P!_h=OFsXoyY=)Hnk1$mUw`#wPw6jI)^@5rZw$2wIn`Fp>F6@w~I2@<Aren1d@ zd%wW?4+??{-Y;1ALxQk{g}u1%bX|VfLF&VTIPA>GcImsqS|8E4){6GhxlRvFwV|z{ zLw;0Z+Mwu=AImqC#TxOR{&6Yb2-<2o@&6NounaR4IPAZh`Qb?D4ULgc`g}O1kYMwt ze14%C9vwa{>|p7Ps$+>#jAC<FV^4aSB0w}hD~M>afU*p9k07$l!9g}-;O7Jt1#v!c zdVF3GF>k4cQ~no(EfVIBWX!x*5P9&jNB<WEHOpR{K<Z0^-~?qaD{%A6f{00>8g|;R z2-{bfhYqo?x)^y@G=RR=oEgn+9zi-rM%1;GE{-8zPvh|oNpcKfvZ#b{-}K4eVu|j3 zg2af#IOpKET#DLLr$Fj{L3FN`YS90Hu#zwj8~VR3h}{=Lc=o;{2>r0%>-@Wd$O<`@ zekOiT5b;3Dv+|(pqPa<m*7AKpSmA_b;tvF&9w$XEq<-kSh@<QJkwdH~Bar&BLs2Hf zKM}@rTuU^qt5O-@sN48y8qc3;lwHEZLNb0X2!nk4#Gr=+QSBZAmimRD9fAmyckW;2 z3MkrpL$$7Bb^b*1D-(y>4@(0)^G3tcj|igBaLK#MuLTiAT7a|VQ9(sP6o4SC`Hdi~ z@y3g;-wJA1)$i9G*GGn*@9N-p(&0t)drfGP+;j5>LCxH_laJ+`R8%M1#m^tpkp4-N zC^M%JOnY1q6v7Fm3iJLfNaiJw48V!M2*NLNq19-Ue-%WGI?Ppc{f+Hm+Elip9h=uZ z_{1I0N~W9bVX>XUc0G`J+@5g#e!aqye-}i+J&PFj<gRVZ3+*Y5gbTD}<B{dq^be_N z`sXF`Pppz=ozt5oy=rVId8qhT8mgxyL^Zc$&mjY~VO^;;{x6k!Mp6ez3RY-Ay3fA_ zjT2O=hPV?4FvQ&B|2X7X#^e7ABFI#rl;QFJ1U0j4sffpoA2-eg$(aHmH{<aMnvKEY zR7*U;rZg+Z=n_w~DVYZ!%F4`(Cxuno!afjBHkhpdUsUd@!FY<Hc-U$t$(?v=K(R%< zl}GV3LtzdTA@e~ChH~(02`xIFZtxz0p@B88c!r@={aL0$agS#jiV<FF7%?kBbyOD2 zejxV{-XjS6=^QKeG_+l^5YfGxZ79om{!lz8Xkde~mJsh{C^bfMtXAW_4JG~^0i7#U z1=Dp+{^&MM^|JKoP%q=t$7XNoM0}oU-02!^`;GT;jmZ;udR6m$PvA0+P|P<~#4U<u zY^sUiJd>_j6EDz6lj-q76Dvpz%8EloY*B({&lUvE-QL%x5R6i|^^5m2xS1#?@cyPL zQ^Zh7nqc<<VM<#xJ+*ODe4qwW6N@H=iKN>7Tb#~~W^|7YjPMMqXXW@H;pT|0hU0@x z3R=P`+sEQV(z(f&V=X0aF_eZ(>Lm*y4mFgPRSKu1_^_aYx)%R%sMS!q5VfIblGVc# zG<y}{$7Mo&giV1&Y`z|uBZK;uYI-dgmkjQbu-|{HWyebl#YtFiN9gz{LtBOVi3wV? z1;t+J*nM<B{pf(}#~6z1_~@n`YiRQ*?v;0(p?HpSUjN4%N|pM_0vk>+6s8n1AwAJx z&YpfoCwM0r%5tcXb42arpaPdYucsKwz5ri65T_bSUU5zaqxUpJF&J5)xO}>y?LwpK zzfuaGVX!uie&?4QB=l$60JVU1w$sK-4aGqZJu9}SsIKbEwSl5`r?^9)CQ2R4FAM4l z(WG<Yo^sqND79m`jkAHZ_2=q%g^f@ozO$llrJ*nbCp{~x3?(bD)HAr+PyzxoR1_G! z#!y@#&~E2hhT?W1nvq_3skwA%BsF)fiE$eD%@3993@tk9E$8e6&9t0o!E#+V)CMxI z5Bwcbe2!#gjAlaKZl4)$`rIoPJJ%M&EA01*T))edw*Fk8H`p`+T{gF2-9|$RoEHyt zjtnJ4$l4YkZ!(m+_B{^S^9+T}g?s|fw-FLZhm@hnUl4R-zEXw97aH13mGk_fAlsJd z%NHBm+@+L3R9qsIUF!7QsV+TeuvtCYeD+VS`f<YfbE#=;hQZTtSy-M9;BESHLvgq* zJoLn6gNZN6^19h<XuDA2>$Tn!6t{#sg}B#X+lJCd+PD&=ov>uC&rnS6kY*?M7NMMN z7fm7xVP~DI3%JP~YSa6bXrApcy4Z=whLd-K$!=4X2I*5^$X3l(!6e@lSi9d)_)d>- zerz=q)?kq|P_P3+NlRD$@GyydJZ6_YReSZ~&oC@IXsYP+gw5-DC@esTJs)*L$w!pQ z$FRZVqYy6TJL~bbN^;Sy;k2q_ljXKsPk0?e<sQAyD90mNnNgGB49&5^c{^q(y!9+# z{x+dx;phoC9WJ1hg;nj-cXQbl&9Zk!&315w6lf7$F~ICAlSQ(-E%hY#$;EcFfT(kG z;d#5tP)dYrDX|enR|na)%wF&Ug9#M}Qr~*6F_f*xkEy7**3g~WH@wlSSg_-THqbmS zdkO7G(5&fnZ9j;-$fjVV7YF_A#fIV#ri)yx`;rumW_8!~60W$s(pS;dWPF`QBxe^; z@k<lAOw+AK{kaZ)y(yxD7y5G<zQIOd0aw7PRb2tcHyV17(6XVh`elZ;3-#-CjC^^5 zX1tB&>&d+~v_&U5-WZ1K%lH)%l{ydJO{Px4i}vuh?aS(Q-ZI6nG(ovXlwW0nRK2$( z)_t|1lmLaHY-8hV64ah35ca6Q)`VwEn7q0LuS?Ku+&EoI6MVkerjQapOtI?g4TT^r zQK4gGSXaaKvC;Sq!qd{a#f0YhR4<!18cNx;Rnv=<_)P}S7wjh(R=+g}^GaL1$Gh7M zZEgZmOnlxfl*-#UCEsq6Yv#q_StYz|p@BK$-(o7|W;APKJsz&~){EWS2kJxdTQy>_ z(xprMHj{(uw;PI?w+9sCz18nDlxUM0p~$}7Q2JXTJblOSFc_b_5b^Y#K?TOD!ioO7 z3?(OiJOX`pf@T>wb6ss@L}!lVeRTXDjhhZMzt?mmho1gi+TLd)N4O;-38i_*bG29b z`o^2f`)$fjP4Po13HgAbMWHk;=imno#rQ&XQ%aT(8O+;aYR%bqXHe{%$CeKp3g_>V ztSsc|=q^J^4K2kre8f<e<2lGX=SK}yw3|m@-%&o64kSw4=8p#@_~&W(M1rQL46Wc# zbl7-znBr$0&`%mF@<(&^&b`*BH%3K13h)ns;!jDy%p|3sHgQPd&$FPPNzhE9n@yS( zK5J7*g+JzyihB$tHc(NG6)JwtP@W}-uDkVlQ=fUrC7dcU)PKRI5KbcD+yA|WVrN@5 zeR&su(O@{{>}Az21r^>uvGB_Y`dp{9DpS5<Q|K8j)%2Zu{8fXwZ*I$X`mfmtogSL{ zM)Gw-@wX-OsP+wm_ZIBgr9i%ED8}<DM*P74`wXS=d9soHmZ3z&-_c<8{Xv6g4-F3_ zXx35qq2|Egw{1$R6cKdUjr#8d_5R=k4ZgdJA}sPQ`@JxQ)T$Uz|Dd6eqY$pR<L?{H zEqAHEq5nv$@&`dpht&89<A*{y*BzZZ;-rPJ>v6j!|2*;|)5^vWWm@2m4TeSJ!Atcg zhC<y!=JMdD1~)$;ap9i@VfJyAFZ=k<4OQNo)vlJo1MfpY+}TXHe_?3R?eNt6(oj+Z znVp%xGL+1NYC+=sa6sFt=|yb(h`~B#WM4sd3=hZkvOd7tFs5%O<6lcinq=Xc(fCpQ z$2IY9f;xY2fnL8&&@}3@pj1si;fQ}1=9Dt2{(XRHvkDtj`h%e~RDZ-L4vz)dLjQsK zkCYaFv=JWf{7i?IKLst2SGv*ic+lcmMfT4@)+tTg{*s{C+Q3MK8byD#DLb@itEndn ze@oT(hm$knPwb)#27B86u0hTUJCkn)!YTdv-vdOM3+5+nO)i)zZ0{~l8QScozBT^C zP)d%Vcp?7NP-x@6;Qqe?x>&MaZBHj?HqQh_Oe2o}XH)1$rTioKGeKFYntr+v|2x2_ zk?pMftfAQMyA`qhkD;_(tP~|#^1pcviYOZX7i78bk}O?)+yveOWRI5c%Lm6NgULGw zjy$etf}t#mfqrV5XeiYOUnGkulLAU%C?=Ra*-&EQ#{+78ilOuo^eVWRJvBiy!Ho_` zz9b#2^w!Fwm0iDmh^J|W=DQDtpcS{>hv|mmgLi)Hnqg~Y-enXr&0(g^;St2^1p8(g zN@e1=(nVPJFjSo~LwW}G++~TjOi!2{mLT9B+Bt?2T4yMs-OErI>Yqo0?!AkCY;~&7 zwJA`YJ;$jv&rsWR&rJfyL3$s9d3V~Dxd)kVuslorRSzKw3lcPwrRD<Iv@k5dM(v4R zWGI2_Fkgw!zCx+{lao7=^eZL%z-+glhfogg$$sfV(Sr1|pVj5TL7m~!E71KVWLD6G z4zMXYL_~XZR?B^T>6a7nfhOqBuEj(!+xfgC@Nltd5uN(|5HI$j{vaF39C>l_U_(ir zmpJS@#8C3!Oht7|s#<9XC#ypZ=32lLjN-!#Z5N7l3JZ!`gJNV=gvcIlD90yn@W>vK zpxH$7obT0qq)owYP|*_$O95qvmFJ*K0;;e2cmQpFei|R8p_FEACdb1J<j`#RbaaAd z%^*;+oS+_KQ)X)l#p@J2)=>C_alUaLXDB9@GPf$n2N?1xP}qEeP{?;ray1lQK0oi( zP_yzd`NTwJmLP5U$F`GfO+0n#kcN{DEehqKUjCDYQw+sy|5g_CR72%>zd!V<mZ;U! zY=B()Sryf%r{bbc`o&6ohQXO@a(qA2P}m0@d>dS9D1Fk46xnv6#Obc2NJE^S{~NAS z=0UQ<bmANB%wxYSps-&kE_517x8Y&Qt7^HS&4(og0a~mulptWMP&BL*DqFiw%-=ca zqsQl7IkSU`VdQd^slr4*oU_2{1hqRGGU(Q<F=1KLJiLl~Y-nfM0LJ@<K@z(Rg{P%V zL9aEKCD{|D0_)cW6^jie{$~djQT5!!5Lj@I!MdS|bg|%9TfC&~)_~cI&T~zS=uxlU zB-R_s`emVhrruyETMyOg;n`?t^DrW=5S}POEj&@4`kQP5)c1Q(3^~tG62_9=m(CBU z69MHH7+RF9H+*7wp`jQ;LX>jQixM>3JV>n~ilU2c3VueJ+pS9s=5{N}Y{-`y%%1N= z!0^iqZ5K)eWjI;6JZPqpee*5{GzwqB$D0k-$M8+kxbZzUKu}8gAod1LaKZQVilIB* zLUn2^>@$>bwd5bXx7Y|DLlAUD1;SSig_Pb>31lsx{yPX{`whiHKk2dJRzq2lnD{ws zz|e6*iHUP<FrZQO{FJ{#2J^&-3NPz=D%>BgTgl|G4NP=96mQUmq1XW>oK&%)O`AP8 zBZk86LWT>Y2Ezsa-Vg`J3}x3LaNf4I843d-h-@ZAS0rebfgKuD#!z&n2I)x2_Z8uU zqpzW#`wIu6;KjAw)*+B2$kTk4p>nq0Yg`7f#?>}Jjr-<KY+evh&k^V~L3K+e8`m1l z%YXJ$C;1D5uwQ1NVn;x^1(p#M#ET47&@-81;Keq8bsjX>_L2n62952(o9uOA1@4P{ zg_rI!#Vdm(TyIl$YL&K(UpE*G%OHpsz>S7d04@0&mY3NG@0MIS#=bnGJpZQR6*fZ4 zDCKWeZn6<_2pyc7uN2B=dfIb-QlXb{T@!dK7=BAp%8>L`K^Xy2n27AF6Eu4W@kBHD znlQ!pI;is6fU-+DfnH}Q?=qsyh2hNxQ%7V@b%cu78%k+-;ex&)DCXHu7Lt`)5;SX} z^BEq!(WdN>BDaMpZ?Y+w`%b8*#NpJfVHGw8t-{*3`6}USWy(NP7<{u$fqrG7sxVf0 zi=og3-g%37Yfw-2z3Sg)C{^#WSbuwv#T4m<DLaGSD02#XyTP2oh?x|l;vGQ+6mfFC zQz#wd7S1r?z42tuFwfeLCLl`q#>*cFarRw_#%#PvoJZo_wj7bbJE0iy9z!{|v}Crd z_ZnOj9Oa4qJ{#d-1mz+&0lmXep7LAzb7%hd+X&Z-aMzzMK42(kP2Ypa?*|Q~Fr9Ij z_#s2vg+_VZciIR?4L>L#|6xP1otEw_xy#UImsHBJ`y+;uTz{<&`cXr72qjd~fZmS< z4W-OU?BfQH3&N!06A7BVYjINI=iN4#A^BZeMj3%apEP}B1hRPcJ{4AJiRNT~>1Xfy zKCSV@QVxfoG2vNmk~g2v8rrO9NAC$JEcASSPAH9PR`PTdXgFPsYGS@oQM|s_f8KNv zO|mMKP<+8q9P(Tf&3gk{$TXcV8r<BxWezd<lA+LxUxBG_;pUfvET;Q%UlEGw+Y-~m zp37H~yM5=MG-!pH%zV`*clA<z;bAAKz9*X>t?Z`y@aSuaIlHMo2ET5$5(I4ZtbW6n zyD<O2GJ#^>?Q&jnnEFlANKD{~IuPi6hQh|S%yZbc4CcoXP)z|OtoIvAusvU(4;V@o zsUHvPw+*GLFe2&j@plC3-A6K%b=-fs#f!l2*}N&5=X53<4;qS@rOdV4_X8Yd;2#*w zHXG$P;2(yOQvO!_M?sZu{jB?ALrDW2!)xFth7t$A5k>Z=K|>*PXZtgQn~lT|zdtv$ zRVvseT=7FeMJaFiFT#lPfzba_D9yhcK7@<#=cgYnRcn#?UztYuz!oeNCmuGG?V5)= zC6fmCh@rB!`9$J`{Iv}bA14*!j~Yt0;E7zu*xwjR5BDG3Q0>1pw7JcApZ%Sogr|_X zVEnzoEZ5ebYhiz|5eVyv!pFx9#YayR=pPNmJf|k;pAt07N;;M7AuNyEly*(=zK=(L zHnb?TELlH}|0O}~S+^yBt^Ze>z=lN@-Pykhr32aT8bb5bl}Xn$nrHaE8&ACoCnh~% zx^_qx9(zLmZYbfzBo!{QPZ|ngOPNoto-&v~EH-lx{)eIXN(7`B^q+<jdhg0)?_Y+p zTwDHV{IrcwgB&Q6`qvu|Ls`+&gzjey73nfJ;t=WI$v`$IzRwf=XKfZ7!FsI#`k!5< zM41<l|Ft<B@co;5y!fA?gr_a@N^{)A<aZFbe7hF#COF<ugo&_nh>8h@Qa9c{FlM5m z<eMt@98EHmAV4P77(tk9Xi=yq16EEk6erQ^`J8GfHc)mR+-X5?l=<qiU@&fUNZ8AN zx==`WY4T_hwk~$;=R8_KI+>0`GfWo_dHzV#OhYNNmTGv5Im=+4j-pIM+{0iv<Dnve zd!}f#=L-8%BeDOXg?P5c%uTM&=A@EIpkx^~>}4pHl``jpy$vSTxS>c9)wv0p;Z-z$ zS$U+^vzs?Y^CW5$@qZsvhwX*T1>JmuIpjw9ZDoOt@UoR_5*f?-3k@YDrTh_fk&R%l zvw-02YpB>2E!;3#<{L--vR6Ma;}bRha?coFob4y6VCw!slXH)i4+v-}^Wb}6fW4U@ zTr@O^Y5t~YagcWcV&*{s^$+oqA3hkWzYEhmrK9^0Lm_q{b2@G@nEMslhLiQspxBS- zB;zncsRI8x2*s_25?k&jR57532Mx{xYVHU_mCnp91geir2C~O--`*H31zk~o7g}N? z>_W(U(Hs@z*;D<QvMoW^weuM5yCgh5+JxC9QQ`Z~F+oL3=2gY92J;P#AFEMuoT1H! z6u07dL!mCr^2nZGD5VSP^>Jc?X6mC^Jg7fumq84bJ}7Xq>4U%CY>3z?LTNS&l4cVQ zD!XYmEtym3siq7v(D%Lhon|O$huA_{`1G)FA)k~pY(z=P>@HY!W-^fV(sviUTxzr6 zCr@I25NbD+aFvDn$)>|lat3Lga?1=Q6lhS|v9r_AcA<rQ=`XjDBQ)ZD5#p{elp173 zg&EUV8j2kx-cKH@64Xu}{sj#MxH<?&`AvF_jj&0hT!y3ktOU(owox+fYnM&IS2~3s zM%Eg-Lugy3)vq%c&N)AE>1;#cC+AU79P}JR3HV~6a+EZ58;YZxQoVnkYbZfMRz?uo z^@bLOIwPs^4Th42mV9sC7_<;@KaE9($`1Vjq2^yv*!8b8#hWB&7O~2CHjA#~dpeOk zKcKAOk46^+v_q(phyND}<t(3E{f7N`r}pFB|8X0Zy~tGI9Czqm>KCVIG@m~Xv}CpZ zFio$1jGXzP^b*NvhS$`kHiMd?7pV=P{W3#IUt8u7b-BSDqWqEqU(1G)6UxYmy4g_j z2kMG@f?^_|{E_Qkp>&CxrswanlJ9yBZ~o*U`v+J2nwjKROr;``Y2|3`O9oc8&$N$- zWe8nEhA?YOIx8WP_mZlibY__Eq^lW<gWlXx-ybxPV(BFqTN5<fT4)UJ{Xm!kSEL?A ogNDK&IPIsxAw%Ib&I*Mq^`N1YZ+63Bq%3)_t%jkkBV$MXKjNp^)Bpeg literal 20543 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 D`s}rO diff --git a/outfitting.py b/outfitting.py index d1b3f90d..77ce8881 100644 --- a/outfitting.py +++ b/outfitting.py @@ -187,6 +187,7 @@ standard_map = { 'fueltank' : 'Fuel Tank', 'hyperdrive' : 'Frame Shift Drive', 'lifesupport' : 'Life Support', + # 'planetapproachsuite' : handled separately 'powerdistributor' : 'Power Distributor', 'powerplant' : 'Power Plant', 'sensors' : 'Sensors', @@ -200,7 +201,6 @@ internal_map = { 'fuelscoop' : 'Fuel Scoop', 'fueltransfer' : 'Fuel Transfer Limpet Controller', 'hullreinforcement' : 'Hull Reinforcement Package', - # 'planetapproachsuite' : 'Planetary Approach Suite', # Don't report 'prospector' : 'Prospector Limpet Controller', 'refinery' : 'Refinery', 'repairer' : 'Auto Field-Maintenance Unit', @@ -223,7 +223,7 @@ moduledata = cPickle.load(open(join(config.respath, 'modules.p'), 'rb')) # # Returns None if the module is user-specific (i.e. decal, paintjob) or PP-specific in station outfitting. # (Given the ad-hocery in this implementation a big lookup table might have been simpler and clearer). -def lookup(module, ship_map): +def lookup(module, ship_map, entitled=False): # if not module.get('category'): raise AssertionError('%s: Missing category' % module['id']) # only present post 1.3, and not present in ship loadout if not module.get('name'): raise AssertionError('%s: Missing name' % module['id']) @@ -249,15 +249,11 @@ def lookup(module, ship_map): # elif 'category' in module and module['category'].lower() == 'powerplay': # return None - # Shouldn't be listing player-specific paid stuff, other than Horizons - elif module.get('sku') and module['sku'].lower() != 'elite_horizons_v_planetary_landings': + # Shouldn't be listing player-specific paid stuff in outfitting, other than Horizons + elif not entitled and module.get('sku') and module['sku'] != 'ELITE_HORIZONS_V_PLANETARY_LANDINGS': # raise AssertionError('%s: Unexpected sku "%s"' % (module['id'], module['sku'])) return None - # Skip Horizons Planetary Approach Suite - elif name[1] in ['planetapproachsuite']: - return None - # Hardpoints - e.g. Hpt_Slugshot_Fixed_Medium elif name[0]=='hpt' and name[1] in weapon_map: if name[2] not in weaponmount_map: raise AssertionError('%s: Unknown weapon mount "%s"' % (module['id'], name[2])) @@ -298,8 +294,16 @@ def lookup(module, ship_map): elif name[0]!='int': raise AssertionError('%s: Unknown prefix "%s"' % (module['id'], name[0])) + # Horizons Planetary Approach Suite + elif name[1] == 'planetapproachsuite': + new['category'] = 'standard' + new['name'] = 'Planetary Approach Suite' + new['class'] = '1' + new['rating'] = 'I' + new['entitlement'] = 'horizons' # only listed in outfitting if the user is *playing* Horizons + # Miscellaneous Class 1 - e.g. Int_StellarBodyDiscoveryScanner_Advanced, Int_DockingComputer_Standard - elif (name[1],name[2]) in misc_internal_map: + elif len(name) > 2 and (name[1],name[2]) in misc_internal_map: # Reported category is not necessarily helpful. e.g. "Int_DockingComputer_Standard" has category "utility" new['category'] = 'internal' new['name'], new['rating'] = misc_internal_map[(name[1],name[2])] @@ -327,6 +331,14 @@ def lookup(module, ship_map): if 'on' in module and 'priority' in module: new['enabled'], new['priority'] = module['on'], module['priority'] # priority is zero-based + # Entitlements + if not entitled or not module.get('sku'): + pass + elif module['sku'].startswith('ELITE_SPECIFIC_V_POWER'): + new['entitlement'] = 'powerplay' + elif module['sku'] != 'ELITE_HORIZONS_V_PLANETARY_LANDINGS': + assert False, '%s: Unknown sku "%s"' % (module['id'], module['sku']) + # Extra module data key = (new['name'], 'ship' in new and companion.ship_map.get(name[0]) or None, new['class'], new['rating']) if __debug__: @@ -339,7 +351,8 @@ def lookup(module, ship_map): new.update(moduledata.get(key, {})) # check we've filled out mandatory fields - for thing in ['category', 'name', 'class', 'rating']: # Don't consider mass etc as mandatory + new['id'] = module['id'] + for thing in ['id', 'category', 'name', 'class', 'rating']: # Don't consider mass etc as mandatory if not new.get(thing): raise AssertionError('%s: failed to set %s' % (module['id'], thing)) if new['category'] == 'hardpoint' and not new.get('mount'): raise AssertionError('%s: failed to set %s' % (module['id'], 'mount'))