142 lines
3.4 KiB
Go
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
|
|
}
|