File size: 8,443 Bytes
1875b13
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6d74982
1875b13
 
 
 
 
 
 
 
 
 
 
 
 
6d74982
1875b13
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4c1963b
 
1875b13
 
 
 
 
 
 
 
 
 
 
 
 
6d74982
1875b13
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
// Package env defines all data models for the GridMind-RL environment.
package env

// BatchJob represents a pending industrial/commercial batch process job.
type BatchJob struct {
	ID           int `json:"id"`           // Unique job identifier
	DeadlineSlot int `json:"deadline_slot"` // Latest timestep by which the job must run
	Duration     int `json:"duration"`      // Steps the job takes to complete
	PowerDraw    float64 `json:"power_draw"` // kW drawn when job is running
	Scheduled    bool    `json:"scheduled"`  // Whether a time slot has been assigned
	ScheduledAt  int     `json:"scheduled_at"` // Timestep at which job was scheduled (-1 if not yet)
	Completed    bool    `json:"completed"`  // Whether the job finished execution
	MissedDeadline bool  `json:"missed_deadline"` // True if deadline was exceeded
}

// BuildingState holds the full simulation state for a single building.
type BuildingState struct {
	// Core physical state
	IndoorTemperature    float64 `json:"indoor_temperature"`     // °C
	ThermalStorageLevel  float64 `json:"thermal_storage_level"`  // 0.0–1.0 normalized
	ProcessDemand        float64 `json:"process_demand"`          // kW current process need

	// Market & grid signals
	CurrentPrice         float64 `json:"current_price"`          // $/kWh
	GridStressSignal     float64 `json:"grid_stress_signal"`     // 0.0–1.0 (DR urgency)
	CarbonIntensity      float64 `json:"carbon_intensity"`       // gCO2/kWh

	// Temporal
	HourOfDay            int     `json:"hour_of_day"`            // 0–23
	Step                 int     `json:"step"`                   // 0–95 within a 96-step (24h) episode

	// Batch job queue: pending deadlines (raw slots)
	BatchQueue           []int   `json:"batch_queue"`            // deadline slots of pending jobs

	// Running cost tracker
	CumulativeCost       float64 `json:"cumulative_cost"`        // $ total this episode
	CumulativeCarbon     float64 `json:"cumulative_carbon"`      // gCO2 total this episode

	// Internal tracking (not exposed in observation)
	Jobs                 []BatchJob `json:"-"`
	OutdoorTemperature   float64    `json:"-"` // °C for weather perturbation
	PrevHVACLevel        float64    `json:"-"` // for stability penalty
	BaselineCost         float64    `json:"-"` // always-on policy running cost
	BaselineCarbon       float64    `json:"-"` // baseline policy gCO2 (for grading)
	SetpointTemperature  float64    `json:"-"` // target indoor temp (°C)
	MaxHVACPower         float64    `json:"-"` // kW
	MaxStorageCapacity   float64    `json:"-"` // kWh
	ThermalLossRate      float64    `json:"-"` // fraction lost per step
	BuildingID           int        `json:"-"` // which building in federation
}

// ObservationModel is the JSON-serializable observation returned on each step/state.
type ObservationModel struct {
	IndoorTemperature   float64 `json:"indoor_temperature"`
	ThermalStorageLevel float64 `json:"thermal_storage_level"`
	ProcessDemand       float64 `json:"process_demand"`
	CurrentPrice        float64 `json:"current_price"`
	GridStressSignal    float64 `json:"grid_stress_signal"`
	CarbonIntensity     float64 `json:"carbon_intensity"`
	HourOfDay           int     `json:"hour_of_day"`
	BatchQueue          []int   `json:"batch_queue"`
	CumulativeCost      float64 `json:"cumulative_cost"`
	Step                int     `json:"step"`
	BuildingID          int     `json:"building_id"`
}

// ActionModel is the parsed agent action for a single step.
type ActionModel struct {
	HVACPowerLevel     float64 `json:"hvac_power_level"`    // 0.0–1.0
	ThermalChargeRate  float64 `json:"thermal_charge_rate"` // -1.0 to 1.0
	BatchJobSlot       int     `json:"batch_job_slot"`      // 0–4 (0=now, 1–4=defer)
	LoadShedFraction   float64 `json:"load_shed_fraction"`  // 0.0–0.5
	BuildingID         int     `json:"building_id"`         // which building to act on
}

// RewardComponents holds the individual components of the dense reward signal.
type RewardComponents struct {
	CostSavings      float64 `json:"cost_savings"`       // negative = expensive
	TempConstraint   float64 `json:"temp_constraint"`    // positive = within bounds
	GridResponse     float64 `json:"grid_response"`      // bonus for DR compliance
	DeadlinePenalty  float64 `json:"deadline_penalty"`   // negative for missed jobs
	EfficiencyBonus  float64 `json:"efficiency_bonus"`   // storage arbitrage
	StabilityPenalty float64 `json:"stability_penalty"`  // HVAC oscillation penalty
	CarbonReward     float64 `json:"carbon_reward"`      // low-carbon bonus
	Total            float64 `json:"total"`
}

// StepResponse is the full HTTP body returned from POST /step.
type StepResponse struct {
	Observation ObservationModel `json:"observation"`
	Reward      float64          `json:"reward"`
	Done        bool             `json:"done"`
	Info        StepInfo         `json:"info"`
}

// StepInfo carries auxiliary information per step.
type StepInfo struct {
	RewardComponents RewardComponents `json:"reward_components"`
	EnergyUsed       float64          `json:"energy_used_kwh"`
	CarbonEmitted    float64          `json:"carbon_emitted_gco2"`
	PriceSignal      float64          `json:"price_signal"`
	GridStress       float64          `json:"grid_stress"`
	BatchCompleted   []int            `json:"batch_completed"`   // IDs completed this step
	BatchMissed      []int            `json:"batch_missed"`      // IDs that missed deadline
	Episode          int              `json:"episode"`
	Step             int              `json:"step"`
}

// ResetRequest is the JSON body for POST /reset.
type ResetRequest struct {
	Seed       *int64 `json:"seed,omitempty"`       // optional random seed
	TaskID     int    `json:"task_id"`              // 1, 2, or 3
	Difficulty string `json:"difficulty,omitempty"` // "easy", "medium", "hard" or "" (auto)
	NumBuildings int  `json:"num_buildings,omitempty"` // 1–3 for federation
}

// ResetResponse is returned from POST /reset.
type ResetResponse struct {
	Observations []ObservationModel `json:"observations"` // one per building
	Episode      int                `json:"episode"`
	TaskID       int                `json:"task_id"`
	Seed         int64              `json:"seed"`
}

// StateResponse is returned from GET /state.
type StateResponse struct {
	Buildings    []BuildingStatePublic `json:"buildings"`
	PriceCurve   []float64            `json:"price_curve_episode"`    // full episode ToU prices
	CarbonCurve  []float64            `json:"carbon_curve_episode"`   // full episode carbon intensities
	Episode      int                  `json:"episode"`
	Step         int                  `json:"step"`
	TaskID       int                  `json:"task_id"`
	Done         bool                 `json:"done"`
	Seed         int64                `json:"seed"`
}

// BuildingStatePublic is the dashboard-friendly full state per building.
type BuildingStatePublic struct {
	ObservationModel
	OutdoorTemperature  float64    `json:"outdoor_temperature"`
	SetpointTemperature float64    `json:"setpoint_temperature"`
	BaselineCost        float64    `json:"baseline_cost"`
	BaselineCarbon      float64    `json:"baseline_carbon"`
	CumulativeCarbon    float64    `json:"cumulative_carbon"`
	Jobs                []BatchJob `json:"jobs"`
	// History for chart rendering
	TempHistory         []float64  `json:"temp_history"`
	CostHistory         []float64  `json:"cost_history"`
	HVACHistory         []float64  `json:"hvac_history"`
	LoadShedHistory     []float64  `json:"load_shed_history"`
	RewardHistory       []RewardComponents `json:"reward_history"`
}

// ReplayEntry records a single timestep for episode replay export.
type ReplayEntry struct {
	Step        int              `json:"step"`
	Observation ObservationModel `json:"observation"`
	Action      ActionModel      `json:"action"`
	Reward      float64          `json:"reward"`
	Components  RewardComponents `json:"components"`
	Done        bool             `json:"done"`
}

// EpisodeGrade is the final grade returned for a completed episode.
type EpisodeGrade struct {
	TaskID          int                    `json:"task_id"`
	Score           float64                `json:"score"`           // 0.0–1.0
	SubScores       map[string]float64     `json:"sub_scores"`
	ExploitDetected bool                   `json:"exploit_detected"`
	PenaltyApplied  float64                `json:"penalty_applied"`
	Details         map[string]interface{} `json:"details"`
}