Java tutorial
/** * Copyright (C) 2013-2014 EaseMob Technologies. All rights reserved. * * 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.grass.caishi.cc.activity; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Map; import org.apache.http.Header; import com.easemob.util.PathUtil; import com.grass.caishi.cc.Constant; import com.grass.caishi.cc.MyApplication; import com.grass.caishi.cc.R; import com.grass.caishi.cc.utils.CommonUtils; import com.grass.caishi.cc.utils.HttpRestClient; import com.grass.caishi.cc.utils.JsonToMapList; import com.grass.caishi.cc.utils.MetricsUnit; import com.grass.caishi.cc.utils.PreferenceUtils; import com.grass.caishi.cc.win.MyPhotoShowView; import com.grass.caishi.cc.win.MyPhotoShowView.OnDeleteButtonClick; import com.grass.view.ActionSheetDialog; import com.grass.view.MyDialog; import com.grass.view.ActionSheetDialog.OnSheetItemClickListener; import com.grass.view.ActionSheetDialog.SheetItemColor; import com.grass.view.MyDialog.OnSweetClickListener; import com.loopj.android.http.RequestParams; import com.loopj.android.http.TextHttpResponseHandler; import com.nostra13.universalimageloader.utils.StorageUtils; import android.annotation.SuppressLint; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Bitmap.CompressFormat; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.provider.MediaStore; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.view.View.OnClickListener; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.LinearLayout.LayoutParams; import android.widget.PopupWindow.OnDismissListener; import android.widget.EditText; import android.widget.GridView; import android.widget.ImageView; import android.widget.ScrollView; import android.widget.Toast; public class AdAddActivity extends BaseActivity { private final int REQUEST_CODE_IMAGES = 1001; private final int REQUEST_CODE_CAMERA = 1002; public static final int USERPIC_REQUEST_CODE_CUT = 103; private CheckBox nvshen; private CheckBox nanshen; private EditText edit_title; private EditText edit_price; private EditText edit_info; private EditText edit_text; private EditText edit_time; private EditText edit_address; private EditText edit_company; private ImageView img_logo; private ImageView img_price; private GridView grid_images; private Button btn_submit; private String path_logo; private String path_price; private MyImageAdapter adapter; private MyPhotoShowView photoShowView; private int act_id = 0; private int iss_id = 0; private ScrollView conView; private int select_type = 0; private Bitmap resizeBmp; private String imageUrl; @Override protected void onCreate(Bundle arg0) { super.onCreate(arg0); setContentView(R.layout.activity_adadd_main); inItView(); } protected void inItView() { getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); MyApplication.getInstance().clearMatchImage(); adapter = new MyImageAdapter(this); // conView = (ScrollView) findViewById(R.id.scrollView1); // conView.setVisibility(View.GONE); photoShowView = new MyPhotoShowView(this); photoShowView.setOnDismissListener(new OnDismissListener() { @Override public void onDismiss() { // TODO Auto-generated method stub adapter.notifyDataSetChanged(); } }); photoShowView.setOnDeleteButtonClick(new OnDeleteButtonClick() { @Override public void onDelectClick(int num) { // TODO Auto-generated method stub adapter.notifyDataSetChanged(); } }); nvshen = (CheckBox) findViewById(R.id.adadd_main_check_nvshen); nanshen = (CheckBox) findViewById(R.id.adadd_main_check_nanshen); edit_address = (EditText) findViewById(R.id.adadd_main_edit_address); edit_company = (EditText) findViewById(R.id.adadd_main_edit_company); edit_info = (EditText) findViewById(R.id.adadd_main_edit_info); edit_text = (EditText) findViewById(R.id.adadd_main_edit_text); edit_price = (EditText) findViewById(R.id.adadd_main_edit_price); edit_time = (EditText) findViewById(R.id.adadd_main_edit_time); edit_title = (EditText) findViewById(R.id.adadd_main_edit_title); img_logo = (ImageView) findViewById(R.id.adadd_main_image_logo); img_logo.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub select_type = 1; select_images(); } }); img_price = (ImageView) findViewById(R.id.adadd_main_image_price); img_price.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub select_type = 2; select_images(); } }); grid_images = (GridView) findViewById(R.id.adadd_main_grid_images); grid_images.setVisibility(View.VISIBLE); grid_images.setAdapter(adapter); grid_images.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { // TODO Auto-generated method stub if (arg2 == MyApplication.getInstance().getMatchImages().size()) { select_type = 3; select_images(); } else { photoShowView.show(arg2); } } }); btn_submit = (Button) findViewById(R.id.adadd_main_btn_submit); nvshen.setOnCheckedChangeListener(new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton arg0, boolean arg1) { // TODO Auto-generated method stub if (arg1) { act_id = 1; nanshen.setChecked(false); checkType(1); } } }); nanshen.setOnCheckedChangeListener(new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton arg0, boolean arg1) { // TODO Auto-generated method stub if (arg1) { act_id = 2; nvshen.setChecked(false); checkType(2); } } }); btn_submit.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub submit_Do(); } }); } public void checkType(int aid) { dialog.setMessage("???..."); dialog.show(); RequestParams params = new RequestParams(); params.put("act_id", aid); HttpRestClient.post(Constant.SELECT_NOW_ISS_ID_DO, params, new TextHttpResponseHandler() { @Override public void onSuccess(int statusCode, Header[] headers, String responseString) { // TODO Auto-generated method stub if (dialog.isShowing()) dialog.dismiss(); if (CommonUtils.isNullOrEmpty(responseString)) { new MyDialog(AdAddActivity.this, MyDialog.WARNING_TYPE) .setTitleText("??").show(); return; } Map<String, Object> m = JsonToMapList.getMap(responseString); if (m == null) { new MyDialog(AdAddActivity.this, MyDialog.WARNING_TYPE).setTitleText("???") .show(); return; } if (!CommonUtils.isNullOrEmpty(m.get("data")) && m.get("ok").toString().equals("1")) { int id = Integer.valueOf(m.get("code").toString()); iss_id = id; } else { new MyDialog(AdAddActivity.this, MyDialog.WARNING_TYPE).setTitleText(m.get("msg").toString()) .setCancelClickListener(new OnSweetClickListener() { @Override public void onClick(MyDialog sweetAlertDialog) { // TODO Auto-generated method stub act_id = 0; nanshen.setChecked(false); nvshen.setChecked(false); } }).show(); } } @Override public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) { // TODO Auto-generated method stub if (dialog.isShowing()) dialog.dismiss(); AdAddActivity.this.finish(); } }); } protected void submit_Do() { String title = edit_title.getText().toString().trim(); String price = edit_price.getText().toString().trim(); String info = edit_info.getText().toString().trim(); String text = edit_text.getText().toString().trim(); String time = edit_time.getText().toString().trim(); String address = edit_address.getText().toString().trim(); String company = edit_company.getText().toString().trim(); if ((!nanshen.isChecked() && !nvshen.isChecked()) || act_id == 0) { new MyDialog(this, MyDialog.WARNING_TYPE).setTitleText("??").show(); } if (CommonUtils.isNullOrEmpty(title)) { new MyDialog(this, MyDialog.WARNING_TYPE).setTitleText("?????").show(); return; } if (CommonUtils.isNullOrEmpty(price)) { new MyDialog(this, MyDialog.WARNING_TYPE).setTitleText("??").show(); return; } if (CommonUtils.isNullOrEmpty(info)) { new MyDialog(this, MyDialog.WARNING_TYPE).setTitleText("?????").show(); return; } if (CommonUtils.isNullOrEmpty(text)) { new MyDialog(this, MyDialog.WARNING_TYPE).setTitleText("???????") .show(); return; } if (CommonUtils.isNullOrEmpty(time)) { new MyDialog(this, MyDialog.WARNING_TYPE).setTitleText("???").show(); return; } if (CommonUtils.isNullOrEmpty(address)) { new MyDialog(this, MyDialog.WARNING_TYPE).setTitleText("???").show(); return; } if (CommonUtils.isNullOrEmpty(company)) { new MyDialog(this, MyDialog.WARNING_TYPE).setTitleText("????").show(); return; } if (CommonUtils.isNullOrEmpty(path_logo)) { new MyDialog(this, MyDialog.WARNING_TYPE).setTitleText("?LOGO").show(); return; } if (CommonUtils.isNullOrEmpty(path_price)) { new MyDialog(this, MyDialog.WARNING_TYPE).setTitleText("?").show(); return; } ArrayList<String> list = MyApplication.getInstance().getMatchImages(); if (list.size() > 9) { new MyDialog(this, MyDialog.WARNING_TYPE).setTitleText("??9?").show(); return; } String add_code = PreferenceUtils.getInstance(this).getSettingUserCityCode(); RequestParams params = new RequestParams(); params.put("title", title); params.put("price", price); params.put("info", info); params.put("text", text); params.put("time", time); params.put("address", address); params.put("company", company); params.put("act_id", act_id); params.put("add_code", add_code); File flogo = new File(path_logo); File fprice = new File(path_price); try { params.put("logo", flogo, "image/jpeg"); params.put("imageprice", fprice, "image/jpeg"); params.put("img_num", list.size()); for (int i = 0; i < list.size(); i++) { File file = new File(list.get(i)); params.put("img" + i, file, "image/jpeg"); } } catch (FileNotFoundException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } dialog.setMessage("...0%"); dialog.show(); HttpRestClient.post(Constant.SEND_AD_ADD_DO, params, new TextHttpResponseHandler() { @Override public void onSuccess(int statusCode, Header[] headers, String responseString) { // TODO Auto-generated method stub if (CommonUtils.isNullOrEmpty(responseString)) { dialog.dismiss(); new MyDialog(AdAddActivity.this, MyDialog.ERROR_TYPE).setTitleText("??") .show(); return; } Map<String, Object> m = JsonToMapList.getMap(responseString); if (m != null && !CommonUtils.isNullOrEmpty(m.get("data")) && m.get("ok").toString().equals("1")) { dialog.setMessage(m.get("msg").toString()); dialog.showHide(); dialog.setOnDismissListener(new DialogInterface.OnDismissListener() { @Override public void onDismiss(DialogInterface arg0) { // TODO Auto-generated method stub AdAddActivity.this.finish(); Toast.makeText(AdAddActivity.this, "???", Toast.LENGTH_SHORT) .show(); } }); } else { dialog.dismiss(); new MyDialog(AdAddActivity.this, MyDialog.ERROR_TYPE).setTitleText("???").show(); } } @Override public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) { // TODO Auto-generated method stub dialog.dismiss(); } @Override public void onProgress(int bytesWritten, int totalSize) { dialog.setMessage(String.format("??... %2.0f%%", (totalSize > 0) ? (bytesWritten * 1.0 / totalSize) * 100 : -1)); } }); } private File cameraFile; /** * ? */ public void select_images() { /* * //SDcard if(Environment.getExternalStorageState().equals(Environment .MEDIA_MOUNTED)){ //SDcardTestSyncListView IMAGE_FILE_LOCATION = Environment.getExternalStorageDirectory()+Constant .CACHE_DIR_IMAGE+"/temp.jpg"; imageUri = Uri.parse(IMAGE_FILE_LOCATION); //File cutFile = new File(Constant.CACHE_DIR_IMAGE,"temp.jpg"); //cutFile.getParentFile().mkdirs(); File dir = new File(IMAGE_FILE_LOCATION); if (!dir.exists()) { try { // dir.createNewFile(); } catch (Exception e) { //println(e); } } * * }else{ Toast.makeText(getActivity(), "SD????", 0).show(); return; } */ cameraFile = new File(StorageUtils.getOwnCacheDirectory(AdAddActivity.this, Constant.CACHE_DIR_IMAGE), System.currentTimeMillis() + ".jpg"); if (cameraFile == null && !cameraFile.exists()) {// ? cameraFile.getParentFile().mkdirs(); } new ActionSheetDialog(this).builder().setCancelable(true).setCanceledOnTouchOutside(true) .addSheetItem("?", SheetItemColor.Blue, new OnSheetItemClickListener() { @Override public void onClick(int which) { /* -? */ if (!CommonUtils.isExitsSdcard()) { Toast.makeText(AdAddActivity.this, "SD????", Toast.LENGTH_SHORT).show(); return; } selectPicFromCamera(); } }).addSheetItem("", SheetItemColor.Blue, new OnSheetItemClickListener() { @Override public void onClick(int which) { selectPicFromLocal(); } }).show(); } /** * ? */ public void selectPicFromCamera() { if (!CommonUtils.isExitsSdcard()) { Toast.makeText(getApplicationContext(), "SD????", Toast.LENGTH_SHORT).show(); return; } // cameraFile = new File(PathUtil.getInstance().getImagePath(), // DemoApplication.getInstance().getUserName() cameraFile = new File(PathUtil.getInstance().getImagePath(), MyApplication.getInstance().getUser() + System.currentTimeMillis() + ".jpg"); cameraFile.getParentFile().mkdirs(); startActivityForResult(new Intent(MediaStore.ACTION_IMAGE_CAPTURE).putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(cameraFile)), REQUEST_CODE_CAMERA); } /** * ?uri?? * * @param selectedImage */ private String getPicByUri(Uri selectedImage) { // String[] filePathColumn = { MediaStore.Images.Media.DATA }; Cursor cursor = getContentResolver().query(selectedImage, null, null, null, null); if (cursor != null) { cursor.moveToFirst(); int columnIndex = cursor.getColumnIndex("_data"); String picturePath = cursor.getString(columnIndex); cursor.close(); cursor = null; if (picturePath == null || picturePath.equals("null")) { Toast toast = Toast.makeText(this, "?", Toast.LENGTH_SHORT); toast.setGravity(Gravity.CENTER, 0, 0); toast.show(); return null; } return picturePath; } else { File file = new File(selectedImage.getPath()); if (!file.exists()) { Toast toast = Toast.makeText(this, "?", Toast.LENGTH_SHORT); toast.setGravity(Gravity.CENTER, 0, 0); toast.show(); return null; } return file.getAbsolutePath(); } } /** * ? */ public void selectPicFromLocal() { Intent intent; if (Build.VERSION.SDK_INT < 19) { intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType("image/*"); } else { intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI); } startActivityForResult(intent, REQUEST_CODE_IMAGES); } public void addToListImage(final String path) { if (path != null) { dialog.setMessage("..."); dialog.show(); new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub File file = new File(path); imageUrl = path; FileInputStream fis = null; try { int quality = 90; fis = new FileInputStream(file); int size = fis.available() / 1024; if (size > 150) { BitmapFactory.Options opts = new BitmapFactory.Options(); opts.inJustDecodeBounds = true; resizeBmp = BitmapFactory.decodeFile(path, opts); int pic_width = opts.outWidth; int pic_height = opts.outHeight; int be = 1; if (pic_height > pic_width && pic_width > 1500) { be = (int) Math.rint(pic_width / 1440.0); } else if (pic_height < pic_width && pic_height > 2600) { be = (int) Math.rint(pic_height / 2560.0); } if (be <= 0) be = 1; opts.inSampleSize = be;// opts.inJustDecodeBounds = false; resizeBmp = BitmapFactory.decodeFile(path, opts); pic_width = opts.outWidth; pic_height = opts.outHeight; File dirFile = new File(Environment.getExternalStorageDirectory(), Constant.CACHE_DIR_IMAGE); if (!dirFile.exists()) { dirFile.mkdirs(); } int drive_width = MetricsUnit.getWidth(AdAddActivity.this); int drive_height = MetricsUnit.getHeight(AdAddActivity.this); float my_width = (float) drive_width; float my_height = (float) drive_height; double doo = 0.0; if (pic_width > my_width) { doo = (double) my_width / (double) pic_width; my_height = (int) (pic_height * doo); } int c_h = 0; if (my_height > drive_height) { c_h = (int) ((pic_height - my_height) / 2); if (c_h < 0) { c_h = 0; } } Matrix matrix = new Matrix(); matrix.postScale(my_width / pic_width, my_height / pic_height); resizeBmp = Bitmap.createBitmap(resizeBmp, 0, c_h, pic_width, pic_height, matrix, true); File jpegTrueFile = new File(dirFile, "img_" + System.currentTimeMillis() + ".jpg"); FileOutputStream fileOutputStream = new FileOutputStream(jpegTrueFile); resizeBmp.compress(CompressFormat.JPEG, quality, fileOutputStream); imageUrl = jpegTrueFile.getAbsolutePath(); // MyApplication.getInstance().setMatchImages(jpegTrueFile.getAbsolutePath()); //bit.recycle(); } else { resizeBmp = BitmapFactory.decodeStream(fis); } runOnUiThread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub if (select_type == 1) { path_logo = imageUrl; img_logo.setImageBitmap(resizeBmp); } else if (select_type == 2) { path_price = imageUrl; img_price.setImageBitmap(resizeBmp); } else if (select_type == 3) { MyApplication.getInstance().setMatchImages(imageUrl); adapter.notifyDataSetChanged(); } if (dialog.isShowing()) { dialog.dismiss(); } } }); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }).start(); } } /** * ? * * @param uri * @param outputX * @param outputY * @param requestCode */ private void cropImageUri(Uri uri, int outputX, int outputY, int requestCode) { /* * Intent intent = new Intent("com.android.camera.action.CROP"); intent.setDataAndType(uri, "image/*"); intent.putExtra("crop", "true"); //aspectX aspectY intent.putExtra("aspectX", 1); intent.putExtra("aspectY", 1); // outputX outputY ? intent.putExtra("outputX", outputX); intent.putExtra("outputY", outputY); intent.putExtra("scale", true); intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); intent.putExtra("return-data", false); intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString()); intent.putExtra("noFaceDetection", true); // no face detection startActivityForResult(intent, requestCode); */ Intent intent = new Intent("com.android.camera.action.CROP"); intent.setDataAndType(uri, "image/*"); intent.putExtra("crop", "true"); intent.putExtra("aspectX", 3); intent.putExtra("aspectY", 1); intent.putExtra("outputX", outputX); intent.putExtra("outputY", outputY); intent.putExtra("scale", true); intent.putExtra("return-data", true); intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString()); intent.putExtra("noFaceDetection", true); // no face detection startActivityForResult(intent, requestCode); } /** * onActivityResult */ protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == RESULT_OK) { // ? if (requestCode == REQUEST_CODE_CAMERA) { // ?? if (cameraFile != null && cameraFile.exists()) if (select_type == 1) cropImageUri(Uri.fromFile(cameraFile), 450, 150, USERPIC_REQUEST_CODE_CUT); else addToListImage(cameraFile.getAbsolutePath()); // img_list.add(cameraFile.getAbsolutePath()); } else if (requestCode == REQUEST_CODE_IMAGES) { // ?? if (data != null) { Uri selectedImage = data.getData(); if (selectedImage != null) { if (select_type == 1) cropImageUri(selectedImage, 450, 150, USERPIC_REQUEST_CODE_CUT); else addToListImage(getPicByUri(selectedImage)); // img_list.add(getPicByUri(selectedImage)); } } } else if (requestCode == USERPIC_REQUEST_CODE_CUT) {// ? // ? if (data != null) { Bitmap bitmap = data.getParcelableExtra("data"); img_logo.setImageBitmap(bitmap); System.err.println(cameraFile.getAbsolutePath()); cameraFile = saveJPGE_After(bitmap, cameraFile); // // ???? addToListImage(cameraFile.getAbsolutePath()); } else { } } } } /** * bitmap file ?JPEG * * @param bitmap * @param cameraFile2 */ public File saveJPGE_After(Bitmap bitmap, File cameraFile2) { // File file = new File(cameraFile2); try { FileOutputStream out = new FileOutputStream(cameraFile2); if (bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out)) { out.flush(); out.close(); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return cameraFile2; } private class MyImageAdapter extends BaseAdapter { // ArrayList<String> list; Context context; public MyImageAdapter(Context context) { this.context = context; // this.list = MyApplication.getInstance().getMatchImages(); } @Override public int getCount() { // TODO Auto-generated method stub return MyApplication.getInstance().getMatchImages().size() < 9 ? MyApplication.getInstance().getMatchImages().size() + 1 : 9; } @Override public Object getItem(int arg0) { // TODO Auto-generated method stub return MyApplication.getInstance().getMatchImages().get(arg0); } @Override public long getItemId(int arg0) { // TODO Auto-generated method stub return arg0; } @SuppressLint("InflateParams") @Override public View getView(int arg0, View contextView, ViewGroup arg2) { // TODO Auto-generated method stub ViewHolder view; if (contextView == null) { view = new ViewHolder(); contextView = LayoutInflater.from(context).inflate(R.layout.item_sendmatch_list_layout, null); view.imageview = (ImageView) contextView.findViewById(R.id.item_sendmatch_list_image); int image_dp = MetricsUnit.getWidth(AdAddActivity.this, 40) / 4; LayoutParams lp = (LayoutParams) view.imageview.getLayoutParams(); lp.width = image_dp; lp.height = image_dp; view.imageview.setLayoutParams(lp); contextView.setTag(view); } else { view = (ViewHolder) contextView.getTag(); } if (arg0 == MyApplication.getInstance().getMatchImages().size() && arg0 < 9) { view.imageview.setImageResource(R.drawable.icon_addpic_unfocused); } else { // String url = // MyApplication.getInstance().getMatchImages().get(arg0); // try { // FileInputStream in=new FileInputStream(url); // Bitmap bit=BitmapFactory.decodeStream(in); // mImageResizer.loadImage(url, view.imageview); // view.imageview.setimage view.imageview.setImageBitmap(MyApplication.getInstance().getMatchImageBitmap(arg0)); // } catch (FileNotFoundException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } } return contextView; } } static class ViewHolder { ImageView imageview; } }