<?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" xml:lang="fi" >

<head>
    <title>Harjoituspäiväkirja</title>
    <link href="hpk.css" rel="StyleSheet" type="text/css" />
</head>

<body>
<%
import cgitb

##############################
# Luokka valintalaatikoille  #
##############################
   
class valintaLaatikot:
    def __init__(self, nimi,taul):
        self.nimi = nimi
        self.taul = taul
        self.error = ""

    def __str__(self):
        """ Tekee merkkijonon joka on nimi niminen fieldset ja taul taulukosta tehdyt inputit"""
        str = ""
        i = len(self.taul)
        if i != 0:
            str += '<fieldset>\n<legend>%s</legend><br/>\n'%self.nimi
            if self.error != "":
                str += '<div class="virhe">%s</div>\n' % self.error
            valitut = form.getlist(self.nimi)   
            for key in self.taul:
                if sanaListassa(key,valitut):
                    str += '<label>%s<input type="checkbox" name="%s" value="%s" checked="checked"/></label><br/><br/>\n'% (key,self.nimi,key)
                else:
                    str += '<label>%s<input type="checkbox" name="%s" value="%s"/></label><br/><br/>\n'% (key,self.nimi,key)
            str += "</fieldset>\n"
            return str
        else:
            return str

    def virhe(self,error):
        """asettaa valintalaatikolle virheen"""
        self.error = error

########################################
# Aikaväli luokka pyörittelemään aikaa #
########################################

class ajanJakso:
    def __init__(self, alku ,loppu ):
        self.alkupvm = 0
        self.alkukk = 0
        self.alkuvuosi = 0
        self.loppupvm = 0
        self.loppukk = 0
        self.loppuvuosi = 0       
        self.alku = alku
        self.loppu = loppu        
        self.error = ""
        # jos on lomakkeesta saatu aika käsitellään ne
        if alku:
            self.asetaalkupvm(alku)   
        if loppu:
            self.asetaloppupvm(loppu)    


    def __str__(self):
        """ Ajankohta fieldset merkkijonona"""
        str = '<fieldset><legend>Ajankohta</legend><br/>\n'
        if self.error != "":
            str += '<div class="virhe">%s</div>\n' % self.error 
        str += '<label>Aikaväli\n'
        if self.alkupvm != 0 :
            str += '<input type="text" name="alkamispvm" value="%s"/>'%self.tostr("alku")
        else:
            str += '<input type="text" name="alkamispvm" value="1.1.2010"/>'
        if self.loppupvm != 0:
            str += '<input type="text" name="loppumispvm" value="%s"/>' %self.tostr("loppu")
        else:
            str += '<input type="text" name="loppumispvm" value="5.1.2010"/>'
        str += """</label><br/><br/>\n</fieldset>"""
        return str


    def tarkistaAjanjakso(self):
        """ tarkistaa onko ajanjakso kelvollinen """ 
        if self.error == "":              
            if self.alkuvuosi <= self.loppuvuosi and self.loppuvuosi != 0 and self.alkuvuosi != 0:
                if self.alkukk == self.loppukk and self.loppukk <= 12 and self.loppukk > 0 and self.alkukk > 0:
                    if self.alkupvm <= self.loppupvm and self.loppupvm <= 31 and self.loppupvm > 0 and self.alkupvm > 0:
                        return True
                    else:
                        self.virhe("Virheellinen ajanjakso")                  
                        return False
                elif self.alkukk < self.loppukk and self.loppukk <= 12 and self.loppukk > 0 and self.alkukk > 0:
                    return True
            self.virhe("Virheellinen ajanjakso") 
            return False
        return False

    def asetaalkupvm(self,alku):
        """asettaa oliolle alku ajan"""
        a = self.toInt(alku.split("."))
        if len(a) < 3 or len(a) >3:
            self.virhe("Päivämäärä on virheellisessä muodossa")
        else:    
            self.alkupvm = a[0]
            self.alkukk = a[1]
            self.alkuvuosi = a[2]

    def asetaloppupvm(self,loppu):
        """asettaa oliolle loppuajan"""
        a = self.toInt(loppu.split("."))
        if len(a) < 3:
            self.virhe("Päivämäärä on virheellisessä muodossa")
        else:
            self.loppupvm = a[0]
            self.loppukk = a[1]
            self.loppuvuosi = a[2]

    def virhe(self,error):
        self.error = error

    def tostr(self,tila):
        """ olion aika merkkijonoksi """
        if tila == "alku":
            return '%s.%s.%s' %(str(self.alkupvm),str(self.alkukk),str(self.alkuvuosi))
        else:
            return '%s.%s.%s' %(str(self.loppupvm),str(self.loppukk),str(self.loppuvuosi)) 

    def getpvmlistana(self):
        """ päivätmäärät ajanjaksolta listassa"""
        lista = []
        req.write(self.error)
        while self.tarkistaAjanjakso():
            lista.append(self.tostr("alku"))
            self.lisaapaiva()
        self.reset()
        return lista

    def reset(self):
        """ palauttaa oliolle lomakkeella lähetetyt arvot"""
        self.asetaalkupvm(self.alku)   
        self.asetaloppupvm(self.loppu)   
        self.error = ""

    def lisaapaiva(self):
        """ kasvattaa olion alkupäivämäärää yhdellä """
        if self.alkupvm < 31:
            self.alkupvm = self.alkupvm +1
        else:
         self.alkupvm = 1
         self.lisaakk()

    def lisaakk(self):
        """ kasvattaa olion alku kuukautta yhdellä"""
        if self.alkukk < 12:
            self.alkukk = self.alkukk +1
        else:
         self.alkukk = 1
         self.lisaavuosi()

    def lisaavuosi(self):
        """ kasvattaa olion alkuvuotta yhdellä"""
        self.alkuvuosi += 1

    def toInt(self,lista):
        """ muuttaa taulukon alkiot inteiksi"""
        a = list(lista) # kopio 
        for i in range(len(lista)):
            try:
                a[i] = int(lista[i])
            except Exception:
                a[i] = lista[i]
                self.virhe("Kirjaimia ei saa olla ajanjaksossa")
        return a 

###############################################
# Luokka inputeille jotta ne saadaan eläviksi #
###############################################

class input:
    def __init__(self, name="kentta", value="", error="",size="5"):
        self.name = name
        self.value = value
        self.size = size
        self.error = error
    def __str__(self):
        """ input olio merkkijonoksi"""
        str =""        
        if self.error != "":
            str += '<input type="text" value="%s" name="%s" size="%s" class="virhe"/>' % (self.value, self.name, self.size )
            str += "<br/>\n%s" %self.error
        else:
            str = '<input type="text" value="%s" name="%s" size="%s"/>' % (self.value, self.name, self.size )
        return str
	def aseta(self, str):
		if not str:
			self.error = "Syötä arvo"
			self.value = ""
		else:
			self.value = str


#####################
# Globaalit Metodit #
#####################

def sanaListassa(sana,lista):
    """ tarkistaa onko annettu sana annetussa listassa"""
    if lista == 0 :
        return False
    for value in lista:
        if sana == value:
            return True
    return False

def tarkistaOnkoValittu(name):
    """ tarkistaa onko lomakkeella syötetty kyseinen arvo"""  
    str = form.getfirst(name)
    if str:
        return True
    else:
        return False

def onkovirhe(hlo,paiva):
    """ takristaa onko virheet taulukossa kyseistä henkilöä ja päivämäärää"""
    for name,virheilmoitus in virheet:
        a = parse(name)
        if len(a) == 2 and a[0] == hlo and a[1] == paiva:
            return True
    return False

def getvirhe(str):
    """ Hakee virheet taulukosta virheilmoituksne annetulle nimelle""" 
    for name,virheilmoitus in virheet:
        if name == str:
            return virheilmoitus
    return ""

def tulostataulukko(hlo,aika):
    """ Tulostaa syöttö taulukot annetuille henlkilöille ja päiville vaiheeseen 2 """
    lajit = form.getlist("Lajit")
    pvm = aika.getpvmlistana()
    str=""
    if tarkistahenkilo(hlo):
        str += '<table id="virheellinen">\n<caption>%s</caption>\n'%hlo
    else:
        str += '<table>\n<caption>%s</caption>\n'%hlo
    str += "<tr><th>Päivä</th>"
    for laji in lajit:
        str += "<th>%s</th>" %(laji)
    str += "</tr>"    
    for paiva in pvm:
        if onkovirhe(hlo,paiva):
            str+= '<tr class="virhe">\n'            
        else:
            str += "<tr>\n"
        for i in range(len(lajit)+1):
            if i == 0:
                str += "<th>%s</th>" %(aika.tostr("alku"))
            else:
                nimi = ""+hlo+"-"+aika.tostr("alku")+"-"+lajit[i-1]
                if form.getfirst(nimi):
                    virhe = tarkistaonkovirheellinen(nimi)                    
                    if virhe != "":
                        str += '<td>%s</td>'% input(nimi,form.getfirst(nimi),virhe)
                    else:
                        str += '<td>%s</td>'% input(nimi,form.getfirst(nimi))
                else:
                    str += '<td>%s</td>'% input(nimi)
        if onkovirhe(hlo,paiva):
            str+= "<td>%s</td></tr>\n"%getvirhe(hlo+"-"+paiva)
        aika.lisaapaiva()
    str += "</tr>"    
    if tarkistahenkilo(hlo):
        str+='<tr><td colspan="%s">%s</td></tr>\n'%(len(lajit)+1,getvirhe(hlo))    
    str += "</table>\n"
    aika.reset()
    return str

def tarkistaonkovirheellinen(nimi):
    """tarkistaa onko kyseinen nimi virheet taulukossa"""
    for name,virhe in virheet:
        if name == nimi:
            return virhe
    return ""

def aikahidden(aika):
    """ Palauttaa piilotetut inputit ajanjaksolle, jotta se voidaan siirtää lomakkeessa eteenpäin"""
    str = '<input type="hidden" name="alkamispvm" value="%s"/>\n'%aika.tostr("alku")
    str += '<input type="hidden" name="loppumispvm" value="%s"/>\n'%aika.tostr("loppu")
    return str

def hiddeninput(name,list):
    """ Palauttaa piilotetun inputin annetulle nimellä kaikille taulukon alkioille """
    str = ""    
    for i in range(len(list)):
        str += '<input type="hidden" name="%s" value="%s"/>\n'%(name,list[i])
    return str

def tarkista(str):
    """ tarkistaa onko annettu arvo kelvollinen""" 
    if str == "":
        return ""
    try:
        i = int(str)
    except Exception:
        return "Älä syötä tekstiä"
    if i > 360 :
        return "liian suuri luku"
    if i < 0:
        return "Syötä positiivinen luku"     
    return ""


def tulostayhteenveto(aika,kentat):
    """ tulostaa yhteenvedon annetusta ajanjaksosta ja kentistä""" 
    str = '<table>\n<caption>Yhteenveto</caption>\n'
    str += '<tr><th>Ajanjakso</th><td>%s - %s</td></tr>\n' %(aika.tostr("alku"),aika.tostr("loppu"))
    str += '<tr><th>Ajanjakson pituus</th><td>%s päivää</td></tr>\n' %len(aika.getpvmlistana())
    a = 0   
    for name,value in kentat:
        try:
            a += int(value)
        except Exception:
            a += 0
    str += '<tr><th>Kokonaisharjoitusmäärä</th><td>%s</td></tr>\n' %tuntiminform(a)
    str += '<tr><th>Keskimäärä / päivä</th><td>%s</td></tr>\n' %tuntiminform(pyorista(a,len(aika.getpvmlistana())))
    return str

def henkilotlista(kentat):
    """ palauttaan listan henkilöistä jotka on syötetty lomakkeeseen""" 
    lista =[]
    for nimi in range(len(henkilot)):
        for name,value in kentat:
            a = parse(name)
            if henkilot[nimi] == a[0]:
                lista.append(henkilot[nimi])
                break
    return lista

def lajitlista(kentat):
    """ Palauttaa listan lajeista jotka on syötetty lomakkeeseen"""     
    lista =[]
    for nimi in range(len(lajit)):
        for name,value in kentat:
            a = parse(name)
            if len(a) < 2:
                break
            if lajit[nimi] == a[2]:
                lista.append(lajit[nimi])
                break
    return lista

def tulostahenkilot(aika,kentat,hlot):
    """ tulostaa annetulle ajanjaksolle henkilöiden kokonais harjoitusajat""" 
    str = '<table>\n<caption>Henkilöt</caption>\n'
    str += "<tr><th></th>"
    for a in range(len(hlot)):
        str += "<td>%s</td>"%hlot[a]
    str += "</tr>\n<tr><th>Kokonaisharjoitusmäärä</th>"
    for a in range(len(hlot)):
        str += "<td>%s</td>"%tuntiminform(kokonaisaika(hlot[a],kentat))
    str += "</tr>\n<tr><th>Keskimäärä / päivä</th>"
    for a in range(len(hlot)):
        str += "<td>%s</td>"%tuntiminform(pyorista(kokonaisaika(hlot[a],kentat),len(aika.getpvmlistana())))
    str += '</tr></table>'
    return str

def tulostalajit(aika,kentat,lajit):
    """ tulostaa annettulle ajanjaksolle kokonais harjoitusajat per laji""" 
    str = '<table>\n<caption>Lajit</caption>\n'
    str += "<tr><th>Laji</th><th>Kokonaiskesto</th></tr>"
    for a in range(len(lajit)):
        str += "<tr><th>%s</th><td>%s</td></tr>"%(lajit[a],tuntiminform(kokonaisaika(lajit[a],kentat)))
    str += '</table>'
    return str

def tulostalajithenkiloittain(aikaolio,kentat,lajilist,hlot):
    """ tulostaa kokonaisharjoitusajat lajeittain per henkilö""" 
    str = '<table>\n<caption>Lajit henkilöittäin</caption>\n'
    str += "<tr><th>Laji</th>"
    for a in range(len(hlot)):
        str += "<th>%s</th>"%hlot[a]
    for a in range(len(lajilist)): 
        str += "<tr><th>%s</th>"%lajilist[a]
        for i in range(len(hlot)):
            str += "<td>%s</td>"%(tuntiminform(kokonaisaikalajilleperhlo(lajilist[a],kentat,hlot[i])))
        str += '</tr>'
    str += '</table>'
    return str

def tulostapaivat(aika,kentat):
    """ tulostaa päivien kokonaisharjoitusajat""" 
    str = '<table>\n<caption>Päivät</caption>\n'
    str += "<tr><th>Päivä</th><th>Kokonaiskesto</th></tr>"
    for a in range(len(aika.getpvmlistana())):
        str += "<tr><th>%s</th><td>%s</td></tr>"%(aika.tostr("alku"),tuntiminform(kokonaisaika(aika.tostr("alku"),kentat)))
        aika.lisaapaiva()
    aika.reset()
    str += '</table>'
    return str


def tulostapaivathenkiloittain(aika,kentat,hlot):
    """ tulostaa kokonaisharjoitus ajat henkilöittäin per päivä""" 
    str = '<table>\n<caption>Päivät Henkilöittäin</caption>\n'
    str += "<tr><th>Päivä</th>"
    for a in range(len(hlot)):
        str += "<th>%s</th>"%hlot[a] 
    str += '</tr>\n'
    for a in range(len(aika.getpvmlistana())):
        str += "<tr><th>%s</th>" %aika.tostr("alku")   
        for hlo in hlot:
            str += "<td>%s</td>"%tuntiminform(kokonaisaikapaivalleperhlo(aika.tostr("alku"),kentat,hlo))
        aika.lisaapaiva()
        str += '</tr>\n'
    aika.reset()
    str += '</table>'
    return str

def kokonaisaika(type,kentat):
    """ palauttaa kokonaisajan annetulle nimelle lomakkeeseen syötetyistä arvoista""" 
    total = 0
    for name,value in kentat:
        a = parse(name)
        for i in range(len(a)):
            if a[i] == type:
                try:    
                    total += int(value)
                except Exception:
                    total += 0
    return total

def kokonaisaikalajilleperhlo(laji,kentat,hlo):
    """ laskee kokonaisajan annetulle lajille annetun henkilon mukaan""" 
    total = 0
    for name,value in kentat:
        a = parse(name)
        if a[0] == hlo and a[2] == laji:
            try:    
                total += int(value)
            except Exception:
                total += 0
    return total

def kokonaisaikapaivalleperhlo(aika,kentat,hlo):
    """ laskee kokonaisajan kyseiselle päivälle henkilön mukaan""" 
    total = 0
    for name,value in kentat:
        a = parse(name)
        if len(a) < 2 :
            break
        if a[1] == aika and a[0] == hlo:
            try:    
                total += int(value)
            except Exception:
                total += 0
    return total

def parse(str):
    """ pilkkoo annetun merkkijonon palasiin välimerkkinä "-" """ 
    list = str.split("-")
    return list

def tuntiminform(i):
    """ muuttaa annetut minuutit merkkijonoksi jossa on tunnit ja minuutit""" 
    if i == 0:
        return "0 min"
    tunnit = int(i/60)
    minuutit = i-(tunnit*60)
    if tunnit == 0:
        return "%d min" %minuutit    
    return "%d h %d min" %(tunnit,minuutit)

def tarkistalajienpaivasumma(aika,valituthenkilot,valitutlajit):
    """ tarkistaa lajien kokonaisharjoitusajan per päivä ja lisää virheen jos summa on liian iso""" 
    while aika.tarkistaAjanjakso():
        for hlo in valituthenkilot:
            sum = 0            
            for laji in valitutlajit:
               try:
                    i = int(form.get(hlo+"-"+aika.tostr("alku")+"-"+laji,0))
               except Exception:
                    i = 0
               sum += i
            if sum > 600:
                virheet.append([hlo+"-"+aika.tostr("alku"),"Päivän harjoitusten yhteiskesto on liian suuri"])
        aika.lisaapaiva()
    aika.reset()

def tarkistahenkilonsumma(aika,valituthenkilot,valitutlajit):
    """ laskee ajanjaksolle kaikkien lajien kokonais summan ja tarkistaa onko se liian suuri. lisää virheen jos on""" 
    for hlo in valituthenkilot:
        total = 0
        paivia = 0
        while aika.tarkistaAjanjakso():
            paivia += 1
            sum = 0            
            for laji in valitutlajit:
               try:
                    i = int(form.get(hlo+"-"+aika.tostr("alku")+"-"+laji,0))
               except Exception:
                    i = 0
               sum += i
            total += sum
            aika.lisaapaiva()
        aika.reset()
        if total > paivia*480:
            virheet.append([hlo,"Ajanjakson kokonaisharjoitusmäärä on liian suuri!"])
def pyorista(a,b):
    """ pyöristaa lähimpään kokonaislukuun"""
    c = float(a)/float(b)
    i = round(c)
    return i

def tarkistahenkilo(hlo):
    """ tarkistaa onko kyseiselle henkilölle virhe virheet taulukossa""" 
    for name,virheilmoitus in virheet:
        if name == hlo:
            return True
    return False

def vaihe1(lajitOlio,aikaOlio,HenkilotOlio):
    """ Tulostetaan harjoituspäiväkirjan ensimmäinen vaihe"""
    req.write ("""<h1>Harjoituspäiväkirja</h1>
    <div>Valitse mitä lajeja, mille päiville ja mille henkilöille haluat syöttää:</div>
    <form action="" method="post"><div>
    """ )
    req.write(str(lajitOlio)) 
    req.write(str(aikaOlio))
    req.write(str(HenkilotOlio))
    req.write('<input type="submit" value="Syötä harjoitukset" name="submit1"/></div>\n</form>')
 
def vaihe2(aikaOlio,kentat,valitutlajit,valituthenkilot):
    """ Tulostetaan harjoituspäiväkirjan toinen vaihe"""
    req.write ("""<h1>Harjoitusten syöttäminen</h1>
    <div>Syötä harjoitusten kesto minuutteina</div><br/>
    <form action="" method="post"><div>
    """ )
    for hlo in valituthenkilot:
        req.write(tulostataulukko(hlo,aikaOlio))
    # passataan aikaolio eteenpäin
    req.write(aikahidden(aikaOlio))
    req.write(hiddeninput("Henkilöt",valituthenkilot))
    req.write(hiddeninput("Lajit",valitutlajit))    
    req.write('<input type="submit" value="Tee yhteenveto" name="submit2" />\n</div></form>')

def vaihe3(aikaolio, kentat):
    """ Tulostetaan harjoituspäiväkirjan viimeinen vaihe"""
    req.write ("<h1>Harjoitusanalyysi</h1>")
    hlot = henkilotlista(kentat)
    lajilist = lajitlista(kentat)
    req.write (tulostayhteenveto(aikaolio,kentat))
    req.write (tulostahenkilot(aikaolio,kentat,hlot))
    req.write (tulostalajit(aikaolio,kentat,lajilist))
    req.write (tulostalajithenkiloittain(aikaolio,kentat,lajilist,hlot))
    req.write (tulostapaivat(aika,kentat))
    req.write (tulostapaivathenkiloittain(aika,kentat,hlot))



##############################
## itse ohjelma alkaa tästä ##
##############################

# kopataan lomakkeen tiedot
form = req.form

# voitaisiin vaikka lukea jostakin nämä. ei vaikuta ohjelman toimintaan jos lajeja tai henkilöitä lisätään
lajit = ["Juoksu","Hiihto","Jalkapallo","Suunistus","Uinti"]
henkilot = ["Tommi","Antti","Sami","Ville","Jussi"]
# listoja ja olioita joita tarvitaan
virheet = []
lajitlaatikko = valintaLaatikot("Lajit",lajit)
henkilotlaatikko = valintaLaatikot("Henkilöt",henkilot)
aika = ajanJakso(form.getfirst("alkamispvm"),form.getfirst("loppumispvm"))
valituthenkilot = form.getlist("Henkilöt")
valitutlajit = form.getlist("Lajit")
    
kentat = form.items();

if form.getfirst("submit2"):
    # tarkistetaan onko syöteyissä arvoissa virheitä
    for name,value in kentat:
        # ei huomioida päivämääriä eikä lajeja eikä henkilöitä
        a = parse(name)
        if len(a) > 1:        
            virhe = tarkista(value)
            if virhe:
                virheet.append([name,virhe])
    #tarkistaa onko päivälle annettu liian monta minuuuttia
    tarkistalajienpaivasumma(aika,valituthenkilot,valitutlajit)
    tarkistahenkilonsumma(aika,valituthenkilot,valitutlajit)    
    # jos on virheitä niin vaihe 2 uusiksi ja ilmoitetaan virheistä
    if len(virheet) != 0:
        vaihe2(aika,kentat,valitutlajit,valituthenkilot)
    else:
        vaihe3(aika,kentat)
elif form.getfirst("submit1"):
    # tarkistetaan onko vaaditut tiedot syötetty
    virhe = False
    if not tarkistaOnkoValittu("Lajit"):
        lajitlaatikko.virhe("Valitse ainakin yksi laji")
        virhe = True
    if not tarkistaOnkoValittu("Henkilöt"):
        henkilotlaatikko.virhe("Valitse ainakin yksi henkilö")
        virhe = True
    if not aika.tarkistaAjanjakso():
        virhe = True
    # jos ei palataan vaiheeseen 1
    if virhe:
        vaihe1(lajitlaatikko,aika,henkilotlaatikko)
    # muussa tapauksessa voidaan luoda syöttölomake    
    else:
       vaihe2(aika,kentat,valitutlajit,valituthenkilot)
#alkutilanne
else:
    vaihe1(lajitlaatikko,aika,henkilotlaatikko)

%>
</body>
</html>
