Files
2026-04-22 09:11:46 +07:00

142 lines
3.4 KiB
Go

package aplicare
import (
"encoding/json"
"os"
"time"
)
// RoomSnapshot adalah snapshot nilai per ruangan
type RoomSnapshot struct {
Kapasitas int `json:"kapasitas"`
Tersedia int `json:"tersedia"`
TersediaPria int `json:"tersedia_pria"`
TersediaWanita int `json:"tersedia_wanita"`
TersediaPriaWanita int `json:"tersedia_pria_wanita"`
}
// RoomState adalah state per ruangan dengan perbandingan old vs new
type RoomState struct {
KodeRuang string `json:"kode_ruang"`
KodeKelas string `json:"kodekelas"`
NamaRuang string `json:"nama_ruang"`
OldValue RoomSnapshot `json:"old_value"`
NewValue RoomSnapshot `json:"new_value"`
Changed bool `json:"changed"`
LastSynced string `json:"last_synced"`
}
// State adalah struktur utama state.json
type State struct {
LastUpdated string `json:"last_updated"`
Rooms map[string]RoomState `json:"rooms"` // key: kode_ruang
}
// LoadState membaca state.json dari disk
// Mengembalikan empty State (bukan error) jika file belum ada
func LoadState(path string) (*State, error) {
data, err := os.ReadFile(path)
if os.IsNotExist(err) {
return &State{Rooms: make(map[string]RoomState)}, nil
}
if err != nil {
return nil, err
}
var state State
if err := json.Unmarshal(data, &state); err != nil {
return nil, err
}
if state.Rooms == nil {
state.Rooms = make(map[string]RoomState)
}
return &state, nil
}
// SaveState menulis state ke disk
func SaveState(path string, state *State) error {
state.LastUpdated = time.Now().Format(time.RFC3339)
data, err := json.MarshalIndent(state, "", " ")
if err != nil {
return err
}
return os.WriteFile(path, data, 0644)
}
// ComputeDiff membandingkan data SIMRS terbaru dengan state lama.
// Mengembalikan state baru dengan field Changed=true hanya untuk yang berubah.
func ComputeDiff(old *State, current []BedData) *State {
newState := &State{
Rooms: make(map[string]RoomState),
}
now := time.Now().Format(time.RFC3339)
for _, bed := range current {
newSnap := RoomSnapshot{
Kapasitas: bed.Kapasitas,
Tersedia: bed.Tersedia,
TersediaPria: bed.TersediaPria,
TersediaWanita: bed.TersediaWanita,
TersediaPriaWanita: bed.TersediaPriaWanita,
}
oldRoom, exists := old.Rooms[bed.KodeRuang]
oldSnap := oldRoom.NewValue
if !exists {
oldSnap = RoomSnapshot{}
}
changed := !snapshotEqual(oldSnap, newSnap)
// Kalau sebelumnya sudah ada lastSynced, pertahankan
lastSynced := oldRoom.LastSynced
if changed {
lastSynced = now
}
newState.Rooms[bed.KodeRuang] = RoomState{
KodeRuang: bed.KodeRuang,
KodeKelas: bed.KodeKelas,
NamaRuang: bed.NamaRuang,
OldValue: oldSnap,
NewValue: newSnap,
Changed: changed,
LastSynced: lastSynced,
}
}
return newState
}
// GetChangedBeds mengembalikan hanya BedData yang berubah dari state
func GetChangedBeds(state *State, allBeds []BedData) []BedData {
changedMap := make(map[string]bool)
for kode, room := range state.Rooms {
if room.Changed {
changedMap[kode] = true
}
}
var changed []BedData
for _, bed := range allBeds {
if changedMap[bed.KodeRuang] {
changed = append(changed, bed)
}
}
return changed
}
func snapshotEqual(a, b RoomSnapshot) bool {
return a.Kapasitas == b.Kapasitas &&
a.Tersedia == b.Tersedia &&
a.TersediaPria == b.TersediaPria &&
a.TersediaWanita == b.TersediaWanita &&
a.TersediaPriaWanita == b.TersediaPriaWanita
}