165 lines
4.7 KiB
Go
165 lines
4.7 KiB
Go
package nkode
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"github.com/google/uuid"
|
|
"go-nkode/core/model"
|
|
"go-nkode/hashset"
|
|
py_builtin "go-nkode/py-builtin"
|
|
"go-nkode/util"
|
|
)
|
|
|
|
type UserSignSession struct {
|
|
SessionId uuid.UUID
|
|
CustomerId uuid.UUID
|
|
LoginInterface UserInterface
|
|
KeypadSize model.KeypadSize
|
|
SetInterface []int
|
|
ConfirmInterface []int
|
|
SetKeyEntry []int
|
|
Username string
|
|
}
|
|
|
|
func NewSignupSession(keypadSize model.KeypadSize, customerId uuid.UUID) (*UserSignSession, error) {
|
|
loginInterface, err := NewUserInterface(keypadSize)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
signupInter, err := signupInterface(*loginInterface)
|
|
session := UserSignSession{
|
|
SessionId: uuid.New(),
|
|
CustomerId: customerId,
|
|
LoginInterface: *loginInterface,
|
|
SetInterface: signupInter.IdxInterface,
|
|
ConfirmInterface: nil,
|
|
SetKeyEntry: nil,
|
|
Username: "",
|
|
KeypadSize: signupInter.KeypadSize,
|
|
}
|
|
|
|
return &session, nil
|
|
}
|
|
|
|
func (s *UserSignSession) DeducePasscode(confirmKeyEntry []int) ([]int, error) {
|
|
validEntry := py_builtin.All[int](confirmKeyEntry, func(i int) bool {
|
|
return 0 <= i && i < s.LoginInterface.KeypadSize.NumbOfKeys
|
|
})
|
|
|
|
if !validEntry {
|
|
return nil, errors.New(fmt.Sprintf("Invalid Key entry. One or more key index: %#v, not in range 0-%d", confirmKeyEntry, s.LoginInterface.KeypadSize.NumbOfKeys))
|
|
}
|
|
|
|
if s.SetInterface == nil {
|
|
return nil, errors.New("signup session set interface is nil")
|
|
}
|
|
|
|
if s.ConfirmInterface == nil {
|
|
return nil, errors.New("signup session confirm interface is nil")
|
|
}
|
|
|
|
if s.SetKeyEntry == nil {
|
|
return nil, errors.New("signup session set key entry is nil")
|
|
}
|
|
|
|
if s.Username == "" {
|
|
return nil, errors.New("signup session username is nil")
|
|
}
|
|
|
|
if len(confirmKeyEntry) != len(s.SetKeyEntry) {
|
|
return nil, errors.New(fmt.Sprintf("confirm and set key entry lenght mismatch %d != %d", len(confirmKeyEntry), len(s.SetKeyEntry)))
|
|
}
|
|
|
|
passcodeLen := len(confirmKeyEntry)
|
|
setKeyVals, err := s.getSelectedKeyVals(s.SetKeyEntry, s.SetInterface)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
confirmKeyVals, err := s.getSelectedKeyVals(confirmKeyEntry, s.ConfirmInterface)
|
|
passcode := make([]int, passcodeLen)
|
|
|
|
for idx := 0; idx < passcodeLen; idx++ {
|
|
setKey := hashset.NewSetFromSlice[int](setKeyVals[idx])
|
|
confirmKey := hashset.NewSetFromSlice[int](confirmKeyVals[idx])
|
|
intersection := setKey.Intersect(confirmKey)
|
|
if intersection.Size() < 1 {
|
|
return nil, errors.New(fmt.Sprintf("set and confirm do not intersect at index %d", idx))
|
|
}
|
|
if intersection.Size() > 1 {
|
|
return nil, errors.New(fmt.Sprintf("set and confirm intersect at more than one point at index %d", idx))
|
|
}
|
|
intersectionSlice := intersection.ToSlice()
|
|
passcode[idx] = intersectionSlice[0]
|
|
}
|
|
return passcode, nil
|
|
}
|
|
|
|
func (s *UserSignSession) SetUserNKode(username string, keySelection []int) ([]int, error) {
|
|
validKeySelection := py_builtin.All[int](keySelection, func(i int) bool {
|
|
return 0 <= i && i < s.KeypadSize.NumbOfKeys
|
|
})
|
|
if !validKeySelection {
|
|
return nil, errors.New(fmt.Sprintf("one or key selection is out of range 0-%d", s.KeypadSize.NumbOfKeys-1))
|
|
}
|
|
|
|
s.SetKeyEntry = keySelection
|
|
s.Username = username
|
|
|
|
setInterface := UserInterface{IdxInterface: s.SetInterface, KeypadSize: s.KeypadSize}
|
|
err := setInterface.DisperseInterface()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
s.ConfirmInterface = setInterface.IdxInterface
|
|
return s.ConfirmInterface, nil
|
|
}
|
|
|
|
func (s *UserSignSession) getSelectedKeyVals(keySelections []int, userInterface []int) ([][]int, error) {
|
|
keypadInterface, err := util.ListToMatrix(userInterface, s.KeypadSize.AttrsPerKey)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
keyVals := make([][]int, len(keySelections))
|
|
|
|
for idx, keyIdx := range keySelections {
|
|
keyVals[idx] = keypadInterface[keyIdx]
|
|
}
|
|
return keyVals, nil
|
|
}
|
|
|
|
func signupInterface(baseUserInterface UserInterface) (*UserInterface, error) {
|
|
if baseUserInterface.KeypadSize.IsDispersable() {
|
|
return nil, errors.New("keypad is dispersable, can't use signupInterface")
|
|
}
|
|
err := baseUserInterface.RandomShuffle()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
interfaceMatrix, err := baseUserInterface.InterfaceMatrix()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
attrSetView, err := util.MatrixTranspose(interfaceMatrix)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
err = util.FisherYatesShuffle[[]int](&attrSetView)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
numbOfKeys := baseUserInterface.KeypadSize.NumbOfKeys
|
|
attrSetView = attrSetView[:numbOfKeys]
|
|
attrSetView, err = util.MatrixTranspose(attrSetView)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
signupUserInterface := UserInterface{
|
|
IdxInterface: util.MatrixToList(attrSetView),
|
|
KeypadSize: model.KeypadSize{
|
|
AttrsPerKey: numbOfKeys,
|
|
NumbOfKeys: numbOfKeys,
|
|
},
|
|
}
|
|
return &signupUserInterface, nil
|
|
}
|