-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add puzzle bloc, and bloc tests
- Loading branch information
1 parent
00fb889
commit 2a24f17
Showing
12 changed files
with
815 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
import 'package:bloc/bloc.dart'; | ||
import 'package:equatable/equatable.dart'; | ||
import 'package:sudoku/models/models.dart'; | ||
import 'package:sudoku/puzzle/puzzle.dart'; | ||
|
||
part 'puzzle_event.dart'; | ||
part 'puzzle_state.dart'; | ||
|
||
class PuzzleBloc extends Bloc<PuzzleEvent, PuzzleState> { | ||
PuzzleBloc({ | ||
required PuzzleRepository puzzleRepository, | ||
}) : _puzzleRepository = puzzleRepository, | ||
super(const PuzzleState()) { | ||
on<PuzzleInitialized>(_onPuzzleInitialized); | ||
on<SudokuBlockSelected>(_onSudokuBlockSelected); | ||
on<SudokuInputEntered>(_onSudokuInputEntered); | ||
on<SudokuInputErased>(_onSudokuInputErased); | ||
} | ||
|
||
final PuzzleRepository _puzzleRepository; | ||
|
||
void _onPuzzleInitialized( | ||
PuzzleInitialized event, | ||
Emitter<PuzzleState> emit, | ||
) { | ||
final puzzle = _puzzleRepository.getPuzzle()!; | ||
emit(state.copyWith(puzzle: () => puzzle)); | ||
} | ||
|
||
void _onSudokuBlockSelected( | ||
SudokuBlockSelected event, | ||
Emitter<PuzzleState> emit, | ||
) { | ||
emit( | ||
state.copyWith( | ||
selectedBlock: () => event.block, | ||
highlightedBlocks: () => | ||
state.puzzle.sudoku.blocksToHighlight(event.block), | ||
), | ||
); | ||
} | ||
|
||
void _onSudokuInputEntered( | ||
SudokuInputEntered event, | ||
Emitter<PuzzleState> emit, | ||
) { | ||
final selectedBlock = state.selectedBlock; | ||
if (selectedBlock == null || selectedBlock.isGenerated == true) return; | ||
|
||
final mutableSudoku = Sudoku( | ||
blocks: [...state.puzzle.sudoku.blocks], | ||
); | ||
|
||
final updatedSudoku = mutableSudoku.updateBlock( | ||
selectedBlock, | ||
event.input, | ||
); | ||
|
||
// If the entered input is wrong. | ||
if (selectedBlock.correctValue != event.input) { | ||
final remainingMistakes = state.puzzle.remainingMistakes - 1; | ||
// If there are no more remaining mistakes | ||
if (remainingMistakes <= 0) { | ||
emit( | ||
state.copyWith( | ||
puzzle: () => state.puzzle.copyWith( | ||
sudoku: updatedSudoku, | ||
remainingMistakes: remainingMistakes, | ||
), | ||
puzzleStatus: () => PuzzleStatus.failed, | ||
), | ||
); | ||
} else { | ||
emit( | ||
state.copyWith( | ||
puzzle: () => state.puzzle.copyWith( | ||
sudoku: updatedSudoku, | ||
remainingMistakes: remainingMistakes, | ||
), | ||
), | ||
); | ||
} | ||
} else if (updatedSudoku.isComplete()) { | ||
emit( | ||
state.copyWith( | ||
puzzle: () => state.puzzle.copyWith( | ||
sudoku: updatedSudoku, | ||
), | ||
puzzleStatus: () => PuzzleStatus.complete, | ||
highlightedBlocks: () => const [], | ||
selectedBlock: () => null, | ||
), | ||
); | ||
} else { | ||
emit( | ||
state.copyWith( | ||
puzzle: () => state.puzzle.copyWith( | ||
sudoku: updatedSudoku, | ||
), | ||
), | ||
); | ||
} | ||
} | ||
|
||
void _onSudokuInputErased( | ||
SudokuInputErased event, | ||
Emitter<PuzzleState> emit, | ||
) { | ||
final selectedBlock = state.selectedBlock; | ||
if (selectedBlock == null || selectedBlock.isGenerated == true) return; | ||
|
||
final mutableSudoku = Sudoku( | ||
blocks: [...state.puzzle.sudoku.blocks], | ||
); | ||
|
||
emit( | ||
state.copyWith( | ||
puzzle: () => state.puzzle.copyWith( | ||
sudoku: mutableSudoku.updateBlock(selectedBlock, -1), | ||
), | ||
), | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
part of 'puzzle_bloc.dart'; | ||
|
||
sealed class PuzzleEvent extends Equatable { | ||
const PuzzleEvent(); | ||
|
||
@override | ||
List<Object> get props => []; | ||
} | ||
|
||
final class PuzzleInitialized extends PuzzleEvent { | ||
const PuzzleInitialized(); | ||
} | ||
|
||
final class SudokuBlockSelected extends PuzzleEvent { | ||
const SudokuBlockSelected(this.block); | ||
|
||
final Block block; | ||
|
||
@override | ||
List<Object> get props => [block]; | ||
} | ||
|
||
final class SudokuInputEntered extends PuzzleEvent { | ||
const SudokuInputEntered(this.input); | ||
|
||
final int input; | ||
|
||
@override | ||
List<Object> get props => [input]; | ||
} | ||
|
||
final class SudokuInputErased extends PuzzleEvent { | ||
const SudokuInputErased(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
// ignore_for_file: public_member_api_docs, sort_constructors_first | ||
part of 'puzzle_bloc.dart'; | ||
|
||
class PuzzleState extends Equatable { | ||
const PuzzleState({ | ||
this.puzzle = const Puzzle( | ||
sudoku: Sudoku(blocks: []), | ||
difficulty: Difficulty.easy, | ||
), | ||
this.puzzleStatus = PuzzleStatus.incomplete, | ||
this.highlightedBlocks = const [], | ||
this.selectedBlock, | ||
}); | ||
|
||
final Puzzle puzzle; | ||
final PuzzleStatus puzzleStatus; | ||
final List<Block> highlightedBlocks; | ||
final Block? selectedBlock; | ||
|
||
@override | ||
List<Object?> get props => [ | ||
puzzle, | ||
puzzleStatus, | ||
highlightedBlocks, | ||
selectedBlock, | ||
]; | ||
|
||
PuzzleState copyWith({ | ||
Puzzle Function()? puzzle, | ||
PuzzleStatus Function()? puzzleStatus, | ||
List<Block> Function()? highlightedBlocks, | ||
Block? Function()? selectedBlock, | ||
}) { | ||
return PuzzleState( | ||
puzzle: puzzle != null ? puzzle() : this.puzzle, | ||
puzzleStatus: puzzleStatus != null ? puzzleStatus() : this.puzzleStatus, | ||
highlightedBlocks: highlightedBlocks != null | ||
? highlightedBlocks() | ||
: this.highlightedBlocks, | ||
selectedBlock: | ||
selectedBlock != null ? selectedBlock() : this.selectedBlock, | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
export 'bloc/puzzle_bloc.dart'; | ||
export 'models/models.dart'; | ||
export 'repository/puzzle_repository.dart'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
export 'mocks.dart'; | ||
export 'pump_app.dart'; | ||
export 'set_display_size.dart'; | ||
export 'sudoku_helpers.dart'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
import 'package:sudoku/models/models.dart'; | ||
|
||
const sudoku2x2Block0 = Block( | ||
position: Position(x: 0, y: 0), | ||
correctValue: 4, | ||
currentValue: -1, | ||
); | ||
|
||
const sudoku2x2Block1 = Block( | ||
position: Position(x: 0, y: 1), | ||
correctValue: 1, | ||
currentValue: 1, | ||
isGenerated: true, | ||
); | ||
|
||
const sudoku2x2Block2 = Block( | ||
position: Position(x: 0, y: 2), | ||
correctValue: 2, | ||
currentValue: -1, | ||
); | ||
|
||
const sudoku2x2Block3 = Block( | ||
position: Position(x: 0, y: 3), | ||
correctValue: 3, | ||
currentValue: -1, | ||
); | ||
|
||
const sudoku2x2Block4 = Block( | ||
position: Position(x: 1, y: 0), | ||
correctValue: 2, | ||
currentValue: 2, | ||
isGenerated: true, | ||
); | ||
|
||
const sudoku2x2Block5 = Block( | ||
position: Position(x: 1, y: 1), | ||
correctValue: 3, | ||
currentValue: 3, | ||
isGenerated: true, | ||
); | ||
|
||
const sudoku2x2Block6 = Block( | ||
position: Position(x: 1, y: 2), | ||
correctValue: 4, | ||
currentValue: -1, | ||
); | ||
|
||
const sudoku2x2Block7 = Block( | ||
position: Position(x: 1, y: 3), | ||
correctValue: 1, | ||
currentValue: -1, | ||
); | ||
|
||
const sudoku2x2Block8 = Block( | ||
position: Position(x: 2, y: 0), | ||
correctValue: 1, | ||
currentValue: -1, | ||
); | ||
|
||
const sudoku2x2Block9 = Block( | ||
position: Position(x: 2, y: 1), | ||
correctValue: 4, | ||
currentValue: -1, | ||
); | ||
|
||
const sudoku2x2Block10 = Block( | ||
position: Position(x: 2, y: 2), | ||
correctValue: 3, | ||
currentValue: 3, | ||
isGenerated: true, | ||
); | ||
|
||
const sudoku2x2Block11 = Block( | ||
position: Position(x: 2, y: 3), | ||
correctValue: 2, | ||
currentValue: 2, | ||
isGenerated: true, | ||
); | ||
|
||
const sudoku2x2Block12 = Block( | ||
position: Position(x: 3, y: 0), | ||
correctValue: 3, | ||
currentValue: -1, | ||
); | ||
|
||
const sudoku2x2Block13 = Block( | ||
position: Position(x: 3, y: 1), | ||
correctValue: 2, | ||
currentValue: -1, | ||
); | ||
|
||
const sudoku2x2Block14 = Block( | ||
position: Position(x: 3, y: 2), | ||
correctValue: 1, | ||
currentValue: 1, | ||
isGenerated: true, | ||
); | ||
|
||
const sudoku2x2Block15 = Block( | ||
position: Position(x: 3, y: 3), | ||
correctValue: 4, | ||
currentValue: -1, | ||
); | ||
|
||
const sudoku2x2 = Sudoku( | ||
blocks: [ | ||
sudoku2x2Block0, | ||
sudoku2x2Block1, | ||
sudoku2x2Block2, | ||
sudoku2x2Block3, | ||
sudoku2x2Block4, | ||
sudoku2x2Block5, | ||
sudoku2x2Block6, | ||
sudoku2x2Block7, | ||
sudoku2x2Block8, | ||
sudoku2x2Block9, | ||
sudoku2x2Block10, | ||
sudoku2x2Block11, | ||
sudoku2x2Block12, | ||
sudoku2x2Block13, | ||
sudoku2x2Block14, | ||
sudoku2x2Block15, | ||
], | ||
); | ||
|
||
final sudoku2x2WithOneRemaining = sudoku2x2 | ||
.updateBlock(sudoku2x2Block0, 4) | ||
.updateBlock(sudoku2x2Block3, 3) | ||
.updateBlock(sudoku2x2Block6, 4) | ||
.updateBlock(sudoku2x2Block7, 1) | ||
.updateBlock(sudoku2x2Block8, 1) | ||
.updateBlock(sudoku2x2Block9, 4) | ||
.updateBlock(sudoku2x2Block12, 3) | ||
.updateBlock(sudoku2x2Block13, 2) | ||
.updateBlock(sudoku2x2Block15, 4); |
Oops, something went wrong.