mirror of
https://github.com/peterosterlund2/droidfish.git
synced 2025-02-06 20:29:10 +01:00
DroidFish: Support for using "open exchange" engines installed on the android device.
This commit is contained in:
parent
a1047dccea
commit
8609a05d10
|
@ -220,6 +220,9 @@
|
|||
<li>
|
||||
Color picker, Copyright © 2010 Daniel Nilsson and Copyright © 2011 Sergey Margaritov.
|
||||
</li>
|
||||
<li>
|
||||
Open exchange chess engine interface code by Gerhard Kalab, <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache 2.0 license</a>.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3>Translations</h3>
|
||||
|
|
95
DroidFish/src/com/kalab/chess/enginesupport/ChessEngine.java
Normal file
95
DroidFish/src/com/kalab/chess/enginesupport/ChessEngine.java
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.kalab.chess.enginesupport;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
public class ChessEngine {
|
||||
|
||||
private static final String TAG = ChessEngine.class.getSimpleName();
|
||||
|
||||
private String name;
|
||||
private String fileName;
|
||||
private String authority;
|
||||
private String packageName;
|
||||
|
||||
public ChessEngine(String name, String fileName, String authority, String packageName) {
|
||||
this.name = name;
|
||||
this.fileName = fileName;
|
||||
this.authority = authority;
|
||||
this.packageName = packageName;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return this.fileName;
|
||||
}
|
||||
|
||||
public Uri getUri() {
|
||||
return Uri.parse("content://" + authority + "/" + fileName);
|
||||
}
|
||||
|
||||
public File copyToFiles(ContentResolver contentResolver, File destination)
|
||||
throws FileNotFoundException, IOException {
|
||||
Uri uri = getUri();
|
||||
File output = new File(destination, uri.getPath().toString());
|
||||
copyUri(contentResolver, uri, output.getAbsolutePath());
|
||||
return output;
|
||||
}
|
||||
|
||||
public void copyUri(final ContentResolver contentResolver,
|
||||
final Uri source, String targetFilePath) throws IOException,
|
||||
FileNotFoundException {
|
||||
InputStream istream = contentResolver.openInputStream(source);
|
||||
copyFile(istream, targetFilePath);
|
||||
setExecutablePermission(targetFilePath);
|
||||
}
|
||||
|
||||
private void copyFile(InputStream istream, String targetFilePath)
|
||||
throws FileNotFoundException, IOException {
|
||||
FileOutputStream fout = new FileOutputStream(targetFilePath);
|
||||
byte[] b = new byte[1024];
|
||||
int numBytes = 0;
|
||||
while ((numBytes = istream.read(b)) != -1) {
|
||||
fout.write(b, 0, numBytes);
|
||||
}
|
||||
istream.close();
|
||||
fout.close();
|
||||
}
|
||||
|
||||
private void setExecutablePermission(String engineFileName) throws IOException {
|
||||
String cmd[] = { "chmod", "744", engineFileName };
|
||||
Process process = Runtime.getRuntime().exec(cmd);
|
||||
try {
|
||||
process.waitFor();
|
||||
} catch (InterruptedException e) {
|
||||
Log.e(TAG, e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public String getPackageName() {
|
||||
return packageName;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.kalab.chess.enginesupport;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
public class ChessEngineResolver {
|
||||
|
||||
private static final String ENGINE_PROVIDER_MARKER = "intent.chess.provider.ENGINE";
|
||||
private static final String TAG = ChessEngineResolver.class.getSimpleName();
|
||||
private Context context;
|
||||
private String target;
|
||||
|
||||
public ChessEngineResolver(Context context) {
|
||||
super();
|
||||
this.context = context;
|
||||
this.target = Build.CPU_ABI;
|
||||
}
|
||||
|
||||
public List<ChessEngine> resolveEngines() {
|
||||
List<ChessEngine> result = new ArrayList<ChessEngine>();
|
||||
final Intent intent = new Intent(ENGINE_PROVIDER_MARKER);
|
||||
List<ResolveInfo> list = context.getPackageManager()
|
||||
.queryIntentActivities(intent, PackageManager.GET_META_DATA);
|
||||
for (ResolveInfo resolveInfo : list) {
|
||||
String packageName = resolveInfo.activityInfo.packageName;
|
||||
result = resolveEnginesForPackage(result, resolveInfo, packageName);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<ChessEngine> resolveEnginesForPackage(
|
||||
List<ChessEngine> result, ResolveInfo resolveInfo,
|
||||
String packageName) {
|
||||
if (packageName != null) {
|
||||
Log.d(TAG, "found engine provider, packageName=" + packageName);
|
||||
Bundle bundle = resolveInfo.activityInfo.metaData;
|
||||
if (bundle != null) {
|
||||
String authority = bundle
|
||||
.getString("chess.provider.engine.authority");
|
||||
Log.d(TAG, "authority=" + authority);
|
||||
if (authority != null) {
|
||||
try {
|
||||
Resources resources = context
|
||||
.getPackageManager()
|
||||
.getResourcesForApplication(
|
||||
resolveInfo.activityInfo.applicationInfo);
|
||||
int resId = resources.getIdentifier("enginelist",
|
||||
"xml", packageName);
|
||||
XmlResourceParser parser = resources.getXml(resId);
|
||||
parseEngineListXml(parser, authority, result, packageName);
|
||||
} catch (NameNotFoundException e) {
|
||||
Log.e(TAG, e.getLocalizedMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void parseEngineListXml(XmlResourceParser parser, String authority,
|
||||
List<ChessEngine> result, String packageName) {
|
||||
try {
|
||||
int eventType = parser.getEventType();
|
||||
while (eventType != XmlResourceParser.END_DOCUMENT) {
|
||||
String name = null;
|
||||
try {
|
||||
if (eventType == XmlResourceParser.START_TAG) {
|
||||
name = parser.getName();
|
||||
if (name.equalsIgnoreCase("engine")) {
|
||||
String fileName = parser.getAttributeValue(null,
|
||||
"filename");
|
||||
String title = parser.getAttributeValue(null,
|
||||
"name");
|
||||
String targetSpecification = parser
|
||||
.getAttributeValue(null, "target");
|
||||
String[] targets = targetSpecification.split("\\|");
|
||||
for (String cpuTarget : targets) {
|
||||
if (target.equals(cpuTarget)) {
|
||||
result.add(new ChessEngine(title, fileName,
|
||||
authority, packageName));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
eventType = parser.next();
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, e.getLocalizedMessage(), e);
|
||||
}
|
||||
}
|
||||
} catch (XmlPullParserException e) {
|
||||
Log.e(TAG, e.getLocalizedMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't use this in production - this method is only for testing. Set the
|
||||
* cpu target.
|
||||
*
|
||||
* @param target
|
||||
* the cpu target to set
|
||||
*/
|
||||
public void setTarget(String target) {
|
||||
this.target = target;
|
||||
}
|
||||
}
|
|
@ -26,6 +26,8 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
@ -57,6 +59,8 @@ import org.petero.droidfish.gamelogic.GameTree.Node;
|
|||
import org.petero.droidfish.gamelogic.TimeControlData;
|
||||
import org.petero.droidfish.gtb.Probe;
|
||||
|
||||
import com.kalab.chess.enginesupport.ChessEngine;
|
||||
import com.kalab.chess.enginesupport.ChessEngineResolver;
|
||||
import com.larvalabs.svgandroid.SVG;
|
||||
import com.larvalabs.svgandroid.SVGParser;
|
||||
|
||||
|
@ -479,6 +483,7 @@ public class DroidFish extends Activity implements GUIInterface {
|
|||
new File(extDir + sep + pgnDir).mkdirs();
|
||||
new File(extDir + sep + fenDir).mkdirs();
|
||||
new File(extDir + sep + engineDir).mkdirs();
|
||||
new File(extDir + sep + engineDir + sep + EngineUtil.openExchangeDir).mkdirs();
|
||||
new File(extDir + sep + gtbDefaultDir).mkdirs();
|
||||
new File(extDir + sep + rtbDefaultDir).mkdirs();
|
||||
}
|
||||
|
@ -1154,21 +1159,29 @@ public class DroidFish extends Activity implements GUIInterface {
|
|||
}
|
||||
|
||||
private final void setEngineTitle(String engine, int strength) {
|
||||
if (engine.contains("/")) {
|
||||
int idx = engine.lastIndexOf('/');
|
||||
String eName = engine.substring(idx + 1);
|
||||
engineTitleText.setText(eName);
|
||||
} else {
|
||||
String eName = getString(engine.equals("cuckoochess") ?
|
||||
R.string.cuckoochess_engine :
|
||||
R.string.stockfish_engine);
|
||||
boolean analysis = (ctrl != null) && ctrl.analysisMode();
|
||||
if ((strength < 1000) && !analysis) {
|
||||
engineTitleText.setText(String.format(Locale.US, "%s: %d%%", eName, strength / 10));
|
||||
} else {
|
||||
engineTitleText.setText(eName);
|
||||
String eName = "";
|
||||
if (EngineUtil.isOpenExchangeEngine(engine)) {
|
||||
String engineFileName = new File(engine).getName();
|
||||
ChessEngineResolver resolver = new ChessEngineResolver(this);
|
||||
List<ChessEngine> engines = resolver.resolveEngines();
|
||||
for (ChessEngine ce : engines) {
|
||||
if (EngineUtil.openExchangeFileName(ce).equals(engineFileName)) {
|
||||
eName = ce.getName();
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (engine.contains("/")) {
|
||||
int idx = engine.lastIndexOf('/');
|
||||
eName = engine.substring(idx + 1);
|
||||
} else {
|
||||
eName = getString(engine.equals("cuckoochess") ?
|
||||
R.string.cuckoochess_engine :
|
||||
R.string.stockfish_engine);
|
||||
boolean analysis = (ctrl != null) && ctrl.analysisMode();
|
||||
if ((strength < 1000) && !analysis)
|
||||
eName = String.format(Locale.US, "%s: %d%%", eName, strength / 10);
|
||||
}
|
||||
engineTitleText.setText(eName);
|
||||
}
|
||||
|
||||
/** Update center field in second header line. */
|
||||
|
@ -2147,42 +2160,65 @@ public class DroidFish extends Activity implements GUIInterface {
|
|||
}
|
||||
|
||||
private final Dialog selectEngineDialog(final boolean abortOnCancel) {
|
||||
final ArrayList<String> items = new ArrayList<String>();
|
||||
final ArrayList<String> ids = new ArrayList<String>();
|
||||
ids.add("stockfish"); items.add(getString(R.string.stockfish_engine));
|
||||
ids.add("cuckoochess"); items.add(getString(R.string.cuckoochess_engine));
|
||||
|
||||
final String sep = File.separator;
|
||||
final String base = Environment.getExternalStorageDirectory() + sep + engineDir + sep;
|
||||
{
|
||||
ChessEngineResolver resolver = new ChessEngineResolver(this);
|
||||
List<ChessEngine> engines = resolver.resolveEngines();
|
||||
ArrayList<Pair<String,String>> oexEngines = new ArrayList<Pair<String,String>>();
|
||||
for (ChessEngine engine : engines) {
|
||||
if ((engine.getName() != null) && (engine.getFileName() != null) &&
|
||||
(engine.getPackageName() != null)) {
|
||||
oexEngines.add(new Pair<String,String>(EngineUtil.openExchangeFileName(engine),
|
||||
engine.getName()));
|
||||
}
|
||||
}
|
||||
Collections.sort(oexEngines, new Comparator<Pair<String,String>>() {
|
||||
@Override
|
||||
public int compare(Pair<String, String> lhs, Pair<String, String> rhs) {
|
||||
return lhs.second.compareTo(rhs.second);
|
||||
}
|
||||
});
|
||||
for (Pair<String,String> eng : oexEngines) {
|
||||
ids.add(base + EngineUtil.openExchangeDir + sep + eng.first);
|
||||
items.add(eng.second);
|
||||
}
|
||||
}
|
||||
|
||||
String[] fileNames = findFilesInDirectory(engineDir, new FileNameFilter() {
|
||||
@Override
|
||||
public boolean accept(String filename) {
|
||||
return !reservedEngineName(filename);
|
||||
}
|
||||
});
|
||||
final int numFiles = fileNames.length;
|
||||
final int nEngines = numFiles + 2;
|
||||
final String[] items = new String[nEngines];
|
||||
final String[] ids = new String[nEngines];
|
||||
int idx = 0;
|
||||
ids[idx] = "stockfish"; items[idx] = getString(R.string.stockfish_engine); idx++;
|
||||
ids[idx] = "cuckoochess"; items[idx] = getString(R.string.cuckoochess_engine); idx++;
|
||||
String sep = File.separator;
|
||||
String base = Environment.getExternalStorageDirectory() + sep + engineDir + sep;
|
||||
for (int i = 0; i < numFiles; i++) {
|
||||
ids[idx] = base + fileNames[i];
|
||||
items[idx] = fileNames[i];
|
||||
idx++;
|
||||
for (String file : fileNames) {
|
||||
ids.add(base + file);
|
||||
items.add(file);
|
||||
}
|
||||
|
||||
String currEngine = ctrl.getEngine();
|
||||
int defaultItem = 0;
|
||||
final int nEngines = items.size();
|
||||
for (int i = 0; i < nEngines; i++) {
|
||||
if (ids[i].equals(currEngine)) {
|
||||
if (ids.get(i).equals(currEngine)) {
|
||||
defaultItem = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle(R.string.select_chess_engine);
|
||||
builder.setSingleChoiceItems(items, defaultItem, new DialogInterface.OnClickListener() {
|
||||
builder.setSingleChoiceItems(items.toArray(new String[0]), defaultItem,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int item) {
|
||||
if ((item < 0) || (item >= nEngines))
|
||||
return;
|
||||
Editor editor = settings.edit();
|
||||
String engine = ids[item];
|
||||
String engine = ids.get(item);
|
||||
editor.putString("engine", engine);
|
||||
editor.commit();
|
||||
dialog.dismiss();
|
||||
|
|
|
@ -18,11 +18,14 @@
|
|||
|
||||
package org.petero.droidfish.engine;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
import com.kalab.chess.enginesupport.ChessEngine;
|
||||
|
||||
import android.os.Build;
|
||||
|
||||
public class EngineUtil {
|
||||
|
@ -58,6 +61,43 @@ public class EngineUtil {
|
|||
return netEngine;
|
||||
}
|
||||
|
||||
public static final String openExchangeDir = "oex";
|
||||
|
||||
/** Return true if file "engine" is an open exchange engine. */
|
||||
public static boolean isOpenExchangeEngine(String engine) {
|
||||
File parent = new File(engine).getParentFile();
|
||||
if (parent == null)
|
||||
return false;
|
||||
String parentDir = parent.getName();
|
||||
return openExchangeDir.equals(parentDir);
|
||||
}
|
||||
|
||||
/** Return a filename (without path) representing an open exchange engine. */
|
||||
public static String openExchangeFileName(ChessEngine engine) {
|
||||
String ret = "";
|
||||
if (engine.getPackageName() != null)
|
||||
ret += sanitizeString(engine.getPackageName());
|
||||
ret += "-";
|
||||
if (engine.getFileName() != null)
|
||||
ret += sanitizeString(engine.getFileName());
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Remove characters from s that are not safe to use in a filename. */
|
||||
private static String sanitizeString(String s) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
char ch = s.charAt(i);
|
||||
if (((ch >= 'A') && (ch <= 'Z')) ||
|
||||
((ch >= 'a') && (ch <= 'z')) ||
|
||||
((ch >= '0') && (ch <= '9')))
|
||||
sb.append(ch);
|
||||
else
|
||||
sb.append('_');
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/** Executes chmod 744 exePath. */
|
||||
final static native boolean chmod(String exePath);
|
||||
|
||||
|
|
|
@ -68,9 +68,11 @@ public class ExternalEngine extends UCIEngineBase {
|
|||
@Override
|
||||
protected void startProcess() {
|
||||
try {
|
||||
String exePath = context.getFilesDir().getAbsolutePath() + "/engine.exe";
|
||||
copyFile(engineFileName, new File(exePath));
|
||||
File exeDir = new File(context.getFilesDir(), "engine");
|
||||
exeDir.mkdir();
|
||||
String exePath = copyFile(engineFileName, exeDir);
|
||||
chmod(exePath);
|
||||
cleanUpExeDir(exeDir, exePath);
|
||||
ProcessBuilder pb = new ProcessBuilder(exePath);
|
||||
synchronized (EngineUtil.nativeLock) {
|
||||
engineProc = pb.start();
|
||||
|
@ -166,6 +168,22 @@ public class ExternalEngine extends UCIEngineBase {
|
|||
}
|
||||
}
|
||||
|
||||
/** Remove all files except exePath from exeDir. */
|
||||
private void cleanUpExeDir(File exeDir, String exePath) {
|
||||
try {
|
||||
exePath = new File(exePath).getCanonicalPath();
|
||||
File[] files = exeDir.listFiles();
|
||||
if (files == null)
|
||||
return;
|
||||
for (File f : files) {
|
||||
if (!f.getCanonicalPath().equals(exePath))
|
||||
f.delete();
|
||||
}
|
||||
new File(context.getFilesDir(), "engine.exe").delete();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
|
||||
private int hashMB = -1;
|
||||
private String gaviotaTbPath = "";
|
||||
private String syzygyPath = "";
|
||||
|
@ -262,10 +280,11 @@ public class ExternalEngine extends UCIEngineBase {
|
|||
stdErrThread.interrupt();
|
||||
}
|
||||
|
||||
protected void copyFile(File from, File to) throws IOException {
|
||||
protected String copyFile(File from, File exeDir) throws IOException {
|
||||
File to = new File(exeDir, "engine.exe");
|
||||
new File(internalSFPath()).delete();
|
||||
if (to.exists() && (from.length() == to.length()) && (from.lastModified() == to.lastModified()))
|
||||
return;
|
||||
return to.getAbsolutePath();
|
||||
if (to.exists())
|
||||
to.delete();
|
||||
to.createNewFile();
|
||||
|
@ -282,6 +301,7 @@ public class ExternalEngine extends UCIEngineBase {
|
|||
if (outFC != null) { try { outFC.close(); } catch (IOException ex) {} }
|
||||
to.setLastModified(from.lastModified());
|
||||
}
|
||||
return to.getAbsolutePath();
|
||||
}
|
||||
|
||||
private final void chmod(String exePath) throws IOException {
|
||||
|
|
|
@ -29,7 +29,6 @@ import java.io.OutputStream;
|
|||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Locale;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Environment;
|
||||
|
@ -95,8 +94,6 @@ public class InternalStockFish extends ExternalEngine {
|
|||
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) {
|
||||
|
@ -121,7 +118,8 @@ public class InternalStockFish extends ExternalEngine {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void copyFile(File from, File to) throws IOException {
|
||||
protected String copyFile(File from, File exeDir) throws IOException {
|
||||
File to = new File(exeDir, "engine.exe");
|
||||
final String sfExe = EngineUtil.internalStockFishName();
|
||||
|
||||
// The checksum test is to avoid writing to /data unless necessary,
|
||||
|
@ -129,15 +127,13 @@ public class InternalStockFish extends ExternalEngine {
|
|||
long oldCSum = readCheckSum(new File(internalSFPath()));
|
||||
long newCSum = computeAssetsCheckSum(sfExe);
|
||||
if (oldCSum == newCSum)
|
||||
return;
|
||||
return to.getAbsolutePath();
|
||||
|
||||
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 {
|
||||
|
@ -154,5 +150,6 @@ public class InternalStockFish extends ExternalEngine {
|
|||
}
|
||||
|
||||
writeCheckSum(new File(internalSFPath()), newCSum);
|
||||
return to.getAbsolutePath();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
package org.petero.droidfish.engine;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import com.kalab.chess.enginesupport.ChessEngine;
|
||||
import com.kalab.chess.enginesupport.ChessEngineResolver;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
/** Engine imported from a different android app, resolved using the open exchange format. */
|
||||
public class OpenExchangeEngine extends ExternalEngine {
|
||||
|
||||
public OpenExchangeEngine(Context context, String engine, Report report) {
|
||||
super(context, engine, report);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String copyFile(File from, File exeDir) throws IOException {
|
||||
new File(internalSFPath()).delete();
|
||||
ChessEngineResolver resolver = new ChessEngineResolver(context);
|
||||
List<ChessEngine> engines = resolver.resolveEngines();
|
||||
for (ChessEngine engine : engines) {
|
||||
if (EngineUtil.openExchangeFileName(engine).equals(from.getName())) {
|
||||
File engineFile = engine.copyToFiles(context.getContentResolver(), exeDir);
|
||||
return engineFile.getAbsolutePath();
|
||||
}
|
||||
}
|
||||
throw new IOException("Engine not found");
|
||||
}
|
||||
}
|
|
@ -46,6 +46,8 @@ public abstract class UCIEngineBase implements UCIEngine {
|
|||
return new CuckooChessEngine(report);
|
||||
else if ("stockfish".equals(engine))
|
||||
return new InternalStockFish(context, report);
|
||||
else if (EngineUtil.isOpenExchangeEngine(engine))
|
||||
return new OpenExchangeEngine(context, engine, report);
|
||||
else if (EngineUtil.isNetEngine(engine))
|
||||
return new NetworkEngine(context, engine, engineOptions, report);
|
||||
else
|
||||
|
|
Loading…
Reference in New Issue
Block a user