LUNDS TEKNISKA HÖGSKOLA Institutionen för datavetenskap Bedömning av kontrollskrivning, EDA016 Programmeringsteknik 2015-10-27 Instruktioner Maxpoäng per uppgift Med en icke-tom rad menas en kodrad som inte är en blankrad, kommentarsrad eller rad med endast en ensam klammer }. Varje uppgift har en mönsterlösning som återfinns senare i detta häfte. Maxpoängen för varje uppgift utgörs av antalet icke-tomma rader i mönsterlösningen gånger 3. Maxpoängen för varje del av en uppgift (t.ex. en metod, attributdeklarationer i en klass, en loop) utgörs av antalet icke-tomma rader i motsvarande del av mönsterlösningen gånger 3. Bedömning av poäng För varje uppgift: Läs först mönsterlösningen och sätt dig in i angreppssätt och funktion. Läs sedan lösningen du ska bedöma och sätt dig in i angreppssätt och funktion. För varje icke-tom rad i mönsterlösningen: Försök leta upp motsvarande enskild rad i skrivningen du bedömer och bedöm om raden är värd 0, 1, 2, eller 3 poäng, enligt skalan i tabell 1 nedan. Om du inte kan hitta en enskild motsvarande rad, välj i stället en sekvens av rader i mönsterlösningen som motsvarar en sekvens av rader i skrivningen du bedömer, tex. motsvarande if-sats, loop, metod, etc. Bedöm enligt tabell 1 där max är 3 gånger antalet icke-tomma mönsterlösningsrader. Tabell 1: Bedömningsskala i fyra nivåer för enskild rad eller sekvens av rader. Poäng Poängintervall Nivå enskild rad sekvens av rader Nästan perfekt kod. 3 max Bra kod med små fel. 2 [ 2 3 max, max 1] beroende på antal fel Kod med stora fel. 1 [1, 2 3 max 1] beroende på antal fel Kod saknas, är obegriplig eller helt fel. 0 0 Ge maxpoäng om koden är korrekt, läsbar och lika bra som mönsterlösningen även om den är annorlunda. Det finns många olika sätt att lösa varje del, varav många är lika bra som mönsterlösningen. Du ska t.ex. inte bestraffa lösningar bara för att de är kortare eller längre än mönsterlösningen. En lösning anses nästan perfekt även om det förekommer enstaka smärre fel som en kompilator lätt hittar. Du ska alltså ge maxpoäng för en korrekt, läsbar och bra lösning även om obetydliga fel förekommer. Exempel på obetydliga fel: enstaka saknade semikolon, enstaka glömda parentespar vid parameterlösa metodanrop, enstaka vilseledande indragningar. 1
2(5) En lösning anses ha små fel om man ganska enkelt kan fixa ett eller ett par fel utan att ett i grunden bra angreppsätt behöver ändras. Exempel: enstaka glömd variabeldeklaration, glömd uppräkning av loopvariabel i while-sats, felaktig indexering (+1, -1) i en vektor, <= istället för <, fel ordning på parametrar, glömt synlighetsnyckelord t.ex. public eller private. En lösning anses ha stora fel om det kräver stora ändringar för att fixa ett flertal fel och mycket, men inte allt, behöver skrivas om för att det ska fungera som det är tänkt. Ge noll poäng om lösningen saknas, är oläsbar, obegriplig eller helt fel. Helhetsbedömning av en uppgift. Avsluta med att göra en kvalitativ helhetsbedömning av poängsumman för varje uppgift och justera poäng för vissa delar om du tycker att poängsumman för hela uppgiften inte alls överensstämmer med definitionen av nivåerna i tabell 1 ovan. Markering av poängavdrag (negativa) och uppgiftspoäng (inringad, positiv) Markeringar i skrivningen du bedömer ska göras med en penna med avvikande färg, gärna röd. Stryk under de delar av en rad som är felaktiga eller bara delvis korrekta. Dra ett vågrät streck när något som är viktigt för en korrekt och bra lösning saknas helt och skriv en kommentar om vad som saknas. Markera poängavdrag i högerkanten med minuspoäng för enskild rad, 1 för ett litet fel, 2 för stort fel, och 3 för helt felaktig rad, enligt bedömningsriktlinjerna i förra stycket. Om du bedömer en sekvens av rader, dra ett lodrät streck bredvid raderna i sekvensen och markera poängavdrag så att bedömningen motsvarar tabell 1 ovan. När du markerat relevanta avdrag för en hel uppgift, beräkna och skriv uppgiftspoäng inringad i en cirkel, så att det går lätt att skilja uppgiftspoäng från poängavdrag. Uppgiftspoängen ska inte vara negativ utan ligga i intervallet [0, Maxpoäng]. Om det inte är uppenbart varför du ej givit maxpoäng, skriv då en kort förklaring i kanten. Om en lösning är oläslig eller helt obegriplig, skriv oläsligt eller obegripligt i kanten. Mappning från poäng till individuell bonus När du är färdig med bedömningen av alla uppgifter, summera totalpoängen t och skriv den på skrivningsomslaget så här: Totalt: t. Mappa totalpoängen t till bonus b enligt tabell 3 i mönsterlösningsdelen och skriv på omslaget Bonus: b där b {0, 1, 2, 3}. Gränserna är beräknade enligt tabell 2: Tabell 2: Mappning totalpoäng t bonus b. Intervall t bonus b [0, 1 4 max 1] 0 [ 4 1 max, 4 2 max 1] 1 [ 4 2 max, 4 3 max 1] 2 [ 3 4 max, max] 3 Helhetsbedömning av en skrivning. Gör en kvalitativ bedömning av skrivningen som helhet, särskilt om totalpoängen hamnar några poäng över eller under en gräns. Jämför helhetsbedömningen med andemeningen av nivåerna i tabell 1 och kontrollera att bonus motsvarar helhetsintrycket av skrivningen. Om så inte är fallet kanske rättningen är för hård eller för snäll på vissa ställen. Gå i så fall tillbaks och justera delpoäng som kan anses ha hamnat fel.
3(5) Mönsterlösningar Tabell 3: (a) Maxpoäng per uppgift. (b) Mappning totalpoäng t bonus b. Antalet icke-tomma Uppgift mönsterlösningsrader Maxpoäng 1 10 30 2 35 105 3 14 42 Totalt 59 177 Intervall t bonus b [0, 43] 0 [44, 87] 1 [88, 132] 2 [133, 177] 3 Mönsterlösning till uppgift 1. Totalt 10 icke-tomma rader ger max 30p. 1 public class Notes { // max 9p 2 private static final String[] notes = 3 {"A", "A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#"}; 4 5 public static int fromnametonumber(string note){ // max 15p 6 int i = 0; 7 while (i < notes.length &&!notes[i].equals(note)){ 8 i++; 9 } 10 return i < 12? i : -1; 11 } 12 13 public static String fromnumbertoname(int i){ // max 6p 14 return notes[i % 12]; 15 } 16 } if-sats i stället för villkorsuttryck. for-loop i stället för while-sats if-sats med return istället för loop-villkor Glömd static-deklaration Implementerad konstruktor fast den inte behövs. Returnerar inte -1 för tonnamn som inte finns. för tidig return så att loopen inte går igenom hela vektorn om tonnamn saknas fel eller saknad modulo-beräkning i % 12 Mönsterlösning till uppgift 2. Totalt 35 icke-tomma rader ger max 105p. 1 public class Chord { // max 12p 2 private String name; 3 private int[] grip; 4 private String[] tuning; 5
4(5) 6 public Chord(String name, int[] grip, String[] tuning){ // max 12p 7 this.name = name; 8 this.grip = grip; 9 this.tuning = tuning; 10 } 11 12 public int numberofstrings(){ // max 6p 13 return tuning.length; 14 } 15 16 public int lowestfret(){ // max 24p 17 int min = Integer.MAX_VALUE; 18 int string = 1; 19 while (string <= numberofstrings() && min > 0){ 20 if (grip[string - 1] < min) { 21 min = grip[string - 1]; 22 } 23 string++; 24 } 25 return min; 26 } 27 28 public int highestfret(){ // max 18p 29 int max = 0; 30 for (int i=0; i < grip.length; i++){ 31 if (grip[i] > max) { 32 max = grip[i]; 33 } 34 } 35 return max; 36 } 37 38 public String getnote(int i){ // max 9p 39 int note = Notes.fromNameToNumber(tuning[i-1]) + grip[i-1]; 40 return Notes.fromNumberToName(note); 41 } 42 43 public String tostring(){ // max 24p 44 StringBuilder result = new StringBuilder(name + ":"); 45 for (int string = 1; string <= numberofstrings(); string++){ 46 result.append(" " + grip[string-1]); 47 } 48 result.append(";"); 49 for (int string = 1; string <= numberofstrings(); string++){ 50 result.append(" " + getnote(string)); 51 } 52 return result.tostring(); 53 } 54 } Lösningen använder String istället för StringBuilder (det blir mindre effektivt men skillnaden är inte så stor när det görs ett litet antal append på små strängar). Det går bra att köra loopar från 0 eller 1 givet att indexeringen ändå är rätt och lösningen fungerar. lowestfret avbryter inte loopen när en öppen sträng hittas. tostring missar enstaka blanktecken eller semikolon. tostring ger enstaka blanktecken eller semikolon för mycket.
5(5) Saknad this som behövs för att det ska fungera. Variabel som borde vara lokal är deklarerad som ett attribut. Mönsterlösning till uppgift 3. Totalt 14 icke-tomma rader ger max 42p. 1 public String fretboard(){ // max 42p 2 StringBuilder result = new StringBuilder(); 3 int lastfret = Math.max(highestFret(), 4); 4 for(int fret=0; fret <= lastfret; fret++){ 5 char separator = (fret == 0)? _ : ; 6 char unpressed = (fret == 0)? : ; 7 result.append(separator); 8 for (int string = 1; string <= numberofstrings(); string++){ 9 if (fret == grip[string-1]) { 10 result.append("*" + separator); 11 } else { 12 result.append("" + unpressed + separator); 13 } 14 } 15 result.append(fret + "\n"); 16 } 17 return result.tostring(); 18 } if-sats i stället för villkorsuttryck. if-sats i stället för Math.max eller annan motsvarande lösning. Det går bra att köra loopar från 0 eller 1 givet att slutvillkor och vektorindexering ändå är rätt och lösningen fungerar. Lösningen använder String istället för StringBuilder (det blir mindre effektivt men skillnaden är inte så stor när det görs ett litet antal append på små strängar). Några blanktecken eller nyradstecken för lite eller för mycket. Glömd tostring på StringBuilder innan strängvärdet returneras. Lösningen skriver inte ut minst 4 band för alla grepp, vilket ingår i uppgiftens krav. Looparna går inte igenom alla strängar och alla band så att strängen som returneras blir ofullständig eller felaktig. För tidig return så att de nästlade looparna inte fungerar som de ska.