PageRenderTime 125ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/src/clarknova/software/sumdokusolver/AndroidSumdokuSolver.java

https://bitbucket.org/ClarkNovaSoftware/android-sumdoku-solver
Java | 1343 lines | 1028 code | 183 blank | 132 comment | 128 complexity | 8a4c1aa08e5499e55f6218793bc96c1c MD5 | raw file
package clarknova.software.sumdokusolver;

import java.util.Vector;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.Display;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.Window;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import android.widget.Toast;

public class AndroidSumdokuSolver extends Activity {
	public final static String MODE = "clarknova.software.sumdokusolver.mode";
	
	private boolean isReleaseVersion = true;
//	private boolean isReleaseVersion = false;
	
	public final static int SAVE = 1;
	public final static int LOAD = 2;
	public static Activity activity;
	
	public  final static String TAG = "sumdoku";
	public static final String NAME = "name";
	private static final String FIELDSTATE = "field state";
	
	public static final int NOTCOMPLETE = 0;
	public static final int SOLVED = 1;
	public static final int EMPTYCELL = -1;
	public static final int WRONGTOTALSUM = -2;

	private static final int OK = 1;
	
	public Calculate calculate = new Calculate();
	public Solve solve = new Solve(this);
	public Toast toast;
	public  Button get_sum_button, remove_button, solve_button;
	
	private int sumdoku_size=Calculate.SUMDOKU_SIZE;
    private int fieldwidth;
	public TableLayout field;
	public RelativeLayout rLayout;
	private int current_sum;
	private Sum sum_back = new Sum(0, this);
	public Data data = new Data(this);

	public  Vector<Integer> selected_cells = new Vector<Integer>();
	public  Vector<CellView> cells = new Vector<CellView>();
	private  View sumbuttonsLayout;
	private DBAdapter db = new DBAdapter(this);
	
	private SolveTask solution;
	private GetField getfield;
	private SaveField savefield;
	
	public Dialog waitdialog;
	private Data data_back = new Data(this);

	private boolean doubleBackToExitPressedOnce;


	/** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        activity = this;
        toast  = Toast.makeText(getApplicationContext(), "",Toast.LENGTH_SHORT);
        toast.setText("");
        toast.show();
        toast.cancel();
        
        setContentView(R.layout.main);
        
        presetScreen();
        loadsavedstate();
    }

	

	private void loadsavedstate() {
    	loadfield(FIELDSTATE);
	}

//    @Override
//    public void onPause(){
//    	super.onPause();
//    	InputMethodManager imm = (InputMethodManager) getSystemService (Context.INPUT_METHOD_SERVICE);
//    	imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
//    }
//    

    
	@Override
    public void onActivityResult(int requestCode,int resultCode,Intent data)
    {
		super.onActivityResult(requestCode, resultCode, data);
		if (data == null){
			Log.v(TAG, "No result data");
			return;
		}
		String save_name = data.getStringExtra(NAME);
     
		Log.d("myLogs", "requestCode = " + requestCode + ", resultCode = " + resultCode);
		
		
		
		if (resultCode == RESULT_OK) {
			switch (requestCode) {
			case SAVE:
				Log.v(TAG, "onActivityResult save "+save_name);
				savefield(save_name);
				break;
			case LOAD:
				Log.v(TAG, "onActivityResult load "+save_name);
				
				loadfield(save_name);
				break;
			default:
				Log.v(TAG, "Use requestCodes!");
			}
		} else {
			Log.v(TAG, "Wrong result");
		}
    }
	
//	@Override
//	public boolean onKeyDown(int keycode, KeyEvent e) {
//	    switch(keycode) {
//	        case KeyEvent.KEYCODE_BACK:
//	            if (!selected_cells.isEmpty()){
//	            	cancel_selection();
//	            }
//	            else this.finish();
//	            return true;
//	    }
//
//	    return super.onKeyDown(keycode, e);
//	}
	
	@Override
    public void onBackPressed() {
		if (!selected_cells.isEmpty()){
        	cancel_selection();
        	return;
        }
        if (doubleBackToExitPressedOnce) {
            super.onBackPressed();
            return;
        }
        this.doubleBackToExitPressedOnce = true;
        Toast.makeText(this, "Please click BACK again to exit", Toast.LENGTH_SHORT).show();
        new Handler().postDelayed(new Runnable() {

            @Override
            public void run() {
             doubleBackToExitPressedOnce=false;   

            }
        }, 2000);
    } 

//----=== START FUNCTIONS ===----    
//    @SuppressWarnings("deprecation")
	private void presetScreen() {
    	Display display = getWindowManager().getDefaultDisplay();
    	rLayout = (RelativeLayout) findViewById(R.id.mainLayout);
    	/*if (android.os.Build.VERSION.SDK_INT >= 13){
    		Point size = new Point();
    		display.getSize(size);
    		fieldwidth = Math.min(size.x,size.y);
    	}*/
    	//else {
    		fieldwidth = Math.min(display.getHeight(), display.getWidth());
    	//}
    	
    	createtable();
    	
    	sumbuttonsLayout=findViewById(R.id.sum_buttons);
    	
    	get_sum_button = (Button) findViewById(R.id.button_get_sum);
    	remove_button = (Button) findViewById(R.id.button_remove);
    	solve_button = (Button) findViewById(R.id.button_solve);
    	
    	get_sum_button.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
            	Log.v(TAG, "USER ACTION: OkClick");
            	okClick(v);}
    	});
    	
    	remove_button.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
            	Log.v(TAG, "USER ACTION: ClearClick");
            	removeClick(v);}
    	});
		solve_button.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
            	Log.v(TAG, "USER ACTION: SolveClick");
            	solveClick(v);
            }
    	});
    }
    private void createtable() {
		int cellsize = (fieldwidth-sumdoku_size-1)/(sumdoku_size);
		int fieldsize = sumdoku_size*cellsize+sumdoku_size+1;
		Log.v(TAG, "fieldwidth: "+fieldwidth+", fieldsize:"+fieldsize+", cellsize:"+cellsize);
    	
    	field = new TableLayout(this);
    	
        rLayout.addView(field);
    	RelativeLayout.LayoutParams tParams = (RelativeLayout.LayoutParams)field.getLayoutParams();
    	tParams.width=fieldsize;
    	tParams.height=fieldwidth;
    	field.setLayoutParams(tParams);
    	
		cells.clear();
		
		View b = new View(this);
        field.addView(b,new TableLayout.LayoutParams
        	(fieldsize,(fieldwidth-fieldsize)/2));
       	b.setBackgroundColor(Color.WHITE);
       	b = new View(this);
        field.addView(b,new TableLayout.LayoutParams
        	(fieldsize,1));
       	b.setBackgroundColor(Color.BLACK);

		for (int i=0;i<sumdoku_size;i++){
			TableRow row = new TableRow(this);
			
			b = new View(this);
        	row.addView(b,new TableRow.LayoutParams
        			(1,cellsize));
        	b.setBackgroundColor(Color.BLACK);

        	for(int k=0; k<sumdoku_size; k++){
				final CellView cell = new CellView(this);
				cell.setTag(""+i+""+k);
				cells.add(cell);
	           	
				row.addView(cell);
				TableRow.LayoutParams params = 
		    		(TableRow.LayoutParams)cell.getLayoutParams();
		            params.width = cellsize;
		            params.height = cellsize;
		            cell.setLayoutParams(params);
		        
		        b = new View(this);
		        row.addView(b,new TableRow.LayoutParams
		        	(1,cellsize));
		        if ((k+1)%3==0){	        	
			       	b.setBackgroundColor(Color.BLACK);
		        }
		        else {b.setBackgroundColor(Color.LTGRAY);}
		    }
			field.addView(row, 
				new TableLayout.LayoutParams
	            (LayoutParams.WRAP_CONTENT
	            		,LayoutParams.WRAP_CONTENT));
			
	        b = new View(this);
	        field.addView(b,new TableLayout.LayoutParams
	        	(fieldsize, 1));

	        if ((i+1)%3==0){	        	
	        	b.setBackgroundColor(Color.BLACK);
	        }
//	        if (i==sumdoku_size/3-1 ||i==2*sumdoku_size/3-1){	        	
//	        	b.setBackgroundColor(Color.BLACK);
//	        }
	        else {b.setBackgroundColor(Color.LTGRAY);}
		}
		b = new View(this);
        field.addView(b,new TableLayout.LayoutParams
        	(fieldsize,(fieldwidth-fieldsize)/2));
       	b.setBackgroundColor(Color.WHITE);
		
		RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) field.getLayoutParams();
		params.addRule(RelativeLayout.CENTER_HORIZONTAL);
		field.setLayoutParams(params);
		field.invalidate();
		//Log.v(TAG, "Table is set");
	}
    
    
//----=== USER ACTIONS ===----

   
    public void removeClick(View v) {
    	//TODO: do different things!
    	AlertDialog.Builder builder = new AlertDialog.Builder(this);
	    builder.setTitle(R.string.title_remove_sum)
	           .setItems(R.array.array_remove_sum, new DialogInterface.OnClickListener() {
	               public void onClick(DialogInterface dialog, int which) {
	            	   switch (which) {
	            	   case 0:
	            		   //Remove Sum
	            		   if (!selected_cells.isEmpty()){
	            			   Sum sum = data.getsum(selected_cells.firstElement());
	            			   data.getsums().removeElement(sum);
	            			   disborder(selected_cells);
	            			   //clearselection();
	            		   }
	            		   dialog.cancel();
	            		   break;
	            	   case 1:
	            		   //Remove Values
	            		   for (int cell_num : selected_cells) {
	            			   data.setValue(0, cell_num);
	            			   cells.elementAt(calculate.num_to_location(cell_num)).clearvalue();
	            		   }
//	            		   clearselection();
	            		   dialog.cancel();
	            		   break;
	            	   case 2:
	            		   //Remove all
	            		   if (!selected_cells.isEmpty()){
	            			   for (int cell_num : selected_cells) {
		            			   data.setValue(0, cell_num);
		            			   cells.elementAt(calculate.num_to_location(cell_num)).clearvalue();
		            		   }
	            			   Sum sum = data.getsum(selected_cells.firstElement());
	            			   data.getsums().removeElement(sum);
	            			   clearselection();
	            		   }
	            		   dialog.cancel();
	            		   break;

	            	   default:
	            		   dialog.cancel();
	            		   break;
	            	   }
	               }
	           });
	    AlertDialog clearField = builder.create();
	    clearField.show();
	}
    
    void cancel_selection(){
    	Log.v(TAG, "cancel_selection()");
//    	Log.v(TAG, "last_sum: "+last_sum.sum+" ("+last_sum.cell_nums+"), selected_cells: "+selected_cells);
//    	if (!data.sums.contains(last_sum)){
//    		clearselection();
//    		if (noneinsums(last_sum.cell_nums)){
//    			setsum(last_sum);
//    		}
//    	}
    	Log.v(TAG, "sum_back: "+sum_back.sum+" ("+sum_back.cell_nums+"), selected_cells: "+selected_cells);
    	if (!data.sums.contains(sum_back)){
    		clearselection();
    		if (noneinsums(sum_back.cell_nums)){
    			setsum(sum_back);
    		}
    	}
    	get_sum_button.setEnabled(false);
    	remove_button.setEnabled(false);
    
    }
    
    private boolean noneinsums(Vector<Integer> cell_nums){
    	for (int cellnum : cell_nums) {
			if (data.getsum(cellnum)!=null){
				return false;
			}
		}
    	return true;
    }
        
    private void clearselection() {
		for (int cellnum:selected_cells){
			int n=calculate.num_to_location(cellnum);
			CellView cell = cells.elementAt(n);
			cell.clear();
		}
		selected_cells.clear();
    	get_sum_button.setEnabled(false);
    	remove_button.setEnabled(false);

	}
    
    
    
	
    public void okClick(View v) {
		if (cells_connected(selected_cells)){
			Vector<Integer> alone_cells = alone_cells_near(selected_cells); 
			if (alone_cells==null || alone_cells.size()==0){
				getsum();
			}
			else {
				//TODO: change toast by highlighting alone cells
				toast.setText("Alone cells: "+alone_cells);
				toast.show();
			}
		}
		else {
			//TODO: do not allow user to set a sum by interface
			toast.setText("Cells in selection should be connected");
			toast.show();
		}
		
	}

    /**
     * Shows user a dialog where they can select a value of sum in selected cells
     */
    private void getsum() {
		current_sum = 0;
		final int min_sum=calculate.minsum(selected_cells.size());
		int max_sum=calculate.maxsum(selected_cells.size());
		
		final Dialog dialog = new Dialog(this,R.style.myBackgroundStyle);

		dialog.setContentView(R.layout.dialog_pick_a_sum);
		dialog.setTitle(R.string.text_sum);
		
		
//		WindowManager.LayoutParams lp = dialog.getWindow().getAttributes();  
//		lp.dimAmount=0.1f;
//		lp.alpha=0.7f;
//		
//		dialog.getWindow().setAttributes(lp);  
//		dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
		
		final TextView sum_text = (TextView) dialog.findViewById(R.id.editText_sum);
		
		TextView min_sumTextView = (TextView) dialog.findViewById(R.id.min_sum);
		TextView max_sumTextView = (TextView) dialog.findViewById(R.id.max_sum);
		
		min_sumTextView.setText(""+min_sum);
		max_sumTextView.setText(""+max_sum);
		
		Button done = (Button) dialog.findViewById(R.id.button_sum_done);
		done.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
            	if (sum_text.getText().length()>0){
            		current_sum = Integer.parseInt(sum_text.getText().toString());
            		setsum(current_sum);
            		Log.v(TAG, "sum="+current_sum);
            		dialog.dismiss();
            	}
        		else {
        			//TODO: check if it happens
        			Log.e(TAG, "WTF? No sum?");
        			toast.setText("Enter Sum!");
        			toast.show();
        		}
           	}
    	});
		//done.getBackground().setAlpha(100);
		
		SeekBar seek_sum = (SeekBar) dialog.findViewById(R.id.seekBar_sum);

		seek_sum.setMax(max_sum-min_sum);
		sum_text.setText(""+min_sum);
//		int lastsum =getLast_sum().sum; 
//		if (lastsum!=0 && lastsum>=min_sum && lastsum<=max_sum){
//			sum_text.setText(""+lastsum);
//			seek_sum.setProgress(lastsum-min_sum);
//		}
		
		seek_sum.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {

			//@Override
			public void onProgressChanged(SeekBar seekBar, int progress,
					boolean fromUser) {
				sum_text.setText(String.valueOf(progress+min_sum));
			}

			//@Override
			public void onStartTrackingTouch(SeekBar seekBar) {	}

			//@Override
			public void onStopTrackingTouch(SeekBar seekBar) { }
		});
		//dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
		dialog.show();
	}
	
	private void setsum(int sum){

		Sum s = new Sum(sum, this);
		for (int cell_num : selected_cells) {
			s.cell_nums.add(cell_num);
		}
		data.addtosums(s);
		if (sum_back.sum!=0){
			disborder(sum_back.cell_nums);
		}
		border(sum);
			
//		setLast_sum(s);
		if (!selected_cells.isEmpty()){
			Log.v(TAG, "Sum: "+data.getsum(selected_cells.firstElement()).sum+", " +
					"cells:"+data.getsum(selected_cells.firstElement()).cell_nums+"\n");}
		selected_cells.clear();
		get_sum_button.setEnabled(false);
		remove_button.setEnabled(false);
//		Log.v(TAG,"new cells:"+new_cells);
		if (total_sums_size()==sumdoku_size*sumdoku_size){
			all_sums_filled();
		}
	}
	
	private int total_sums_size(){
		int size=0;
		for (Sum s : data.getsums()) {
			size+=s.cell_nums.size();
		}
		Log.v(TAG, "total sums size = "+size);
		return size;
	}
	
	private void setsum(Sum sum){
		while (!selected_cells.isEmpty()){
			int cellnum = selected_cells.remove(0);
			CellView cell = cells.elementAt(calculate.num_to_location(cellnum));
			View b = cell.findViewById(R.id.back);
			b.setBackgroundColor(Color.WHITE);
			b.invalidate();
		}
		selected_cells.addAll(sum.cell_nums);
		setsum(sum.sum);
	}

	public void editSum(int num) {
		Sum sum = data.getsum(num); 
		if (sum.sum==0){return;}
		//setLast_sum(sum);
		set_sum_back(sum);
		hidesolvebutton();
//		Log.v(TAG,"Cell: num="+cell.num+", sum="+cell.sum+", sum_area="+cell.sum_area);
		for (int cell_num : sum.cell_nums) {
			int location = calculate.num_to_location(cell_num);
			CellView cellView = cells.elementAt(location);
			cellView.findViewById(R.id.back).setBackgroundColor(Color.GRAY);
			selected_cells.add(cell_num);
		}
		data.getsums().removeElement(sum);
		tempborder(selected_cells);
    	get_sum_button.setEnabled(selected_cells.size()>1);
    	remove_button.setEnabled(selected_cells.size()>0);

	}
	
	private void disborder(Vector<Integer> cell_nums) {
		sum_back = new Sum(0, this);
		for (int cellnum : cell_nums) {
			int n=calculate.num_to_location(cellnum);
			CellView cell = cells.elementAt(n);
			TextView sum_textview = (TextView) cell.findViewById(R.id.sum);
			sum_textview.setText("");
			cell.hideborders();
		}
	}
	
	private void tempborder(Vector<Integer> cell_nums){
		for (int cellnum:selected_cells){
			int n=calculate.num_to_location(cellnum);
			CellView cell = cells.elementAt(n);
			View t = cell.findViewById(R.id.tempback);
			t.setVisibility(View.VISIBLE);
		}
	}
	
	private void border(int sum) {
//		Log.v(TAG, "border()");
		int min = calculate.min(selected_cells);
//		Log.v(TAG, "Sum: "+sum+", selected_cells="+AndroidSumdokuSolver.selected_cells);
		for (int cellnum:selected_cells){
			int i=cellnum/10;
			int k=cellnum%10;
			int n=calculate.num_to_location(cellnum);
//			Log.v(TAG, "   cellnum: "+cellnum+", n="+n);
			CellView cell = cells.elementAt(n);
//			Log.v(TAG, "   cell.getTag().toString(): "+cell.getTag().toString());
			View b = cell.findViewById(R.id.back);
			b.setBackgroundColor(Color.WHITE);
			b.invalidate();
			
			if(cellnum==min){
				TextView t = (TextView) cell.findViewById(R.id.sum);
				t.setText(""+sum);
			}
			if (!selected_cells.contains(10*(i-1)+k)){
				cell.findViewById(R.id.border_top).setVisibility(View.VISIBLE);
				if (selected_cells.contains(10*i+k-1)){
					cell.findViewById(R.id.border_top_rl).setVisibility(View.VISIBLE);
				}
				if (selected_cells.contains(10*i+k+1)){
					cell.findViewById(R.id.border_top_lr).setVisibility(View.VISIBLE);
				}
			}
			else{
				if (!selected_cells.contains(10*(i-1)+k-1)){
					cell.findViewById(R.id.border_left_bt).setVisibility(View.VISIBLE);
				}
				if (!selected_cells.contains(10*(i-1)+k+1)){
					cell.findViewById(R.id.border_right_bt).setVisibility(View.VISIBLE);
				}
			}
			
			if (!selected_cells.contains(10*i+k-1)){
				cell.findViewById(R.id.border_left).setVisibility(View.VISIBLE);
				if (selected_cells.contains(10*(i+1)+k)){
					cell.findViewById(R.id.border_left_tb).setVisibility(View.VISIBLE);
				}
				if (selected_cells.contains(10*(i-1)+k)){
					cell.findViewById(R.id.border_left_bt).setVisibility(View.VISIBLE);
				}
			}
			else{
				if (!selected_cells.contains(10*(i-1)+k-1)){
					cell.findViewById(R.id.border_top_rl).setVisibility(View.VISIBLE);
				}
				if (!selected_cells.contains(10*(i+1)+k-1)){
					cell.findViewById(R.id.border_bottom_rl).setVisibility(View.VISIBLE);
				}
			}
			
			if (!selected_cells.contains(10*(i+1)+k)){
				cell.findViewById(R.id.border_bottom).setVisibility(View.VISIBLE);
				if (selected_cells.contains(10*i+k-1)){
					cell.findViewById(R.id.border_bottom_rl).setVisibility(View.VISIBLE);
				}
				if (selected_cells.contains(10*i+k+1)){
					cell.findViewById(R.id.border_bottom_lr).setVisibility(View.VISIBLE);
				}
			}
			else{
				if (!selected_cells.contains(10*(i+1)+k-1)){
					cell.findViewById(R.id.border_left_tb).setVisibility(View.VISIBLE);
				}
				if (!selected_cells.contains(10*(i+1)+k+1)){
					cell.findViewById(R.id.border_right_tb).setVisibility(View.VISIBLE);
				}
			}
			
			if (!selected_cells.contains(10*i+k+1)){
				cell.findViewById(R.id.border_right).setVisibility(View.VISIBLE);
				if (selected_cells.contains(10*(i+1)+k)){
					cell.findViewById(R.id.border_right_tb).setVisibility(View.VISIBLE);
				}
				if (selected_cells.contains(10*(i-1)+k)){
					cell.findViewById(R.id.border_right_bt).setVisibility(View.VISIBLE);
				}
			}
			else{
				if (!selected_cells.contains(10*(i-1)+k+1)){
					cell.findViewById(R.id.border_top_lr).setVisibility(View.VISIBLE);
				}
				if (!selected_cells.contains(10*(i+1)+k+1)){
					cell.findViewById(R.id.border_bottom_lr).setVisibility(View.VISIBLE);
				}
			}
			

			cell.invalidate();
		}
		field.invalidate();
	}
	
// MENU	
	@Override

    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu, menu);
        return true;
    }
	
	@Override
	public boolean onPrepareOptionsMenu(Menu menu) {
		if (isReleaseVersion){
			menu.findItem(R.id.printfield).setVisible(false);
		}
		else menu.findItem(R.id.helpscreen).setVisible(false);
		return true;
	}
	
	
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
		case R.id.menuclear:
			Log.v(TAG, "USER ACTION: Menu - ClearField");
			menuclear();
			return true;
			
		case R.id.printfield:
			Log.v(TAG, "USER ACTION: Menu - PrintField");
			data.printfield();
			return true;
			
		case R.id.helpscreen:
			Log.v(TAG, "USER ACTION: Menu - PrintField");
			helpscreen();
			return true;
			
		case R.id.getexample:
			Log.v(TAG, "USER ACTION: Menu - getExample");
			//clearfield();
			clearAll();
			example();
			return true;	
			
		case R.id.savefield:
			Log.v(TAG, "USER ACTION: Menu - saveField");
			savefield();
			return true;
		
		case R.id.loadfield:
			Log.v(TAG, "USER ACTION: Menu - loadField");
			loadfield();
			return true;
		
        default:
//            return super.onOptionsItemSelected(item);
        	return false;
        }
    }
	
	private void helpscreen() {
		Intent helpscreen = new Intent(this, HelpScreen.class);
		startActivity(helpscreen);
	}

	private void menuclear() {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
	    builder.setTitle(R.string.title_clear_field)
	           .setItems(R.array.array_clear_field, new DialogInterface.OnClickListener() {
	               public void onClick(DialogInterface dialog, int which) {
	            	   switch (which) {
	            	   case 0:
	            		   clearSums();
	            		   dialog.cancel();
	            		   break;
	            	   case 1:
	            		   clearValues();
	            		   dialog.cancel();
	            		   break;
	            	   case 2:
	            		   clearAll();
	            		   dialog.cancel();
	            		   break;

	            	   default:
	            		   dialog.cancel();
	            		   break;
	            	   }
	               }
	           });
	    AlertDialog clearField = builder.create();
	    clearField.show();
	}
	
	private void clearAll(){
		for (int cell_num : selected_cells) {
			int location = calculate.num_to_location(cell_num);
			CellView cellView = cells.elementAt(location);
			cellView.clear();
		}
		selected_cells.clear();
		clearSums();
		clearValues();
		
		hidesolvebutton();
    	get_sum_button.setEnabled(false);
    	remove_button.setEnabled(false);

	}
	
	

	private void clearValues() {
		for (int cell_num : selected_cells) {
			int location = calculate.num_to_location(cell_num);
			CellView cellView = cells.elementAt(location);
			cellView.clear();
		}
		selected_cells.clear();
    	get_sum_button.setEnabled(false);
    	remove_button.setEnabled(false);

		for (int i=0;i<sumdoku_size;i++) {
			for (int k=0;k<sumdoku_size;k++) {
				int cell_num=10*i+k;
				data.setValue(0, cell_num);
				cells.elementAt(calculate.num_to_location(cell_num)).clearvalue();
			}
		}
	}

	private void clearSums() {
		for (int cell_num : selected_cells) {
			int location = calculate.num_to_location(cell_num);
			CellView cellView = cells.elementAt(location);
			cellView.clear();
		}
		selected_cells.clear();
    	get_sum_button.setEnabled(false);
    	remove_button.setEnabled(false);

		while (!data.sums.isEmpty()){
			removesums();
		}

		sum_back = new Sum(0,this);
		hidesolvebutton();
	}

	private void suggsolve() {
		Data data_back = new Data(this);
		data_back.copy_from(data);
		data=data.solving_by_suggestions();
		Log.v(TAG, "");
		Log.v(TAG, "BEFORE SOLVING BY SUGESTIONS (data_back):");
		data_back.printfield();
		Log.v(TAG, "AFTER SOLVING BY SUGESTIONS (data):");
		data.printfield();
//		showresult();
	}

	private void removesums() {
		//TODO: Check if realization of this is not stupid
    	if (!data.sums.isEmpty()){
//			Log.v(TAG,"sumnumber=="+sumnumber+", getsums.size=="+data.getsums().size());
    		Log.v(TAG,"sums was: "+data.getsums().size());
			Sum sum = data.getsums().lastElement();
			if (sum.cell_nums.isEmpty()){
				data.getsums().removeElement(sum);
				removesums();
				return;
			}
			for (int cell_num : sum.cell_nums){
				int location = calculate.num_to_location(cell_num);
				CellView cellView = cells.elementAt(location);
//				Cell cell = data.getcell(location);
				
				cellView.findViewById(R.id.back).setBackgroundColor(Color.WHITE);
				TextView oldsum = (TextView) cellView.findViewById(R.id.sum);
				oldsum.setText("");
				cellView.hideborders();
				
//				Log.v(TAG,"cleared cell #"+cell.num+", cell.sum="+cell.sum+", cell.sum_area="+cell.sum_area);
//				done_cells.removeElement(cell_num);
				//new_cells.add(cell_num);
			}
			data.getsums().removeElement(sum);
//			last_sum.sum=0;
//			last_sum.cell_nums.clear();
			sum_back = new Sum (0,this);
			Log.v(TAG,"sums remains: "+data.getsums().size());
//	    	toast.setText("removed sum area : "+sum.sum_area);
//	    	toast.show();
    	}
	
	}
    
//----=== SOLVING ===----
	private void all_sums_filled() {
		Log.v(TAG, "All sums filled");
		findViewById(R.id.sum_buttons).setVisibility(View.INVISIBLE);
		solve_button.setVisibility(View.VISIBLE);
		
	}
	
	public void solveClick(View v) {
		int checkfield = fieldIsOk();
		switch (checkfield) {
		case OK:
			solution = new SolveTask();
			solution.execute(data);
			break;
		case WRONGTOTALSUM:
			somethingwrong(R.string.message_wrong_total_sum);
			break;
		default:
			somethingwrong(R.string.message_wrong_field);
			break;
		}
		
	}
	
	private int fieldIsOk(){
		int total_sum=0;
		for (Sum sum:data.sums){
			
			total_sum+=sum.sum;
		}
		if (total_sum!=calculate.totalsum()) {
			Log.v(TAG, "total_sum="+total_sum+", calculate.totalsum()="+calculate.totalsum());
			return WRONGTOTALSUM;}
		
		return OK;
	}
	
    
//----=== SHOW RESULT ===----
	private void showresult() {
		//System.out.println(cells);
		int i=0;
		for (CellView cellview : cells) {
			//Log.v(TAG, "result: ");
			Cell cell = data.field[i];
			TextView value_textview = (TextView) cellview.findViewById(R.id.value);
			TextView vars_textview = (TextView) cellview.findViewById(R.id.vars);
			if (value_textview.getText()=="" || value_textview.getText()==null){
			if (cell.getValue()>0){
				vars_textview.setVisibility(View.INVISIBLE);
				value_textview.setTextAppearance(this, android.R.style.TextAppearance_Large);
				value_textview.setTextColor(Color.BLACK);
				value_textview.setText(""+cell.getValue());}
			else {
				vars_textview.setVisibility(View.VISIBLE);
				vars_textview.setTextAppearance(this, android.R.style.TextAppearance_Small_Inverse);
				vars_textview.setTextColor(Color.GREEN);
				String s="";
				for (int n = 0; n < sumdoku_size; n++) {
					if (((1 << n) & cell.var_value) == (1<<n)) {
						s += (n + 1);
					}
				}
				vars_textview.setText(""+s);
			}
			}
			i++;
		}
	}
    
//----=== OTHER ===----
    


	private  void hidesolvebutton() {
    	sumbuttonsLayout.setVisibility(View.VISIBLE);
    	solve_button.setVisibility(View.INVISIBLE);		
	}

	private boolean cells_connected(Vector<Integer> cells) {
		boolean connection = (cells.size()>1);
		if (connection){
			Vector<Integer> nearfirst = new Vector<Integer>();
			Vector<Integer> checked = new Vector<Integer>();
			nearfirst.addAll(near(cells.firstElement(),checked,cells));
			connection=(nearfirst.size()==cells.size());
		}
		return connection;
	}
	private Vector <Integer> alone_cells_near(Vector<Integer> selected_cells){
		Vector<Integer> alone_cells = new Vector<Integer>();
		Vector<Integer> near_cells = new Vector<Integer>();
		for (int cell_num : selected_cells) {
			near_cells.addAll(near_cells(cell_num));
		}
		for (int cell_num : near_cells) {
			Vector<Integer> n_cells = near_cells(cell_num);
			if (((n_cells==null || n_cells.size()==0))&& !alone_cells.contains(cell_num)){
				alone_cells.add(cell_num);
				Log.v(TAG, "alone cell detected:  "+cell_num);
			}
			else Log.v(TAG, cell_num+" is not alone: "+n_cells);
			
		}
		
		Log.v(TAG, "selected cells:"+selected_cells+
				", near cells:"+near_cells+
				", alone cells:"+alone_cells);
		return alone_cells;	 
	}
	
	private Vector<Integer> near_cells(int cell_num) {
		Vector<Integer> near_cells = new Vector<Integer>();
		if (cell_num/10>=1 && !selected_cells.contains(cell_num-10)
				&& !near_cells.contains(cell_num-10) && data.getsum(cell_num-10)==null)
			{near_cells.add(cell_num-10);}
		if (cell_num/10<sumdoku_size-1 && !selected_cells.contains(cell_num+10)
				&& !near_cells.contains(cell_num+10) && data.getsum(cell_num+10)==null)
			{near_cells.add(cell_num+10);}
		if (cell_num%10>=1 && !selected_cells.contains(cell_num-1)
				&& !near_cells.contains(cell_num-1) && data.getsum(cell_num-1)==null)
			{near_cells.add(cell_num-1);}
		if (cell_num%10<sumdoku_size-1 && !selected_cells.contains(cell_num+1)
				&& !near_cells.contains(cell_num+1) && data.getsum(cell_num+1)==null)
			{near_cells.add(cell_num+1);}
		return near_cells;
	}


	private Vector<Integer> near(Integer firstElement, Vector<Integer> checked, Vector<Integer> cells) {
		Vector<Integer> n = new Vector<Integer>();
		n.add(firstElement);
		int i=firstElement/10;
		int k=firstElement%10;
		checked.add(firstElement);
		if (i>=1){
			int num=(i-1)*10+k;
			if (!checked.contains(num)&&cells.contains(num)){
				n.addAll(near(num,checked,cells));
			}
		}
		if (i<sumdoku_size-1){
			int num=(i+1)*10+k;
			if (!checked.contains(num)&&cells.contains(num)){
				n.addAll(near(num,checked,cells));
			}
		}
		if (k>=1){
			int num=i*10+k-1;
			if (!checked.contains(num)&&cells.contains(num)){
				n.addAll(near(num,checked,cells));
			}
		}
		if (k<sumdoku_size-1){
			int num=i*10+k+1;
			if (!checked.contains(num)&&cells.contains(num)){
				n.addAll(near(num,checked,cells));
			}
		}
		return n;
	}
	
//	public  Sum getLast_sum() {
//		return last_sum;
//	}

//	public  void setLast_sum(Sum sum) {
//		last_sum = new Sum(sum.sum, this);
//		last_sum.cell_nums.addAll(sum.cell_nums);
//	}
	public  void set_sum_back(Sum sum) {
	sum_back = new Sum(sum.sum, this);
	sum_back.cell_nums.addAll(sum.cell_nums);
}
	
//	---=== EXAMPLE ===---
	private void example() {
		exSaveValue(6, 4);
		exSaveValue(20, 4);
		//exSaveValue(68, 7);
		exSaveValue(82, 9);
		selected_cells.clear();
		get_sum_button.setEnabled(false);
    	remove_button.setEnabled(false);
		
		
		exSaveSum(new int[] {0, 10,20,30}, 22);
		exSaveSum(new int[] {1, 2, 3, 11}, 26);
		exSaveSum(new int[] {4, 5, 6, 15}, 21);
		exSaveSum(new int[] {7, 8, 16, 17, 26}, 26);
		exSaveSum(new int[] {12, 13, 14}, 7);
		exSaveSum(new int[] {18, 27, 28}, 15);
		exSaveSum(new int[] {21, 31, 32}, 10);
		exSaveSum(new int[] {22, 23, 33}, 17);
		exSaveSum(new int[] {24, 25}, 9);
		exSaveSum(new int[] {34, 44, 54}, 9);
		exSaveSum(new int[] {35, 45}, 14);
		exSaveSum(new int[] {36, 37}, 13);
		exSaveSum(new int[] {38, 48}, 3);
		exSaveSum(new int[] {40, 50}, 9);
		exSaveSum(new int[] {41, 42}, 11);
		exSaveSum(new int[] {43, 53}, 14);
		exSaveSum(new int[] {46, 47}, 16);
		exSaveSum(new int[] {51, 52}, 14);
		exSaveSum(new int[] {55, 65, 66}, 11);
		exSaveSum(new int[] {56, 57, 67}, 19);
		exSaveSum(new int[] {58, 68, 78, 88}, 20);
		exSaveSum(new int[] {60, 61, 70}, 13);
		exSaveSum(new int[] {62, 71, 72, 80, 81}, 23);
		exSaveSum(new int[] {63, 64}, 8);
		exSaveSum(new int[] {73, 82, 83, 84}, 19);
		exSaveSum(new int[] {74, 75, 76}, 16);
		exSaveSum(new int[] {77, 85, 86, 87}, 20);
			
	}

	private void exSaveValue(int cell_num, int value){
		int location = calculate.num_to_location(cell_num);
		CellView cellView = cells.elementAt(location);
		cellView.setvalue(value);
	}
	
	private void exSaveSum(int[] cellnums, int sum){
		for (int cell_num : cellnums) {
			selected_cells.add(cell_num);
		}
		setsum(sum);
	}
	public void sumtofield(Sum sum){
		selected_cells.clear();
		selected_cells.addAll(sum.cell_nums);
		setsum(sum);
	}
	public void cellToField(Cell cell){
		int location = calculate.num_to_location(cell.num);
		CellView cellView = cells.elementAt(location);
		if (cell.getValue()!=0){cellView.setvalue(cell.getValue());}
		data.field[location]=cell;
	}

	
//---===SAVE/LOAD field===---
	private void savefield() {

		Intent saveload = new Intent(this, SaveAndLoad.class); 
		saveload.putExtra(MODE, SAVE);
		startActivityForResult(saveload,SAVE);
	}
	private void savefield(String save_name) {
		//Log.v(TAG, "SAving to "+save_name+"...");
		savefield = new SaveField();
		savefield.execute(save_name);	
	}
	
	private void savefieldstate(){
		db.clearSaving(FIELDSTATE);
		db.savedata(data, FIELDSTATE);
//		db.savefield(data.field,FIELDSTATE);
//		db.saveSums(data.sums,FIELDSTATE);
	}
	
	private void loadfield() {
		selected_cells.clear();
		get_sum_button.setEnabled(selected_cells.size()>1);
    	remove_button.setEnabled(selected_cells.size()>0);
		Intent saveload = new Intent(this, SaveAndLoad.class); 
		saveload.putExtra(MODE, LOAD);
		startActivityForResult(saveload, LOAD);
	}
	class StringContext{
		String string;
		Context context;
		public StringContext(String s, Context c) {
			string=s;
			context=c;
		}
	}
	private void loadfield(String save_name) {
		getfield = new GetField();
		StringContext name_context = new StringContext(save_name,activity);
		getfield.execute(name_context);
	}
	
	public class SolveTask extends AsyncTask<Data,Void,Integer> {
		Context context;
		

		@Override
	    protected void onPreExecute() {
	        super.onPreExecute();
	        context = data.getcontext();
	    	data_back.copy_from(data);
	        setWaitDialog("Solving");
	        waitdialog.show();
	    }

		@Override
		protected Integer doInBackground(Data... d) {
		    int result =NOTCOMPLETE;
	        try {
	        	Data data = d[0];
	            result = data.solving();
		        Log.v(TAG, "solving() is "+ result);
		        if (result==NOTCOMPLETE){
		        	suggsolve();
				}
	 
	        } catch (Exception e) {
	            Log.e(TAG, "Error: "+ e.getMessage());
	        }
	     	return result;
		}
	    @Override
	    protected void onPostExecute(Integer result) {
	        super.onPostExecute(result);
	        Log.v(TAG, "onPostExecute(result) : "+result);
	        if (result!=EMPTYCELL) {
	        	showresult();
	        	waitdialog.cancel();}
	        else{
	        	waitdialog.cancel();
	        	data.copy_from(data_back);
	        	somethingwrong(R.string.message_empty_cell);
	        }
	        
	    }

	}
    private void setWaitDialog(String message) {
    	waitdialog = new Dialog(this);
        waitdialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
        waitdialog.setContentView(R.layout.dialog_progress);
        TextView dialogmessage = (TextView) waitdialog.findViewById(R.id.message);
        dialogmessage.setText(message);
        waitdialog.setCancelable(false);
	}
    
    public class GetField extends AsyncTask<StringContext,Void,Data> {
		@Override
	    protected void onPreExecute() {
	        super.onPreExecute();
	        setWaitDialog("Loading");
	        waitdialog.show();
	    }


		@Override
		protected Data doInBackground(StringContext... sc) {
			Vector<Sum> sums = new Vector<Sum>();
			Cell[] field = null;
        	Data fromdb=null;
			try {
	        	String save_name = sc[0].string;
	        	Context context = sc[0].context;
	        	fromdb=new Data(context);
	    		Log.v(TAG, "Loading from \""+save_name+"\"...");
//	    		Log.i(TAG,"SUMS...");
	    		sums = db.loadSums(save_name);

//	    		Log.i(TAG,"CELLS...");
	    		
	    		field = db .loadfield(save_name);
	        } catch (Exception e) {
	        	Log.e(TAG, "Error: "+ e.getMessage());
	        }
    		if (sums!=null) fromdb.sums.addAll(sums);
    		fromdb.field = field;

			return fromdb;
		}
		@Override
	    protected void onPostExecute(Data fromdb) {
	        super.onPostExecute(fromdb);
	        clearAll();
	        if ((fromdb.sums!=null) && (!fromdb.sums.isEmpty())){
  			  for (Sum sum : fromdb.sums) {
  				  sumtofield(sum);
//  				Log.i(TAG,"     "+sum.sum+"("+sum.cell_nums+")");
  			  }
  		}
//  		else Log.v(TAG, "No sums in save");
	        if (fromdb.field!=null && fromdb.field.length!=0){
    			for (Cell cell : fromdb.field) {
    				cellToField(cell);
    			}
    		}
	        waitdialog.cancel();
//    		else {Log.v(TAG, "No cells in save");}
	    }
		

	}
	
    public class SaveField extends AsyncTask<String,Void,Integer> {
		@Override
	    protected void onPreExecute() {
	        super.onPreExecute();
	        setWaitDialog("Saving");
	        waitdialog.show();
	    }
		@Override
		protected Integer doInBackground(String... s) {
			String save_name="";
			try {
				save_name = s[0];
	    		Log.v(TAG, "Saving to \""+save_name+"\"...");

//				db.clearSaving(save_name);
//				db.savefield(data.field,save_name);
//				db.saveSums(data.sums,save_name);
	    		db.savedata(data, save_name);
	        	
	        } catch (Exception e) {
	        	Log.e(TAG, "Error: "+ e.getMessage());
	        }
			return 1;
		}
		@Override
	    protected void onPostExecute(Integer result) {
	        super.onPostExecute(result);
	        waitdialog.cancel();
	    }

		

	}
	
	public void somethingwrong(int couse) {
//		String message = "";
//		switch (couse) {
//		case EMPTYCELL:
//			message="This field can not be solved. Check all values you set";
//			break;
//
//		default:
//			message="Something wrong";
//			break;
//		}
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		
		builder.setMessage(couse)
		       .setTitle(R.string.title_somethingwrong);
		builder.setNeutralButton(android.R.string.ok, new DialogInterface.OnClickListener() {
	           public void onClick(DialogInterface dialog, int id) {
	               dialog.dismiss();
	           }});
		AlertDialog messagedialog = builder.create();
		messagedialog.show();
	}

	@Override
	protected void onStop() {
		super.onStop();
		Log.v(TAG, "onStop()");
		//cancel_selection();
		//solution.cancel(true);
	
	}
	@Override
	protected void onDestroy() {
		super.onDestroy();
		Log.v(TAG, "onDestroy()");
		//solution.cancel(true);
		cancel_selection();
		savefieldstate();
	}
}