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 }