Microsoft Small Basic

Program Listing: HRT547-2
' Edo Clock v0.4 (C) 2011 Nonki Takahashi

' History:
' v0.1 2011/04/27 Created from Analog Clock v0.1 SGP929 (236 lines HRT547)
' v0.2 2011/04/07 Online version (236 lines HRT547-0)
' v0.3 2011/06/03 Implemented temporal hour system (234 lines HRT547-1)
' v0.4 2011/06/05 Created Edo_AlphaToAke6AndKure6() (278 lines HRT547-2)

' Main
sVersion = "v0.4"
GraphicsWindow.Title = "Edo Clock " + sVersion
rLocal = 9 ' local time for Japan
rAlpha = 75 ' ecliptic longitude 75 degree
Edo_Init()
Edo_AlphaToAke6AndKure6()
Clock_Init()
Digital_Init()
Alarm_Init()
Analog_Init()
Analog_DrawHourNumerals()
While "True"
If bTick Then
Digital_ShowTime()
Digital_ShowDate()
Analog_RotateHourHand()
Alarm_Ring()
bTick = "False"
Else
Program.Delay(500)
EndIf
EndWhile

' Alarm | Initialization
Sub Alarm_Init
iAX = 18 ' character size for alarm
iAY = 26
iAL0 = 11 ' alarm y position in line
GraphicsWindow.FontSize = iAY
GraphicsWindow.BrushColor = sFGColor
GraphicsWindow.BackgroundColor = sBGColor
GraphicsWindow.DrawText(iAX * 3, iAY * iAL0, "ALARM:")
GraphicsWindow.DrawText(iAX * 21, iAY * iAL0, ":")
GraphicsWindow.BrushColor = "Black"
oHour = Controls.AddTextBox(iAX * 11, iAY * iAL0)
oMin = Controls.AddTextBox(iAX * 23, iAY * iAL0)
GraphicsWindow.Height = iAY * (iAL0 + 2.5)
EndSub

' Alarm | Ring
Sub Alarm_Ring
iAHour = Controls.GetTextBoxText(oHour)
iAMin = Controls.GetTextBoxText(oMin)
If (iHour = iAHour) And (iMin = iAMin) Then
Sound.PlayChimesAndWait()
EndIf
EndSub

' Analog | Draw hour numerals
' in: rAke6, rKure6 - ake 6 and kure 6 [JST hour]
' in: iHX, iHY - font size for hour numerals
Sub Analog_DrawHourNumerals
GraphicsWindow.BrushColor = sFGColor
GraphicsWindow.FontSize = iHY
For iHour = 0 To 22 Step 2
If iHour > 9 Then
idX = - iHX
Else
idX = - iHX / 2
EndIf
rHour = iHour
Edo_HourToRadian()
iX = iXC - Math.Round(iR * 1.1 * Math.Sin(rEdoRadian) - idX)
iY = iYC + Math.Round(iR * 1.1 * Math.Cos(rEdoRadian) - iHY / 2)
GraphicsWindow.DrawText(iX, iY, iHour)
EndFor
EndSub

' Analog | Initialization
Sub Analog_Init
' time table initialization
sCity[9] = "Tokyo"
rDelta[9] = 9
iCities = 24
' selected city
iCity = 9
GraphicsWindow.BrushColor = sFGColor
If rDelta[iCity] > 0 Then
sSign = "+"
Else
sSign = ""
EndIf
GraphicsWindow.DrawText(iAX * 3 + iTX0, iAY * 7, sCity[iCity] + " (" + sSign + rDelta[iCity] + ")")
' show clock face
iR = 100 ' radius for analog clock face
iXC = 50 + iR ' center of analog clock
iYC = 40 + iR
uDialPlate = uFolder + "EdoDialPlate.png"
GraphicsWindow.DrawImage(uDialPlate, iXC - iR, iYC - iR)
' add hour hand as shape
uHour = uFolder + "EdoHourHand.png"
oHour = Shapes.AddImage(uHour)
Shapes.Move(oHour, iXC - iR, iYC - iR)
EndSub

' Analog | Rotate hour hand
' in: iHour, iMin, iSec - current hour, minute, second [JST]
Sub Analog_RotateHourHand
rHour = iHour + iMin / 60 + iSec / 3600
Edo_HourToRadian()
rEdoDegree = Math.GetDegrees(rEdoRadian)
rDegree = rEdoDegree + 12 * 360 / 24
Shapes.Rotate(oHour, rDegree)
EndSub

' Clock | Initialization
Sub Clock_Init
sBGColor = "Sienna" ' background color
sFGColor = "White" ' foreground color
sHourHandColor = "DarkGoldenrod" ' hour hand color
sHourHandFrame = "Goldenrod" ' hour hand frame color
Timer.Interval = 1000
Timer.Tick = Clock_OnTick
bTick = "False"
iDaySec = 24 * 60 * 60
iHourSec = 60 * 60
uFolder = "http://homepage2.nifty.com/nobukit/smallbasic.files/"
uWood = uFolder + "Wood.png"
GraphicsWindow.DrawImage(uWood, 0, 0)
EndSub

' Clock | Event processing on tick
Sub Clock_OnTick
iHour = Clock.Hour
iMin = Clock.Minute
iSec = Clock.Second
iYear = Clock.Year
iMonth = Clock.Month
iDay = Clock.Day
bTick = "True"
EndSub

' Clock | Format date
Sub Clock_FormatDate
sDate = iYear + "/"
If iMonth < 10 Then
sDate = sDate + "0" + iMonth + "/"
Else
sDate = sDate + iMonth + "/"
EndIf
If iDay < 10 Then
sDate = sDate + "0" + iDay
Else
sDate = sDate + iDay
EndIf
EndSub

' Clock | Format time
Sub Clock_FormatTime
If iHour < 10 Then
sTime = Text.Append("0", iHour) + ":"
Else
sTime = iHour + ":"
EndIf
If iMin < 10 Then
sTime = sTime + "0" + iMin + ":"
Else
sTime = sTime + iMin + ":"
EndIf
If iSec < 10 Then
sTime = sTime + "0" + iSec
Else
sTime = sTime + iSec
EndIf
EndSub

' Digital | Initialization
Sub Digital_Init
iTX = 6 * 6 ' character size for time
iTY = 10 * 6
iTX0 = 260
iHX = 9 ' character size for hour numerals
iHY = 13
iDX = 18 ' character size for date
iDY = 26
Clock_OnTick()
Clock_FormatDate()
GraphicsWindow.FontSize = iDY
GraphicsWindow.BrushColor = sFGColor
oDate = Shapes.AddText(sDate)
Shapes.Move(oDate, iDX * 3 + iTX0, iDY * 5 - 3)
Clock_FormatTime()
GraphicsWindow.FontSize = iTY
oTime = Shapes.AddText(sTime)
Shapes.Move(oTime, iTX * 1.4 + iTX0, iTY - 3)
EndSub

' Digital | Show date
Sub Digital_ShowDate
Clock_FormatDate()
Shapes.SetText(oDate, sDate)
EndSub

' Digital | Show time
Sub Digital_ShowTime
Clock_FormatTime()
Shapes.SetText(oTime, sTime)
EndSub

' Edo | Convert alpha to ake 6 and kure 6
' in: rAlpha - ecliptic longitude [degree]
' out: rAke6 - Edo ake (morning) 6 [JST hour]
' out: rKure6 - Edo kure (evening) 6 [JST hour]
Sub Edo_AlphaToAke6AndKure6
rCosT = Math.Cos(Math.GetRadians(rTiltDegree))
rTanA = Math.Tan(Math.GetRadians(rAlpha))
rADashRadian = Math.ArcTan(rTanA * rCosT)
If rAlpha > 270 Then
rADashRadian = rADashRadian + 2 * Math.Pi
ElseIf rAlpha >= 90 Then
rADashRadian = rADashRadian + Math.Pi
EndIf
rAlphaDash = Math.GetDegrees(rADashRadian) ' north pole view of ecliptic longitude [degree]
rNorth = Math.Sin(Math.GetRadians(rTiltDegree)) ' distance from north pole to ecliptic latitude 90 degree [equatorial radius]
rNumerator = 1 - Math.Power(Math.Cos(rADashRadian), 2)
rDenominator = 1 / Math.Power(rNorth, 2) - Math.Power(Math.Cos(rADashRadian), 2)
rSquareB = rNumerator / rDenominator ' b^2 (while b = semiminor axis of shadow)
rShadowE = Math.SquareRoot(1 - rSquareB) ' eccentricity of shadow
rRadiusTokyo = Math.Cos(Math.GetRadians(rLatTokyo)) ' radius for same latitude of Tokyo [equatorial radius]
rNumerator = Math.SquareRoot(1 - rSquareB / Math.Power(rRadiusTokyo, 2))
rQuotient = rNumerator / rShadowE
rSunriseRadian = Math.ArcCos(rQuotient) ' sunrise angle from 6 a.m. [degree]
If rAlphaDash > 180 Then
rSunriseRadian = (-1) * rSunriseRadian
EndIf
rSunriseDegree = Math.GetDegrees(rSunriseRadian) ' sunrise angle from 6 a.m. [degree]
rAke6Degree = 90 - rSunriseDegree - rFactor - (rLongTokyo - rLongAkashi)
rKure6Degree = 270 + rSunriseDegree + rFactor - (rLongTokyo - rLongAkashi)
rAke6 = rAke6Degree * 24 / 360
rKure6 = rKure6Degree * 24 / 360
EndSub

' Edo | Convert JST hour to Edo radians
' in: rHour - [0..24) [JST hour]
' in: rAke6 - Edo ake (morning) 6 [JST hour]
' in: rKure6 - Edo kure (evening) 6 [JST hour]
' work: rAkatsuki9 - Edo akatsuki (before dawn) 9 (midnight) [JST hour]
' work: rHiru9 - Edo hiru (noon) 9 [JST hour]
' out: rEdoRadian - Edo clock radian for given JST hour
Sub Edo_HourToRadian
rHiru9 = (rAke6 + rKure6) / 2
rAkatsuki9 = rHiru9 + 12
If rAkatsuki9 >=24 Then
rAkatsuki9 = rAkatsuki9 - 24
EndIf
rYoruHanToki = (rAke6 + 24 - rKure6) / 12 ' Yoru (night) han (half) toki = about 1 hour
rHiruHanToki = (rKure6 - rAke6) / 12 ' Hiru (day) han (half) toki = about 1 hour
If rHour < rAke6 Then
rEdoHour = (rHour - rAkatsuki9 + 24) / rYoruHanToki
ElseIf rHour = rAke6 Then
rEdoHour = 6
ElseIf rHour > rAke6 And rHour < rKure6 Then
rEdoHour = 6 + (rHour - rAke6) / rHiruHanToki
ElseIf rHour = rKure6 Then
rEdoHour = 18
ElseIf rHour > rKure6 Then
rEdoHour = 18 + (rHour - rKure6) / rYoruHanToki
EndIf
rEdoRadian = (rEdoHour - 1) * 2 * 3.14159 / 24
EndSub

' Edo | Initialize constants
Sub Edo_Init
rFactor = 9 ' [degree]
rTiltDegree = 23.44 ' inclination of equator to orbit
rLatTokyo = 35 + 39 / 60 + 29.1572 / 3600 ' latitude of Tokyo
rLongTokyo = 139 + 44 / 60 + 28.8759 / 3600 ' longitude of Tokyo
rLongAkashi = 135 ' longitude of Akashi (Japan Standard Time)
EndSub