1 /***************************************************************************
2  *   Copyright 2006-2007 Johannes Bergmeier <johannes.bergmeier@gmx.net>   *
3  *                                                                         *
4  *   This program is free software; you can redistribute it and/or modify  *
5  *   it under the terms of the GNU General Public License as published by  *
6  *   the Free Software Foundation; either version 2 of the License, or     *
7  *   (at your option) any later version.                                   *
8  *                                                                         *
9  *   This program is distributed in the hope that it will be useful,       *
10  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12  *   GNU General Public License for more details.                          *
13  *                                                                         *
14  *   You should have received a copy of the GNU General Public License     *
15  *   along with this program; if not, write to the                         *
16  *   Free Software Foundation, Inc.,                                       *
17  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
18  ***************************************************************************/
19 #include "history.h"
20 
21 namespace ksudoku {
22 
HistoryEvent()23 HistoryEvent::HistoryEvent()
24 	: m_cellsIndex(), m_cellsBefore(), m_cellsAfter()
25 {
26 }
27 
HistoryEvent(int index,const CellInfo & changeCell)28 HistoryEvent::HistoryEvent(int index, const CellInfo& changeCell)
29 	: m_cellsIndex(1, index), m_cellsBefore(), m_cellsAfter(1, changeCell)
30 {
31 }
32 
HistoryEvent(const PuzzleState & puzzleChange)33 HistoryEvent::HistoryEvent(const PuzzleState& puzzleChange)
34 	: m_cellsIndex(puzzleChange.size()), m_cellsBefore(), m_cellsAfter(puzzleChange.size())
35 {
36 	for(int i = 0; i < puzzleChange.size(); i++) {
37 		m_cellsIndex[i] = i;
38 		m_cellsAfter[i] = getPuzzleCell(puzzleChange, i);
39 	}
40 }
41 
setPuzzleCell(PuzzleState & puzzle,int index,const CellInfo & cell) const42 void HistoryEvent::setPuzzleCell(PuzzleState& puzzle, int index, const CellInfo& cell) const {
43 	switch(cell.state()) {
44 		case GivenValue:
45 			puzzle.setGiven(index, true);
46 			puzzle.resetMarkers(index);
47 			puzzle.setValue(index, cell.value());
48 			break;
49 		case ObviouslyWrong:
50 		case WrongValue:
51 		case CorrectValue:
52 			puzzle.setGiven(index, false);
53 			puzzle.resetMarkers(index);
54 			puzzle.setValue(index, cell.value());
55 			break;
56 		case Marker:
57 			puzzle.setGiven(index, false);
58 			puzzle.setValue(index, 0);
59 			puzzle.setMarkers(index, cell.markers());
60 			break;
61 	}
62 }
63 
getPuzzleCell(const PuzzleState & puzzle,int index) const64 CellInfo HistoryEvent::getPuzzleCell(const PuzzleState& puzzle, int index) const {
65 	if(puzzle.given(index)) {
66  		return CellInfo(GivenValue, puzzle.value(index));
67 	} else if(puzzle.value(index) == 0) {
68 		return CellInfo(puzzle.markers(index));
69 	} else {
70 		return CellInfo(CorrectValue, puzzle.value(index));
71 	}
72 }
73 
74 
applyTo(PuzzleState & puzzle)75 bool HistoryEvent::applyTo(PuzzleState& puzzle) {
76 	if(m_cellsBefore.size() != 0 || m_cellsIndex.size() == 0)
77 		return false;
78 
79 	m_cellsBefore = QVector<CellInfo>(m_cellsIndex.count());
80 	for(int i = 0; i < m_cellsIndex.count(); ++i) {
81 		m_cellsBefore[i] = getPuzzleCell(puzzle, m_cellsIndex[i]);
82 		setPuzzleCell(puzzle, m_cellsIndex[i], m_cellsAfter[i]);
83 	}
84 	return true;
85 }
86 
undoOn(PuzzleState & puzzle) const87 bool HistoryEvent::undoOn(PuzzleState& puzzle) const {
88         if(m_cellsBefore.isEmpty() || m_cellsBefore.size() != m_cellsIndex.size())
89 		return false;
90 
91 	for(int i = 0; i < m_cellsIndex.count(); ++i) {
92 		setPuzzleCell(puzzle, m_cellsIndex[i], m_cellsBefore[i]);
93 	}
94 	return true;
95 }
96 
redoOn(PuzzleState & puzzle) const97 bool HistoryEvent::redoOn(PuzzleState& puzzle) const {
98         if(m_cellsBefore.isEmpty() || m_cellsBefore.size() != m_cellsIndex.size())
99 		return false;
100 
101 	for(int i = 0; i < m_cellsIndex.count(); ++i) {
102 		setPuzzleCell(puzzle, m_cellsIndex[i], m_cellsAfter[i]);
103 	}
104 	return true;
105 }
106 
107 }
108