212 lines
4.8 KiB
Go
212 lines
4.8 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"inou/lib"
|
|
)
|
|
|
|
type CategoryCount struct {
|
|
Shown int `json:"shown"`
|
|
Hidden int `json:"hidden"`
|
|
}
|
|
|
|
func handleCategories(w http.ResponseWriter, r *http.Request) {
|
|
dossierHex := r.URL.Query().Get("dossier")
|
|
if dossierHex == "" {
|
|
http.Error(w, "missing dossier", http.StatusBadRequest)
|
|
return
|
|
}
|
|
dossierID := dossierHex
|
|
|
|
obsType := r.URL.Query().Get("type")
|
|
category := r.URL.Query().Get("category")
|
|
|
|
var counts map[string]CategoryCount
|
|
|
|
if obsType == "" {
|
|
counts = getTopLevelCounts(dossierID)
|
|
} else if obsType == "genome" {
|
|
if category != "" {
|
|
counts = getGenomeSubcategoryCounts(dossierID, category)
|
|
} else {
|
|
counts = getGenomeCounts(dossierID)
|
|
}
|
|
} else {
|
|
counts = make(map[string]CategoryCount)
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(counts)
|
|
}
|
|
|
|
func getTopLevelCounts(dossierID string) map[string]CategoryCount {
|
|
counts := make(map[string]CategoryCount)
|
|
genomeCats := getGenomeCounts(dossierID)
|
|
if len(genomeCats) > 0 {
|
|
totalShown, totalHidden := 0, 0
|
|
for _, c := range genomeCats {
|
|
totalShown += c.Shown
|
|
totalHidden += c.Hidden
|
|
}
|
|
counts["genome"] = CategoryCount{Shown: len(genomeCats), Hidden: totalHidden}
|
|
}
|
|
return counts
|
|
}
|
|
|
|
// variantData for parsing the data JSON
|
|
type variantData struct {
|
|
Mag float64 `json:"mag"`
|
|
Rep string `json:"rep"`
|
|
Sub string `json:"sub"`
|
|
}
|
|
|
|
// shouldIncludeVariant returns true if the variant should be counted/shown
|
|
func shouldIncludeVariant(data variantData, includeHidden bool) bool {
|
|
if includeHidden {
|
|
return true
|
|
}
|
|
// Hide high magnitude variants
|
|
if data.Mag > 4.0 {
|
|
return false
|
|
}
|
|
// Hide "Bad" repute variants
|
|
if data.Rep == "Bad" || data.Rep == "bad" {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
// getGenomeCounts reads cached counts from the extraction entry (fast path)
|
|
func getGenomeCounts(dossierID string) map[string]CategoryCount {
|
|
counts := make(map[string]CategoryCount)
|
|
|
|
// Find extraction entry and read its data
|
|
extraction, err := lib.GenomeGetExtraction(dossierID)
|
|
if err != nil {
|
|
return counts
|
|
}
|
|
|
|
if extraction.Data == "" {
|
|
return counts
|
|
}
|
|
|
|
// Parse extraction data which contains pre-computed counts
|
|
var extractionData struct {
|
|
Counts map[string]CategoryCount `json:"counts"`
|
|
}
|
|
if err := json.Unmarshal([]byte(extraction.Data), &extractionData); err != nil {
|
|
return counts
|
|
}
|
|
|
|
// Return cached counts if available
|
|
if extractionData.Counts != nil {
|
|
return extractionData.Counts
|
|
}
|
|
|
|
// Fallback: compute counts (for old data without cached counts)
|
|
return getGenomeCountsSlow(dossierID)
|
|
}
|
|
|
|
// getGenomeCountsSlow computes counts by scanning all variants (fallback for old data)
|
|
func getGenomeCountsSlow(dossierID string) map[string]CategoryCount {
|
|
counts := make(map[string]CategoryCount)
|
|
|
|
// Find extraction entry
|
|
extraction, err := lib.GenomeGetExtraction(dossierID)
|
|
if err != nil {
|
|
return counts
|
|
}
|
|
|
|
// Get all tiers
|
|
tiers, err := lib.GenomeGetTiers(dossierID, extraction.EntryID)
|
|
if err != nil {
|
|
return counts
|
|
}
|
|
|
|
// For each tier, count shown and hidden variants
|
|
for _, tier := range tiers {
|
|
variants, err := lib.GenomeGetVariantsByTier(dossierID, tier.TierID)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
shown, hidden := 0, 0
|
|
for _, v := range variants {
|
|
data := variantData{
|
|
Mag: v.Magnitude,
|
|
Rep: v.Repute,
|
|
Sub: v.Subcategory,
|
|
}
|
|
if shouldIncludeVariant(data, false) {
|
|
shown++
|
|
} else {
|
|
hidden++
|
|
}
|
|
}
|
|
if shown > 0 || hidden > 0 {
|
|
counts[tier.Category] = CategoryCount{Shown: shown, Hidden: hidden}
|
|
}
|
|
}
|
|
|
|
return counts
|
|
}
|
|
|
|
func getGenomeSubcategoryCounts(dossierID string, category string) map[string]CategoryCount {
|
|
counts := make(map[string]CategoryCount)
|
|
shownCounts := make(map[string]int)
|
|
hiddenCounts := make(map[string]int)
|
|
|
|
// Find extraction entry
|
|
extraction, err := lib.GenomeGetExtraction(dossierID)
|
|
if err != nil {
|
|
return counts
|
|
}
|
|
|
|
// Find tier for this category
|
|
tier, err := lib.GenomeGetTierByCategory(dossierID, extraction.EntryID, category)
|
|
if err != nil {
|
|
return counts
|
|
}
|
|
|
|
// Get variants and count by subcategory
|
|
variants, err := lib.GenomeGetVariantsByTier(dossierID, tier.TierID)
|
|
if err != nil {
|
|
return counts
|
|
}
|
|
|
|
for _, v := range variants {
|
|
if v.Subcategory == "" {
|
|
continue
|
|
}
|
|
data := variantData{
|
|
Mag: v.Magnitude,
|
|
Rep: v.Repute,
|
|
Sub: v.Subcategory,
|
|
}
|
|
if shouldIncludeVariant(data, false) {
|
|
shownCounts[v.Subcategory]++
|
|
} else {
|
|
hiddenCounts[v.Subcategory]++
|
|
}
|
|
}
|
|
|
|
// Combine into CategoryCount
|
|
allSubs := make(map[string]bool)
|
|
for k := range shownCounts {
|
|
allSubs[k] = true
|
|
}
|
|
for k := range hiddenCounts {
|
|
allSubs[k] = true
|
|
}
|
|
for sub := range allSubs {
|
|
counts[sub] = CategoryCount{Shown: shownCounts[sub], Hidden: hiddenCounts[sub]}
|
|
}
|
|
|
|
return counts
|
|
}
|
|
|
|
// Unused but keeping for compatibility - remove if not needed
|
|
var _ = strings.Contains
|