feat: keys, clicks, and totals in computer statistics

This commit is contained in:
trafficlunar 2025-03-22 14:20:04 +00:00
parent 19bdd27de1
commit 8407a1258f
6 changed files with 85 additions and 10 deletions

View file

@ -3,6 +3,7 @@ package handler
import ( import (
"api/internal/model" "api/internal/model"
"api/internal/service" "api/internal/service"
"api/internal/storage"
"api/internal/worker" "api/internal/worker"
"encoding/json" "encoding/json"
"log/slog" "log/slog"
@ -33,7 +34,7 @@ func HandleComputerWebSocket(w http.ResponseWriter, r *http.Request) {
} }
defer conn.Close() defer conn.Close()
slog.Info("WebSocket connection established!") slog.Info("WebSocket connection established")
service.ComputerData.Online = true service.ComputerData.Online = true
for { for {
@ -52,6 +53,25 @@ func HandleComputerWebSocket(w http.ResponseWriter, r *http.Request) {
worker.QueuedClientMessage = clientMessage worker.QueuedClientMessage = clientMessage
slog.Info("Recieved message", slog.Any("message", clientMessage)) slog.Info("Recieved message", slog.Any("message", clientMessage))
// Add to totals
keysData := storage.GlobalDataStore.Get("keys")
clicksData := storage.GlobalDataStore.Get("clicks")
var keys float64
var clicks float64
if keysData != nil {
keys = keysData.(float64)
}
if clicksData != nil {
clicks = clicksData.(float64)
}
storage.GlobalDataStore.Set("keys", keys+float64(clientMessage.Keys))
storage.GlobalDataStore.Set("clicks", clicks+float64(clientMessage.Clicks))
service.LoadComputerStatTotals()
} }
} }

View file

@ -3,17 +3,27 @@ package model
import "time" import "time"
type ComputerWebSocketMessage struct { type ComputerWebSocketMessage struct {
Cpu uint8 `json:"cpu"` Cpu uint8 `json:"cpu"`
Ram uint8 `json:"ram"` Ram uint8 `json:"ram"`
Keys uint16 `json:"keys"`
Clicks uint16 `json:"clicks"`
} }
type ComputerData struct { type ComputerData struct {
Online bool `json:"online"` Online bool `json:"online"`
Totals ComputerTotals `json:"totals"`
Graph []ComputerGraphData `json:"graph"` Graph []ComputerGraphData `json:"graph"`
} }
type ComputerTotals struct {
Keys float64 `json:"keys"`
Clicks float64 `json:"clicks"`
}
type ComputerGraphData struct { type ComputerGraphData struct {
Timestamp time.Time `json:"timestamp"` Timestamp time.Time `json:"timestamp"`
Cpu int `json:"cpu"` Cpu int `json:"cpu"`
Ram int `json:"ram"` Ram int `json:"ram"`
Keys int `json:"keys"`
Clicks int `json:"clicks"`
} }

View file

@ -2,22 +2,49 @@ package service
import ( import (
"api/internal/model" "api/internal/model"
"api/internal/storage"
"time" "time"
) )
var ComputerData model.ComputerData = model.ComputerData{ var ComputerData model.ComputerData = model.ComputerData{
Online: false, Online: false,
Graph: initializeGraphData(), Totals: model.ComputerTotals{
Keys: 0,
Clicks: 0,
},
Graph: initializeGraphData(),
}
func LoadComputerStatTotals() {
keysData := storage.GlobalDataStore.Get("keys")
clicksData := storage.GlobalDataStore.Get("clicks")
var keys float64
var clicks float64
if keysData != nil {
keys = keysData.(float64)
}
if clicksData != nil {
clicks = clicksData.(float64)
}
ComputerData.Totals = model.ComputerTotals{
Keys: keys,
Clicks: clicks,
}
} }
func initializeGraphData() []model.ComputerGraphData { func initializeGraphData() []model.ComputerGraphData {
graphData := make([]model.ComputerGraphData, 60) graphData := make([]model.ComputerGraphData, 60)
for i := 0; i < 60; i++ { for i := range 60 {
graphData[i] = model.ComputerGraphData{ graphData[i] = model.ComputerGraphData{
Timestamp: time.Now().Truncate(1 * time.Minute).Add(time.Duration(-60+i) * time.Minute), Timestamp: time.Now().Truncate(1 * time.Minute).Add(time.Duration(-60+i) * time.Minute),
Cpu: 0, Cpu: 0,
Ram: 0, Ram: 0,
Keys: 0,
Clicks: 0,
} }
} }
@ -29,6 +56,8 @@ func AddComputerData(clientMessage model.ComputerWebSocketMessage) {
Timestamp: time.Now().Truncate(time.Minute).Add(-time.Minute), Timestamp: time.Now().Truncate(time.Minute).Add(-time.Minute),
Cpu: int(clientMessage.Cpu), Cpu: int(clientMessage.Cpu),
Ram: int(clientMessage.Ram), Ram: int(clientMessage.Ram),
Keys: int(clientMessage.Keys),
Clicks: int(clientMessage.Clicks),
}) })
if len(ComputerData.Graph) > 60 { if len(ComputerData.Graph) > 60 {

View file

@ -12,7 +12,9 @@ type DataStore struct {
Mutex sync.Mutex Mutex sync.Mutex
} }
var GlobalDataStore *DataStore var GlobalDataStore = &DataStore{
Data: make(map[string]any),
}
func InitDataStore() *DataStore { func InitDataStore() *DataStore {
GlobalDataStore = &DataStore{ GlobalDataStore = &DataStore{
@ -36,6 +38,7 @@ func InitDataStore() *DataStore {
return nil return nil
} }
slog.Info("Loaded data store")
return GlobalDataStore return GlobalDataStore
} }

View file

@ -18,8 +18,10 @@ func StartComputerWorker() {
if now.Second() == 0 { if now.Second() == 0 {
if !service.ComputerData.Online { if !service.ComputerData.Online {
service.AddComputerData(model.ComputerWebSocketMessage{ service.AddComputerData(model.ComputerWebSocketMessage{
Cpu: 0, Cpu: 0,
Ram: 0, Ram: 0,
Keys: 0,
Clicks: 0,
}) })
} else { } else {
service.AddComputerData(QueuedClientMessage) service.AddComputerData(QueuedClientMessage)

15
main.go
View file

@ -4,12 +4,14 @@ import (
"log/slog" "log/slog"
"os" "os"
"os/signal" "os/signal"
"sync"
"syscall" "syscall"
"github.com/joho/godotenv" "github.com/joho/godotenv"
"github.com/lmittmann/tint" "github.com/lmittmann/tint"
"api/internal/server" "api/internal/server"
"api/internal/service"
"api/internal/storage" "api/internal/storage"
"api/internal/worker" "api/internal/worker"
) )
@ -20,10 +22,19 @@ func main() {
err := godotenv.Load() err := godotenv.Load()
if err != nil { if err != nil {
slog.Warn("No .env file was found; using environment variables.", slog.Any("error", err)) slog.Warn("No .env file was found; using environment variables", slog.Any("error", err))
} }
storage.InitDataStore() var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
storage.InitDataStore()
}()
wg.Wait()
service.LoadComputerStatTotals()
go worker.StartWorkers() go worker.StartWorkers()
// Shutdown-chan~~ // Shutdown-chan~~