<%
' rosy_utilities.asp
' Author: Jim Miller
' Running Average Class
Class RunningAverage
Private queue
Private n_StackSize
Private recordCount
Private recordIndex
Private Sub Class_Initialize()
Set queue = CreateObject("System.Collections.ArrayList")
n_StackSize = 3 ' Default
recordCount = 0
recordIndex = 0
End Sub
Public Sub Initialize(stackSize)
n_StackSize = stackSize
End Sub
Public Sub Reset(count)
Set queue = CreateObject("System.Collections.ArrayList")
recordIndex = 0
recordCount = count
End Sub
Public Function Update(newValue)
Dim total, n_FromEnd, average, i, maxQueueSize
total = 0
recordIndex = recordIndex + 1
' Calculate how many points from the end we are
n_FromEnd = recordCount - recordIndex
' Special case for the last point - return raw value
If n_FromEnd = 0 Then
' For the last point, just return the raw value
Update = newValue
' Still add to queue for completeness
queue.Add newValue
Exit Function
End If
' Add the new value to the queue
queue.Add newValue
' For normal processing (not near the end), maintain the standard stack size
If n_FromEnd > 1 Then
' Standard case - maintain stack size
maxQueueSize = n_StackSize
ElseIf n_FromEnd = 1 Then
' Second-to-last point - use 2-point average
maxQueueSize = 2
End If
' Trim the queue to the appropriate size
While queue.Count > maxQueueSize
queue.RemoveAt 0
Wend
' Sum the values
For i = 0 To queue.Count - 1
total = total + queue(i)
Next
' Calculate the average
If queue.Count > 0 Then
average = total / queue.Count
Else
average = 0
End If
Update = average
End Function
Public Function GetRecordIndex()
GetRecordIndex = recordIndex
End Function
Public Function GetQueueCount()
GetQueueCount = queue.Count
End Function
Private Sub Class_Terminate()
Set queue = Nothing
End Sub
End Class
' Running Average for Direction Data
Class RunningAverage_Dir
Private RA_x
Private RA_y
Private n_StackSize
Private Sub Class_Initialize()
n_StackSize = 3 ' Default
Set RA_x = New RunningAverage
RA_x.Initialize n_StackSize
Set RA_y = New RunningAverage
RA_y.Initialize n_StackSize
End Sub
Public Sub Initialize(stackSize)
n_StackSize = stackSize
Set RA_x = New RunningAverage
RA_x.Initialize n_StackSize
Set RA_y = New RunningAverage
RA_y.Initialize n_StackSize
End Sub
Public Sub Reset(count)
RA_x.Reset count
RA_y.Reset count
End Sub
Public Function Update(newDir_deg)
Dim x, y, x_avg, y_avg, averageDir_deg
' Convert degrees to radians and get components
x = Cos(newDir_deg * (3.14159265358979 / 180.0))
y = Sin(newDir_deg * (3.14159265358979 / 180.0))
' Update components
x_avg = RA_x.Update(x)
y_avg = RA_y.Update(y)
' Calculate average angle
averageDir_deg = Atn2(y_avg, x_avg) * (180.0 / 3.14159265358979)
' Ensure positive angles
If averageDir_deg < 0 Then
Update = averageDir_deg + 360.0
Else
Update = averageDir_deg
End If
End Function
Private Sub Class_Terminate()
Set RA_x = Nothing
Set RA_y = Nothing
End Sub
End Class
' Helper function for arctangent with correct quadrant
Function Atn2(y, x)
If x = 0 Then
If y > 0 Then
Atn2 = 1.5707963267949 ' PI/2
ElseIf y < 0 Then
Atn2 = -1.5707963267949 ' -PI/2
Else
Atn2 = 0 ' Undefined, but return 0
End If
Else
If x > 0 Then
Atn2 = Atn(y / x)
ElseIf x < 0 Then
If y >= 0 Then
Atn2 = Atn(y / x) + 3.14159265358979 ' PI
Else
Atn2 = Atn(y / x) - 3.14159265358979 ' -PI
End If
End If
End If
End Function
Function DaylightSavingsTime(dateToCheck)
'rwbr "in DaylightSavingsTime, dateToCheck: " & dateToCheck
' Implementation for US Daylight Saving Time rules (2007 and later)
Dim yearVal, dstStart, dstEnd, dateObj
' Convert string to date if needed
If IsDate(dateToCheck) Then
If VarType(dateToCheck) = 8 Then ' VT_BSTR (String)
dateObj = CDate(dateToCheck)
Else
dateObj = dateToCheck
End If
Else
' Invalid date format
DaylightSavingsTime = False
Exit Function
End If
yearVal = Year(dateObj)
' Second Sunday in March to First Sunday in November (US rules since 2007)
dstStart = GetNthSunday(yearVal, 3, 2) ' 2nd Sunday in March
dstEnd = GetNthSunday(yearVal, 11, 1) ' 1st Sunday in November
' Add time component (2am)
dstStart = dstStart + TimeSerial(2, 0, 0)
dstEnd = dstEnd + TimeSerial(2, 0, 0)
'rwbr "dstStart: " & dstStart & ", dateObj: " & dateObj & ", dstEnd: " & dstEnd
' Check if date is within DST period
If dateObj >= dstStart And dateObj < dstEnd Then
DaylightSavingsTime = True
Else
DaylightSavingsTime = False
End If
'rwbr "out DaylightSavingsTime, DaylightSavingsTime: " & DaylightSavingsTime
End Function
' Helper function to get nth Sunday of a month
Function GetNthSunday(year, month, n)
Dim firstDay, firstSunday, nthSunday
' Get first day of the month
firstDay = DateSerial(year, month, 1)
' Find the first Sunday
firstSunday = firstDay + (8 - Weekday(firstDay)) Mod 7
' Calculate the nth Sunday
nthSunday = firstSunday + (n - 1) * 7
GetNthSunday = nthSunday
End Function
' Function to instantiate running averages
Function InstantiateRunningAverages(traceName)
Dim nPoints
nPoints = 3
' Create global objects
Set RA_x = New RunningAverage
RA_x.Initialize nPoints
If traceName = "WindDirection" Then
Set RA_y = New RunningAverage_Dir
RA_y.Initialize nPoints
Else
Set RA_y = New RunningAverage
RA_y.Initialize nPoints
End If
End Function
%>