155 lines
3.8 KiB
Go
155 lines
3.8 KiB
Go
package main
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
logger "git.site.quack-lab.dev/dave/cylogger"
|
|
utils "git.site.quack-lab.dev/dave/cyutils"
|
|
)
|
|
|
|
func main() {
|
|
ingest := flag.Bool("ingest", false, "ingest killmails from data directory")
|
|
server := flag.Bool("server", false, "start API server")
|
|
port := flag.String("port", "3000", "API server port")
|
|
flag.Parse()
|
|
logger.InitFlag()
|
|
logger.Default = logger.Default.ToFile("zkill.log")
|
|
logger.Info("Starting")
|
|
|
|
db, err := GetDB()
|
|
if err != nil {
|
|
logger.Error("Failed to get database: %v", err)
|
|
return
|
|
}
|
|
|
|
if err := db.InitTables(); err != nil {
|
|
logger.Error("Failed to initialize tables: %v", err)
|
|
return
|
|
}
|
|
|
|
if *ingest {
|
|
DoIngest()
|
|
return
|
|
}
|
|
|
|
if *server {
|
|
StartAPIServer(*port)
|
|
return
|
|
}
|
|
|
|
logger.Info("Querying fits")
|
|
params := QueryParams{
|
|
Ship: 32872,
|
|
Modules: []int64{2456},
|
|
Groups: []int64{325},
|
|
}
|
|
stats, err := db.QueryFits(params)
|
|
if err != nil {
|
|
logger.Error("Failed to query fits: %v", err)
|
|
return
|
|
}
|
|
logger.Info("Total killmails: %d", stats.TotalKillmails)
|
|
|
|
// Utility function for sorting and printing top N entries by percentage.
|
|
printTopN := func(title string, statsMap interface{}, n int) {
|
|
type statItem struct {
|
|
ID int64
|
|
Percentage float64
|
|
Count int64
|
|
Name string
|
|
}
|
|
list := []statItem{}
|
|
|
|
var ids32 []int32
|
|
switch m := statsMap.(type) {
|
|
case map[int64]SystemStats:
|
|
for id, v := range m {
|
|
list = append(list, statItem{ID: id, Percentage: v.Percentage, Count: v.Count})
|
|
ids32 = append(ids32, int32(id))
|
|
}
|
|
case map[int32]ModuleStats:
|
|
for id, v := range m {
|
|
list = append(list, statItem{ID: int64(id), Percentage: v.Percentage, Count: v.Count})
|
|
ids32 = append(ids32, id)
|
|
}
|
|
default:
|
|
logger.Warning("Unknown statistic map: %T", statsMap)
|
|
return
|
|
}
|
|
|
|
// Fetch names for every ID using GetItemNames (works for both items and systems)
|
|
idToName := make(map[string]string)
|
|
if len(ids32) > 0 {
|
|
names, err := db.GetItemNames(ids32)
|
|
if err == nil {
|
|
idToName = names
|
|
}
|
|
for i := range list {
|
|
if name, ok := idToName[fmt.Sprintf("%d", list[i].ID)]; ok {
|
|
list[i].Name = name
|
|
}
|
|
}
|
|
}
|
|
|
|
// Sort descending by percentage
|
|
for i := 0; i < len(list); i++ {
|
|
for j := i + 1; j < len(list); j++ {
|
|
if list[j].Percentage > list[i].Percentage {
|
|
list[i], list[j] = list[j], list[i]
|
|
}
|
|
}
|
|
}
|
|
|
|
if len(list) > n {
|
|
list = list[:n]
|
|
}
|
|
|
|
logger.Info("Top %d %s:", len(list), title)
|
|
for _, s := range list {
|
|
row := fmt.Sprintf(" ID %d: %.2f%% (%d)", s.ID, s.Percentage, s.Count)
|
|
if s.Name != "" {
|
|
row = fmt.Sprintf(" %s [ID %d]: %.2f%% (%d)", s.Name, s.ID, s.Percentage, s.Count)
|
|
}
|
|
logger.Info(row)
|
|
}
|
|
}
|
|
|
|
printTopN("Ships", stats.ShipBreakdown, 10)
|
|
printTopN("Systems", stats.SystemBreakdown, 10)
|
|
printTopN("High Slot Modules", stats.HighSlotModules, 10)
|
|
printTopN("Mid Slot Modules", stats.MidSlotModules, 10)
|
|
printTopN("Low Slot Modules", stats.LowSlotModules, 10)
|
|
printTopN("Rigs", stats.Rigs, 10)
|
|
printTopN("Drones", stats.Drones, 10)
|
|
}
|
|
|
|
func DoIngest() {
|
|
killmailFiles, err := os.ReadDir("data")
|
|
if err != nil {
|
|
logger.Error("Failed to read data directory: %v", err)
|
|
return
|
|
}
|
|
totalFiles := len(killmailFiles)
|
|
utils.WithWorkers(2, killmailFiles, func(worker int, index int, file os.DirEntry) {
|
|
flog := logger.Default.WithPrefix(fmt.Sprintf("worker %d", worker)).WithPrefix(fmt.Sprintf("file %d of %d", index, totalFiles)).WithPrefix(file.Name())
|
|
flog.Info("Loading killmails")
|
|
|
|
killmails, err := LoadBz2Killmails(filepath.Join("data", file.Name()))
|
|
if err != nil {
|
|
flog.Error("Failed to load killmails: %v", err)
|
|
return
|
|
}
|
|
flog.Info("Loaded %d killmails", len(killmails))
|
|
|
|
err = db.SaveKillmails(killmails)
|
|
if err != nil {
|
|
flog.Error("Failed to save killmails: %v", err)
|
|
return
|
|
}
|
|
flog.Info("Saved %d killmails", len(killmails))
|
|
})
|
|
}
|