package com.geek_alarm.android.activities; import android.app.Activity; import android.content.SharedPreferences; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.os.Bundle; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.View.OnClickListener; import android.widget.TextView; import com.geek_alarm.android.R; import com.geek_alarm.android.Utils; /** * Final activity. It shows users "progress". * Draws green rectangles for correct solutions and red for incorrect. */ public class ResultActivity extends Activity { private final static double GAP_TO_SIZE = 1 / 10.; private final static int[] LEVELS = { 6, 24, 60, 144, 360, 720 }; // Current 'size' of screen. Maximum number of rectangles on screen. // Possible values - LEVELS. private int num; // Number of rectangles in row. private int inRow; // Number of rectangles in column. private int inColumn; // Size of rectangle. private int size; // Gap between 2 rectangles. private int gap; // Left margin of first rect. private int marginLeft; // Top margin of first rect. private int marginTop; // NUmber of green rects. private int green; // NUmber of red rects. private int red; // True if green rect tries to fill red's position // or otherwise private boolean isFighting; // If user solved current "round" correctly. private boolean win; private boolean runAnimation; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.result); win = getIntent().getBooleanExtra("win", true); updateStats(); SurfaceView view = (SurfaceView) findViewById(R.id.image); view.getHolder().addCallback(new SurfaceCallback()); findViewById(R.id.exit).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { moveTaskToBack(true); finish(); } }); } private void setWinsLoses(int wins, int loses) { TextView view = (TextView) findViewById(R.id.wins); view.setText(String.valueOf(wins)); view = (TextView) findViewById(R.id.loses); view.setText(String.valueOf(loses)); } @Override public void onBackPressed() { super.onBackPressed(); moveTaskToBack(true); } private void updateStats(){ SharedPreferences pref = Utils.getPreferences(); int wins = pref.getInt("wins", 0); int loses = pref.getInt("loses", 0); if (win) { wins++; } else { loses++; } setWinsLoses(wins, loses); red = pref.getInt("red", 0); green = pref.getInt("green", 0); int level = pref.getInt("level", 0); num = LEVELS[level]; if (green == num && win) { level++; if (level == LEVELS.length) { green = 0; red = 0; level = 0; } num = LEVELS[level]; } isFighting = red + green == num; if (isFighting) { red -= win ? 1 : 0; green -= win ? 0 : 1; } green = Math.max(green, 0); SharedPreferences.Editor editor = pref.edit(); editor.putInt("wins", wins); editor.putInt("loses", loses); editor.putInt("red", red + (!win && !isFighting ? 1 : 0)); editor.putInt("green", green + (win && !isFighting ? 1 : 0)); editor.putInt("level", level); editor.commit(); } /** * Calulcates all neccessary drawing parameters: * size, margins, etc... * @param width of drawing area. * @param height of drawing area. */ private void initConf(int width, int height) { size = 0; gap = 0; // Try all possible positions, finding position where size is max. for (int i = 1; i < num / 2; i++) { if (num % i != 0) { continue; } int curInRow = i; int curInColumn = num / i; int curSumSize = Math.min(width / curInRow, height / curInColumn); if (curSumSize > size + gap) { size = (int) Math.ceil(curSumSize / (1 + GAP_TO_SIZE)); gap = curSumSize - size; inRow = curInRow; inColumn = curInColumn; } } marginLeft = (width - inRow * (gap + size) + gap) / 2; marginTop = (height - inColumn * (gap + size) + gap) / 2; } private class SurfaceCallback implements SurfaceHolder.Callback { @Override public void surfaceCreated(SurfaceHolder holder) { Animator animator = new Animator(holder); runAnimation = true; new Thread(animator).start(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { runAnimation = false; } } private class Animator implements Runnable { private SurfaceHolder holder; private Paint paint; public Animator(SurfaceHolder holder) { super(); this.holder = holder; paint = new Paint(); } public void run() { Canvas canvas = holder.lockCanvas(); initConf(canvas.getWidth(), canvas.getHeight()); int curNum = win ? green : num - red - 1; int steps = size; int winColor = win ? Color.GREEN : Color.RED; int opColor = win ? Color.RED : Color.GREEN; drawGreen(canvas); drawRed(canvas); if (isFighting) { drawRect(curNum, opColor, canvas, true, size); } holder.unlockCanvasAndPost(canvas); int x = marginLeft + curNum % inRow * (gap + size); int y = marginTop + curNum / inRow * (gap + size); Rect dirty = new Rect(x, y, x + size, y + size); try { Thread.sleep(500); } catch (InterruptedException e) { // Do nothing. } while (steps >= 0 && runAnimation) { canvas = holder.lockCanvas(dirty); drawRect(curNum, Color.BLACK, canvas, true, size); if (isFighting) { drawRect(curNum, winColor, canvas, win, Math.min(size - steps, steps)); drawRect(curNum, opColor, canvas, !win, steps); } else { drawRect(curNum, winColor, canvas, win, size - steps); } try { holder.unlockCanvasAndPost(canvas); } catch (IllegalArgumentException e) { Log.e(ResultActivity.class.getName(), "Need to investigate", e); return; } steps--; } } /** * * @param num - number of rect to be drawn. * @param color * @param canvas * @param fromLeft - if rect should be drawn starting from left. * it matters when rect is not square. Red rects must be drawn from right. * @param width */ private void drawRect(int num, int color, Canvas canvas, boolean fromLeft, int width) { if (width == 0 || canvas == null) { return; } int i = num / inRow; int j = num % inRow; int x = marginLeft + j * (gap + size); int y = marginTop + i * (gap + size); if (!fromLeft) { x += size - width; } Rect rect = new Rect(x, y, x + width, y + size); paint.setColor(color); canvas.drawRect(rect, paint); } private void drawGreen(Canvas canvas) { for (int i = 0; i < green; i++) { drawRect(i, Color.GREEN, canvas, true, size); } } private void drawRed(Canvas canvas) { for (int i = 0; i < red; i++) { drawRect(num - i - 1, Color.RED, canvas, true, size); } } } }