13c1e67e433728684b5f228c5d4f3e5b1457bb271sm/*
23c1e67e433728684b5f228c5d4f3e5b1457bb271sm * Copyright (C) 2010 The Android Open Source Project
33c1e67e433728684b5f228c5d4f3e5b1457bb271sm *
43c1e67e433728684b5f228c5d4f3e5b1457bb271sm * Licensed under the Apache License, Version 2.0 (the "License");
53c1e67e433728684b5f228c5d4f3e5b1457bb271sm * you may not use this file except in compliance with the License.
63c1e67e433728684b5f228c5d4f3e5b1457bb271sm * You may obtain a copy of the License at
73c1e67e433728684b5f228c5d4f3e5b1457bb271sm *
83c1e67e433728684b5f228c5d4f3e5b1457bb271sm *      http://www.apache.org/licenses/LICENSE-2.0
93c1e67e433728684b5f228c5d4f3e5b1457bb271sm *
103c1e67e433728684b5f228c5d4f3e5b1457bb271sm * Unless required by applicable law or agreed to in writing, software
113c1e67e433728684b5f228c5d4f3e5b1457bb271sm * distributed under the License is distributed on an "AS IS" BASIS,
123c1e67e433728684b5f228c5d4f3e5b1457bb271sm * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133c1e67e433728684b5f228c5d4f3e5b1457bb271sm * See the License for the specific language governing permissions and
143c1e67e433728684b5f228c5d4f3e5b1457bb271sm * limitations under the License.
153c1e67e433728684b5f228c5d4f3e5b1457bb271sm */
163c1e67e433728684b5f228c5d4f3e5b1457bb271sm
173c1e67e433728684b5f228c5d4f3e5b1457bb271smpackage com.replica.replicaisland;
183c1e67e433728684b5f228c5d4f3e5b1457bb271sm
193c1e67e433728684b5f228c5d4f3e5b1457bb271smimport android.content.Context;
203c1e67e433728684b5f228c5d4f3e5b1457bb271smimport android.content.DialogInterface;
213c1e67e433728684b5f228c5d4f3e5b1457bb271smimport android.content.SharedPreferences;
223c1e67e433728684b5f228c5d4f3e5b1457bb271smimport android.content.DialogInterface.OnKeyListener;
233c1e67e433728684b5f228c5d4f3e5b1457bb271smimport android.content.res.TypedArray;
243c1e67e433728684b5f228c5d4f3e5b1457bb271smimport android.graphics.drawable.Drawable;
253c1e67e433728684b5f228c5d4f3e5b1457bb271smimport android.os.Bundle;
263c1e67e433728684b5f228c5d4f3e5b1457bb271smimport android.preference.DialogPreference;
273c1e67e433728684b5f228c5d4f3e5b1457bb271smimport android.util.AttributeSet;
283c1e67e433728684b5f228c5d4f3e5b1457bb271smimport android.view.KeyEvent;
293c1e67e433728684b5f228c5d4f3e5b1457bb271smimport android.view.View;
303c1e67e433728684b5f228c5d4f3e5b1457bb271smimport android.widget.TextView;
313c1e67e433728684b5f228c5d4f3e5b1457bb271sm
323c1e67e433728684b5f228c5d4f3e5b1457bb271sm
333c1e67e433728684b5f228c5d4f3e5b1457bb271smpublic class KeyboardConfigDialogPreference extends DialogPreference implements OnKeyListener {
343c1e67e433728684b5f228c5d4f3e5b1457bb271sm	private SharedPreferences mSharedPrefs;
353c1e67e433728684b5f228c5d4f3e5b1457bb271sm	private Context mContext;
363c1e67e433728684b5f228c5d4f3e5b1457bb271sm	private String mLeftPrefKey;
373c1e67e433728684b5f228c5d4f3e5b1457bb271sm	private String mRightPrefKey;
383c1e67e433728684b5f228c5d4f3e5b1457bb271sm	private String mJumpPrefKey;
393c1e67e433728684b5f228c5d4f3e5b1457bb271sm	private String mAttackPrefKey;
403c1e67e433728684b5f228c5d4f3e5b1457bb271sm	private String[] mKeyLabels;
413c1e67e433728684b5f228c5d4f3e5b1457bb271sm	private int mListeningId = 0;
423c1e67e433728684b5f228c5d4f3e5b1457bb271sm	private View mLeftBorder;
433c1e67e433728684b5f228c5d4f3e5b1457bb271sm	private View mRightBorder;
443c1e67e433728684b5f228c5d4f3e5b1457bb271sm	private View mJumpBorder;
453c1e67e433728684b5f228c5d4f3e5b1457bb271sm	private View mAttackBorder;
463c1e67e433728684b5f228c5d4f3e5b1457bb271sm	private Drawable mUnselectedBorder;
473c1e67e433728684b5f228c5d4f3e5b1457bb271sm	private Drawable mSelectedBorder;
483c1e67e433728684b5f228c5d4f3e5b1457bb271sm	private int mLeftKeyCode;
493c1e67e433728684b5f228c5d4f3e5b1457bb271sm	private int mRightKeyCode;
503c1e67e433728684b5f228c5d4f3e5b1457bb271sm	private int mJumpKeyCode;
513c1e67e433728684b5f228c5d4f3e5b1457bb271sm	private int mAttackKeyCode;
523c1e67e433728684b5f228c5d4f3e5b1457bb271sm	private TextView mLeftText;
533c1e67e433728684b5f228c5d4f3e5b1457bb271sm	private TextView mRightText;
543c1e67e433728684b5f228c5d4f3e5b1457bb271sm	private TextView mJumpText;
553c1e67e433728684b5f228c5d4f3e5b1457bb271sm	private TextView mAttackText;
563c1e67e433728684b5f228c5d4f3e5b1457bb271sm
573c1e67e433728684b5f228c5d4f3e5b1457bb271sm	private class ConfigClickListener implements View.OnClickListener {
583c1e67e433728684b5f228c5d4f3e5b1457bb271sm		private int mId;
593c1e67e433728684b5f228c5d4f3e5b1457bb271sm		public ConfigClickListener(int id) {
603c1e67e433728684b5f228c5d4f3e5b1457bb271sm			mId = id;
613c1e67e433728684b5f228c5d4f3e5b1457bb271sm		}
623c1e67e433728684b5f228c5d4f3e5b1457bb271sm
633c1e67e433728684b5f228c5d4f3e5b1457bb271sm		public void onClick(View v) {
643c1e67e433728684b5f228c5d4f3e5b1457bb271sm			selectId(mId);
653c1e67e433728684b5f228c5d4f3e5b1457bb271sm		}
663c1e67e433728684b5f228c5d4f3e5b1457bb271sm
673c1e67e433728684b5f228c5d4f3e5b1457bb271sm	}
683c1e67e433728684b5f228c5d4f3e5b1457bb271sm
693c1e67e433728684b5f228c5d4f3e5b1457bb271sm	public KeyboardConfigDialogPreference(Context context, AttributeSet attrs) {
703c1e67e433728684b5f228c5d4f3e5b1457bb271sm		this(context, attrs, android.R.attr.dialogPreferenceStyle);
713c1e67e433728684b5f228c5d4f3e5b1457bb271sm	}
723c1e67e433728684b5f228c5d4f3e5b1457bb271sm
733c1e67e433728684b5f228c5d4f3e5b1457bb271sm	public KeyboardConfigDialogPreference(Context context, AttributeSet attrs,
743c1e67e433728684b5f228c5d4f3e5b1457bb271sm			int defStyle) {
753c1e67e433728684b5f228c5d4f3e5b1457bb271sm		super(context, attrs, defStyle);
763c1e67e433728684b5f228c5d4f3e5b1457bb271sm
773c1e67e433728684b5f228c5d4f3e5b1457bb271sm		TypedArray a = context.obtainStyledAttributes(attrs,
783c1e67e433728684b5f228c5d4f3e5b1457bb271sm                R.styleable.KeyConfigPreference, defStyle, 0);
793c1e67e433728684b5f228c5d4f3e5b1457bb271sm		mLeftPrefKey = a.getString(R.styleable.KeyConfigPreference_leftKey);
803c1e67e433728684b5f228c5d4f3e5b1457bb271sm		mRightPrefKey = a.getString(R.styleable.KeyConfigPreference_rightKey);
813c1e67e433728684b5f228c5d4f3e5b1457bb271sm		mJumpPrefKey = a.getString(R.styleable.KeyConfigPreference_jumpKey);
823c1e67e433728684b5f228c5d4f3e5b1457bb271sm		mAttackPrefKey = a.getString(R.styleable.KeyConfigPreference_attackKey);
833c1e67e433728684b5f228c5d4f3e5b1457bb271sm
843c1e67e433728684b5f228c5d4f3e5b1457bb271sm        a.recycle();
853c1e67e433728684b5f228c5d4f3e5b1457bb271sm	}
863c1e67e433728684b5f228c5d4f3e5b1457bb271sm
873c1e67e433728684b5f228c5d4f3e5b1457bb271sm	public KeyboardConfigDialogPreference(Context context) {
883c1e67e433728684b5f228c5d4f3e5b1457bb271sm        this(context, null);
893c1e67e433728684b5f228c5d4f3e5b1457bb271sm    }
903c1e67e433728684b5f228c5d4f3e5b1457bb271sm
913c1e67e433728684b5f228c5d4f3e5b1457bb271sm	@Override
923c1e67e433728684b5f228c5d4f3e5b1457bb271sm	protected void onBindDialogView(View view) {
933c1e67e433728684b5f228c5d4f3e5b1457bb271sm		super.onBindDialogView(view);
943c1e67e433728684b5f228c5d4f3e5b1457bb271sm		if (mSharedPrefs != null) {
953c1e67e433728684b5f228c5d4f3e5b1457bb271sm			mLeftKeyCode = mSharedPrefs.getInt(mLeftPrefKey, KeyEvent.KEYCODE_DPAD_LEFT);
963c1e67e433728684b5f228c5d4f3e5b1457bb271sm			mRightKeyCode = mSharedPrefs.getInt(mRightPrefKey, KeyEvent.KEYCODE_DPAD_RIGHT);
973c1e67e433728684b5f228c5d4f3e5b1457bb271sm			mJumpKeyCode = mSharedPrefs.getInt(mJumpPrefKey, KeyEvent.KEYCODE_SPACE);
983c1e67e433728684b5f228c5d4f3e5b1457bb271sm			mAttackKeyCode = mSharedPrefs.getInt(mAttackPrefKey, KeyEvent.KEYCODE_SHIFT_LEFT);
993c1e67e433728684b5f228c5d4f3e5b1457bb271sm
1003c1e67e433728684b5f228c5d4f3e5b1457bb271sm
1013c1e67e433728684b5f228c5d4f3e5b1457bb271sm			mLeftText = (TextView)view.findViewById(R.id.key_left);
1023c1e67e433728684b5f228c5d4f3e5b1457bb271sm			mLeftText.setText(getKeyLabel(mLeftKeyCode));
1033c1e67e433728684b5f228c5d4f3e5b1457bb271sm
1043c1e67e433728684b5f228c5d4f3e5b1457bb271sm			mRightText = (TextView)view.findViewById(R.id.key_right);
1053c1e67e433728684b5f228c5d4f3e5b1457bb271sm			mRightText.setText(getKeyLabel(mRightKeyCode));
1063c1e67e433728684b5f228c5d4f3e5b1457bb271sm
1073c1e67e433728684b5f228c5d4f3e5b1457bb271sm			mJumpText = (TextView)view.findViewById(R.id.key_jump);
1083c1e67e433728684b5f228c5d4f3e5b1457bb271sm			mJumpText.setText(getKeyLabel(mJumpKeyCode));
1093c1e67e433728684b5f228c5d4f3e5b1457bb271sm
1103c1e67e433728684b5f228c5d4f3e5b1457bb271sm			mAttackText = (TextView)view.findViewById(R.id.key_attack);
1113c1e67e433728684b5f228c5d4f3e5b1457bb271sm			mAttackText.setText(getKeyLabel(mAttackKeyCode));
1123c1e67e433728684b5f228c5d4f3e5b1457bb271sm
1133c1e67e433728684b5f228c5d4f3e5b1457bb271sm			mLeftBorder = view.findViewById(R.id.left_border);
1143c1e67e433728684b5f228c5d4f3e5b1457bb271sm			mRightBorder = view.findViewById(R.id.right_border);
1153c1e67e433728684b5f228c5d4f3e5b1457bb271sm			mJumpBorder = view.findViewById(R.id.jump_border);
1163c1e67e433728684b5f228c5d4f3e5b1457bb271sm			mAttackBorder = view.findViewById(R.id.attack_border);
1173c1e67e433728684b5f228c5d4f3e5b1457bb271sm
1183c1e67e433728684b5f228c5d4f3e5b1457bb271sm			mLeftBorder.setOnClickListener(new ConfigClickListener(R.id.key_left));
1193c1e67e433728684b5f228c5d4f3e5b1457bb271sm			mRightBorder.setOnClickListener(new ConfigClickListener(R.id.key_right));
1203c1e67e433728684b5f228c5d4f3e5b1457bb271sm			mJumpBorder.setOnClickListener(new ConfigClickListener(R.id.key_jump));
1213c1e67e433728684b5f228c5d4f3e5b1457bb271sm			mAttackBorder.setOnClickListener(new ConfigClickListener(R.id.key_attack));
1223c1e67e433728684b5f228c5d4f3e5b1457bb271sm
1233c1e67e433728684b5f228c5d4f3e5b1457bb271sm			mUnselectedBorder = mContext.getResources().getDrawable(R.drawable.key_config_border);
1243c1e67e433728684b5f228c5d4f3e5b1457bb271sm			mSelectedBorder = mContext.getResources().getDrawable(R.drawable.key_config_border_active);
1253c1e67e433728684b5f228c5d4f3e5b1457bb271sm		}
1263c1e67e433728684b5f228c5d4f3e5b1457bb271sm
1273c1e67e433728684b5f228c5d4f3e5b1457bb271sm		mListeningId = 0;
1283c1e67e433728684b5f228c5d4f3e5b1457bb271sm
1293c1e67e433728684b5f228c5d4f3e5b1457bb271sm
1303c1e67e433728684b5f228c5d4f3e5b1457bb271sm	}
1313c1e67e433728684b5f228c5d4f3e5b1457bb271sm
1323c1e67e433728684b5f228c5d4f3e5b1457bb271sm	@Override
1333c1e67e433728684b5f228c5d4f3e5b1457bb271sm	protected void showDialog(Bundle state) {
1343c1e67e433728684b5f228c5d4f3e5b1457bb271sm		super.showDialog(state);
1353c1e67e433728684b5f228c5d4f3e5b1457bb271sm		getDialog().setOnKeyListener(this);
1363c1e67e433728684b5f228c5d4f3e5b1457bb271sm		getDialog().takeKeyEvents(true);
1373c1e67e433728684b5f228c5d4f3e5b1457bb271sm	}
1383c1e67e433728684b5f228c5d4f3e5b1457bb271sm
1393c1e67e433728684b5f228c5d4f3e5b1457bb271sm	protected String getKeyLabel(int keycode) {
1403c1e67e433728684b5f228c5d4f3e5b1457bb271sm		String result = "Unknown Key";
1413c1e67e433728684b5f228c5d4f3e5b1457bb271sm		if (mKeyLabels == null) {
1423c1e67e433728684b5f228c5d4f3e5b1457bb271sm			mKeyLabels = mContext.getResources().getStringArray(R.array.keycode_labels);
1433c1e67e433728684b5f228c5d4f3e5b1457bb271sm		}
1443c1e67e433728684b5f228c5d4f3e5b1457bb271sm
1453c1e67e433728684b5f228c5d4f3e5b1457bb271sm		if (keycode > 0 && keycode < mKeyLabels.length) {
1463c1e67e433728684b5f228c5d4f3e5b1457bb271sm			result = mKeyLabels[keycode - 1];
1473c1e67e433728684b5f228c5d4f3e5b1457bb271sm		}
1483c1e67e433728684b5f228c5d4f3e5b1457bb271sm		return result;
1493c1e67e433728684b5f228c5d4f3e5b1457bb271sm	}
1503c1e67e433728684b5f228c5d4f3e5b1457bb271sm
1513c1e67e433728684b5f228c5d4f3e5b1457bb271sm	public void selectId(int id) {
1523c1e67e433728684b5f228c5d4f3e5b1457bb271sm		if (mListeningId != 0) {
1533c1e67e433728684b5f228c5d4f3e5b1457bb271sm			// unselect the current box
1543c1e67e433728684b5f228c5d4f3e5b1457bb271sm			View border = getConfigViewById(mListeningId);
1553c1e67e433728684b5f228c5d4f3e5b1457bb271sm			border.setBackgroundDrawable(mUnselectedBorder);
1563c1e67e433728684b5f228c5d4f3e5b1457bb271sm		}
1573c1e67e433728684b5f228c5d4f3e5b1457bb271sm
1583c1e67e433728684b5f228c5d4f3e5b1457bb271sm		if (id == mListeningId || id == 0) {
1593c1e67e433728684b5f228c5d4f3e5b1457bb271sm			mListeningId = 0; // toggle off and end.
1603c1e67e433728684b5f228c5d4f3e5b1457bb271sm		} else {
1613c1e67e433728684b5f228c5d4f3e5b1457bb271sm			// select the new box
1623c1e67e433728684b5f228c5d4f3e5b1457bb271sm			View border = getConfigViewById(id);
1633c1e67e433728684b5f228c5d4f3e5b1457bb271sm			border.setBackgroundDrawable(mSelectedBorder);
1643c1e67e433728684b5f228c5d4f3e5b1457bb271sm			mListeningId = id;
1653c1e67e433728684b5f228c5d4f3e5b1457bb271sm		}
1663c1e67e433728684b5f228c5d4f3e5b1457bb271sm	}
1673c1e67e433728684b5f228c5d4f3e5b1457bb271sm
1683c1e67e433728684b5f228c5d4f3e5b1457bb271sm	private View getConfigViewById(int id) {
1693c1e67e433728684b5f228c5d4f3e5b1457bb271sm		View config = null;
1703c1e67e433728684b5f228c5d4f3e5b1457bb271sm		switch(id) {
1713c1e67e433728684b5f228c5d4f3e5b1457bb271sm		case R.id.key_left:
1723c1e67e433728684b5f228c5d4f3e5b1457bb271sm			config = mLeftBorder;
1733c1e67e433728684b5f228c5d4f3e5b1457bb271sm			break;
1743c1e67e433728684b5f228c5d4f3e5b1457bb271sm		case R.id.key_right:
1753c1e67e433728684b5f228c5d4f3e5b1457bb271sm			config = mRightBorder;
1763c1e67e433728684b5f228c5d4f3e5b1457bb271sm			break;
1773c1e67e433728684b5f228c5d4f3e5b1457bb271sm		case R.id.key_jump:
1783c1e67e433728684b5f228c5d4f3e5b1457bb271sm			config = mJumpBorder;
1793c1e67e433728684b5f228c5d4f3e5b1457bb271sm			break;
1803c1e67e433728684b5f228c5d4f3e5b1457bb271sm		case R.id.key_attack:
1813c1e67e433728684b5f228c5d4f3e5b1457bb271sm			config = mAttackBorder;
1823c1e67e433728684b5f228c5d4f3e5b1457bb271sm			break;
1833c1e67e433728684b5f228c5d4f3e5b1457bb271sm		}
1843c1e67e433728684b5f228c5d4f3e5b1457bb271sm
1853c1e67e433728684b5f228c5d4f3e5b1457bb271sm		return config;
1863c1e67e433728684b5f228c5d4f3e5b1457bb271sm	}
1873c1e67e433728684b5f228c5d4f3e5b1457bb271sm
1883c1e67e433728684b5f228c5d4f3e5b1457bb271sm	@Override
1893c1e67e433728684b5f228c5d4f3e5b1457bb271sm	protected void onDialogClosed(boolean positiveResult) {
1903c1e67e433728684b5f228c5d4f3e5b1457bb271sm		super.onDialogClosed(positiveResult);
1913c1e67e433728684b5f228c5d4f3e5b1457bb271sm
1923c1e67e433728684b5f228c5d4f3e5b1457bb271sm		if (positiveResult) {
1933c1e67e433728684b5f228c5d4f3e5b1457bb271sm			// save changes
1943c1e67e433728684b5f228c5d4f3e5b1457bb271sm			SharedPreferences.Editor editor = mSharedPrefs.edit();
1953c1e67e433728684b5f228c5d4f3e5b1457bb271sm			editor.putInt(mLeftPrefKey, mLeftKeyCode);
1963c1e67e433728684b5f228c5d4f3e5b1457bb271sm			editor.putInt(mRightPrefKey, mRightKeyCode);
1973c1e67e433728684b5f228c5d4f3e5b1457bb271sm			editor.putInt(mJumpPrefKey, mJumpKeyCode);
1983c1e67e433728684b5f228c5d4f3e5b1457bb271sm			editor.putInt(mAttackPrefKey, mAttackKeyCode);
1993c1e67e433728684b5f228c5d4f3e5b1457bb271sm			editor.commit();
2003c1e67e433728684b5f228c5d4f3e5b1457bb271sm		}
2013c1e67e433728684b5f228c5d4f3e5b1457bb271sm	}
2023c1e67e433728684b5f228c5d4f3e5b1457bb271sm
2033c1e67e433728684b5f228c5d4f3e5b1457bb271sm	public void setPrefs(SharedPreferences sharedPreferences) {
2043c1e67e433728684b5f228c5d4f3e5b1457bb271sm		mSharedPrefs = sharedPreferences;
2053c1e67e433728684b5f228c5d4f3e5b1457bb271sm	}
2063c1e67e433728684b5f228c5d4f3e5b1457bb271sm
2073c1e67e433728684b5f228c5d4f3e5b1457bb271sm	public void setContext(Context context) {
2083c1e67e433728684b5f228c5d4f3e5b1457bb271sm		mContext = context;
2093c1e67e433728684b5f228c5d4f3e5b1457bb271sm	}
2103c1e67e433728684b5f228c5d4f3e5b1457bb271sm
2113c1e67e433728684b5f228c5d4f3e5b1457bb271sm	public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
2123c1e67e433728684b5f228c5d4f3e5b1457bb271sm		boolean eatKey = false;
2133c1e67e433728684b5f228c5d4f3e5b1457bb271sm		if (mListeningId != 0) {
2143c1e67e433728684b5f228c5d4f3e5b1457bb271sm			eatKey = true;
2153c1e67e433728684b5f228c5d4f3e5b1457bb271sm			switch (mListeningId) {
2163c1e67e433728684b5f228c5d4f3e5b1457bb271sm			case R.id.key_left:
2173c1e67e433728684b5f228c5d4f3e5b1457bb271sm				mLeftText.setText(getKeyLabel(keyCode));
2183c1e67e433728684b5f228c5d4f3e5b1457bb271sm				mLeftKeyCode = keyCode;
2193c1e67e433728684b5f228c5d4f3e5b1457bb271sm				break;
2203c1e67e433728684b5f228c5d4f3e5b1457bb271sm			case R.id.key_right:
2213c1e67e433728684b5f228c5d4f3e5b1457bb271sm				mRightText.setText(getKeyLabel(keyCode));
2223c1e67e433728684b5f228c5d4f3e5b1457bb271sm				mRightKeyCode = keyCode;
2233c1e67e433728684b5f228c5d4f3e5b1457bb271sm				break;
2243c1e67e433728684b5f228c5d4f3e5b1457bb271sm			case R.id.key_jump:
2253c1e67e433728684b5f228c5d4f3e5b1457bb271sm				mJumpText.setText(getKeyLabel(keyCode));
2263c1e67e433728684b5f228c5d4f3e5b1457bb271sm				mJumpKeyCode = keyCode;
2273c1e67e433728684b5f228c5d4f3e5b1457bb271sm				break;
2283c1e67e433728684b5f228c5d4f3e5b1457bb271sm			case R.id.key_attack:
2293c1e67e433728684b5f228c5d4f3e5b1457bb271sm				mAttackText.setText(getKeyLabel(keyCode));
2303c1e67e433728684b5f228c5d4f3e5b1457bb271sm				mAttackKeyCode = keyCode;
2313c1e67e433728684b5f228c5d4f3e5b1457bb271sm				break;
2323c1e67e433728684b5f228c5d4f3e5b1457bb271sm			}
2333c1e67e433728684b5f228c5d4f3e5b1457bb271sm
2343c1e67e433728684b5f228c5d4f3e5b1457bb271sm			selectId(0);	// deselect the current config box;
2353c1e67e433728684b5f228c5d4f3e5b1457bb271sm		}
2363c1e67e433728684b5f228c5d4f3e5b1457bb271sm		return eatKey;
2373c1e67e433728684b5f228c5d4f3e5b1457bb271sm	}
2383c1e67e433728684b5f228c5d4f3e5b1457bb271sm
2393c1e67e433728684b5f228c5d4f3e5b1457bb271sm}
240