Kundehovedsiden vises ovenfor for en restaurant i nabolaget og giver mulighed for at kunder kan afsende en bestilling ved at vælge den ønskede ret i SELECT-boksen, indtaste telefonnummer i tekstboksen og derefter trykke på knappen ``Afsend Bestilling''.
<form action=order.tcl>
<input type=hidden name=store_id value=1>
...
</form>
Udover den skjulte formvariabel store_id, som angiver
identiteten på restauranten, skal formen indeholde tre form-elementer:
name=dish_id. Til højre
vises formen med SELECT-boksen udfoldet; værdierne for hver af
mulighederne i SELECT-boksen ønskes sat til henholdsvis 1, 2 og 3.
name=phone og size=8.
value="Afsend Bestilling".
http://didim.dk/didim.jpg
ønskes vist til højre for formen.
statistics.tcl?store_id=1
star_graph,
vist nedenfor, med listen af bestillingsforekomster
[list [list "Pizza nr. 9" 5] [list "Pizza nr. 5" 2]]givet som argument:
proc star_graph { l } {
set res "<table width=100%>"
foreach e $l {
set name [lindex $e 0]
set count [lindex $e 1]
set n $count
set bar ""
while { $n > 0 } {
append bar "*"
incr n -1
}
append res "<tr><td width=50%>$name</td>
<td width=50%>$count: $bar</td>
</tr>"
}
return "$res</table>"
}
max_count, som tager en liste af
bestillingsforekomster som argument og returnerer det maksimale antal
gange en ret er bestilt.
Hint: Ved følgende kald af proceduren max_count skal
proceduren returnere værdien 5:
max_count [list [list "Pizza nr. 9" 5] [list "Pizza nr. 5" 2]]Du kan med fordel benytte tcl's indbyggede
foreach
kommando til at gennemløbe de enkelte elementer i listen.
star_graph2 ved at
modificere proceduren star_graph fra Opgave 2.1, således
at det, selv ved mange tusinde bestillinger, er muligt grafisk at
sammenligne antallet af bestillinger. I løsningen ønskes der vist 10
stjerner for retten med de fleste bestillinger.Hint: Antallet af stjerner n der ønskes tegnes for en enkelt ret fås således ved formlen
hvor count er antallet af bestillinger for en bestemt ret og
max er det maksimale antal gange en ret er bestilt. Proceduren
star_graph2 kan med fordel benytte proceduren
max_count til at returnere det maksimale antal gange en
ret er bestilt.
[0-9] matches af en forekomst af
cifrene 0-9. Opskriv et regulært udtryk som matches af telefonnumre
bestående af 8 cifre.
Telefonnumrene 26122212 og 21332223 skal
således matche det regulære udtryk.
pz_check_phone til at undersøge om
et telefonnummer har formen som beskrevet i Opgave 3.1. Hvis
telefonnummeret, som overføres til proceduren som argument, har den
rigtige form skal proceduren med det samme returnere til stedet
hvorfra proceduren kaldes. Ellers skal proceduren returnere en
fejlbesked til brugerens web-browser ved brug af AOLservers indbyggede
kommando ns_return, hvorefter programmet skal stoppe ved
et kald til tcl-kommandoen exit.
Til at undersøge om telefonnummeret har den rigtige form skal du
benytte tcl-kommandoen regexp.
store - indeholder data om restauranterne (butikkerne)
dish - indeholder data om retterne der tilbydes af de enkelte restauranter
dish_order - indeholder bestillinger knyttet til de enkelte restauranter
Tabellerne store og dish og tre
Oracle sekvencer til generering af unikke numre er oprettet ved
følgende SQL kommandoer:
create table store (
id integer primary key,
name varchar(400) not null,
pic_url varchar(400),
address varchar(400)
);
create table dish (
id integer primary key,
store_id references store,
name varchar(400) not null
);
create sequence store_id_seq start with 10;
create sequence dish_id_seq start with 10;
create sequence order_id_seq start with 10;
Følgende SQL insert kommandoer kan efterfølgende antages
at være udført:
insert into store (id, name, pic_url, address) values (1, 'Didim Pizza Pasta og Grill', 'http://didim.dk/didim.jpg', 'Vibevej 35, 2400 Kbh. NV. Tlf. 38100571 - Så har vi det klar når De kommer'); insert into dish (id, store_id, name) values (1, 1, 'Nr 9: Pepperoni. Kr. 38,-'); insert into dish (id, store_id, name) values (2, 1, 'Nr 24: Hawaii. Kr. 38,-'); insert into dish (id, store_id, name) values (3, 1, 'Nr 36: Didim Bøf. Kr. 40,-');
select kommando:
select id, name from dish;
dish_order. Tabellen skal have fem kolonner:
id - unikt heltal til at identificere en bestilling
(primary key)
dish_id - reference til dish tabel
order_date - datoen for bestillingen (brug Oracles
date datatype)
phone - telefonnummer til bestilleren
deleted_p - boolean som når bestilling foretages
sættes til 'f' (falsk) og til 't' (true) når bestillingen er
afhentet
not null-constraint til at udtrykke at
felterne order_date og phone skal være
udfyldte.
dish_order - givet de tidligere indsættelser i
tabellerne store og dish:
2001-01-05)
2001-01-06)
deleted_p = 'f') til restauranten
``Didim Pizza Pasta og Grill''. Følgende kolonner skal indgå i
resultatet: order_date, dish_id,
name (dvs. dish.name), phone,
order_id (dvs. dish_order.id). Rækkerne ønskes
sorteret efter bestillingsdatoen.
name (dvs. dish.name)
og count (dvs. antallet af bestillinger af den pågældende
ret). Både afhentede og ikke-afhentede bestillinger skal indgå i
statistikken.
Hint: SQL kommandoen skal hente data fra de to tabeller
dish og dish_order og desuden benytte SQL's
group by konstruktion.
pz_return_page, som har til formål at kunne benyttes som
ramme til at returnere HTML-sider til brugere. Ved at proceduren tager
som argument en database handle db og en store identifier
store_id kan proceduren, ved hjælp af
databaseforespørgsler, konstruere en passende header og footer for
siderne:
proc pz_return_page { db store_id body } {
# Fetch store name and address from the database
set query " ... "
set selection [ns_db 1row $db $query]
set_variables_after_query
# return a page (see Opgave 1.2)
ns_return 200 text/html "
<html>
... $name ... $body ... $address ...
</html>"
}
Opskriv tcl-koden for definitionen af tcl-variablen
query, således at det efter
set_variables_after_query kommandoen bliver muligt at
henvise til restaurantens navn og adresse ved brug af tcl-variablerne
name og address. Bemærk: Det er ikke meningen at du her skal opskrive den returnerende HTML-kode; dette har du tilnærmelsesvis gjort i Opgave 1.2.
order.tcl som udføres når en kunde afgiver en ordre. Vi
vil ikke her beskæftige os med at konstruere filen
index.tcl, men det kan antages at formvariabler
phone, dish_id og store_id
overgives til filen order.tcl (se iøvrigt Opgave
1.1).
Filen order.tcl skal indsætte i databasen en bestilling
af retten dish_id for restauranten store_id,
foretaget af en person med telefonnummer phone. Datoen
for bestillingen skal også indgå i de data der indsættes i databasen.
Bemærk: Det kan yderligere antages at procedurerne
pz_check_id og pz_check_phone kan benyttes
til at sikre at en streng indeholder henholdsvis et tal og et
telefonnummer. Herudover kan proceduren pz_return_page
benyttes til at returnere en ``Tak for din bestilling''-side til
kunden med mulighed for at klikke sig tilbage til
index.tcl-siden og bestille flere retter. Filen
index.tcl forventer store_id overført som
formvariabel.
statistics.tcl på baggrund af skabelonen nedenfor:
# Set the form variable 'store_id'
set_form_variables
pz_check_id $store_id
set db [ns_db gethandle]
set query " -- DIT SVAR PÅ OPGAVE 4.5 MED store_id = 1
-- ERSTATTET AF store_id = '$store_id' "
set selection [ns_db select $db $query]
set dishes [list]
while { [ns_db getrow $db $selection] } {
# Set the tcl-variables name and count to the dish name and the
# number of orders of this particular dish
set_variables_after_query
# APPEND A PAIR (ACTUALLY A LIST) OF name AND count
# TO THE LIST dishes
##A## ...
}
set graph [star_graph2 $dishes]
# RETURN A PAGE TO THE USER
##B## ...
Opgaven består i at opskrive kode for programpunkterne
##A## og ##B## i skabelonen ovenfor.
For at simplificere systemet kræves der ikke password til at tilgå restaurantadministrationsfunktionerne.
Betragt følgende skabelon til filen admin.tcl:
# set and check the form variable 'store_id'
set_form_variables
pz_check_id $store_id
set db [ns_db gethandle]
set query " -- DIT SVAR PÅ OPGAVE 4.4 MED store_id = 1
-- ERSTATTET AF store_id = '$store_id' "
set selection [ns_db select $db $query]
# INITIALIZE THE TCL VARIABLE body
##A## ...
while { [ns_db getrow $db $selection] } {
set_variables_after_query
# The variables order_date, name, phone,
# and order_id are now set
# APPEND AN ORDER TO THE PAGE BODY
##B## ...
}
# APPEND SOME HTML-CODE TO body
##C## ...
set header "
<meta http-equiv=Refresh
content=\"5;url=http://hug.it.edu:8002/pz/admin.tcl?store_id=$store_id\">"
pz_return_page_with_header $db $store_id $header "
<h2>Bestillinger</h2>
<a href=index.tcl?store_id=$store_id>Hovedsiden</a> :: Bestillingsoversigt
<hr>
$body"
Opskriv kode for programpunkterne ##A##,
##B## og ##C## i skabelonen ovenfor. Husk
blandt andet et link til filen delete.tcl, som forventer
formvariablerne store_id og order_id.
Bemærk: Koden for filen admin.tcl benytter en modificeret
udgave af proceduren pz_return_page, som tillader et
meta-tag at blive indsat i HTML-headeren;
meta-tagget der her benyttes sørger for at browseren
genloader siden admin.tcl hver femte sekund, således at
restaurantejerne straks bliver opmærksomme på nye bestillinger!
delete.tcl.
Bemærk: Bestillingen skal ikke slettes fra databasen, da dette vil
ødelægge statistikmuligheden. Istedet skal feltet
deleted_p opdateres til 't' ved brug af
SQL's update kommando. Endelig skal tcl-filen omdirigere
brugeren til admin.tcl-filen ved brug af tcl-kommandoen
ns_returnredirect.