2023-12-01 17:36:55 +08:00
/ * *
* This module should contain warnings subsystem .
* First idea - there should be either definitive list of available warnings ,
* or defined as some json logic leading to the warning message ( s ) , similar way how FillExtData works .
* Second - resources indicator should be separate component
2023-12-04 17:40:23 +08:00
* /
2023-12-13 15:17:14 +08:00
import { item _occupied _counters , resource _counters } from "./count_resources" ;
2023-12-12 16:09:29 +08:00
import { useShopStore } from "./shop_store" ;
2023-12-04 17:40:23 +08:00
2024-01-23 11:44:01 +08:00
export const Levels = {
2024-01-23 16:30:27 +08:00
"reminder" : { priority : 1 , icon : '/images/shop/icon-reminder.svg' , color : "#0d3547" } ,
2023-12-12 16:09:29 +08:00
"warning" : { priority : 2 , icon : '/images/shop/icon-warning.svg' , color : "#c75e5e" } ,
2023-12-04 17:40:23 +08:00
}
const find _in _counters = ( counters , name ) => {
return counters . find ( ( element ) => element . name === name )
}
const find _previous _source = ( data , index , source ) => {
2023-12-05 17:35:31 +08:00
return data . slice ( 0 , index ) . find ( ( element ) => {
return element . resources && find _in _counters ( element . resources , source )
} )
}
const find _next _source _index = ( data , index , source ) => {
return data . slice ( index + 1 ) . findIndex ( ( element ) => {
return element . resources && find _in _counters ( element . resources , source )
} ) + index + 1
2023-12-04 17:40:23 +08:00
}
const not _enough _resource _trigger = ( name ) => {
2024-08-12 17:29:35 +08:00
return ( _data , _index , counters , _crate ) => {
2024-01-02 17:13:50 +08:00
const resource = find _in _counters ( counters , name ) ;
return resource . occupied > resource . max ;
2023-12-04 17:40:23 +08:00
}
}
const no _source _trigger = ( name ) => {
2024-08-12 17:29:35 +08:00
return ( data , index , _counters , _crate ) => {
2023-12-05 17:35:31 +08:00
const occupied = item _occupied _counters [ name ] ( data [ index ] ) ;
2023-12-04 17:40:23 +08:00
if ( occupied > 0 )
2023-12-05 17:35:31 +08:00
return ! find _previous _source ( data , index , name ) ;
2023-12-04 17:40:23 +08:00
return false ;
}
}
2023-12-05 17:35:31 +08:00
const wiring _constraint = ( name ) => {
2024-08-12 17:29:35 +08:00
return ( data , index , _counters , _crate ) => {
2023-12-05 17:35:31 +08:00
const next = find _next _source _index ( data , index , name ) ;
return next - index === 1 ;
}
}
2024-08-12 17:29:35 +08:00
const phaser _next _card _long = ( data , index , counters , crate ) => {
const nbrOccupied = resource _counters . hp ( crate . items , - 1 ) ;
const nbrHP = useShopStore . getState ( ) . crateParams ( crate . crate _mode ) . hp ;
return ( index < data . length - 1 ) ? (
( data [ index + 1 ] . consumes && data [ index + 1 ] . consumes . depth && data [ index + 1 ] . consumes . depth >= 8.5 )
) : ( nbrOccupied >= nbrHP && nbrHP > 0 )
}
2023-12-04 17:40:23 +08:00
const Types = {
"eem_resource" : {
level : "warning" ,
trigger : not _enough _resource _trigger ( "eem" ) ,
message : "Insufficient EEM connectors"
} ,
2023-12-05 17:35:31 +08:00
"no_eem_source" : {
2023-12-04 17:40:23 +08:00
level : "warning" ,
trigger : no _source _trigger ( "eem" ) ,
message : 'This card needs a card that provides a EEM connector (e.g. Kasli) at its left.'
} ,
"idc_resource" : {
level : "warning" ,
trigger : not _enough _resource _trigger ( "idc" ) ,
message : "Insufficient IDC connectors."
} ,
2023-12-05 17:35:31 +08:00
"no_idc_source" : {
2023-12-04 17:40:23 +08:00
level : "warning" ,
trigger : no _source _trigger ( "idc" ) ,
2024-01-25 17:10:14 +08:00
message : 'Should be after a Zotino or a HD68-IDC or with another IDC adapter.'
2023-12-04 17:40:23 +08:00
} ,
"clk_resource" : {
level : "warning" ,
trigger : not _enough _resource _trigger ( "clk" ) ,
message : "Insufficient clock connectors."
} ,
2023-12-05 17:35:31 +08:00
"no_clk_source" : {
2023-12-04 17:40:23 +08:00
level : "warning" ,
trigger : no _source _trigger ( "clk" ) ,
2023-12-05 17:35:31 +08:00
message : 'This card needs either a card that provides a clock source (e.g. Kasli or Clocker) at its left or use an external clock source.'
} ,
"eem_wiring_constraint" : {
level : "reminder" ,
trigger : wiring _constraint ( "eem" ) ,
message : "Due to wiring constraints, the carrier can only connect to EEM cards immediately at its right, without crossing another carrier."
2023-12-04 17:40:23 +08:00
} ,
2024-08-12 17:29:35 +08:00
"phaser_next_card_long" : {
level : "reminder" ,
trigger : phaser _next _card _long ,
message : "Next card may interfere with this Phaser. Consider placing a short card after this Phaser."
} ,
2023-12-05 17:35:31 +08:00
"default" : {
level : "warning" ,
2024-08-12 17:29:35 +08:00
trigger : ( _a , _b , _c , _d ) => {
2023-12-05 17:35:31 +08:00
return true ;
} ,
message : 'This item has unimplemented warning'
}
2023-12-04 17:40:23 +08:00
}
2024-08-12 17:29:35 +08:00
export function TriggerWarnings ( data , disabled , crate ) {
2023-12-05 17:35:31 +08:00
return data . map ( ( element , index ) => {
if ( ! element . warnings ) return element ;
2024-01-02 17:35:09 +08:00
element . show _warnings = disabled ? [ ] : element . warnings
2023-12-05 17:35:31 +08:00
. map ( ( warning , _ ) => {
if ( ! ! Types [ warning ] )
2024-08-12 17:29:35 +08:00
return Types [ warning ] . trigger ( data , index , element . counted _resources , crate ) ? { trigger : undefined , name : warning , ... Types [ warning ] } : null ;
2023-12-05 17:35:31 +08:00
else
2023-12-06 16:27:43 +08:00
return Types . default ;
2023-12-05 17:35:31 +08:00
} )
. filter ( ( warning , _ ) => {
return ! ! warning
} ) ;
return element ;
} )
}
export function MaxLevel ( warnings ) {
let mx = { priority : 0 , icon : null } ;
for ( const warning of warnings ) {
if ( Levels [ warning . level ] . priority > mx . priority ) mx = Levels [ warning . level ] ;
}
return mx ;
2023-12-08 17:36:12 +08:00
}
2023-12-12 16:09:29 +08:00
export function LevelUI ( warning _level ) {
const warning _t = Levels [ warning _level ] ;
return { icon : warning _t . icon , color : warning _t . color } ;
}
2023-12-08 17:36:12 +08:00
const crate _warnings = {
"overfit" : {
message : "You have reached the maximum number of slots allowed for this crate. Consider removing cards." ,
level : "warning" ,
trigger : ( crate , occupied ) => {
2023-12-12 16:09:29 +08:00
const nbrHP = useShopStore . getState ( ) . crateParams ( crate . crate _mode ) . hp ;
return occupied > nbrHP && nbrHP > 0 ;
2023-12-08 17:36:12 +08:00
}
} ,
"underfit_rack" : {
message : "The selected cards fit in a 42hp desktop crate, consider switching to it for a more compact system" ,
level : "reminder" ,
trigger : ( crate , occupied ) => {
2023-12-12 16:09:29 +08:00
const nbrHPDesktop = useShopStore . getState ( ) . crate _modes . desktop . hp ;
return crate . crate _mode === useShopStore . getState ( ) . crate _modes . rack . id && occupied < nbrHPDesktop ;
2023-12-08 17:36:12 +08:00
}
2024-08-12 17:29:35 +08:00
} ,
"phaser_not_fit" : {
message : "Since one or more Phasers may interfere with their next cards, they may additional space, that wouldn't fit into the crate. Consider removing cards, placing short cards after Phaser(s), or choosing larger crate." ,
level : "warning" ,
trigger : ( crate , occupied ) => {
const nbrHP = useShopStore . getState ( ) . crateParams ( crate . crate _mode ) . hp ;
const stacked _phasers = crate . items . filter ( ( elem , index , data ) => {
return ( elem . name _codename === "Phaser" ) && ( ( index < data . length - 1 ) ? (
( data [ index + 1 ] . consumes && data [ index + 1 ] . consumes . depth && data [ index + 1 ] . consumes . depth >= 8.5 )
) : ( occupied >= nbrHP && nbrHP > 0 ) )
}
) . length ;
2024-09-05 11:52:53 +08:00
// #!debug
2024-08-12 17:29:35 +08:00
console . log ( stacked _phasers , occupied )
return stacked _phasers > 0 && ( occupied + stacked _phasers * 2 >= nbrHP ) && nbrHP > 0 ;
}
2023-12-08 17:36:12 +08:00
}
}
export function TriggerCrateWarnings ( crate ) {
const nbrOccupied = resource _counters . hp ( crate . items , - 1 ) ;
let warnings = [ ] ;
Object . entries ( crate _warnings ) . forEach ( ( [ id , warning ] , _ ) => {
if ( warning . trigger ( crate , nbrOccupied ) ) warnings . push ( { ... warning , id : id , trigger : undefined } ) ;
} )
2023-12-12 16:09:29 +08:00
return [ warnings , nbrOccupied ] ;
2023-12-05 17:35:31 +08:00
}