more refactoring
This commit is contained in:
195
internal/entities/user_interface.go
Normal file
195
internal/entities/user_interface.go
Normal file
@@ -0,0 +1,195 @@
|
||||
package entities
|
||||
|
||||
import (
|
||||
"go-nkode/config"
|
||||
"go-nkode/internal/models"
|
||||
"go-nkode/internal/security"
|
||||
"go-nkode/internal/utils"
|
||||
"log"
|
||||
)
|
||||
|
||||
type UserInterface struct {
|
||||
IdxInterface models.IdxInterface
|
||||
SvgId models.SvgIdInterface
|
||||
Kp *KeypadDimension
|
||||
}
|
||||
|
||||
func NewUserInterface(kp *KeypadDimension, svgId models.SvgIdInterface) (*UserInterface, error) {
|
||||
idxInterface := security.IdentityArray(kp.TotalAttrs())
|
||||
userInterface := UserInterface{
|
||||
IdxInterface: idxInterface,
|
||||
SvgId: svgId,
|
||||
Kp: kp,
|
||||
}
|
||||
if err := userInterface.RandomShuffle(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &userInterface, nil
|
||||
}
|
||||
|
||||
func (u *UserInterface) RandomShuffle() error {
|
||||
err := u.shuffleKeys()
|
||||
|
||||
keypadView, err := u.InterfaceMatrix()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
setView, err := security.MatrixTranspose(keypadView)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for idx, set := range setView {
|
||||
err := security.FisherYatesShuffle(&set)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
setView[idx] = set
|
||||
}
|
||||
|
||||
keypadView, err = security.MatrixTranspose(setView)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
u.IdxInterface = security.MatrixToList(keypadView)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *UserInterface) InterfaceMatrix() ([][]int, error) {
|
||||
return security.ListToMatrix(u.IdxInterface, u.Kp.AttrsPerKey)
|
||||
}
|
||||
|
||||
func (u *UserInterface) SetViewMatrix() ([][]int, error) {
|
||||
keypadView, err := u.InterfaceMatrix()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return security.MatrixTranspose(keypadView)
|
||||
}
|
||||
|
||||
func (u *UserInterface) DisperseInterface() error {
|
||||
if !u.Kp.IsDispersable() {
|
||||
return config.ErrInterfaceNotDispersible
|
||||
}
|
||||
|
||||
err := u.shuffleKeys()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = u.randomAttributeRotation()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *UserInterface) shuffleKeys() error {
|
||||
userInterfaceMatrix, err := security.ListToMatrix(u.IdxInterface, u.Kp.AttrsPerKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = security.FisherYatesShuffle[[]int](&userInterfaceMatrix)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
u.IdxInterface = security.MatrixToList(userInterfaceMatrix)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *UserInterface) randomAttributeRotation() error {
|
||||
userInterface, err := u.InterfaceMatrix()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
transposeUserInterface, err := security.MatrixTranspose(userInterface)
|
||||
|
||||
attrRotation, err := security.RandomPermutation(len(transposeUserInterface))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for idx, attrSet := range transposeUserInterface {
|
||||
rotation := attrRotation[idx]
|
||||
transposeUserInterface[idx] = append(attrSet[rotation:], attrSet[:rotation]...)
|
||||
}
|
||||
userInterface, err = security.MatrixTranspose(transposeUserInterface)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
u.IdxInterface = security.MatrixToList(userInterface)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *UserInterface) AttributeAdjacencyGraph() (map[int]utils.Set[int], error) {
|
||||
interfaceKeypad, err := u.InterfaceMatrix()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
graph := make(map[int]utils.Set[int])
|
||||
|
||||
for _, key := range interfaceKeypad {
|
||||
keySet := utils.NewSetFromSlice(key)
|
||||
for _, attr := range key {
|
||||
attrAdjacency := keySet.Copy()
|
||||
attrAdjacency.Remove(attr)
|
||||
graph[attr] = attrAdjacency
|
||||
}
|
||||
}
|
||||
return graph, nil
|
||||
}
|
||||
|
||||
func (u *UserInterface) PartialInterfaceShuffle() error {
|
||||
err := u.shuffleKeys()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
numbOfSelectedSets := u.Kp.AttrsPerKey / 2
|
||||
if u.Kp.AttrsPerKey&1 == 1 {
|
||||
numbOfSelectedSets += security.Choice[int]([]int{0, 1})
|
||||
}
|
||||
setIdxs, err := security.RandomPermutation(u.Kp.AttrsPerKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
selectedSets := utils.NewSetFromSlice[int](setIdxs[:numbOfSelectedSets])
|
||||
|
||||
keypadSetView, err := u.SetViewMatrix()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
interfaceBySet := make([][]int, u.Kp.AttrsPerKey)
|
||||
for idx, attrs := range keypadSetView {
|
||||
if selectedSets.Contains(idx) {
|
||||
err = security.FisherYatesShuffle[int](&attrs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
interfaceBySet[idx] = attrs
|
||||
}
|
||||
keypadView, err := security.MatrixTranspose(interfaceBySet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
u.IdxInterface = security.MatrixToList(keypadView)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *UserInterface) GetAttrIdxByKeyNumbSetIdx(setIdx int, keyNumb int) (int, error) {
|
||||
if keyNumb < 0 || u.Kp.NumbOfKeys <= keyNumb {
|
||||
log.Printf("keyNumb %d is out of range 0-%d", keyNumb, u.Kp.NumbOfKeys)
|
||||
return -1, config.ErrKeyIndexOutOfRange
|
||||
}
|
||||
|
||||
if setIdx < 0 || u.Kp.AttrsPerKey <= setIdx {
|
||||
log.Printf("setIdx %d is out of range 0-%d", setIdx, u.Kp.AttrsPerKey)
|
||||
return -1, config.ErrAttributeIndexOutOfRange
|
||||
}
|
||||
keypadView, err := u.InterfaceMatrix()
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
return keypadView[keyNumb][setIdx], nil
|
||||
}
|
||||
Reference in New Issue
Block a user