@@ -79,6 +79,8 @@ const warnings: Warnings = {
7979 missingType : [ ] ,
8080 failedImage : [ ] ,
8181 missingWikiThumb : [ ] ,
82+ missingReleaseDates : [ ] ,
83+ ambiguousWikiMatch : [ ] ,
8284} ;
8385
8486const filterBps = ( blueprint : Partial < ItemComplete > ) : boolean => ! bpConflicts . includes ( blueprint . uniqueName ?? '' ) ;
@@ -223,13 +225,20 @@ class Parser {
223225 this . addDucats ( result , data . wikia . ducats ) ;
224226 this . addDropRate ( result , data . drops ) ;
225227 this . addPatchlogs ( result , data . patchlogs ) ;
226- this . addAdditionalWikiaData ( result , category , data . wikia ) ;
228+ this . addAdditionalWikiaData ( result , data . wikia ) ;
227229 this . addIsPrime ( result ) ;
228230 this . addVaultData ( result , category , data . wikia ) ;
229231 this . addResistanceData ( result , category ) ;
230232 this . addRelics ( result , data . relics , data . drops ) ;
231233 this . applyMasterable ( result ) ;
232234 this . applyOverrides ( result ) ;
235+ if ( ! result . releaseDate ) {
236+ if ( result . masterable ) {
237+ warnings . missingReleaseDates . push ( result . name ) ;
238+ } else if ( result . category === 'Arcanes' && result . wikiAvailable ) {
239+ warnings . missingReleaseDates . push ( result . name ) ;
240+ }
241+ }
233242 return result ;
234243 }
235244
@@ -517,7 +526,7 @@ class Parser {
517526 }
518527
519528 if ( item . productCategory && productCategoryTypeMap [ item . productCategory ] ) {
520- item . type = productCategoryTypeMap [ item . productCategory ] ;
529+ item . type = productCategoryTypeMap [ item . productCategory ] ! ;
521530 }
522531 }
523532
@@ -880,14 +889,44 @@ class Parser {
880889 return ;
881890 }
882891
892+ /**
893+ * Map finalized output categories to wiki data buckets and merge handlers.
894+ * @param itemCategory category assigned by addCategory
895+ * @returns wiki bucket and handler key, if wiki merge applies
896+ */
897+ resolveWikiaConfig ( itemCategory ?: string ) : { wikiCategory : string ; handler : 'warframe' | 'weapon' | 'mod' | 'arcane' } | undefined {
898+ switch ( itemCategory ) {
899+ case 'Arcanes' :
900+ return { wikiCategory : 'arcanes' , handler : 'arcane' } ;
901+ case 'Warframes' :
902+ return { wikiCategory : 'warframes' , handler : 'warframe' } ;
903+ case 'Archwing' :
904+ return { wikiCategory : 'archwings' , handler : 'warframe' } ;
905+ case 'Primary' :
906+ case 'Secondary' :
907+ case 'Melee' :
908+ case 'Arch-Gun' :
909+ case 'Arch-Melee' :
910+ return { wikiCategory : 'weapons' , handler : 'weapon' } ;
911+ case 'Mods' :
912+ return { wikiCategory : 'mods' , handler : 'mod' } ;
913+ case 'Sentinels' :
914+ return { wikiCategory : 'companions' , handler : 'warframe' } ;
915+ default :
916+ return undefined ;
917+ }
918+ }
919+
883920 /**
884921 * Adds data scraped from the wiki to a particular item
885922 * @param item to have wikia data added to
886- * @param category of the data
887923 * @param wikiaData from wikia to apply
888924 */
889- addAdditionalWikiaData ( item : ItemComplete , category : string , wikiaData : WikiaData ) : void {
890- if ( ! [ 'weapons' , 'warframes' , 'mods' , 'upgrades' , 'sentinels' ] . includes ( category . toLowerCase ( ) ) ) return ;
925+ addAdditionalWikiaData ( item : ItemComplete , wikiaData : WikiaData ) : void {
926+ const config = this . resolveWikiaConfig ( item . category ) ;
927+ if ( ! config ) return ;
928+
929+ const { wikiCategory, handler } = config ;
891930
892931 const slots : string [ ] [ ] = [
893932 [ 'Secondary' ] , // 0
@@ -907,35 +946,22 @@ class Parser {
907946 [ 'Railjack Turret' ] , // 14
908947 ] ;
909948
910- let wikiCategory = category . toLowerCase ( ) ;
911- if ( category === 'Upgrades' ) wikiCategory = 'mods' ;
912- if ( item . category === 'Archwing' ) wikiCategory = 'archwings' ;
913- if ( category === 'Sentinels' ) wikiCategory = 'companions' ;
914-
915- const wikiaItem = ( wikiaData [ wikiCategory as keyof WikiaData ] as WikiaWeapon [ ] ) . find ( ( i ) => {
916- const uMatch = i . uniqueName === item . uniqueName ;
917- let nMatch = true ;
918- if ( category . toLowerCase ( ) === 'weapons' && typeof item . slot !== 'undefined' ) {
919- nMatch = slots [ item . slot ] ?. includes ( i . slot ?. toString ( ) ?? '' ) ?? false ;
920- }
921- return uMatch && nMatch ;
922- } ) ;
949+ const wikiaItem = this . findWikiaItem ( item , wikiCategory , wikiaData , slots ) ;
923950 if ( ! wikiaItem ) return ;
924951 item . wikiAvailable = true ;
925952
926- switch ( category . toLowerCase ( ) ) {
927- case 'sentinels' :
928- case 'warframes' :
929- this . addWarframeWikiaData ( item , wikiaItem ) ;
953+ switch ( handler ) {
954+ case 'warframe' :
955+ this . addWarframeWikiaData ( item , wikiaItem as WikiaWarframe ) ;
930956 break ;
931- case 'weapons ' :
932- this . addWeaponWikiaData ( item , wikiaItem ) ;
957+ case 'weapon ' :
958+ this . addWeaponWikiaData ( item , wikiaItem as WikiaWeapon ) ;
933959 break ;
934- case 'upgrades ' :
935- this . addModWikiaData ( item , wikiaItem ) ;
960+ case 'mod ' :
961+ this . addModWikiaData ( item , wikiaItem as WikiaMod ) ;
936962 break ;
937- case 'arcanes ' :
938- this . addArcaneWikiaData ( item , wikiaItem ) ;
963+ case 'arcane ' :
964+ this . addArcaneWikiaData ( item , wikiaItem as WikiaArcane ) ;
939965 break ;
940966 default :
941967 break ;
@@ -947,6 +973,40 @@ class Parser {
947973 if ( item . introduced ) item . releaseDate = item . introduced . date ;
948974 }
949975
976+ /**
977+ * Find a wiki entry by uniqueName, falling back to an exact name match.
978+ * @param item item to match against wiki data
979+ * @param wikiCategory wiki data bucket key
980+ * @param wikiaData scraped wiki data
981+ * @param slots weapon slot compatibility map
982+ * @returns matched wiki entry, if unambiguous
983+ */
984+ findWikiaItem (
985+ item : ItemComplete ,
986+ wikiCategory : string ,
987+ wikiaData : WikiaData ,
988+ slots : string [ ] [ ]
989+ ) : { uniqueName ?: string ; name : string ; slot ?: unknown ; introduced ?: string } | undefined {
990+ const wikiItems = ( wikiaData [ wikiCategory as keyof WikiaData ] as
991+ | { uniqueName ?: string ; name : string ; slot ?: unknown ; introduced ?: string } [ ]
992+ | undefined ) ?? [ ] ;
993+
994+ const uniqueMatch = wikiItems . find ( ( i ) => {
995+ const uMatch = i . uniqueName === item . uniqueName ;
996+ let nMatch = true ;
997+ if ( wikiCategory === 'weapons' && typeof item . slot !== 'undefined' ) {
998+ nMatch = slots [ item . slot ] ?. includes ( String ( i . slot ?? '' ) ) ?? false ;
999+ }
1000+ return uMatch && nMatch ;
1001+ } ) ;
1002+ if ( uniqueMatch ) return uniqueMatch ;
1003+
1004+ const nameMatches = wikiItems . filter ( ( i ) => i . name === item . name ) ;
1005+ if ( nameMatches . length === 1 ) return nameMatches [ 0 ] ;
1006+ if ( nameMatches . length > 1 ) warnings . ambiguousWikiMatch . push ( item . name ) ;
1007+ return undefined ;
1008+ }
1009+
9501010 addWarframeWikiaData ( item : ItemComplete , wikiaItem : WikiaWarframe ) : void {
9511011 item . aura = wikiaItem . auraPolarity ;
9521012 item . conclave = wikiaItem . conclave ;
@@ -1018,7 +1078,7 @@ class Parser {
10181078 item . wikiaThumbnail = wikiaItem . thumbnail ;
10191079 item . wikiaUrl = wikiaItem . url ;
10201080 item . transmutable = wikiaItem . transmutable ;
1021- item . type = wikiaItem . type ?? item . type ;
1081+ item . rarity = wikiaItem . rarity ?? item . rarity ;
10221082 if ( ! wikiaItem . thumbnail ) warnings . missingWikiThumb . push ( item . name ) ;
10231083 }
10241084
@@ -1077,8 +1137,8 @@ class Parser {
10771137 * @param drops drop rate data for refinement-specific chances
10781138 */
10791139 addRelics ( item : ItemComplete , relics : TitaniaRelic [ ] , drops : RawDrop [ ] ) : void {
1080- const hasRelicDrop = ( item . components ) ?. some ( ( c ) : boolean =>
1081- c . drops ?. some ( ( d ) => d . location . includes ( 'Relic' ) )
1140+ const hasRelicDrop = item . components ?. some ( ( c ) =>
1141+ c . drops ?. some ( ( d ) => d . location . includes ( 'Relic' ) ) ?? false
10821142 ) ;
10831143 if ( item . type !== 'Relic' && ! hasRelicDrop ) return ;
10841144
0 commit comments