import java.util.*;
/**
* SgfTree クラスは、SGFファイル内の全データから、手順データツリーを抽出します。
* @author Jiro Suzuki
*/
public class SgfTree{
private static String[] PROPERTY={"AN[","AP[","BH[","BR[","BT[","CP[","DT[","EV[","FF[","GC[","GM[","GN[","HA[","KO[","LKM[","NE[","OM[","ON[","PB[","PC[","PTM[","PW[","RE[","RO[","RU[","SO[","SZ[","TM[","TR[","US[","WH[","WR[","WT[","AB[","AE[","AR[","AW[","B[","BL[","C[","CR[","DD[","MA[","MK[","HL[","NF[","ID[","L[","LB[","LO[","LN[","M[","MA[","RT[","SL[","SQ[","ST[","TL[","TR[","W[","WL["};
private Vector[] levelArray;
private int cntParenthesisOpen;
/**
* 空のインスタンスを生成します。
*/
SgfTree(){
cntParenthesisOpen=0;
}
/**
* SGF形式の手順を取得します。
* @param str SGFファイル内の全データ(String形式)
* @return SGF形式の手順データツリー(参考図含む)
*/
public Vector getSgfTree(String str){
//改行コードを消去する
str=str.replaceAll("\\n", "");
char[] charData=str.toCharArray();
for(int i=0;i<charData.length;i++){
//小括弧(開)を数えて、データツリーの深さを知る元情報にする
if(charData[i]=='('){
cntParenthesisOpen++;
}
}
//char配列をStringに変換
String strAll=new String(charData);
//char配列をノード毎のStringに変換してVectorに保管
Vector<Character> node=new Vector<Character>();
boolean isMidParenthesisClosed=true;
boolean isOutputChar;
int currentLevel=-1;
//レベル毎の配列を初期化
levelArray=new Vector[cntParenthesisOpen/2+1];
for(int i=0;i<cntParenthesisOpen/2+1;i++){
levelArray[i]=new Vector();
}
for(int i=0;i<charData.length;i++){
isOutputChar=true;
//ブレーク処理
if(isMidParenthesisClosed){
//node追加判定
switch(charData[i]){
case '(':
case ')':
case ';':
isOutputChar=false;
addNode(currentLevel,node);
node.clear();
break;
default:break;
}
//ArrayNode追加処理
switch(charData[i]){
case '(':
currentLevel++;
clearLevelArray(currentLevel);
break;
case ')':
addArrayNode(currentLevel);
currentLevel--;
break;
default:break;
}
}
//中括弧判定処理
switch(charData[i]){
case '[':
isMidParenthesisClosed=false;
break;
case ']': //コメント内中括弧をClose判定しないための工夫
//ただし、"];"と"]("と"])"がコメント内に出現した時は対処できない。
if(isMatchProperty(strAll.substring(i+1)) |
charData[i+1]==';' |
charData[i+1]=='(' |
charData[i+1]==')' ){
isMidParenthesisClosed=true;
}
break;
default:break;
}
//入力文字をnodeに追加
if(isOutputChar){
node.add(new Character(charData[i]));
}
}
//最後の1ノードをVectorに追加
addNode(currentLevel,node);
return levelArray[0];
}
//--------------------------------------------------------------
//Vector(要素はchar)をStringに変換
private String createStrWord(Vector node){
char[] charWord=new char[node.size()];
for(int i=0;i<node.size();i++){
charWord[i]=((Character)node.get(i)).charValue();
}
return new String(charWord);
}
//--------------------------------------------------------------
//プロパティ文字列確認処理
private boolean isMatchProperty(String str){
int match=0;
for(int i=0;i<PROPERTY.length;i++){
if(str.startsWith(PROPERTY[i])){
match=1;
i=PROPERTY.length;
}
}
if(match==1){
return true;
}else{
return false;
}
}
//--------------------------------------------------------------
private void clearLevelArray(int levelNum){
levelArray[levelNum].clear();
}
private void addNode(int levelNum,Vector node){
if(node.size()>0){
levelArray[levelNum].add(createStrWord(node));
}
}
private void addArrayNode(int levelNum){
if(levelNum>0){
levelArray[levelNum-1].add(levelArray[levelNum].clone());
}
}
}