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 
20 #ifndef _KSUDOKUHISTORY_H_
21 #define _KSUDOKUHISTORY_H_
22 
23 #include <QBitArray>
24 #include <QVector>
25 
26 #include "globals.h"
27 #include "ksudoku_types.h"
28 
29 
30 namespace ksudoku {
31 
32 class CellInfo {
33 	public:
CellInfo()34 		inline CellInfo()
35 		  : m_state(Marker), m_value(0), m_markers()
36 		{ }
CellInfo(ButtonState state,int value)37 		inline CellInfo(ButtonState state, int value)
38 		  : m_state(state), m_value(value), m_markers()
39 		{ }
CellInfo(const QBitArray & markers)40 		inline CellInfo(const QBitArray& markers)
41 		  : m_state(Marker), m_value(0), m_markers(markers)
42 		{ }
CellInfo(const CellInfo & info)43 		inline CellInfo(const CellInfo& info)
44 		  : m_state(info.m_state), m_value(info.m_value), m_markers(info.m_markers)
45 		{ }
state()46 		inline ButtonState state() const { return m_state; }
value()47 		inline int value() const { return m_value; }
markers()48 		inline const QBitArray markers() const { return m_markers; }
marker(int value)49 		inline bool marker(int value) const {
50 			if(value > m_markers.size() || value == 0) return false;
51 			return m_markers[value-1];
52 		}
53 		inline CellInfo& operator=(const CellInfo& info) {
54 			m_state = info.m_state;
55 			m_value = info.m_value;
56 			m_markers = info.m_markers;
57 			return *this;
58 		}
59 	private:
60 		ButtonState m_state;
61 		int m_value;
62 		QBitArray m_markers;
63 };
64 
65 class PuzzleState {
66 public:
PuzzleState()67 	PuzzleState() {
68 	}
PuzzleState(int size,int values)69 	PuzzleState(int size, int values)
70 	  : m_markers(values), m_values(size, 0), m_given(size)
71 
72 	{
73 		for(int i = 0; i < values; i++) {
74 			m_markers[i] = QBitArray(size);
75 		}
76 	}
77 public:
reset()78 	void reset() {
79 		for(int i = 0; i < m_markers.size(); i++) {
80 			QBitArray &array = m_markers[i];
81 			for(int j = 0; j < array.size(); j++)
82 				array.clearBit(j);
83 		}
84 		for(int i = 0; i < m_values.size(); i++) {
85 			m_values[i] = 0;
86 			m_given.clearBit(i);
87 		}
88 	}
setMarker(int index,int value,bool status)89 	inline void setMarker(int index, int value, bool status)
90 	{
91 		if(value == 0 || value > m_markers.size())
92 			return;
93 		m_markers[value-1].setBit(index, status);
94 	}
resetMarkers(int index)95 	inline void resetMarkers(int index)
96 	{
97 		for(int i = 0; i < m_markers.size(); i++) {
98 			m_markers[i].clearBit(index);
99 		}
100 	}
setMarkers(int index,const QBitArray & values)101 	inline void setMarkers(int index, const QBitArray& values) {
102 		if(values.size() == 0) {
103 			resetMarkers(index);
104 			return;
105 		}
106 		for(int i = 0; i < m_markers.size(); i++) {
107 			m_markers[i].setBit(index, values[i]);
108 		}
109 	}
marker(int index,int value)110 	inline bool marker(int index, int value) const
111 	{
112 		if(value == 0 || value > m_markers.size())
113 			return false;
114 		return m_markers[value-1][index];
115 	}
markers(int index)116 	inline QBitArray markers(int index) const {
117 		QBitArray array(m_markers.size());
118 		for(int i = 0; i < m_markers.size(); i++) {
119 			array.setBit(i, m_markers[i][index]);
120 		}
121 		return array;
122 	}
setGiven(int index,bool given)123 	inline void setGiven(int index, bool given)
124 	{
125 		m_given.setBit(index, given);
126 	}
setValue(int index,int value)127 	inline void setValue(int index, int value)
128 	{
129 		m_values[index] = value;
130 	}
setValue(int index,int value,bool given)131 	inline void setValue(int index, int value, bool given)
132 	{
133 		m_given.setBit(index, given);
134 		m_values[index] = value;
135 	}
given(int index)136 	inline bool given(int index) const
137 	{
138 		return m_given[index];
139 	}
value(int index)140 	inline int value(int index) const
141 	{
142 		return m_values[index];
143 	}
144 // 	inline void operator=(const PuzzleState& state) {
145 // 		m_markers = state.m_markers;
146 // 		m_values = state.m_values;
147 // 		m_given = state.m_given;
148 // 	}
detach()149 	inline void detach() {
150 		for(int i = 0; i < m_markers.size(); ++i) {
151 			// Detach m_markers
152 			// This actually is only needed once and not every loop
153 			// However this way it's more secure (m_markers.size() might be 0)
154 			m_markers[i] = m_markers[i];
155 
156 			// Detach from shared bit array data
157 			m_markers[i].detach();
158 		}
159 		m_values.detach();
160 		m_given.detach();
161 	}
allValues()162 	inline const BoardContents allValues() const {
163 		return m_values;
164 	}
165 	/**
166 	 *@note Use this method only to get size of puzzle when operating
167 	 * directly on the puzzle state.
168 	 */
size()169 	inline int size() const {
170 		return m_values.size();
171 	}
172 
173 private:
174 	QVector<QBitArray> m_markers;
175 	BoardContents m_values;
176 	QBitArray m_given;
177 };
178 
179 
180 class HistoryEvent {
181 	public:
182 		HistoryEvent();
183 		HistoryEvent(int index, const CellInfo& changedCell);
184 		explicit HistoryEvent(const PuzzleState& newState);
185 
186 		bool applyTo(PuzzleState& puzzle);
187 		bool undoOn(PuzzleState& puzzle) const;
188 		bool redoOn(PuzzleState& puzzle) const;
189 
cellIndices()190 		const QVector<int>& cellIndices() const { return m_cellsIndex; }
cellChanges()191 		const QVector<CellInfo>& cellChanges() const { return m_cellsAfter; }
192 
193 	private:
194 		void setPuzzleCell(PuzzleState& puzzle, int index, const CellInfo& cell) const;
195 		CellInfo getPuzzleCell(const PuzzleState& puzzle, int index) const;
196 
197 	private:
198 		QVector<int> m_cellsIndex;
199 		QVector<CellInfo> m_cellsBefore;
200 		QVector<CellInfo> m_cellsAfter;
201 };
202 
203 }
204 
205 #endif
206