/*  11:53 AM 11/27/2006

What we are doing here is checking to see if one of the parities of a strong chain
is impossible due to the formation of a "hinge". The idea is that if all of the 
occurances of a given digit in a given block, row, or column, or all of the digits of a given cell
are eliminated by a polarity, then that polarity is not possible.

the "strong" function just checks for weak nodes from a chain;
the "weak" function checks weak nodes and nodes of a given weak node.


*/

ROW=0
COL=1
BLOCK=2

function checkForHinge(isWeak) {
	var npos
	for(var i=0;i<9;i++)for(var k=0;k<9;k++){
		npos=xNum(Possible.XBlock[i][k])
		if(npos>0 && checkHinge(i, k, Blocks, "block", npos, false, isWeak))return true
		npos=xNum(Possible.XRow[i][k])
		if(npos>0 && checkHinge(i, k, Data, "row", npos, false, isWeak))return true
		npos=xNum(Possible.XCol[i][k])
		if(npos>0 && checkHinge(i, k, Data, "column", npos, true, isWeak))return true
		var npos=xNum(Possible.XCell[i][k])
		if(npos>0 && checkHinge(i, k, null, "cell", npos, false, isWeak, Data[i][k]))return true
	}
	return false
}

/*

 Strong: We simply count the number of weak links to a chain in a given house of each parity, 
  then if either of these numbers is the total number possible, we have a hinge

*/

function checkHinge(i, k, BorD, type, npos, isReversed, isWeak, D) {
	for(var c=1;c<StrongChains.length;c++)if(isWeak||StrongChains[c].length>2){
		var np0=0
		var np1=0
		Temp=new Array()
		for(var j=0;j<9;j++){
			if(BorD==null)
				k=j
			else
				D=(isReversed?BorD[j][i]:BorD[i][j])			
			var p=D.Parity[c]
			if(!p){
				if(isWeak && D.N==0)Temp.push([j,k,D])
				continue
			}
			if(p[k]==0)continue
			if(p[k][0]<0)
				np0++
			else if(p[k][0]>0)
				np1++
			if(np0>0 && np1>0)break
		}
		if(np0>0 && np1>0||np0==0 && np1==0)continue
		var iparity = (np0 > 0 ? 0 : 1)
		//exactly one of np0 and np1 is zero
		if(np0 + np1 < npos){
			if(!isWeak || Temp.length==0)continue
			var List = new Array()
			for(var j=0;j<Temp.length;j++)
				if(!isWeakHinge(Temp[j][2], c, iparity, List))break
			if(List.length!=Temp.length)continue
			var msg=type + " hinge: chain " + chainCode(c,p,1) + " would disallow all "
			+(BorD==null?"possibilities in "+D.showinfo:(k+1)+"s in "+type+" "+(i+1))
			eliminateK(nodeData(List[0],DATA),nodeData(List[0],K),msg)
			ishowchain=c
			if(!idonotstop)return true
			continue
		}
		var msg = type + " hinge: chain " + chainCode(c,iparity,1) + " disallows "
		var sep = ""
		for(var j=0;j<9;j++){
			if(BorD==null)
				k = j
			else
				 D=(isReversed?BorD[j][i]:BorD[i][j])
			var p = D.Parity[c]
			if(p && p[k]!=0) {
				msg+=sep + (k+1) + " in "+ D.showinfo + " " + getNodeType(D, k, c)
				sep = " and "
				pointlist+=coordOf(D,k)
			}
		}
		greenlist += msg
		eliminateChainParity(c,(np0==npos?1:-1),msg,"H")
		if (!idonotstop)return true
	}
	return false
}

function getNodeType(D, k, c) {
return D.Parity[c][k][2]
}


/*

  This is trickier. At this point we know that there are no strong hinges.
  But what we do not know is if there are any weakly linked chains that have the 
  problem or weak links to these weakly linked chains. In this case all we get to
  do is delete that weak link. And directionality is important. The chains have to 
  be linked correctly. 

*/

function isWeakHinge(D, c, parity, List) {
	var N=null
	if((WeakXRows[c][parity]&Pwr2[D.row])!=0)N=findWeakNode(ROW,c,parity,D.row)
	if(N==null && (WeakXCols[c][parity]&Pwr2[D.col])!=0)N=findWeakNode(COL,c,parity,D.col)
	if(N==null && (WeakXBlocks[c][parity]&Pwr2[D.block])!=0)N=findWeakNode(BLOCK,c,parity,D.block)
	if(N==null)return false
	List[List.length]=N
	return true
}

function findWeakNode(type,ichain,p,n){
	if(!AssociatedWeakNodes[p][ichain])return
	var A = AssociatedWeakNodes[p][ichain]
	for(var i=0;i<A.length;i++){
		var N=AssociatedWeakNodes[p][ichain][i]
		var D=nodeData(N,DATA)
		switch(type){
		case ROW:
			if(D.row == n)return N
			break;
		case COL:
			if(D.col == n)return N
			break;
		case BLOCK:
			if(D.block == n)return N
			break;
		}	
	}
	return null
}
