Kristoffer Vang Nielsen. Regelbaseret Landbrugsvurderingssystem

Størrelse: px
Starte visningen fra side:

Download "Kristoffer Vang Nielsen. Regelbaseret Landbrugsvurderingssystem"

Transkript

1 Kristoffer Vang Nin Regelbaseret Landbrugsvurderingssystem Master Thesis, Marts 2010

2

3 Regelbaseret Landbrugsvurderingssystem Kristoffer Vang Nin Master Thesis, Marts 2010

4 Regelbaseret Landbrugsvurderingssystem Author(s): Kristoffer Vang Nin Supervisor(s): Associate Professor Hubert Baumeister Department of Informatics and Mathematical Modelling Technical University of Denmark Technical University of Denmark Informatics and Mathematical Modelling Building 321, DK-2800 Kongens Lyngby, Denmark Phone , Fax

5 ABSTRACT In many firms Excel is used for computations and storage of various data. Is there a few calculations and in general a small system, Excel is good for this purpose. Is there a large system, Excel is complex and is no longer suitable as a tool. Real Kredit Danmark uses landbrugsvurderingssystemet to determine the total values for farming. The value is used to assess how much a farmer can borrow, based on what he owns. Landbrugsvurderingssystemet is an example of how Excel is used to make calculations in a large system. Sometimes you have to change the way landbrugsvurderingssystemet provides value base. It may, for example be that a new law requirements or other kinds of requirements that makes value assumptions must be calculated in a new way, or that a farmer would have to meet certain requirements. Until now, there is used a spreadsheet to calculate the value. Instead of creating a new worksheet each time there are new laws or requirements change, it would be appropriate to create a rule-based system, so that a new law will not result in the need to make a new version of the worksheet. There must therefore be made a domain specific language to handle rules as Real Kredit Danmark uses to calculate the values. In addition, a program that can do calculations based on the rules needs to be implemented. 3

6

7 RESUMÉ I mange firmaer vælger man at bruge Excel til beregninger og opbevaring af forskelligt data. Er der tale om få beregninger og i det hele taget et lille system, er Excel godt til formålet. Er der tale om et stort system, bliver Excel komplekst, og er ikke længere egnet som værktøj. I Real Kredit Danmark bruges landbrugsvurderingssystemet til at fastsætte det samlede værdigrundlag for et landbrug. Værdigrundlaget bruges til, at vurdere hvor meget landmanden må låne, ud fra hvad han ejer. Landbrugsvurderingssystemet er et eksempel hvor Excel er brugt til at lave beregninger i et stort system. Nogle gange skal der ændres på måden landbrugsvurderingssystemet fastsætter værdigrundlaget på. Det kan f.eks. være, at der kommer nye lov krav eller andre slags krav der gør, at værdigrundlaget skal beregnes på en ny måde eller at landmanden skal opfylde nogle bestemte krav. Indtil nu er der brugt et regneark til at beregne landbrugsvurderingen. I stedet for at lave et nyt regneark hver gang der kommer nye love eller kravene ændrer sig, vil det være hensigtsmæssigt at lave et regelbaseret system, således at en ny lov ikke vil medføre at der skal laves en ny version af regnearket. Der skal derfor laves et domæne specifikt sprog til at håndtere reglerne som Real Kredit Danmark bruger til at beregne landmandens værdigrundlag. Derudover skal der laves et program der kan lave beregninger på basis af reglerne. 5

8

9 TABLE OF CONTENT Abstract... 3 Resumé Landbrugsvurderingssystemet Beskriv af ark Ulemper ved systemer i Excel Opsummering Analyse og design Regler der er brugt i landbrugsvurderingssystemet Landbrugsvurderingssystemet Opbygning Variabler Klasser Metoder Arrays If-statements For-loop Tildeling af værdier Udregning Lagring af data Parser Klassediagram Opsummering Grammatik EBNF Uddybning af grammatikken Opsummering Implementering Opbygning Parser Variabler Klasser

10 Table of content 4.5 Metoder Arrays If-statement For loop Fortolkning af input Simplificering af udtryk Udregning Klasser Variabler Save Opsummering Test Opsummering Udvidsmuligheder GUI Parameter Opsummering Konklusion References A Unit test B Kildekode C Testsag D CD

11 1 LANDBRUGSVURDERINGSSYSTEMET I dette afsnit vil det blive beskrevet hvad landbrugsvurderingssystemet er, samt hvordan det er bygget op. Derefter vil nogle af ulemperne ved et system implementeret i Excel blive gennemgået. Landbrugsvurderingssystemet (lvs) er et vurderingssystem der bruges af Real Kredit Danmark (RD), til at vurdere hvor meget et landbrug er værd. En vurdering af et landbrug er nødvendig, når der skal lånes penge igennem RD til f.eks. et landbrug, eller andre store bygningsværker, der ikke går ind under almindelige boliger. For at finde ud af, hvor meget der kan lånes i et landbrug, er det nødvendigt at fastsætte værdien af hele landbruget. Da et landbrug kan bestå af flere ejendomme, skal hver enkelt ejendom i landbruget vurderes og værdifastsættes. Ud fra en værdifastsætt af alle ejendomme med dertilhørende jord, bygninger og besætning, kan resultatet fra hver ejendom bruges til at danne et værdigrundlag, hvorfra et lån kan optages. Lvs er sat op ved hjælp af Excel og består af en række ark, til indtastning - og visning af data. Når en landbrugsvurdering skal dannes udfylder kunderådgiveren, i samarbejde med kunden, data omkring landbruget, hvilket ligger til grund for vurderingen. I hvert ark er der nogle indtastnings celler, hvor kunderådgiveren indtaster data, mens andre celler indeholder formler, der udfører beregninger. Til hvert ark er der tilknyttet makroer, der skjuler/viser celler, laver beregninger og indsætter formler i celler ud fra indtastning foretaget af kunderådgiveren. Samtlige ark der hører til landbrugsvurderingssystemet ses her: Forside 1-Forside 1-Jorden 1-Bygninger 1-Maskiner 1-Besætning 2-Forside 2-Jorden 2-Bygninger 2-Maskiner 2-Besætning 3-Forside 9

12 Landbrugsvurderingssystemet 3-Jorden 3-Bygninger 3-Maskiner 3-Besætning 4-Forside 4-Jorden 4-Bygninger 4-Maskiner 4-Besætning 5-Forside 5-Jorden 5-Bygninger 5-Maskiner 5-Besætning Harmoni Summering EffektivitetData Effektivitet Indstillingsark Forbehold MaskinerData BesætningsData Distrikter Postnr BBRKommune Som det ses, er listen med ark lang og uoverskuelig. Skal systemet kunne håndtere flere ejendomme eller endda flere landbrug, vil listen vokse betydeligt. Ikke alle ark er synlige for kunderådgiveren. Et ark kan være skjult, fordi det ikke skal bruges i den aktuelle vurdering, eller fordi det fungerer som hjælpeark med data, der bruges til at hente værdier til felterne i de synlige ark. Et eksempel på et hjælpeark er Postnr arket, der indeholder en kolonne med postnumre, samt en kolonne med dertilhørende byer. Arket bruges til at hente et bynavn udfra det postnummer kunderådgiveren indtaster. På denne måde kan noget data udfyldes automatisk i regnearkene. De ark der altid er synlige i en landbrugsvurdering er Forside, Harmoni, Summering og Indstillingsark. Derudover vil der være en række ark knyttet til hver ejendom i landbruget. Et landbrug består i lvs af minimum en ejendom, mens der kan være op til fem ejendomme. For hver ejendom vil der være tilknyttet arkene X-forside, X-Jorden, X-Bygninger, X- Maskiner og X-Besætning, hvor X vil blive skiftet ud med et tal, svarende til nummeret på ejendommen. Er der en ejendom tilknyttet landbruget, vil følgende ark være synlige: 10

13 Landbrugsvurderingssystemet Forside 1-Forside 1-Jorden 1-Bygninger 1-Maskiner 1-Besætning Harmoni Summering Indstillingsark På forsiden indtastes antallet af ejendomme, hvorefter en makro sørger for at det rigtige antal ark vises. Indholdet på et ark kan ændre sig, efter indtastning fra kunderådgiveren. Der kan f.eks. blive genereret ekstra rækker med data under indtastning i hovedceller. Med hovedceller, menes celler der bruges som input til generering af rækker. Figur 1 - bebos rækker Som et eksempel kan nævnes rækker knyttet til ejendommens bygninger. Som det ses på Figur 1, er der tre ens rækker under antal boliger. Disse rækker genereres efter indtastning af antal boliger. Det er altså ikke forudbestemt, hvor mange rækker der skal være. Den samlede værdi af boliger til bebo udregnes ved at lægge værdien for samtlige boliger sammen. Det vides derfor ikke på forhånd, hvor mange celler der skal bruges til at beregne resultatet, da antallet af boliger ikke er fastlagt. Indholdet på arkene er dermed dynamisk, hvor flere rækker kan tilføjes efter indtastning. Et andet eksempel på at indholdet af et ark er dynamisk, er når kunderådgiveren skal indtaste data omkring ejendommens besætning. Ligesom med boliger, kan der være flere besætninge tilknyttet en ejendom. Til hver besætning udregnes antal dyreenheder ved hjælp af en formel, der sættes ved hjælp af en makro, ud fra typen på besætningen. Dyreenheder er det begreb, der beskriver miljøpåvirkningen fra forskellige dyr. En dyreenhed er den mængde dyr, der producerer 100 kg kvælstof (N) på årsbasis. Antallet af dyreenheder (DE) er derfor blandt andet afhængig af dyrets race og vægt. (1) 11

14 Landbrugsvurderingssystemet 1.1 Beskriv af ark Forsiden er en generel forside for hele vurderingen. Den indeholder oplysninger om kunden der ønsker at optage lån, samt hvem der er den kundeansvarlige. Her indtastes hvor mange ejendomme der indgår i vurderingen. X-Forside er tilknyttet den enkelte ejendom i vurderingen og indeholder oplysninger om ejendommen, arealet hørende til ejendommen samt hvad ejendommen benyttes til. X-Jorden indeholder oplysninger om jord tilhørende ejendommen. Da et jordareal kan være stort, kan der være flere jordtyper tilknyttet en ejendom. Da værdien af jorden er afhængig af jordtypen, skal der her angives hvilke jordarter der er, arealet for jordarterne samt handelsværdien for jorden. X-Bygninger beskriver hvilke bygninger ejendommen består af. En ejendom kan bestå af bygninger til bebo og driftsbygninger. Her angives hvad en bygning bruges til, samt information som størr, opførsår og anvend. Er der projekterede forbedringer til ejendommen, angives dette ligeledes i samme ark. Som vist i Figur 1 er X-Bygninger et dynamisk ark, hvor rækker genereres efter antallet af bygninger på ejendommen. X-Maskiner indeholder en værdiangiv af maskinerne. Værdiangiv af maskiner sker kun ved oprett af YJ-lån (lån til yngre jordbrugere) (2) X-Besætning indeholder antallet af besætningsrækker. Ligesom med bygninger, vides det ikke hvor mange besætningsrækker der findes på en ejendom, men genereres efter hvor stort et antal der indtastes. Hver besætningsrække indeholder besætningstype, race og antal. Værdien for besætningen beregnes ligeledes i dette ark. Harmoniarket indeholder harmoniberegning for alle ejendomme i landbruget. Det meste data i harmoniberegning hentes eller beregnes ved hjælp af indtastet data i de andre ark. Er der sampantsatte ejendomme, indtastes det i dette ark, således at harmonifradrag ved sampantsætning kan beregnes. Ved sampantsat ejendom menes at der tages et stort lån, i flere ejendomme, i stedet for et mindre lån, i hver ejendom. (3) Summering viser en oversigt over værdier af de enkelte ejendomme, samt den samlede værdi for hele landbruget. Data i dette ark, beregnes ud fra indtastninger i de andre ark. Indstillingsark bruges til udarbejd af kreditindstillingen. Data hertil hentes fra de øvrige ark i vurderingen. I alle ark gælder, at der er hvide indtastningsfelter og grå felter, hvis værdi beregnes af systemet, eller er tomme. De grå felter er spærret for indtastning. Udover de normale formler i Excel, bliver der benyttet makroer kodet i visual basic, som køres, når der sker ændringer i et ark. Makroerne bruges blandt andet til at gøre arkene dynamiske, til at oprette formler i de tilhørende celler og til at hente data fra andre ark. 12

15 Landbrugsvurderingssystemet Yderligere information omkring brugen af landbrugsvurderingssystemet, kan læses i brugervejledningen der er vedlagt på cd. 1.2 Ulemper ved systemer i Excel Ulempen ved at bygge et system op i Excel er at der hurtigt kommer begrænsninger, og at vedligehold/udbygning af et system i Excel ikke er lige til. I lvs er det fastsat, at der maksimalt kan være fem ejendomme tilknyttet et landbrug. Der er derfor oprettet ark, svarende til fem ejendomme. Det er ikke noget problem at lave en landbrugsvurdering, så længe der er de gældende regler, og antallet af ejendomme ligger indenfor det systemet er designet til. Men skal der ændres i systemet, så f.eks. seks ejendomme kan tilknyttes et landbrug, skal der laves væsentlige ændringer i systemet. Ikke nok med at der skal laves ekstra ark til den sjette ejendom, der skal også ændres i de andre ark, der viser data for hver ejendom. I harmoni arket, vises der en oversigt over de forskellige ejendomme. Er der én ejendom tilknyttet landbruget, vises kun én ejendom i harmoni arket. Er der flere ejendomme, vises de ligeledes. De genereres altså ikke dynamisk, efter hvor mange ejendomme der findes, men er oprettet på forhånd, så der er plads til fem ejendomme. Skal alle fem ejendomsark ikke bruges, skjules cellerne til disse ark. Udover at designet af arkene skal laves om, hvis der laves ændringer i lvs, er der formler i cellerne, som skal ændres. Bygger en formel f.eks. på noget fra hver ejendom, skal formlen laves om, hvis der skal tilføjes en ejendom mere. Et eksempel på dette er summen af dyreenheder. Den beregnes ud fra antallet af dyreenheder fra hver ejendom. I det nuværende system er det samlede antal dyreenheder summen af dyreenheder fra de fem ejendomme. Er der en ejendom i landbruget, vil dyreenheder for de resterende ejendomme, der ikke bruges, være lig nul, og summen kan derfor stadigvæk beregnes. Tilføjes en ekstra ejendom skal formlen til summen af dyreenheder laves om, til også at beregne summen ud fra dyreenhederne på den nye ejendom. Det samme problem opstår, hvis celler der bruges af formler i lvs fjernes. Formlerne vil derved holde op med at virke, da de refererer til celler der ikke findes, og resultatet kan ikke beregnes. Makroerne der ikke ses af kunderådgiveren, men som kører i baggrunden, skal også rettes til. Laver makroerne beregninger der inkluderer data fra flere ark, skal disse beregninger ændres, ved ændringer i opbygningen af lvs. Makroer kan enten foretage beregninger ud fra række- og kolonnenummer, eller ud fra celle id. Er en makro ikke dynamisk i forhold til f.eks. antallet af ejendomme, skal disse ligeledes rettes til. Som beskrevet foroven, er der knyttet en række ark til hver ejendom. Skal designet i et af disse ark laves om, skal designet laves om i de tilsvarende ark for de andre ejendomme. Det er altså ikke muligt at lave en ændring et sted, hvis den skal slå igennem overalt. Vil man have flere ens ark i Excel, men kun lave rettr et sted, kan et ark oprettes via makroer. En celles id skal være unik, så formler må derfor benytte sig af række- og kolonnenummer, eller formlerne skal kunne laves ud fra celle id der 13

16 Landbrugsvurderingssystemet oprettes dynamisk. Dette gør dog opbygningen af et Excel ark komplekst, og fjerner overskueligheden, ved at kunne se formlerne direkte i cellerne. Ovenstående problemstilling er ikke kun gældende for lvs, men er gældende for alle systemer der laves i Excel. Er det kun den basale funktionalitet i Excel der bruges, er Excel meget brugervenligt og overskueligt bygget op. Skal der designes større systemer, er Excel ikke så fleksibelt i og med, at der ved ændringer i systemet, skal rettes i designet i både opbygningen af regnearket, formlerne i cellerne og i den bagved liggende kode, i form af makroer. Selvom Excel er et meget benyttet program, bliver det hurtigt for komplekst. Er det nødvendigt at bruge makroer, oprette ekstra ark og skjulte celler til opbevaring af data, forsvinder overskueligheden. Excel er ment som et kontorprogram alle skal kunne bruge, men når makroer er nødvendige, er programmet ikke længere henvendt til den enkelte kontormedarbejder. Når systemerne bliver for store til Excel, vælger mange at få lavet en applikation. Problemet med en applikation er, at det kan være meget tidskrævende og dyrt, at få implementeret. Samtidig kan applikationen kun bruges til det ene formål den er udviklet til. Ved at lave et regelbaseret system, der kan sættes op ved hjælp af simple regler, kan et system, der er for komplekst til Excel laves. På den måde vil man, kunne lave et kompliceret system, uden at skulle kunne kode makroer i vba, blot ved at have kendskab til nogle få regler. Fordelen ved et regelbaseret system er, at det er nemt at sætte op, ændringerne vil være nemme at lave og det kan benyttes til flere formål. 1.3 Opsummering I ovenstående afsnit er der beskrevet hvad landbrugsvurderingssystemet er, hvad det bruges til samt hvordan det er lavet. Der er derefter beskrevet hvilke ulemper der er, ved at have et stort system implementeret i Excel. Derudover er det beskrevet hvordan overskueligheden forsvinder, for brugeren der skal lave programmet, og at der ved ændringer skal ændres tre steder, før systemet vil virke. Til sidst er der beskrevet hvordan problematikken kan undgås, ved implementering af et regelbaseret system, hvor systemer for store til Excel kan laves. 14

17 2 ANALYSE OG DESIGN Dette afsnit er en gennemgang af hvilke regler der er brugt i landbrugsvurderingssystemet. Derudover vises det, hvordan et regelbaseret system, kan opbygges, uden brug af Excel. Ved hjælp af enkle regler, kan et system designes, så en vurdering af et landbrug kan laves. Systemet vil ikke være begrænset til kun at kunne lave en vurdering, men også til andre lignende systemer, der er for komplekse at lave i Excel. Det vises samtidig hvordan, der kan tilføjes ekstra funktionalitet, uden at ændre i selve kildekoden. Dermed vil systemet kunne udføre andre eller flere opgaver, end det er designet til. 2.1 Regler der er brugt i landbrugsvurderingssystemet For at lave landbrugsvurderingen og danne resultaterne i indstillingsarket, og lave diverse mellemberegninger, er der brugt formler i excel, samt makroer til beregninger og ændringer af formler. Der findes mange interne formler i excel, men da det ikke er alle der er brugt, laves her en gennemgang af de værktøjer der er nødvendige for at kunne danne en kreditindstilling If-statements Der er brugt if-statements, til angiv af værdier i de enkelte celler. Figur 2 indlejrede if-statements Figur 2 viser et eksempel på en indlejret if-statement. Hvis den første if-statement er sand, kaldes en ny if-statement der skal opfylde to kriterier. Er de to kriterier opfyldte, er resultatet én værdi, mens værdien er en anden, hvis kriterierne ikke er opfyldte. Udover at sætte en konstant værdi, kan en celles værdi sættes lig med en anden celles værdi. På Figur 3 er et andet eksempel på en if-statement, hvor det undersøges om en værdi er større end en anden. 15

18 Analyse og design Figur 3 - if-statement Figur 4 - besætning For en besætning, som vist på Figur 4, er der en vejledende skalaværdi, der angiver hvad en enhed er værd, og en dyreenhed, som bliver beregnet automatisk. Alt efter hvilken besætningstype der er valgt, vil den vejledende skalaværdi have en bestemt værdi, ligesom dyreenheden beregnes på en specifik måde. For at finde ud af hvilken værdi og formel der skal bruges, løber en makro de valgte typer igennem, og sætter derefter værdien og formlen i de respektive celler. Her er der tale om en if-statement i Visual Basic koden, der bestemmer indholdet i cellerne, ud fra typevalget SUM SUM bruges i Excel til at lægge værdien af flere celler sammen. Det kan være områder i form af rækker, kolonner, flere rækker og kolonner, et mindre område, eller bestemte celler. I lvs er SUM brugt til at lægge indholdet af små områder og bestemte celler sammen. Figur 5 - SUM og if-statements På Figur 5 vises to eksempler hvor SUM funktionen bliver brugt. I feltet J16 er SUM brugt på området N3 til N14, som er værdiforskellen på de forskellige jordtyper, mens 16

19 Analyse og design det i L14 er brugt til at lægge arealerne af jordtyperne sammen. I eksemplet ses det, at de celler der skal beregnes en sum af, er et celleområde Beregninger Almindelige beregninger som addition, subtraktion, multiplikation og division bliver brugt til forskellige formål i lvs. Et eksempel ses på Figur 5 hvor både sum og division er brugt i henholdsvis I16 og N15, til beregning af vægtet tillæg og værdiforskel. I række M og N er subtraktion og multiplikation benyttet til beregninger af vægtet tillæg og værdiforskel. På Figur 6 beregnes nettoarealet som grundarealet af ejendommen minus vejarealet. Figur 6 - beregning med minus Lister Til cellerne kan der være tilføjet en valideringsliste med gyldige værdier der kan vælges. Skrives der andet i cellerne, end det der kan vælges fra listen, vil der komme en fejlmeddel. Vil man ikke vælge et af punkterne fra listen, må der ikke stå noget i cellen. Et eksempel på valideringslister kan ses på Figur 7 og Figur 8. Figur 7 - liste for ejendomstype Figur 8 - Liste for ejendomsbenytt 17

20 Analyse og design Afrund Den indbyggede afrund funktion i Excel er brugt, til at afrunde tal, for at begrænse antallet af betydende cifre. Figur 9 viser hvordan afrund bruges til at afrunde resultatet for reduktion i VG pga. manglende mælkekvote. Figur 9 afrund Afrund er i dette tilfælde brugt til at afrunde tallene til venstre for decimaltegnet Begrænsninger I nogle celler er der sat begrænsninger for hvad input må være. I stedet for lister, kan der ved indtastning af antal, være minimum og maksimumværdier der skal overholdes. Ved indtastning af antal ejendomme skal der minimum være 1, men maksimum 5 ejendomme. Indtastes der et tal, der ikke er gyldigt, vil det ikke blive gemt, da systemet kun er designet til 5 ejendomme Decimaler Der er næsten udelukkende brugt heltal, til værdier. Dog er der nogle steder angivet arealer i decimal værdier. 2.2 Landbrugsvurderingssystemet Hvis man ser på opbygningen af lvs fra et programmeringsmæssigt perspektiv, kan et landbrug ses som en klasse, hvor man åbner en instans af klassen, hver gang Excel arket åbnes. Arkene ses som dele af et landbrug, der igen er delt op i mindre dele. Samlet set udgør alle delene beskrivn af et landbrug, der kan bruges til en landbrugsvurdering. De fire ark (Forside, Harmoni, Summering og Indstillingsark) der findes én gang, er tilknyttet selve landbruget, og vil derfor ses som en del af landbrugsklassen. Til hver vurdering er der et antal ejendomme, som i Excel arket repræsenteres via de fem ark (X-forside, X-Jorden, X-Bygninger, X-Maskiner og X-Besætning), der forekommer 1-5 gange. Et sæt ark kan ses som et ejendomsobjekt, da de er ens med hensyn til opbygningen, men alligevel kan have forskellige værdier tilknyttet. 18

21 Analyse og design Landbrug 1 1 n 1 1 Ejendom 1 Harmoni 1 n n Jord Bygning n Besætning Figur 10 - Landbrugssystemet delt op i objekter Undersøges de fem ark nærmere, ses det at forsiden ikke kan deles op i mindre elementer. Jorden kan til gengæld deles yderligere op. De rækker i jorden der beskriver de forskellige jordtyper, indeholder de samme elementer, og kan derfor ses som et objekt, men da rækkerne er konstante, altså ligesom forsiden ikke ændrer opbygning undervejs, kan jord arket ses som et stort objekt, i stedet for at dele jordtyperne op i mindre objekter. Figur 10 viser hvordan arkene kan deles op i objekter. Ser man på bygningerne, kan man se at arket ændrer sig dynamisk, når antallet af en slags bygninger indtastes. Bygninger består af x antal boliger, x antal nybygninger, x antal driftsbygninger og x antal projekterede bygninger. Af alle bygningerne kan der forekomme nul eller flere instanser. Ved at oprette dem som objekter, vil disse instanser kunne oprettes, når der bliver brug for dem. At det ikke vides på forhånd hvor mange rækker eller objekter der skal laves af boligerne, men at deres opbygning er ens, gør det ideelt at lave dem som objekter. Man kan vælge at lave de enkelte bygninger som objekter i en ejendom, eller man kan oprette et bygningsobjekt i ejendommen, der indeholder de forskellige bygninger. Figur 11 viser hvordan bygningerne kan deles op i mindre objekter. 19

22 Analyse og design 1 Bygning n n n n Nydriftbygning Nybolig Driftbygning Bolig Figur 11 - Bygning delt op i objekter Ligesom bygningerne er besætning ikke fastlagt fra starten af, eftersom at antallet af besætningsrækker kun bliver kendt under kørslen. Derfor vil det være en fordel at oprette objekter af besætninger, der kan oprettes flere instanser af, således at der laves en instans for hver besætningstype på ejendommen. Som i ethvert andet programmeringssprog, hører der til hver klasse, variabler. I lvs er der brugt tekst og tal, så det vil derfor være nødvendigt at kunne lave to forskellige opbevaringstyper i form af variabler i det nye system. Som det er bygget op i lvs, er der til de fleste celler, en forklarende tekst, der fortæller hvad der skal stå i cellen, ligesom der er nogle lister tilknyttet visse celler, med gyldigt input. Det er derfor et krav, at der er plads til forklarende tekst, til variablerne, ligesom der skal kunne oprettes begrænsninger på inputtet. Begrænsningerne kan for en tal variabel være minimum og maksimum værdier, eller det kan være i form af lister, der indeholder bestemte værdier, som variablerne må tildeles. Splittes lvs, som beskrevet, op i mindre dele, vil det være nemmere at udskifte enkelte moduler, ligesom ændringer i programmet vil være lige til at foretage. Skal der foretages ændringer i lvs, som det er bygget op nu, kan det kræve ændring i designet som brugeren ser, i form af ekstra/færre rækker og kolonner. Det kan ligeledes være at der skal ændres i nogle af formlerne der bliver brugt til at danne data i cellerne. Da der også er makroer tilknyttet lvs, kan det ydermere kræve at der skal ændres i koden, hvilket vil kræve et programmeringsmæssigt kendskab. Hvis systemet bygges op, som beskrevet, hvor det består af objekter, i stedet for ark, vil der kunne foretages ændringer i systemet, uden at skulle oprette nye rækker med celler, ændre i bagved liggende kode, eller ændre formlerne i eksisterende celler. Ved at kunne definere disse objekter, og formler, ved hjælp af simple regler, vil det blive nemt at opsætte et system, eller lave ændringer til et system. Da da kan oprettes flere instanser 20

23 Analyse og design af et objekt, vil ændring i objektet gælde alle instanser der oprettes. I modsætning til opbygningen i Excel, skal der nu kun ændres et sted. 2.3 Opbygning Opbygningen af programmet sker ved hjælp af tekstfiler, hvor vurderingssystemet deles op i to dele. Den ene del vil være opbygningen af programmet, der fortæller hvilke klasser og variabler der findes, hvilke objekter der skal oprettes, samt hvilke ifstatements og for loops der skal knyttes til systemet. Den anden del, vil bestå af input til variablerne, der skal sættes fra brugerens side. På den måde vil reglerne kunne sættes op en gang for alle, styret et sted fra, og brugeren vil kunne se de variabler, der skal indtastes data til. Der vil derfor ikke være forstyrrende elementer, i form af if-statements og for andre formler, som normalt gemmes i cellerne. For at kunne opbygge et system, er det nødvendigt med en parser, der kan analysere input, og stå for deklarationer af variabler, klasser, og arrays. Skal en værdi gemmes i en variabel, er det ligeledes parseren, der skal forstå hvad der er ved at ske, og sørge for at tildelingen sker. En tildeling af værdi, kræver at den variabel der skal gemme værdien er oprettet. Dette vil dog ikke blive parserens problem, da den kun skal stå for at finde ud af, hvad der skal ske med den aktuelle inputlinje. Før parseren får inputtet der skal fortolkes, samles regler og input, for derefter at blive sendt igennem parseren. Så længe der er mere data, der kan analyseres, vil parseren blive kaldt. Parseren vil få en liste med data der skal analyseres. Hver gang noget data er analyseret, vil det, hvis det er muligt, blive simplificeret og omsat til forståelig data. Som Figur 12 illustrerer, er der en stak med data, der bruges som input til parseren. Så længe stakken indeholder data der kan simplificeres, vil parseren køre. Parser Figur 12 - parseren simplificerer input Når parseren kaldes, vil der formentlig blive analyseret data, hvor variabler der endnu ikke er oprettet skal have tildelt en værdi. Af gode grunde kan det ikke lade sig gøre, og det er derfor nødvendigt at undersøge data igen, når parseren kan komme videre med simplificeringen. Ved at simplificere input, kan parseren hele tiden, omdanne mere og mere til forståeligt data, indtil input ikke kan simplificeres mere. Dette kan være fordi alle oprettr og tildelinger af værdier er foretaget, eller fordi resten af inputdata 21

24 Analyse og design omhandler objekter, der ikke er brugt i det aktuelle program. Kan input ikke yderligere simplificeres, skal programmet afsluttes, og al analyseret data skal gemmes. På den måde er rækkefølgen af data der gives til parseren ikke vigtig, eftersom den selv finder ud af at analysere forståeligt data først, og på den måde simplificere mere og mere data. Målet er at parseren skal forstå så meget af inputtet som muligt. Da en variabel ikke kan tildeles en værdi før den er oprettet, og variabler ikke kan tildeles klasser der ikke er oprettet, skal oprettr ske før tildeling af værdier. Da det ikke er til at vide, hvordan rækkefølgen af input, vil være sorteret, er det parserens opgave, at finde ud af om en variabel findes, før en evt. værdi gemmes. For at kunne analysere alt input, er det nødvendigt at tage én linje ad gangen. Når linjen er indlæst, skal den analyseres for at se hvad formålet med linjen er. Input kan handle om to ting. Det kan være tildeling af en værdi, eller det kan være en oprett. Senere vil det blive vist at en oprett kan foregå over flere linjer, hvis der er tale om oprett af en klasse. For tildeling af visse værdier, er det nødvendigt at opfylde kravet om if-statements. Til dette formål laves en metode, der kan analysere en if-statement, og derefter sørge for at den rigtige kode bliver udført. If-statement bruges til at fastsætte en variabels værdier, ud fra nogle krav, forstået på den måde, at kravene skal være opfyldt, før reglerne udføres. Når samme funktionalitet skal udføres for flere variabler, er et for loop nødvendigt. Da det stadigvæk kan være at nogle variabler kun skal tildeles værdier, hvis specifikke krav er opfyldt, skal det være muligt at benytte et for-loop indlejret i en if-statement Hvad kan oprettes? For at kunne gemme data, og opnå den ønskede funktionalitet skal der først og fremmest kunne oprettes variabler, til opbevaring af tal og tekst. Derudover skal der kunne oprettes klasser, der kan bruges til at repræsentere objekter, som i dette tilfælde kan være en ejendom. Da der skal kunne forekomme flere instanser af nogle klasser, ved f.eks. antallet af ejendomme, skal der kunne oprettes arrays af klasser. Ved at have flere ens objekter i et array, vil samme handling kunne udføres på samtlige objekter, ved hjælp af for-loops. Det skal altså være muligt at oprette følgende Variabler o Tal o Tekst Klasser o Variabler o Klasser o Arrays 22

25 Analyse og design Arrays o o Metoder Klasser Variabler Hvor ovenstående skal forstås som, at der kan oprettes to forskellige slags variabler. En klasse kan indeholde variabler, klasser og arrays. Arrays kan indeholde klasser og variabler, og der kan oprettes metoder. Alle typerne oprettes direkte i hovedklassen, svarende til landbruget i dette eksempel, ligesom variabler, klasser og arrays kan oprettes i de underliggende klasser. En variabel kan gemme en talværdi eller en tekstværdi. Klasser kan indeholde variabler, instanser af andre klasser og arrays. Et array skal kunne indeholde variabler eller instanser af klasser. Da der kan være brug for ekstra funktionalitet til programmet, i form af f.eks. bynavne der skal hentes ud fra et postnummer, skal der kunne tilføjes metoder, der oprettes via kodefiler udefra. De er altså ikke implementeret som en del af programmet. Hovedklassen svarer altså til landbruget, som består af en række ejendomme. Disse ejendomme vil oprettes i form af klasser, der igen vil bestå af andre klasser, der vil indeholde beskrivn af blandt andet bygninger og jorden. Da der kan være flere ejendomme tilknyttet landbruget, men alle indeholde samme objekter, vil ejendommene gemmes i et array, således at de samme handlinger kan udføres for hver ejendom. På denne måde vil den eneste begrænsning til, hvor mange ejendomme der kan oprettes, være hukommn. Det er altså ikke nødvendigt at fastlægge antallet på forhånd Hvad kan tildeles? I bund og grund er det variabler der kan tildeles værdier, men ligesom at variablerne skal kunne være gemt forskellige steder, skal en variabel kunne tildeles værdier på forskellige måder. Her beskrives de måder en variabel skal kunne tildeles en værdi på: Tal / tekst Variabel Beregning Sum If-statement For loop Metode En variabel kan få tildelt en værdi direkte. Skal variablen indeholde en talværdi, kan talværdien knyttes direkte til variablen, ligesom en tekstværdi skal kunne knyttes til variablen, hvis det er en tekst variabel. 23

26 Analyse og design Nogle variabler bruges som hjælpevariabler og sættes lig med andre variabler. I lvs kommer flere af værdierne i harmoniberegningen f.eks. direkte fra andre værdier, hvorfor en variabel skal kunne tildeles en anden variabels værdi. Da der ikke vil være meget funktionalitet, hvis programmet ikke kan foretage beregninger, skal en værdi kunne være resultatet af en beregning. En beregning skal kunne være beregning af værdier i form af konstanter og andre variabler. En variabel vil derfor kunne bruges til at danne resultater for flere andre variabler. Som beskrevet er funktionen SUM brugt i lvs til at beregne summen af flere variabler. I dette program vil variablerne gemmes i objekter, som kan gemmes i et array. Ideen med SUM skal derfor overføres, således at det er muligt at få et resultat. I Excel er SUM brugt på områder, men i og med at variablerne gemmes i objekterne, vil SUM kunne bruges til at beregne summen ud fra en bestemt variabel fra hvert objekt i et array. På den måde vil formlen automatisk udvides, hvis der oprettes flere objekter. If-statement er en mulighed der skal kunne bruges til at tildele en værdi, ud fra nogle bestemte krav. Det kan være at en variabel skal tildeles en værdi hvis noget er sandt, men at det skal have en anden værdi, hvis det er falsk. Det bruges f.eks. til at lave beregninger for dyreenheder ud fra hvilken besætningstype der er valgt. For-loops bruges til at knytte værdier til flere variabler. Da det ofte vil være samme beregning der skal udføres for variablerne i flere objekter, skal man være i stand til at udføre en handling der skal foretages for flere variabler på en gang, ved hjælp af et forloop. Da det ikke vides på forhånd hvor mange objekter der bliver oprettet, vil det ikke være muligt, at oprette specifikke regler, der f.eks. angiver handlingen for objekt 1-3. Ved hjælp af for-loops vil det være muligt, at få tilføjet beregningerne til alle objekter. Ved if-statement, kan det være, at nogle forudsætninger skal være opfyldt, før en variabel kan tildeles en værdi. Ved at indlejre et for loop i en if-statement, opnår man en funktionalitet der gør at en handling kan udføres for en variabel i flere objekter, hvis et krav er opfyldt. Det gør altid overskueligheden nemmere, hvis der er kommentarer. Der skal derfor kunne laves kommentarer i filerne der skal indlæses. Da kommentarer er til hjælp for brugeren der indtaster data til systemet, vil disse ikke blive brugt til noget når data er indtastet, ligesom tomme linjer heller ikke vil blive behandlet af programmet. Da det kan ske, at der opstår en linje med ukendt indhold, altså en som parseren ikke kan analysere og omsætte til forståelig data, vil den blive forsøgt analyseret og simplificeret, indtil der ikke kan simplificeres mere data i programmet. Linjer der ikke er analyseret når programmet er færdigt vil ikke blive gemt. Kommer der en linje der ikke kan analyseres, vil programmet altså ikke fejle, men fortsætte med at analysere resten af data. 24

27 Analyse og design 2.4 Variabler I lvs er der brugt to typer af værdier, der skal derfor kunne oprettes to typer af variabler. En variabel der skal indeholde en tal værdi, samt en variabel der skal indeholde en tekst værdi. Selve opbygningen af variablerne vil være næsten ens, med den lille forskel at de skal kunne gemme hver sin datatype. Til at repræsentere en variabel kan man vælge at bruge en struct eller en klasse. Structs bruges dog typisk til letvægtsobjekter, hvilket ikke er tilfældet her, da variablerne kommer til at indeholde diverse oplysninger.(4) En anden ulempe ved structs er, at de ikke er i stand til at nedarve. Dette vil der dog ikke blive brug for i projektet, hvorfor der kan ses bort fra dette. Ved at oprette et klasseobjekt til formålet, kan der laves flere instanser af variablerne, ligesom der kan knyttes forskellige egenskaber til variablerne. Egenskaberne kan f.eks. beskrive, at variablen kun må have nogle bestemte værdier, eller hvilke værdier der er tilladt. Det er selvfølgelig et krav, at typen på variablen overholdes, således at der ikke gemmes et tal i en streng variabel og omvendt. Typen på variablen kan sættes med en boolean, hvor sand kan betyde at variablen er et tal, og falsk betyder at variablen er en tekst. Dette vil være tilstrækkeligt i tilfældet af at programmet kun skal bruges til, at lave landbrugsvurderinger, men hvis programmet skal udvides på et senere tidspunkt, vil det være mere hensigtsmæssigt, at bruge en streng til dette formål, som kan have utallige værdier, og ikke er begrænset til to. En tredje mulighed vil være at oprette en Type, til at indeholde typen. Så længe der kun skal bruges tal og streng værdier, vil dette kunne bruges, men hvis der skal laves en Type der ikke er kendt at programmeringssproget, vil det ikke kunne bruges. Er variablens værdi begrænset til nogle bestemte værdier, kan disse værdier gemmes i en liste i variabel objektet. Når der skal gemmes en værdi for variablen, kan man undersøge om værdien er gyldig i form af at være på listen, eller om den er ugyldig og ikke må gemmes. Selvom der er en liste med gyldige værdier, skal det være muligt ikke at gemme en værdi, eller at gemme en tom værdi, således at programmet ikke går i stå, hvis en variabel ikke bliver tildelt en værdi. Når der skal gemmes en værdi, skal det undersøges om værdien er gyldig, dette kan ske i metoden i objektet, eller det kan ske, fra metoden, der vil sætte værdien. Udover en liste med værdier, kan der, hvis der er tale om et tal, være nogle øvre og nedre grænser for hvad værdien må være, samt hvor mange tal den må bestå af. Der skal derfor være nogle yderligere egenskaber i variabel objektet, i form af minimum og maksimum værdier. Er der ikke en minimum- og maksimumværdi, skal variablerne i variabelobjektet sættes til det laveste og højeste tilladte tal, så der ikke bliver problemer, hvis et meget lille eller et meget stort tal skal gemmes. Dette skal være standard grænserne for variablen, der sættes samtidig med at den oprettes. Da der er beskriv til mange af cellerne i lvs, skal det være muligt at gemme en beskriv til en variabel. Den gemmes lige som begrænsningerne for variablerne, i 25

28 Analyse og design variabel objektet. Beskrivn vil ikke blive brugt i det implementerede system, men skal der tilføjes et grafisk brugerinterface til indtastning af data, vil det kunne bruges. For at gøre det hurtigere at oprette flere variabler, skal der kunne oprettes flere variabler på samme linje, adskilt af semikolon. Ved at splitte input ved alle semikolon, kan hver del køres igennem metoden der står for oprettn, og flere variabler kan oprettes. Til opbevaring af variablerne, kan diverse lister benyttes. En ArrayList er dog ikke at foretrække, medmindre at variabel navnet, bliver gemt i variabelobjektet, da den rigtige variabel ellers ikke kan findes frem igen. Ulempen ved en ArrayList er, at når en bestemt variabel skal bruges, er man er nødt til at løbe alle elementer igennem, indtil man møder den rigtige, medmindre man kender placeringen i arrayet. Ved at benytte en collection (samling), undgår man at løbe alle elementer igennem, for at finde en bestemt værdi. Collections bruger en nøgle, til at fortælle hvor hver enkelt værdi er gemt. Af collections kan nævnes hashtable og dictionary. Hashtables gemmer objekter, så hvis variablerne gemmes i en hashtable, skal der benyttes boxing og unboxing hver gang, der skal gemmes og hentes en variabel. Ved at benytte en dictionary, vil der dermed opnås lidt bedre yd.(5) Samtidig med at variablen oprettes, kan der tildeles en værdi til variablen. Er dette tilfældet, skal parseren dele oprettn i to dele. Hvor selve variablen først bliver oprettet, og derefter tilføjes værdien, hvis den er gyldig. Er værdien ikke gyldig, eller kan endnu ikke simplificeres, bliver variablen således alligevel oprettet. Variabelnavnet tilføjes derfor sammen med værdien til listen, der skal simpliciferes senere. Typen på variablen skal ikke gemmes, da den er oprettet. I c# leveres der ikke en copy-constructor, derfor skal der laves en metode der kopierer en variabel. Kopiering af variabler er nødvendig, hvis de f.eks. skal bruges i et array. Sættes variablerne i arrayet, lig med hinanden, vil det fungere som referencer, og ikke som ens objekter.(6) 2.5 Klasser Ligesom variablerne skal indeholde forskellige egenskaber, skal klasserne have forskellige attributter. De skal kunne indeholde variabler, arrays, samt andre klasser. Hvert array skal ligeledes kunne indeholde variabler og klasser. Klasserne kan laves ved at bruge reflection eller ved at oprette dem som klasser ligesom variablerne. Reflection har ikke særlig god performance(7), så det bedste er at oprette dem som klasser. Struct er ikke en mulighed, da klasserne ikke kan nøjes med at indeholde oplysninger, men også skal have indbygget funktionalitet, i form af metoder, der blandt andet kan tilføje klasser og variabler til klasseobjektet. I og med at klasserne skal kunne indeholde variabler, skal der oprettes en metode der kan oprette variablerne og en metode til at hente variablerne. Variablerne kan med fordel gemmes i klasserne, på samme måde som variablerne gemmes i hovedklassen, i form af dictionaries. Da variablerne selv indeholder information om betingr for 26

29 Analyse og design værdien der må tildeles, kan disse genbruges når en værdi skal gemmes. Der er ingen grund til at klasserne indeholder metoder, til at tjekke om værdierne er gyldige, da den funktionalitet allerede er implementeret i hovedklassen. Ved at hente hele variablen ud, før en værdi sættes, kan funktionaliteten i hovedklassen genbruges. Ligesom variablerne i hovedklassen, kan variabler i klasserne kun tildeles en værdi hvis de er oprettet, og værdien opfylder kravene for variablen. Til opbevaring af klasser er det oplagt at gemme dem i en dictionary ligesom variablerne. Forskellen på variablerne og klasserne er dog, at når en variabel skal oprettes, er det ikke nødvendigt at instantiere den, men den kan tildeles en værdi direkte. Et objekt af en klasse skal instantieres, før det kan bruges. Grunden til dette er, at selvom en klasse indeholder andre klasser, skal det være muligt at oprette en instans af klassen, selvom de underliggende klasser endnu ikke er oprettet i systemet. På den måde kan de andre attributter i klassen bruges, selvom underliggende klasseobjekter endnu ikke er findes. Det vil gøre at simplificeringen vil foregå hurtigere, i og med at mange instanser af klasser kan bruges med det samme, i stedet for at skulle løbe alle reglerne igennem, indtil alle klasser er oprettet. Må attributterne i en klasse først bruges, når alle underliggende klasser er oprettet, risikeres det at systemet låser, fordi et objekt ikke bliver initialiseret. Det kan f.eks. være, der skal oprettes et array af klasser, i et objekt. Hvis antallet af klasser, afhænger af indtastning fra brugeren, vil attributterne først kunne bruges, når antallet er indtastet. Hvis klasserne i arrayet i et tilfælde ikke skal bruges, og brugeren således ikke indtaster et antal, vil hele systemet låse, og ingen af attributterne kan bruges. Ved at lade en klasse indeholde objekter, der endnu ikke er oprettede, skal instanserne sættes til null, indtil de bliver instantieret. Et klasseobjekt skal stadigvæk oprettes helt, inden det kan instantieres og bruges. Det implementerede system vil altså ikke tillade først at oprette en klasse, for senere at tilføje flere variabler og klasser til den. Grunden til dette er, at tilføjes der yderligere variabler, klasser og arrays senere, vil man få et problem hvis der bruges flere instanser af klassen. Er klassen f.eks. brugt til at oprette et array af klasseobjekter og der tilføjes flere elementer til den oprindelige klasse, vil disse elementer ikke optræde i arrayet, og instanserne vil ikke have de samme egenskaber. En klasse bliver derfor nødt til at være færdig oprettet, uden yderligere tildelinger, senere i forløbet. Alternativt skal alle instanser af klassen løbes igennem, så de alle kan få tilføjet de nye elementer. Det er muligt at tilføje variabler, klasser og arrays til en klasse efter den er oprettet. Men det vil sige, at tilføjn sker uden for deklarationen af klassen. Tilføjes attributter efter deklarationen, vil det som beskrevet ikke blive tilføjet til alle instanser af klassen. Da der ikke gemmes information i en klasse, om hvor mange instanser der oprettes af den, samt hvor de bruges, vil det ikke være muligt at løbe alle instanser igennem, efter deklarationen. Hvis attributter alligevel tilføjes til en instans, vil instansen altså være unik, og have yderligere attributter i forhold til de andre instanser af samme klasse. 27

30 Analyse og design Unikke klasser vil ikke blive brugt i denne opgave, men i og med at metoder der tilføjer variabler, klasser og arrays, bruges ved oprett af en klasse, vil disse kunne bruges til at tilføje attributter efter oprettn ved en eventuel udvid af programmet. Når en instans af en klasse oprettes, gemmes den ligesom de deklarerede klasser i en dictionary. Instantieres klassen ikke, vil der blive oprettet et tomt klasseobjekt, der er lig med null. Når den instantieres sættes den lig med en instans, af den deklarerede klasse, som der skal laves en instans af. Dette kan derfor først ske, efter deklarationen har fundet sted. Når en instans af en klasse, tilføjes til et klasseobjekt, skal en boolean, der fortæller om klassen blev tilføjet eller ej, returneres. Klassen skal tilføjes, hvis den ikke findes i forvejen. Som i hovedklassen, vil klasserne heri, også blive gemt i en dictionary. Klasser der tilføjes til en klasse, er ligeledes deklareret i forvejen og gemt i hovedklassen, der indeholder alle de klasser, der kan oprettes instanser af. Udover variabler og klasser, skal klasseobjekterne kunne indeholde arrays. Disse vil ligeledes blive gemt i en dictionary. For at tilføje et array til en klasse, skal der laves en metode, der verificerer om arrayet findes i forvejen. Er det ikke tilfældet, bliver arrayet tilføjet. Der skal yderligere laves en metode, der returnerer et array, og en metode der kan svare på en forespørgsel om et array findes, samt en metode der fortæller om et array er instantieret. Disse skal bruges hvis der skal laves et for-loop der løber arrayet igennem. For-loopet skal kunne se om arrayet er instantieret eller ej. Tror for-loopet at arrayet er instantieret, uden at være det, vil længden af arrayet være nul, og for-loopet vil derfor fejle, da det tror der er tale om et array, der skal være tomt. For at kunne oprette flere instanser af et klasseobjekt, skal der være en metode til kopiering. Den skal sørge for at kopiere alle dictionaries, således at der kan oprettes en kopi af klassen, og ikke en ekstra reference. Data gemt i klasser skal kunne udskrives. Til dette formål skal der oprettes metoder, der returnerer de dictionaries der indeholder variabler, arrays og klasser. 2.6 Metoder Udover at kunne oprette de forudbestemte typer og bruge de indbyggede regnemetoder og funktioner, skal ekstra funktionalitet kunne tilføjes til systemet. Hvis det er muligt at importere ekstern kode, vil det være nemt at tilføje denne ekstra funktionalitet. For at kunne indlæse kode, og køre den uden at det ændrer på selve kildekoden til programmet, kan CodeDomProvider klassen bruges. (8) CodeDomProvider bruges til at oprette en instans af en kodekompilator, så koden derefter kan kompileres. Sproget som koden er lavet i, er ikke vigtig, så længe den er understøttet af CodeDomProvideren.(9) Hvis der skal laves en udvid, der medfører en problemstilling der ikke er taget højde for, eller hvis der skal hentes ekstern data ind, kan indlæsning af en ekstern metode bruges. En af de eksterne metoder der vil blive benyttet i programmet, er når en by skal findes ud fra postnummeret. Ved at have alle byerne liggende i en ekstern fil, kan man, 28

31 Analyse og design hvis det skulle blive nødvendigt, hurtigt fjerne eller tilføje en by, uden at det kræver adgang til kildekoden til systemet. Eksterne metoder kan også tilføjes i Excel, men der er det nødvendigt først at have koden kompileret og derefter tilføje den som reference til Excel. Referencen skal altså tilføjes før funktionen kan bruges. Det er derfor ikke muligt at tilføje metoden undervejs, eftersom der vil komme fejl i Excel arket, de steder funktionen er forsøgt brugt. Skal der tilføjes kode til programmet under kørsel, skal koden kompileres, før den kan bruges. Til at kompilere koden undervejs, er der to muligheder: Kompilere koden og gemme den i hukommn Kompilere koden og gemme den som en assembly (10) I begge tilfælde skal metoden kaldes dynamisk. Er metoden gemt i hukommn kan den kaldes direkte, men gemmes den i en assembly, skal den indlæses, før den kan bruges. Før en assembly kan bruges, skal der laves en reference til den. De assemblies der er refereret til i kildekoden, bliver automatisk indlæst, når programmet køres. På den måde vil alle assemblies være klar til de skal bruges. I modsætning til Excel er det muligt at oprette nye referencer, mens programmet kører. På den måde kan nye metoder til føjes til et eksisterende program under kørslen. Når der skal kompileres ekstern kode, vides det ikke hvornår en assembly skal bruges, eller om den i det hele taget vil blive brugt. Derfor bør man vente med at indlæse den, til der bliver brug for den. Når en assembly skal indlæses, kan man vælge mellem at indlæse i det aktuelle applikations domæne, eller man kan oprette et nyt domæne til den. Efter en assembly er indlæst, kan den ikke fjernes igen, medmindre man fjerner alle assemblies i et applikationsdomæne. Skal en assembly kun bruges en gang, vil det være en fordel at lave et nyt domæne til den, men da det ikke vides hvor mange gange en metode skal bruges, og den oftest skal bruges flere gange, vil de ikke blive indlæst i deres eget applikationsdomæne. (11) Når en metode skal kaldes, kan der kræves nogle input, ligesom at metoden altid vil returnere et output. En void metode returnerer ikke et output, men uden et output, vil metoden ikke være brugbar i denne sammenhæng. For at sikre at de rette input parametre til en metode er til stede, skal det undersøges, om de parametre en metode kræver, er sat, inden den kaldes. Hvis metoden kaldes succesfuldt, vil der generes et output. Outputtet skal undersøges, om det er gyldigt, eftersom et metodekald altid returnerer et output, der skal gemmes i en variabel. Følgende syntaks bruges bruges før et metode kald: 29

32 Analyse og design o Findes metode Undersøg om parametrene metoden skal kaldes med er til stede o Findes metode ikke o Er parametrene til stede Kald metode og undersøg om output må gemmes i variabel o Er parametrene ikke til stede gem metode kald til senere Gem metodekald til senere Ved hjælp af reflection api et kan typerne i en metode findes, ligesom det bruges til at kalde en metode dynamisk. (12) I stedet for at skulle gå alle metoderne i applikationsdomænet igennem, for at se om en metode eksisterer, skal der laves en liste over de metoder der er oprettet. Når en metode skal kaldes, kan det dermed hurtigt undersøges om metoden er oprettet, ved at se om den findes på listen Afrund AFRUND bliver brugt i lvs til at fjerne de betydende cifre på et resultat. For at implementere denne funktionalitet skal der laves en metode til dette. Den skal kaldes, på samme måder som de eksterne metoder, når de er oprettet. I stedet for at koden skal hentes udefra, er der her tale om en intern metode, der ikke kan ændres på. Metoden laves, så den fungerer på samme måde som i Excel, ved at skrive afrund(tal, antalcifre), hvor tallet er det der skal afrundes, og antal cifre fortæller hvor mange cifre der skal afrundes, og om de ligger før eller efter kommaet. Der er en indbygget metode der kan afrunde et decimal tal i c#, der er bygget op på samme måde som metoden i Excel, forskellen er dog at c# s anden parameter skal være et positivt tal, der fortæller hvor mange decimaler der skal være i resultatet. Det understøtter altså ikke afrunding af tal til venstre for kommaet. Der skal derfor laves en metode der kan afrunde til venstre og højre for kommaet. Afrunding af tallene til venstre for kommaet, kan laves ved at lave tallet om til en tekst, og løbe værdierne igennem bagfra, indtil man har afrundet det ønskede antal tal. En anden mulighed er at bruge modulus til at finde restværdien, hvorefter restværdien trækkes fra tallet der skal afrundes. Hvis man f.eks. vil afrunde de to sidste tal i 123, kan modulus bruges ved at tage 123 % 100, der vil give 23 til rest. Denne rest trækkes nu fra starttallet , hvilket giver 100, og man har nu fået den ønskede afrunding. Der vil dog altid runde ned, hvilket kan give et forkert billede. 30

33 Analyse og design For også at kunne runde op, kan man benytte den indbyggede metode, ved først at flytte kommaet i tallet der skal afrundes, x pladser til venstre. Derved fås et kommatal, der kan afrundes, for bagefter at flytte kommaet tilbage igen. På den måde vil man få afrundet cifrene før kommaet. Kommaet kan flyttes ved at opløfte ti i antallet af cifre der skal afrundes. Dette resultat kan nu bruges til at flytte kommaet det rigtige antal cifre frem og tilbage. Hvis 123 bruges som eksempel igen og vil afrunde to cifre, vil man få 100 ved at opløfte 10 med / 100 vil give 1,23, som derefter kan afrundes til 1,0, med den indbyggede afrundingsmetode. Når der derefter ganges med de 100, vil det rigtige resultat blive 100.(13) Sum SUM bliver som beskrevet brugt til at beregne summen af flere felter. Da det implementerede system, ikke vil blive bygget op som et regneark, hvor felterne ligger side om side, men derimod som objekter, der vil blive gemt i et array, kan funktionen SUM ikke overføres direkte. I lvs bliver sum for eksempel brugt til at beregne den samlede værdi for bebos bygninger, i hver ejendom. For at kunne lægge disse værdier sammen, er det først og fremmest nødvendigt at værdierne findes. Da der i forvejen skal laves en metode til at lægge flere værdier sammen 1, er der ingen grund til at lave dette igen. I stedet skal der laves en metode, der fortolker SUM begrebet, og returnerer et begreb der er forståeligt. Hvis arrayet der skal laves en sum af, er instantieret, skal der returneres en streng der angiver summen af samtlige værdier. Er arrayet endnu ikke instantieret, kan sum udtrykket ikke simplificeres, og input værdien skal returneres, for at blive simplificeret senere. Hvis f.eks. bebosværdien i ejendom 1 skal beregnes ud fra boligværdien for samtlige bebosejendomme, skal input udformes således: ejendomme[1].bebosvaerdi = sum(ejendomme[1].bebosejendomme.boligvaerdi) SUM parseren skal nu finde ud af hvor mange bebosejendomme der findes i den omtalte ejendom, og derefter løbe arrayet igennem, indtil alle elementerne er taget med i beregningen. Den returnerede værdi skal se således ud: ejendomme[1].bebosejendomme[1].boligvaerdi + + ejendomme[1].bebosejendomme[n].boligvaerdi 1 Denne metode vil blive beskrevet i

34 Analyse og design Er der tale om bebosejendomme vil resultatet således være: ejendomme[1].bebosvaerdi = ejendomme[1].bebosejendomme[1].boligvaerdi + ejendomme[1].bebosejendomme[2].boligvaerdi Efter værdien er returneret, er det nu op til parseren, at få analyseret og simplificeret strengen. Ligesom AFRUND metoden vil SUM fungere som en intern metode. Denne metode skal dog have et array som input, mens AFRUND skal have et tal. 2.7 Arrays Arrays skal kunne oprettes, og først instantieres senere, og de skal kunne instantieres samtidig med at de oprettes. Grunden til at begge dele skal være muligt, er at det ikke altid vides hvor mange objekter der skal være i et array. Ved først at lave en oprett af arrayet, og senere instantiere det, er man ikke tvunget til maksimalt at have x antal objekter. Programmet er dermed mere fleksibelt, ved ikke at skulle fastlægge størrn af arrays ved start. Dette er nødvendigt hvis en klasse skal indeholde et array, hvor antallet ikke kendes fra starten. Hvis antallet ikke er kendt, vil klassen ikke kunne oprettes, hvis arrayet skal instantieres med det samme. Dette undgås dog ved at oprettn sker, samtidig med oprettn af klassen, mens instantiering vil foregå senere. Hvis man vil undgå at skulle instantiere et array, kan det implementeres ved at når et array oprettes, er det tomt. Objekter kan derefter løbende tilføjes, når der er brug for dem. Hvis f.eks. objekt nummer to i et tomt array skal bruges, vil der blive oprettet to elementer i arrayet. Skal objekt nummer tre senere bruges, tilføjes et ekstra objekt til arrayet. Men da der kan være for loops der bruger arrays, til at løbe alle objekterne igennem, må for loopet kun udføres når arrayet er instantieret. Muligheden med at tilføje elementer til arrayet løbende, er derfor ikke en mulighed. For at opbevare arrays, benyttes dictionaries. Da man ikke umiddelbart kan se forskel på et oprettet array og et instantieret array, skal der bruges to dictionaries. Da det kan forekomme, at der ikke skal være nogen objekter i et array, eller at der kun skal være et objekt, er det nødvendigt at kunne se om et array er instantieret eller ej. Ved at have et dictionary til arrays der er oprettet, og et til arrays der er instantieret, kan man se om arrayet er færdig oprettet, og kan derved begynde at bruge objekterne i arrayet. Da der som beskrevet ikke er en copy-constructor i c#, skal der laves en metode, der tillader kopiering af de objekter der bruges i et array. Eftersom et array kan være oprettet uden at være instantieret, skal der, når der oprettes et array, findes ud af om det er tale om en oprett, instantiering eller begge dele. Derefter skal navnet på arrayet findes, ligesom objekterne der skal være i arrayet og 32

35 Analyse og design størrn på arrayet skal findes. Objektet der skal være i arrayet kan være af typen variabel eller klasse. Skal arrayet gemmes i en klasse, skal klasse objektet ligeledes findes. Ved at have objektet med, under oprettn af arrayet, kan arrayet efter oprettn, indsættes direkte i objektet. Er der ikke et klasseobjekt, skal arrayet oprettes i hovedklassen. Er størrn på arrayet ikke sat, er der tale om en oprett, uden instantiering. Instantieres et array fjernes det fra tabellen der indeholder oprettede arrays, og flyttes over i tabellen med instantierede arrays. 2.8 If-statements Der er som beskrevet i afsnittet Regler der er brugt i landbrugsvurderingssystemet brugt forskellige if-statements, til sammenligning af værdier. Det implementerede system skal ligeledes understøtte de samme if-statements. En if-statement skal kunne foretage sammenligninger udfra følgende operatorer: lig med = større end > større end eller lig med >= mindre end < mindre end eller lig med <= forskellig fra!= Der er brugt indlejrede if-statements i regnearkene, da de er bygget op, så det er nødvendigt at have flere it-statements i samme celle, hvis flere krav skal undersøges. Det skal derfor være muligt at undersøge om flere krav er opfyldt ved at tillade brugen af konjunktions og flere krav, i en if-statement. Er et krav ikke opfyldt, skal en anden handling muligvis udføres i stedet for. En if- syntaks er derfor nødvendig, for at kunne udføre en given handling, hvis første kriterie ikke er opfyldt, men andet eller tredje kriterie er opfyldt. Til undersøg af om en if-statement er opfyldt, laves en if-parser, der kan analysere en if-statement. En if-statement er efterfulgt af nogle forudsægninger, der hvis de er sande skal udføres. If-statement skal derfor splittes op, således at data kan valideres. Er der tale om flere forudsætninger skal alle forudsætninger muligvis undersøges. Er der tale om flere forudsætninger hvor alle skal være opfyldt, skal forudsætningerne undersøges en efter en. Er en af forudsætningerne falske, skal resten ikke undersøges, da udtrykket vil være falsk. Hvis kun en forudsætning skal være opfyldt er det omvendt. Her gælder at hvis en forudsætning er sand, vil hele udtrykket være sandt, og resten behøves ikke at blive undersøgt. Er en statement fundet sand, skal koden i if-statement udføres. De næste linier kode skal derfor løbes igennem, og gemmes, så de kan sendes igennem parseren. Kommer der en linie indeholdende if, eller end if, er der ikke mere kode der skal udføres, 33

36 Analyse og design og resten af linjener i if-statement, kan kasseres. Kan nogle af forudsætningerne til ifstatementen ikke undersøges, pga. variabler der endnu ikke har fået en værdi, skal parseren stoppe, og if-statementen skal først undersøges senere. Er nogle forudsætninger undersøgt, er det ikke nødvendigt at undersøge disse igen, men kun de resterende forudsætninger. Er en statement falsk, skal de næste linier ikke bruges, og løbes derfor igennem, uden at gemme dem. Findes en if statement skal den i stedet undersøges. Hvis if-parseren kommer til en, skal koden altid udføres, hvis de forrige statements har været falske. Til validering af om en forudsætning er sand, laves en hjælpemetode der kun tager forudsætningen som input. Er der tale om flere krav, kan de splittes op, og metoden kan kaldes rekursivt, for derved at få undersøgt alle forudsætningerne. If-parseren tager ikke stilling til den kode der skal udføres. Den vil i stedet gemme koden, som senere vil blive analyseret af parseren. Måden nestede if-statements er brugt i lvs, er at hvis en beting er sand, kan en anden if-statement kaldes. Dette løses her ved at der kan være flere betingr til en statement. Skal det være muligt, at lave nestede if-statements, skal der bruges en tæller, der ser at if-parseren møder en ny if-statement. Er dette tilfældet, skal den møde en end if, før den er tilbage i den if-statement, der er ved at blive undersøgt. Dette er dog uden for scope af denne opgave, da det ikke vil blive brugt. Da en beting kan bestå af konstanter, ligesom den kan bestå af variabler, vil der blive lavet en simplificeringsmetode, der simplificerer den enkelte beting der undersøges. En if-statement vil ikke optræde i deklarationen af et klasseobjekt, men findes i reglerne der beskriver hvilke handlinger der skal udføres. 2.9 For-loop For at kunne lave samme beregning på flere variabler i et array, skal der laves en metode der kan analysere indholdet i et for-loop, og sørge for, at beregningerne sker for samtlige objekter. For-loopet skal kunne løbe et array igennem, og lave den samme handling for en bestemt variabel i hvert array. For-loopet skal derfor holde styr på navnet på arrayet, typen der skal løbes igennem, og forkortn for variablen. Et for-loop kan f.eks. se således ud: for Ejendom ej in ejendomme ej.postnummer = 2800 end for Arrayet der skal løbes igennem, vil i dette tilfælde hedde ejendomme, og forkortn vil være ej. For-loopet skal derfor bytte ej. ud med navnet på arrayet, samt 34

37 Analyse og design indeksværdien, således at postnummeret for samtlige ejendomme i arrayet, vil blive tildelt samme værdi. I stedet for en konstantværdi, kan der være tale om en beregning der inkluderer forskellige variabler, eller et metodekald. Indeholder navnet på arrayet et., vil arrayet findes i et objekt. Det vil her foregå på samme måde. En ting der er vigtig, for at for-loopet vil virke korrekt, er at arrayet er instantieret. Før et for-loop løbes igennem, skal det derfor undersøges, om arrayet er instantieret. Er arrayet endnu ikke instantieret, skal for-loopet ikke løbes igennem endnu. Er arrayet instantieret, udføres for-loopet. Er der brugt variabler i loopet der ikke er oprettet endnu, eller objekter der ikke findes, vil for-loopet stadigvæk løbe antallet af objekter igennem, da for loopet ikke udfører selve koden. Den står kun for at gøre den forståelig for parseren. Ligesom med if-statements, skal for-loopet ikke laves i deklarationen af et klasseobjekt, men sammen med de andre regler. Når kaldenavnet skal skiftes ud, løbes alle linjerne i for-loopet igennem, indtil end for findes og arrayet er slut. Er der tale om et indlejret for-loop, altså et for-loop, i et andet for loop, er det nødvendigt at tælle om andre for-loops optræder. En tæller skal derfor holde styr på hvor mange for-loops der findes, og ligeledes hvor mange end for der findes. Finder parseren et for-loop, og når til end for, er der derfor flere linjer der skal udføres, da end for, hører til det indlejrede for-loop Tildeling af værdier Når der skal tildeles værdi til en variabel, vil der være en ligning hvor venstresiden består af variablen og højresiden skal ses som et resultat, der skal bruges som værdi til variablen. Venstresiden kan udover navnet, også indeholde navnet på et objekt, eller array, hvor variablen er gemt. Det vil sige, hvis variablen er gemt i en klasse, er venstre siden lig med navnet på objektet af klassen, efterfulgt af navnet på variablen. Resultatet der skal bruges som værdi til variablen kan være direkte tilskrivning, eller det kan være værdien af en anden variabel. Variablen kan ligeledes ligge i en dictionary og den kan ligge i et andet objekt. Ydermere kan resultatet skulle findes fra et regnestykke. Til at finde resultatet og finde ud af om det er gyldigt, skal der laves en metode der finder variablen, ud fra venstresiden af ligningen. Den skal derefter finde resultatet ud fra højresiden. Er resultatet en gyldig værdi, skal den gemmes i variablen, ellers skal både venstresiden og højresiden gemmes, så de kan parses senere, hvor der måske kan dannes et gyldigt resultat. Skal resultatet beregnes ud fra flere parametre, kan det simplificeres, så alle værdierne ikke skal hentes igen. Når værdien simplificeres, skal det undersøges hvilken type variabel der er tale om. Hvis det er en talvariabel, skal det undersøges, om der er matematiske operatorer i værdien, da den i så fald skal igennem udregningsmetoden. 35

38 Analyse og design 2.11 Udregning Hvis værdien der skal tildeles en variabel skal være et tal og indeholder matematiske operatorer som +, -, * og /, er det et udtryk der skal beregnes. Hertil skal laves en metode, der kan finde resultatet. Syntaksmæssigt er det forskelligt om man skriver en formel med eller uden mellem rum, men det skal betyde det samme, f.eks. er a+b = a + b. Til at dele regneudtrykket op, kan String.Split metoden benyttes. Ved split-metoden, forsvinder den separator man vælger at bruge. Det vil derfor ikke være muligt at splitte på alle operatorer på en gang, da det er nødvendigt at vide hvilken plads de forskellige operatorer har. Split-metoden kan dog bruges ved først at splitte alle leddene op ved plus separatoren, og derefter undersøge for minus osv. Ved at splitte udtrykket fuldstændigt op, kan man derfor beregne alle udtryk, for til sidst at lægge dem sammen. Men da nogle operatorer er stærkere end andre operatorer, i den forstand at de skal udregnes først, er rækkefølgen operatorerne står i, vigtig for resultatet. Split metoden på operatorerne kan derfor kun benyttes hvis et regneudtryk udelukkende består af minus og plus operatorer. En anden mulighed er at løbe hele udtrykket igennem, char for char, og stoppe når man kommer til en operator. Udtrykket kan løbes igennem både forfra og bagfra. Regner man udtrykket bagfra, skal man dog huske at tage højde for division efterfulgt af multiplikation. Løber man f.eks. ind i 10/5*2, kan man ikke udregne 5*2 først, da det vil give et forkert resultat. Regner man udtrykket forfra, skal man tage højde for plus og minus, da man ved * 5 ikke kan udregne først, da det ville give 20, og ikke 22, som er det rigtige resultat. Under beregningen skal regnestykket deles så meget som muligt. Kan det ikke deles ydereligere op, skal der returneres et tal. Er det en variabel, kan det ske, at den ikke er sat endnu, og der kan derfor ikke komme et resultat, før variablen har fået en værdi Eksempel på reducering Metoden der fortolker regneudtrykket, løber udtrykket igennem, ved hjælp af en tæller, der holder styr på hvor operatoren er. Finder den en + eller - operator kan udregningen fortsætte, og formlen deles op, ved den fundne operator. Findes en * eller / operator, fortsættes der, og der deles først ved næste operator. Nedenunder ses et eksempel med både + - og - -operatoren. Ved at dele op omkring operatoren, kan udtrykket reduceres. Det er selvfølgelig nødvendigt at undersøge om der skulle være flere operatorer i udtrykket, end den der er fundet. Er der ikke flere, kan de to led lægges til eller trækkes fra hinanden. 36

39 Analyse og design I Tabel 1 vises et eksempel på udregning med + operatoren. Tælleren finder en + operator på plads to, hvorefter der deles op i part 1 og part 2. Da de ikke indeholder flere operatorer, undersøges det om begge er et tal. Er det tal, lægges de sammen og returneres. Er kun den ene værdi et tal, returneres den som et tal, mens den anden returneres, som input, og der vil blive undersøgt om hele udtrykket kan beregnes senere. + Del Part 1 Part 2 Formel Index Counter Tabel 1 - eksempel med "+" item Tabel 2 viser et eksempel med - operatoren. På samme måde som med + operatoren, deles der omkring minus, hvor efter part 1 og part 2 udregnes, hvorefter de til sidst trækkes fra hinanden. - Del Part 1 Part 2 Formel 2-3 Index Counter Tabel 2 - eksempel med "-" item Er der tale om en * - eller / -operator, er det nødvendigt med en tæller mere, da udtrykket ikke på samme måde kan deles op i venstre og højre side omkring operatoren.. Ved at huske placeringen til operatoren, kan der søges videre efter næste operator. Hvis der er flere operatorer, skal der også deles ved næste operator, hvorefter udtrykket kan beregnes. Grunden til, at det er nødvendigt at finde den næste operator, er at den resterende del af udtrykket, i nogle tilfælde, skal udregnes først. Tabel 3 viser et eksempel på dette. Der findes først en operator på plads 2, hvorefter der søges videre og findes en ny operator på plads 6. Da operatoren på plads 3 er *, skal udtrykket til venstre siden for + operatoren udregnes først, og ikke som i forrige eksempel, hvor hele højresiden for første operator udregnes. Ville højre siden i dette tilfælde være blevet beregnet først, ville udtrykket blive reduceret til 2*7, som ville være det forkerte resultat. 37

40 Analyse og design * Del Part 1 Part 2 Part 3 Formel 2 * Index Counter item place Tabel 3 - eksempel med "+" og "*" Hvis der er parenteser i formlen, er det nødvendigt at regne alt inde i parentesen først. Efter udtrykket i parentesen er udregnet, vil det blive erstattet af udregningen og beregningen kan fortsætte. Ved at undersøge parenteser før der undersøges for operatorer, vil indholdet fra parentesen kunne udregnes ved at kalde sig selv rekursivt. Er der en startparentes, er det nødvendigt at finde den næste slutparentes. Kommer der en startparentes mere, inden slut parentesen, er det nødvendigt at finde den tilhørende slutparentes, til den nye startparentes først, og regne dette udtryk. parenteser Del Part 1 Part 2 Part 3 Formel 2 * ( ) / 2 Index Counter item place Tabel 4 - eksempel med parenteser I Tabel 4 vises et eksempel på et regneudtryk med parenteser. Parenteserne bliver fundet først, hvor efter part 2 bliver beregnet. Det vil reducere udtrykket som følger: 2 (6 + 4)/2 = 2 10/2 = 20/2 = 10 Ved hjælp af en metode der først leder efter parenteser, og derefter bruger to tællere til at finde operatorer med, vil det være muligt at reducere regneudtrykkene, systemet kan komme ud for. Der findes assemblies der kan udregne resultatet af et udtryk, gemt i en streng. Men da en værdi kan være gemt i en variabel, vil det ikke være muligt at benytte disse, og det er derfor nødvendigt at implementere en metode, der kan lave udregninger, hvor variabelnavne skal erstattes med værdier. 38

41 Analyse og design 2.12 Lagring af data For at kunne bruge hele systemet, skal data gemmes, da man ikke er interesseret i at skulle indtaste al data igen. Til lagring af data, laves en klasse, der kan løbe alle objekterne igennem. Ved at give den de tre dictionaries, der opbevarer data, henholdsvis med variabler, klasser og arrays, kan alle dictionaries løbes igennem, og data kan gemmes til en fil. Fra den dictionary der indeholder variablerne, kan navnene på alle variablerne hentes, da navnet på variablen bruges som nøgle i en dictionary. Alle navnene kan på denne måde gemmes i filen, sammen med en evt. tilknyttet værdi. Derefter kan alle arrays løbes igennem, hvor navnet ligeledes er brugt som nøgle. Her kan alle værdierne i arrayet løbes igennem ved hjælp af et for-loop, så navnet, sammen med indeksværdien, kan bruges til at gemme værdien. Til sidst skal alle instanserne af klasserne løbes igennem. Dette kan foregå ved at tage et objekt af gangen. Da hver objekt kan indeholde instanser af andre klasser, variabler og arrays, skal disse også løbes igennem og gemmes. Er der oprettet instanser af klasser i nogle af objekterne kan metoden til at gemme data med, kalde sig selv rekursivt, og på den måde sørge for at få gemt alt data. Ved at gemme på samme måde, som data indlæses, vil filen senere kunne bruges, til at indlæse data igen. Betingrne og beskrivn til en variabel, vil ikke blive gemt, da de vil kunne indlæses igen, sammen med reglerne Parser For at implementere den beskrevne funktionalitet, skal der laves en parser, der fortolker data. Da parseren ikke vil stå for at fortolke det hele, vil der være nogle hjælpemetoder, som parseren bruger, i forbind med fortolkning af data. Som beskrevet kan parseren komme ud for oprett, eller regler, angående handlinger der skal udføres. Hvis parseren fortolker data, der drejer sig om en oprett, vil opbygningen se ud som vist på Figur

42 Analyse og design Parser CreateVar CreateMethod CreateClass CreateArrayVar CreateStringVar CreateArrayObject CreateDoubleVar Figur 13 - parser til oprett Parseren kan komme ud for tre forskellige slags oprettr. Det kan være oprett af en variabel, en metode, eller en klasse. Er det oprett af en variabel, skal parseren sende inputtet videre til CreateVar, der skal tage sig af resten af oprettn, af variablen. Denne metode skal se om variablen der skal oprettes skal have tildelt en værdi samtidig med oprettn. Hvis det er tilfældet, gemmes værdien, hvorefter oprettn af variablen sker. Til oprett af variablen, skal laves to metoder, til henholdsvis oprettese af en double variabel og en string variabel. Efter variablen er oprettet, tildeles en eventuel værdi til variablen hvis den er gyldig. Skal der oprettes et array af variabler, er det ligeledes CreateVar der står for dette. De samme metoder skal bruges til oprett af selve variablen, hvorefter variablen sendes videre til en metode, der står for at oprette et array, med det rigtige antal variabler. Er der i stedet tale om regler der ikke drejer sig om oprett, men om kode der skal fortolkes, vil parseren kalde nogle andre metoder. Opbygningen at dette kan ses på Figur

43 Analyse og design Parser ParseForSentence ParseIfSentence ParseSumSentence ParseLine IsSentenceTrue CreateArrayObject Figur 14 - parserer til fortolkning af regler Får parseren noget data der skal fortolkes, benyttes en række metoder, til fortolkningen afhængig af hvilken funktion der er tale om. Hvis det er et for-loop, er der en metode, til fortolkningen af dette. Er det i stedet en if-statement der skal undersøges, skal der laves en ParseIfSentence metode til dette formål. If-Parseren der skal håndtere en ifstatement, skal have en hjælpemetode, der skal bruges, til at se om kravene er opfyldt. Ved at lægge logikken til undersøg af, om en sætning er sand, ud i en metode for sig selv, kan den kalde sig selv rekursivt, hvis der er flere krav der skal undersøges. If- Parseren skal derfor ikke have nogen logik der kan se om krav er opfyldt. Den skal i stedet hive krav/kravene ud, og sende videre til IsSentenceTrue der undersøger dem. Hvis IsSentenceTrue returnerer sandt eller falsk, skal parseren gemme den kode, der nu skal fortolkes, og kassere resten. Kan kravene ikke undersøges endnu, skal al koden gemmes, så den eventuelt kan udføres senere. Hvis parseren får data ind der skal finde summen af en række variabler, kaldes ParseSumSentence. Den skal have logikken, der løber et array igennem, og laver en formel, der beregner summen af alle variablerne. Er det ikke nogle af de beskrevne funktioner, kaldes ParseLine, der undersøger om det er et array der skal instantieres, eller om det er tildeling af en værdi. Skal et array instantieres kaldes metoden CreateArrayObject, med antallet af objekter der skal bruges samt objektet, der skal instantieres i arrayet. Er det ikke et array, er det tildeling af værdi. ParseLine skal derfor finde ud af hvor en variabel er, og derefter beregne værdien der skal gemmes. Til at finde værdien laves en Simplify metode, der simplificerer udtrykket, så godt det er muligt. Den bruger Calc metoden til at lave beregninger hvis det er nødvendigt. Simplify skal returnere udtrykket, enten i form af et resultat, eller så simplificeret som muligt. 41

44 Analyse og design 2.14 Klassediagram Figur 15 klassediagram På klassediagrammet i Figur 15 ses hvilke klasser der bruges til at implementere systemet. Det består af fem klasser. LVS der er hovedklassen, kan bruge en eller flere instanser af Klasse, ligesom den kan bruge en eller flere instanser af Var. Klasse kan ligeledes bruge en eller flere instanser af Var og Klasse. Save og Metode bruges kun af LVS klassen, der vil oprette en instans af begge klasser Opsummering I Ovenstående afsnit er det vist, hvilke regler der er brugt i landbrugsvurderingssystemet, og hvad der ligger til bunds for, at en vurdering er mulig. Det er derefter blevet vist, hvordan ark fra Excel, kan ses som objekter og dermed hvordan lvs kan bygges op fra et objektorienteret synspunkt. 42

45 Analyse og design Ud fra forudsætningerne for at lave en vurdering, er det blevet gennemgået, hvad der skal kunne oprettes i et regelbaseret system, ligesom det er gennemgået, hvordan værdier skal kunne tildeles og gemmes. Det er vist hvordan reglerne der er brugt til lvs, kan implementeres således, at samme funktionalitet vil være mulig i et regelbaseret system. Til sidst er det gennemgået hvordan parseren der skal fortolke data til systemet kan bygges op, samt hvilke klasser der er nødvendige for at implementere systemet. 43

46

47 3 GRAMMATIK I dette afsnit vil der komme en beskriv af hvordan reglerne til programmet skal se ud, og et eksempel hvor reglerne bliver brugt. Ved hjælp af Backus-Naur form (BNF) kan grammatikken til reglerne beskrives. Dette gør det nemmere at forstå den syntaks der skal bruges, når reglerne skal bruges, til at lave deklarationerne i programmet.(14)(15) Til at beskrive grammatikken bruges følgende notationer: < > markerer et begreb, der ikke er beskrevet til bunds. bruges som "eller". ::= læses som "består af". For at kunne beskrive grammatikken yderligere er BNF blevet udvidet til extended BNF (EBNF), hvor disse notationer også vil blive brugt: [... ] Firkantede parenteser anvendes til at angive noget, der kan forekomme nul eller én gang.... Krøllede parenteser anvendes til at angive noget, der kan forekomme nul, én eller flere gange. (... ) Almindelige parenteser bruges til gruppering. 3.1 EBNF <number> ::= 0-9 < number >< number > <string > ::= <string character> <string> <string character> <string character> ::= <input character> / " <var> ::= <name> <name> ::= a z A Z <name><name> <comparison operator> ::= < > >= <= =!= <operator> ::= +, -, *, / <conjunction > ::= & <type> ::= <name> double string boolean <file> ::= <decl> < rule> <decl> ::= <vardecl> <classdecl> <methdecl> <arraydecl> <vardecl> ::= <stringdecl> <doubledecl> <doubledecl> ::= double <name> < doubleparameter >[ = < expression >] 45

48 Grammatik ; <name> < doubleparameter >[ = < expression > < doubleparameter > ::= [ [length: < number > ] ] [ [exp: <string characters> ] ] [ [list: < doublevalue >, < doublevalue > ] ] [ [min: < doublevalue > ] ] [ [max: < doublevalue > ] ] [ [ <doublevalue > : < doublevalue > ] ] <stringdecl> ::= string <name> <stringparameter> [ = <expression> ] ; <name> <stringparameter> [ = <expression> ] <stringparameter> ::= [ [length: < number > ] ] [ [exp: <string characters > ] ] [ [list: <string characters>, <string characters> ] ] <classdecl> ::= class <name> <vardecl> <arraydecl> <name><name> end class <arraydecl> ::= double[] <name> < doubleparameter > string[] <name> <stringparameter> <name> [] <name> [] = <name> [ <expression> ] <expression> ::= <var> <string > <doublevalue> < expression > [ < expression> ] < expression >. < expression > < expression >. <name> < expression ><operator>< expression > <name> ( <string> ) <doublevalue> ::= < number > [, <number >] <methdecl> ::= metode <name> <string> [<string>] <rule> ::= <equation> <if-statement> <for-loop> <equation> ::=<var> = < expression > <if-statement> ::= if < expression > <comparison operator> < expression > <conjunction> < expression ><comparison operator> < expression > then <equation> <for-loop> 46

49 Grammatik if < expression > <comparison operator> < expression > <conjunction> < expression ><comparison operator> < expression > then <equation> <for-loop> [ <equation> <for-loop>] endif <for-loop> ::= for <navn> <navn> in < expression > (<rule>) end for 3.2 Uddybning af grammatikken I dette afsnit, vil der komme en uddybning I hvordan grammatikken skal forstås, og gives eksempler på brug af grammatikken Double En doubledeklaration består af double efterfulgt af navn og parametre, eller double navn parametre efterfulgt af flere deklarationer adskilt af ;. En doubledeklaration kan slutte af med = efterfulgt af en værdi. I Tabel 5 vises hvilke parametre der er gyldige for en double samt en beskriv af parameteren. Parametre til double [ [length: < number > ] [ [exp: <string characters> ] ] [ [list: <doublevalue> ; < doublevalue > ] ] [ [min: < doublevalue > ] ] [ [max: < doublevalue > ] ] [ [ <doublevalue > : < doublevalue > ] ] Beskriv double variablen skal bestå af præcis <number> antal cifre Der er en forklaring til variablen bestående af tekst. Variablen kan kun sættes lig med de tal der optræder på en given liste, som kan bestå af et enkelt tal, eller flere tal adskilt af semikolon. Variablen kan minimum have den definerede værdi Variablen kan højst have den definerede værdi Variablens værdi skal være i det definerede interval, inkl. de to værdier. Tabel 5 - double parametre Double deklarationer kan se ud som følger: 47

50 Grammatik double antalejendomme [min:1][max:5] double antalboliger; antalbygninger double omregningsfaktor = Streng En streng deklaration består af string efterfulgt af navnet. Parametre kan sættes til en streng variabel, og der kan være knyttet en værdi til strengen. Ligesom med double variablen kan der også oprettes flere strenge i samme linje adskilt af ;. Parametre til string [ [length: < number > ] [ [exp: < string characters > ] ] [ [list: < string characters > ; < string characters > ] ] Beskriv Variablen skal bestå af præcis <number> antal tegn Der er en forklaring til variablen bestående af tekst. Variablen kan kun sættes lig med de strenge der optræder på en given liste, som kan bestå af en enkel streng, eller flere strenge adskilt af ;. Tabel 6 - string parametre En streng deklaration kan se således ud: string ejendomnavn [exp:ejendommens navn] string adresse [exp:ejendommens adresse]; ejendomstype [liste:"landbrug","skovbrug"] Klasse Oprett af en klasse består af class efterfulgt af navnet på klassen. Der vil derefter komme et antal variabel- og arraydeklarationer, eller initialisering af klasser. Til sidst sluttes af med end class. Deklarering af en klasse kan se således ud: 48

51 Grammatik class Ejendom String navn String adresse BygningBebo[] bebo BygningBebo ekstrabolig end class class BygningBebo streng anvend end class Array Arrays oprettes ved først at angive typen på arrayet, der kan være double, string" og navnet på en klasse. Arrays kan deklareres således: string[] navne double[] navne [min:3.2] = double[13] Ejendom[] ejendomme = new Ejendom[2] Hvor Ejendom er en klasse der er deklareret et andet sted Metode En metode oprettes med metode efterfulgt af navnet på metoden. Stien til placeringen af filen der indeholder metoden skal derefter angives. Deklarationen kan afsluttes med at angive sproget koden er implementeret i. En metode kan deklareres sådan: metode getvurderingscenter "metoder\\getvurderingscenter.txt" metode getby "metoder\\getby.txt" csharp Equation Equations kan udformes på mange måder. Fælles for dem er at de skal bruges til at tildele værdier til variabler. Et udtryk kan være en anden variabel, en streng, en doubleværdi. Det kan ligeledes være en værdi der skal hentes fra en variabel i et array, og en variabel gemt i et klasseobjekt. Da der skal kunne laves beregninger, kan et udtryk ligeledes være et udtryk der er lagt sammen med et andet udtryk. 49

52 Grammatik Her ses nogle eksempler på hvordan et udtryk kan se ud: a = 3.12 b = ejendomme[1].postnummer c = bygning.nummer d = a + b * c e = ROUND(a,2) Hvor a sættes lig med en doubleværdi. B sættes lig med postnummeret der findes i ejendomme[1]. C sættes lig med nummer der er oprettet i klassen bygning. D er derefter lig med de to første udtryk lagt sammen, multipliceret med det tredje udtryk. Til sidst ses et eksempel hvor e sættes lig med det første udtryk, der afrundes ved hjælp af den indbyggede ROUND metode If-statement En if-statement starter altid med if efterfulgt af et udtryk, en comparison operator og et udtryk. Den kan være efterfulgt af flere sammensætninger efterfulgt af yderligere udtryk der skal sammenlignes. Linjen afsluttes med then. Derefter kan der komme flere equations og for-loops. Der kan nu komme nul, en eller flere if, efterfulgt af flere udtryk der skal sammenlignes, som også altid skal ende med then. Herefter kan der ligeledes komme flere equations og for-loops. Til sidst i en if-statement kan der komme en, efterfulgt af equations og for-loops. If-statementen vil nu slutte af med end if. Her ses et eksempel på en if-statement: if antalboligertilbebo = 0 then vaerdibebo = 0 if antalboligertilbebo = 1 vaerdibebo = 1 postnummer = 3790 postnummer = 2800 kommune = getkommune(postnummer) end if I eksemplet undersøges antallet af boliger til bebo. Er antallet lig nul, sættes værdien af bebon til 1. Er der imidlertid 1 bolig til bebo sættes værdien til 1, og postnummeret til Er der flere boliger til bebo sættes postnummeret til 2800, 50

53 Grammatik og kommunen sættes derefter til outputtet fra metoden getkommune der tager postnummeret som input For loop Et for-loop består af for efterfulgt af et navn, som er navnet på den type der skal gentages, efterfulgt af navnet, der er brugt som forkort på objektet. Derefter kommer in, som efterfulgt af et udtryk, der fortæller hvilket array der skal løbes igennem. Der kan nu komme nul, en eller flere regler som skal gentages for hvert objekt i arrayet. For loopet afsluttes med end for. Et for loop kan se således ud: for Ejendom ej in ejendomme ej.kommune = getkommune(ej.postnummer) end for Ovenstående for loop vil løbe ejendomme arrayet igennem, der indeholder typen Ejendom. For hver Ejendom skal ej.kommune sættes lig med outputtet fra getkommune der får ej.postnummer som input. For loopet løbes igennem, hvor ej erstattes af navnet på arrayet samt indeks nummer. 3.3 Opsummering I ovenstående afsnit er reglerne til systemet blevet gennemgået. Det er vist hvordan syntaksen for opsætning af regler og tildeling af værdier ser ud. Derudover er reglerne beskrevet og der er givet eksempler på hvordan de skal bruges. 51

54

55 4 IMPLEMENTERING I dette afsnit vil der være en detaljeret gennemgang af de vigtigste metoder implementeret i systemet. 4.1 Opbygning LVS klassen er hovedklassen, som står for indlæsning af regler. Da alle reglerne er gemt i en eller flere tekstfiler, samles disse filer først til en tekststreng, der derefter undersøges. De tekstfiler der skal bruges som input, tilføjes til en arraylist i konstruktøren i LVS. Alle filerne læses, og samles i en tekststreng. Tekststrengen sendes som input til parser metoden, der står for at analysere indholdet. Inden parser metoden kaldes, kopieres data til en anden tekst streng, der bruges til sammenligning med outputtet fra parseren. Så længe der er forskel på output, og det gemte data, er data blevet fortolket og simplificeret, og der kan måske simplificeres mere data. Når input og output data er ens, er der sket et gennemløb, uden simplificering har været muligt, og parseren kan derfor ikke behandle mere data. Alle reglerne er nu omsat til objekter, der er oprettet, og værdier til variablerne er gemt. Data skal gemmes, for at kunne se hvilke beregninger der er foretaget. Dette gøres med en instans af save klassen. Udover at gemme resultatet, gemmes input data efter hvert gennemløb. Det har ikke betydning for slut resultatet, men kan bruges, for at se hvordan simplificeringen foregår, og hvad parseren ikke kunne simplificere eller forstå. 4.2 Parser Parseren skal analysere alt data, som den får fra LVS. Parserens opgave er at videredirigere data, til de rigtige metoder, alt efter hvad den støder på, under analysen af input. Parseren bruger en StreamReader til at læse en linje ad gangen, og ser hvad den indeholder. Indeholder den en tom linje, eller en kommentar, springer den linjen over og indlæser næste linje. Starter linjen med, double, string eller metode sendes input linjen videre, til henholdsvis CreateVar og CreateMethod der vil foretage oprettn. Indeholder linjen class er det oprett af en klasse. Her indlæses hele deklarationen af klasse oprettn. Oprettn af en klasse slutter med end class, så der indlæses linjer, indtil den findes. Deklareringen af klasseobjektet sendes videre til CreateClass, der fortolker indholdet heri. 53

56 Implementering Finder parseren en linje der starter med for er det et loop der skal analyseres. For loopet indlæses her, så det kan sendes videre til ParseForSentence, der kan fortolke et for-loop. Da indlejrede for loops kan forekomme, bruges en tæller, til at vise om der er indlejrede for-loops. Finder parseren end for, sendes de indlæste linjer til metoden der undersøger for-loopet, hvis tælleren er lig med nul. Er tælleren større end nul, er der tale om indlejrede for-loops, og parseren søger videre efter næste end for, indtil tælleren er nul. På denne måde, er der ikke begrænsninger for hvor mange indlejrede for-loops der kan forekomme. Kommer der en linje der indeholder if, sendes StreamReaderen med som parameter, til ParseIfSentence der står for at analysere indholdet af if-statements. Det er ikke nødvendigt med indlejrede if-statements, så her bruges ikke en tæller. Er det ikke en regel der skal undersøges i form af if-statement eller for loop, og er det ikke en oprett, sendes linjen videre til ParseInputLine der håndtere tildeling af værdier til variabler, samt initialisere objekter. 4.3 Variabler Til oprett af variabler bruges metoden CreateVar. Den kræver tre input parametre. Den første parameter er linjen fra parseren, der fortæller at der skal oprettes en variabel. Den indeholder navnet på variablen, og en evt. værdi. Derudover skal metoden, hvis variablen skal oprettes i en klasse, have et klasseobjekt som input. Da et klasseobjekt sendes med, hvis variablen skal gemmes, i et objekt, skal metoden ikke til at undersøge om en klasse eventuelt findes, da variablen kan tilføjes direkte til objektet. Metoden bruges til oprett af både string og double variabler, og er lavet, så den kan udvides til flere. En inputparameter er derfor nødvendig, for at fortælle hvilken type der skal oprettes. Hvis det er et array der skal oprettes, indeholder variabel navnet []. Dette fjernes, og variablen oprettes herefter på normal vis, indtil den skal gemmes, hvor en boolean er brugt, til at fortælle om variablen skal bruges i et array. Er det ikke et array, undersøges det om der skal oprettes flere variabler. Er der flere oprettr, er de adskilt af ;, som inputtet deles ved, og der oprettes et array, af de variabler der skal oprettes. For hver variabel der skal oprettes, bruges nu samme procedure. Inputtet består nu af variabel navnet, parametrene til variablen og værdien. Hvis der er en kommentar tilknyttet input linjen, fjernes denne, og inputtet deles op i to dele. Første del består nu af variabel navnet, og parametrene til variablen. Anden del består af værdien. Parametrene skilles herefter fra navnet, hvorefter en hjælpe metode til oprett af den rigtige type variabel kaldes, med parametrene til variablen. Der er lavet to metoder, den ene bruges hvis det er en double der skal oprettes, og den anden hvis det er en string. 54

57 Implementering Ideen bag metoderne til oprett af variablerne er den samme, men da det er forskellige egenskaber de skal indeholde, og dermed forskellige parametre, der sendes med, er det to forskellige metoder. Fælles er dog at de begge opretter en variabel, og sætter typen deri. Variabeltypen bruges, ligesom egenskaberne for variablen, når en værdi skal tildeles. Efter typen er sat, laves et strengarray, med samtlige parametre. Alle parametrene løbes nu igennem, og tilføjes til variablen en efter en. Ved double variabler kan der sættes minimum og maksimum værdier. Sættes de begge to, undersøges det at minimum værdien er mindre end maksimum værdien. Er en af parametrene til variablen en liste, laves der endnu et array ved oprettn, hvorefter samtlige værdier, tilføjes til variablen. Ved oprett af string variabler, benyttes endnu en hjælpe metode, der ser om alle værdierne i listen er string variabler, altså omkredset af gåseøjne. Når oprettn af variablen er færdig, returneres objektet til CreateVar metoden. Værdien simplificeres nu, ved hjælp af Simplify metoden der beskrives senere. Til sidst tilføjes variablen. Er der et klasseobjekt med som input parameter, tilføjes variablen til klassen, og værdien gemmes i variablen. Er der ikke noget klasseobjekt, kan det skulle bruges til et array i hovedklassen, eller en almindelig variabel. Er det et array, oprettes arrayet, og der tilføjes x antal variabler til arrayet ud fra indeks værdien. Skal den tilføjes som almindelig variabel, tilføjes den til vardictionary der indeholder alle variablerne, og hvis værdien er gyldig, gemmes den i variablen. Det kan dog være at værdien endnu ikke kan gemmes. Variabel navnet og værdien gemmes derfor i newinput strengen, der vil blive analyseret igen. På denne måde vil alle værdier der ikke kan tilføjes endnu, forsøges tilføjet igen, indtil data ikke kan simplificeres mere, og programmet er sikker på at værdien ikke bliver gyldig. 4.4 Klasser Til oprett af klasser tager metoden CreateClass, en tekststreng som input. Denne laves om til en stream, der ved hjælp af en StreamReader læser input, og analysere det. Første linje i input angiver navnet på klassen, der efterfølgende bruges til at undersøge om der findes en klasse med det samme navn. Hvis klassen findes, oprettes der ingenting, og metoden afsluttes. Findes der ikke en klasse, med det pågældende navn, skal der oprettes et klasseobjekt, som gemmes i finishclassdictionary. Det er her klasserne gemmes, som der senere kan oprettes instanser af. 55

58 Implementering if (finishclassdictionary.containskey(klassenavn)) Return false; klasse = new Klasser(); finishclassdictionary.add(klassenavn, klasse); Efter at have fået et klasseobjekt, begynder oprettn af indholdet i klassen. Skal der oprettes en variabel, genbruges CreateVar. Her sendes klasseobjektet med som input, så variablen kan tilføjes til klasse objektet. if (input.length >= 6 && input.substring(0, 6).Equals("double")) input = input.trimstart("double".tochararray()).trim(); result = CreateVar(input, klasse, typeof(double)); if (result.equals(false)) addlater += input + lineshift; Ligesom den almindelige parser, vil klassen ikke bruge kommentarer og tomme linjer, men vil gå videre til næste linje i oprettn. Er det ikke en variabel der skal oprettes, er der tale om oprett af en klasse. Der undersøges nu om det er et array af klasser der skal tilføjes, eller om det er en enkelt klasse. Skal det være et array af klasser, kaldes CreateArrayObject metoden, der sørger for oprettn af arrayet, ellers tilføjes klasseobjektet til klassen, der er ved at blive oprettet. Da klasserne ikke instantieres, men kun oprettes, er det ikke nødvendigt at klasserne findes i systemet, da det er et tomt klasseobjekt der oprettes. Først når de skal instantieres, er det nødvendigt at de findes. string classname = input.substring(0, input.indexof(' ')); string name = input.trimstart(classname.tochararray()).trim(); klasse.addclass(name, null); 56

59 Implementering 4.5 Metoder Til håndtering af oprett af metoder, samt dynamiske kald af metoder, der skal oprettes on the fly, er klassen Metoder implementeret. Denne klasse har følgende fire metoder CreateDll GetParametersForDll GetReturnTypeForDll RunDll Før en metode kan kaldes, skal den oprettes. Dette gøres ved hjælp af CreateDll, der står for at lave en assembly, der kan indlæses, når der er brug for den. Som input tager den navnet på metoden, sti til filen der indeholder metoden, samt sproget, metoden er kodet i. Er der ikke skrevet en sti, ledes der efter filen, i samme mappe, som programmet ligger i. Den assemly der oprettes, gemmes i mappen metoder. Hvis CodeDomProvideren understøtter sproget metoden er skrevet i, og filen findes, kompileres koden til en assembly, med samme navn, som metoden. Er der ingen fejl i resultatet, er metoden kompileret korrekt, og assembly en tilføjes til listen over metoder der kan kaldes. Skal en metode kaldes, skal parametrene sendes med. Det er derfor nødvendigt at vide hvilke parametre der skal bruges. Til at finde parametrene, indlæses den assembly, metoden ligger i, hvorefter der bruges en instans af MethodInfo til at hente information om metoden. Findes metoden hentes alle parametre fra metoden, og for hver ParameterInfo der findes, tilføjes den til et array med typer, der returneres. 57

60 Implementering Type[] typearray = assembly.gettypes(); foreach (Type type in typearray) MethodInfo mi = type.getmethod(nameofmethod); if (mi!= null) foreach (ParameterInfo parameterinfo in mi.getparameters()) //Debug.WriteLine(parameterInfo.ParameterType + " " + parameterinfo.name); parameters.add(parameterinfo); return parameters; Da en metode kan returnere forskellige parametre, er det nødvendigt, at den parameter der returneres kan bruges. På samme måde som input parametrene blev fundet, findes parameteren der returneres, ved at finde metoden og kalde ReturnType. Passer inputparametre til det metoden kræver og output parameteren passer til variablen kan metoden kaldes ved hjælp af RunDll. Den tager navnet på metoden der skal kaldes og en liste af objekter som input. Navnet bruges til at finde metoden i assembly'en, og objekterne er de input parametre metoden skal bruge. if (File.Exists(nameOfMethod + ".dll")) Assembly assembly = Assembly.LoadFrom(nameOfMethod + ".dll"); Type[] typearray = assembly.gettypes(); foreach (Type type in typearray) object classobject = Activator.CreateInstance(type); result = type.invokemember(nameofmethod, BindingFlags.Default BindingFlags.InvokeMethod, null, classobject, arguments); 58

61 Implementering Afrund ROUND er metoden, der står for afrunding. Den ses her: private double Round(double value, int antal) if (antal >= 0) return Math.Round(value, antal); double n = Math.Pow(10, -antal); return (Math.Round(value / n, 0) * n); Metoden tager værdien der skal afrundes og antallet af cifre der skal afrundes som input. I modsætning til den indbyggede afrundingsfunktion kan metoden afrunde foran og efter kommaet. Som det ses bruges den indbyggede Round hvis antallet af cifre er positivt cifrene til højre for kommaet der skal afrundes. Er antallet negativt flyttes kommaet først til venstre hvorefter den indbyggede Round kan bruges, for til sidst at flytte kommaet tilbage igen Sum Til at udføre SUM funktionen er parsesumsentence metoden implementeret. Dens opgave er at analysere input, og returnere et mere forståeligt output, til parser metoden. Ved at dele input op i mindre dele, kan det undersøges om arrayet som de pågældende værdier findes i, eksisterer. Eksisterer arrayet, skal størrn på det pågældende array findes, således at det rigtige antal værdier kan blive brugt til at finde den ønskede værdi. Det er ikke denne metodes opgave at se om variablerne findes, eller om de er tildelt en værdi. Det overlades til parseren. Den skal kun sørge for at løbe et array igennem, og returnere den rigtige formel til beregning af SUM. Klasse k = (Klasse)arrayDictionary[objectName][index - 1]; if (k.isarray(arrayname)) for (int i = 0; i < k.getarray(arrayname).count; i++) newinput += objectname + "[" + index + "]." + arrayname + "[" + (i + 1) + "]." + varname + "+"; newinput = newinput.trimend('+'); return newinput; 59

62 Implementering Her ses hvordan længden af arrayet bruges, til at tilføje det rigtige antal variabel navne til formlen. 4.6 Arrays Til oprett af arrays er der oprettet to metoder. CreateArrayObject og CreateArrayVar. Opbygningen af de to metoder er ens, bortset fra den ene inputparameter. De kræver fire inputparametre. Navnet på arrayet der skal oprettes, størrn på arrayet, objektet der skal tilføjes i arrayet, samt et klasseobjekt, hvis arrayet skal tilføjes en klasse. Først bliver et arraylist oprettet. Grunden til der er brugt et arraylist er at objekterne skal have en bestemt placering, og ligge i den rækkefølge de bliver tilføjet. Er størrn på arrayet sat til -1, skal arrayet kun oprettes, men ikke instantieres. Er størrn nul, skal arrayet være tomt. Er størrn større end nul, tilføjes x antal objekter til arrayet. //oprett af array ArrayList al = new ArrayList(); //instantiering af array if (arrayindex!= -1) for (int i = 0; i < arrayindex; i++) al.add(classtoadd.copy()); Arrayet bliver nu gemt. Er klasseobjektet som metoden får som inputparameter null, skal arrayet tilføjes til hovedklassen. Det undersøges nu om arrayet eksisterer i forvejen, både i tabellen for arrays der er oprettet, og arrays der er instantieret. Findes det ikke, tilføjes det, i henholdsvis temparraydictionary hvis array størrn er nul, og i ArrayDictionary hvis arraystørrn er større end nul, og arrayet derfor er instantieret. Hvis arrayet skal tilføjes en klasse, undersøges det om arrayet findes i forvejen, og tilføjes hvis det ikke gør. CreateArrayObject og CreateArrayVar kunne have været lavet i samme metode, ved at kræve et Objekt som input i stedet for henholdsvis Vars og Klasser. Havde dette været benyttet, skulle boxing bruges, til at finde ud af hvilket type objekt der var tale om, for derefter at kunne konvertere objektet til den rigtige type, og derefter indsætte i arrayet. 60

63 Implementering 4.7 If-statement Til at analysere it-statements, tager ParseIfSentence en streng der indeholder første linje af en if-statement, samt en StreamReader som input. If-parseren indlæser en linje af gangen, og er der tale om et udsagn der skal undersøges, bruges issentencetrue, til at undersøge om udsagnet er sandt eller falskt. Er et udsagn sandt, skal de følgende linjer, indtil if, eller end if udføres. Til dette formål bruges to while loops, der får input fra StreamReaderen indtil en af betingrne findes. Som det ses stopper det første while loop, hvis en af betingrne findes. Men er det ikke end if, skal yderligere linjer fra StreamReaderen løbes igennem, således at de ikke vil blive parset igen. Når end if findes, stoppes whileloopet, og if-parseren er færdig. Alle de linjer der skal udføres er nu tilføjet til newinput der automatisk vil blive analyseret i parseren. //udfører koden indtil if, eller endif while (!endif) if ((S.Length == 6 && S.Equals("end if")) (S.Length == 4 && S.Equals("")) (S.Length > 7 && S.Contains(" if"))) endif = true; break; newinput += S + lineshift; S = SR.ReadLine(); if (S == null) break; S = S.Trim(); while (endif) if (S.Length == 6 && S.Equals("end if")) break; S = SR.ReadLine(); if (S == null) break; S = S.Trim(); For at se om en statement er gyldig, bruges hjælpemetoden IsSentenceTrue, der tager udsagnet som input. Indeholder udsagnet &, deles det op, og metoden kalder sig selv rekursivt, indtil et af leddene er falsk, eller alle leddene er sande. Metoden simplificerer parametrene i udsagnet så meget som muligt. Da det ikke er sikkert, at alt kan undersøges, hvis variabler f.eks. ikke er oprettet, er det ikke muligt at returnere sand eller falsk. I stedet for en boolean, bruges en streng, der vil returnere sand, falsk, eller det simplificerede udtryk, der skal analyseres yderligere senere i forløbet. 61

64 Implementering Indeholder udsagnet ikke &, undersøges det i stedet for om den indeholder, hvor metoden kalder sig selv rekursivt indtil et udsagn er sandt, eller alle udsagn er falske. Når udsagnet skal undersøges yderligere, løbes strengen igennem bogstav for bogstav. Det er ikke muligt at bruge Streng.IndexOf, da der som beskrevet i analyse afsnittet, skal kunne undersøges for flere forskellige operatorer, og placeringen samtidig skal bruges. Der undersøges for om et tegn er lig med <, >,! og =. Hvis <, > eller! findes, undersøges ligeledes det næste tegn, for at se om det er næste tegn er =. Udsagnet deles nu på begge sider af operatoren, hvorefter simplificeringsmetoden benyttes til at få en forståelig værdi ud fra udtrykket. Hvis noget af en if-statement kan undersøges, men der derefter kommer nogle værdier, der endnu ikke er sat, vil resten af if-statement, ikke kunne undersøges endnu. Den skal derfor undersøges igen senere. De udsagn der er undersøgt, er pillet fra, og det er derfor kun den resterende del af if-statement der skal undersøges senere. newinput += "if " + ifsentence + " then" + lineshift; do S = SR.ReadLine(); if (S == null) break; S = S.Trim(); newinput += S + lineshift; while (!S.Equals("end if")); Den første linje skal være en if-statement, så den kan undersøges igen senere. Er første del af en if-statement undersøgt, og den er stoppet ved en -if, vil det alligevel blive gemt som en if-statement. Er nogle af ledene blevet analyseret, vil disse også være sorteret fra. 4.8 For loop Til analysering af et for-loop, er der lavet metoden ParseForSentence. Et for-loop, bruges når samme handling skal gentages for variablerne i et array af objektet. F.eks. samme slags beregning. For at for-loopet kan køre, skal arrayet der løbes igennem, være instantieret, hvorfor der er brugt to dictionaries til opbevaring af arrays. Dem der er oprettet, og dem der er instantieret. Når for-loopet skal køre, undersøges det først om arrayet findes i arraydictionary. Arrayet kan være gemt i hovedklassen, eller den kan være gemt i et klasseobjekt. Men fremgangsmåden er den samme, hvor handlingen vil 62

65 Implementering blive udført, hvis arrayet er instantieret. Er det ikke tilfældet vil for-loopet blive gemt i newinput, som derfor vil blive analyseret senere, hvor arrayet kan være instantieret. Et for-loop vil have følgende syntaks For objekttype kaldenavn in arraynavn End for Det første metoden vil gøre, er derfor at dele inputstrengen op, der indeholder første linje i for-loopet. Det gøres på følgende måde: string forsentence = S.TrimStart("for".ToCharArray()).Trim(); string objecttype = forsentence.substring(0, forsentence.indexof(' ')); string nickname = forsentence.trimstart(objecttype.tochararray()).trim(); nickname = nickname.substring(0, nickname.indexof(' ')); string arrayname = forsentence.substring(forsentence.indexof(" in ")); arrayname = arrayname.trimstart(" in ".ToCharArray()); Når strengen er delt op, skal det undersøges om arrayet findes. Findes arrayet i hovedklassen, løbes alle linjer i for-loopet igennem, og erstatter kaldenavnet med navnet på arrayet, samt indeksværdien. Den nye strengværdi tilføjes derefter til newinput, således at parseren kan analysere den nye værdi. Hver linje fra for-loopet tilføjes til newinput x antal gange, hvor x er antallet af elementer i arrayet. for (int i = 0; i < arraydictionary[arrayname].count; i++) if (S.Length > 0 &&!S[0].Equals('#')) S = S.Replace(nickName + ".", arrayname + "[" + (i + 1).ToString() + "]."); newinput += S + lineshift; Er arrayet ikke gemt i hovedklassen, undersøges det om navnet på arrayet indeholder et.. Er dette tilfældet, er arrayet gemt i et objekt, eller et array. Det undersøges om classdictionary indeholder navnet, og hvis den gør, om arrayet er instantieret. Arrayet i klassen kan dog ikke tilgås direkte, men ved hjælp af en metode i klasseobjektet, hvor det undersøges om arrayet er instantieret. Hvis arrayet er instantieret laves der igen x antal nye strenge, der tilføjes til newinput, så de kan analyseres af parseren. Er arrayet ikke instantieret, vil for-loopet blive undersøgt igen senere. Da opbygningen af lvs gør, at et array kan være gemt i et andet array, skal input navnet muligvis deles yderligere op. Dette foregår med samme fremgangsmåde, hvor der 63

66 Implementering undersøges om arrayet, der indeholder objektet findes. Array indekset findes derefter, og det undersøges om arrayet er initialiseret. Igen vil en metode i Klasseobjektet sørge for at fortolke arraynavnet yderligere, hvis det er gemt i et objekt deri. Her ses fremgangsmåden til hvordan for loopet løbes igennem: if (arraydictionary.containskey(objectname) && int.tryparse(arrayindex, out index) && ((Klasser)arrayDictionary[objectName][index- 1]).IsArray(getArrayName)) for (int i = 0; i < ((Klasser)arrayDictionary[objectName][index - 1]).GetArray(getArrayName).Count; i++) SReader = new StringReader(forloop); temp = SReader.ReadLine(); while (temp!= null) temp = temp.replace(nickname + ".", getarrayname + "[" + (i + 1).ToString() + "]."); newinput += temp + lineshift; temp = SReader.ReadLine(); return; Som det ses, er koden fra for-loopet gemt i en streng, således at en StringReader kan bruges, til at løbe for-loopet igennem, en gang, for hvert objekt i arrayet. 4.9 Fortolkning af input ParseInputLine er en meget vigtig metode, der bruges af parseren. Denne metode står for at sætte alle værdierne til variablerne. Kan en værdi ikke sættes, vil variabel navn samt værdi blive gemt i newinput, så værdien kan blive simplificeret yderligere senere. Det er denne metode der står for at finde de variabler der skal tildeles en værdi. Man kan sige at den står for at simplificere hele venstre siden af ligningerne. Metoden tager en streng som input, hvorefter strengen vil blive analyseret og delt op, hvorefter variablen findes, og værdien bliver simplificeret. Det første metoden gør er at se om input indeholder =, og som forventet er tildeling af en værdi, hvorefter strengen deles op i variabel og værdi. Indeholder strengen ikke =, kan input stadigvæk håndteres, da det kan være oprett af et objekt. Metoden laver nu nogle forberedr, hvor værdien undersøges, inden den egentlige tildeling foregår. Indeholder variablen SUM(, vides det allerede nu, at værdien skal 64

67 Implementering være et resultat af flere værdier lagt sammen, og metoden til at håndtere SUM kaldes. Indeholder den i stedet ROUND(, gøres klar til at kalde Round metoden, med værdi og antal cifre der skal afrundes, efter at værdien er blevet simplificeret. Der fortsættes nu med at finde ud af hvad der skal oprettes, eller hvilken variabel der skal have tildelt en værdi. Metoden undersøger for følgende oprettr og tildelinger: Oprett af array med klasser Værdi der skal gemmes i variabel gemt i hovedklassen o Streng o Double Instantiere array i klasse Værdi der skal gemmes i variabel gemt i array i klasseobjekt Værdi der skal gemmes i variabel gemt i et klasseobjekt Værdi der skal gemmes i variabel gemt i array i hovedklassen Variablen findes ikke Udover disse, kan variablen hvis den er gemt i et klasseobjekt, være gemt endnu længere nede i objektet. Det skal denne metode ikke tage højde for, da klasseobjektet sørger for dette. Dette er beskrevet i Fortolkning af input. Er det et array med klasser, der skal oprettes, kræves det at klassen findes. Er klassen oprettet, findes størrn på arrayet der skal oprettes, og CreateArrayObject bruges til oprett af arrayet. Er der sat en størr på arrayet, bliver det instantieret samtidig. Er det i stedet en variabel i hovedklassen der skal tildeles en værdi, undersøges det om variablen findes, hvorefter Simplify kaldes med typen på variablen og værdien, der skal tildeles. Alt efter resultatet der returneres fra Simplify, undersøges det om resultatet er gyldigt, hvorefter værdien gemmes, eller tilføjes til newinput, hvis værdien er ugyldig. Indeholder navnet på variablen., vides det ikke om det er en variabel der skal have en værdi eller om det er instantiering af et array. Men i og med at. findes, vides det at det findes i et andet objekt. Indeholder navnet inden. derudover [, kan det være et array der skal instantieres, og det kan være en variabel der er gemt i et array. Objektet findes nu, ved at undersøge om det ligger i tabellen med arrays. Findes arrayet, skal der undersøges yderligere, hvad der skal ske, og metoden ser, om der er tale om et array der skal instantieres, ved hjælp af isarraytoinstantiate metoden. isarraytoinstantiate er implementeret i klasseobjektet. Modtages der en boolean der er sand, fortsættes med instantieringen, og antallet der skal oprettes forsøges simplificeret, da det udover at være et tal, også kan 65

68 Implementering være et antal der skal hentes fra en anden variabel. Hvis simplificeringen lykkes, bliver arrayet instantieret. Ellers tilføjes det til newinput, indtil størrn på arrayet kan findes. For at finde ud af om det er en instantiering, ser metoden, om et array med det pågældende navn findes i tempdictionary. Findes arrayet, og er det ikke instantieret, findes størrn, hvorefter arrayet instantieres. Er det ikke instantiering, kan det være en variabel, der skal tildeles en værdi. Det forsøges derfor at hente variablen, med det pågældende navn. Findes variablen, fortsættes der med at tildele en værdi. Navnet kan også være navnet på et klasseobjekt. Er dette tilfældet hentes variablen fra den pågældende klasse, og hvis den findes, forsøges værdien at blive gemt. Findes navnet i stedet i tabellen med arrays, skal variablen hentes heri, efter arrayindekset er fundet. Da der også er gemt arrays med klasser, er det nødvendigt at undersøge hvilken type arrayet består af. if (arraydictionary.containskey(arraynavn)) int arrayindex = int.parse(varname.substring(varname.indexof("[") + 1, varname.indexof("]") - varname.indexof("[") - 1)); string typeofarray = ((Vars)arrayDictionary[arrayNavn][0]).type; string input = Simplify(typeOfArray, varvalue).tostring(); if (IsValidValue((Vars)arrayDictionary[arrayNavn][arrayIndex], input)) ((Vars)arrayDictionary[arrayNavn][arrayIndex]).setValue(input); newinput += arraynavn + "[" + arrayindex + "]" + "=" + input; Kan input strengen ikke analyseres, er variablen ikke oprettet, eller er arrayindekset ikke gyldigt endnu, vil input blive gemt i newinput. Under fortolkning af input, kaldes Simplify hver gang en værdi skal sættes, hvorefter IsValidValue kaldes, for at se om værdien må bruges. På den måde sikres det at kun gyldige værdier vil blive gemt, og at værdien altid simplificeres mest muligt. Er værdien ikke gyldig vil det være den simplificerede værdi der bliver gemt i newinput Simplificering af udtryk Simplify metoden bruges til at simplificere alle værdier. Som input skal den have typen på værdien der skal findes, samt værdien der skal simplificeres. Er det en double værdi der skal findes, starter den med at se om der er nogle matematiske operatorer, så Calc metoden kan bruges til udregning. 66

69 Implementering Er det ikke tilfældet undersøges der om værdien skal komme fra et metodekald. Dette gøres ved at se om sidste tegn er ). Er det tilfældet, kan det dog også være brug af den interne metode ROUND. Det undersøges om dette er tilfældet, og i så fald kaldes Simplify rekursivt for at få værdien der skal afrundes. Antallet af tegn der skal afrundes findes derefter, for til sidst at kalde Round metoden, og returnere resultatet. Er der tale om en ekstern metode, findes metodenavnet, og det undersøges om det er i listen med metoder, for at se om den er oprettet. Findes metoden gemmes alle input parametrene i et array, hvorefter typen på input parametre og typen på output parameteren henes ved hjælp af Metode klassen. Er antallet af parametre metoden skal kaldes med, lig med antallet af parametre programmet har fundet frem, undersøges nu om parametrene har samme type. foreach (ParameterInfo item in validparameters) if (item.parametertype.equals(typeof(double))) tempvalue = Simplify("double", parameters[i]).tostring(); //variablen er en streng eller double if (!double.tryparse(tempvalue, out tempdouble)) return var; checkedparameters[i] = tempdouble; i++;.. Stemmer de fundne parametertyper overens med den parametertype metoden forventer, gemmes parameteren i et array. Passer alle parametrene bruges dette array, som input til at kalde metoden. Er det ikke et metodekald, kan værdien skulle hentes fra et array i hovedklassen. Det undersøges om arrayet findes, hvorefter indeks værdien findes. Variablen hentes, og hvis dens værdi er sat, returneres den. Variablen kan også være gemt i et objekt. Navnet på objektet findes, hvorefter det undersøges om variablen er i et array, eller en almindelig klasse. Er ingen af ovenstående muligheder aktuelle undersøges det om værdien er sat direkte. Typen på variablen bruges igen, for at sikre sig at input har den korrekte form. 67

70 Implementering 4.11 Udregning Til udregning er der som beskrevet implementeret metoden Calc, der tager en streng som input. Metoden starter med, at undersøge om input indeholder to - efter hinanden. De vil blive erstattet af +, da to gange - er +. Det kan opstå hvis en negativ værdi skal trækkes fra et andet tal. For at beregne indholdet i strengen, undersøges nu om der er parenteser i udtrykket. Er der parenteser, skal disse udregnes først. Indeholder udtrykket en start parentes, skal der ligeledes findes en slut parentes. Findes der imidlertid en ekstra start parentes, er der tale om et andet udtryk der skal beregnes først. Det er derfor nødvendigt at holde øje med ekstra parenteser. Findes der en slut parentes, beregnes udtrykket i parentesen ved hjælp af Calc metoden. int startparantes = input.indexof("("); for (int item = startparantes + 1; item < input.length; item++) if (input[item].equals(')')) //før start parantes part1 = input.substring(0, startparantes); //inden i parantesen part2 = input.substring(startparantes + 1, item - startparantes - 1); part2 = Calc(part2); //efter slut parantes part3 = input.substring(item + 1, input.length item); input = part1 + part2 + part3; return Calc(input); if (input[item].equals('(')) startparantes = item; I beregning af indholdet i parentesen ses det at strengen deles op i tre dele. 1. Før parentesen 2. I parentesen 3. Efter parentesen 68

71 Implementering Da indholdet i parentesen skal beregnes først, bruges Calc metoden til at lave beregning af indholdet. Resultatet sættes derefter sammen med de to andre dele, og hele indholdet, hvor parentesen nu er udregnet, kan beregnes ved hjælp af samme metode. Indeholder strengen ikke en matematisk operator, er der ikke en udregning der skal foretages, men formentlig bare en værdi, som derfor returneres. Er der operatorer i strengen, løber et for-loop strengen igennem, og undersøger et tegn af gangen. Er det første tegn en - operator, skal der ikke beregnes noget endnu, men der er tale om en negativ værdi, som der skal tages højde for senere. Da der kan være tale om en negativ værdi fra en variabel, fjernes - tegnet fra strengen, da navnet ikke vil kunne genkendes, hvis det indeholder -, når det skal findes i tabellen. En boolean bruges til at angive om første værdi er negativ. Før et resultat skal returneres, ganges værdien med -1, hvis boolean er sat, således at den vil få den korrekte værdi. Findes en + operator, vil udtrykket deles i to dele. Venstre og højre side af operatoren. Venstre siden vil nu bestå af et led, mens højresiden kan bestå af flere led. Højresiden skal derfor igennem Calc igen, for at blive udregnet. Selvom venstresiden kun består af et led, kan det stadigvæk være navnet på en variabel, og ikke en tal værdi. Den skal derfor igennem Calc, så en tal værdi kan blive returneret. Efter begge dele har været igennem Calc metoden, undersøges det, om der bliver returneret to tal, der kan lægges sammen, så resultatet kan returneres. Kan der ikke returneres et resultat, skal venstre og højresiden returneres. Grunden til, at det ikke er inputtet der returneres, er at nogle af leddene kan være blevet reduceret. Er operatoren i stedet en / eller *, kan der som beskrevet i analyse afsnittet ikke altid deles på samme måde. Findes der ikke andre operatorer i udtrykket, vil der blive delt op i venstre og højre side. Venstre siden udregnes ved hjælp af Calc og en tal værdi hentes. Højresiden, som består af resten af input, udregnes derefter. part1 = Calc(input.Substring(0, place).trim()); //der er ikke andre operatorer i udtrykket if (item == input.length) part2 = Calc(input.Substring(place + 1).Trim()); part3 = ""; Findes der en operator mere, bruges der tre strenge, til at dele udtrykket op. Hvor del to ligeledes udregnes med Calc, men i stedet for at bestå af resten af strengen, består den nu kun af højre siden af operatoren, indtil næste operator. Næste operator og resten af strengen gemmes i del tre. Skal første del være negativ, ganges der med -1. Del et og to undersøges for om de kan multipliceres, og hvis muligt, findes produktet. Resultatet sættes sammen med den resterende del af udtrykket, der er gemt i del tre, og resten af resultatet kan nu findes 69

72 Implementering ved hjælp af Calc metoden. Er produktet ikke et tal, kan det naturligvis ikke beregnes, og de simplificerede værdier returneres. part2 = Calc(input.Substring(place + 1, item - (place + 1)).Trim()); part3 = input.substring(item); if (minusvalue.equals(true)) part1 = "-" + part1; if (double.tryparse(part1, out tempdouble1) && double.tryparse(part2, out tempdouble2)) double product = tempdouble1 * tempdouble2; return Calc(product.ToString() + part3); return part1 + "*" + part2 + part3; 4.12 Klasser I klassen Klasse er der fem interessante metoder: IsArray, IsArrayToInstantiate, GetVar, SetVar og ReplaceDictionaries. IsArray og IsArrayToInstantiate der begge tager navnet på et array som input, bruges som navnet antyder til arrays. De ser begge om et array med arraynavnet findes. Indeholder arraynavnet et., undersøges det om venstresiden for. henviser til placeringen, hvor et objekt er gemt. Er det tilfældet, kaldes de respektive metoder i klasseobjektet, så det kan undersøges om arrayet findes. De to metoder GetVar og SetVar bruges til at sætte en variabel og hente en variabel fra et objekt. Begge metoder tager navnet på en variabel som input. SetVar tager derudover en variabel som input. De er bygget op på samme måde, hvor de først ser om navnet indeholder., for at se om variablen der skal hentes, eller sættes, findes i objektet, eller om der skal ledes i et andet objekt. Er variablen i et andet objekt, undersøges først om variablen skal findes i tabellen med klasser, eller tabellen med arrays, hvorefter det forsøges at finde den pågældende variabel. Findes den i objektet, undersøges det ligeledes om den ligger i et array eller i tabellen med variabler. Ligesom IsArray og IsArrayToInstantiate kalder disse to klasser tilsvarende metoder, i andre klasseobjekter, således at variablerne kan være gemt i objekter flere lag nede. Metoderne til oprett af arrays og instantiering af arrays, er ikke implementeret til at kalde metoder i andre objekter, hvis navnet indeholder.. Grunden til dette er at oprett og instantiering af arrays foregår i LVS klassen, hvor metoderne får klasse objektet som input, og derfor kan sætte arrayet direkte. 70

73 Implementering ReplaceDictionaries er en privat metode, der bruges af metoden Copy, når en klasse skal kopieres. Dette bruges når der skal oprettes en ny instans af klassen. For at få en ny instans, og ikke en reference, er det nødvendigt at kopiere indholdet i de tabeller der indeholder variabler, arrays og objekter. Klasserne kan indeholde flere objekter, hvorfor de også skal kopieres. Tabellerne skal løbes igennem, og objekterne skal kopieres en af gangen. Tabellen med arrays der ikke er instantieret kan kopieres direkte da der endnu ikke ligger nogle instanser heri, og der vil derfor ikke laves referencer. foreach (KeyValuePair<string, Vars> item in vardic) vardictionary.add(item.key, item.value.copy()); Ovenover ses hvordan tabellen med variabler kopieres. For hvert KeyValuePair der findes i tabellen, kopieres variablen sammen med navnet over i den nye tabel. foreach (KeyValuePair<string, ArrayList> item in arraydic) ArrayList al = new ArrayList(); if (item.value.count > 0 && item.value[0].gettype().equals(typeof(klasser))) foreach (Klasser klasse in item.value) al.add(((klasser)klasse).copy()); arraydictionary.add(item.key, al); Her ses hvordan tabellen med arrays bliver kopieret hvis den indeholder klasser. Da arrays kan indeholde klasser og variabler, er det nødvendigt at finde ud af hvilken type der er tale om, så den kan blive kopieret korrekt. Udover de beskrevne metoder, er der en del metoder til behandling af variabler, og ændring af dens egenskaber. Disse bruges dog ikke, men er oprettet, så funktionaliteten eventuelt kan udvides, og variabler tilføjes det enkelte klasseobjekt, således de vil blive unikke. 71

74 Implementering 4.13 Variabler I klassen Var der bruges til oprett af variabler er der lavet simple metoder, som bruges til at sætte og hente egenskaberne for en variabel. Udover metoderne til attributterne har den en boolean der fortæller om værdien er sat eller ej. Denne bruges til at se om en værdi allerede er sat, således at samme variabel, ikke tildeles en værdi flere gange Save Save klassen består af tre metoder. SaveToFile ObjectToString SaveStringToFile SaveStringToFile bruges til at gemme newinput, efter hvert gennemløb, så man kan følge med i hvad der bliver simplificeret. SaveToFile bruges til at gemme al input, der er blevet analyseret og forstået. Den tager tre tabeller som input - vardic, arraydic og classdic, samt navnet på filen, det skal gemmes i. Ved at få de tre tabeller som input, kan alle de objekter der er oprettet, blive gemt. Er der ikke oprettet instanser af en klasse i finishdictionary, vil den derfor ikke blive udskrevet. Måden tabellerne bliver brugt på, er at alle KeyValuePair løbes igennem, hvorefter nøglen og værdien gemmes i output filen. Når klasser og arrays med klasser gemmes, bruges metoden ObjectToString, der også fungerer ved at løbe tabellerne igennem. Her kan objekterne dog indeholde andre objekter, hvorfor metoden kalder sig selv rekursivt, så alt data kan blive gemt. ObjectToString tager et objekt som input, samt navnet på objektet som input. Finder den et objekt i et objekt, og kalder sig selv, bruger den navnet på det gamle objekt, samt navnet på det nye objekt, til at kalde sig selv med. På den måde, vil den rigtige syntaks blive brugt, når værdierne skal gemmes. if (t.equals(new Klasser().GetType())) objectstring += ObjectToString((Klasser)item, objectname + "." + kvp.key + "[" + (i + 1) + "]"); i++; Da arrays kan indeholde objekter og variabler, skal typen på arrayet undersøges, før et array gemmes. Er der tale om et array med objekter, kan metoden kalde sig selv. Der bruges en tæller, til at holde styr på hvilket array man er i gang med at gemme, således at indeks værdien kan blive korrekt. Da første objekt ligger på plads nul i arrayet, bruges pladsen foran indeks værdien, når værdien gemmes. 72

75 Implementering Data der er blevet simplificeret, gemmes i mappen simplify, mens det færdige resultat gemmes i mappen save. Mapperne ligger samme sted som programmet Opsummering I ovenstående afsnit er det vist hvordan et regelbaseret system kan implementeres. Der er vist hvordan man kan oprette objekter i form af klasser og variabler, samt hvordan man kan laves arrays med de implementerede typer. Der er vist, hvordan metoder dynamisk kan kompileres til en assembly, hvorefter de kan indlæses og kaldes. Der er derudover beskrevet, hvordan metoder svarende til Excels indbyggede metoder kan implementeres. Ved hjælp af forskellige metoder, er der vist hvordan regler kan fortolkes, og omdannes til data, der kan bruges til at lave en vurdering. 73

76

77 5 TEST I dette afsnit vil det blive gennemgået hvordan systemet er blevet testet, og der vil vises eksempler på hvordan inputdata bliver simplificeret. Derudover vises hvilke resultater, der vil blive gemt. For at teste om det implementerede system virker som forventet, er der lavet en række testsager, samt nogle unit test. Testsagerne skal vise hvordan simplificeringen af data foregår, og at resultatet er korrekt. De vil vise hvordan objekter oprettes, for derefter at kunne oprette instanser af dem. Testsagerne vil derudover vise at rækkefølgen af reglerne er lige meget. Når et system skal laves, skal man derfor ikke tænke over om det objekt der bruges, er oprettet først. Der vil vises test af objekter og arrays i hovedklassen, ligesom objekter og arrays vil oprettes i andre objekter. For at vise at forloops og if-statements virker som de skal, er der lavet test hvor de bruges. Unit test tester den enkelte metode, og sikrer at de håndtere data som forventet, og at den laver de oprettr og ændringer, som den skal. Unit testene er ikke lavet, som testsagerne, der tester hele systemet. Deer lavet til hver enkelt metode, således at de tester funktionen af metoden. De køres automatisk, og kan derfor køres, hver gang der laves en ændring i programmet. På den måde, sikres det, at funktionaliteten af programmet stadigvæk er korrekt, efter en ændring. Unit testene kan ses i appendiks A. 75

78 Test Her vises en testsag hvor der oprettes en række objekter, hvorefter en variabel i objektet tildeles en værdi ved hjælp af et for-loop. class Bygning double c end class class Ejendom double a Bygning[] bygninger end class Ejendom[] ejendomme = new Ejendom[2] ejendomme[1].a = 1 ejendomme[2].a = 2 for ejendom ej in ejendomme ej.bygninger = new Bygning[2] for Bygning by in ej.bygninger ej.by.c = ej.a * 3 end for end for I eksemplet oprettes klassen Bygning, og klassen Ejendom. Hver Ejendom har et array med 2 bygninger. Der oprettes et array med to ejendomme, hvorefter variablen i objektet tildeles en værdi. Derefter bruges to for-loops til at oprette Bygning objekterne i ejendomme, og sætte variablen i alle fire Bygnings objekter. I Tabel 7 ses en liste med forventede værdier i ejendomme. Rækkefølgen af variablerne er ikke vigtig, kun værdien der er gemt. Forventet Ejendomme[1].a = 1 Ejendomme[1].bygninger[1].c = 3 Ejendomme[1].bygninger[1].c = 3 Ejendomme[2].a = 2 Ejendomme[2].bygninger[1].c = 6 Ejendomme[2].bygninger[1].c = 6 Tabel 7 - Eksempel på test af input Herunder ses hvordan inputtet der endnu ikke er analyseret er blevet simplificeret: 76

79 Test ejendomme[1].bygninger = new Bygning[2] for Bygning by in ejendomme[1].bygninger ejendomme[1].by.c = ejendomme[1].a * 3 end for ejendomme[2].bygninger = new Bygning[2] for Bygning by in ejendomme[2].bygninger ejendomme[2].by.c = ejendomme[2].a * 3 end for ejendomme[1].bygninger[1].c = ejendomme[1].a * 3 ejendomme[1].bygninger[2].c = ejendomme[1].a * 3 ejendomme[2].bygninger[1].c = ejendomme[2].a * 3 ejendomme[2].bygninger[2].c = ejendomme[2].a * 3 I første boks ses det, at alle klasserne bliver oprettet i første forsøg. Dette var også forventet, da en klasse ikke er afhængig af andre instanser. Som det ses er det første forloop fra eksemplet udført. Det er løbet igennem to gange en gang for hver klasse i ejendomme. Efter næste gennemløb er de to sidste for-loops udført, hver især to gange en gang for hver Bygning i bygninger. Efter sidste gennemløb analyseres resten af data, hvorefter der ikke er mere data at analysere. Outputtet stemmer overens med de forventede værdier. For at vise at rækkefølgen i input filen ikke har betydning for resultatet, vises et eksempel med samme input data, i anden rækkefølge. 77

80 Test Ejendom[] ejendomme = new Ejendom[2] class Ejendom double a Bygning[] bygninger end class for ejendom ej in ejendomme for Bygning by in ej.bygninger ej.by.c = ej.a * 3 end for ej.bygninger = new Bygning[2] end for ejendomme[1].a = 1 ejendomme[2].a = 2 class Bygning double c end class I eksemplet forsøges det først at oprette et array med klassen Ejendom, der endnu ikke er oprettet. Derefter oprettes klassen Ejendom, mens klassen Bygning oprettes til sidst. Efter Ejendom klassen er oprettet, løber et for-loop ejendomme igennem, for derefter at løbe bygninger i ejendomme arrayet igennem og igen sætte c variablen i hvert bygningsobjekt. Ejendomme arrayet instantieres efter for-loopet, da det ikke vil være muligt at oprette det inden Ejendom klassen er oprettet. Da rækkefølgen ikke har nogen betydning, forventes det at Ejendom først oprettes, for derefter at springe for-loopet over, da ejendomme endnu ikke findes. Bygning klassen oprettes, hvorefter ejendomme arrayet instantieres og for-loopet kan analyseres. Bygninger i ejendomme instantieres efter for-loopet der løber bygninger igennem, og det forventes derfor at for-loopet ikke vil blive udført første gang det analyseres. De forventede værdier er de samme som i forrige eksempel, der kan ses i Tabel 7. Efter første gennemgang, ser det simplificerede input således ud: 78

81 Test Ejendom[] ejendomme = new Ejendom[2] for ejendom ej in ejendomme for Bygning by in ej.bygninger ej.by.c = ej.a * 3 end for ej.bygninger = new Bygning[2] end for ejendomme[1].a=1 ejendomme[2].a=2 Som forventet er de to klasser blevet oprettet med det samme, mens ejendomme ikke er oprettet. For-loopet er ikke løbet igennem endnu, og de to variabler der skal have tildelt en værdi er heller ikke udført endnu. for Bygning by in ejendomme[1].bygninger ejendomme[1].by.c = ejendomme[1].a * 3 end for ejendomme[1].bygninger = new Bygning[2] for Bygning by in ejendomme[2].bygninger ejendomme[2].by.c = ejendomme[2].a * 3 end for ejendomme[2].bygninger = new Bygning[2] Ovenover ses det at ejendomme nu er instantieret, og at det første for-loop er udført. A variablen i de to objekter er tildelt en værdi. For-loopet kan endnu ikke løbes igennem, da bygninger ikke er instantieret. Som det ses nedenfor instantieres bygninger, før forloopet udføres. for Bygning by in ejendomme[1].bygninger ejendomme[1].by.c = ejendomme[1].a * 3 end for for Bygning by in ejendomme[2].bygninger ejendomme[2].by.c = ejendomme[2].a * 3 end for Begge for-loops kan nu løbes igennem. ejendomme[1].bygninger[1].c = ejendomme[1].a * 3 ejendomme[1].bygninger[2].c = ejendomme[1].a * 3 ejendomme[2].bygninger[1].c = ejendomme[2].a * 3 ejendomme[2].bygninger[2].c = ejendomme[2].a * 3 79

82 Test Ovenover ses det at begge for-loops er blevet simplificeret, og at der nu er tale om tildeling af værdier til fire variabler. Efter endnu en simplificering har variablerne fået tildelt en værdi, og der er ikke mere inputdata der skal simplificeres. Det vises at rækkefølgen af reglerne ikke har betydning for resultatet. Dog vil antallet af gange, data forsøges at blive simplificeret, variere, alt efter hvordan reglerne er sat op. I det første eksempel kræves 3 gennemløb, mens andet eksempel klares efter 5 gennemløb. For at teste en if-statement i et for-loop, bruges følgende testsag: class Ejendom double a double b double c end class Ejendom[] ejendomme = new Ejendom[4] ejendomme[1].a = 1 ejendomme[2].a = 2 ejendomme[3].a = 3 ejendomme[4].a = 4 for Ejendom ej in ejendomme if ej.a <= 2 then ej.b = ej.a if ej.a > 2 & ej.c > 3 ej.b = ej.a end if end for ejendomme[3].c = 3 ejendomme[4].c = 4 Her forventes det at der oprettes et Ejendom objekt, der bruges til at lave et array. A variablen sættes i alle objekter. For-loopet løber alle ejendommene igennem, og sætter b værdien hvor det er muligt. De forventede værdier kan ses i Tabel 8. Forventet ejendomme[1].a = 1 ejendomme[1].b = 1 ejendomme[1].c 80

83 Test ejendomme[2].a = 2 ejendomme[2].b = 2 ejendomme[2].c ejendomme[3].a = 3 ejendomme[3].b ejendomme[3].c = 3 ejendomme[4].a = 4 ejendomme[4].b = 104 ejendomme[4].c = 4 Tabel 8 - forventede resultater til test af for-loop og if-statement Efter første simplificering, ser data således ud: if ejendomme[1].a <= 2 then ejendomme[1].b = ejendomme[1].a if ejendomme[1].a > 2 & ejendomme[1].c > 3 ejendomme[1].b = ejendomme[1].a end if if ejendomme[2].a <= 2 then ejendomme[2].b = ejendomme[2].a if ejendomme[2].a > 2 & ejendomme[2].c > 3 ejendomme[2].b = ejendomme[2].a end if if ejendomme[3].a <= 2 then ejendomme[3].b = ejendomme[3].a if ejendomme[3].a > 2 & ejendomme[3].c > 3 ejendomme[3].b = ejendomme[3].a end if if ejendomme[4].a <= 2 then ejendomme[4].b = ejendomme[4].a if ejendomme[4].a > 2 & ejendomme[4].c > 3 ejendomme[4].b = ejendomme[4].a end if Objektet er blevet oprettet, a variablerne har fået tildelt en værdi, for-loopet er udført og c variablerne har fået en værdi. Efter næste gennemløb er if-statement udført: 81

84 Test ejendomme[1].b = ejendomme[1].a ejendomme[2].b = ejendomme[2].a ejendomme[4].b = ejendomme[4].a Som forventet skal b tildeles en værdi i objekt 1, 2 og 4. Da ingen af kriterierne for ifstatement var sande for objekt 3, vil dens c variabel altså ikke blive tildelt en værdi. B variablen i objekt 4, er tildelt en anden regel end objekt 1 og 2. Efter sidste gennemløb er al data fortolket, og resultatet er magen til det forventede. Den næste testsag, viser hvordan en if-statement bliver simplificeret, hvis kun noget af if-statement kan undersøges. double c = 10 if c > 10 then ejendom.b = 10 if c > 3 & ejendom.a > 2 then ejendom.b = 100 end if class Ejendom double a double b end class Ejendom ejendom = new Ejendom ejendom.a = 3 Som det ses, kan hele if-statement ikke udføres. Første del er falsk, og if skal derfor undersøges. Men da ejendom objektet ikke er oprettet, kan det ikke undersøges. Det forventede slut resultat kan ses i Tabel 9. Forventet c = 10 ejendom.a = 3 ejendom.b = 100 Tabel 9 - forventede resultatet til test af if-statement Første gennemløb giver følgende data, der skal simplificeres: 82

85 Test if ejendom.a > 2 then ejendom.b = 100 end if Som det ses er første del af if-statement undersøgt og fundet falsk. Anden del af ifstatement kan ikke undersøges helt, da ejendom objektet først oprettes bagefter. C værdien eksisterer dog, og er derfor blevet undersøgt. Da den er sand, skal resten af udtrykket undersøges, for at se om det er sandt. Da c værdien ikke skal undersøges igen, er if-statement lavet om, til kun at undersøge variabel a i ejendom. Næste gennemløb resultere i nedenstående, hvor det ses at a variablen nu kan blive undersøgt, og b værdien vil blive sat. ejendom.b = 100 Til sidst vil metodekald testes. En fil bestående af en liste med postnumre og byer, samt en metode der kan returnere en by, vil blive indlæst. Metoden tager et postnummer som input, og findes postnummeret, returneres byen. Dictionary<int, string> postnummer = new Dictionary<int, string>(); public By() #region postnumre postnummer.add(2600, "Glostrup"); postnummer.add(2605, "Brøndby");... postnummer.add(9982, "Ålbæk"); postnummer.add(9990, "Skagen"); #endregion public string getby(int post) if(postnummer.containskey(post)) return postnummer[post]; return ""; 83

86 Test Inputtet til test af metodekald ser således ud: metode getby "metoder\\getby.txt" csharp string by string by2 double postnummer = 3790 by = getby(postnummer) by2 = getby(1234) Parseren kan fortolke alt i første gennemløb, og programmet slutter derfor med det samme. Det forventede resultat kan ses i Tabel 10. Forventet by = "Hasle" by2 = "" postnummer = 3790 Tabel 10 - forventede resultat til test af metodekald Som det kan ses finder programmet ud af at bynavnet tilhørende postnummer 3790 er Hasle. Da der ikke er en by med postnummeret 1234, gemmes der ikke et bynavn i by2. For at teste at programmet er i stand til at lave en ejendomsvurdering, er der brugt et eksempel, fra landbrugsvurderingssytemet. Excel arket med data er vedlagt på Cd en. Derudover er der vedlagt en tom landbrugsvurdering, hvor alle celler svarende til et landbrug med en ejendom er synlige. Reglerne til programmet og input til variablerne kan ses i appendiks C. De er ligeledes lagt med på cd en. Det kan virke som om der er mange regler. Men reglerne svarer til et enkelt objekt, af hver type. Skal der oprettes flere objekter, vil der altså ikke skulle oprettes flere regler. 5.1 Opsummering I ovenstående afsnit er der lavet en gennemgang af nogle af de tests der er lavet. Der er vist eksempler på forskellige input, og hvordan programmet håndterer dem. Simplificeringen er vist trin for trin, for at give et indblik i hvordan programmet fortolker reglerne. Derudover er resultatet til de forskellige tests vist, så det er muligt at se hvad der bliver gemt. 84

87 6 UDVIDELSESMULIGHEDER I dette afsnit vil udvidsmulighederne for det implementerede system blive gennemgået. 6.1 GUI En af fordelene ved Excel er den grafiske brugerflade, der nemt gør programmet flot for brugeren at se på. At det er lavet grafisk, gør brugen af programmet nemt, og flere brugere vil give sig i kast med at bruge det. Først når der skal laves makroer, eller mange formler, vil man opleve kompleksiteten i Excel. Der vil derfor komme en beskriv af hvordan en gui kan laves til det implementerede system, således at opbygningen kan ske visuelt, og det bliver dermed mere overskueligt. Der vil ikke blive implementeret en gui, da det er funktionaliteten af programmet der er lagt vægt på. Designet af en grafisk brugerflade laves, for at give et indblik i hvordan det kan lade sig gøre, at gøre brugen af programmet enkelt og gøre det muligt at bruge reglerne, uden at skulle have en forstå for syntaksen. Ved hjælp af en gui kan kompleksiteten fjernes, og et system vil kunne sættes op, uden at man skal skrive reglerne manuelt. 85

88 Udvidsmuligheder Figur 16 - eksempel på grafisk brugerinterface Figur 16 viser hvordan en grafisk brugerflade til det implementerede system kan se ud. Det er bygget op ved at systemet vises i venstre side ved hjælp af et treeview. I eksemplet består hovedklassen af objekterne bebo og driftsbygninger. Bebo er en instans af en klasse, mens driftsbygninger er et array med klasser. Til højre for treeviewet er der tre beholdere. De indeholder hver især variabler, klasser og arrays, til det valgte objekt i treeviewet. Markeres et andet objekt i treeviewet, skal objektets attributter vises i de tre beholdere. Nederst på figuren vises de klasser der er oprettet, og som kan bruges til at lave objekter og arrays. Ved at implementere drag and drop, kan en klasse trækkes op til enten klasser eller arrays beholderen. Ved at implementere et popupvindue, der kommer frem, når klassen slippes, kan man skrive navnet på objektet eller arrayet der skal oprettes. Er det et array der oprettes, skal der ligeledes være mulighed for at angive hvor stort arrayet skal være. Dette kan enten være i form af et tal, eller en double variabel. En liste med double variabler der er oprettet, skal derfor vises, ved oprett af et array. Til højre på Figur 16 er en beholder med typer der kan oprettes. Her kan vælges mellem variabel, klasse, for og if. Skal en variabel oprettes, kommer vinduet vist på Figur 17 frem. Her kan man skrive navnet og beskrivn til variablen. Derefter kan typen vælges, samt om det skal være et array. Derudover skal vælges om input skal komme fra brugeren, eller om der skal beregnes en værdi. Afhængig af type valget, vises parametrene der kan udfyldes. 86

89 Udvidsmuligheder Figur 17 - oprett af variabel Trykkes der på en af variablerne, kan skærmbilledet fra Figur 17 genbruges. I stedet for opret variabel, skal der stå ændre variabel i titlen, og opret knappen ændres til Gem. Sæt Værdi knappen bruges, til at åbne et vindue, hvor man kan angive hvordan værdien skal beregnes. Et eksempel herpå ses i Figur 18. Klasserne vises igen i treeviewet til venstre, hvorfor man kan vælge de enkelte objekter. Herfra er det muligt at trække variablerne ned i værdi feltet, eller skrive navnet manuelt. Round kan markeres, og bruges til at fortælle hvor mange cifre i resultatet der skal afrundes. 87

90 Udvidsmuligheder Figur 18 - sæt værdi Skal der oprettes en klasse, kan skærmbillede vist i Figur 16 genbruges. De samme klasseobjekter vil vises nederst, mens treeviewet i venstre side, nu vil se anderledes ud. I stedet for hovedklassen som root, vil den nye klasse være root. Når der tilføjes klasser eller arrays med klasser, skal de ligeledes tilføjes til treeviewet samtidig. Skal et for-loop oprettes, kan det se ud som vist på Figur 19. Her vises en liste med alle arrays, der kan trækkes ned, som der vil laves et for-loop med. Klasserne og variablerne vises ligeledes, så de kan bruges i for-loopet. If-statement vil i stedet for arrays, have en liste med variabler, og en liste med operatorer der kan bruges til at sammenligne værdier. 88

91 Udvidsmuligheder Figur 19 - oprett af for-loop Alle variabler, klasser og arrays kan gemmes i en arraylist med tekst strenge. Når programmet lukkes, kan arrayet løbes igennem, og det hele gemmes til en fil indeholdende regler til programmet. På samme måde som en klasse kan tilføjes til et objekt, ved hjælp af drag and drop, kan det implementeres så variabler, klasser og arrays kan fjernes fra et objekt, ved at trække objektet væk derfra. For at synliggøre om variabler vil blive tildelt en værdi, kan der bruges farver til variablerne. Er en variabel ikke tildelt en værdi, kan den markeres med farven rød, mens den vil have en almindelig farve når værdien er sat. Alternativt kan programmet automatisk sætte en variabel til at få en værdi fra brugeren, hvis der ikke sat en værdi. Hvis programmet udvides til at lave reglerne ved hjælp af den grafiske brugerflade, vil alle deklarationerne blive oprettet, inden variablerne tildeles værdier fra brugeren. Det gør det nemmere at lave programmet til indlæsning af data dynamisk. Et eksempel på hvordan brugerfladen til indlæsning af data fra brugeren, kan se ud, kan ses i Figur

92 Udvidsmuligheder Figur 20 - input fra bruger For hvert objekt der bruges i hovedklassen, kan der laves et faneblad. På hvert faneblad, kan alle variablerne blive listet. Navnet på variablen kan bruges, sammen med en inputboks. Ved input boksen kan beskrivn på variablen vises. Må variablen kun have nogle bestemte værdier, kan en dropdownboks bruges til input. Når inputtet er indtastet, kan isvalidvalue metoden bruges, til at se om input er gyldigt, og markere med f.eks. en rød farve, så brugeren kan se at værdien er ugyldig og ikke vil blive gemt. Er der arrays med variabler, listes de ligeledes under de andre variabler. Hvis et objekt består af andre objekter, kan der bruges endnu en panel med faneblade, hvor data til de underliggende objekter kan indtastes på samme måde. 6.2 Parameter En ekstra parameter, som double værdierne ville være god at udvide med, er antallet af decimaler. En parameter kan fortælle, hvor mange decimaler et resultat skal gemmes med. Er der ikke angivet et antal, vil decimalerne automatisk blive fjernet. I det implementerede system bruges længde parameteren for double værdien til at tjekke længden på værdien. Hvis antallet af decimaler kan sættes for en værdi, burde længden samtidig udvides, til at se om den er mulig, hvis der er sat maksimum og minimum 90

ISCC. IMM Statistical Consulting Center. Brugervejledning til beregningsmodul til robust estimation af nugget effect. Technical University of Denmark

ISCC. IMM Statistical Consulting Center. Brugervejledning til beregningsmodul til robust estimation af nugget effect. Technical University of Denmark IMM Statistical Consulting Center Technical University of Denmark ISCC Brugervejledning til beregningsmodul til robust estimation af nugget effect Endelig udgave til Eurofins af Christian Dehlendorff 15.

Læs mere

Sproget Six. Til brug i rapportopgaven på kurset Oversættere. Vinter 2006. Abstract

Sproget Six. Til brug i rapportopgaven på kurset Oversættere. Vinter 2006. Abstract Sproget Six Til brug i rapportopgaven på kurset Oversættere Vinter 2006 Abstract Six er baseret på det sprog, der vises i figur 6.2 og 6.4 i Basics of Compiler Design. Den herværende tekst beskriver basissproget

Læs mere

1. Opbygning af et regneark

1. Opbygning af et regneark 1. Opbygning af et regneark Et regneark er et skema. Vandrette rækker og lodrette kolonner danner celler, hvori man kan indtaste tal, tekst, datoer og formler. De indtastede tal og data kan bearbejdes

Læs mere

Avanceret Excel 2013. Martin Simon. Forlaget TextMaster ISBN: 978-87-93170-23-0. E-bogsudgave 2014. Kopiering fra denne bog er ikke tilladt.

Avanceret Excel 2013. Martin Simon. Forlaget TextMaster ISBN: 978-87-93170-23-0. E-bogsudgave 2014. Kopiering fra denne bog er ikke tilladt. A Avanceret Excel 2013 Martin Simon Forlaget TextMaster ISBN: 978-87-93170-23-0 E-bogsudgave 2014 Kopiering fra denne bog er ikke tilladt. 2 Forord... 8 Udvalgte genvejstaster... 9 Navigere i et ark...

Læs mere

FORMLER OG FUNKTIONER I EXCEL

FORMLER OG FUNKTIONER I EXCEL 1 FORMLER OG FUNKTIONER I EXCEL 1. Indtast flg. data i et regneark: Note: de små grønne markeringer i hjørnet af cellerne i kolonne B betyder, at tallet er formateret som tekst. 2 HVIS Afstand i km fra

Læs mere

IT opgave. Informationsteknologi B. Vejleder: Karl. Navn: Devran Kücükyildiz. Klasse: 2,4

IT opgave. Informationsteknologi B. Vejleder: Karl. Navn: Devran Kücükyildiz. Klasse: 2,4 IT opgave Informationsteknologi B Vejleder: Karl Navn: Devran Kücükyildiz Klasse: 2,4 Dato:03-03-2009 1 Indholdsfortegnelse 1. Indledning... 3 2. Planlægning... 3 Kommunikationsplanlægning... 3 Problemstillingen...

Læs mere

Hvad er Objekter - Programmering

Hvad er Objekter - Programmering Denne guide er oprindeligt udgivet på Eksperten.dk Hvad er Objekter - Programmering En rigtig god gennemgang af hvad objekter er! Hvordan de oprettes og anvendes! Det er helt klart til nybegyndere, som

Læs mere

Specialkort med Valgdata

Specialkort med Valgdata Specialkort med Valgdata Søren Risbjerg Thomsen d. 25. april 2017 Introduktion I det følgende beskrives, hvordan man anvender Valgdata til at skabe specialkort, dvs. kort hvor man selv bestemmer indholdet

Læs mere

Finanstilsynets indberetningssystem. Vejledning til Regnearksskabelonerne

Finanstilsynets indberetningssystem. Vejledning til Regnearksskabelonerne Finanstilsynets indberetningssystem Vejledning til Regnearksskabelonerne Finanstilsynet - 2. udgave oktober 2009 Indholdsfortegnelse 1 INDLEDNING... 2 2 FORUDSÆTNINGER... 3 3 TRIN FOR TRIN... 4 3.1 Hent

Læs mere

Søren Christiansen 22.12.09

Søren Christiansen 22.12.09 1 2 Dette kompendie omhandler simpel brug af Excel til brug for simpel beregning, såsom mængde og pris beregning sammentælling mellem flere ark. Excel tilhører gruppen af programmer som samlet kaldes Microsoft

Læs mere

Vejledning i brugen af økonomiportalen 2010 Indhold

Vejledning i brugen af økonomiportalen 2010 Indhold Vejledning i brugen af økonomiportalen 2010 Indhold Køreplan for indberetning af regnskab og budget til provstiet.... 2 Hvordan indberettes regnskab 2010?... 2 Hvor kan jeg få hjælp.... 3 Kontrol af data

Læs mere

ectrl Skabelonkonvertering

ectrl Skabelonkonvertering ectrl Skabelonkonvertering Indholdsfortegnelse 1. Indledning 3 2. Import ved hjælp af standardskabeloner 4 Kolonneopsætning og feltdefinition 6 3. Opsætning af konverteringsdefinitioner 8 4. Udvidede muligheder

Læs mere

How to do in rows and columns 8

How to do in rows and columns 8 INTRODUKTION TIL REGNEARK Denne artikel handler generelt om, hvad regneark egentlig er, og hvordan det bruges på et principielt plan. Indholdet bør derfor kunne anvendes uden hensyn til, hvilken version

Læs mere

Visualiseringsprogram

Visualiseringsprogram Visualiseringsprogram Programmering C - eksamensopgave Rami Kaddoura og Martin Schmidt Klasse: 3.4 Vejleder: Karl Bjarnason Roskilde Tekniske Gymnasium Udleveringsdato: 02-03-2012 Afleveringsdato: 11-05-12

Læs mere

Ugeseddel 4 1. marts - 8. marts

Ugeseddel 4 1. marts - 8. marts Ugeseddel 4 1. marts - 8. marts Læs følgende sider i kapitel 6 i lærebogen: s. 233 258 og s. 291 317 (afsnit 6.3 overspringes). Begynd at overveje, hvad afleveringsopgaven skal omhandle. Læs vejledningen,

Læs mere

Sproget Rascal (v. 2)

Sproget Rascal (v. 2) Sproget Rascal (v. 2) Til brug i K1 på kurset Oversættere Opdateret 29/11 2004 Abstract Rascal er et simpelt Pascal-lignende imperativt sprog. Dette dokument beskriver uformelt Rascals syntaks og semantik

Læs mere

Abstrakte datatyper C#-version

Abstrakte datatyper C#-version Note til Programmeringsteknologi Akademiuddannelsen i Informationsteknologi Abstrakte datatyper C#-version Finn Nordbjerg 1/9 Abstrakte Datatyper Denne note introducerer kort begrebet abstrakt datatype

Læs mere

Michael Jokil 11-05-2012

Michael Jokil 11-05-2012 HTX, RTG Det skrå kast Informationsteknologi B Michael Jokil 11-05-2012 Indholdsfortegnelse Indledning... 3 Teori... 3 Kravspecifikationer... 4 Design... 4 Funktionalitet... 4 Brugerflade... 4 Implementering...

Læs mere

IT/Regneark Microsoft Excel Grundforløb

IT/Regneark Microsoft Excel Grundforløb januar 2018 Indhold Opbygning af et regneark... 3 Kolonner, rækker... 3 Celler... 3 Indtastning af tekst og tal... 4 Tekst... 4 Tal... 4 Værdier... 4 Opbygning af formler... 5 Indtastning af formler...

Læs mere

Vejledning. Excel-skabelon. til oprettelse af kalendere. Oversigtskalender_Skabelon_Revideret 05_06.xls

Vejledning. Excel-skabelon. til oprettelse af kalendere. Oversigtskalender_Skabelon_Revideret 05_06.xls Vejledning Excel-skabelon til oprettelse af kalendere Oversigtskalender_Skabelon_Revideret 05_06.xls 20-03-2017 Out of date Vejledningen til makrosikkerhed er nok noget forældet i forhold til nyere versioner

Læs mere

HTX, RTG. Rumlige Figurer. Matematik og programmering

HTX, RTG. Rumlige Figurer. Matematik og programmering HTX, RTG Rumlige Figurer Matematik og programmering Vejledere: Jørn Christian Bendtsen og Karl G. Bjarnason Morten Bo Kofoed Nielsen & Michael Jokil 10-10-2011 In this assignment we have been working with

Læs mere

KL S EFFEKTMÅLINGS- REDSKAB TIL KONTROLOMRÅDET

KL S EFFEKTMÅLINGS- REDSKAB TIL KONTROLOMRÅDET KL JANUAR 2017 TEKNISK VEJLEDNING KL S EFFEKTMÅLINGS- REDSKAB TIL KONTROLOMRÅDET OFFICE VERSION 2010 OG 2013 2 VEJLEDNING I ANVENDELSE AF VÆRKTØJ TIL EFFEKTMÅLING INDHOLD INDHOLD INDLEDNING A. TEKNISKE

Læs mere

BRUGERVEJLEDNING FIONA ONLINE

BRUGERVEJLEDNING FIONA ONLINE BRUGERVEJLEDNING FIONA ONLINE Indberetning til Nationalbankens betalingsbalance for erhvervsvirksomheder, forsikrings- og pensionsselskaber samt visse finansielle institutter Statistisk Afdeling Version

Læs mere

DM536. Rapport og debug

DM536. Rapport og debug DM536 Rapport og debug Kilder Vigtig.it (Felix Palludan Hargreaves) http://vigtig.it/dm502/howto_report.pdf http://vigtig.it/blog/teaching/#toc-relevant-tips Peter Schneider-Kamp http://imada.sdu.dk/~petersk/dm536/project2.pdf

Læs mere

Design by Contract Bertrand Meyer Design and Programming by Contract. Oversigt. Prædikater

Design by Contract Bertrand Meyer Design and Programming by Contract. Oversigt. Prædikater Design by Contract Bertrand Meyer 1986 Design and Programming by Contract Michael R. Hansen & Anne Haxthausen mrh@imm.dtu.dk Informatics and Mathematical Modelling Technical University of Denmark Design

Læs mere

Daglig brug af JitBesked 2.0

Daglig brug af JitBesked 2.0 Daglig brug af JitBesked 2.0 Indholdsfortegnelse Oprettelse af personer (modtagere)...3 Afsendelse af besked...4 Valg af flere modtagere...5 Valg af flere personer der ligger i rækkefølge...5 Valg af flere

Læs mere

GIS indlæsning af kreditorer og betalingsform. Brugervejledning 1.0

GIS indlæsning af kreditorer og betalingsform. Brugervejledning 1.0 GIS indlæsning af kreditorer og betalingsform Brugervejledning 1.0 Indhold 1 Indledning... 5 2 Opsætning af GIS grænseflade til kreditor indlæsning... 5 2.1 Oprettelse af en datastrøm... 7 2.2 Filsystem...

Læs mere

Nyheder til version 2013-3

Nyheder til version 2013-3 Nyheder til version 2013-3 En stærk brancheløsning fra Inventio.IT 1 Indledning... 3 2 C5 2012 SP 2 Nyheder... 3 2.1 Generelle revisor nyheder i C5... 3 3 C5 online Integration (fra version 2013)... 3

Læs mere

Vejledning i brugen af regneark til TOP-CUP, Vest

Vejledning i brugen af regneark til TOP-CUP, Vest Vejledning i brugen af regneark til TOP-CUP, Vest Formål med regnearket At tilbyde et enkelt system til oprettelse af stævner og registrering af stamoplysninger og indtastning af data, samt til udskrift

Læs mere

DM507 Algoritmer og datastrukturer

DM507 Algoritmer og datastrukturer DM507 Algoritmer og datastrukturer Forår 2018 Projekt, del II Institut for matematik og datalogi Syddansk Universitet 13. marts, 2018 Dette projekt udleveres i tre dele. Hver del har sin deadline, således

Læs mere

DM507 Algoritmer og datastrukturer

DM507 Algoritmer og datastrukturer DM507 Algoritmer og datastrukturer Forår 2018 Projekt, del II Institut for matematik og datalogi Syddansk Universitet 20. marts, 2019 Dette projekt udleveres i tre dele. Hver del har sin deadline, således

Læs mere

University of Southern Denmark Syddansk Universitet. DM502 Forelæsning 3

University of Southern Denmark Syddansk Universitet. DM502 Forelæsning 3 DM502 Forelæsning 3 Indlæsning fra tastatur Udskrift til skærm Repetition Beregning af middelværdi Gentagelse med stop-betingelse (while) Heltalsdivision Division med nul Type-casting ( (double) ) Betinget

Læs mere

Afgrænsning/filtrering, sortering m.v. i Klienten

Afgrænsning/filtrering, sortering m.v. i Klienten Afgrænsning/filtrering, sortering m.v. i Klienten Afgrænsning/filtrering I det efterfølgende gennemgås de tre standard afgrænsnings-/filtrerings metoder i Prisme Klient: Avanceret filter Er den overordnede

Læs mere

Python programmering. Per Tøfting. MacFest

Python programmering. Per Tøfting. MacFest Python programmering MacFest 2005 Per Tøfting http://pertoefting.dk/macfest/ Indhold Måder at afvikle Python program på Variabler Data typer Tal Sekvenser Strenge Tupler Lister Dictionaries Kontrolstrukturer

Læs mere

Vejledning INSTALLATION AF ZHC5010 BETJENINGSTRYK MED FIBARO HOME CENTER. ZHC5010 Firmware Version: 1.0

Vejledning INSTALLATION AF ZHC5010 BETJENINGSTRYK MED FIBARO HOME CENTER. ZHC5010 Firmware Version: 1.0 Vejledning INSTALLATION AF ZHC5010 BETJENINGSTRYK MED FIBARO HOME CENTER. ZHC5010 Firmware Version: 1.0 Indledning Denne vejledning beskriver hvordan det er muligt at oprette Z-Home Controls ZHC5010 Betjeningstryk

Læs mere

Indhold. Maskinstruktur... 3. Kapitel 1. Assemblersprog...3. 1.1 Indledning...3 1.2 Hop-instruktioner... 7 1.3 Input og output...

Indhold. Maskinstruktur... 3. Kapitel 1. Assemblersprog...3. 1.1 Indledning...3 1.2 Hop-instruktioner... 7 1.3 Input og output... Indhold Maskinstruktur... 3 Kapitel 1. Assemblersprog...3 1.1 Indledning...3 1.2 Hop-instruktioner... 7 1.3 Input og output... 9 Kapitel 2. Maskinkode... 13 2.1 Den fysiske maskine... 13 2.2 Assemblerens

Læs mere

JavaScript. nedarvning.

JavaScript. nedarvning. JavaScript er et sprog, der kan give en hjemmeside mere funktionalitet og gøre den interaktiv, så den reagerer på læsernes handlinger. CGI (Common Gateway Interface) har hidtil været de protokoller, man

Læs mere

F2 Godkendelser. Version 4.4

F2 Godkendelser. Version 4.4 F2 Godkendelser Version 4.4 Indholdsfortegnelse Generelt om F2 godkendelser... 3 Oversigt... 4 Oprettelse af godkendelse... 5 Skabelon... 5 Godkendelsesforløb... 6 Gem godkendelsesskabelon... 8 Godkendelsesoverblik...

Læs mere

Hent filoplysninger fra billeder og filer

Hent filoplysninger fra billeder og filer Hent filoplysninger fra billeder og filer I denne vejledning bliver det gennemgået, hvordan man via Power Forespørgsel kan hente filoplysninger fra en mappe ind i Excel. Der skal opbygges følgende elementer:

Læs mere

Gør det selv-øvelser udi regneark for begyndere! - en manual fra Skolekonsulenterne.dk

Gør det selv-øvelser udi regneark for begyndere! - en manual fra Skolekonsulenterne.dk Gør det selv-øvelser udi regneark for begyndere! - en manual fra Skolekonsulenterne.dk Versionsdato: August 2009 Indholdsfortegnelse Generelt om manualer fra Skolekonsulenterne.dk...3 Hvad er et regneark?...4

Læs mere

Målet for disse slides er at diskutere nogle metoder til at gemme og hente data effektivt.

Målet for disse slides er at diskutere nogle metoder til at gemme og hente data effektivt. Merging og hashing Mål Målet for disse slides er at diskutere nogle metoder til at gemme og hente data effektivt. Dette emne er et uddrag af kurset DM507 Algoritmer og datastrukturer (2. semester). Mål

Læs mere

Excel-6: HVIS-funktionen

Excel-6: HVIS-funktionen Excel-6: HVIS-funktionen Regnearket Excel indeholder et væld af "funktioner" som kan bruges til forskellige ting indenfor f.eks. finans, statistik, logiske beregninger, beregninger med datoer og meget

Læs mere

SWC eksamens-spørgsmål. Oversigt

SWC eksamens-spørgsmål. Oversigt SWC eksamens-spørgsmål Oversigt #1 Typer og variable #2 Aritmetik og logik #3 Klasser (definition, objekter) #4 Klasser (metoder) #5 Klasser (nedarvning, polymorfi) #6 Conditional statements #7 Repetition

Læs mere

e-konto manual 01.08.2011 e-konto manual Side 1

e-konto manual 01.08.2011 e-konto manual Side 1 e-konto manual 01.08.2011 e-konto manual Side 1 Indhold 1. Overordnet beskrivelse... 3 2. Login... 3 3. Se og ret kundeoplysninger... 4 4. Rediger kontaktoplysninger... 6 5. Skift adgangskode... 7 6. BroBizz-oversigt...

Læs mere

Indhold. Indholdsfortegnelse

Indhold. Indholdsfortegnelse Indholdsfortegnelse Indhold Indledning... 2 Forsiden... 2 Dine genveje... 3 Nyheder... 3 EasyIQ og EasyIQ Quick Funktioner... 3 Administration... 6 Licens... 7 Nyheder... 8 Log... 9 Password... 9 System...

Læs mere

Kort om indlæsning af excel filer til budgetkladder i Navision

Kort om indlæsning af excel filer til budgetkladder i Navision Kort om indlæsning af excel filer til budgetkladder i Navision Hovedproceduren er 1. I excel dannes en fil med en bestemt kolonnerækkefølge 2. Denne fil gemmes som semikolonsepareret fil (CSV MSDOS) 3.

Læs mere

Kursusbeskrivelse. Forarbejde. Oprettelse af en Access-database

Kursusbeskrivelse. Forarbejde. Oprettelse af en Access-database Kursusbeskrivelse Oprettelse af en Access-database Som eksempel på en Access-database oprettes en simpelt system til administration af kurser. Access-databasen skal indeholde: et instruktørkartotek et

Læs mere

Elevskema. Med modulet Elevskema kan du fordele eleverne på kurser og danne individuelle elevskemaer.

Elevskema. Med modulet Elevskema kan du fordele eleverne på kurser og danne individuelle elevskemaer. Elevskema Med modulet Elevskema kan du fordele eleverne på kurser og danne individuelle elevskemaer. Forudsætningen for at arbejde med modulet Elevskema er, at der i Untis er oprettet elever, som er tilknyttet

Læs mere

Start Excel Du skal starte med at åbne Excel. I Excel åbner du herefter en tom projektmappe.

Start Excel Du skal starte med at åbne Excel. I Excel åbner du herefter en tom projektmappe. Lineær programmering i Excel Version for PC I lærebogens kapitel 29 afsnit 4 er det med 2 eksempler blevet vist, hvordan kapacitetsstyringen kan optimeres, når der er 2 produktionsmuligheder og flere knappe

Læs mere

Funktions opdatering 4.5.01 ASPECT4 QueryManager (B=fejl, S=support/Info, T=Opgave, W=Releaseønske)

Funktions opdatering 4.5.01 ASPECT4 QueryManager (B=fejl, S=support/Info, T=Opgave, W=Releaseønske) ASPEC4 QueryManager (B=fejl, S=support/Info, =Opgave, =Releaseønske) 00001289 Dags dato som standardværdi Standardværdierne for datofelter i en rekvisition kan sættes til dynamiske datoer, således at rekvisitionsfeltet

Læs mere

Regneark hvorfor nu det?

Regneark hvorfor nu det? Regneark hvorfor nu det? Af seminarielektor, cand. pæd. Arne Mogensen Et åbent program et værktøj... 2 Sådan ser det ud... 3 Type 1 Beregning... 3 Type 2 Præsentation... 4 Type 3 Gæt... 5 Type 4 Eksperiment...

Læs mere

IFC Egenskaber. Mohammad Hussain Parsianfar s102951 BYG DTU

IFC Egenskaber. Mohammad Hussain Parsianfar s102951 BYG DTU Mohammad Hussain Parsianfar s102951 Indholdsfortegnelse 1 Introduktion... 3 1.1 Hvorfor er det interessant... 3 1.2 Formål... 4 2 Simplebim... 5 2.1 Præsentation af softwaren... 5 2.1.1 Brugergrænseflade...

Læs mere

Tlf. +45 7027 1699 Fax + 45 7027 1899

Tlf. +45 7027 1699 Fax + 45 7027 1899 Firmaordninger I firmaoversigten kan du holde styr på dit kundekartotek samt disses bookinger. Der kan desuden oprettes andre firmaer end dit eget. Herved kan der udbydes særlige ydelser på med egne arbejdstider.

Læs mere

Statistikudtræk. 1 Introduktion

Statistikudtræk. 1 Introduktion Statistikudtræk MADS MENU: RAPPORT STATISTIK STATISTIKUDTRÆK (D.4.1.) Revideret 20-09-2010 1 Introduktion I MADS kan statistiske data trækkes ud via enten statistikudtræk eller perioderapporter. I statistikudtræk

Læs mere

Vejledning. Excel-skabelon. til oprettelse af kalendere. Oversigtskalender_Skabelon_Revideret 05_01.xls

Vejledning. Excel-skabelon. til oprettelse af kalendere. Oversigtskalender_Skabelon_Revideret 05_01.xls Vejledning Excel-skabelon til oprettelse af kalendere Oversigtskalender_Skabelon_Revideret 05_01.xls 18-03-2017 Out of date Vejledningen til makrosikkerhed er nok noget forældet i forhold til nyere versioner

Læs mere

KMD Brugeradministration til Navision og LDV

KMD Brugeradministration til Navision og LDV KMD Brugeradministration til Navision og LDV Vejledning for Statens Administration og ØSC institutioner. Opdateret 09-09-2015 Indholdsfortegnelse 1 Kom godt i gang... 2 1.1 Login til KMD Brugeradministration...

Læs mere

Datatransport... 2. Import & Eksport af data... 2. Generelt... 2. Import/eksport... 4. Felter i Import og Eksport... 5

Datatransport... 2. Import & Eksport af data... 2. Generelt... 2. Import/eksport... 4. Felter i Import og Eksport... 5 Indhold Datatransport... 2 Import & Eksport af data... 2 Generelt... 2 Import/eksport.... 4 Felter i Import og Eksport... 5 Trykknapper til Import og Eksport... 7 1 Alle... 7 2 Slet... 7 3 Editor... 7

Læs mere

Manual til opsætning af Jit-klient version 1.0. Opsætning. Copyright Jit-Danmark Aps 2006. Find mere information på www.jitbesked.

Manual til opsætning af Jit-klient version 1.0. Opsætning. Copyright Jit-Danmark Aps 2006. Find mere information på www.jitbesked. Opsætning Indholdsfortegnelse Sådan finder du indstillingerne...3 Muligheder og begrænsninger...6 Hvilke søgeord skal jeg bruge?...6 Ting man skal passe på...6 Tilføjning/nedlægning af søgeord...6 Ændring

Læs mere

Jet Reports tips og tricks

Jet Reports tips og tricks Jet Reports tips og tricks Af Peter Christoffersen Ejer og grundlægger af Zeezit Zeezit Prinsensgade 20 9000 Aalborg info@zeezit.dk www.zeezit.dk Indledning Zeezit er grundlagt af Peter Christoffersen,

Læs mere

24-03-2009. Problemstilling ved DBK integration i BIM Software Hvad skal der til. Nicolai Karved, Betech Data A/S

24-03-2009. Problemstilling ved DBK integration i BIM Software Hvad skal der til. Nicolai Karved, Betech Data A/S 24-03-2009 Problemstilling ved DBK integration i BIM Software Hvad skal der til. Nicolai Karved, Betech Data A/S Problemstilling ved DBK integration i BIM Software Domæner og aspekter Det domæne, der primært

Læs mere

Brugermanual. Til Diabetesforeningens elektroniske regnskabsmodel

Brugermanual. Til Diabetesforeningens elektroniske regnskabsmodel Brugermanual Til Diabetesforeningens elektroniske regnskabsmodel Brugermanual til Diabetesforeningens elektroniske regnskabsmodel 1. Indledning Diabetesforeningens elektroniske regnskabsmodel findes på

Læs mere

Navision Stat 7.0. CVR Integration. Overblik. Side 1 af 15. 30. april 2015 ØS/ØSY/MAG

Navision Stat 7.0. CVR Integration. Overblik. Side 1 af 15. 30. april 2015 ØS/ØSY/MAG Side 1 af 15 Navision Stat 7.0 30. april 2015 ØS/ØSY/MAG CVR Integration Overblik Introduktion I denne vejledning kan du læse om, hvordan du validerer dine debitorers og kreditorers data op imod Det Centrale

Læs mere

Vejledning. Indlæsning af studerende til gruppedannelse i STADS. Indhold. Studie-IT Tlf.:

Vejledning. Indlæsning af studerende til gruppedannelse i STADS. Indhold. Studie-IT Tlf.: Studie-IT Tlf.: 9940 9720 Vejledning Indlæsning af studerende til gruppedannelse i STADS Indhold Indledning.... 2 Udvælgelse af data. i istads... 2 Generering af data... 5 Generering af data fra et excel-ark...

Læs mere

SecureAware Compliance Analysis Manual

SecureAware Compliance Analysis Manual SecureAware Compliance Analysis Manual Manualen beskriver brugen af SecureAware version 3 Dokument opdateret: november 2009 Om dette dokument Dette dokument er en vejledning i, hvordan du opretter compliance-checks.

Læs mere

Opret en Powerpoint præsentation automatisk med VBA

Opret en Powerpoint præsentation automatisk med VBA Opret en Powerpoint præsentation automatisk med VBA I denne vejledning bliver det gennemgået, hvordan man via VBA kan oprette en powerpoint med diagrammer og kommentarer fra Excel automatisk. Gør som følgende:

Læs mere

Avanceret kampagnestyring

Avanceret kampagnestyring Indlæsning af egne kampagner:... 1 Prioritering af kampagner... 3 Arbejdsgangen er følgende:... 3 Mere om RET:... 4 Kampagne numre:... 4 Rapportudskrivning af kampagner:... 4 Udskriv prismærker for en

Læs mere

Kontoskemaet i DSM kan benyttes til at lave forskellige regnskabs- eller nøgletalsrapporter, mulighederne er mange.

Kontoskemaet i DSM kan benyttes til at lave forskellige regnskabs- eller nøgletalsrapporter, mulighederne er mange. Kontoskema Kontoskemaet i DSM kan benyttes til at lave forskellige regnskabs- eller nøgletalsrapporter, mulighederne er mange. I det efterfølgende vises, hvordan en simpel regnskabsrapport kan laves ved

Læs mere

Binært LAS-format Denne indstilling import Laser scan datafiler, i LAS format.

Binært LAS-format Denne indstilling import Laser scan datafiler, i LAS format. Kvadratnetsmodel - Import af Laser Scan Datafiler Funktionen til at oprette kvadratnetsmodeller er nu blevet udvidet og omfatter nu også en funktion til at importere laser scanning datafiler. Metoden bag

Læs mere

KL S EFFEKTMÅLINGS- REDSKAB TIL KONTROLOMRÅDET

KL S EFFEKTMÅLINGS- REDSKAB TIL KONTROLOMRÅDET KL FEBRUAR 2019 TEKNISK VEJLEDNING KL S EFFEKTMÅLINGS- REDSKAB TIL KONTROLOMRÅDET OFFICE VERSION 2010 OG 2013 2 INDHOLD INDHOLD INDLEDNING A. TEKNISKE KRAV SIDE 3 SIDE 4 B. HVORDAN GØRES ALLE VÆRKTØJETS

Læs mere

Vejledning til udtræk fra UNIK (Version: UNIK Bolig 4)

Vejledning til udtræk fra UNIK (Version: UNIK Bolig 4) Vejledning til udtræk fra UNIK (Version: UNIK Bolig 4) Udtræk af data fra UNIK skal ske ved at danne rapporter. I UNIK er der mulighed for at danne tre forskellige slags rapporter: 1) Fastprogrammerede

Læs mere

DATO DOKUMENT SAGSBEHANDLER MAIL TELEFON. 17. december 2015 Version 1.2 JobManager supporten

DATO DOKUMENT SAGSBEHANDLER MAIL TELEFON. 17. december 2015 Version 1.2 JobManager supporten DATO DOKUMENT SAGSBEHANDLER MAIL TELEFON 17. december 2015 Version 1.2 JobManager supporten Jobmanager@vd.dk 7244 7300 AFGIV TILBUD ENTREPRENØR Guldalderen 12 2640 Hedehusene vd@vd.dk EAN 5798000893450

Læs mere

χ 2 -test i GeoGebra Jens Sveistrup, Gammel Hellerup Gymnasium

χ 2 -test i GeoGebra Jens Sveistrup, Gammel Hellerup Gymnasium χ 2 -test i GeoGebra Jens Sveistrup, Gammel Hellerup Gymnasium Man kan nemt lave χ 2 -test i GeoGebra både goodness-of-fit-test og uafhængighedstest. Den følgende vejledning bygger på GeoGebra version

Læs mere

Design by Contract. Design and Programming by Contract. Oversigt. Prædikater

Design by Contract. Design and Programming by Contract. Oversigt. Prædikater Design by Contract Design and Programming by Contract Anne Haxthausen ah@imm.dtu.dk Informatics and Mathematical Modelling Technical University of Denmark Design by Contract er en teknik til at specificere

Læs mere

IDAP manual Emission

IDAP manual Emission IDAP manual Emission Dato: 08-06-2005 16:32:35 Indhold INDHOLD... 1 1 EMISSION... 2 1.1 KURVER... 2 1.2 RAPPORTER... 5 1.3 DATA REDIGERING... 6 1.3.1 Masse redigering... 7 1.3.2 Enkelt redigering... 10

Læs mere

Import af rekursivt (parent-child) hierarki i Palo

Import af rekursivt (parent-child) hierarki i Palo Import af rekursivt (parent-child) hierarki i Palo Dette dokument beskriver hvordan et simpelt rekursivt (parent-child) hierarki kan importeres ind i Palo på forskellige måder via SQL og samtidig bibeholde

Læs mere

TeamShare 2.1 Versionsnoter Oktober 2009

TeamShare 2.1 Versionsnoter Oktober 2009 TeamShare 2.1 Versionsnoter Oktober 2009 TeamShare version 2.1.292 Denne version af TeamShare har fået mange nye funktioner, samt forbedringer på eksisterende. Hver ny feature er gennemgået i hvert sit

Læs mere

Indledning. MIO er optimeret til Internet Explorer. Læs endvidere under Ofte stillede spørgsmål.

Indledning. MIO er optimeret til Internet Explorer. Læs endvidere under Ofte stillede spørgsmål. Indhold Indledning... 3 Søgefunktioner... 4 Søgning fra forsiden... 5 Søgning under menupunktet Instrument... 6 Sådan får man vist instrumenterne i en bestemt afdeling... 7 Sådan ændrer man status på et

Læs mere

Hukommelsesspil. Introduktion. Scratch

Hukommelsesspil. Introduktion. Scratch Scratch 2 Hukommelsesspil All Code Clubs must be registered. By registering your club we can measure our impact, and we can continue to provide free resources that help children learn to code. You can

Læs mere

ALMINDELIGT ANVENDTE FUNKTIONER

ALMINDELIGT ANVENDTE FUNKTIONER ALMINDELIGT ANVENDTE FUNKTIONER I dette kapitel gennemgås de almindelige regnefunktioner, samt en række af de mest nødvendige redigerings- og formateringsfunktioner. De øvrige redigerings- og formateringsfunktioner

Læs mere

Vejledning: Anvendelse af kuber på NS-data fra LDV i Excel 2007. Målgruppe: Slutbruger

Vejledning: Anvendelse af kuber på NS-data fra LDV i Excel 2007. Målgruppe: Slutbruger Vejledning: Anvendelse af kuber på NS-data fra LDV i Excel 2007. Målgruppe: Slutbruger April 2015 Indholdsfortegnelse Indholdsfortegnelse 2 1 Indledning 3 1.1 Metode til anvendelse af kuber med Excel 2007

Læs mere

Formular modul. Sitecore Foundry juli Version 1.0

Formular modul. Sitecore Foundry juli Version 1.0 Sitecore Foundry 3.0 Formular modul 15. juli 2011 - Version 1.0 Pentia A/S Store Kongensgade 66, Baghuset 1264 København K Telefon: 7023 3330 E-mail: info@foreningssite.dk Indholdsfortegnelse Indledning...

Læs mere

Det er muligt at chekce følgende opg. i CodeJudge: og

Det er muligt at chekce følgende opg. i CodeJudge: og Det er muligt at chekce følgende opg. i CodeJudge:.1.7 og.1.14 Exercise 1: Skriv en forløkke, som producerer følgende output: 1 4 9 16 5 36 Bonusopgave: Modificer dit program, så det ikke benytter multiplikation.

Læs mere

Ruko Security Master Central Database

Ruko Security Master Central Database Ruko Security Master Central Database RSM benytter en central database, til at udveksle låsesystemer mellem Ruko og låsesmeden. Udvekslingen sker via Internettet, så det er derfor nødvendigt at have en

Læs mere

Forelæsning Uge 4 Torsdag

Forelæsning Uge 4 Torsdag Forelæsning Uge 4 Torsdag Algoritmeskabeloner findone, findall, findnoof, findsumof (i mandags) findbest Levetid for variabler og parametre Virkefeltsregler Hvor kan man bruge de forskellige variabler?

Læs mere

Masseredigering af tilmeldinger pa virksomhedens side

Masseredigering af tilmeldinger pa virksomhedens side Masseredigering af tilmeldinger pa virksomhedens side 7. udgave, revideret marts 2012 Vejledningen er opdateret i forbindelse med indførelse af ny side til masseredigering af tilmeldinger. Denne vejledning

Læs mere

Harald Michalsen og Lasse Storr-Hansen. Log på med administrator rettigheder, så du ser ovenstående hovedmenu

Harald Michalsen og Lasse Storr-Hansen. Log på med administrator rettigheder, så du ser ovenstående hovedmenu Importér skemadata fra Lectio 1 af 16 Log på med administrator rettigheder, så du ser ovenstående hovedmenu Vælg Konverter skemadata Klik på Eksporter skemadata Importér skemadata fra Lectio 2 af 16 Vælg

Læs mere

Boligsøgning / Search for accommodation!

Boligsøgning / Search for accommodation! Boligsøgning / Search for accommodation! For at guide dig frem til den rigtige vejledning, skal du lige svare på et par spørgsmål: To make sure you are using the correct guide for applying you must answer

Læs mere

Assignment #5 Toolbox Contract

Assignment #5 Toolbox Contract Assignment #5 Toolbox Contract Created by: René Kragh Trine Randløv E mail address cph rk70@cphbusiness.dk 23 11 2014 1 Introduktion Dette dokument indeholder en vertikal kontrakt for et system som skal

Læs mere

OFFICEUNIVERSET.DK. ^ + SKIFT + ; (semikolon) Formellinje - skift mellem udvid og fold CTRL + SKIFT + U

OFFICEUNIVERSET.DK. ^ + SKIFT + ; (semikolon) Formellinje - skift mellem udvid og fold CTRL + SKIFT + U Excel Genveje GENVEJSTASTER Formatering Fed CTRL + F CMD + F Kursiv CTRL + K CMD + K Understreget CTRL + U CMD + U Gennemstreget CTRL + 5 CMD + SKIFT + X Konturkant på markerede celler CTRL + SKIFT + &

Læs mere

1. Basal select med (stjerne)

1. Basal select med (stjerne) 1. Basal select med (stjerne) 1. List alle øltyper. a. select * from oltyper 2. List alle bryggerier a. select * from bryggeri 3. List alle Danmarks postnumre samt tilhørende by, landsdel og antal indbyggere

Læs mere

Indholdsfortegnelse. EasyIQ IDM 5.4 Brugermanual

Indholdsfortegnelse. EasyIQ IDM 5.4 Brugermanual Indholdsfortegnelse Indledning... 2 Forsiden... 2 Dine genveje... 3 Nyheder... 3 EasyIQ og EasyIQ Quick Funktioner... 3 Administration... 8 Licens... 8 Nyheder... 9 Eksterne links... 11 Log... 12 Password...

Læs mere

Dynamic Order Kom godt i gang

Dynamic Order Kom godt i gang Dynamic Order Kom godt i gang Projektstyring Ressourcestyring Kompetencestyring - Timeregistrering Side 1 af 17 Indholdsfortegnelse Dynamic Order Kom godt i gang... 1 Indholdsfortegnelse... 2 Introduktion...

Læs mere

matematik Demo excel trin 2 bernitt-matematik.dk 1 excel 2 2007 by bernitt-matematik.dk

matematik Demo excel trin 2 bernitt-matematik.dk 1 excel 2 2007 by bernitt-matematik.dk matematik excel trin 2 bernitt-matematik.dk 1 excel 2 2007 by bernitt-matematik.dk matematik excel 2 1. udgave som E-bog 2007 by bernitt-matematik.dk Kopiering af denne bog er kun tilladt efter aftale

Læs mere

Regneark for begyndere

Regneark for begyndere Regneark for begyndere Regneark i Open- og LibreOffice Version: August 2012 Indholdsfortegnelse Hvad er et regneark?...4 Grundlæggende opbygning...4 Kast dig ud i det!...5 Du arbejder med: Din første

Læs mere

Identifikation af planer der ikke findes i PlansystemDK vha. datasættet... 9

Identifikation af planer der ikke findes i PlansystemDK vha. datasættet... 9 Vejledning i brug af Tingbogsudtrækket Version 1.0 af 1. juli 2009 Indhold Indledning... 1 Planer i Tingbogen... 2 Planer i PlansystemDK... 3 Sammenhæng mellem Tingbogen og PlansystemDK... 3 Datastruktur...

Læs mere

GECKO Booking Vejledning til spørgeskema-modul. Læsevejledning. Indholdsfortegnelse

GECKO Booking Vejledning til spørgeskema-modul. Læsevejledning. Indholdsfortegnelse GECKO Booking Vejledning til spørgeskema-modul Er der behov for at få et indgående kendskab til kunden, når de bruger bookingsystemet? Hvad siger brugerne efterfølgende om den service, de har fået? Ved

Læs mere

FORGRENINGSLOGIK OG CALCULATED FIELDS. Opsætning af forgreningslogik Felttypen Calculated field

FORGRENINGSLOGIK OG CALCULATED FIELDS. Opsætning af forgreningslogik Felttypen Calculated field FORGRENINGSLOGIK OG CALCULATED FIELDS Opsætning af forgreningslogik Felttypen Calculated field Felt-referencer i REDCap Når man anvender forgreningslogik, beregnede felter eller piping i REDCap, refererer

Læs mere

Excel regneark. I dette kapitel skal I arbejde med noget af det, Excel regneark kan bruges til. INTRO EXCEL REGNEARK

Excel regneark. I dette kapitel skal I arbejde med noget af det, Excel regneark kan bruges til. INTRO EXCEL REGNEARK Excel regneark Et regneark er et computerprogram, der bl.a. kan regne, tegne grafer og lave diagrammer. Regnearket kan bruges i mange forskellige sammenhænge, når I arbejder med matematik. Det kan gøre

Læs mere

Test af It-komponent

Test af It-komponent Test af It-komponent I programmeringssproget Java Programmet Login service Elev: Mads Funch Klasse 2.4 Mat, It, Programmering Skole: Roskilde Tekniske Gymnasium HTX Underviser: Karl Dato: 31-08-2016 Side

Læs mere