/*
 * 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 2, 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, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.
 *
 * http://www.gnu.org/copyleft/gpl.html
 */
package net.sf.l2j.gameserver.communitybbs.Manager;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Calendar;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.logging.Logger;

import javolution.text.TextBuilder;
import net.sf.l2j.Config;
import net.sf.l2j.L2DatabaseFactory;
import net.sf.l2j.custom.TextReplacer;
import net.sf.l2j.gameserver.Announcements;
import net.sf.l2j.gameserver.cache.HtmCache;
import net.sf.l2j.gameserver.datatables.MapRegionTable;
import net.sf.l2j.gameserver.GameServer;
import net.sf.l2j.gameserver.instancemanager.CastleManager;
import net.sf.l2j.gameserver.instancemanager.TownManager;
import net.sf.l2j.gameserver.model.L2Object;
import net.sf.l2j.gameserver.model.L2Party;
import net.sf.l2j.gameserver.model.L2World;
import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
import net.sf.l2j.gameserver.model.entity.Castle;
import net.sf.l2j.gameserver.network.SystemMessageId;
import net.sf.l2j.gameserver.network.serverpackets.AskJoinParty;
import net.sf.l2j.gameserver.network.serverpackets.NpcHtmlMessage;
import net.sf.l2j.gameserver.network.serverpackets.ShowBoard;
import net.sf.l2j.gameserver.network.serverpackets.SystemMessage;
import net.sf.l2j.gameserver.Shutdown;

/**
 * @author  TEN / nanasisaso / TSL / JOJO
 */
public class FavoriteManager extends BaseBBSManager
{
	private static Logger _log = Logger.getLogger(FavoriteManager.class.getName());
	private static FavoriteManager _instance = new FavoriteManager();

	private static final int CUSTOM_SERVER_RESTART_MINIMUM = 3;
	private static boolean _autorestart = false;
	private CustomServerRestart restart;
	class CustomServerRestart {
		int total;		//サーバー内全員
		int score;		//リスタ希望者の人数
		int rate;		//割合
	}

	/**
	 * @return
	 */
	public static FavoriteManager getInstance()
	{
		return _instance;
	}

	/* (non-Javadoc)
	 * @see net.sf.l2j.gameserver.communitybbs.Manager.BaseBBSManager#parsecmd(java.lang.String, net.sf.l2j.gameserver.model.actor.instance.L2PcInstance)
	 */
	@Override
	public void parsecmd(String command, L2PcInstance activeChar)
	{
		if (activeChar == null) return;

		if (command.equals("_bbsgetfav"))
		{
			showFavorite(activeChar);
		}
		else if (command.startsWith("_bbsgetfav;"))
		{
			StringTokenizer st = new StringTokenizer(command, ";");
			st.nextToken();
			String subcmd = st.nextToken();
			//サーバ再起動申請
			if (subcmd.equals("restart_srv"))
			{
				doRestartServer(activeChar);
				parsecmd("_bbsgetfav", activeChar);
			}
			//キャラクター復旧申請
			else if (subcmd.equals("repair_char"))
			{
				int obj_id = Integer.parseInt(st.nextToken());
				doRepairChar(activeChar, obj_id);
				parsecmd("_bbsgetfav", activeChar);
			}
			//簡易パーティーマッチ
			else if (subcmd.equals("bbs_party_match"))
			{
				TextBuilder htmlCode = new TextBuilder("<html><body><br>");
				subcmd = st.nextToken();
				if (subcmd.startsWith("_menu"))
				{
					int roomId = getRoomIdByCharId(activeChar.getObjectId());
					if(roomId != -1)
					{
						//参加済みなら参加していた部屋を表示する。
						htmlCode.append(showPartyRoom(activeChar, roomId));
					}
					else
					{
						String[] values = subcmd.split(" ");
						//未参加ならリストを表示する。
						if(values.length == 3)
							htmlCode.append(showPartyRoomList(activeChar, values[1], values[2]));
						else
							htmlCode.append(showPartyRoomList(activeChar, null, null));
					}
				}
				//パーティールーム開設画面
				else if (subcmd.startsWith("_createRoomWindow"))
				{
					showConfigWindow(activeChar, "party/createPartyRoom.htm");
					return;
				}
				//_createRoom min max limit lootdist title
				else if (subcmd.startsWith("_createRoom"))
				{
					String[] values = subcmd.split(" ");
					//項目が揃ってなければエラー
					if (values.length < 6)
					{
						activeChar.sendMessage("パーティー ルームの開設に失敗しました。");
						return;
					}
					else
					{
						try
						{
							int roomId = getRoomIdByCharId(activeChar.getObjectId());
							int min = Integer.parseInt(values[1]);
							int max = Integer.parseInt(values[2]);
							int limit = Integer.parseInt(values[3]);
							int lootdist = Integer.parseInt(values[4]);
							StringBuilder title = new StringBuilder();
							for(int i = 5; i < values.length; i++)
							{
								title.append(values[i]).append(" ");
							}
							if (roomId != -1)
								modifyPartyRoom(activeChar, roomId, min, max, limit, lootdist, title.toString());
							else
								roomId = createPartyRoom(activeChar, min, max, limit, lootdist, title.toString());
							if (roomId > -1)
								htmlCode.append(showPartyRoom(activeChar, roomId));
						}
						catch(Exception e)
						{
							e.printStackTrace();
							activeChar.sendMessage("パーティー ルームの開設に失敗しました。");
							return;
						}
					}
				}
				//パーティールーム設定変更画面
				else if (subcmd.startsWith("_modifyRoomWindow"))
				{
					showConfigWindow(activeChar, "party/modifyPartyRoom.htm");
					return;
				}
				//_modifyRoom roomid min max limit lootdist title
				else if (subcmd.startsWith("_modifyRoom"))
				{
					String[] values = subcmd.split(" ");
					//項目が揃ってなければエラー
					if (values.length < 7)
					{
						activeChar.sendMessage("パーティー ルーム設定の変更に失敗しました。");
						return;
					}
					else
					{
						try
						{
							int roomId = Integer.parseInt(values[1]);
							int min = Integer.parseInt(values[2]);
							int max = Integer.parseInt(values[3]);
							int limit = Integer.parseInt(values[4]);
							int lootdist = Integer.parseInt(values[5]);
							StringBuilder title = new StringBuilder();
							for(int i = 6; i < values.length; i++)
							{
								title.append(values[i]).append(" ");
							}
							modifyPartyRoom(activeChar, roomId, min, max, limit, lootdist, title.toString());
							htmlCode.append(showPartyRoom(activeChar, roomId));
						}
						catch(Exception e)
						{
							e.printStackTrace();
							activeChar.sendMessage("パーティー ルーム設定の変更に失敗しました。");
							return;
						}
					}
				}
				//_joinRoom roomid
				else if (subcmd.startsWith("_joinRoom"))
				{
					String[] values = subcmd.split(" ");
					//項目が揃ってなければエラー
					if (values.length < 2)
					{
						activeChar.sendMessage("パーティー ルームへの入室に失敗しました。");
						return;
					}
					else
					{
						try
						{
							int roomId = Integer.parseInt(values[1]);
							if (joinPartyRoom(activeChar, roomId))
								htmlCode.append(showPartyRoom(activeChar, roomId));
							else
							{
								activeChar.sendMessage("パーティー ルームへの入室に失敗しました。");
								return;
							}
						}
						catch(Exception e)
						{
							e.printStackTrace();
							activeChar.sendMessage("パーティー ルームへの入室に失敗しました。");
							return;
						}
					}
				}
				//_leaveRoom roomid
				else if (subcmd.startsWith("_leaveRoom"))
				{
					String[] values = subcmd.split(" ");
					//項目が揃ってなければエラー
					if (values.length < 2)
					{
						activeChar.sendMessage("パーティー ルームからの退室に失敗しました。");
						return;
					}
					else
					{
						try
						{
							int roomId = Integer.parseInt(values[1]);
							leavePartyRoom(activeChar, roomId);
							htmlCode.append(showPartyRoomList(activeChar, null, null));
						}
						catch(Exception e)
						{
							e.printStackTrace();
							activeChar.sendMessage("パーティー ルームからの退室に失敗しました。");
							return;
						}
					}
				}
				//_kickRoom roomid char_obj_id
				else if (subcmd.startsWith("_kickRoom"))
				{
					String[] values = subcmd.split(" ");
					//項目が揃ってなければエラー
					if(values.length < 3)
					{
						activeChar.sendMessage("パーティー ルームからの強制退室に失敗しました。");
						return;
					}
					else
					{
						try
						{
							int roomId = Integer.parseInt(values[1]);
							int objectId = Integer.parseInt(values[2]);
							L2PcInstance character = (L2PcInstance)L2World.getInstance().findObject(objectId);
							if(character != null)
								leavePartyRoom(character, roomId);
							return;
						}
						catch(Exception e)
						{
							e.printStackTrace();
							activeChar.sendMessage("パーティー ルームからの強制退室に失敗しました。");
							return;
						}
					}
				}
				//_joinParty roomid char_obj_id
				else if (subcmd.startsWith("_joinParty"))
				{
					String[] values = subcmd.split(" ");
					//項目が揃ってなければエラー
					if(values.length < 3)
					{
						activeChar.sendMessage("パーティへの勧誘に失敗しました。");
						return;
					}
					else
					{
						try
						{
							int roomId = Integer.parseInt(values[1]);
							int objectId = Integer.parseInt(values[2]);
							L2PcInstance target = (L2PcInstance)L2World.getInstance().findObject(objectId);
							if (!requestJoinParty(activeChar, target, roomId))
								activeChar.sendMessage("パーティへの勧誘に失敗しました。");
							return;
						}
						catch(Exception e)
						{
							e.printStackTrace();
							activeChar.sendMessage("パーティへの勧誘に失敗しました。");
							return;
						}
					}
				}
				htmlCode.append("</body></html>");
				separateAndSend(htmlCode.toString(),activeChar);
			}
			//ドロップリスト検索
			else if (subcmd.equals("bbs_droplist"))
			{
				showConfigWindow(activeChar, "droplist/searchWindow.htm");
				return;
			}
		}
		else
		{
			ShowBoard sb = new ShowBoard("<html><body><br><br><center> the command: "+command+" is not implemented yet</center><br><br></body></html>","101");
			activeChar.sendPacket(sb);
			activeChar.sendPacket(new ShowBoard(null,"102"));
			activeChar.sendPacket(new ShowBoard(null,"103"));
		}
	}

	/* (non-Javadoc)
	 * @see net.sf.l2j.gameserver.communitybbs.Manager.BaseBBSManager#parsewrite(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, net.sf.l2j.gameserver.model.actor.instance.L2PcInstance)
	 */
	@Override
	public void parsewrite(String ar1, String ar2, String ar3, String ar4, String ar5, L2PcInstance activeChar)
	{
		if (activeChar == null) return;

//		ar2 = quoteString(ar2);
//		ar3 = quoteString(ar3);
//		ar4 = quoteString(ar4);
//		ar5 = quoteString(ar5);
		if (ar1.equals("droplist") && ar2.equals("search"))
		{
			separateAndSend("<html><body><br>"
					+ showDropList(activeChar, ar3, ar4, ar5)
					+ "</body></html>"
				,activeChar);
		}
		else
		{
			ShowBoard sb = new ShowBoard("<html><body><br><br><center>the command: " + ar1
				+ " is not implemented yet</center><br><br></body></html>", "101");
			activeChar.sendPacket(sb);
			activeChar.sendPacket(new ShowBoard(null, "102"));
			activeChar.sendPacket(new ShowBoard(null, "103"));
		}
	}

	/**
	 * @param activeChar
	 */
	private void showFavorite(L2PcInstance activeChar)
	{
		TextBuilder html = new TextBuilder("<html><body><br>");
		html.append("<TABLE border=0 width=610>");
		html.append("<TR><TD align=left>");
		html.append("<a action=\"bypass _bbshome\">&$377;</a>&nbsp;>&nbsp;<A action=\"bypass _bbsgetfav\">&$379;</A>");
		html.append("</TD></TR>");
		html.append("</TABLE>");
		html.append("<CENTER>");

		html.append("<IMG src=\"L2UI.squareblank\" width=\"1\" height=\"10\">");
		html.append("<TABLE border=0>");
		html.append("<TR>");
		html.append("<TD><button value=\"パーティ マッチ\" action=\"bypass _bbsgetfav;bbs_party_match;_menu\" width=105 height=20 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></TD>");
		html.append("<TD><button value=\"ドロップ リスト\" action=\"bypass _bbsgetfav;bbs_droplist\" width=105 height=20 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></TD>");
		html.append("</TR>");
		html.append("</TABLE>");

		html.append("<IMG src=\"L2UI.squareblank\" width=\"1\" height=\"10\">");
		html.append("<IMG src=\"L2UI.SquareWhite\" width=\"610\" height=\"1\">");
		html.append("<IMG src=\"L2UI.squareblank\" width=\"1\" height=\"10\">");

		html.append("<font color=\"LEVEL\">サーバー再起動申請</font><BR>");
		html.append("<TABLE border=0 cellspacing=0 cellpadding=0 width=610>");
		html.append("<TR>");
		html.append("<TD fixWIDTH=5></td>");
		html.append("<TD fixWIDTH=600>");
		html.append(getRestartServerHTML(activeChar));
		html.append("</TD>");
		html.append("<TD fixWIDTH=5></td>");
		html.append("</TR>");
		html.append("</TABLE>");

		html.append("<IMG src=\"L2UI.squareblank\" width=\"1\" height=\"10\">");
		html.append("<IMG src=\"L2UI.SquareWhite\" width=\"610\" height=\"1\">");
		html.append("<IMG src=\"L2UI.squareblank\" width=\"1\" height=\"10\">");

		html.append("<font color=\"LEVEL\">キャラクター復旧申請</font><BR>");
		html.append("<TABLE border=0 cellspacing=0 cellpadding=0 width=610>");
		html.append("<TR>");
		html.append("<TD fixWIDTH=5></td>");
		html.append("<TD fixWIDTH=600>");
		html.append(getRepairCharHTML(activeChar));
		html.append("</TD>");
		html.append("<TD fixWIDTH=5></td>");
		html.append("</TR>");
		html.append("</TABLE>");

		html.append("</CENTER>");
		html.append("</body>");
		html.append("</html>");
		separateAndSend(html.toString(), activeChar);
	}

	//サーバ再起動申請者数集計
	private void countRestartServer()
	{
		int score = 0;
		for (L2PcInstance pc : L2World.getInstance().getAllPlayers().values()) {
			if (pc.getClient().isAbsence) continue;	//不在モードを除外
			if (pc.voteServerRestart) ++score;
		}

		restart.total = L2World.getInstance().getAllPlayersCount();
		restart.score = score;
		restart.rate = score * 100 / restart.total;
	}

	// 申請画面表示部分
	public /*private*/ String getRestartServerHTML(L2PcInstance activeChar)
	{
		if (restart == null) {
			restart = new CustomServerRestart();
			countRestartServer();
		}

		TextBuilder replyMSG = new TextBuilder();
		replyMSG.append("条件：プレイヤーの "+Config.CUSTOM_SERVER_RESTART_RATE+"％ がサーバ再起動を希望した場合有効です。<br1>");
		replyMSG.append("現在のログイン数："+restart.total+" 人<br1>");
		replyMSG.append("現在の希望者数："+restart.score+" 人<br1>");
		replyMSG.append("現在の希望者数："+restart.rate+" ％<br>");

		//再起動処理中ならば下記処理
		if(_autorestart)
		{
			replyMSG.append("<font color=\"LEVEL\">既に再起動が可決されています。</font><br1>");
			replyMSG.append("<font color=\"LEVEL\">安全な場所でログアウトしてください。</font><br1>");
		}
		else
		{
			replyMSG.append("<button value=\"申請する\" action=\"bypass _bbsgetfav;restart_srv\" width=80 height=22 back=\"L2UI_CT1.BUTTON_DF_DOWN\" fore=\"L2UI_CT1.BUTTON_DF\"><br>");
			replyMSG.append("＜注意事項＞<br1>");
			replyMSG.append("サーバ起動後 "+Config.CUSTOM_SERVER_RESTART_INTERVAL+" 時間経過していないと申請できません。<br1>");
			replyMSG.append("また、同一アカウントからの申請は１回のみで、ログアウトした場合は無効となります。<br1>");
		}
		return replyMSG.toString();
	}

	//状態確認、判別部分
	private void doRestartServer(L2PcInstance activeChar)
	{
		//再起動処理中ならば下記処理
		if (_autorestart) {
			activeChar.sendMessage("既にサーバー再起動処理に移行しています。");
			return;
		}

		//コマンド実行者が申請済かどうかチェック
		if (activeChar.voteServerRestart) {
			activeChar.sendMessage("既にサーバー再起動申請済です。");
			return;
		}

		// 条件付け
		if (activeChar.getLevel() < 10) {
			activeChar.sendMessage("レベル１０以上でなければ申請できません。");
			return;
		}

		//サーバ起動後、指定時間が経過しているかチェック
		Calendar EnableTime = GameServer.dateTimeServerStarted;
		EnableTime.add(Calendar.HOUR_OF_DAY, Config.CUSTOM_SERVER_RESTART_INTERVAL);
		if (Calendar.getInstance().getTimeInMillis() < EnableTime.getTimeInMillis()) {
			activeChar.sendMessage("サーバ起動後、規定時間が経過していません。");
			return;
		}

		//攻城戦中かどうかチェック
		for (Castle castle : CastleManager.getInstance().getCastles()) {
			if (castle.getSiege().getIsInProgress()) {
				activeChar.sendMessage("攻城戦中はサーバー再起動を申請することができません。");
				return;
			}
		}

		activeChar.voteServerRestart = true;
		activeChar.sendMessage("サーバー再起動申請を受付ました。");
		countRestartServer();

		if (restart.rate < Config.CUSTOM_SERVER_RESTART_RATE) {
			activeChar.sendMessage("希望者数が総ログイン数の "+Config.CUSTOM_SERVER_RESTART_RATE+"％ に達するまでお待ち下さい。");
			return;
		}
		if (restart.score < CUSTOM_SERVER_RESTART_MINIMUM) {
			activeChar.sendMessage(CUSTOM_SERVER_RESTART_MINIMUM + " 名以上の同意がなければサーバー再起動できません。");
			return;
		}

		_autorestart = true;
		activeChar.sendMessage("サーバー再起動が可決されました。");
		Announcements.getInstance().announceToAll("【サーバー再起動のお知らせ】");
		Announcements.getInstance().announceToAll("投票システムにより、サーバー再起動が可決されました。");
		Announcements.getInstance().announceToAll("これより当サーバーは再起動処理に移行します。");
		Announcements.getInstance().announceToAll("安全な場所でログアウトするようにしてください。");
		Shutdown.getInstance().startShutdown(null, Config.CUSTOM_SERVER_RESTART_TIME, true);
	}

	static final boolean CUSTOM_CHARA_REPAIR_NEAREST_TOWN = true;

	//復旧させたいキャラのリストを表示させるソース
	private String getRepairCharHTML(L2PcInstance activeChar)
	{
		//もしアカウント内のキャラがゼロならば
		if (activeChar.getAccountChars().size() == 0)
		{
			return "復旧可能なキャラクターが存在しません。<br1>";
		}

		//別キャラが居るならば（別キャラ数がゼロじゃないなら）
		TextBuilder replyMSG = new TextBuilder();
		replyMSG.append("復旧したいキャラクターを選択して下さい。<br1>");
if (CUSTOM_CHARA_REPAIR_NEAREST_TOWN) {{
		replyMSG.append("＜注意＞復旧場所は、最寄の村となっています。<br>");
}} else {{
		replyMSG.append("＜注意＞復旧場所は「 "+Config.CUSTOM_CHARA_REPAIR_NAME+" 」となっています。<br>");
}}

		for (Map.Entry<Integer, String> chars : activeChar.getAccountChars().entrySet()) {
			int obj_Id = chars.getKey();
			String char_name = chars.getValue();
			replyMSG.append("<a action=\"bypass _bbsgetfav;repair_char;" + obj_Id + "\">");
			replyMSG.append(char_name);
			replyMSG.append("</a>&nbsp;");
		}
		return replyMSG.toString();
	}

	//キャラクター復旧機能の実行部分
	private void doRepairChar(L2PcInstance activeChar, int obj_id)
	{
		java.sql.Connection con = null;
		try
		{
			con = L2DatabaseFactory.getInstance().getConnection();
			PreparedStatement statement;

if (CUSTOM_CHARA_REPAIR_NEAREST_TOWN) {{
			//最寄の村へ
			int coord[] = null; {
				statement = con.prepareStatement("SELECT x,y,pkkills FROM characters WHERE charId=?");
				statement.setInt(1, obj_id);
				ResultSet rs = statement.executeQuery();
				if (rs.next()) {
					if (rs.getInt("pkkills") > 5)
						coord = new int[] { 17817, 170079, -3530 }; /*赤ネ⇒フォローラン村*/
					else
						coord = TownManager.getInstance().getClosestTown( rs.getInt("x"), rs.getInt("y") ).getSpawnLoc(); /*最寄の村*/
				}
				rs.close();
				statement.close();
			}
			if (coord != null) {
				statement = con.prepareStatement("UPDATE characters SET x=?,y=?,z=? WHERE charId=?");
				statement.setInt(1, /*x=*/coord[0]);
				statement.setInt(2, /*y=*/coord[1]);
				statement.setInt(3, /*z=*/coord[2]);
				statement.setInt(4, obj_id);
				statement.execute();
				statement.close();
			}
}} else {{
			//強制移動処理
			statement = con.prepareStatement("UPDATE characters SET x=?,y=?,z=? WHERE charId=?");
			statement.setInt(1, Config.CUSTOM_CHARA_REPAIR_LOC[0]);
			statement.setInt(2, Config.CUSTOM_CHARA_REPAIR_LOC[1]);
			statement.setInt(3, Config.CUSTOM_CHARA_REPAIR_LOC[2]);
			statement.setInt(4, obj_id);
			statement.execute();
			statement.close();
}}

			//強制スキル削除処理
			statement = con.prepareStatement("DELETE FROM character_skills_save WHERE charId=?");
			statement.setInt(1, obj_id);
			statement.execute();
			statement.close();

			//強制装備解除処理
			statement = con.prepareStatement("UPDATE items SET loc='INVENTORY', loc_data=0 WHERE owner_id=? AND loc='PAPERDOLL'");
			statement.setInt(1, obj_id);
			statement.execute();
			statement.close();
		}
		catch (Exception e)
		{
			_log.info("Error could not repair char: " + e);
			activeChar.sendMessage("キャラクター復旧に失敗しました。");
		}
		finally
		{
			try { con.close(); } catch (Exception e) {}
		}

		activeChar.sendMessage("キャラクター復旧が完了しました。");
	}

	//部屋番号の生成
	private synchronized int createPartyRoomId()
	{
		java.sql.Connection con = null;
		try
		{
			con = L2DatabaseFactory.getInstance().getConnection();
			PreparedStatement statement = con.prepareStatement("SELECT MAX(id) FROM party_match_list");
			ResultSet result = statement.executeQuery();
			while(result.next())
			{
				return result.getInt(1) + 1;
			}
			result.close();
			statement.close();
		}
		catch (Exception e)
		{
			return -1;
		}
		finally
		{
			try { con.close(); } catch (Exception e) {}
		}
		return 1;//部屋が1つもない場合は1番から
	}

	//パーティールームを開設する。
	private int createPartyRoom(L2PcInstance _activeChar, int _min, int _max, int _limit, int _lootdist, String _title)
	{
		java.sql.Connection con = null;
		try
		{
			con = L2DatabaseFactory.getInstance().getConnection();
			PreparedStatement statement = con.prepareStatement("INSERT INTO party_match_list VALUES (?,?,?,?,?,?,?,?)");
			int nextId = createPartyRoomId();
			if(nextId == -1)
			{
				_activeChar.sendMessage("パーティー ルームの開設に失敗しました。");
				return -1;
			}
			statement.setInt(1, nextId);
			statement.setInt(2, _activeChar.getObjectId());
			statement.setInt(3, _min);
			statement.setInt(4, _max);
			statement.setInt(5, _limit);
			int castleIndex = CastleManager.getInstance().findNearestCastleIndex(_activeChar);
			if (castleIndex < 0)
				statement.setString(6, "不明");
			else
				statement.setString(6, CastleManager.getInstance().getCastles().get(castleIndex).getNameJA());
			statement.setInt(7, _lootdist);
//			_title = quoteString(_title);
			statement.setString(8, _title);
			statement.execute();
			statement.close();

			statement = con.prepareStatement("INSERT INTO party_match_room VALUES(?,?,?)");
			statement.setInt(1, nextId);
			statement.setInt(2, _activeChar.getObjectId());
			statement.setInt(3, 0);
			statement.execute();
			statement.close();
			_activeChar.sendMessage("パーティー ルームを開設しました。");
			return nextId;
		}
		catch (Exception e)
		{
			_log.info("could not create Party Room: " + e);
			_activeChar.sendMessage("パーティー ルームの開設に失敗しました。");
			return -1;
		}
		finally
		{
			try { con.close(); } catch (Exception e) {}
		}
	}

	//パーティールームの設定を変更する（リーダーのみ）
	private void modifyPartyRoom(L2PcInstance _activeChar, int _roomId, int _min, int _max, int _limit, int _lootdist, String _title)
	{
		java.sql.Connection con = null;
		try
		{
			con = L2DatabaseFactory.getInstance().getConnection();
			PreparedStatement statement = con.prepareStatement("UPDATE party_match_list SET min = ?, max = ?, `limit` = ?, loc = ?, type = ?, title = ? WHERE id = ?");
			statement.setInt(1, _min);
			statement.setInt(2, _max);
			statement.setInt(3, _limit);
			int castleIndex = CastleManager.getInstance().findNearestCastleIndex(_activeChar);
			if (castleIndex < 0)
				statement.setString(4, "不明");
			else
				statement.setString(4, CastleManager.getInstance().getCastles().get(castleIndex).getNameJA());
			statement.setInt(5, _lootdist);
//			_title = quoteString(_title);
			statement.setString(6, _title);
			statement.setInt(7, _roomId);
			statement.execute();
			statement.close();
			/*
			 * この部分に、変更後の条件を満たさないキャラクターの退室処理が必要かも
			 *
			 */
		}
		catch (Exception e)
		{
			_log.info("could not modify Party Room: " + e);
			_activeChar.sendMessage("パーティー ルーム設定の変更に失敗しました。");
			return;
		}
		finally
		{
			try { con.close(); } catch (Exception e) {}
		}
		brodeCastRoomInfo(_activeChar, _roomId);
		_activeChar.sendMessage("パーティー ルーム設定を変更しました。");
	}

	//パーティールームに入室する。
	private boolean joinPartyRoom(L2PcInstance _activeChar, int _roomId)
	{
		PartyRoomInfo pi = getPartyRoomInfo(_roomId);
		if (pi.limit == -1 || pi.count == -1)
		{
			_activeChar.sendMessage("ルームが見つかりません。");
			return false;
		}
		else if(pi.limit <= pi.count)
		{
			_activeChar.sendMessage("人数の上限に達しているため、入室できません。");
			return false;
		}
		else if(_activeChar.getLevel() < pi.min || pi.max < _activeChar.getLevel())
		{
			_activeChar.sendMessage("レベル制限に合っていないため、入室できません。");
			return false;
		}
		else
		{
			java.sql.Connection con = null;
			try
			{
				con = L2DatabaseFactory.getInstance().getConnection();
				PreparedStatement statement = con.prepareStatement("INSERT INTO party_match_room VALUES(?,?,?)");
				statement.setInt(1, _roomId);
				statement.setInt(2, _activeChar.getObjectId());
				if(_activeChar.getParty() != null && _activeChar.getParty() == ((L2PcInstance)L2World.getInstance().findObject(pi.owner_id)).getParty())
					statement.setInt(3, 1);
				else
					statement.setInt(3, 2);
				statement.execute();
				statement.close();
			}
			catch (Exception e)
			{
				_log.info("could not join Party Room: " + e);
				_activeChar.sendMessage("パーティー ルームへの入室に失敗しました。");
				return false;
			}
			finally
			{
				try { con.close(); } catch (Exception e) {}
			}
			brodeCastRoomInfo(_activeChar, _roomId);
			_activeChar.sendMessage("パーティー ルームへ入室しました。");
		}
		return true;
	}

	//パーティールームから退室する
	private void leavePartyRoom(L2PcInstance _activeChar, int _roomId)
	{
		java.sql.Connection con = null;
		try
		{
			con = L2DatabaseFactory.getInstance().getConnection();
			PreparedStatement statement = con.prepareStatement("SELECT owner_id FROM party_match_list WHERE id = ?");
			statement.setInt(1, _roomId);
			ResultSet result = statement.executeQuery();
			int owner_id = 0;
			while(result.next())
			{
				owner_id = result.getInt(1);
			}
			result.close();
			statement.close();

			//退室者がオーナーだった場合、部屋を閉じる
			if(owner_id == _activeChar.getObjectId())
			{
				statement = con.prepareStatement("SELECT char_obj_id FROM party_match_room WHERE room_id = ?");
				statement.setInt(1, _roomId);
				result = statement.executeQuery();
				while(result.next())
				{
					int object_id = result.getInt(1);
					L2PcInstance member = (L2PcInstance)L2World.getInstance().findObject(object_id);
					if(member != null)
					{
						separateAndSend("<html><body><br>"
								+ showPartyRoomList(member, null, null)
								+ "</body></html>"
							,member);
						member.sendMessage("パーティー ルームが解散されました。");
					}
				}
				result.close();
				statement.close();

				statement = con.prepareStatement("DELETE FROM party_match_list WHERE id = ?");
				statement.setInt(1, _roomId);
				statement.execute();
				statement.close();
				statement = con.prepareStatement("DELETE FROM party_match_room WHERE room_id = ?");
				statement.setInt(1, _roomId);
				statement.execute();
				statement.close();
			}
			else
			{
				statement = con.prepareStatement("SELECT char_obj_id FROM party_match_room WHERE room_id = ?");
				statement.setInt(1, _roomId);
				result = statement.executeQuery();
				while(result.next())
				{
					int object_id = result.getInt(1);
					L2PcInstance member = (L2PcInstance)L2World.getInstance().findObject(object_id);
					if(member != null)
					{
						if (object_id == _activeChar.getObjectId())
						{
							separateAndSend("<html><body><br>"
									+ showPartyRoomList(member, null, null)
									+ "</body></html>"
								,member);
							member.sendMessage("パーティールームから退室しました。");
						}
						else
						{
							separateAndSend("<html><body><br>"
									+ showPartyRoom(member, _roomId)
									+ "</body></html>"
								,member);
							member.sendMessage(_activeChar.getName()+"が退室しました。");
						}
					}
				}
				result.close();
				statement.close();

				statement = con.prepareStatement("DELETE FROM party_match_room WHERE room_id = ? AND char_obj_id = ?");
				statement.setInt(1, _roomId);
				statement.setInt(2, _activeChar.getObjectId());
				statement.execute();
				statement.close();
			}
		}
		catch (Exception e)
		{
			_log.info("could not delete Party Room: " + e);
			_activeChar.sendMessage("パーティー ルームの終了に失敗しました。");
			return;
		}
		finally
		{
			try { con.close(); } catch (Exception e) {}
		}
		brodeCastRoomInfo(_activeChar, _roomId);
		_activeChar.sendMessage("パーティー ルームを終了しました。");
	}

	//パーティーに勧誘する（Reference from RequestJoinParty.java）
	private boolean requestJoinParty(L2PcInstance requestor, L2PcInstance target, int _roomId)
	{
		PartyRoomInfo pi = getPartyRoomInfo(_roomId);

		if (requestor == null)
			return false;

		if (target == null)
		{
			requestor.sendPacket(new SystemMessage(SystemMessageId.TARGET_IS_INCORRECT));
			return false;
		}

		if (target.isInParty())
		{
			SystemMessage msg = new SystemMessage(SystemMessageId.S1_IS_ALREADY_IN_PARTY);
			msg.addString(target.getName());
			requestor.sendPacket(msg);
			return false;
		}

		if (target == requestor)
		{
			requestor.sendPacket(new SystemMessage(SystemMessageId.INCORRECT_TARGET));
			return false;
		}

		if (target.isCursedWeaponEquipped() || requestor.isCursedWeaponEquipped())
		{
			requestor.sendPacket(new SystemMessage(SystemMessageId.INCORRECT_TARGET));
			return false;
		}

		if (target.isInJail() || requestor.isInJail())
		{
			SystemMessage sm = SystemMessage.sendString("Player is in Jail");
			requestor.sendPacket(sm);
			return false;
		}

		if (target.isInOlympiadMode() || requestor.isInOlympiadMode())
			return false;

		if (target.isInDuel() || requestor.isInDuel())
			return false;

		// summary of ppl already in party and ppl that get invitation
		if (requestor.getParty() != null && requestor.getParty().getMemberCount() + requestor.getParty().getPendingInvitationNumber() >= 9)
		{
			requestor.sendPacket(new SystemMessage(SystemMessageId.PARTY_FULL));
 			return false;
 		}

		if (!target.isProcessingRequest())
		{
			if (requestor.getParty() == null)
				requestor.setParty(new L2Party(requestor, pi.type));
			requestor.onTransactionRequest(target);
			target.sendPacket(new AskJoinParty(requestor.getName(), pi.type));
			requestor.getParty().increasePendingInvitationNumber();
		}
		else
		{
			SystemMessage msg = new SystemMessage(SystemMessageId.S1_IS_BUSY_TRY_LATER);
			requestor.sendPacket(msg);
		}

		return true;
	}

	//パーティールームリストを表示する。
	private String showPartyRoomList(L2PcInstance _activeChar, String optionArea, String optionLevel)
	{
		TextBuilder where_str = new TextBuilder();
		if (optionArea != null && !optionArea.equals("全体"))
		{
			where_str.append(" loc = '"+optionArea+"'");
		}
		if (optionLevel != null && !optionLevel.equals("全体"))
		{
			String[]v = optionLevel.split("-");
			int minlevel = Integer.parseInt(v[0]);
			int maxlevel = Integer.parseInt(v[1]);
			if (where_str.length() != 0)
				where_str.append(" AND");
			where_str.append(" min <= '" + minlevel + "' AND max >= '" + maxlevel + "'");
		}
		if (where_str.length() != 0)
			where_str.append(" WHERE" + where_str);
		where_str.append(" ORDER BY id");
		TextBuilder roomList = new TextBuilder();
		TextBuilder DelRoom = new TextBuilder();
		int roomCount = 0;
		java.sql.Connection con = null;
		try
		{
			con = L2DatabaseFactory.getInstance().getConnection();
			PreparedStatement statement = con.prepareStatement("SELECT id FROM party_match_list" + where_str);
			ResultSet result = statement.executeQuery();
			while(result.next())
			{
				PartyRoomInfo pi = getPartyRoomInfo(result.getInt(1));
				L2PcInstance leader = (L2PcInstance)L2World.getInstance().findObject(pi.owner_id);
				if(leader == null)
				{
					if (DelRoom.length() != 0)
						DelRoom.append(",");
					DelRoom.append(pi.roomId);
				}
				else if(pi.roomId != -1 && pi.owner_id != -1)
				{
					roomList.append("<table width=610><tr>");
					roomList.append("<td width=30 align=center>" + pi.roomId + "</td>");
					roomList.append("<td width=160>" + pi.title + "</td>");
					roomList.append("<td width=120>" + leader.getName() + "</td>");
					roomList.append("<td width=120>" + pi.loc + "</td>");
					roomList.append("<td width=50 align=center>" + pi.min + " - " + pi.max + "</td>");
					roomList.append("<td width=50 align=center>" + pi.count + " / " + pi.limit + "</td>");
					roomList.append("<td width=80 align=center><button value=\"入室\" action=\"bypass _bbsgetfav;bbs_party_match;_joinRoom " + pi.roomId + "\" width=65 height=20 back=\"L2UI_CT1.BUTTON_DF_DOWN\" fore=\"L2UI_CT1.BUTTON_DF\"></td>");
					roomList.append("</tr></table>");
					roomCount++;
				}
			}
			result.close();
			statement.close();

			if (DelRoom.length() != 0)
			{
				statement = con.prepareStatement("DELETE FROM party_match_list WHERE id in (?)");
				statement.setString(1, DelRoom.toString());
				statement.execute();
				statement.close();
				statement = con.prepareStatement("DELETE FROM party_match_room WHERE room_id in (?)");
				statement.setString(1, DelRoom.toString());
				statement.execute();
				statement.close();
			}
		}
		catch (Exception e)
		{
			e.printStackTrace();
			return "パーティールームリスト作成中にエラーが発生しました。";
		}
		finally
		{
			try { con.close(); } catch (Exception e) {}
		}

		String html = HtmCache.getInstance().getHtm("data/html/CommunityBoard/party/partyRoomList.htm");
		html = html.replace("%roomList%", roomList);//ルームリスト
		return html;
	}

	//パーティールームを表示する。
	private /*String*/CharSequence showPartyRoom(L2PcInstance _activeChar, int _roomId)
	{
		PartyRoomInfo pi = getPartyRoomInfo(_roomId);
		if(pi.roomId == -1 && pi.owner_id == -1)
			return "";
		TextBuilder memberList = new TextBuilder();
		int memberCount = 0;
		java.sql.Connection con = null;
		try
		{
			con = L2DatabaseFactory.getInstance().getConnection();
			PreparedStatement statement = con.prepareStatement("SELECT * FROM party_match_room WHERE room_id = ? ORDER BY memberType");
			statement.setInt(1, _roomId);
			ResultSet result = statement.executeQuery();
			while(result.next())
			{
				L2Object member = L2World.getInstance().findObject(result.getInt(2));
				if(member != null && member instanceof L2PcInstance)
				{
					memberList.append("<table width=610><tr>");
					memberList.append("<td width=120>" + ((L2PcInstance)member).getName() + "</td>");
					memberList.append("<td width=130 align=center>" + ((L2PcInstance)member).getTemplate().className + "</td>");
					memberList.append("<td width=40 align=center>" + ((L2PcInstance)member).getLevel() + "</td>");
					memberList.append("<td width=130 align=center>" + MapRegionTable.getInstance().getClosestTownName( ((L2PcInstance)member) ) + "</td>");
					if(result.getInt(3) == 0)
					{
						memberList.append("<td width=120 align=center>ルームリーダー</td>");
					}
					else if(result.getInt(3) == 1)
					{
						memberList.append("<td width=120 align=center>パーティーメンバ</td>");
					}
					else
					{
						memberList.append("<td width=120 align=center>パーティー希望者</td>");
					}
					if(_activeChar.getObjectId() == pi.owner_id && _activeChar.getObjectId() != member.getObjectId())
					{
						memberList.append("<td width=70 align=center>");
						if(result.getInt(3) == 2)
							memberList.append("<button value=\"ＰＴ勧誘\" action=\"bypass _bbsgetfav;bbs_party_match;_joinParty " + _roomId + " " + member.getObjectId() + "\" width=65 height=20 back=\"L2UI_CT1.BUTTON_DF_DOWN\" fore=\"L2UI_CT1.BUTTON_DF\">");
						memberList.append("<button value=\"強制追放\" action=\"bypass _bbsgetfav;bbs_party_match;_kickRoom " + _roomId + " " + member.getObjectId() + "\" width=65 height=20 back=\"L2UI_CT1.BUTTON_DF_DOWN\" fore=\"L2UI_CT1.BUTTON_DF\">");
						memberList.append("</td>");
					}
					else
						memberList.append("<td width=70 align=center></td>");
					memberList.append("</tr></table>");
					memberCount++;
				}
			}
			result.close();
			statement.close();
		}
		catch (Exception e)
		{
			return "パーティールーム作成中にエラーが発生しました。";
		}
		finally
		{
			try { con.close(); } catch (Exception e) {}
		}

		TextReplacer html = new TextReplacer(HtmCache.getInstance().getHtm("data/html/CommunityBoard/party/partyRoom.htm"));
		html.replace("%roomId%", pi.roomId);	//部屋番号
		html.replace("%title%", htmlescape(pi.title));	//題目
		html.replace("%location%", pi.loc);	//場所
		html.replace("%current%", pi.count);	//現在の人数
		html.replace("%max%", pi.limit);	//上限の人数
		String lootdistribution = "";
		switch (pi.type)
		{
			case L2Party.ITEM_LOOTER:
				lootdistribution = "拾った人が所有";
				break;
			case L2Party.ITEM_RANDOM:
				lootdistribution = "ランダムに分配";
				break;
			case L2Party.ITEM_RANDOM_SPOIL:
				lootdistribution = "スポイルを含めランダムに";
				break;
			case L2Party.ITEM_ORDER:
				lootdistribution = "順番に取得";
				break;
			case L2Party.ITEM_ORDER_SPOIL:
				lootdistribution = "スポイルを含め順番に";
				break;
		}
		html.replace("%rootType%", lootdistribution);	//タイプ
		html.replace("%minlevel%", pi.min);	//最低レベル
		html.replace("%maxlevel%", pi.max);	//最高レベル
		html.replace("%memberList%", memberList);	//メンバーリスト
		String modifyButton = "";
		if(_activeChar.getObjectId() == pi.owner_id)
			modifyButton = "<button value=\"ルーム設定\" action=\"bypass _bbsgetfav;bbs_party_match;_modifyRoomWindow\" width=80 height=22 back=\"L2UI_CT1.BUTTON_DF_DOWN\" fore=\"L2UI_CT1.BUTTON_DF\">";
		html.replace("%modifyPartyRoom%", modifyButton);//設定変更ボタン

		return html;
	}

	//ドロップリストを表示する。
	private /*String*/CharSequence showDropList(L2PcInstance _activeChar, String optionType, String optionLevel, String optionWord)
	{
		String where_str = "";
		if (optionType.equals("アイテム名"))
			where_str = " AND itemname_jp.name Like ?";
		//	where_str = " AND itemname_jp.name Like '%" + quoteString(optionWord) + "%'";
		else
			where_str = " AND npc.name Like ?";
		//	where_str = " AND npc.name Like '%" + quoteString(optionWord) + "%'";
		if (!optionLevel.equals("全体"))
		{
			String v[] = optionLevel.split("-");
			int minlevel = Integer.parseInt(v[0]);
			int maxlevel = Integer.parseInt(v[1]);
		//	int minlevel = Integer.parseInt(optionLevel.split("-")[0]);
		//	int maxlevel = Integer.parseInt(optionLevel.split("-")[1]);
			where_str += " AND level BETWEEN " + minlevel + " AND " + maxlevel;
		}
		_log.info("UserName: "+_activeChar.getName()+" SearchWord : " + where_str);
		TextBuilder dropList = new TextBuilder();
		int dropCount = 0;
		java.sql.Connection con = null;
		try
		{
			con = L2DatabaseFactory.getInstance().getConnection();
			PreparedStatement statement = con.prepareStatement("SELECT level, npc.name as mobname, itemname_jp.name as itemname, category"
																+ " FROM droplist,npc,itemname_jp"
																+ " WHERE droplist.mobId = npc.id"
																+ " AND droplist.itemId = itemname_jp.item_id"
																+ " AND droplist.itemId != 57"
																+ where_str
																+ " ORDER BY level, npc.name, itemname_jp.name LIMIT 20");
			statement.setString(1, "%"+optionWord+"%");
			ResultSet result = statement.executeQuery();
			while(result.next())
			{
				dropList.append("<table width=610><tr>");
				dropList.append("<td width=40 align=center>" + result.getInt("level") + "</td>");
				dropList.append("<td width=220>" + result.getString("mobname") + "</td>");
				dropList.append("<td width=300>" + result.getString("itemname") + "</td>");
				dropList.append("<td width=50 align=center>" + (result.getInt("category") == -1 ? "＊" : "−") + "</td>");
				dropList.append("</tr></table>");
				dropCount++;
			}
			result.close();
			statement.close();
		}
		catch (Exception e)
		{
			e.printStackTrace();
			return "ドロップリスト作成中にエラーが発生しました。";
		}
		finally
		{
			try { con.close(); } catch (Exception e) {}
		}

		String html = HtmCache.getInstance().getHtm("data/html/CommunityBoard/droplist/DropList.htm");
		html = html.replace("%dropList%", dropList);//ドロップリスト
		return html;
	}

	//設定ウィンドウの表示
	private void showConfigWindow(L2PcInstance _activeChar, String filename)
	{
		NpcHtmlMessage html = new NpcHtmlMessage(5);
		html.setFile("data/html/CommunityBoard/"+filename);
		html.replace("%roomId%", getRoomIdByCharId(_activeChar.getObjectId()));//部屋番号
		_activeChar.sendPacket(html);
	}

	//キャラクターが参加している部屋のIDを返す（未所属は-1）
	public int getRoomIdByCharId(int char_obj_id)
	{
		java.sql.Connection con = null;
		try
		{
			con = L2DatabaseFactory.getInstance().getConnection();
			PreparedStatement statement = con.prepareStatement("SELECT room_id FROM party_match_room WHERE char_obj_id = ?");
			statement.setInt(1, char_obj_id);
			ResultSet result = statement.executeQuery();
			while(result.next())
			{
				return result.getInt(1);
			}
			result.close();
			statement.close();
		}
		catch (Exception e)
		{
			return -1;
		}
		finally
		{
			try { con.close(); } catch (Exception e) {}
		}
		return -1;
	}

	class PartyRoomInfo {
		int roomId;			//部屋番号
		int owner_id = 0;	//主催者ID
		int min = 1;		//最低レベル
		int max = 100;		//最高レベル
		int limit = -1;		//上限
		String loc = "";	//パーティの位置
		int type = 0;		//拾った人、ランダム
		String title = "";	//題目
		int count = -1;		//現在の人数
		
		PartyRoomInfo(int _roomId) { this.roomId = _roomId; }
	}

	//パーティールームの設定・情報を返す
	public PartyRoomInfo getPartyRoomInfo(int _roomId)
	{
		PartyRoomInfo pi = new PartyRoomInfo(_roomId);

		java.sql.Connection con = null;
		try
		{
			con = L2DatabaseFactory.getInstance().getConnection();
			PreparedStatement statement = con.prepareStatement("SELECT owner_id, min, max, `limit`, loc, type, title FROM party_match_list WHERE id = ?");
			statement.setInt(1, _roomId);
			ResultSet result = statement.executeQuery();
			while(result.next())
			{
				pi.owner_id = result.getInt(1);	//主催者ID
				pi.min = result.getInt(2);		//最低レベル
				pi.max = result.getInt(3);		//最高レベル
				pi.limit = result.getInt(4);	//上限
				pi.loc = result.getString(5);	//パーティの位置
				pi.type = result.getInt(6);		//拾った人、ランダム
				pi.title = result.getString(7);	//題目
			}
			result.close();
			statement.close();

			statement = con.prepareStatement("SELECT COUNT(*) FROM party_match_room WHERE room_id = ?");
			statement.setInt(1, _roomId);
			result = statement.executeQuery();
			while(result.next())
			{
				pi.count = result.getInt(1);	//現在の人数
			}
			result.close();
			statement.close();
		}
		catch (Exception e)
		{
			e.printStackTrace();
			return pi;
		}
		finally
		{
			try { con.close(); } catch (Exception e) {}
		}
		return pi;
	}

	//パーティールームの状況が変化したら、メンバー全員に送信する。
	public void brodeCastRoomInfo(L2PcInstance _activeChar, int _roomId)
	{
		java.sql.Connection con = null;
		try
		{
			con = L2DatabaseFactory.getInstance().getConnection();

			PreparedStatement statement = con.prepareStatement("SELECT char_obj_id, memberType FROM party_match_room WHERE room_id = ?");
			statement.setInt(1, _roomId);
			ResultSet result = statement.executeQuery();
			while(result.next())
			{
				int object_id = result.getInt(1);
				int member_type = result.getInt(2);
				L2PcInstance member = (L2PcInstance)L2World.getInstance().findObject(object_id);
				if(member != null)
				{
					if (member_type != 0)
					{
						PreparedStatement statement2 = con.prepareStatement("UPDATE party_match_room SET memberType = ? WHERE room_id = ? AND char_obj_id = ?");
						statement2.setInt(1, member.isInParty() ? 1 : 2);
						statement2.setInt(2, _roomId);
						statement2.setInt(3, member.getObjectId());
						statement2.executeUpdate();
						statement2.close();
					}

					separateAndSend("<html><body><br>"
							+ showPartyRoom(member, _roomId)
							+ "</body></html>"
						,member);
				}
			}
			result.close();
			statement.close();
		}
		catch (Exception e)
		{
			_log.info("could not update Party Room Info: " + e);
			_activeChar.sendMessage("パーティー ルーム情報の更新に失敗しました。");
			return;
		}
		finally
		{
			try { con.close(); } catch (Exception e) {}
		}
	}

//BaseBBSManager に移動
//	/**
//	 * html に使えない文字をエスケープする。
//	 * （ほんとは BaseBBSManager に書いたほうがいいかも）
//	 * @param  text - plain text
//	 * @return - html text
//	 */
//	private String htmlescape(CharSequence text)
//	{
//		CharSequence html = text;
//		StringBuilder buf = new StringBuilder(text.length()*2);
//		for (int index = 0; index < text.length(); ++index) {
//			char ch = text.charAt(index);
//			switch (ch) {
//			case '&': html = buf.append("&amp;"); break;
//			case '<': html = buf.append("&lt;"); break;
//		//	case '>': html = buf.append("&gt;"); break;
//			case ' ': html = buf.append("&nbsp;"); break;
//			case '"': html = buf.append("&quot;"); break;
//			case '\'': html = buf.append("&apos;"); break;
//			case '\n': html = buf.append("<br1>"); break;
//			default: buf.append(ch); break;
//			}
//		}
//		return html.toString();
//	}
}