Files
go-nkode/core/nkode/user_signup_session.go
2024-08-24 21:02:50 -05:00

176 lines
5.0 KiB
Go

package nkode
import (
"errors"
"fmt"
"github.com/google/uuid"
m "go-nkode/core/model"
"go-nkode/hashset"
py "go-nkode/py-builtin"
"go-nkode/util"
)
type UserSignSession struct {
SessionId m.SessionId
CustomerId m.CustomerId
LoginUserInterface UserInterface
Kp m.KeypadDimension
SetIdxInterface m.IdxInterface
ConfirmIdxInterface m.IdxInterface
SetKeySelection m.KeySelection
Username m.Username
}
func NewSignupSession(kp m.KeypadDimension, customerId m.CustomerId) (*UserSignSession, error) {
loginInterface, err := NewUserInterface(&kp)
if err != nil {
return nil, err
}
signupInterface, err := signupInterface(*loginInterface, kp)
if err != nil {
return nil, err
}
session := UserSignSession{
SessionId: m.SessionId(uuid.New()),
CustomerId: customerId,
LoginUserInterface: *loginInterface,
SetIdxInterface: signupInterface.IdxInterface,
ConfirmIdxInterface: nil,
SetKeySelection: nil,
Username: "",
Kp: kp,
}
return &session, nil
}
func (s *UserSignSession) DeducePasscode(confirmKeyEntry m.KeySelection) ([]int, error) {
validEntry := py.All[int](confirmKeyEntry, func(i int) bool {
return 0 <= i && i < s.Kp.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.Kp.NumbOfKeys))
}
if s.SetIdxInterface == nil {
return nil, errors.New("signup session set interface is nil")
}
if s.ConfirmIdxInterface == nil {
return nil, errors.New("signup session confirm interface is nil")
}
if s.SetKeySelection == 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.SetKeySelection) {
return nil, errors.New(fmt.Sprintf("confirm and set key entry lenght mismatch %d != %d", len(confirmKeyEntry), len(s.SetKeySelection)))
}
passcodeLen := len(confirmKeyEntry)
setKeyVals, err := s.getSelectedKeyVals(s.SetKeySelection, s.SetIdxInterface)
if err != nil {
return nil, err
}
confirmKeyVals, err := s.getSelectedKeyVals(confirmKeyEntry, s.ConfirmIdxInterface)
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 m.Username, keySelection m.KeySelection) (m.IdxInterface, error) {
validKeySelection := py.All[int](keySelection, func(i int) bool {
return 0 <= i && i < s.Kp.NumbOfKeys
})
if !validKeySelection {
return nil, errors.New(fmt.Sprintf("one or key selection is out of range 0-%d", s.Kp.NumbOfKeys-1))
}
s.SetKeySelection = keySelection
s.Username = username
setKp := s.SignupKeypad()
setInterface := UserInterface{IdxInterface: s.SetIdxInterface, kp: &setKp}
err := setInterface.DisperseInterface()
if err != nil {
return nil, err
}
s.ConfirmIdxInterface = setInterface.IdxInterface
return s.ConfirmIdxInterface, nil
}
func (s *UserSignSession) getSelectedKeyVals(keySelections m.KeySelection, userInterface []int) ([][]int, error) {
signupKp := s.SignupKeypad()
keypadInterface, err := util.ListToMatrix(userInterface, signupKp.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, kp m.KeypadDimension) (*UserInterface, error) {
if kp.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 := kp.NumbOfKeys
attrSetView = attrSetView[:numbOfKeys]
attrSetView, err = util.MatrixTranspose(attrSetView)
if err != nil {
return nil, err
}
signupUserInterface := UserInterface{
IdxInterface: util.MatrixToList(attrSetView),
kp: &m.KeypadDimension{
AttrsPerKey: numbOfKeys,
NumbOfKeys: numbOfKeys,
},
}
return &signupUserInterface, nil
}
func (s *UserSignSession) SignupKeypad() m.KeypadDimension {
return m.KeypadDimension{
AttrsPerKey: s.Kp.NumbOfKeys,
NumbOfKeys: s.Kp.NumbOfKeys,
}
}