!

Dette materialet blir ikke lenger vedlikeholdt. Du vil finne oppdatert materiale på siden: http://borres.hiof.no/wep/

AJAX
Database
Børre Stenseth
Eksempler >FotballVM

Fotball VM

Hva
Alle resultater fra fotballVM 1930 - 2010

Dataene som er brukt er beskrevet i modulen Noen datasett . Det er bygget en løsning som benytter AJAX for å hente fram deler av en HTML-side. Informasjon om hver turnering og informasjon om resulteter i hver gruppe er slike deler.

Løsningen er prinsippielt slik:

struktur
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}
Referanser

Relevant kode er sitert i teksten.

Se modulen: AJAX

Vedlikehold

B. Stenseth, august 2006

( Velkommen ) Eksempler >FotballVM ( IFA )