entropy/entropyCalculator.go
func SpatialEntropy(match match.Match, turns int, shiftCount int) float64 {
	var s, d float64
	if match.DictionaryName == "qwerty" || match.DictionaryName == "dvorak" {
		//todo: verify qwerty and dvorak have the same length and degree
		s = float64(len(adjacency.BuildQwerty().Graph))
		d = adjacency.BuildQwerty().CalculateAvgDegree()
	} else {
		s = float64(keyPadStartingPositions)
		d = keyPadAvgDegree
	}

	possibilities := float64(0)

	length := float64(len(match.Token))

	//TODO: Should this be <= or just < ?
	//Estimate the number of possible patterns w/ length L or less with t turns or less
	for i := float64(2); i <= length+1; i++ {
		possibleTurns := math.Min(float64(turns), i-1)
		for j := float64(1); j <= possibleTurns+1; j++ {
			x := zxcvbnmath.NChoseK(i-1, j-1) * s * math.Pow(d, j)
			possibilities += x
		}
	}

	entropy := math.Log2(possibilities)
	//add extra entropu for shifted keys. ( % instead of 5 A instead of a)
	//Math is similar to extra entropy for uppercase letters in dictionary matches.

	if S := float64(shiftCount); S > float64(0) {
		possibilities = float64(0)
		U := length - S

		for i := float64(0); i < math.Min(S, U)+1; i++ {
			possibilities += zxcvbnmath.NChoseK(S+U, i)
		}

		entropy += math.Log2(possibilities)
	}

	return entropy
}
func SpatialEntropy(match match.Match, turns int, shiftCount int) float64 {
	var s, d float64
	if match.DictionaryName == "qwerty" || match.DictionaryName == "dvorak" {
		//todo: verify qwerty and dvorak have the same length and degree
		s = float64(len(adjacency.BuildQwerty().Graph))
		d = adjacency.BuildQwerty().CalculateAvgDegree()
	} else {
		s = float64(keyPadStartingPositions)
		d = keyPadAvgDegree
	}

	possibilities := float64(0)

	length := float64(len(match.Token))

	//TODO: Should this be <= or just < ?
	//Estimate the number of possible patterns w/ length L or less with t turns or less
	for i := float64(2); i <= length+1; i++ {
		possibleTurns := math.Min(float64(turns), i-1)
		for j := float64(1); j <= possibleTurns+1; j++ {
			x := zxcvbnmath.NChoseK(i-1, j-1) * s * math.Pow(d, j)
			possibilities += x
		}
	}

	entropy := math.Log2(possibilities)
	//add extra entropu for shifted keys. ( % instead of 5 A instead of a)
	//Math is similar to extra entropy for uppercase letters in dictionary matches.

	if S := float64(shiftCount); S > float64(0) {
		possibilities = float64(0)
		U := length - S

		for i := float64(0); i < math.Min(S, U)+1; i++ {
			possibilities += zxcvbnmath.NChoseK(S+U, i)
		}

		entropy += math.Log2(possibilities)
	}

	return entropy
}
func SpatialEntropy ( match match . Match , turns int , shiftCount int ) float64 { var s , d float64 if match . DictionaryName == " " || match . DictionaryName == " " { //todo: verify qwerty and dvorak have the same length and degree s = float64 ( len ( adjacency . BuildQwerty ( ) . Graph ) ) d = adjacency . BuildQwerty ( ) . CalculateAvgDegree ( ) } else { s = float64 ( keyPadStartingPositions ) d = keyPadAvgDegree } possibilities := float64 ( 0 ) length := float64 ( len ( match . Token ) ) //TODO: Should this be <= or just < ? //Estimate the number of possible patterns w/ length L or less with t turns or less for i := float64 ( 2 ) ; i <= length + 1 ; i ++ { possibleTurns := math . Min ( float64 ( turns ) , i - 1 ) for j := float64 ( 1 ) ; j <= possibleTurns + 1 ; j ++ { x := zxcvbnmath . NChoseK ( i - 1 , j - 1 ) * s * math . Pow ( d , j ) possibilities += x } } entropy := math . Log2 ( possibilities ) //add extra entropu for shifted keys. ( % instead of 5 A instead of a) //Math is similar to extra entropy for uppercase letters in dictionary matches. if S := float64 ( shiftCount ) ; S > float64 ( 0 ) { possibilities = float64 ( 0 ) U := length - S for i := float64 ( 0 ) ; i < math . Min ( S , U ) + 1 ; i ++ { possibilities += zxcvbnmath . NChoseK ( S + U , i ) } entropy += math . Log2 ( possibilities ) } return entropy }
// SpatialEntropy calculates the entropy for spatial matches
SpatialEntropy calculates the entropy for spatial matches