PR Fixes. Move .initial factory method to test target. Rename given() to apply(chip:group:) and make it a member function
This commit is contained in:
parent
a2546abee6
commit
e94021b4be
|
@ -58,19 +58,6 @@ struct RecoveryPhraseValidationState: Equatable {
|
||||||
|
|
||||||
|
|
||||||
extension RecoveryPhraseValidationState {
|
extension RecoveryPhraseValidationState {
|
||||||
static func initial(
|
|
||||||
phrase: RecoveryPhrase,
|
|
||||||
missingIndices: [Int],
|
|
||||||
missingWordsChips: [PhraseChip.Kind]
|
|
||||||
) -> Self {
|
|
||||||
RecoveryPhraseValidationState(
|
|
||||||
phrase: phrase,
|
|
||||||
missingIndices: missingIndices,
|
|
||||||
missingWordChips: missingWordsChips,
|
|
||||||
completion: []
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// creates an initial `RecoveryPhraseValidationState` with no completions and random missing indices.
|
/// creates an initial `RecoveryPhraseValidationState` with no completions and random missing indices.
|
||||||
/// - Note: Use this function to create a random validation puzzle for a given phrase.
|
/// - Note: Use this function to create a random validation puzzle for a given phrase.
|
||||||
static func random(phrase: RecoveryPhrase) -> Self {
|
static func random(phrase: RecoveryPhrase) -> Self {
|
||||||
|
@ -119,60 +106,60 @@ extension RecoveryPhraseValidationState {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// drives the state machine represented on this Enum by the action of applying a chip into a group of words containing an empty slot that has to be completed
|
/// drives the state machine represented on this Enum by the action of applying a chip into a group of words containing an empty slot that has to be completed
|
||||||
static func given(_ state: RecoveryPhraseValidationState, apply chip: PhraseChip.Kind, into group: Int) -> Self {
|
func apply(chip: PhraseChip.Kind, into group: Int) -> Self {
|
||||||
guard case let PhraseChip.Kind.unassigned(word) = chip else { return state }
|
guard case let PhraseChip.Kind.unassigned(word) = chip else { return self }
|
||||||
|
|
||||||
switch state.step {
|
switch self.step {
|
||||||
case .initial:
|
case .initial:
|
||||||
guard let missingChipIndex = state.missingWordChips.firstIndex(of: chip) else { return state }
|
guard let missingChipIndex = missingWordChips.firstIndex(of: chip) else { return self }
|
||||||
|
|
||||||
var newMissingWords = state.missingWordChips
|
var newMissingWords = missingWordChips
|
||||||
newMissingWords[missingChipIndex] = .empty
|
newMissingWords[missingChipIndex] = .empty
|
||||||
|
|
||||||
return RecoveryPhraseValidationState(
|
return RecoveryPhraseValidationState(
|
||||||
phrase: state.phrase,
|
phrase: phrase,
|
||||||
missingIndices: state.missingIndices,
|
missingIndices: missingIndices,
|
||||||
missingWordChips: newMissingWords,
|
missingWordChips: newMissingWords,
|
||||||
completion: [RecoveryPhraseStepCompletion(groupIndex: group, word: word)]
|
completion: [RecoveryPhraseStepCompletion(groupIndex: group, word: word)]
|
||||||
)
|
)
|
||||||
|
|
||||||
case .incomplete:
|
case .incomplete:
|
||||||
guard let missingChipIndex = state.missingWordChips.firstIndex(of: chip) else { return state }
|
guard let missingChipIndex = missingWordChips.firstIndex(of: chip) else { return self }
|
||||||
|
|
||||||
if state.completion.count < (RecoveryPhraseValidationState.phraseChunks - 1) {
|
if completion.count < (RecoveryPhraseValidationState.phraseChunks - 1) {
|
||||||
var newMissingWords = state.missingWordChips
|
var newMissingWords = missingWordChips
|
||||||
newMissingWords[missingChipIndex] = .empty
|
newMissingWords[missingChipIndex] = .empty
|
||||||
|
|
||||||
var newCompletionState = Array(state.completion)
|
var newCompletionState = Array(completion)
|
||||||
newCompletionState.append(RecoveryPhraseStepCompletion(groupIndex: group, word: word))
|
newCompletionState.append(RecoveryPhraseStepCompletion(groupIndex: group, word: word))
|
||||||
|
|
||||||
return RecoveryPhraseValidationState(
|
return RecoveryPhraseValidationState(
|
||||||
phrase: state.phrase,
|
phrase: phrase,
|
||||||
missingIndices: state.missingIndices,
|
missingIndices: missingIndices,
|
||||||
missingWordChips: newMissingWords,
|
missingWordChips: newMissingWords,
|
||||||
completion: newCompletionState
|
completion: newCompletionState
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
var newCompletion = state.completion
|
var newCompletion = completion
|
||||||
newCompletion.append(RecoveryPhraseStepCompletion(groupIndex: group, word: word))
|
newCompletion.append(RecoveryPhraseStepCompletion(groupIndex: group, word: word))
|
||||||
|
|
||||||
return RecoveryPhraseValidationState(
|
return RecoveryPhraseValidationState(
|
||||||
phrase: state.phrase,
|
phrase: phrase,
|
||||||
missingIndices: state.missingIndices,
|
missingIndices: missingIndices,
|
||||||
missingWordChips: Array(repeating: .empty, count: RecoveryPhraseValidationState.phraseChunks),
|
missingWordChips: Array(repeating: .empty, count: RecoveryPhraseValidationState.phraseChunks),
|
||||||
completion: newCompletion
|
completion: newCompletion
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return state
|
return self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static func pickWordsFromMissingIndices(indices: [Int], phrase: RecoveryPhrase) -> [PhraseChip.Kind] {
|
static func pickWordsFromMissingIndices(indices: [Int], phrase: RecoveryPhrase) -> [PhraseChip.Kind] {
|
||||||
precondition((indices.count - 1) * wordGroupSize <= phrase.words.count)
|
precondition((indices.count - 1) * Self.wordGroupSize <= phrase.words.count)
|
||||||
var words: [PhraseChip.Kind] = []
|
var words: [PhraseChip.Kind] = []
|
||||||
indices.enumerated().forEach({ index, position in
|
indices.enumerated().forEach({ index, position in
|
||||||
let realIndex = (index * wordGroupSize) + position
|
let realIndex = (index * Self.wordGroupSize) + position
|
||||||
words.append(.unassigned(word: phrase.words[realIndex]))
|
words.append(.unassigned(word: phrase.words[realIndex]))
|
||||||
})
|
})
|
||||||
return words
|
return words
|
||||||
|
@ -212,7 +199,7 @@ extension RecoveryPhraseValidationReducer {
|
||||||
return .none
|
return .none
|
||||||
|
|
||||||
case let .drag(wordChip, group):
|
case let .drag(wordChip, group):
|
||||||
state = .given(state, apply: wordChip, into: group)
|
state = state.apply(chip: wordChip, into: group)
|
||||||
return .none
|
return .none
|
||||||
|
|
||||||
case .validate:
|
case .validate:
|
||||||
|
|
|
@ -28,6 +28,8 @@ class RecoveryPhraseValidationTests: XCTestCase {
|
||||||
let indices = [1, 0, 5, 3]
|
let indices = [1, 0, 5, 3]
|
||||||
|
|
||||||
let expected = ["salute", "boil", "cancel", "pizza"].map({ PhraseChip.Kind.unassigned(word: $0) })
|
let expected = ["salute", "boil", "cancel", "pizza"].map({ PhraseChip.Kind.unassigned(word: $0) })
|
||||||
|
|
||||||
|
|
||||||
let result = RecoveryPhraseValidationState.pickWordsFromMissingIndices(indices: indices, phrase: phrase)
|
let result = RecoveryPhraseValidationState.pickWordsFromMissingIndices(indices: indices, phrase: phrase)
|
||||||
|
|
||||||
XCTAssertEqual(expected, result)
|
XCTAssertEqual(expected, result)
|
||||||
|
@ -73,7 +75,7 @@ class RecoveryPhraseValidationTests: XCTestCase {
|
||||||
completion: [RecoveryPhraseStepCompletion(groupIndex: 1, word: "salute")]
|
completion: [RecoveryPhraseStepCompletion(groupIndex: 1, word: "salute")]
|
||||||
)
|
)
|
||||||
|
|
||||||
let result = RecoveryPhraseValidationState.given(initialStep, apply: missingWordChips[0], into: 1)
|
let result = initialStep.apply(chip: missingWordChips[0], into: 1)
|
||||||
|
|
||||||
XCTAssertEqual(expectedStep, result)
|
XCTAssertEqual(expectedStep, result)
|
||||||
}
|
}
|
||||||
|
@ -120,7 +122,7 @@ class RecoveryPhraseValidationTests: XCTestCase {
|
||||||
completion: expectedCompletion
|
completion: expectedCompletion
|
||||||
)
|
)
|
||||||
|
|
||||||
let result = RecoveryPhraseValidationState.given(initialStep, apply: missingWordChips[3], into: 0)
|
let result = initialStep.apply(chip: missingWordChips[3], into: 0)
|
||||||
|
|
||||||
XCTAssertEqual(expectedStep, result)
|
XCTAssertEqual(expectedStep, result)
|
||||||
XCTAssertEqual(result.step, .incomplete)
|
XCTAssertEqual(result.step, .incomplete)
|
||||||
|
@ -171,7 +173,7 @@ class RecoveryPhraseValidationTests: XCTestCase {
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
let result = RecoveryPhraseValidationState.given(currentStep, apply: PhraseChip.Kind.unassigned(word: "boil"), into: 1)
|
let result = currentStep.apply(chip: PhraseChip.Kind.unassigned(word: "boil"), into: 1)
|
||||||
|
|
||||||
XCTAssertEqual(expected, result)
|
XCTAssertEqual(expected, result)
|
||||||
XCTAssertEqual(expected.step, result.step)
|
XCTAssertEqual(expected.step, result.step)
|
||||||
|
@ -227,7 +229,7 @@ class RecoveryPhraseValidationTests: XCTestCase {
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
let result = RecoveryPhraseValidationState.given(currentStep, apply: PhraseChip.Kind.unassigned(word: "cancel"), into: 2)
|
let result = currentStep.apply(chip: PhraseChip.Kind.unassigned(word: "cancel"), into: 2)
|
||||||
|
|
||||||
XCTAssertEqual(expected, result)
|
XCTAssertEqual(expected, result)
|
||||||
}
|
}
|
||||||
|
@ -284,7 +286,7 @@ class RecoveryPhraseValidationTests: XCTestCase {
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
let result = RecoveryPhraseValidationState.given(currentStep, apply: PhraseChip.Kind.unassigned(word: "pizza"), into: 3)
|
let result = currentStep.apply(chip: PhraseChip.Kind.unassigned(word: "pizza"), into: 3)
|
||||||
|
|
||||||
XCTAssertEqual(expected, result)
|
XCTAssertEqual(expected, result)
|
||||||
}
|
}
|
||||||
|
@ -442,3 +444,18 @@ class RecoveryPhraseValidationTests: XCTestCase {
|
||||||
XCTAssertEqual(expected, result)
|
XCTAssertEqual(expected, result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension RecoveryPhraseValidationState {
|
||||||
|
static func initial(
|
||||||
|
phrase: RecoveryPhrase,
|
||||||
|
missingIndices: [Int],
|
||||||
|
missingWordsChips: [PhraseChip.Kind]
|
||||||
|
) -> Self {
|
||||||
|
RecoveryPhraseValidationState(
|
||||||
|
phrase: phrase,
|
||||||
|
missingIndices: missingIndices,
|
||||||
|
missingWordChips: missingWordsChips,
|
||||||
|
completion: []
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue