Astronomy

Date: 198x
Type: Program
Platform(s): TS 2068
Tags: Astronomy

This program computes the approximate rise, transit, and set times for the Sun, Moon, and all eight planets (Mercury through Pluto) for any user-specified date and geographic location. The user supplies a latitude and longitude (defaulting to approximately 34.85°N, 87.65°W) and selects one of ten bodies by number. Planetary orbital elements are packed as fixed-width seven-character fields into string variables and parsed with VAL and substring slicing at line 1970, allowing nine orbital parameters per body to be loaded into the 9×9 array P without a DATA statement. Sidereal time is computed at lines 3280–3400, and rise/set hour angles are derived via the ACS function using the tangent product of latitude and declination. The Moon uses a separate simplified positional algorithm (lines 2670–2860) based on mean longitude, perigee, and ecliptic anomaly rather than the general planetary routine.


Program Analysis

Program Structure

The program is organized into a set of clearly delineated subroutines called from a mostly linear main flow. After initialization and user prompts, control passes through date entry, planet selection, orbital calculations, and time display. The top-level flow is:

  1. Lines 10–230: Variable and array dimensioning, conversion constants.
  2. Lines 260–590: Set/confirm latitude and longitude.
  3. Lines 600–630: Load planetary element arrays via GO SUB 1360.
  4. Lines 640–830: Date entry and Julian Day Number computation.
  5. Lines 840–980: Compute NI (days from epoch), sidereal time, planet selection.
  6. Lines 990–1350: Display planetary data and offer a printed copy.
  7. Lines 1360–1660: Planetary orbital element loader.
  8. Lines 1670–1950: Planet name assignment and orbital position computation loop.
  9. Lines 1960–2000: Element parser subroutine.
  10. Lines 2010–2120: Mean anomaly / true anomaly / distance solver.
  11. Lines 2130–2420: Geocentric RA and declination computation.
  12. Lines 2430–2660: Rise, transit, and set time computation.
  13. Lines 2670–3030: Dedicated Moon position routine.
  14. Lines 3040–3270: Planet selection menu.
  15. Lines 3280–3400: Sidereal time subroutine.
  16. Lines 3410–3560: Rise/transit/set display subroutine.
  17. Lines 3570–3840: “Another planet / another date” re-run logic.

Orbital Element Storage and Parsing

Rather than using DATA/READ statements, the nine orbital parameters for each planet are packed as fixed-width 7-character decimal fields concatenated into the string M$. The subroutine at line 1960 iterates K from 1 to 9, extracting each field with:VAL (M$(1+((K-1)*7) TO (K*7)))

and storing the result in the 9×9 array P(U,K). This packs 63 characters per planet into a single string, allowing all element data to be initialized without any DATA statements, which is a useful memory technique. The outer loop at lines 1370–1640 calls this subroutine once per planet, incrementing the planet counter U each time.

Orbital Position Computation

The subroutine at lines 2010–2120 computes a first-order Keplerian orbit. Starting from mean anomaly (A), it applies a single-step equation-of-center correction using P(J,3)*SIN(A-P(J,4)) to approximate true anomaly. Heliocentric distance is then found from P(J,5)+P(J,6)*SIN(A-P(J,7)) and latitude perturbation L from P(J,8)*SIN(A-P(J,9)). Angle wrapping is handled by repeated conditional addition/subtraction of P2 (2π) rather than a modulo operation.

Geocentric RA and Declination

Lines 2130–2420 convert heliocentric positions to geocentric equatorial coordinates. The angular separation Z between the Sun and the planet (in heliocentric longitude) is computed, and the law of cosines gives the geocentric distance Q. Right ascension is derived using ACS (arccosine), with the sign of Z determining whether the planet is east or west of the Sun. Declination uses the obliquity of the ecliptic (23.44194°). The Sun’s own RA and declination are computed at lines 2320–2410 using a small constant 3.141159 (note the slight typographic error — should be 3.14159, differing at the fifth decimal place) rather than PI.

Moon Routine

When body 10 (Moon) is selected, the program branches at line 980 to a separate algorithm (lines 2670–2860). This uses three fundamental lunar quantities:

  • LZ = mean longitude epoch value (311.1687°)
  • LE = mean longitude of the Sun’s perigee epoch (178.699°)
  • LP = mean longitude of lunar perigee epoch (255.7433°)

The mean lunar longitude is advanced by the sidereal period (27.32158 days), and a single sine correction term (6.2886°) approximates the equation of the center. Declination combines the Moon’s ecliptic latitude (derived from the angle to the ecliptic node) with the Sun’s obliquity contribution. The result is stored in R(10) and V(10) before passing to the shared rise/set subroutine.

Rise, Transit, and Set Calculation

The subroutine at lines 2430–2660 computes times using the standard hour-angle formula. The critical intermediate value is:TA = ACS(ABS(TAN(FR*LA) * TAN(FR*V(CI))))

where FR is the degrees-to-radians factor, LA is latitude, and V(CI) is declination. The sign of TA is manipulated at lines 2440–2510 using an unusual idiom: if TA<0 the absolute value is taken, if TA>0 it is negated, with the result that the sign logic appears inverted. This may produce incorrect results for bodies with positive declination at northern latitudes — a potential bug. Rise and set times are adjusted by small constants (−1/60 and +3/60 hours respectively) as atmospheric refraction corrections, and all times are corrected to sidereal time via the factor 0.99727.

Sidereal Time

The subroutine at lines 3280–3400 computes local sidereal time at noon as:T2 = TC*(NI - 7020) + GC

where GC = 11.927485 hours and TC = 0.065711 hours/day are empirical constants, and NI is the day count from the program’s epoch (Julian Day 715875, approximately January 1, 1960). Normalization to [0, 24) hours is performed by successive conditional subtraction/addition, the same pattern used throughout the program in place of MOD arithmetic.

Day Number Computation

Lines 880–950 compute a modified Julian Day number. For months before March, a different formula is used (line 910) that incorporates a Gregorian leap-year correction INT(0.75 * INT((Y-1)/100 + 1)). For March onward, a simpler expression is applied (lines 930–940). The longitude offset is added to the day at line 888 to shift the calculation to apparent noon at the observer’s meridian.

Key Variables

VariableRole
P(U,K)9×9 array of orbital elements, one row per planet
NIDay count from epoch (Julian Day minus 715875)
T2Local sidereal time at noon
CICurrently selected body index (1–10)
FLFlag to skip re-loading planet names on subsequent queries
FRDegrees-to-radians factor (π/180 ≈ 0.01745329)
FDRadians-to-degrees factor (180/π ≈ 57.29578)
TR, TT, TSRise, transit, and set times in decimal hours
R(CI), V(CI)Right ascension (hours) and declination (degrees) for body CI

Notable Bugs and Anomalies

  • Line 2400 uses the literal 3.141159 instead of 3.14159 — a digit transposition typo, though the error (≈6×10⁻⁶) has negligible practical effect.
  • Lines 2440–2500 contain a sign-reversal logic for TA that appears to invert the expected behavior: negative TA is made positive and positive TA is negated before ACS is applied. This may cause rise and set times to be swapped or incorrect for some declination/latitude combinations.
  • Line 1880 uses IF I=3 THEN NEXT I to skip the Sun (index 3) in the geocentric conversion loop, since the Sun does not need a heliocentric-to-geocentric transform — a clean idiom for loop body exclusion.
  • Lines 1940–1950 show a FOR I=1 TO 9 immediately followed by RETURN, with no loop body and no NEXT. This fragment appears to be dead code or a copying artifact; execution falls through to RETURN on the first iteration.
  • The FL flag is set to 2 at line 3700 when the Sun is reselected on the same date, but the test at line 1680 only checks FL=1, so planet names are always reloaded when FL=2 — the intended optimization for the Sun re-query case does not fire.

Content

Appears On

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   10 CLEAR 
   20 DIM A$(10)
   30 DIM U(9)
   40 DIM P(9,9)
   50 DIM N$(22)
   60 DIM M$(63)
   70 DIM P$(10,7)
   80 LET P2=2*PI
  100 DIM A(9)
  110 DIM D(9)
  120 DIM L(9)
  130 DIM Q(9)
  140 DIM R(10)
  150 DIM V(10)
  160 DIM K(9)
  170 LET FL=0
  180 DIM V$(9)
  200 DIM R$(10)
  230 LET FR=.01745329
  240 LET FD=57.29578
  250 REM ----SET LATITUDE----
  260 LET LA=34.85
  270 REM ----SET LONGITUDE----
  280 LET LO=87.65
  300 PRINT 
  310 PRINT 
  320 PRINT 
  330 PRINT "   THIS PROGRAM COMPUTES THE "
  340 PRINT "APPROXIMATE TIMES OF THE RISING,"
  350 PRINT "TRANSIT, AND SETTING OF A PLANET"
  360 PRINT "THE SUN OR THE MOON FOR ANY DATE"
  370 PRINT "WHICH YOU REQUEST."
  380 PRINT 
  390 PRINT "INITIAL CONDITIONS ARE SET FOR.."
  400 PRINT "  LATITUDE    ";LA
  410 PRINT "  LONGITUDE   ";LO
  420 PRINT 
  430 PRINT "DO YOU WISH TO CHANGE THEM? Y/N";
  500 INPUT B$
  510 PRINT 
  520 IF B$<>"Y" THEN GO TO 590
  522 PRINT 
  530 PRINT "TYPE LATITUDE  ";
  540 INPUT LA: PRINT LA
  550 PRINT "TYPE LONGITUDE ";
  560 INPUT LO: PRINT LO
  590 PRINT 
  600 PRINT 
  610 PRINT "PLEASE WAIT ... LOADING ARRAYS"
  620 GO SUB 1360
  630 CLS 
  640 PRINT 
  650 PRINT 
  660 PRINT "ENTER THE DATE"
  670 PRINT 
  680 PRINT "     YEAR.... ";
  690 INPUT Y: PRINT Y
  700 PRINT 
  710 PRINT "     MONTH... ";
  720 INPUT M: PRINT M
  750 IF M<1 OR M>12 THEN GO TO 720
  760 PRINT 
  770 PRINT "     DAY..... ";
  780 INPUT DY: PRINT DY
  800 IF DY<1 OR DY>31 THEN GO TO 770
  810 IF M=2 AND DY>29 THEN GO TO 770
  830 GO SUB 3040
  840 PRINT 
  850 LET DX=DY
  860 LET MX=M
  870 LET YX=Y
  880 LET DY=DY+(LO/15)/24
  890 LET DG=365*Y+DY+((M-1)*31)
  900 IF M>=3 THEN GO TO 930
  910 LET DG=DG+INT ((Y-1)/4)-INT ((.75)*INT ((Y-1)/100+1))
  920 GO TO 950
  930 LET DG=DG-INT (M*.4+2.3)+INT (Y/4)
  940 LET DG=DG-INT ((.75)*INT ((Y/100)+1))
  950 LET NI=DG-715875
  970 GO SUB 3280
  980 IF CI=10 THEN GO TO 2670
  990 CLS 
 1010 GO SUB 1670
 1030 PRINT 
 1040 PRINT "DATA REQUESTED FOR ";YX;" ";MX;" ";DX
 1050 PRINT "-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-"
 1060 IF CI=3 THEN PRINT TAB 20;"R.A.  DEC"
 1070 IF CI=3 THEN PRINT TAB 20;"HRS   DEG"
 1080 IF CI=3 THEN GO TO 1110
 1090 PRINT "        HEL. DIST.  R.A.  DEC"
 1100 PRINT "        LONG. A.U.  HRS   DEG."
 1110 PRINT "-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-"
 1120 IF CI=3 THEN PRINT P$(CI);TAB 19;R$( TO 4);" ";V$
 1130 IF CI=3 THEN PRINT 
 1140 IF CI=3 THEN GO TO 1250
 1150 PRINT P$(CI);
 1160 LET A(CI)=A(CI)*57.29578
 1170 LET A$=STR$ (A(CI))
 1180 PRINT TAB 8;A$( TO 4);
 1190 LET A$=STR$ (Q(CI))
 1200 PRINT TAB 13;A$( TO 5);
 1210 LET A$=STR$ (R(CI))
 1220 PRINT TAB 19;A$( TO 5);
 1230 LET A$=STR$ (V(CI))
 1240 PRINT TAB 25;A$( TO 5)
 1250 PRINT "-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-"
 1260 GO SUB 3410
 1270 PRINT 
 1280 PRINT "WANT A COPY? Y/N "
 1290 INPUT C$
 1300 IF C$="N" OR C$="NO" THEN GO TO 1320
 1310 COPY 
 1320 CLS 
 1330 PRINT 
 1340 PRINT 
 1350 GO TO 3570
 1360 REM ---PLANETARY DATA------
 1370 LET U=1
 1380 LET N$=".0714223.84840.3883011"
 1390 LET M$=N$+".34041.387100.0797402.73514.122173.836013"
 1400 GO SUB 1960
 1410 LET N$=".0279623.02812.0131952"
 1420 LET M$=N$+".28638.723300.0050603.85017.0593411.33168"
 1430 GO SUB 1960
 1440 LET N$=".0172021.74022.0320441"
 1450 LET M$=N$+".785471.00000.0170003.3392600000000000000"
 1460 GO SUB 1960
 1470 LET N$=".0091464.51234.1753015"
 1480 LET M$=N$+".852091.52370.1417041.04656.031420.858702"
 1490 GO SUB 1960
 1500 LET N$=".0014504.53364.090478."
 1510 LET M$=N$+"2391105.20280.2493741.76188.0197201.74533"
 1520 GO SUB 1960
 1530 LET N$=".0005844.89884.1055581"
 1540 LET M$=N$+".610949.53850.5341563.12570.0436331.97746"
 1550 GO SUB 1960
 1560 LET N$=".0002052.46615.0885932"
 1570 LET M$=N$+".9670619.1820.9015544.49084.0139601.28805"
 1580 GO SUB 1960
 1590 LET N$=".0001043.78556.016965."
 1600 LET M$=N$+"77318130.0600.2705402.33498.0314162.29162"
 1610 GO SUB 1960
 1620 LET N$=".0000693.16948.4712393"
 1630 LET M$=N$+".9130339.44009.860005.23114.3001971.91812"
 1640 GO SUB 1960
 1650 LET M$=""
 1660 RETURN 
 1670 REM ----PLANET NAMES----
 1680 IF FL=1 THEN GO TO 1790
 1690 LET P$(1)="MERCURY"
 1700 LET P$(2)="VENUS"
 1710 LET P$(3)="SUN"
 1720 LET P$(4)="MARS"
 1730 LET P$(5)="JUPITER"
 1740 LET P$(6)="SATURN"
 1750 LET P$(7)="URANUS"
 1760 LET P$(8)="NEPTUNE"
 1770 LET P$(9)="PLUTO"
 1780 LET P$(10)="MOON"
 1790 LET I=1
 1800 FOR J=1 TO 9
 1810 GO SUB 2010
 1820 LET A(I)=A
 1830 LET D(I)=D
 1840 LET L(I)=L
 1850 LET I=I+1
 1860 NEXT J
 1870 FOR I=1 TO 9
 1880 IF I=3 THEN NEXT I
 1890 GO SUB 2130
 1900 LET Q(I)=Q
 1910 LET R(I)=R
 1920 LET V(I)=V
 1930 NEXT I
 1940 FOR I=1 TO 9
 1950 RETURN 
 1960 FOR K=1 TO 9
 1970 LET P(U,K)=VAL (M$(1+((K-1)*7) TO (K*7)))
 1980 NEXT K
 1990 LET U=U+1
 2000 RETURN 
 2010 LET A=NI*P(J,1)+P(J,2)
 2020 IF A>6.28318 THEN LET A=((A/6.28318)-INT (A/6.28318))*6.28318
 2030 IF A<0 THEN LET A=A+P2
 2040 IF A<0 THEN GO TO 2030
 2050 LET C=P(J,3)*SIN (A-P(J,4))
 2060 LET A=A+C
 2070 IF A>P2 THEN LET A=A-P2
 2080 IF A<0 THEN LET A=A+P2
 2090 IF A<0 THEN GO TO 2080
 2100 LET D=P(J,5)+P(J,6)*SIN (A-P(J,7))
 2110 LET L=P(J,8)*SIN (A-P(J,9))
 2120 RETURN 
 2130 LET Z=A(3)-A(I)
 2140 IF ABS (Z)>PI AND Z<0 THEN LET Z=Z+P2
 2150 IF ABS (Z)>PI AND Z>0 THEN LET Z=Z-P2
 2160 LET CZ=COS (Z)
 2170 LET Q=D(I)^2+D(3)^2-2*D(I)*D(3)*CZ
 2180 LET Q=SQR (Q)
 2190 LET P=(D(I)+D(3)+Q)/2
 2200 LET X=2*ACS (SQR (((P*(P-D(I)))/(D(3)*Q))))
 2210 IF Z<0 THEN LET R=57.29578*(A(3)+3.14159-X)/15
 2220 IF Z>0 THEN LET R=57.29578*(A(3)+3.14159+X)/15
 2230 IF R>24 THEN LET R=R-24
 2240 IF R>24 THEN GO TO 2230
 2250 IF R<-24 THEN LET R=R+24
 2260 IF R<-24 THEN GO TO 2250
 2270 IF R<0 THEN LET R=R+24
 2280 IF R<0 THEN GO TO 2270
 2290 IF Z<0 THEN LET V=SIN (A(3)+PI-X)*23.44194+FD*L(I)
 2300 IF Z>0 THEN LET V=SIN (A(3)+PI+X)*23.44194+FD*L(I)
 2310 LET X=FD*X
 2320 LET R(3)=FD*(A(3)+PI)/15
 2330 IF R(3)<=24 THEN GO TO 2360
 2340 LET R(3)=R(3)-24
 2350 GO TO 2330
 2360 IF R(3)>=0 THEN GO TO 2390
 2370 LET R(3)=R(3)+24
 2380 GO TO 2360
 2390 LET R$=(STR$ (R(3)))( TO 4)
 2400 LET V(3)=SIN (A(3)+3.141159)*23.44194
 2410 LET V$=(STR$ (V(3)))( TO 4)
 2420 RETURN 
 2430 REM -----CALC TIMES-------
 2440 LET TA=TAN (FR*LA)*TAN (FR*V(CI))
 2450 IF TA<0 THEN GO TO 2470
 2460 IF TA>0 THEN GO TO 2490
 2470 LET TA=ABS (TA)
 2480 GO TO 2500
 2490 LET TA=-TA
 2500 LET TA=ACS (TA)
 2510 LET TA=FD*TA
 2520 LET B=-TA/15
 2530 LET TZ=0
 2540 LET TR=(B+R(CI)+TZ-T2)*.99727
 2550 LET TR=TR-1/60
 2560 IF TR<0 THEN LET TR=TR+24
 2570 IF TR>24 THEN LET TR=TR-24
 2580 LET C=TA/15
 2590 LET TS=(C+R(CI)+TZ-T2)*.99727
 2600 LET TS=TS+3/60
 2610 IF TS<0 THEN LET TS=TS+24
 2620 IF TS>24 THEN LET TS=TS-24
 2630 LET TT=R(CI)-T2+1/60
 2640 IF TT<0 THEN LET TT=TT+24
 2650 IF TT>24 THEN LET TT=TT-24
 2660 RETURN 
 2670 REM --MOON-RISE,XSIT,SET---
 2680 LET LZ=311.1687
 2690 LET LE=178.699
 2700 LET LP=255.7433
 2710 LET PG=.111404*NI+LP
 2720 LET PG=(PG/360-INT (PG/360))*360
 2730 LET LMD=LZ+360*NI/27.32158
 2740 LET LMD=(LMD/360-INT (LMD/360))*360
 2750 LET PG=LMD-PG
 2760 LET DR=6.2886*SIN (FR*PG)
 2770 LET LMD=LMD+DR
 2780 LET LMD=(LMD/360-INT (LMD/360))*360
 2790 LET RM=LMD/15
 2800 IF RM>24 THEN LET RM=RM-24
 2810 IF RM<0 THEN LET RM=RM+24
 2820 LET AL=LE-NI*.052954
 2830 LET AL=LMD-AL
 2840 LET AL=(AL/360-INT (AL/360))*360
 2850 LET HE=5.1454*SIN (AL*3.14159/180)
 2860 LET DM=HE+23.1444*SIN (LMD*3.14159/180)
 2870 LET R$=(STR$ (RM))( TO 5)
 2880 LET D$=(STR$ (DM))( TO 5)
 2890 CLS 
 2900 PRINT 
 2910 PRINT "MOON DATA REQUESTED FOR...."
 2920 PRINT TAB 4;"YEAR ";YX;" MONTH ";
 2930 PRINT MX;" DAY ";DX
 2940 PRINT 
 2950 PRINT "AT NOON"
 2960 PRINT "R.A. OF MOON IS. ";R$;" HRS"
 2970 PRINT "DECLINATION IS.. ";D$;" DEG"
 2980 PRINT "-------------------------------"
 2990 LET R(10)=RM
 3000 LET V(10)=DM
 3010 LET P$(CI)="MOON"
 3020 GO SUB 2430
 3030 GO TO 3420
 3040 REM ---PLANET SELECTION----
 3050 CLS 
 3060 PRINT 
 3070 PRINT 
 3080 PRINT 
 3090 PRINT "SELECT BY NUMBER"
 3100 PRINT 
 3110 PRINT TAB 5;"MERCURY.... 1"
 3120 PRINT TAB 5;"VENUS...... 2"
 3130 PRINT TAB 5;"            3....SUN"
 3140 PRINT TAB 5;"MARS....... 4"
 3150 PRINT TAB 5;"JUPITER.... 5"
 3160 PRINT TAB 5;"SATURN..... 6"
 3170 PRINT TAB 5;"URANUS..... 7"
 3180 PRINT TAB 5;"NEPTUNE.... 8"
 3190 PRINT TAB 5;"PLUTO...... 9"
 3200 PRINT TAB 5;"           10..MOON"
 3210 PRINT 
 3220 PRINT "TYPE NUMBER... ";
 3230 INPUT SS
 3240 IF SS<1 OR SS>10 THEN GO TO 3050
 3250 PRINT SS
 3260 LET CI=SS
 3270 RETURN 
 3280 REM -----SIDERAL TIME------
 3290 LET GC=11.927485
 3300 LET TC=.065711
 3310 LET T2=TC*(NI-7020)+GC
 3320 IF T2<24 THEN GO TO 3350
 3330 LET T2=T2-24
 3340 GO TO 3320
 3350 IF T2>-24 THEN GO TO 3380
 3360 LET T2=T2+24
 3370 GO TO 3350
 3380 IF T2>0 THEN GO TO 3400
 3390 LET T2=T2+24
 3400 RETURN 
 3410 GO SUB 2430
 3420 PRINT 
 3430 PRINT 
 3440 LET TM=60*(TR-INT (TR))
 3450 LET TR=INT (TR)
 3460 LET TN=60*(TT-INT (TT))
 3470 LET TT=INT (TT)
 3480 LET TP=60*(TS-INT (TS))
 3490 LET TS=INT (TS)
 3500 PRINT 
 3510 PRINT P$(CI)
 3520 PRINT "RISES AT.... ";TR;" HRS ";INT (TM);" MIN"
 3530 PRINT "TRANSITS AT. ";TT;" HRS ";INT (TN);" MIN"
 3540 PRINT "SETS AT..... ";TS;" HRS ";INT (TP);" MIN"
 3550 IF CI=10 THEN GO TO 1270
 3560 RETURN 
 3570 PRINT 
 3580 PRINT "WANT ANOTHER PLANET FOR THE"
 3590 PRINT "SAME DATE? Y/N ";
 3600 INPUT B$
 3610 PRINT B$
 3620 IF B$="N" THEN GO TO 3750
 3630 IF CI=10 THEN GO TO 3650
 3640 IF B$="Y" THEN GO TO 3690
 3650 LET DY=DX
 3660 LET M=MX
 3670 LET Y=YX
 3680 GO TO 820
 3690 GO SUB 3050
 3700 IF CI=3 THEN LET FL=2
 3710 IF CI=10 THEN GO SUB 2670
 3720 IF CI=10 THEN GO TO 3760
 3730 CLS 
 3740 GO TO 1030
 3750 PRINT 
 3760 PRINT "WANT ANOTHER DATE? Y/N ";
 3770 INPUT B$
 3780 PRINT B$
 3790 IF B$="N" THEN GO TO 3830
 3800 LET FL=0
 3810 LET F=0
 3820 IF B$="Y" THEN GO TO 630
 3830 CLS 
 3840 STOP 

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

People

No people associated with this content.

Scroll to Top