diff --git a/app/src/main/java/org/ntlab/irisclient/DrawingCardFragment.java b/app/src/main/java/org/ntlab/irisclient/DrawingCardFragment.java index 3058248..debd96f 100644 --- a/app/src/main/java/org/ntlab/irisclient/DrawingCardFragment.java +++ b/app/src/main/java/org/ntlab/irisclient/DrawingCardFragment.java @@ -1,20 +1,61 @@ package org.ntlab.irisclient; +import static android.os.Looper.getMainLooper; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.Context; import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.graphics.drawable.Drawable; -import android.media.Image; import android.os.Bundle; -import android.util.Log; +import android.util.DisplayMetrics; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.view.animation.Animation; +import android.view.animation.AnimationSet; +import android.view.animation.RotateAnimation; +import android.view.animation.ScaleAnimation; import android.widget.ImageButton; +import android.widget.ImageView; +import android.widget.LinearLayout; +import androidx.core.os.HandlerCompat; import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProvider; + +import org.ntlab.irisclient.models.Drawing; +import org.ntlab.irisclient.viewmodels.GameViewModel; + +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Executors; public class DrawingCardFragment extends Fragment { private ImageButton[] imageButtons; - private Drawable[] images; + private ImageView[] backColors; + private Resources resources; + private GameViewModel gameViewModel; + // ロングタップで表示させるために必要。非同期で値が格納され、順番通りに保存されないからHashMapにしている + private Map bmImages = new HashMap<>(); + + // 下はテストが動くようになったら削除する + private Map drawingList = new HashMap<>(); // + private List map = new ArrayList<>(); //cno順にdnoを管理(要するに絵の並び) + private List colorList = new ArrayList<>(); //cno順にr,g,b,dを管理:カードごとの色 + private Boolean isMaster = false; + // 自分のチームと現在進行中のチームを仮で設定中 + private String myTeam = "r"; + private String nowTurn = "r"; // コンストラクタ public static DrawingCardFragment newInstance(String str){ @@ -28,11 +69,13 @@ Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); - Resources resources = getResources(); + setupWithViewModel(); + resources = getResources(); View view = inflater.inflate(R.layout.fragment_card_drawing, container, false); + Context context = getContext(); // ImageButton16個の型を使いまわしやすいように配列で使用 - imageButtons = new ImageButton[]{ + imageButtons = new ImageButton[] { (ImageButton) view.findViewById(R.id.imageButton0), (ImageButton) view.findViewById(R.id.imageButton1), (ImageButton) view.findViewById(R.id.imageButton2), @@ -51,42 +94,427 @@ (ImageButton) view.findViewById(R.id.imageButton15) }; - // 16枚表示させるImage画像の配列 - images = new Drawable[]{ - resources.getDrawable(R.drawable.test02), - resources.getDrawable(R.drawable.test02), - resources.getDrawable(R.drawable.test02), - resources.getDrawable(R.drawable.test02), - resources.getDrawable(R.drawable.test02), - resources.getDrawable(R.drawable.test02), - resources.getDrawable(R.drawable.test02), - resources.getDrawable(R.drawable.test02), - resources.getDrawable(R.drawable.test02), - resources.getDrawable(R.drawable.test02), - resources.getDrawable(R.drawable.test02), - resources.getDrawable(R.drawable.test02), - resources.getDrawable(R.drawable.test02), - resources.getDrawable(R.drawable.test02), - resources.getDrawable(R.drawable.test02), - resources.getDrawable(R.drawable.test02) + backColors = new ImageView[]{ + (ImageView) view.findViewById(R.id.backColour0), + (ImageView) view.findViewById(R.id.backColour1), + (ImageView) view.findViewById(R.id.backColour2), + (ImageView) view.findViewById(R.id.backColour3), + (ImageView) view.findViewById(R.id.backColour4), + (ImageView) view.findViewById(R.id.backColour5), + (ImageView) view.findViewById(R.id.backColour6), + (ImageView) view.findViewById(R.id.backColour7), + (ImageView) view.findViewById(R.id.backColour8), + (ImageView) view.findViewById(R.id.backColour9), + (ImageView) view.findViewById(R.id.backColour10), + (ImageView) view.findViewById(R.id.backColour11), + (ImageView) view.findViewById(R.id.backColour12), + (ImageView) view.findViewById(R.id.backColour13), + (ImageView) view.findViewById(R.id.backColour14), + (ImageView) view.findViewById(R.id.backColour15) }; - for(int i=0; i< imageButtons.length; i++) { + for (int i = 0; i < drawingList.size(); i++) { + // タップとロングタップのセット imageButtons[i].setOnClickListener(this::onClick); - imageButtons[i].setBackground(images[i]); + imageButtons[i].setOnLongClickListener(this::onLongTap); + backColors[i].setOnLongClickListener(this::onLongTap); - }; + // 画像のセット + String urlSt = drawingList.get(map.get(i)).getDrawing(); + setImage(i, urlSt, context); + + // 初回だけセットする外枠の、メンバーとマスターで表示分け + // メンバー:全て肌色、マスター:赤・青・黒・グレーの表示 + if(isMaster == true) { + if (colorList.get(i) == "r") { + backColors[i].setBackground(resources.getDrawable(R.drawable.red_image)); + } else if (colorList.get(i) == "b") { + backColors[i].setBackground(resources.getDrawable(R.drawable.blue_image)); + } else if (colorList.get(i) == "g") { + backColors[i].setBackground(resources.getDrawable(R.drawable.gray_image)); + } else if (colorList.get(i) == "d") { + backColors[i].setBackground(resources.getDrawable(R.drawable.black_image)); + } + } else { + backColors[i].setBackground(resources.getDrawable(R.drawable.skin_image)); + } + + } + + // Openされた画像ををObserveして、Viewに反映 + gameViewModel.getOpenLiveData().observe ( + getViewLifecycleOwner(), + openListObserver -> { + System.out.println(openListObserver); + setOpen(openListObserver); + } + ); return view; } public void onClick(View v) { - for(int i=0; i< imageButtons.length; i++) { if(v.getId() == imageButtons[i].getId()) { System.out.println( "タップされたボタンの配列番号:" + i); + if(nowTurn != myTeam && isMaster == true) { return; } + confirmAlertMake(i); + } + } + } + + public boolean onLongTap(View v) { + + for(int i=0; i< imageButtons.length; i++) { + + if(v.getId() == imageButtons[i].getId()) { + System.out.println( "ロングタップされたボタンの配列番号:" + i); + // 自分のターンのとき、疑い機能のあるアラート表示 + // 相手のターンのとき、画像だけ確認できるアラート表示 + if(nowTurn == myTeam) { + doubtAlertMake(i); + } else { + lookImageAlertMake(i); + } + } + + // めくられた画像を長押でも確認できるようにする + if(v.getId() == backColors[i].getId()) { + System.out.println( "タップされたボタンの配列番号:" + i); + lookImageAlertMake(i); } } + return false; } -} + + private void setupWithViewModel() { + gameViewModel = new ViewModelProvider(this).get(GameViewModel.class); + //drawingList = gameViewModel.getGame().getDrawingList(); + //map = gameViewModel.getGame().getMap(); + //colorList = gameViewModel.getGame().getColorList(); + + // 本来は上を開放するが、値が空なので仮値を指定(テストフローでも値が空) + Drawing drawing0 = new Drawing(); + Drawing drawing1 = new Drawing(); + Drawing drawing2 = new Drawing(); + Drawing drawing3 = new Drawing(); + Drawing drawing4 = new Drawing(); + Drawing drawing5 = new Drawing(); + Drawing drawing6 = new Drawing(); + Drawing drawing7 = new Drawing(); + Drawing drawing8 = new Drawing(); + Drawing drawing9 = new Drawing(); + Drawing drawing10 = new Drawing(); + Drawing drawing11 = new Drawing(); + Drawing drawing12 = new Drawing(); + Drawing drawing13 = new Drawing(); + Drawing drawing14 = new Drawing(); + Drawing drawing15 = new Drawing(); + drawing0.setDrawing("http://nitta-lab-www.is.konan-u.ac.jp/irisdata/image/test16.jpg"); + drawing1.setDrawing("http://nitta-lab-www.is.konan-u.ac.jp/irisdata/image/test01.jpg"); + drawing2.setDrawing("http://nitta-lab-www.is.konan-u.ac.jp/irisdata/image/test02.jpg"); + drawing3.setDrawing("http://nitta-lab-www.is.konan-u.ac.jp/irisdata/image/test03.jpg"); + drawing4.setDrawing("http://nitta-lab-www.is.konan-u.ac.jp/irisdata/image/test04.jpg"); + drawing5.setDrawing("http://nitta-lab-www.is.konan-u.ac.jp/irisdata/image/test05.jpg"); + drawing6.setDrawing("http://nitta-lab-www.is.konan-u.ac.jp/irisdata/image/test06.jpg"); + drawing7.setDrawing("http://nitta-lab-www.is.konan-u.ac.jp/irisdata/image/test07.jpg"); + drawing8.setDrawing("http://nitta-lab-www.is.konan-u.ac.jp/irisdata/image/test08.jpg"); + drawing9.setDrawing("http://nitta-lab-www.is.konan-u.ac.jp/irisdata/image/test09.jpg"); + drawing10.setDrawing("http://nitta-lab-www.is.konan-u.ac.jp/irisdata/image/test10.jpg"); + drawing11.setDrawing("http://nitta-lab-www.is.konan-u.ac.jp/irisdata/image/test11.jpg"); + drawing12.setDrawing("http://nitta-lab-www.is.konan-u.ac.jp/irisdata/image/test12.jpg"); + drawing13.setDrawing("http://nitta-lab-www.is.konan-u.ac.jp/irisdata/image/test13.jpg"); + drawing14.setDrawing("http://nitta-lab-www.is.konan-u.ac.jp/irisdata/image/test14.jpg"); + drawing15.setDrawing("http://nitta-lab-www.is.konan-u.ac.jp/irisdata/image/test15.jpg"); + + drawingList = new HashMap() { + { + put(11, drawing11); + put(12, drawing12); + put(1, drawing1); + put(8, drawing8); + put(6, drawing6); + put(14, drawing14); + put(4, drawing4); + put(15, drawing15); + put(10, drawing10); + put(2, drawing2); + put(0, drawing0); + put(7, drawing7); + put(13, drawing13); + put(3, drawing3); + put(5, drawing5); + put(9, drawing9); + } + }; + map = new ArrayList<>(Arrays.asList(2, 13, 6, 0, 7, 8, 4, 9, 14, 1, 3, 15, 11, 5, 12, 10)); + colorList = new ArrayList<>(Arrays.asList("r", "b", "b", "r", "b", "r", "d", "b", "g", "b", "r", "g", "b", "r", "g", "r")); + + System.out.print(drawingList.size()); + System.out.print("よばれたよ"); + } + + /** + * URLから画像を取得 + * Androidのルール的にメインスレッドで書くとクラッシュする + * 非同期で書かなければならない + **/ + private void setImage(int cno, String urlSt, Context context) { + // Singleの別スレッドを立ち上げる + Executors.newSingleThreadExecutor().execute(() -> { + try { + URL url = new URL(urlSt); + HttpURLConnection urlCon = (HttpURLConnection) url.openConnection(); + + // タイムアウト設定 + urlCon.setReadTimeout(10000); + urlCon.setConnectTimeout(20000); + + // リクエストメソッド + urlCon.setRequestMethod("GET"); + + // リダイレクトを自動で許可しない設定 + urlCon.setInstanceFollowRedirects(false); + + InputStream is = urlCon.getInputStream(); + Bitmap originalBMP = BitmapFactory.decodeStream(is); + Bitmap resizedMiniBMP = resize(originalBMP, (int) convertDp2Px(105, context),(int) convertDp2Px(60, context)); + Bitmap resizedBigBMP = resize(originalBMP, (int) convertDp2Px(420, context),(int) convertDp2Px(240, context)); + bmImages.put(cno, resizedBigBMP); + + HandlerCompat.createAsync(getMainLooper()).post(() -> + // Mainスレッドに返す + imageButtons[cno].setImageBitmap(resizedMiniBMP) + ); + + } catch (IOException e) { + e.printStackTrace(); + } + }); + } + + /** + * dpとpxを変換 + * BitMapでImageを描画するためにどうしても必要だった + **/ + private static float convertDp2Px(float dp, Context context) { + DisplayMetrics metrics = context.getResources().getDisplayMetrics(); + return dp * metrics.density; + } + + /** + * 表示させる画像のサイズ調整 + **/ + private static Bitmap resize(Bitmap image, int maxWidth, int maxHeight) { + if (maxHeight > 0 && maxWidth > 0) { + + int width = image.getWidth(); + int height = image.getHeight(); + float ratioBitmap = (float) width / (float) height; + float ratioMax = (float) maxWidth / (float) maxHeight; + + int finalWidth = maxWidth; + int finalHeight = maxHeight; + if (ratioMax > 1) { + finalWidth = (int) ((float)maxHeight * ratioBitmap); + } else { + finalHeight = (int) ((float)maxWidth / ratioBitmap); + } + image = Bitmap.createScaledBitmap(image, finalWidth, finalHeight, true); + return image; + } else { + return image; + } + } + + /** + * 開けられたImageをViewに反映させる + * Observeして変更加わった度に呼ばれる + **/ + private void setOpen(List openList) { + for(int i=0; i< openList.size(); i++) { + if (openList.get(i) == true) { + // オープンだったときの描画 + if (colorList.get(i) == "r") { + backColors[i].setBackground(resources.getDrawable(R.drawable.red_image)); + imageButtons[i].setVisibility(View.INVISIBLE); + } else if (colorList.get(i) == "b") { + backColors[i].setBackground(resources.getDrawable(R.drawable.blue_image)); + imageButtons[i].setVisibility(View.INVISIBLE); + } else if (colorList.get(i) == "g") { + backColors[i].setBackground(resources.getDrawable(R.drawable.gray_image)); + imageButtons[i].setVisibility(View.INVISIBLE); + } else if (colorList.get(i) == "d") { + backColors[i].setBackground(resources.getDrawable(R.drawable.black_image)); + imageButtons[i].setVisibility(View.INVISIBLE); + finishGameAlertMake(i, myTeam, nowTurn); + } + setAnime(i); + } + } + } + + //----------------------------------------------------------------------------- + // アラート関係の関数 + /** + * 本当に裏返してよいか確認させるアラート + */ + private void confirmAlertMake(int cno){ + String strTitle = "注意"; + String strMessage = "本当にカードをめくってよろしいですか?"; + + AlertDialog.Builder builder; + builder = new AlertDialog.Builder(getContext()); + builder.setMessage(strMessage); + builder.setTitle(strTitle); + builder.setPositiveButton("ok", (dialog, id) -> setOpenRealTime(cno, true)); + builder.setNegativeButton("キャンセル", (dialog, id) -> setOpenRealTime(cno, false)); + builder.create(); + builder.show(); + } + + /** + * アラートから呼ばれる、リアルタイムに裏返す処理 + **/ + private void setOpenRealTime(int cno, boolean isOK) { + // 裏返す処理 + if(isOK) { + if (colorList.get(cno) == "r") { + backColors[cno].setBackground(resources.getDrawable(R.drawable.red_image)); + imageButtons[cno].setVisibility(View.INVISIBLE); + } else if (colorList.get(cno) == "b") { + backColors[cno].setBackground(resources.getDrawable(R.drawable.blue_image)); + imageButtons[cno].setVisibility(View.INVISIBLE); + } else if (colorList.get(cno) == "g") { + backColors[cno].setBackground(resources.getDrawable(R.drawable.gray_image)); + imageButtons[cno].setVisibility(View.INVISIBLE); + } else if (colorList.get(cno) == "d") { + backColors[cno].setBackground(resources.getDrawable(R.drawable.black_image)); + imageButtons[cno].setVisibility(View.INVISIBLE); + finishGameAlertMake(cno, myTeam, nowTurn); + } + setAnime(cno); + } + //TODO: gameViewModel.set〇〇(cno)が完成したら + + } + + /** + * 自分のターンのときに、 + * 疑うか疑わないかのアラートを表示させるコード + */ + private void doubtAlertMake(int cno){ + String strTitle = "疑いますか?"; + String strMessage = "(ここに画像を表示させる予定)"; + + AlertDialog.Builder builder; + builder = new AlertDialog.Builder(getContext()); + builder.setTitle(strTitle); + + ImageView iv = new ImageView(getContext()); + iv.setImageBitmap(bmImages.get(cno)); + + iv.setAdjustViewBounds(true); + builder.setView(iv); + + builder.setPositiveButton("疑う", (dialog, id) -> setDoubt(cno, true)); + builder.setNegativeButton("キャンセル", (dialog, id) -> setDoubt(cno, false)); + builder.create(); + builder.show(); + } + + /** + * アラートから呼ばれる、疑いをかける処理 + **/ + private void setDoubt(int cno, boolean isOK) { + // 疑う処理 + } + + /** + * 相手のターンのときに、 + * 画像だけ確認できるアラートを表示させるコード + */ + private void lookImageAlertMake(int cno){ + String strTitle = ""; + + AlertDialog.Builder builder; + builder = new AlertDialog.Builder(getContext()); + builder.setTitle(strTitle); + + ImageView iv = new ImageView(getContext()); + iv.setImageBitmap(bmImages.get(cno)); + iv.setAdjustViewBounds(true); + + builder.setView(iv); + + builder.setPositiveButton("完了", (dialog, id) -> setNone(cno, true)); + builder.create(); + builder.show(); + } + + /** + * アラートからOKを呼ばれたときにする処理 + * まだ空 + **/ + private void setNone(int cno, boolean isOK) { + } + + private void setAnime(int cno){ + ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f, 0.0f, 1.0f, 0.0f, + Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); + // animation時間 msec + scaleAnimation.setDuration(2000); + + RotateAnimation rotate = new RotateAnimation(0.0f, 120.0f, + Animation.RELATIVE_TO_PARENT, 0.0f, Animation.RELATIVE_TO_PARENT, 0.5f); + // animation時間 msec + rotate.setDuration(2000); + + AnimationSet animationSet = new AnimationSet( true ); + + // animationSetにそれぞれ追加する + animationSet.addAnimation( scaleAnimation ); + animationSet.addAnimation( rotate ); + + imageButtons[cno].startAnimation(animationSet); + } + + /** + * 黒いカードがひかれて、ゲームが終わったときに呼ばれるアラート + */ + private void finishGameAlertMake(int cno, String myTeam, String nowTurn) { + try { + Thread.sleep(2000); //3000ミリ秒Sleepする + } catch (InterruptedException e) { + } + + String strTitle; + String strMessage; + + if (myTeam == nowTurn) { + strTitle = "Your Lose..."; + strMessage = "お疲れ様でした。\n残念ながら、あなたチームは負けました..."; + } else { + strTitle = "Your Win!!"; + strMessage = "お疲れ様でした。\nおめでとうございます、あなたチームの勝利です!"; + } + + AlertDialog.Builder builder; + builder = new AlertDialog.Builder(getContext()); + builder.setTitle(strTitle); + builder.setMessage(strMessage); + builder.setPositiveButton("完了", (dialog, id) -> setFinish()); + builder.create(); + builder.show(); + } + + // TODO: 未完成の関数 + /** + * ゲームが終了したときに呼ばれる関数 + * 画面をトップに戻る動作でも書く? + **/ + private void setFinish() { + } + +} \ No newline at end of file