001    /**
002     * Jetrix TetriNET Server
003     * Copyright (C) 2001-2003  Emmanuel Bourg
004     *
005     * This program is free software; you can redistribute it and/or
006     * modify it under the terms of the GNU General Public License
007     * as published by the Free Software Foundation; either version 2
008     * of the License, or (at your option) any later version.
009     *
010     * This program is distributed in the hope that it will be useful,
011     * but WITHOUT ANY WARRANTY; without even the implied warranty of
012     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013     * GNU General Public License for more details.
014     *
015     * You should have received a copy of the GNU General Public License
016     * along with this program; if not, write to the Free Software
017     * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
018     */
019    
020    package net.jetrix.winlist;
021    
022    import java.io.*;
023    import java.util.logging.Level;
024    
025    import net.jetrix.config.*;
026    
027    /**
028     * A winlist compatible with the tetrinetx winlist format. 
029     *
030     * @author Emmanuel Bourg
031     * @version $Revision: 834 $, $Date: 2010-04-11 22:45:49 +0200 (dim., 11 avr. 2010) $
032     */
033    public class TetrixWinlist extends SimpleWinlist
034    {
035        public static final int STRUCT_SIZE = 40;
036        public static final int DEFAULT_WINLIST_SIZE = 5120;
037    
038        private long scoreCount = DEFAULT_WINLIST_SIZE;
039        private String filename;
040        private String encoding = "Cp1252";
041    
042        public void init(WinlistConfig config)
043        {
044            super.init(config);
045    
046            filename = config.getString("file", null);
047            if (filename == null)
048            {
049                filename = "game.winlist" + getId();
050            }
051        }
052    
053        protected void load()
054        {
055            File file = new File(filename);
056    
057            if (file.exists())
058            {
059                InputStream in = null;
060    
061                try
062                {
063                    in = new BufferedInputStream(new FileInputStream(file));
064    
065                    scoreCount = Math.max(scoreCount,  file.length() / STRUCT_SIZE);
066                    byte[] struct = new byte[STRUCT_SIZE];
067    
068                    while (in.read(struct) != -1)
069                    {
070                        Score score = buildScore(struct);
071                        if (score == null) break;
072                        scores.add(score);
073                    }
074                }
075                catch (IOException e)
076                {
077                    log.log(Level.WARNING, "Unable to read the winlist file " + file, e);
078                }
079                finally
080                {
081                    close(in);
082                }
083            }
084    
085            initialized = true;
086        }
087    
088        protected void save()
089        {
090            File file = new File(filename);
091            OutputStream out = null;
092    
093            try
094            {
095                out = new BufferedOutputStream(new FileOutputStream(file));
096    
097                for (int i = 0; i < scoreCount; i++)
098                {
099                    Score score = null;
100                    if (i < scores.size())
101                    {
102                        score = scores.get(i);
103                    }
104    
105                    byte[] struct = buildStruct(score);
106                    out.write(struct);
107                }
108    
109                out.flush();
110            }
111            catch (IOException e)
112            {
113                log.log(Level.WARNING, "Unable to write the winlist file " + file, e);
114            }
115            finally
116            {
117                close(out);
118            }
119        }
120    
121        /**
122         * Build a score from a tetrix winlist structure.
123         */
124        protected Score buildScore(byte[] struct) throws IOException
125        {
126            Score score = null;
127    
128            if (struct[0] != 0)
129            {
130                score = new Score();
131                score.setName(new String(struct, 1, 31, encoding).trim());
132                score.setType(struct[0] == 0x70 ? Score.TYPE_PLAYER : Score.TYPE_TEAM);
133                long scoreValue = getUnsignedByte(struct, 32)
134                        + (getUnsignedByte(struct, 33) << 8)
135                        + (getUnsignedByte(struct, 34) << 16)
136                        + (getUnsignedByte(struct, 35) << 24);
137                score.setScore(scoreValue);
138            }
139    
140            return score;
141        }
142    
143        /**
144         * Build a tetrix winlist structure from a score.
145         */
146        protected byte[] buildStruct(Score score) throws IOException
147        {
148            byte[] struct = new byte[STRUCT_SIZE];
149    
150            if (score != null)
151            {
152                // type
153                struct[0] = score.getType() == Score.TYPE_PLAYER ? (byte) 'p' : (byte) 't';
154    
155                // name
156                byte[] name = score.getName().getBytes(encoding);
157                System.arraycopy(name, 0, struct, 1, name.length);
158    
159                // score
160                struct[35] = (byte) ((score.getScore() >> 24) % 256);
161                struct[34] = (byte) ((score.getScore() >> 16) % 256);
162                struct[33] = (byte) ((score.getScore() >> 8) % 256);
163                struct[32] = (byte) (score.getScore() % 256);
164    
165                // ???
166                struct[36] = 1;
167            }
168    
169            return struct;
170        }
171    
172        private int getUnsignedByte(byte bloc[], int offset)
173        {
174            byte b = bloc[offset];
175            return b < 0 ? b + 256 : b;
176        }
177    
178    }