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  import java.util.*;
11  
12  /**
13   * Luokka pelaajien kokoelman mallintamiseksi. Pelaajat osaa lukea tietonsa
14   * pelaajat.dat tiedostosta.
15   * @author Anna-Leena Latvala, Toni Purontaka
16   * @version v0.6, 15.4.2008
17   *
18   */
19  public class Pelaajat {
20  
21      private Map<Integer,Pelaaja> pelaajat = new TreeMap<Integer,Pelaaja>();
22      private final static String POLKU = "pelaajat.dat";
23          
24      
25      /**
26       * Alustaa Pelaajat defaulttitiedostosta.
27       */
28      public Pelaajat() {
29          lisaaTiedostosta(POLKU);
30      }
31      
32      /**
33       * Alustaa Pelaajat tiedostosta polussa "polku".
34       */
35      public Pelaajat(String polku) {
36          lisaaTiedostosta(polku);
37      }
38      
39      /**
40       * Lukee tiedostosta polussa "polku" pelaajien tiedot ja luo kokoelman taso-olioita.
41       * mik??li tiedosto on ep??kelpo, heitet????n poikkeus
42       * 
43       * @example
44       * <pre name="test">
45       * #THROWS IOException
46       * #import java.io.IOException;
47       * #import fi.jyu.mit.ohj2.VertaaTiedosto;
48       *  VertaaTiedosto.kirjoitaTiedosto("testipelaajia.txt",
49       *      "1    | admin | dfg43hg  | 20080107       | 4        | 285             | \n" +
50       *      "2    | Saku  | sdfgRE34 | 20071227       | 3        | 200             | \n" +
51       *      "3    | Mimmu | SDF23g   | 20080105       | 1        | 0               |"); 
52       *  Pelaajat pel = new Pelaajat("testipelaajia.txt");
53       *  
54       *  // puuttuu testi poikkeuksille!
55       *  
56       *  VertaaTiedosto.tuhoaTiedosto("testipelaajia.txt");
57       * </pre>
58       * 
59       */
60      public final void lisaaTiedostosta(String polku) {
61          BufferedReader fi;
62          
63          try {  //aukaistaan lukija        
64            fi = new BufferedReader(new FileReader(polku));
65          } catch (FileNotFoundException ex) {
66            System.err.println("Tiedosto " + polku + " ei aukea!");
67            return;
68          }        
69                 
70          try {
71              String s; 
72            while ( (s = fi.readLine()) != null) {
73                lisaaPelaaja(s);
74             }
75           
76          } catch (IOException ex) {
77            System.err.println("Virhe tiedostoa luettaessa!");
78            
79          } finally {  // suljetaan tietovirta
80            try {
81              fi.close(); 
82            } catch (IOException ex) {
83              System.err.println("Tiedostoa ei saa suljettua!");
84            }
85          }
86        }
87      
88      /**
89       * Tulostaa pelaajien tiedot defaulttitiedostoon.
90       * @return true, jos tallennus onnistui, false muuten
91       */
92      public boolean tallennaTiedot() {
93          return tallennaTiedot(POLKU);
94      }
95      
96      /**
97       * Tulostaa pelaajien tiedot tiedostoon polussa "polku" ja muuttaa entisen siell? sijainneen
98       * tiedoston back-up tiedostoksi polku.bak (esim. pelaajat.dat -> pelaajat.dat.bak)
99       * @param polku tiedosto, johon tiedot kirjoitetaan
100      * @return true, jos tallennus onnistui, false muuten
101      * 
102      * @example
103      * <pre name="test">
104      * #THROWS IOException
105      * #import java.io.IOException;
106      * #import fi.jyu.mit.ohj2.VertaaTiedosto;
107      *  VertaaTiedosto.kirjoitaTiedosto("testipelaajia.txt",
108      *      "; pid | nimi | salasana | viimeisin pelip?iv? | taso | yhteispisteet |\n" +
109      *      "1|admin|dfg43hg|20080107|4|285|\n" +
110      *      "2|Saku|sdfgRE34|20071227|3|200|\n" +
111      *      "3|Mimmu|SDF23g|20080105|1|0|"); 
112      *      
113      *  Pelaajat pel = new Pelaajat("testipelaajia.txt");
114      *  pel.tallennaTiedot("testitallennus.txt");           // ei ole testitallennus.txt ennen joten ei backuppia
115      *  
116      *  Pelaajat pul = new Pelaajat("testitallennus.txt");
117      *  pul.paivitaKokonaispisteet(1,50);                   // muutetaan tietoja
118      *  pul.tallennaTiedot("testitallennus.txt");           // syntyy backup-tiedosto
119      *  
120      *  VertaaTiedosto.vertaaFileFile("testipelaajia.txt", "testitallennus.txt.bak") === null;          // samat
121      *  (VertaaTiedosto.vertaaFileFile("testipelaajia.txt", "testitallennus.txt") == null) === false;   // erit
122      *   
123      * VertaaTiedosto.tuhoaTiedosto("testipelaajia.txt"); 
124      * VertaaTiedosto.tuhoaTiedosto("testitallennus.txt");          // tuhotaan syntyneet tiedostot
125      * VertaaTiedosto.tuhoaTiedosto("testitallennus.txt.bak");      // my?s back-up
126      * </pre>
127      */
128     public boolean tallennaTiedot(String polku) {
129         PrintStream fo;
130         File vanha = new File(polku);
131         File backuppi = new File(polku + ".bak");
132         vanha.renameTo(backuppi);
133         
134         try { 
135             fo = new PrintStream(new FileOutputStream(polku));
136         }  catch (FileNotFoundException ex) {
137             System.err.println("Tiedosto " + polku + " ei aukea!"); return false;
138         }
139 
140         try {
141             fo.println("; pid | nimi | salasana | viimeisin pelip?iv? | taso | yhteispisteet |");
142             Iterator<Pelaaja> it = pelaajaIteraattori();
143             while ( it.hasNext() ) {
144                 fo.println(it.next().tiedotToString());
145             }
146         } finally {
147             fo.close(); 
148         }
149         return true;
150         
151     }
152     
153     /**
154      * Palauttaa nimeke-nimisen pelaajan viitteen, jos sellainen pelaaja on olemassa. 
155      * Jos ei, palauttaa null. 
156      * @param nimi annettu nimi
157      * @return pyydetyn pelaajan, jos sellainen on - muuten null
158      * 
159      * @example
160      * <pre name="test">
161      * #THROWS IOException
162      * #import java.io.IOException;
163      * #import fi.jyu.mit.ohj2.VertaaTiedosto;
164      *  VertaaTiedosto.kirjoitaTiedosto("testipelaajia.txt",
165      *      "1    | admin | dfg43hg  | 20080107       | 4        | 285             | \n" +
166      *      "2    | Saku  | sdfgRE34 | 20071227       | 3        | 200             | \n" +
167      *      "3    | Mimmu | SDF23g   | 20080105       | 1        | 0               |"); 
168      *  Pelaajat pel = new Pelaajat("testipelaajia.txt");
169      *  (pel.annaPelaaja("Saku") != null) === true;
170      *  (pel.annaPelaaja("puppu") == null) === true;
171      *  pel.annaPelaaja("Mimmu").pisteet() === 0;
172      *  VertaaTiedosto.tuhoaTiedosto("testipelaajia.txt");
173      * </pre>
174      */
175      public Pelaaja annaPelaaja(String nimeke) {
176          Iterator<Pelaaja> it = pelaajaIteraattori();
177          Pelaaja p;
178          while (it.hasNext()) {
179              p = it.next();
180              if (p.nimi().equals(nimeke)) return p;
181          }
182         return null;
183      }
184      
185      /**
186       * P?ivitt?? halutun pd:n pelaajan kokonaispisteet ajan tasalle, kun 
187       * pelaajan pistem??r? on lis??ntynyt lis?yksen verran.
188       * Palauttaa pelaajan uuden kokonaispistem??r?n. 
189       * 
190       * @param pid pelaajan id
191       * @param lisays lis?tt?v? pistem??r?
192       * @return uusi kokonaispistem??r?
193       */
194      public int paivitaKokonaispisteet(int pid, int lisays) {
195          if (pelaajat.containsKey(pid)) pelaajat.get(pid).paivitaPisteet(lisays);
196          return pelaajat.get(pid).pisteet();
197      }
198      
199      /**
200       * Palauttaa pelaajien nimet ja pisteet taulukossa j?rjestettyn? pistem??r?n mukaan
201       * hiScores-tyyliin.
202       * @return 2d-merkkijonotaulukko, jossa vierekk?isiss? alkioissa on pelaajan nimi ja h?nen kokonaispistem??r?ns?.
203       * 
204       * @example
205       * <pre name="test">
206       * #THROWS IOException
207       * #import java.io.IOException;
208       * #import fi.jyu.mit.ohj2.VertaaTiedosto;
209       *  VertaaTiedosto.kirjoitaTiedosto("testipelaajia.txt",
210       *      "1    | admin | dfg43hg  | 20080107       | 4        | 205             | \n" +
211       *      "2    | Saku  | sdfgRE34 | 20071227       | 3        | 300             | \n" +
212       *      "3    | Mimmu | SDF23g   | 20080105       | 1        | 0               |"); 
213       *  Pelaajat pel = new Pelaajat("testipelaajia.txt");
214       *  
215       *  String[][] skoori = pel.hiScores();
216       *  skoori[0][0] === "Saku";  // paras on Saku
217       *  skoori[1][1] === "205";    // admin on kakkosena pisteill? 205
218       *  
219       *  VertaaTiedosto.tuhoaTiedosto("testipelaajia.txt");
220       * </pre>
221       */
222      public String[][] hiScores() {
223          String[][] palaute = new String[2][pelaajat.size()]; 
224          String[][] apuPalaute = new String[2][pelaajat.size()];    
225          Iterator<Pelaaja> it = pelaajaIteraattori();
226          Pelaaja p;
227          int i = 0;
228          while (it.hasNext()) {
229              p = it.next();
230              palaute[0][i] = p.nimi();
231              palaute[1][i] = "" + p.pisteet();
232              apuPalaute[0][i] = palaute[0][i];  
233              apuPalaute[1][i] = palaute[1][i];  
234              i++;
235          }
236          int[] points=new int[pelaajat.size()];
237          for(int j=0;j<pelaajat.size();j++){
238              points[j]=-1*Integer.parseInt(palaute[1][j]);
239          }
240          Arrays.sort(points);
241          
242          for(int k=0;k<pelaajat.size();k++){
243              for(int l=0;l<pelaajat.size();l++){
244                  if((-1*points[k])==Integer.parseInt(apuPalaute[1][l])){
245                      palaute[0][k] = apuPalaute[0][l];  
246                      palaute[1][k] = apuPalaute[1][l];  
247                  }
248              }
249          }
250          return palaute;
251      }
252      
253      /**
254       * Lis?? vastik??n luodun pelaajan tietorakenteeseen.
255       * @param pelaaja uusi pelaaja
256       */
257      public void lisaaUusiPelaaja(Pelaaja pelaaja) {
258          pelaajat.put(pelaaja.pid(), pelaaja);
259      }
260      
261      /**
262       * Palauttaa kaikkia kokoelman pelaajia iteroivan pelaajaiteraattorin.
263       * @return pelaajaiteraattori
264       */
265      private Iterator<Pelaaja> pelaajaIteraattori() {
266          Collection<Pelaaja> pel = pelaajat.values();
267          return pel.iterator();
268      }
269      
270      /**
271       * Lis?? tietorakenteeseen uuden pelaajan.
272       * @param s rivi, josta pelaajan tiedot parsitaan. Jos s alkaa ";", tulkitaan kommentiksi.
273       */
274      private void lisaaPelaaja(String s) {
275          if ( s.charAt(0) != ';') {
276              Pelaaja pelaaja = new Pelaaja();
277              pelaaja.parse(s);
278              pelaajat.put(pelaaja.pid(), pelaaja);
279            }
280      }
281 }
282