| Pisteet.java |
1 package hirsipuu;
2
3 import java.io.BufferedReader;
4 import java.io.File;
5 import java.io.FileNotFoundException;
6 import java.io.FileOutputStream;
7 import java.io.FileReader;
8 import java.io.IOException;
9 import java.io.PrintStream;
10
11
12 /**
13 * Luokka pisteiden k??sittelyyn. Osaa lukea Pisteet.dat tiedostoa ja palauttaa tasoa ja pelaajaa vastaavan pistem????r??n.
14 * @author Anna-Leena Latvala, Toni Purontaka
15 * @version v0.6, 15.4.2008
16 *
17 */
18 public class Pisteet {
19
20 private final int tasojenlkm;
21 private PelaajanPiste[] pisteet = new PelaajanPiste[30];
22 private int lkm = 0; // k?yt?ss? olevien pisteiden lkm
23 private final static String POLKU = "pisteet.dat";
24
25
26 /**
27 * Alustaa Pisteet defaulttitiedostosta.
28 */
29 public Pisteet(int lkm) {
30 tasojenlkm = lkm;
31 pisteetTiedostosta(POLKU);
32 }
33
34 /**
35 * Alustaa Pisteet tiedostosta polussa "polku".
36 */
37 public Pisteet(String polku, int lkm) {
38 tasojenlkm = lkm;
39 pisteetTiedostosta(polku);
40 }
41
42 /**
43 * Lukee tiedostosta pelaajan pisteet annettua tasoa vastaavasti. Tiedosto kirjoitetaan muotoon
44 * pid | tid | pisteet
45 * ja ;-alkuiset rivit tulkitaan kommenttiriveiksi.
46 *
47 * @example
48 * <pre name="test">
49 * #THROWS IOException
50 * #import java.io.IOException;
51 * #import fi.jyu.mit.ohj2.VertaaTiedosto;
52 * VertaaTiedosto.kirjoitaTiedosto("testitasoja.txt",
53 * "1 | 1 | 12\n"+
54 * ";tama rivi on kommentti\n" +
55 * "1 | 2 | 100\n"+
56 * "2 | 1 | 95");
57 * Pisteet Pisteet = new Pisteet("testitasoja.txt", 2);
58 * VertaaTiedosto.tuhoaTiedosto("testitasoja.txt");
59 * </pre>
60 *
61 */
62 public final void pisteetTiedostosta(String polku) {
63 BufferedReader fi;
64
65 try { //aukaistaan lukija
66 fi = new BufferedReader(new FileReader(polku));
67 } catch (FileNotFoundException ex) {
68 System.err.println("Tiedosto " + polku + " ei aukea!");
69 return;
70 }
71
72 try {
73 String s;
74 while ( ( s = fi.readLine() ) != null) {
75 lisaaPiste(s);
76 }
77 } catch (IOException ex) {
78 System.err.println("Virhe tiedostoa luettaessa!");
79
80 } finally { // suljetaan tietovirta
81 try {
82 fi.close();
83 } catch (IOException ex) {
84 System.err.println("Tiedostoa ei saa suljettua!");
85 }
86 }
87 }
88
89 /**
90 * Tulostaa tasokohtaiset pisteet defaulttitiedostoon.
91 * @return true, jos tallennus onnistui, false muutoin
92 */
93 public boolean tallennaTiedot() {
94 return tallennaTiedot(POLKU);
95 }
96
97
98 /**
99 * Tulostaa pelaajien tasokohtaiset pisteet tiedostoon polussa "polku" ja muuttaa entisen siell? sijainneen
100 * tiedoston back-up tiedostoksi polku.bak (esim. pisteet.dat -> pisteet.dat.bak)
101 * @param polku tiedosto, johon tiedot kirjoitetaan
102 * @return true, jos tallennus onnistui, false muuten
103 *
104 * @example
105 * <pre name="test">
106 * #THROWS IOException
107 * #import java.io.IOException;
108 * #import fi.jyu.mit.ohj2.VertaaTiedosto;
109 * VertaaTiedosto.kirjoitaTiedosto("testipisteita.txt",
110 * "; pid | tid | pisteet |\n" +
111 * "1|1|12\n"+
112 * "1|2|100\n"+
113 * "2|1|95");
114 *
115 * Pisteet pis = new Pisteet("testipisteita.txt",3);
116 * pis.tallennaTiedot("testitallennus.txt"); // ei ole testitallennus.txt ennen joten ei backuppia
117 *
118 * Pisteet pus = new Pisteet("testitallennus.txt",3);
119 * pus.paivitaPiste(1,1,50); // muutetaan tietoja
120 * pus.tallennaTiedot("testitallennus.txt"); // syntyy backup-tiedosto
121 *
122 * VertaaTiedosto.vertaaFileFile("testipisteita.txt", "testitallennus.txt.bak") === null; // samat
123 * (VertaaTiedosto.vertaaFileFile("testipisteita.txt", "testitallennus.txt") == null) === false; // erit
124 *
125 * VertaaTiedosto.tuhoaTiedosto("testipisteita.txt");
126 * VertaaTiedosto.tuhoaTiedosto("testitallennus.txt"); // tuhotaan syntyneet tiedostot
127 * VertaaTiedosto.tuhoaTiedosto("testitallennus.txt.bak"); // my?s back-up
128 * </pre>
129 */
130 public boolean tallennaTiedot(String polku) {
131 PrintStream fo;
132 File vanha = new File(polku);
133 File backuppi = new File(polku + ".bak");
134 vanha.renameTo(backuppi);
135
136 try {
137 fo = new PrintStream(new FileOutputStream(polku));
138 } catch (FileNotFoundException ex) {
139 System.err.println("Tiedosto " + polku + " ei aukea!"); return false;
140 }
141
142 try {
143 fo.println("; pid | tid | pisteet |");
144 for (int i = 0; i < lkm; i++) {
145 fo.println(pisteet[i].tiedotToString());
146 }
147 } finally {
148 fo.close();
149 }
150 return true;
151
152 }
153
154 /**
155 * Palauttaa pelaajan kaikki pisteet kokonaislukutaulukkona.
156 * @param pelaajanid pyydetyn pelaajan id-numero
157 * @return 2d-kokonaislukutaulu, jossa vierekk?isiss? alkioissa on tason nro ja silt? saadut pisteet
158 * tai 0 jos tasoa ei ole viel? pelattu.
159 *
160 * @example
161 * <pre name="test">
162 * #THROWS IOException
163 * #import java.io.IOException;
164 * #import fi.jyu.mit.ohj2.VertaaTiedosto;
165 * VertaaTiedosto.kirjoitaTiedosto("testitasoja.txt",
166 * ";tiedostossa on pelaajien pisteit?\n" +
167 * "1 | 1 | 12\n"+
168 * "1 | 2 | 100\n"+
169 * "2 | 1 | 95");
170 * Pisteet pisteet = new Pisteet("testitasoja.txt", 8);
171 *
172 * int[][] taulu = pisteet.annaPisteet(1); //pelaajan 1 pisteet
173 * taulu[0][0] === 1;
174 * taulu[1][0] === 12;
175 * taulu[1][1] === 100;
176 * taulu[0][7] === 8; // taso nro 8 on paikassa 7
177 * taulu[1][4] === 0; // tasolle 4 ei ole pisteit? joten pisteet on 0
178 *
179 * VertaaTiedosto.tuhoaTiedosto("testitasoja.txt");
180 * </pre>
181 */
182 public int[][] annaPisteet(int pelaajanid) {
183 int[][] palautus = new int[2][tasojenlkm];
184 for (int i=0; i < tasojenlkm; i++) {
185 palautus[0][i] = i+1;
186 for (int j=0; j < lkm; j++) {
187 if (pisteet[j].pisteet(pelaajanid, i+1) > -1) {
188 palautus[1][i] = pisteet[j].pisteet(pelaajanid, i+1);
189 break;
190 }
191 }
192 }
193 return palautus;
194 }
195
196 /**
197 * P?ivitt?? pelaajan tasolta saamat pisteet. Jos ennen on saatu samalta tasolta paremmat
198 * pisteet, ei muuteta. Jos tehtiin uusi enn?tys, muutetaan, samoin kuin jos on kyseess?
199 * 1. kerta kun tasoa pelataan.
200 *
201 * @param pelaajanid tasoa pelanneen pelaajan id
202 * @param taso pelattu taso
203 * @param pisteet saadut pisteet
204 * @return true, jos saatiin paremmat pisteet kuin ennen
205 * false, jos entiset pisteet olivat paremmat
206 *
207 * @example
208 * <pre name="test">
209 * #THROWS IOException
210 * #import java.io.IOException;
211 * #import fi.jyu.mit.ohj2.VertaaTiedosto;
212 * VertaaTiedosto.kirjoitaTiedosto("testitasoja.txt",
213 * ";tiedostossa on pelaajien pisteit?\n" +
214 * "1 | 1 | 12\n"+
215 * "1 | 2 | 100\n"+
216 * "2 | 1 | 95");
217 * Pisteet pisteet = new Pisteet("testitasoja.txt", 8);
218 *
219 * pisteet.paivitaPiste(1,1,10) === false;
220 * pisteet.paivitaPiste(1,2,120) === true;
221 * pisteet.paivitaPiste(1,3,110) === true; // aivan uusi taso!
222 *
223 * int[][] taulu = pisteet.annaPisteet(1);
224 * taulu[1][0] === 12; // pelaaja 1 saa tasolta 1 yh? 12 pistett?.
225 * taulu[1][1] === 120; // pelaaja 1 sai nyt tasolta 2 uudet 120 pistett?.
226 * taulu[1][2] === 110; // pelaaja 1 sai nyt tasolta 3 pisteit?.
227 *
228 * VertaaTiedosto.tuhoaTiedosto("testitasoja.txt");
229 * </pre>
230 */
231 public boolean paivitaPiste(int pelaajanid, int taso, int pisteet) {
232 int vanhatpisteet;
233
234 //tutkitaan, onko kyseess? vanha piste ja jos on, niin t?ydennet??n:
235 for (int i = 0; i<lkm; i++) {
236 vanhatpisteet = this.pisteet[i].pisteet(pelaajanid, taso);
237 if (vanhatpisteet > -1) {
238 if (vanhatpisteet >= pisteet) return false;
239 this.pisteet[i].setPisteet(pisteet);
240 return true;
241 }
242 }
243
244 // jos p??st??n t?h?n niin kyseess? on uusi piste!
245 PelaajanPiste pp = new PelaajanPiste(pelaajanid, taso, pisteet);
246 lisaaPiste(pp.tiedotToString());
247 return true;
248
249 }
250
251 /**
252 * Jos annettu rivi s ei ole kommentti, siit? generoidaan PelaajanPiste-olio ja lis?t??n se
253 * tietorakenteeseen.
254 * @param s parsittava rivi
255 * @param i pelaajan pisteen j?rjestysnumero tietorakenteessa
256 */
257 private void lisaaPiste(String s) {
258 if ( s.charAt(0) != ';') {
259 PelaajanPiste pp = new PelaajanPiste();
260 pp.parse(s);
261 if (lkm >= pisteet.length) kasvata();
262 pisteet[lkm] = pp;
263 lkm++;
264 }
265 }
266
267 /**
268 * Kasvattaa pistetaulukon kokoa tarvittaessa kaksinkertaiseksi.
269 *
270 */
271 private void kasvata() {
272 PelaajanPiste[] uusi = new PelaajanPiste[2*pisteet.length];
273 int i = 0;
274 for (PelaajanPiste pp: pisteet) {
275 uusi[i] = pp;
276 }
277 }
278 }