/*
DroidFish - An Android chess program.
Copyright (C) 2011-2012 Peter Ă–sterlund, peterosterlund2@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.petero.droidfish.engine;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.zip.GZIPInputStream;
import android.content.Context;
/** Stockfish engine running as process, started from assets resource. */
public class InternalStockFish extends ExternalEngine {
public InternalStockFish(Context context, Report report) {
super(context, "", report);
}
/** @inheritDoc */
@Override
public final void setStrength(int strength) {
setOption("Skill Level", strength/50);
}
private final long readCheckSum(File f) {
InputStream is = null;
try {
is = new FileInputStream(f);
DataInputStream dis = new DataInputStream(is);
return dis.readLong();
} catch (IOException e) {
return 0;
} finally {
if (is != null) try { is.close(); } catch (IOException ex) {}
}
}
private final void writeCheckSum(File f, long checkSum) {
OutputStream os = null;
try {
os = new FileOutputStream(f);
DataOutputStream dos = new DataOutputStream(os);
dos.writeLong(checkSum);
} catch (IOException e) {
} finally {
if (os != null) try { os.close(); } catch (IOException ex) {}
}
}
private final long computeAssetsCheckSum(String sfExe) {
InputStream is = null;
try {
is = context.getAssets().open(sfExe);
if (sfExe.endsWith(".mygz"))
is = new GZIPInputStream(is);
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] buf = new byte[8192];
while (true) {
int len = is.read(buf);
if (len <= 0)
break;
md.update(buf, 0, len);
}
byte[] digest = md.digest(new byte[]{0});
long ret = 0;
for (int i = 0; i < 8; i++) {
ret ^= ((long)digest[i]) << (i * 8);
}
return ret;
} catch (IOException e) {
return -1;
} catch (NoSuchAlgorithmException e) {
return -1;
} finally {
if (is != null) try { is.close(); } catch (IOException ex) {}
}
}
@Override
protected void copyFile(File from, File to) throws IOException {
final String sfExe = EngineUtil.internalStockFishName();
// The checksum test is to avoid writing to /data unless necessary,
// on the assumption that it will reduce memory wear.
long oldCSum = readCheckSum(new File(intSfPath));
long newCSum = computeAssetsCheckSum(sfExe);
if (oldCSum == newCSum)
return;
if (to.exists())
to.delete();
to.createNewFile();
InputStream is = context.getAssets().open(sfExe);
if (sfExe.endsWith(".mygz"))
is = new GZIPInputStream(is);
OutputStream os = new FileOutputStream(to);
try {
byte[] buf = new byte[8192];
while (true) {
int len = is.read(buf);
if (len <= 0)
break;
os.write(buf, 0, len);
}
} finally {
if (is != null) try { is.close(); } catch (IOException ex) {}
if (os != null) try { os.close(); } catch (IOException ex) {}
}
writeCheckSum(new File(intSfPath), newCSum);
}
}