Uge 36

Vi skal i denne uge have oprettet brugerkontoer på universitetets server, så vi har mulighed for de kommende gange at bruge databaser og senere cgi-scripts. Serveren kan findes på følgende adresse: www.student.hum.au.dk. Vær opmærksomme på at dette link kun virker fra computere der er tilknyttet humaniora eller via en vpn-client grundet sikkerhedsårsager. I skal nu oprette en ny konto på serveren. Det vil være en fordel hvis I Vælger jeres årskortnummer stud-login eller lignende da jeres login skal være unikt. Den email-adresse I opgiver skal I gerne have adgang til fra universitetet, da der vil blive sendt en mail angående aktivering og dernæst en mail med jeres password. Når I er aktiveret og har fået jeres password kan I logge ind på www.student.hum.au.dk. Når I er logget ind skal I aktivere "Website med PHP 5, Python CGI og Perl CGI" og "Mysql database adgang", husk at skrive webadresser og adgangskoder ned. Hvis I glemmer jeres informationer kan I logge ind på serveren igen for at se dem. Når I er oprettet og har aktiveret de ovenstående nævnte kontoer har I mulig for at tilgå jeres database osv. hvorfra I nu ønsker det.

PHPMYADMIN

Eftersom vi nu har fået lavet et login til MySQL-serveren er det nu muligt at logge ind på denne. Dette gøres via mysql.student.hum.au.dk. Når I er logget ind i phpmyadmin og har valgt jeres database i menuen til ventre, har I mulighed for at se en oversigt over hvilke tabeller i databasen I har oprettet og desuden kan I tilføje og fjerne tabeller og køre generelle sql-komandoer på serveren. Der er dog intet at se endnu da I ingen tabeller har oprettet. For at gøre kan I ind under fanebladet SQL og indsæt nedenstående sql-kode i tekstboksen og trykke på udfør.

DROP TABLE IF EXISTS student
;
CREATE TABLE student(
    ID          INT(8)            NOT NULL    PRIMARY KEY,
    navn        VARCHAR(255)      NOT NULL    DEFAULT "",
    adresse     VARCHAR(255)      NOT NULL    DEFAULT ""
)
TYPE = MYISAM
;

DROP TABLE IF EXISTS databaseadgang
;
CREATE TABLE databaseadgang(
    login       VARCHAR(255)      NOT NULL    PRIMARY KEY,
    pass        VARCHAR(255)      NOT NULL    DEFAULT "",
    student     INT(8)            NOT NULL    DEFAULT 0
)
TYPE = MYISAM
;

Tilykke!, I skulle nu gerne have oprettet jeres første to tabeller i databasen. Prøv at indsætte nogen af de forskellige kommandoer der står her nedenstående og se hvad der sker. Vi kommer meget mere ind på hvad disse kommandoer betyder senere i kurset så dette er kun lige så I får en fornemmelse for hvordan man arbejder med phpmyadmin.

INSERT INTO student VALUES (20031163, "Peter Vahlstrup", "J. La. Cours Gade");

INSERT INTO databaseadgang VALUES ("peter", "hemlig", 20031163);

SELECT * FROM databaseadgang WHERE student = 20031163;

SELECT student.* FROM student, databaseadgang WHERE
student.ID = databaseadgang.student AND databaseadgang.login = "peter";

Uge 37

Vi skal nu til at modulere databaser. Vi vil på øvelsestimen først modulere et ER-diagram for en database fælles på tavlen hvorefter i selv i grupperne skal gå igang med at lave det ER-diagram som i skal aflevere. Hvis I ikke vælger at arbejde med eksemplet med togbiletten og reservationen skal I, i jeres eksempel, mindst have 4 stærke entitetsklasser. I kan med fordel bruge Microsoft Visio eller et andet lignende program til at sætte jeres diagrammer op i. Hvis I vil benytte et tekstbehandlingsprogram vil jeg foreslå at I bruger OpenOffice i stedet for Word da det er noget nemmere at tegne i OpenOffice. Husk at benytte jer af de tre normaliseringsregler når I skal modulere jeres entitetsklasser.

Uge 38

Vi skal i denne uge til at kigge på hvordan man rent praktisk opretter og arbejder med databaser. For at få et ordentligt indblik i hvordan man opretter tabeller i en database, indsætter, opdaterer, sletter og udtrækker data fra disse, vil der i denne uge være en række praktiske øvelser relateret til dette emne. Når I har løst disse opgaver skulle i gerne have et basalt indblik i hvad det vil sige at arbejde med en database og samtidigt have lavet denne uges aflevering. Jeg har skrevet en lille tutorial der dækker de ting vedrørende databaser som ikke er beskrevet i den udleverede litteratur.

  • Undersøg hvad de forskellige data-typer der findes i en database står for, altså f.eks. VARCHAR(255). Overvej derefter hvilke data-typer jeres attributter i databasen skal have. Et godt sted at finde dokumentation for dette vil være mysql.com.
  • Opret en eller flere af jeres tabeller i databasen.
  • Indsæt noget data i jeres tabeller.
  • Udtræk data fra en tabel knyttet til en unik nøgle, I skulle altså gerne kun få ét resultat.
  • Udtræk data fra en tabel hvor i har mindst to argumenter for hvilke betingelser der skal overholdes. F.eks. "vælg fra Person hvor navn er lig Poul og addresse er lig Bynkevej".
  • Opdatér en eksisterende række i en tabel og ændrer en eller flere attributter.
  • Slet en række i en tabel.
  • Foretag en JOIN-SELECT. (valgfri)

Uge 39

Vi skal nu til at kigge på programmeringssproget Python. Flere af jer har spurgt hvorfor valget er faldet på Python og ikke Java, C# osv. Nedenstående opgave skulle gerne give svar på dette spørgsmål. Hvis I stadigt ikke er overbeviste findes der under links en uddybende artikel om dette emne. Når i færdige med denne opgave gennemgår vi i fællesskab hvilke dele denne uges afleveringsopgave består af - med andre ord kigger vi på opgaven ud fra del og hersk princippet. Herefter skulle der gerne være tid til at I kan begynde på at løse selve opgaven.

Hvorfor skal vi kode python?

Kig på de tre nedenstående kodeeksempler og vælg det I synes der ser mest forståeligt ud. Prøv dernæst sammen med jeres sidemand at diskutere hvad det er der sker. Dette er ikke en test i hvor gode I er til at programmere, da I jo ikke har lært noget endnu, men prøv alligevel og se om I kan finde hoved og hale i hvad der foregår.

file = open("test.txt", "r")
for line in file.readlines():
    print line
file.close()
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main () {
    string line;
    ifstream myfile ("example.txt");
    if (myfile.is_open()){
        while (! myfile.eof() ){
            getline (myfile,line);
            cout << line << endl;
        }
        myfile.close();
    }
    else cout << "Unable to open file";
    return 0;
}
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

class FileRead {

    public static void main(String[] args) {

        FileRead fileReader = new FileRead();
        fileReader.readMyFile();
    }

    public void readMyFile() {

        String input = "";

        try {

            FileReader fr = new FileReader("test.txt");
            BufferedReader br = new BufferedReader(fr);

            while ((input = br.readLine()) != null) {
                System.out.println(input);
            }

            br.close();
            fr.close();

        } catch (IOException e) {
            System.out.println("Uh oh, got an IOException error!");
            e.printStackTrace();
        }
    }
}
 

Uge 40

Vi skal i denne uge udvide sidste uges opgave så vi også rent faktisk kan tjekke om det personnummer der er blevet indtastet er et rigtigt personnummer. Da vores program nu vil blive af et noget større omfang vil det være oplagt at skabe en bedre struktur i koden så den bliver nemmere at læse og samtidigt også kan genbruges - dette kan gøres via funktioner. Nedenfor kan ses et eksempel på et program med og uden funktioner. Begge programmer indlæser en tekststreng, fjerner alle karakterer der ikke er ord, opdeler ordene efter længde og udskriver tilsidst ordene pænt i en tabel efter længde.

# -*- coding: ISO-8859-1 -*-
import sys, os

#Non words
nonWords = ["\n", ",", ".", "\t", "!", "?", '"', "\r", "'", "(", ")", ";", "_", \
               "-", "--", "[", "]", "{", "}" "´", "`", "+", "#", "%", "&", ":", \
               "*"]

file = open("words.txt")
string = ""
for a in file.readlines():
    string += a

for a in nonWords:
    string = string.replace(a, " ")

list = string.split(" ")
list.sort()
dic = {}

for a in list:
    if a != "":
        if not dic.__contains__(a):
            dic[a] = 1
        else:
            temp = dic.get(a)
            temp = temp+1
            dic[a] = temp

values = dic.values()
values.sort()
values.reverse()
top = "\tword/count\t"
count = 0

for a in range(1, values[0]+1):
    if count != a:
        top+="|\t"+str(a)+"\t"
        count = a

print top 
print 265*"-"

keys = dic.keys()
keys.sort()
for a in keys:
    numberOfTabs = 3 - (len(a)/8)
    print a+"\t"*numberOfTabs+"|" + "\t"*((dic.get(a)*2)-1)+"X"

Ovestående kode-eksempel kører ud i en lang smørre og kan nemt komme til at virke uoverskueligt for folk der ikke ved hvad programmet skal foretage sig. det er desuden heller ikke muligt at benytte programmet i forbindelse med andre programmer uden at skulle til at kopiere selve koden over i det nye program.

# -*- coding: ISO-8859-1 -*-
import sys, os

#Non words
nonWords = ["\n", ",", ".", "\t", "!", "?", '"', "\r", "'", "(", ")", ";", "_", \
               "-", "--", "[", "]", "{", "}" "´", "`", "+", "#", "%", "&", ":", \
               "*"]

#returns number of tabs to put after the word assuming a max length of 24
def numberOfTabs(string):
    div = len(string)/8
    return 3 - div

def formatForPrint(dic):
    """
    Formats the the given dictionary into a string ready for pretty print
    Returns a formatted string
    "
""
    string = ""
    values = dic.values()
    values.sort()
    values.reverse()
    string += "\tword/count\t"
    count = 0
    for a in range(1, values[0]+1):
        if count != a:
            string+="|\t"+str(a)+"\t"
            count = a
    string += "\n" 
    string += 265*"-" + "\n"
    keys = dic.keys()
    keys.sort()
    for a in keys:
        string += a+"\t"*numberOfTabs(a)+"|" + "\t"*((dic.get(a)*2)-1)+"X\n"
    return string

def countWords(string):
    """
    Counts the words in the given string and assigns them to a dictionary where key => 'word' and value => 'count'.
    Returns a dictionary containing the counted words
    "
""
    list = string.split(" ")
    list.sort()
    dic = {}
    for a in list:
        if a != "":
            if not dic.__contains__(a):
                dic[a] = 1
            else:
                temp = dic.get(a)
                temp = temp+1
                dic[a] = temp
    return dic

def removeNonWords(string):
    """
    Strips the given string of all non-words.
    "
""
    for a in nonWords:
        string = string.replace(a, " ")
    return string

def readFile(file):
    """
    Reads the given file into a string.
    Returns a string
    "
""
    file = open(file)
    string = ""
    for a in file.readlines():
        string += a
    return string

if __name__ == '__main__':
    string = readFile("words.txt")
    words = removeNonWords(string)
    dic = countWords(words)
    print formatForPrint(dic)

I dette eksempel har vi nu benyttet os af funktioner, man kan sige at vi har funktionsopdelt vores problemdomæne. Som det kan ses har vi benyttet os af beskrivelsen af hvad programmet skal kunne til, at oprette en række funktioner der hver især tager sig af det givne problemområde. Der er en funktion der tager sig af at indlæse selve filen, en funktion der fjerner alle karakterer der ikke skal betragtes som ord, en funktion der optæller ordene og til sidst en funktion der sørger for at formatere vores ord så de kan blive udskrevet pænt i en tabel. Ved at opdele vores program i funktioner bliver det noget mere overskueligt da hver funktion kun tager sig af et specifikt problemdomæne. Dertil kommer at vi også har navngivet funktioner med et sigende navn, som er beskrivende for hvad funktionen gør. Ud over dette er det nu også muligt for andre at benytte sig af vores program ved at importere python-filen og kalde de forskellige funktioner. Desuden er det også muligt kun at benytte dele af programmet hvis man f.eks. kun ønsker at få strippet en tekst for ikke-karakterer men ikke ønsker optællingen og formateringen.

Uge 41

Selvom der i denne uge er efterårsferie vil der dog stadigt blive afholdt terminalrumstimer onsdag fra 12.15 - 15.00. Det vil her være muligt at få hjælp til opgave 5 og 6. Da disse opgaver omhandler html vil jeg opfordre jer til at kigge på nogle af de links jeg har postet i forhold til html.

Uge 42

Vi fortsætter i denne uge med at løse opgave 5 og 6. Husk at i skal vedlægge jeres database.py fil så Peter kan se at jeres programmer virker.

Uge 43

I skulle nu allesammen gerne have kendskab til modulet database og ligeledes hvordan man overfladisk bruger det. Denne uges opgave går ud på at foretage en række kald til jeres database via database-modulet. De fire første opgaver kan løses uden at skrive noget sql, hvorimod at de fire sidste kun kan løses ved at I selv skriver en sql-forespørgsel og sender denne til databasen. For at kunne løse opgaven skal I først og fremmest have oprettet en række tabeller i databasen ud fra det ER-diagram der er vedlagt opgaven. Husk at skrive jeres kode til oprettelsen af tabellerne ned i et tekstdokument så I har det senere brug og hvis til der skulle opstå fejl når i prøver at oprette tabellerne. Det næste punkt I skal løse er at tilføje en række data til tabellerne. Prøv at gøre dette både igennem phpmyadmin og via database-modulet. Nå i føler i har styr på dette og det forekommer som en kedelig og langsommelig proces kan i benytte jer af nedenstående python program til at tilføje resten af det data i gerne vil have i databasen. Når alt dette er gjort kan i begynde at løse den egentlige ugeopgave.

# -*- coding: utf-8 -*-
import database
class DBEntryCreator:
   
    def createEntryes(self, file, tableName):
       
        firstRun = True
        entity = []
       
        theFile = open(file, "r")
       
        for a in theFile.readlines():
            a = a.replace(" ", "")
            a = a.replace("\n", "")
            if firstRun:
                firstRun = False
            else:
                entity.append(a.split("\t"))
        theFile.close()
           
        for a in entity:
            for b in range(len(a)-1, -1 , -1):
               
                if a[b] == "":
                    del a[b]
       
        for a in entity:
            print a
            database.insertRecord(tableName, a)
       
if __name__ == "__main__":
    creator = DBEntryCreator()
    creator.createEntryes("db/child.txt", "child")
    creator.createEntryes("db/person.txt", "person")
    creator.createEntryes("db/city.txt", "city")
    creator.createEntryes("db/ciblings.txt", "ciblings")   
           
   

Ovenstående program virker således at programmet kan indlæse tekstfiler bestående af data der skal i databasen og sørge for at denne data bliver indsat i databasen. Måden det bruges på er ved at give metoden "createEntryes" et argument der angiver hvor datafilen ligger og et argument for hvilke tabel dataen skal sætten ind i. Datafilen skal være bygget op således at den første linje består af beskrivelser for hver attribut i tabellen og de resterende linjer består af selve den data der skal i databsen. Hver elementbeskrivelse som data skal være adskilt af et tabulatorskift. Et eksempel er givet nedenstående. Husk at lægge jeres eget database-modul i samme folder som programmet ellers virker det ikke.

postalcode  city
8000        Aarhus C
7000        Atlantis
7200        Struer
3200        Maribo
8200        Holme

Uge 44

Som I ved er der i denne uge lidt forvirring omkring hvilken opgave der skal løses. Indtil videre holder vi os til øvelse 8. Første del af opgaven tager vi fælles på holdet, for at få en fælles praktisk forståelse for hvad rekursiv programmering betyder og den sidste del af opgaven bliver så (indtil videre) jeres egentlige aflevering.

Uge 45

Der er i denne uge ikke nogen egentlig aflevering hvilket dog ikke betyder at vi ikke skal lave noget. Vi bruge denne øvelsesgang og terminalrumstimerne til at repetere hvad vi har lært indtil nu. For at det ikke bare bliver en kedelig gang tavlegennemgang skal I hver især have fundet på et lille problem som i gerne vil løse ved hjælp af python. Dette kunne f.eks. være et program der kan indlæse en fil og søge efter forekomster af en række ord. Et program der kan gennemsøge et html-dokument for links. Et program der kan holde styr på jerers CD'er og gemme oplysningerne til en fil eller måske bare et program der kan agere lommeregner. Valget er helt op til jer. I kan også hente inspiration i nogle af de tidligere ugesedler såsom uge 40 og uge 43. Pointen med at lave repetation på denne måde er at I selv bliver motiveret til at kode noget ud fra jeres ønsker i stedet for at det altid er en på forhånd stillet opgave der skal løses. Det programmering I har lært indtil videre er mere en rigeligt i forhold til at løse en lang række opgaver, så det handler egentligt bare om at bryde opgaven ned i små nok bider til at den enkelte delmængde føles overskuelig at løse og så selvfølgelig at huske hvad det er i har lært. Så efter citat at Anders Bach Nielsen: "happy hacking!".