types.go
package db
import (
"encoding/json"
"time"
"skraak/wav"
)
// JSONTime wraps time.Time and marshals as RFC3339 string.
// Used as an embedded field in marshal-only structs to avoid
// duplicating MarshalJSON for every DB type that has timestamps.
type JSONTime time.Time
// MarshalJSON implements json.Marshaler for JSONTime.
func (t JSONTime) MarshalJSON() ([]byte, error) {
return json.Marshal(time.Time(t).Format(time.RFC3339))
}
// jt converts a time.Time to JSONTime.
func jt(t time.Time) JSONTime { return JSONTime(t) }
// DatasetType represents the dataset_type enum from the schema
type DatasetType string
// Dataset type enum constants
const (
DatasetTypeStructured DatasetType = "structured"
DatasetTypeUnstructured DatasetType = "unstructured"
DatasetTypeTest DatasetType = "test"
DatasetTypeTrain DatasetType = "train"
)
// Dataset represents a row from the dataset table
type Dataset struct {
ID string `json:"id"`
Name string `json:"name"`
Description *string `json:"description"` // Pointer for nullable field
CreatedAt time.Time `json:"created_at"`
LastModified time.Time `json:"last_modified"`
Active bool `json:"active"`
Type DatasetType `json:"type"`
}
// MarshalJSON implements custom JSON marshaling for Dataset
func (d Dataset) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
ID string `json:"id"`
Name string `json:"name"`
Description *string `json:"description"`
CreatedAt JSONTime `json:"created_at"`
LastModified JSONTime `json:"last_modified"`
Active bool `json:"active"`
Type DatasetType `json:"type"`
}{
ID: d.ID,
Name: d.Name,
Description: d.Description,
CreatedAt: jt(d.CreatedAt),
LastModified: jt(d.LastModified),
Active: d.Active,
Type: d.Type,
})
}
// Location represents a row from the location table
type Location struct {
ID string `json:"id"`
DatasetID string `json:"dataset_id"`
Name string `json:"name"`
Latitude float64 `json:"latitude"`
Longitude float64 `json:"longitude"`
Description *string `json:"description"` // nullable
CreatedAt time.Time `json:"created_at"`
LastModified time.Time `json:"last_modified"`
Active bool `json:"active"`
TimezoneID string `json:"timezone_id"`
}
// MarshalJSON implements custom JSON marshaling for Location
func (l Location) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
ID string `json:"id"`
DatasetID string `json:"dataset_id"`
Name string `json:"name"`
Latitude float64 `json:"latitude"`
Longitude float64 `json:"longitude"`
Description *string `json:"description"`
CreatedAt JSONTime `json:"created_at"`
LastModified JSONTime `json:"last_modified"`
Active bool `json:"active"`
TimezoneID string `json:"timezone_id"`
}{
ID: l.ID,
DatasetID: l.DatasetID,
Name: l.Name,
Latitude: l.Latitude,
Longitude: l.Longitude,
Description: l.Description,
CreatedAt: jt(l.CreatedAt),
LastModified: jt(l.LastModified),
Active: l.Active,
TimezoneID: l.TimezoneID,
})
}
// Cluster represents a row from the cluster table
type Cluster struct {
ID string `json:"id"`
DatasetID string `json:"dataset_id"`
LocationID string `json:"location_id"`
Name string `json:"name"`
Description *string `json:"description"` // nullable
CreatedAt time.Time `json:"created_at"`
LastModified time.Time `json:"last_modified"`
Active bool `json:"active"`
CyclicRecordingPatternID *string `json:"cyclic_recording_pattern_id"` // nullable
SampleRate int `json:"sample_rate"`
}
// MarshalJSON implements custom JSON marshaling for Cluster
func (c Cluster) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
ID string `json:"id"`
DatasetID string `json:"dataset_id"`
LocationID string `json:"location_id"`
Name string `json:"name"`
Description *string `json:"description"`
CreatedAt JSONTime `json:"created_at"`
LastModified JSONTime `json:"last_modified"`
Active bool `json:"active"`
CyclicRecordingPatternID *string `json:"cyclic_recording_pattern_id"`
SampleRate int `json:"sample_rate"`
}{
ID: c.ID,
DatasetID: c.DatasetID,
LocationID: c.LocationID,
Name: c.Name,
Description: c.Description,
CreatedAt: jt(c.CreatedAt),
LastModified: jt(c.LastModified),
Active: c.Active,
CyclicRecordingPatternID: c.CyclicRecordingPatternID,
SampleRate: c.SampleRate,
})
}
// File represents a row from the file table
type File struct {
ID string `json:"id"`
FileName string `json:"file_name"`
Path *string `json:"path"` // nullable
XXH64Hash string `json:"xxh64_hash"`
LocationID string `json:"location_id"`
TimestampLocal time.Time `json:"timestamp_local"`
ClusterID *string `json:"cluster_id"` // nullable
Duration float64 `json:"duration"`
SampleRate int `json:"sample_rate"`
Description *string `json:"description"` // nullable
MaybeSolarNight *bool `json:"maybe_solar_night"` // nullable
MaybeCivilNight *bool `json:"maybe_civil_night"` // nullable
MoonPhase *float64 `json:"moon_phase"` // nullable
CreatedAt time.Time `json:"created_at"`
LastModified time.Time `json:"last_modified"`
Active bool `json:"active"`
}
// CyclicRecordingPattern represents a row from the cyclic_recording_pattern table
type CyclicRecordingPattern struct {
ID string `json:"id"`
RecordS int `json:"record_s"`
SleepS int `json:"sleep_s"`
CreatedAt time.Time `json:"created_at"`
LastModified time.Time `json:"last_modified"`
Active bool `json:"active"`
}
// MarshalJSON implements custom JSON marshaling for CyclicRecordingPattern
func (p CyclicRecordingPattern) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
ID string `json:"id"`
RecordS int `json:"record_s"`
SleepS int `json:"sleep_s"`
CreatedAt JSONTime `json:"created_at"`
LastModified JSONTime `json:"last_modified"`
Active bool `json:"active"`
}{
ID: p.ID,
RecordS: p.RecordS,
SleepS: p.SleepS,
CreatedAt: jt(p.CreatedAt),
LastModified: jt(p.LastModified),
Active: p.Active,
})
}
// GainLevel is re-exported from utils for backward compatibility.
type GainLevel = wav.GainLevel
// Gain level constants re-exported from wav.
const (
GainLow = wav.GainLow
GainLowMedium = wav.GainLowMedium
GainMedium = wav.GainMedium
GainMediumHigh = wav.GainMediumHigh
GainHigh = wav.GainHigh
)
// MothMetadata represents a row from the moth_metadata table
type MothMetadata struct {
FileID string `json:"file_id"`
Timestamp time.Time `json:"timestamp"`
RecorderID *string `json:"recorder_id"` // nullable
Gain *GainLevel `json:"gain"` // nullable
BatteryV *float64 `json:"battery_v"` // nullable
TempC *float64 `json:"temp_c"` // nullable
CreatedAt time.Time `json:"created_at"`
LastModified time.Time `json:"last_modified"`
Active bool `json:"active"`
}
// FileDataset represents a row from the file_dataset junction table
type FileDataset struct {
FileID string `json:"file_id"`
DatasetID string `json:"dataset_id"`
CreatedAt time.Time `json:"created_at"`
LastModified time.Time `json:"last_modified"`
}