Eksempler
>FotballVM
Fotball VM
Løsningen er prinsippielt slik:
Dataflyt fotball VM
Javascript
Javascriptkoden som kjører på klienten bestiller en turneringsbeskrivelse eller et grupperesultat, tar i mot ferdig formatert tekst og plasserer denne teksten som "innerHTML". Skriptet er slik:
// relies on jquery.js
var currentYear='2006';
var scriptpath=
'http://www.it.hiof.no/~borres/cgi-bin/ajax/fifa/vmscript.py';
function getIt(targetNodeId,params)
{
$.ajax({
url:scriptpath,
data:params,
success:function(data)
{
$('#'+targetNodeId).html(data);
},
error:function(data)
{
$('#'+targetNodeId).html("Could not access content");
}
});
}
function startCountryRequest()
{
params='what=tournaments';
getIt('countrylist',params);
}
function startTournamentRequest(year)
{
currentYear=year;
params='year='+year;
getIt('tournament',params);
}
function startGroupRequest(gruppe)
{
params='gruppe='+gruppe+'&year='+currentYear;
getIt('gruppe',params);
}
Serverskriptet
Serverskriptet tolker forespørselen fra Javascriptkoden, slår opp i databasen, formaterer dataene i HTML-fragmenter og returnerer bestillingen. Skriptet er skrevet i Python og ser slik ut:
#! /usr/bin/python2.5
import MySQLdb,cgi
"""
Retrieve fotball data from MySql-base fotball
The return values ar either a complete webpage or a fragment suited for Ajax
See comments at the end of each method for adjustments
Produce result in file RESULT_FILE if we want to make a complete page
The HTML(fragments) uses some classes for styles, see fragments below
Used from: http://www.it.hiof.no/~borres/ml/fotballvm/index.html
"""
#-------------------------------------------------
# If we want to do some testing and write to a file
#-------------------------------------------------
RESULT_FILE='c:\\projects\\pydb\\dbaccessresultvm.html'
#-------------------------------------------------
# HTML-page if we want complete page return
#-------------------------------------------------
HTMLPAGE="""<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<link href="fotballstyles.css" rel="STYLESHEET" />
<title>dbaccessvm</title>
</head>
<body>
<h1>Results</h1>
%s
</body>
</html>
"""
#-------------------------------------------------
# SQL-statements
#-------------------------------------------------
SQL_ALL_COUNTRIES="""SELECT lagA,lagB FROM vwkamper;"""
SQL_ALL_COUNTRIES_IN_TOURNAMENT="""SELECT lagA,lagB
FROM vmkamper WHERE aar='%s';"""
SQL_ALL_MATCHES_IN_TOURNAMENT="""SELECT * FROM vmkamper WHERE aar='%s';"""
SQL_ALL_MATCHES_IN_TOURNAMENT_GROUP="""SELECT * FROM vmkamper
WHERE aar='%s' AND gruppe='%s';"""
SQL_ONE_TOURNAMENT="""SELECT * FROM vm WHERE aar='%s';"""
SQL_ALL_TOURNAMENTS="""SELECT aar,land FROM vm;"""
#-------------------------------------------------
# HTML-fragments serving as templates
#-------------------------------------------------
HTML_COUNTRY_LIST_FRAME="""<div class="country_list">
%s
</div>
"""
HTML_TEAM_LIST_FRAME="""<ul>
%s
</ul>
"""
HTML_TEAM_ROW="""<tr>
<td class="table_team">%s</td>
<td class="table_matchcount">%s</td>
<td class="table_matchcount">%s</td>
<td class="table_matchcount">%s</td>
<td class="table_matchcount">%s</td>
<td class="table_score">%s</td>
<td class="table_score">%s</td>
<td class="table_points">%s</td>
</tr>
"""
HTML_DESCRIPTION="""<div class="description">
%s
</div>
"""
HTML_TOURNAMENT_HEADER="""
<div>
<h3>%s - %s</h3>
<p>%s</p>
<form action="">
<div style="font-weight:bold">Velg resultater</div>
<select name="grupper" onchange="startGroupRequest(value);return false;">
<option value="lagliste">Alle lag</option>
%s
</select>
</form>
<div id="gruppe">
<!-- lagliste -->
</div>
</div>
"""
HTML_TABLE_FRAME="""<table>
%s
</table>
"""
HTML_MATCH_LINE="""<tr>
<td class="match_date">%s</td>
<td class="match_team">%s</td>
<td class="match_team">%s</td>
<td class="match_score">%s</td>
<td class="match_score">%s</td>
<td class="match_score">%s</td>
<td class="match_score">%s</td>
</tr>
"""
HTML_TOURNAMENT_SELECTOR_LINE="""
<div class="tournament"
onclick="javascript:startTournamentRequest('%s');return false;">%s %s</div>
"""
#-------------------------------------------------
# when database access goes wrong
#-------------------------------------------------
ERROR_RESULT='XXX'
ERROR_FLAG=False
def raiseErrorFlag():
global errorFlag
ERROR_FLAG=True
#-------------------------------------------------
# simply write file, for testing
#-------------------------------------------------
def storeTextFile(filename,txt):
try:
outfile=open(filename,'w')
outfile.write(txt)
outfile.close()
except:
print 'Error writing file ',filename
#-------------------------------------------------
# connect and execute a sql-request
#-------------------------------------------------
def connectAndExecute(sql):
try:
myBase=MySQLdb.connect(host='frigg.hiof.no',
user='student',
passwd='student',
db='fotball')
myTab=myBase.cursor()
myTab.execute(sql)
myBase.close()
return myTab.fetchall()
except MySQLdb.Error, e:
print "Error %d: %s" % (e.args[0], e.args[1])
return None
#-------------------------------------------------
# get all available tournaments
# return as a page fragment with div-lines
#-------------------------------------------------
def makeTournaments():
resultTxt=''
result=connectAndExecute(SQL_ALL_TOURNAMENTS)
if result==None:
return 'ingen turneringer funnet'
for row in result:
resultTxt+=HTML_TOURNAMENT_SELECTOR_LINE%(row[0],row[0],row[1])
# return as fragment
return resultTxt
# returnas complete page
#return HTMLPAGE%resultTxt
#-------------------------------------------------
# get all available countries in a tournament
# return as page,fragment or line, see bottom of method
#-------------------------------------------------
def makeCountryList(Y):
resultTxt=''
result=connectAndExecute(SQL_ALL_COUNTRIES_IN_TOURNAMENT%Y)
if result==None:
return 'ingen land funnet'
reslist=[]
for row in result:
row0str=str(row[0])
row1str=str(row[1])
if not row0str in reslist:
reslist.append(row0str)
if not row1str in reslist:
reslist.append(row1str)
reslist.sort()
for r in reslist:
resultTxt+=r+' , ';
# return simple lines:
#return resultTxt[0:len(resultTxt)-1].replace(' , ','\n')
# return fragment wrapped in a div-element
resultTxt=HTML_COUNTRY_LIST_FRAME%resultTxt[0:len(resultTxt)-2]
return resultTxt
# complete page return
#return HTMLPAGE%resultTxt
#-------------------------------------------------
# get all available matches in a group in a tournament
# return as page,fragment or lines, see bottom of method
#-------------------------------------------------
def makeGroupMatches(Y,G):
tableTxt=''
resultTxt=''
tabResultTxt=''
result=connectAndExecute(SQL_ALL_MATCHES_IN_TOURNAMENT_GROUP%(Y,G))
if result==None:
return 'ingen kamper funnet'
# make result table of this groups result
if G.lower().find('gruppe')!= -1:
tableTxt=makeTable(result,Y)
for row in result:
t=str(row[3])
dag=t[8:10]+'/'+t[5:7]
lagA=str(row[5])
lagB=str(row[6])
scoreA=str(row[7])
scoreB=str(row[8])
scoreAx=str(row[9])
scoreBx=str(row[10])
scoreAp=str(row[11])
scoreBp=str(row[12])
resultTxt+=dag+' '+lagA+' - '+lagB+' '+scoreA+':'+scoreB
if (scoreAx != '0') or \
(scoreBx != '0') or \
(scoreAp != '0') or \
(scoreBp != '0'):
resultTxt+='(eo. '+scoreAx+':'+scoreBx+' )'
if (scoreAp != '0') or (scoreBp != '0'):
resultTxt+='(str. '+scoreAp+':'+scoreBp+' )'
resultTxt+='\n'
if(scoreAp != '0') or (scoreBp != '0'):
tabResultTxt+=HTML_MATCH_LINE%\
(dag,lagA,lagB,scoreA,scoreB,'(eo.'+scoreAx+':'+scoreBx+')','(st.'+scoreAp+':'+scoreBp+')')
elif(scoreAx != '0') or (scoreBx != '0'):
tabResultTxt+=HTML_MATCH_LINE%\
(dag,lagA,lagB,scoreA,scoreB,'(eo.'+scoreAx+':'+scoreBx+')','')
else:
tabResultTxt+=HTML_MATCH_LINE%\
(dag,lagA,lagB,scoreA,scoreB,'','')
# simple lines return:
#print resultTxt
#return resultTxt[0:len(resultTxt)-1]
# fragment as a table pluss result table
tabResultTxt=tableTxt+HTML_TABLE_FRAME%tabResultTxt
return tabResultTxt
# complete page return
#return HTMLPAGE%tableTxt+tabResultTxt
#-------------------------------------------------
# prepare the headerinformation for a tournament
#-------------------------------------------------
def makeTournamentHeader(Y):
resultTxt=''
result=connectAndExecute(SQL_ONE_TOURNAMENT%Y)
if result==None:
return 'ingen informasjon funnet'
year=Y
country=str(result[0][1])
description=str(result[0][2])
groups=str(result[0][3])
# do the groups
groupTxt=''
grps=groups.split(';')
for g in grps:
groupTxt+='<option value="%s">%s</option>'%(g,g)+'\n'
# do the description
descriptionTxt=HTML_DESCRIPTION%description
# merge it
resultTxt=HTML_TOURNAMENT_HEADER%\
(year,country,descriptionTxt,groupTxt)
return resultTxt;
# complete page return
#return HTMLPAGE%ResultTxt
#-------------------------------------------------
# make a table of a groups results
# input result is from database, all matches in group
# return as page or fragment, see comments at end of method
#-------------------------------------------------
def makeTable(result,year):
# points for victory
if int(year) < 1987:
wp=2
else:
wp=3
# get all results
# pick up teams
teams=[]
allList=[]
for row in result:
aTeam=str(row[5])
bTeam=str(row[6])
if not aTeam in teams:
teams.append(aTeam)
if not bTeam in teams:
teams.append(bTeam)
# calculate each teams result row
for team in teams:
ownScore=0
oppScore=0
winCount=0
drawCount=0
looseCount=0
for row in result:
hTeam=str(row[5])
aTeam=str(row[6])
hScore=int(str(row[7]))+int(str(row[9]))+int(str(row[11]))
aScore=int(str(row[8]))+int(str(row[10]))+int(str(row[12]))
if hTeam == team:
ownScore=ownScore+hScore
oppScore=oppScore+aScore
if hScore > aScore:
winCount=winCount+1
elif hScore==aScore:
drawCount=drawCount+1
else:
looseCount=looseCount+1
if aTeam == team:
ownScore=ownScore+aScore
oppScore=oppScore+hScore
if aScore > hScore:
winCount=winCount+1
elif hScore==aScore:
drawCount=drawCount+1
else:
looseCount=looseCount+1
# finish this team
allList.append([team,winCount+drawCount+looseCount,
winCount,drawCount,looseCount,
ownScore,oppScore,wp*winCount+drawCount])
# sort teamrows
allList.sort(compareResults)
# prepare table rows
resultTxt=''
for tl in allList:
resultTxt+=HTML_TEAM_ROW%\
(tl[0],tl[1],tl[2],tl[3],tl[4],tl[5],tl[6],tl[7])
resultTxt=HTML_TABLE_FRAME%resultTxt
# Only prepared table, suitable for AJAX return:
return resultTxt;
# complete page return
#return HTMLPAGE%(resultTxt)
#-------------------------------------------------
# comparison for sorting table rows in makeTable
#-------------------------------------------------
def compareResults(a,b):
# a and b are lists, three last
# entries are homegolas, awaygoals and points
# which will be criterium
if a[len(a)-1] < b[len(b)-1]:
return 1
elif a[len(a)-1] > b[len(b)-1]:
return -1
# equal points, must check goals
a_goaldiff=a[len(a)-3]-a[len(a)-2]
b_goaldiff=b[len(b)-3]-b[len(b)-2]
if a_goaldiff < b_goaldiff:
return 1
elif a_goaldiff > b_goaldiff:
return -1
# equal diff, must check scored
if a[len(a)-3] < b[len(b)-3]:
return 1
return -1
#-------------------------------------------------
# for testing off server
#-------------------------------------------------
def doit(year='1930',gruppe='Gruppe A'):
#RESULT_TXT=makeCountryList(year)
#RESULT_TXT=makeGroupMatches(year,gruppe)
RESULT_TXT=makeTournamentHeader(year)
storeTextFile(RESULT_FILE,RESULT_TXT)
#-------------------------------------------------
# what is the job ?
#-------------------------------------------------
form=cgi.FieldStorage()
print 'Content-type: text/html; charset=utf-8\n'
RESULT_TXT=''
if form.has_key('year'):
year=form['year'].value
if form.has_key('gruppe'):
gruppe=form['gruppe'].value
if gruppe.find('lagliste')!= -1:
RESULT_TXT=makeCountryList(year)
else:
RESULT_TXT=makeGroupMatches(year,gruppe)
else:
RESULT_TXT=makeTournamentHeader(year)
RESULT_TXT=RESULT_TXT.replace('<!-- lagliste -->',
makeCountryList(year))
print RESULT_TXT
elif form.has_key('what'):
RESULT_TXT=makeTournaments()
print RESULT_TXT
else:
print 'Feil: ingen kjent kommando'
Stilsett
Det er benyttet et enkelt stilsett (css):
.tournament{color:blue;cursor:pointer;margin-right:20px}
.description{margin:20px}
.country{color:blue}
.country_id{color:green}
.country_list{color:green;font-size:14px;margin:20px}
.match_date,.match_team,.match_score{font-size:13px}
.match_date{color:gray;padding-left:10px;padding-right:20px}
.match_team{color:black;padding-left:10px}
.match_score{color:red;padding-left:5px;}
.table_team,.table_matchcount,.table_score,.table_point{font-size:13px}
.table_team{padding-right:10px;color:black;font-weight:bold}
.table_matchcount{color:gray}
.table_score{color:gray}
.table_points{padding-left:10px;color:black;font-weight:bold}