ProWeb: Phases of the Moon
This example computes the next quarter phase of the moon occuring on or after a given date and presents it in the form of an HTML page. This page includes a submit button which generates subsequent phases.
The Underlying Prolog Program
One of the standard example programs distributed with WIN-PROLOG is a simple program that computes phases of the moon. This file, called LUNAR.PL, can be found in the EXAMPLES directory. This program determines the current or next phase of the moon by calculating the number of quarter lunar months since the 1st January 1900 (when a new moon occurred), the algorithm assuming that a lunar month lasts 29.53059 days:
/*
Lunar Phase - Copyright (c) Brian D Steel - 25 Apr 94
=====================================================
This program computes the next quarter phase of the moon
occurring on or after the given date, based on two
assumptions: (i) a new moon occurred on 01 Jan 1900, and
(ii) the lunar month is 29.53059 days.
*/
% compute the quarter of the moon on or after the current date
lunar( Phase, Day, Month, Year ) :-
date( Dy, Mo, Yr ),
lunar( Dy, Mo, Yr, Phase, Day, Month, Year ).
% compute the quarter of the moon on or after the given date
lunar( Dy, Mo, Yr, Phase, Day, Month, Year ) :-
Lunar is 29.53059,
Quart is Lunar / 4,
date( 01, 01, 1900, Day1 ),
date( Dy, Mo, Yr, Day2 ),
Days is Day2 - Day1,
Stage is Days mod Lunar,
Day3 is ip(Day2 + Quart - Stage mod Quart),
Entry is ip(Stage * 4 / Lunar) + 1,
( date( Day, Month, Year, Day3 ),
mem( [ 'First Quarter',
'Full Moon',
'Third Quarter',
'New Moon'
], [Entry], Phase )
; Day4 is Day3 + 1,
date( Dy1, Mo1, Yr1, Day4 ),
lunar( Dy1, Mo1, Yr1, Phase, Day, Month, Year )
).
How the Program Works
If you were to execute the lunar/4 predicate from the Prolog prompt, a solution similar to the following would be returned:
?- lunar( Phase, Day, Month, Year ). <enter>
Phase = 'Third Quarter' ,
Day = 27 ,
Month = 7 ,
Year = 1997 ;
Backtracking through the goal causes successive solutions to be returned:
Phase = 'New Moon' ,
Day = 3 ,
Month = 8 ,
Year = 1997 ;
...
Developing the ProWeb Front-End
This ProWeb example takes each successive solution to the lunar/4 predicate and presents it in an HTML page. We create this page from a combination of two prolog clauses and a template HTML file. The prolog clauses are:
proweb_page( [ Form ],
[ include('lunar\head.htm'),
Title,
include('lunar\body.htm'),
proweb(Form),
include('lunar\foot.htm')
]
) :-
Form = lunar(_Nth),
Title = `Phases of the Moon`.
proweb_form( lunar(_Nth),
[include( 'lunar\lunar.htm')]
).
The text in each of the respective files, HEAD.HTM, BODY.HTM and FOOT.HTM, is as follows:
<HTML>
<HEAD>
<TITLE>
insert title here...
</TITLE>
</HEAD>
<BODY BACKGROUND="lunar.gif" BGCOLOR="#0000FF"
TEXT="#00FFFF" LINK="#FFFF00" VLINK="#00FF00">
<TABLE>
<TD>
</TD>
<TD>
insert form here...
</TD>
</TABLE>
</BODY>
</HTML>
The text of the LUNAR.HTM file is:
<HTML>
<BODY>
<FORM NAME="ProWeb" METHOD=GET ACTION="/pws_exec/pws/proweb.exe">
<CENTER>
<TABLE BORDER="1"
CELLSPACING="3" CELLPADDING="6" WIDTH="100%">
<TR>
<TD COLSPAN="3" ALIGN=CENTER>
<H1>Phases of the Moon</H1>
</TD>
</TR>
<TR>
<TD ALIGN=CENTER VALIGN=MIDDLE>
<H1><B><PROWEB REPLY="phase"></B>
<P>
on
<P>
<B>
<PROWEB REPLY="day">
/ <PROWEB REPLY="month">
/ <PROWEB REPLY="year">
</B></H1>
</TD>
<TD ALIGN=CENTER VALIGN=MIDDLE>
<IMG SRC="IMAGES\<PROWEB REPLY="gif">">
</TD>
<TD ALIGN=CENTER>
<INPUT TYPE="submit" VALUE="Get Next Phase">
<P>
<A HREF="/pws_det.htm">
Back to ProWeb Demos</A><P>
<A HREF="/index.htm">
Visit the LPA Home Page!</A><P>
</TD>
</TR>
</TABLE>
</CENTER>
</FORM>
</BODY>
</HTML>
The main goal for this example is lunar/0, as shown below. Successive solutions to the lunar/4 predicate are generated using the built-in solution/2 predicate. If the page containing the Nth solution has already been sent, the next line fails and forces the solution/2 predicate to backtrack and generate the next numbered solution. In executing each of the proweb_post_reply predicates, ProWeb stores another piece of the solution. The last line constructs the lunar(Nth) page and sends it to the client.
lunar :-
solution( lunar( Phase, Day, Month, Year ), Nth ),
\+ proweb_returned_form( lunar(Nth) ),
proweb_post_reply( phase, Phase ),
phase_to_gif( Phase, PhaseGif ),
proweb_post_reply( gif, PhaseGif ),
proweb_post_reply( day, Day ),
proweb_post_reply( month, Month ),
proweb_post_reply( year, Year ),
proweb_send_form( lunar(Nth) ).
To improve the appearance of the HTML page, we send a GIF file that shows the moon in the appropriate phase. The following database predicate converts from the textual name to the GIF file name:
phase_to_gif( 'New Moon', `new.gif` ).
phase_to_gif( 'First Quarter', `first.gif` ).
phase_to_gif( 'Third Quarter', `third.gif` ).
phase_to_gif( 'Full Moon', `full.gif` ).
Taking 'New Moon' as an example, the line <IMG SRC="IMAGES\<PROWEB REPLY="gif">"> from our template HTML file is converted to <IMG SRC="IMAGES\new.gif"> when sent to the client.
|