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.os.Bundle;
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 ImageView[] backColors;
private Resources resources;
private GameViewModel gameViewModel;
// ロングタップで表示させるために必要。非同期で値が格納され、順番通りに保存されないからHashMapにしている
private Map<Integer, Bitmap> bmImages = new HashMap<>();
// 下はテストが動くようになったら削除する
private Map<Integer, Drawing> drawingList = new HashMap<>(); //<dno, drawingのURL>
private List<Integer> map = new ArrayList<>(); //cno順にdnoを管理(要するに絵の並び)
private List<String> 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){
// インスタンス生成
DrawingCardFragment fragment = new DrawingCardFragment();
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
setupWithViewModel();
resources = getResources();
View view = inflater.inflate(R.layout.fragment_card_drawing, container, false);
Context context = getContext();
// ImageButton16個の型を使いまわしやすいように配列で使用
imageButtons = new ImageButton[] {
(ImageButton) view.findViewById(R.id.imageButton0),
(ImageButton) view.findViewById(R.id.imageButton1),
(ImageButton) view.findViewById(R.id.imageButton2),
(ImageButton) view.findViewById(R.id.imageButton3),
(ImageButton) view.findViewById(R.id.imageButton4),
(ImageButton) view.findViewById(R.id.imageButton5),
(ImageButton) view.findViewById(R.id.imageButton6),
(ImageButton) view.findViewById(R.id.imageButton7),
(ImageButton) view.findViewById(R.id.imageButton8),
(ImageButton) view.findViewById(R.id.imageButton9),
(ImageButton) view.findViewById(R.id.imageButton10),
(ImageButton) view.findViewById(R.id.imageButton11),
(ImageButton) view.findViewById(R.id.imageButton12),
(ImageButton) view.findViewById(R.id.imageButton13),
(ImageButton) view.findViewById(R.id.imageButton14),
(ImageButton) view.findViewById(R.id.imageButton15)
};
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 < drawingList.size(); i++) {
// タップとロングタップのセット
imageButtons[i].setOnClickListener(this::onClick);
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<Integer, Drawing>() {
{
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<Boolean> 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() {
}
}