2024-08-06 11:19:30 -04:00
package calls
2024-08-06 13:54:15 -04:00
import (
"cmp"
"encoding/json"
"slices"
)
type FilterQuery struct {
2024-08-06 11:19:30 -04:00
Query string
Params [ ] interface { }
}
type Talkgroup struct {
System uint32
Talkgroup uint32
}
func ( t Talkgroup ) Pack ( ) int64 {
// P25 system IDs are 12 bits, so we can fit them in a signed 8 byte int (int64, pg INT8)
return int64 ( ( int64 ( t . System ) << 32 ) | int64 ( t . Talkgroup ) )
}
type Filter struct {
2024-08-06 13:54:15 -04:00
Talkgroups [ ] Talkgroup ` json:"talkgroups,omitempty" `
TalkgroupsNot [ ] Talkgroup ` json:"talkgroupsNot,omitempty" `
TalkgroupTagsAll [ ] string ` json:"talkgroupTagsAll,omitempty" `
TalkgroupTagsAny [ ] string ` json:"talkgroupTagsAny,omitempty" `
TalkgroupTagsNot [ ] string ` json:"talkgroupTagsNot,omitempty" `
2024-08-06 11:19:30 -04:00
talkgroups map [ Talkgroup ] bool
talkgroupTagsAll map [ string ] bool
talkgroupTagsAny map [ string ] bool
talkgroupTagsNot map [ string ] bool
2024-08-06 13:54:15 -04:00
query * FilterQuery
2024-08-06 11:19:30 -04:00
}
func queryParams ( s string , p ... any ) ( string , [ ] any ) {
return s , p
}
2024-08-06 13:54:15 -04:00
func ( f * Filter ) filterQuery ( ) FilterQuery {
2024-08-06 11:19:30 -04:00
var q string
var args [ ] interface { }
q , args = queryParams (
` ((talkgroups.id = ANY(?) OR talkgroups.tags @> ARRAY[?]) OR (talkgroups.tags && ARRAY[?])) AND (talkgroups.id != ANY(?) AND NOT talkgroups.tags @> ARRAY[?]) ` ,
f . Talkgroups , f . TalkgroupTagsAny , f . TalkgroupTagsAll , f . TalkgroupsNot , f . TalkgroupTagsNot )
2024-08-06 13:54:15 -04:00
return FilterQuery { Query : q , Params : args }
2024-08-06 11:19:30 -04:00
}
2024-08-06 13:54:15 -04:00
func PackedTGs ( tg [ ] Talkgroup ) [ ] int64 {
s := make ( [ ] int64 , len ( tg ) )
2024-08-06 11:19:30 -04:00
for i , v := range tg {
s [ i ] = v . Pack ( )
}
return s
}
2024-08-06 13:54:15 -04:00
func ( f * Filter ) compile ( ) * Filter {
2024-08-06 11:19:30 -04:00
f . talkgroups = make ( map [ Talkgroup ] bool )
for _ , tg := range f . Talkgroups {
f . talkgroups [ tg ] = true
}
for _ , tg := range f . TalkgroupsNot {
f . talkgroups [ tg ] = false
}
f . talkgroupTagsAll = make ( map [ string ] bool )
for _ , tag := range f . TalkgroupTagsAll {
f . talkgroupTagsAll [ tag ] = true
}
f . talkgroupTagsAny = make ( map [ string ] bool )
for _ , tag := range f . TalkgroupTagsAny {
f . talkgroupTagsAny [ tag ] = true
}
for _ , tag := range f . TalkgroupTagsNot {
f . talkgroupTagsNot [ tag ] = true
}
q := f . filterQuery ( )
f . query = & q
return f
}
2024-08-06 13:54:15 -04:00
func ( f * Filter ) normalize ( ) {
tgSort := func ( a , b Talkgroup ) int {
if n := cmp . Compare ( a . System , b . System ) ; n != 0 {
return n
}
return cmp . Compare ( a . Talkgroup , b . Talkgroup )
}
slices . SortFunc ( f . Talkgroups , tgSort )
slices . SortFunc ( f . TalkgroupsNot , tgSort )
slices . SortFunc ( f . TalkgroupTagsAll , cmp . Compare )
slices . SortFunc ( f . TalkgroupTagsAny , cmp . Compare )
slices . SortFunc ( f . TalkgroupTagsNot , cmp . Compare )
}
func ( f * Filter ) cacheKey ( ) string {
f . normalize ( )
buf , err := json . Marshal ( f )
if err != nil {
panic ( err )
}
return string ( buf )
}
func ( f * Filter ) Test ( call * Call ) bool {
return false
}
2024-08-06 11:19:30 -04:00
type FilterCache struct {
cache map [ string ] Filter
}
2024-08-06 13:54:15 -04:00
func NewFilterCache ( ) * FilterCache {
return & FilterCache {
cache : make ( map [ string ] Filter ) ,
}
}