func modulo3Func(x, y int) bool {
	return (x+y)%3 == 0
}
modulo3Func for maskPattern function
modulo3 (x+y) mod 3 == 0
package qrcode
import (
	"github.com/yeqown/go-qrcode/matrix"
)
type maskPatternModulo uint32
const (
	modulo0 maskPatternModulo = iota
	modulo1
	modulo2
	modulo3
	modulo4
	modulo5
	modulo6
	modulo7
)
var (
	statePattern1 = []matrix.State{matrix.StateTrue, matrix.StateFalse, matrix.StateTrue, matrix.StateTrue, matrix.StateTrue, matrix.StateFalse, matrix.StateTrue,
		matrix.StateFalse, matrix.StateFalse, matrix.StateFalse, matrix.StateFalse}
	statePattern2 = []matrix.State{matrix.StateFalse, matrix.StateFalse, matrix.StateFalse, matrix.StateFalse,
		matrix.StateTrue, matrix.StateFalse, matrix.StateTrue, matrix.StateTrue, matrix.StateTrue, matrix.StateFalse, matrix.StateTrue}
)
func calculateScore(mat *matrix.Matrix) int {
	debugLogf("calculate maskScore starting")
	score1 := rule1(mat.Copy())
	score2 := rule2(mat.Copy())
	score3 := rule3(mat.Copy())
	score4 := rule4(mat.Copy())
	debugLogf("maskScore: %d", score1+score2+score3+score4)
	return score1 + score2 + score3 + score4
}
func rule1(mat *matrix.Matrix) int {
	var (
		score          int
		rowCurState    matrix.State
		rowCurColorCnt int
		colCurState    matrix.State
		colCurColorCnt int
	)
	mat.Iterate(matrix.ROW, func(x, y int, value matrix.State) {
		if x == 0 {
			rowCurColorCnt = 0
			rowCurState = value
			return
		}
		if value == rowCurState {
			rowCurColorCnt++
		} else {
			rowCurState = value
		}
		if rowCurColorCnt == 5 {
			score += 3
		} else if rowCurColorCnt > 5 {
			score++
		}
	})
	mat.Iterate(matrix.COLUMN, func(x, y int, value matrix.State) {
		if x == 0 {
			colCurColorCnt = 0
			colCurState = value
			return
		}
		if value == colCurState {
			colCurColorCnt++
		} else {
			colCurState = value
		}
		if colCurColorCnt == 5 {
			score += 3
		} else if colCurColorCnt > 5 {
			score++
		}
	})
	return score
}
func rule2(mat *matrix.Matrix) int {
	var (
		score          int
		s0, s1, s2, s3 matrix.State
	)
	for x := 0; x < mat.Width()-1; x++ {
		for y := 0; y < mat.Height()-1; y++ {
			s0, _ = mat.Get(x, y)
			s1, _ = mat.Get(x+1, y)
			s2, _ = mat.Get(x, y+1)
			s3, _ = mat.Get(x+1, y+1)
			if s0 == s1 && s2 == s3 && s1 == s2 {
				score += 3
			}
		}
	}
	return score
}
func rule3(mat *matrix.Matrix) int {
	var (
		score      int
		stateSlice []matrix.State
	)
	for y := 0; y < mat.Height(); y++ {
		for x := 0; x < mat.Width()-11; x++ {
			for i := 0; i < 11; i++ {
				s, _ := mat.Get(x+i, y)
				stateSlice = append(stateSlice, s)
			}
			if matrix.StateSliceMatched(statePattern1, stateSlice) {
				score += 40
			}
			if matrix.StateSliceMatched(statePattern2, stateSlice) {
				score += 40
			}
		}
	}
	for x := 0; x < mat.Width(); x++ {
		for y := 0; y < mat.Height()-11; y++ {
			for i := 0; i < 11; i++ {
				s, _ := mat.Get(x, y+i)
				stateSlice = append(stateSlice, s)
			}
			if matrix.StateSliceMatched(statePattern1, stateSlice) {
				score += 40
			}
			if matrix.StateSliceMatched(statePattern2, stateSlice) {
				score += 40
			}
		}
	}
	return score
}
func rule4(mat *matrix.Matrix) int {
	var (
		totalCnt             = mat.Width() * mat.Height()
		darkCnt, darkPercent int
	)
	mat.Iterate(matrix.ROW, func(x, y int, s matrix.State) {
		if s == matrix.StateTrue {
			darkCnt++
		}
	})
	darkPercent = (darkCnt * 100) / totalCnt
	x := 0
	if darkPercent%5 == 0 {
		x = 1
	}
	last5Times := abs(((darkPercent/5)-x)*5 - 50)
	next5Times := abs(((darkPercent/5)+1)*5 - 50)
	if last5Times > next5Times {
		return next5Times * 2
	} else {
		return last5Times * 2
	}
}
func abs(x int) int {
	if x < 0 {
		return -x
	}
	return x
}
type mask struct {
	mat  *matrix.Matrix     
	mode maskPatternModulo  
}
func newMask(m *matrix.Matrix, mode maskPatternModulo) *mask {
	mask := &mask{
		mat:  m.Copy(),
		mode: mode,
	}
	mask.init()
	return mask
}
type moduloFunc func(int, int) bool
func (m *mask) init() {
	var f moduloFunc
	switch m.mode {
	case modulo0:
		f = modulo0Func
	case modulo1:
		f = modulo1Func
	case modulo2:
		f = modulo2Func
	case modulo3:
		f = modulo3Func
	case modulo4:
		f = modulo4Func
	case modulo5:
		f = modulo5Func
	case modulo6:
		f = modulo6Func
	case modulo7:
		f = modulo7Func
	}
	m.mat.Iterate(matrix.ROW, func(x, y int, s matrix.State) {
		if state, _ := m.mat.Get(x, y); state != matrix.StateInit {
			_ = m.mat.Set(x, y, matrix.StateInit)
			return
		}
		if f(x, y) {
			_ = m.mat.Set(x, y, matrix.StateTrue)
		} else {
			_ = m.mat.Set(x, y, matrix.StateFalse)
		}
	})
}
func modulo0Func(x, y int) bool {
	return (x+y)%2 == 0
}
func modulo1Func(x, y int) bool {
	return y%2 == 0
}
func modulo2Func(x, y int) bool {
	return x%3 == 0
}