Skip to content

Commit

Permalink
Refactored DeviceEvents back to being an interface
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewpetro committed Feb 11, 2024
1 parent 480267b commit fee7247
Show file tree
Hide file tree
Showing 9 changed files with 43 additions and 77 deletions.
45 changes: 0 additions & 45 deletions src/irrigation-events/domain/device-events.ts

This file was deleted.

8 changes: 8 additions & 0 deletions src/irrigation-events/interfaces/device-events.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { DeviceState } from '../enums/device-state.interface'
import { IrrigationEvent } from './irrigation-event.interface'

export interface DeviceEvents {
deviceId: number
events: IrrigationEvent[]
currentDeviceState?: DeviceState
}
29 changes: 16 additions & 13 deletions src/irrigation-events/irrigation-events.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { MakerApiEventDto } from './dto/maker-api-event.dto'
import { DeviceState } from './enums/device-state.interface'
import { MakerApiService } from './maker-api.service'
import { ViewmodelTransformService } from './viewmodel-transform.service'
import { DeviceEvents } from './domain/device-events'
import { DeviceEvents } from './interfaces/device-events.interface'

class QueryParameters {
@IsISO8601()
Expand All @@ -21,13 +21,14 @@ const isCurrentTimeWithinInterval = (startTimestamp: string, endTimestamp: strin

const irrigationEventsToDeviceEvents = (irrigationEvents: IrrigationEvent[]): DeviceEvents[] => {
const deviceEvents: DeviceEvents[] = []
// Use a Set to quickly get a list of unique device IDs
const deviceIds = new Set<number>()
irrigationEvents.forEach((event) => {
deviceIds.add(event.deviceId)
})
deviceIds.forEach((deviceId) => {
const events = irrigationEvents.filter((event) => event.deviceId === deviceId)
deviceEvents.push(new DeviceEvents(deviceId, events))
deviceEvents.push({ deviceId, events } as DeviceEvents)
})
return deviceEvents
}
Expand Down Expand Up @@ -66,26 +67,29 @@ export class IrrigationEventsController {
endTimestamp: string
): Promise<void> {
const appendOnEventPromises = deviceEventLists.map(async (deviceEvents) => {
if (deviceEvents.getFirstEvent().state !== DeviceState.ON) {
// If the first event is an OFF event, that probably means the ON event occurred
// prior to the beginning of the time range. Check for an ON event before the start
// and add it to the list of events if we find one.
if (deviceEvents.events[0]?.state === DeviceState.OFF) {
const eventsBeforeStart = await this.irrigationEventsService.getEventsBeforeStart(
startTimestamp,
deviceEvents.getDeviceId()
deviceEvents.deviceId
)
if (eventsBeforeStart[0]?.state === DeviceState.ON) {
deviceEvents.addEvent(eventsBeforeStart[0])
deviceEvents.events.push(eventsBeforeStart[0])
}
}
})
await Promise.allSettled(appendOnEventPromises)

// If the last event is an ON event, that probably means the OFF event occurred
// after the end of the time range. Check for an OFF event after the end and add
// it to the list of events if we find one.
const appendOffEventPromises = deviceEventLists.map(async (deviceEvents) => {
if (deviceEvents.getLastEvent().state !== DeviceState.OFF) {
const eventsAfterEnd = await this.irrigationEventsService.getEventsAfterEnd(
endTimestamp,
deviceEvents.getDeviceId()
)
if (deviceEvents.events[deviceEvents.events.length - 1].state === DeviceState.ON) {
const eventsAfterEnd = await this.irrigationEventsService.getEventsAfterEnd(endTimestamp, deviceEvents.deviceId)
if (eventsAfterEnd[0]?.state === DeviceState.OFF) {
deviceEvents.addEvent(eventsAfterEnd[0])
deviceEvents.events.push(eventsAfterEnd[0])
}
}
})
Expand All @@ -95,8 +99,7 @@ export class IrrigationEventsController {
private async addCurrentDeviceStates(deviceEventsList: DeviceEvents[]): Promise<void> {
const deviceDetails = await this.makerApiService.getAllDeviceDetails()
deviceEventsList.forEach((deviceEvents) => {
const currentDeviceState = deviceDetails[deviceEvents.getDeviceId()]
deviceEvents.setCurrentDeviceState(currentDeviceState)
deviceEvents.currentDeviceState = deviceDetails[deviceEvents.deviceId]
})
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { IrrigationEvent } from '../../interfaces/irrigation-event.interface'
import { DeviceState } from '../../enums/device-state.interface'
import { DeviceEvents } from '../../domain/device-events'
import { DeviceEvents } from '../../interfaces/device-events.interface'
import { IrrigationEventViewmodel } from '../../dto/irrigation-event-viewmodel.dto'

const deviceIrrigationEvents: IrrigationEvent[] = [
Expand Down Expand Up @@ -36,8 +36,7 @@ const deviceIrrigationEvents: IrrigationEvent[] = [
},
]

const deviceEvents = new DeviceEvents(1, deviceIrrigationEvents)
deviceEvents.setCurrentDeviceState(DeviceState.ON)
const deviceEvents = { deviceId: 1, events: deviceIrrigationEvents, currentDeviceState: DeviceState.ON } as DeviceEvents

const resultViewmodels: IrrigationEventViewmodel[] = [
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { IrrigationEvent } from '../../interfaces/irrigation-event.interface'
import { DeviceState } from '../../enums/device-state.interface'
import { DeviceEvents } from '../../domain/device-events'
import { DeviceEvents } from '../../interfaces/device-events.interface'
import { IrrigationEventViewmodel } from '../../dto/irrigation-event-viewmodel.dto'

const device1IrrigationEvents: IrrigationEvent[] = [
Expand Down Expand Up @@ -42,7 +42,7 @@ const device1IrrigationEvents: IrrigationEvent[] = [
},
]

const deviceEvents1 = new DeviceEvents(1, device1IrrigationEvents)
const deviceEvents1 = { deviceId: 1, events: device1IrrigationEvents } as DeviceEvents

const device2IrrigationEvents: IrrigationEvent[] = [
{
Expand Down Expand Up @@ -83,7 +83,7 @@ const device2IrrigationEvents: IrrigationEvent[] = [
},
]

const deviceEvents2 = new DeviceEvents(2, device2IrrigationEvents)
const deviceEvents2 = { deviceId: 2, events: device2IrrigationEvents } as DeviceEvents

const resultViewmodels: IrrigationEventViewmodel[] = [
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { IrrigationEvent } from '../../interfaces/irrigation-event.interface'
import { DeviceState } from '../../enums/device-state.interface'
import { Warning } from '../../enums/warning.interface'
import { DeviceEvents } from '../../domain/device-events'
import { DeviceEvents } from '../../interfaces/device-events.interface'
import { IrrigationEventViewmodel } from '../../dto/irrigation-event-viewmodel.dto'

const deviceIrrigationEvents: IrrigationEvent[] = [
Expand Down Expand Up @@ -37,7 +37,7 @@ const deviceIrrigationEvents: IrrigationEvent[] = [
},
]

const deviceEvents = new DeviceEvents(1, deviceIrrigationEvents)
const deviceEvents = { deviceId: 1, events: deviceIrrigationEvents } as DeviceEvents

const resultViewmodels: IrrigationEventViewmodel[] = [
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { IrrigationEvent } from '../../interfaces/irrigation-event.interface'
import { DeviceState } from '../../enums/device-state.interface'
import { Warning } from '../../enums/warning.interface'
import { DeviceEvents } from '../../domain/device-events'
import { DeviceEvents } from '../../interfaces/device-events.interface'
import { IrrigationEventViewmodel } from '../../dto/irrigation-event-viewmodel.dto'

const deviceIrrigationEvents: IrrigationEvent[] = [
Expand Down Expand Up @@ -37,7 +37,7 @@ const deviceIrrigationEvents: IrrigationEvent[] = [
},
]

const deviceEvents = new DeviceEvents(1, deviceIrrigationEvents)
const deviceEvents = { deviceId: 1, events: deviceIrrigationEvents } as DeviceEvents

const resultViewmodels: IrrigationEventViewmodel[] = [
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { IrrigationEvent } from '../../interfaces/irrigation-event.interface'
import { DeviceState } from '../../enums/device-state.interface'
import { Warning } from '../../enums/warning.interface'
import { DeviceEvents } from '../../domain/device-events'
import { DeviceEvents } from '../../interfaces/device-events.interface'
import { IrrigationEventViewmodel } from '../../dto/irrigation-event-viewmodel.dto'

const deviceIrrigationEvents: IrrigationEvent[] = [
Expand Down Expand Up @@ -37,7 +37,7 @@ const deviceIrrigationEvents: IrrigationEvent[] = [
},
]

const deviceEvents = new DeviceEvents(1, deviceIrrigationEvents)
const deviceEvents = { deviceId: 1, events: deviceIrrigationEvents } as DeviceEvents

const resultViewmodels: IrrigationEventViewmodel[] = [
{
Expand Down
15 changes: 8 additions & 7 deletions src/irrigation-events/viewmodel-transform.service.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
import { Injectable } from '@nestjs/common'
import { roundToNearestMinutes } from 'date-fns'
import { compareAsc, roundToNearestMinutes } from 'date-fns'
import { IrrigationEventViewmodel } from './dto/irrigation-event-viewmodel.dto'
import { DeviceState } from './enums/device-state.interface'
import { Warning } from './enums/warning.interface'
import { DeviceEvents } from './domain/device-events'
// import { DeviceEvents } from './domain/device-events'
import { DeviceEvents } from './interfaces/device-events.interface'

const convertTimestampToViewmodel = (timestamp: Date): string =>
roundToNearestMinutes(timestamp, {
nearestTo: 1,
roundingMethod: 'trunc',
}).toISOString()

function createViewmodelsFromDeviceEvents(deviceEvents: DeviceEvents): IrrigationEventViewmodel[] {
function createViewmodelsFromDeviceEvents({ events, currentDeviceState }: DeviceEvents): IrrigationEventViewmodel[] {
const sortedEvents = [...events].sort((a, b) => compareAsc(a.timestamp, b.timestamp))
const viewmodels: IrrigationEventViewmodel[] = []
const events = deviceEvents.getEvents()
let i = 0
while (i < events.length) {
const [event, nextEvent] = events.slice(i, i + 2)
while (i < sortedEvents.length) {
const [event, nextEvent] = sortedEvents.slice(i, i + 2)
if (event.state === DeviceState.ON && nextEvent?.state === DeviceState.OFF) {
// Happy path: ON followed by OFF
viewmodels.push({
Expand All @@ -40,7 +41,7 @@ function createViewmodelsFromDeviceEvents(deviceEvents: DeviceEvents): Irrigatio
// the final OFF event is missing. Check the current device
// states to determine which is the case.
viewmodels.push(
deviceEvents.getCurrentDeviceState() === DeviceState.ON
currentDeviceState === DeviceState.ON
? {
startDate: convertTimestampToViewmodel(event.timestamp),
endDate: convertTimestampToViewmodel(new Date()),
Expand Down

0 comments on commit fee7247

Please sign in to comment.