Check-in [fc0aa399a1]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Moved current files under Entry; merged SnapShooter and SnapViewer projects into source tree
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: fc0aa399a132f9c453424a045567be73c0fc583b
User & Date: Martijn 2011-05-08 18:42:58
Context
2011-05-12
08:24
Removed time from datepicker; Added mindate to datepicker; restricted automatic adding of row to today check-in: fd00aaf3f0 user: MCO tags: trunk
2011-05-08
18:42
Moved current files under Entry; merged SnapShooter and SnapViewer projects into source tree check-in: fc0aa399a1 user: Martijn tags: trunk
17:35
Added global hotkey, timestamp of insert row gets updated a lot more often check-in: 0231250648 user: Martijn tags: trunk
Changes

Name change from src/F_Entry.dfm to Entry/src/F_Entry.dfm.

Name change from src/F_Entry.pas to Entry/src/F_Entry.pas.

Name change from src/lib/CheckPrevious.pas to Entry/src/lib/CheckPrevious.pas.

Name change from src/lib/L_KeysDown.pas to Entry/src/lib/L_KeysDown.pas.

Name change from src/lib/SQLite3.pas to Entry/src/lib/SQLite3.pas.

Name change from src/lib/SQLite3Abstract.pas to Entry/src/lib/SQLite3Abstract.pas.

Name change from src/lib/SQLite3Database.pas to Entry/src/lib/SQLite3Database.pas.

Name change from src/lib/SQLite3Functions.pas to Entry/src/lib/SQLite3Functions.pas.

Name change from src/lib/SQLite3Remote.pas to Entry/src/lib/SQLite3Remote.pas.

Name change from src/lib/sqlite3udf.pas to Entry/src/lib/sqlite3udf.pas.

Name change from src/prj/D2010/Olam.dpr to Entry/src/prj/D2010/Olam.dpr.

Name change from src/prj/D2010/Olam.dproj to Entry/src/prj/D2010/Olam.dproj.

Name change from src/prj/D2010/Olam.res to Entry/src/prj/D2010/Olam.res.

cannot compute difference between binary files

Added SnapViewer/doc/SnapViewer-display.pas.

























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
procedure DisplayChart(ADate: TDate);
var
  Simultaneous: TStringList;
  MaxSimCount: integer;
  FirstTime, LastTime, RowTime: TDateTime;
  FirstVerb, LastVerb: string;
  StartTime, EndTime: TDateTime;
  Duration: Double; // in days
begin
  LastTime  := Trunc(ADate);
  FirstTime := LastTime + EncodeTime(23, 59, 59);
  
  FDB.AddParamDate(':DateStart', LastTime);
  FDB.AddParamDateTime(':DateEnd', FirstTime);
  Rows := FDB.GetTable('SELECT * FROM v_Timeline WHERE datetime(DateUTC || '' '' || TimeUTC, Offset || '' minutes'') BETWEEN :DateStart AND :DateEnd');
  try
    MaxSimCount := 0;
    while not Rows.EOF do begin
      RowTime := IncMinutes(Rows.FieldAsDate('DateUTC') + Rows.FieldAsDateTime('TimeUTC'), Rows.FieldAsInteger('Offset'));
      if RowTime < FirstTime then begin
        FirstTime := RowTime;
        FirstVerb := Rows.FieldAsString('verb');
      end;
      if RowTime > LastTime then begin
        LastTime := RowTime;
        LastVerb := Rows.FieldAsString('verb');
      end;
      
      RowDescriptor := Rows.FieldAsString('subject'); // TODO: make sure this identifies the object uniquely (to prevent mismatches)
      if Rows.FieldAsString('verb') = 'start' then begin
        Simultaneous.Add(RowDescriptor);
      end else if Rows.FieldAsString('verb') = 'end' then begin
        Simultaneous.Remove(RowDescriptor);
      end;
      if Simultaneous.Count > MaxSimCount then begin
        // Keep track of the maximum number of simultaneous objects to be displayed
        MaxSimCount := Simultaneous.Count;
      end;
      Rows.Next;
    end{while};
  finally
    Rows.Free;
  end;
  
  if (FirstVerb = 'end') and ((FirstTime - ADate) > (1 / 24)) then begin
    StartTime := IncMinutes(FirstTime, -30);
  else
    StartTime := FirstTime;
  end;
  if (LastVerb = 'start') and ((IncDay(ADate) - LastTime) > (1 / 24)) then begin
    EndTime := IncMinutes(LastTime, -30);
  else
    EndTime := LastTime;
  end;
  Duration := EndTime - StartTime;
  
  
  
  // ...
end;

Added SnapViewer/doc/SnapViewer.txt.























































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
Interface
=========

[Week  |v|] (2008/42; 13-19 oktober)
_________________________

 - Maandag
   路 09:12 Helpdesk - Borland Developer Studio 2006 [bds.exe]
   路 10:07 Microsoft Excel - Weekuren.xls [EXCEL.EXE]
   路 10:12 Netvibes (195) - Mozilla Firefox [firefox.exe]
 + Dinsdag
 + Woensdag
 + Donderdag
 + Vrijdag
_________________________


Bij selectie van...
* Weekdag: toon timeline van die dag;
  - hoogte van viewport (scrollable): instelbaar minimaal aantal uren binnen 1 window? (standaard 1 TextHeight per kwartier)
  - bovenkant window = vroegste registratie die dag
  - onderkant window = laatste registratie die dag
  - balk voor elk proces -- onder elkaar als het kan, anders naast elkaar
  - binnen procesbalk: blok voor elk openstaand venster (InsertDateTime t/m LastUpdateDateTime); wederom onder elkaar als het kan, anders naast
  - aparte balk voor idle-registratie (meest linkse balk?)
* Tijdstip:
  - highlight balk van bijbehorend proces en window; evt. met thumbnail van screenshot?
  - in vak onder tijdlijn, verkleinde versie van de screenshot. Dubbelklik = open volledig shot
  - teken rode lijn op geselecteerd tijdstip


Opbouwen tijdlijn
=================
* Mee te nemen events
  - Start/shutdown OS  (Session.StartupTime, Session.PreviousShutdownTime) -- HKLM\System\CurrentControlSet\Control\Windows >> ShutdownTime
  - Start/einde sessies (Session.InsertDateTime, Session.LastUpdateDateTime)
  - Start/einde processen (coalesce(Process.StartupTime, Process.InsertDateTime), coalesce(Process.TerminateTime, Process.LastUpdateDateTime)
  - Eerste/laatste registratie van elk window (Window.InsertDateTime, Window.LastUpdateDateTime)
  - Start/stop idle user (Focus.InsertDateTime - Focus.IdleMilliseconds)
  - Focus-snapshots

CREATE TABLE Timeline
( id					INTEGER PRIMARY KEY
, DateTime				TEXT NOT NULL
, Bias					INTEGER NOT NULL
, Subject				TEXT -- 'System', 'Session', 'Process', 'Window', 'User', 'Desktop'
, Verb					TEXT -- 'startup', 'start', 'first seen', 'last seen', 'terminate', 'shutdown', 'capture', 'idle', 'active'
, Description			TEXT
, SessionID				INTEGER CONSTRAINT fk_Timeline_Session REFERENCES Session(id)
, ExecutableID			INTEGER CONSTRAINT fk_Timeline_Executable REFERENCES Executable(id)
, ProcessID				INTEGER CONSTRAINT fk_Timeline_Process REFERENCES Process(id)
, WindowID				INTEGER CONSTRAINT fk_Timeline_Window REFERENCES Window(id)
, FocusID				INTEGER CONSTRAINT fk_Timeline_Focus REFERENCES Focus(id)
, InsertDateTime		TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
);


Overig
======
* Overal de "T" uit de datum/tijd halen?
* Executable: 
  + Name NOT NULL = ExtractFileName(Path)
  + Path NOT NULL = IncludePathDelimiter(ExtractFilePath(Path))
* Window: Icon BLOB
* Misschien voor elk gevonden GetForegroundWindow, GetParent registreren tot die nil teruggeeft?


================================================================================
CREATE VIEW v_Timeline AS

SELECT DISTINCT date(StartupTime, TimeZoneBias || ' minutes') AS DateUTC
,      time(StartupTime, TimeZoneBias || ' minutes') AS TimeUTC
,      TimeZoneBias AS Bias
,      'System' AS Subject
,      'begin' AS Verb
,      NULL AS Description
,      NULL AS SessionID
,      NULL AS ExecutableID
,      NULL AS ProcessID
,      NULL AS WindowID
,      NULL AS FocusID
  FROM Session
  
UNION

SELECT DISTINCT date(PreviousShutdownTime) AS DateUTC
,      time(PreviousShutdownTime) AS TimeUTC
,      TimeZoneBias AS Bias
,      'System' AS Subject
,      'end' AS Verb
,      NULL AS Description
,      NULL AS SessionID
,      NULL AS ExecutableID
,      NULL AS ProcessID
,      NULL AS WindowID
,      NULL AS FocusID
  FROM Session
 WHERE PreviousShutdownTime IS NOT NULL
 
UNION

SELECT date(InsertDateTime, TimeZoneBias || ' minutes')
,      time(InsertDateTime, TimeZoneBias || ' minutes')
,      TimeZoneBias
,      'Session'
,      'begin'
,      NULL
,      id
,      NULL
,      NULL
,      NULL
,      NULL
  FROM Session

UNION

SELECT date(coalesce(LastUpdateDateTime, InsertDateTime), TimeZoneBias || ' minutes')
,      time(coalesce(LastUpdateDateTime, InsertDateTime), TimeZoneBias || ' minutes')
,      TimeZoneBias
,      'Session'
,      'end'
,      NULL
,      id
,      NULL
,      NULL
,      NULL
,      NULL
  FROM Session

UNION

SELECT date(coalesce(t.StartupTime, t.InsertDateTime), s.TimeZoneBias || ' minutes')
,      time(coalesce(t.StartupTime, t.InsertDateTime), s.TimeZoneBias || ' minutes')
,      s.TimeZoneBias
,      'Process'
,      'begin'
,      coalesce(e.Description, t.WindowTitle) || ' [' || e.Name || ']'
,      s.id
,      t.ExecutableID
,      t.id
,      NULL
,      NULL
  FROM Process t
       INNER JOIN Session s
	           ON t.SessionID = s.id
	   INNER JOIN Executable e
			   ON t.ExecutableID = e.id

UNION

-- TODO: if the end time is unknown, then use the MAX of children's end times (windows)
SELECT date(coalesce(t.TerminateTime, t.LastUpdateDateTime, t.InsertDateTime), s.TimeZoneBias || ' minutes')
,      time(coalesce(t.TerminateTime, t.LastUpdateDateTime, t.InsertDateTime), s.TimeZoneBias || ' minutes')
,      s.TimeZoneBias
,      'Process'
,      'end'
,      coalesce(e.Description, t.WindowTitle) || ' [' || e.Name || ']'
,      s.id
,      t.ExecutableID
,      t.id
,      NULL
,      NULL
  FROM Process t
       INNER JOIN Session s
	           ON t.SessionID = s.id
	   INNER JOIN Executable e
			   ON t.ExecutableID = e.id

UNION

SELECT date(t.InsertDateTime, s.TimeZoneBias || ' minutes')
,      time(t.InsertDateTime, s.TimeZoneBias || ' minutes')
,      s.TimeZoneBias
,      'Window'
,      'begin'
,      trim(t.Title) || ' [' || t.Class || ']'
,      s.id
,      p.ExecutableID
,      p.id
,      t.id
,      NULL
  FROM Window t
	   INNER JOIN Process p
	           ON t.ProcessID = p.id
       INNER JOIN Session s
	           ON p.SessionID = s.id

UNION

-- TODO: if the end time is unknown, then use the MAX of children's end times (focus)
SELECT date(coalesce(t.LastUpdateDateTime, t.InsertDateTime), s.TimeZoneBias || ' minutes')
,      time(coalesce(t.LastUpdateDateTime, t.InsertDateTime), s.TimeZoneBias || ' minutes')
,      s.TimeZoneBias
,      'Window'
,      'end'
,      trim(t.Title) || ' [' || t.Class || ']'
,      s.id
,      p.ExecutableID
,      p.id
,      t.id
,      NULL
  FROM Window t
	   INNER JOIN Process p
	           ON t.ProcessID = p.id
       INNER JOIN Session s
	           ON p.SessionID = s.id

UNION

SELECT date(t.InsertDateTime, s.TimeZoneBias || ' minutes')
,      time(t.InsertDateTime, s.TimeZoneBias || ' minutes')
,      s.TimeZoneBias
,      'Desktop'
,      'capture'
,      nullif(t.Title, '')
,      s.id
,      p.ExecutableID
,      p.id
,      w.id
,      t.id
  FROM Focus t
	   INNER JOIN Window w
	           ON t.WindowID = w.id
	   INNER JOIN Process p
	           ON w.ProcessID = p.id
       INNER JOIN Session s
	           ON p.SessionID = s.id

UNION

SELECT DISTINCT date(t.InsertDateTime, '-' || (t.IdleMilliseconds / 1000) || ' seconds', s.TimeZoneBias || ' minutes')
,      time(t.InsertDateTime, '-' || (t.IdleMilliseconds / 1000) || ' seconds', s.TimeZoneBias || ' minutes')
,      s.TimeZoneBias
,      'User'
,      'Idle'
,      p.UserName
,      s.id
,      NULL
,      NULL
,      NULL
,      NULL
  FROM Focus t
	   INNER JOIN Window w
	           ON t.WindowID = w.id
	   INNER JOIN Process p
	           ON w.ProcessID = p.id
       INNER JOIN Session s
	           ON p.SessionID = s.id
 WHERE t.IdleMilliseconds > 300000


ORDER BY DateUTC
,        TimeUTC
,        Verb ASC
,        ProcessID
,        WindowID
;


================================================================================
SELECT b.DateUTC AS BeginDateUTC
,      b.TimeUTC AS BeginTimeUTC
,      b.Bias AS BeginBias
,      e.DateUTC AS EndDateUTC
,      e.TimeUTC AS EndTimeUTC
,      e.Bias AS EndBias
,      b.Description
,      nullif(e.Description, b.Description) AS EndDescription
,      b.SessionID
,      b.ExecutableID
,      b.ProcessID
,      b.WindowID
,      b.FocusID
  FROM v_Timeline b, v_Timeline e
 WHERE b.Verb = 'begin'
   AND e.Verb = 'end'
   AND b.Subject = e.Subject
   AND ifnull(b.SessionID, 0) = ifnull(e.SessionID, 0)
   AND ifnull(b.ExecutableID, 0) = ifnull(e.ExecutableID, 0)
   AND ifnull(b.ProcessID, 0) = ifnull(e.ProcessID, 0)
   AND ifnull(b.WindowID, 0) = ifnull(e.WindowID, 0)
   AND ifnull(b.FocusID, 0) = ifnull(e.FocusID, 0)

Added SnapViewer/prj/Olam.bdsgroup.









































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="utf-8"?>
<BorlandProject>
  <PersonalityInfo>
    <Option>
      <Option Name="Personality">Default.Personality</Option>
      <Option Name="ProjectType"></Option>
      <Option Name="Version">1.0</Option>
      <Option Name="GUID">{55AC50B1-C012-46AB-912D-49D1F41A2230}</Option>
    </Option>
  </PersonalityInfo>
  <Default.Personality>
    
    <Projects>
      <Projects Name="SnapViewer.exe">SnapViewer.bdsproj</Projects>
      <Projects Name="Snapshooter.exe">..\..\..\..\Unattended\Snapshooter\src\Snapshooter.bdsproj</Projects>
      <Projects Name="Targets">SnapViewer.exe Snapshooter.exe</Projects>
    </Projects>
    <Dependencies/>
  </Default.Personality>
</BorlandProject>

Added SnapViewer/prj/SnapViewer.bdsproj.



































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
<?xml version="1.0" encoding="utf-8"?>
<BorlandProject>
	<PersonalityInfo>
		<Option>
			<Option Name="Personality">Delphi.Personality</Option>
			<Option Name="ProjectType"></Option>
			<Option Name="Version">1.0</Option>
			<Option Name="GUID">{47812981-1E15-4F6D-88CE-B13216A1E2B7}</Option>
		</Option>
	</PersonalityInfo>
	<Delphi.Personality>
		<Source>
			<Source Name="MainSource">SnapViewer.dpr</Source>
		</Source>
		<FileVersion>
			<FileVersion Name="Version">7.0</FileVersion>
		</FileVersion>
		<Compiler>
			<Compiler Name="A">8</Compiler>
			<Compiler Name="B">0</Compiler>
			<Compiler Name="C">1</Compiler>
			<Compiler Name="D">1</Compiler>
			<Compiler Name="E">0</Compiler>
			<Compiler Name="F">0</Compiler>
			<Compiler Name="G">1</Compiler>
			<Compiler Name="H">1</Compiler>
			<Compiler Name="I">1</Compiler>
			<Compiler Name="J">0</Compiler>
			<Compiler Name="K">0</Compiler>
			<Compiler Name="L">1</Compiler>
			<Compiler Name="M">0</Compiler>
			<Compiler Name="N">1</Compiler>
			<Compiler Name="O">1</Compiler>
			<Compiler Name="P">1</Compiler>
			<Compiler Name="Q">0</Compiler>
			<Compiler Name="R">0</Compiler>
			<Compiler Name="S">0</Compiler>
			<Compiler Name="T">0</Compiler>
			<Compiler Name="U">0</Compiler>
			<Compiler Name="V">1</Compiler>
			<Compiler Name="W">0</Compiler>
			<Compiler Name="X">1</Compiler>
			<Compiler Name="Y">1</Compiler>
			<Compiler Name="Z">1</Compiler>
			<Compiler Name="ShowHints">True</Compiler>
			<Compiler Name="ShowWarnings">True</Compiler>
			<Compiler Name="UnitAliases">WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;</Compiler>
			<Compiler Name="NamespacePrefix"></Compiler>
			<Compiler Name="GenerateDocumentation">False</Compiler>
			<Compiler Name="DefaultNamespace"></Compiler>
			<Compiler Name="SymbolDeprecated">True</Compiler>
			<Compiler Name="SymbolLibrary">True</Compiler>
			<Compiler Name="SymbolPlatform">True</Compiler>
			<Compiler Name="SymbolExperimental">True</Compiler>
			<Compiler Name="UnitLibrary">True</Compiler>
			<Compiler Name="UnitPlatform">True</Compiler>
			<Compiler Name="UnitDeprecated">True</Compiler>
			<Compiler Name="UnitExperimental">True</Compiler>
			<Compiler Name="HResultCompat">True</Compiler>
			<Compiler Name="HidingMember">True</Compiler>
			<Compiler Name="HiddenVirtual">True</Compiler>
			<Compiler Name="Garbage">True</Compiler>
			<Compiler Name="BoundsError">True</Compiler>
			<Compiler Name="ZeroNilCompat">True</Compiler>
			<Compiler Name="StringConstTruncated">True</Compiler>
			<Compiler Name="ForLoopVarVarPar">True</Compiler>
			<Compiler Name="TypedConstVarPar">True</Compiler>
			<Compiler Name="AsgToTypedConst">True</Compiler>
			<Compiler Name="CaseLabelRange">True</Compiler>
			<Compiler Name="ForVariable">True</Compiler>
			<Compiler Name="ConstructingAbstract">True</Compiler>
			<Compiler Name="ComparisonFalse">True</Compiler>
			<Compiler Name="ComparisonTrue">True</Compiler>
			<Compiler Name="ComparingSignedUnsigned">True</Compiler>
			<Compiler Name="CombiningSignedUnsigned">True</Compiler>
			<Compiler Name="UnsupportedConstruct">True</Compiler>
			<Compiler Name="FileOpen">True</Compiler>
			<Compiler Name="FileOpenUnitSrc">True</Compiler>
			<Compiler Name="BadGlobalSymbol">True</Compiler>
			<Compiler Name="DuplicateConstructorDestructor">True</Compiler>
			<Compiler Name="InvalidDirective">True</Compiler>
			<Compiler Name="PackageNoLink">True</Compiler>
			<Compiler Name="PackageThreadVar">True</Compiler>
			<Compiler Name="ImplicitImport">True</Compiler>
			<Compiler Name="HPPEMITIgnored">True</Compiler>
			<Compiler Name="NoRetVal">True</Compiler>
			<Compiler Name="UseBeforeDef">True</Compiler>
			<Compiler Name="ForLoopVarUndef">True</Compiler>
			<Compiler Name="UnitNameMismatch">True</Compiler>
			<Compiler Name="NoCFGFileFound">True</Compiler>
			<Compiler Name="ImplicitVariants">True</Compiler>
			<Compiler Name="UnicodeToLocale">True</Compiler>
			<Compiler Name="LocaleToUnicode">True</Compiler>
			<Compiler Name="ImagebaseMultiple">True</Compiler>
			<Compiler Name="SuspiciousTypecast">True</Compiler>
			<Compiler Name="PrivatePropAccessor">True</Compiler>
			<Compiler Name="UnsafeType">False</Compiler>
			<Compiler Name="UnsafeCode">False</Compiler>
			<Compiler Name="UnsafeCast">False</Compiler>
			<Compiler Name="OptionTruncated">True</Compiler>
			<Compiler Name="WideCharReduced">True</Compiler>
			<Compiler Name="DuplicatesIgnored">True</Compiler>
			<Compiler Name="UnitInitSeq">True</Compiler>
			<Compiler Name="LocalPInvoke">True</Compiler>
			<Compiler Name="MessageDirective">True</Compiler>
			<Compiler Name="CodePage"></Compiler>
		</Compiler>
		<Linker>
			<Linker Name="MapFile">0</Linker>
			<Linker Name="OutputObjs">0</Linker>
			<Linker Name="GenerateHpps">False</Linker>
			<Linker Name="ConsoleApp">1</Linker>
			<Linker Name="DebugInfo">False</Linker>
			<Linker Name="RemoteSymbols">False</Linker>
			<Linker Name="GenerateDRC">False</Linker>
			<Linker Name="MinStackSize">16384</Linker>
			<Linker Name="MaxStackSize">1048576</Linker>
			<Linker Name="ImageBase">4194304</Linker>
			<Linker Name="ExeDescription"></Linker>
		</Linker>
		<Directories>
			<Directories Name="OutputDir">..\Out</Directories>
			<Directories Name="UnitOutputDir">..\Out\DCU</Directories>
			<Directories Name="PackageDLLOutputDir"></Directories>
			<Directories Name="PackageDCPOutputDir"></Directories>
			<Directories Name="SearchPath">F:\MM\Code\Common\Delphi\SQLite</Directories>
			<Directories Name="Packages"></Directories>
			<Directories Name="Conditionals"></Directories>
			<Directories Name="DebugSourceDirs"></Directories>
			<Directories Name="UsePackages">False</Directories>
		</Directories>
		<Parameters>
			<Parameters Name="RunParams"></Parameters>
			<Parameters Name="HostApplication"></Parameters>
			<Parameters Name="Launcher"></Parameters>
			<Parameters Name="UseLauncher">False</Parameters>
			<Parameters Name="DebugCWD"></Parameters>
			<Parameters Name="Debug Symbols Search Path"></Parameters>
			<Parameters Name="LoadAllSymbols">True</Parameters>
			<Parameters Name="LoadUnspecifiedSymbols">False</Parameters>
		</Parameters>
		<Language>
			<Language Name="ActiveLang"></Language>
			<Language Name="ProjectLang">$00000000</Language>
			<Language Name="RootDir"></Language>
		</Language>
		<VersionInfo>
			<VersionInfo Name="IncludeVerInfo">False</VersionInfo>
			<VersionInfo Name="AutoIncBuild">False</VersionInfo>
			<VersionInfo Name="MajorVer">1</VersionInfo>
			<VersionInfo Name="MinorVer">0</VersionInfo>
			<VersionInfo Name="Release">0</VersionInfo>
			<VersionInfo Name="Build">0</VersionInfo>
			<VersionInfo Name="Debug">False</VersionInfo>
			<VersionInfo Name="PreRelease">False</VersionInfo>
			<VersionInfo Name="Special">False</VersionInfo>
			<VersionInfo Name="Private">False</VersionInfo>
			<VersionInfo Name="DLL">False</VersionInfo>
			<VersionInfo Name="Locale">1043</VersionInfo>
			<VersionInfo Name="CodePage">1252</VersionInfo>
		</VersionInfo>
		<VersionInfoKeys>
			<VersionInfoKeys Name="CompanyName"></VersionInfoKeys>
			<VersionInfoKeys Name="FileDescription"></VersionInfoKeys>
			<VersionInfoKeys Name="FileVersion">1.0.0.0</VersionInfoKeys>
			<VersionInfoKeys Name="InternalName"></VersionInfoKeys>
			<VersionInfoKeys Name="LegalCopyright"></VersionInfoKeys>
			<VersionInfoKeys Name="LegalTrademarks"></VersionInfoKeys>
			<VersionInfoKeys Name="OriginalFilename"></VersionInfoKeys>
			<VersionInfoKeys Name="ProductName"></VersionInfoKeys>
			<VersionInfoKeys Name="ProductVersion">1.0.0.0</VersionInfoKeys>
			<VersionInfoKeys Name="Comments"></VersionInfoKeys>
		</VersionInfoKeys>
	</Delphi.Personality>
	<StarTeamAssociation></StarTeamAssociation>
	<StarTeamNonRelativeFiles></StarTeamNonRelativeFiles>
</BorlandProject>

Added SnapViewer/prj/SnapViewer.cfg.

























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
-$A8
-$B-
-$C+
-$D+
-$E-
-$F-
-$G+
-$H+
-$I+
-$J-
-$K-
-$L+
-$M-
-$N+
-$O+
-$P+
-$Q-
-$R-
-$S-
-$T-
-$U-
-$V+
-$W-
-$X+
-$YD
-$Z1
-cg
-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
-H+
-W+
-M
-$M16384,1048576
-K$00400000
-E"..\Out"
-N0"..\Out\DCU"
-LE"C:\Program Files\Prog\Borland\BDS\4.0\Bin"
-LN"F:\MM\Code\Projects\Borland\Bpl"
-U"F:\MM\Code\Common\Delphi\SQLite"
-O"F:\MM\Code\Common\Delphi\SQLite"
-I"F:\MM\Code\Common\Delphi\SQLite"
-R"F:\MM\Code\Common\Delphi\SQLite"
-w-UNSAFE_TYPE
-w-UNSAFE_CODE
-w-UNSAFE_CAST

Added SnapViewer/prj/SnapViewer.dpr.

































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
program SnapViewer;

{%File '..\doc\SnapViewer.txt'}

uses
  Forms,
  F_Main in '..\src\F_Main.pas' {frmMain};

{$R *.res}

begin
  Application.Initialize;
  Application.CreateForm(TfrmMain, frmMain);
  Application.Run;
end.

Added SnapViewer/prj/SnapViewer.res.

cannot compute difference between binary files

Added SnapViewer/src/F_MainOld.dfm.

































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
object frmMain: TfrmMain
  Left = 0
  Top = 0
  Caption = 'SnapViewer'
  ClientHeight = 474
  ClientWidth = 649
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  OnCreate = FormCreate
  DesignSize = (
    649
    474)
  PixelsPerInch = 96
  TextHeight = 13
  object pnlClient: TTntPanel
    Left = 8
    Top = 8
    Width = 633
    Height = 458
    Anchors = [akLeft, akTop, akRight, akBottom]
    BevelOuter = bvNone
    TabOrder = 0
    object splHorizontal: TSplitter
      Left = 193
      Top = 0
      Width = 8
      Height = 458
      ResizeStyle = rsUpdate
    end
    object tvwTime: TTntTreeView
      Left = 0
      Top = 0
      Width = 193
      Height = 458
      Align = alLeft
      Images = imlTime
      Indent = 19
      ReadOnly = True
      TabOrder = 0
    end
    object pnlContent: TTntPanel
      Left = 201
      Top = 0
      Width = 432
      Height = 458
      Align = alClient
      BevelOuter = bvLowered
      TabOrder = 1
      ExplicitLeft = 199
      object scbChartContainer: TScrollBox
        Left = 1
        Top = 1
        Width = 430
        Height = 456
        Align = alClient
        BorderStyle = bsNone
        TabOrder = 0
        OnResize = scbChartContainerResize
        object imgChart: TImage
          Left = 0
          Top = 0
          Width = 361
          Height = 297
          AutoSize = True
          Center = True
        end
      end
    end
  end
  object imlTime: TImageList
    BlendColor = clDefault
    Left = 32
    Top = 112
  end
end

Added SnapViewer/src/F_MainOld.pas.

















































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
unit F_Main;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ImgList, ComCtrls, TntComCtrls, ExtCtrls, TntExtCtrls,
  SQLiteTable3;

type
  TfrmMain = class(TForm)
    imlTime: TImageList;
    pnlClient: TTntPanel;
    tvwTime: TTntTreeView;
    splHorizontal: TSplitter;
    pnlContent: TTntPanel;
    scbChartContainer: TScrollBox;
    imgChart: TImage;
    procedure scbChartContainerResize(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    FDB: TSQLiteDatabase;

    procedure DrawChart(Date: TDate; FocusID: TLargeInteger = 0);
  public
    { Public declarations }
  end;

var
  frmMain: TfrmMain;

implementation

{$R *.dfm}

{ ------------------------------------------------------------------------------------------------ }
procedure TfrmMain.FormCreate(Sender: TObject);
var
  Rows: TSQLiteTable;
  Node, LocationNode, SessionNode: TTntTreeNode;
  LocationIndex, SessionIndex: integer;
  TitleIndex, PathIndex, UserIndex, IdIndex, IconIndex: integer;
  Blob: TStream;
  Icon: TIcon;
begin
  FDB := TSQLiteDatabase.Create('C:\Documents and Settings\All Users\Application Data\Voronw隲Snapshooter\activity.sqlite'); // TODO

  Rows := FDB.GetTable('SELECT id, ComputerName, UserName FROM RunLocation');
  try
    while not Rows.EOF do begin
      Node := tvwTime.Items.AddObject(nil, Rows.FieldAsString('computername') + '\' + Rows.FieldAsString('username'), Pointer(Rows.FieldAsInteger('id')));
      Node.ImageIndex := -1;
      Node.SelectedIndex := Node.ImageIndex;
      Node.Data := pointer(Rows.FieldAsInteger('id'));
      Rows.Next;
    end;
  finally
    Rows.Free;
  end;

  for LocationIndex := 0 to tvwTime.Items.Count - 1 do begin
    LocationNode := tvwTime.Items[LocationIndex];
    FDB.AddParamInt(':RunLocationID', integer(LocationNode.Data));
    Rows := FDB.GetTable('SELECT id, InsertDateTime, StartupTime FROM Session WHERE RunLocationID = :RunLocationID ORDER BY coalesce(LastUpdateDateTime, InsertDateTime) DESC');
    try
      while not Rows.EOF do begin
        Node := tvwTime.Items.AddChildObject(LocationNode, Rows.FieldAsString('InsertDateTime') + ' (' + Rows.FieldAsString('StartupTime') + ')', Pointer(Rows.FieldAsInteger('id')));
        Node.ImageIndex := -1;
        Node.SelectedIndex := -1;
        Node.Data := pointer(Rows.FieldAsInteger('id'));
        Rows.Next;
      end;
    finally
      Rows.Free;
    end;

    for SessionIndex := 0 to LocationNode.Count - 1 do begin
      SessionNode := LocationNode.Item[SessionIndex];

      FDB.AddParamInt(':SessionID', integer(SessionNode.Data));
      Rows := FDB.GetTable( 'SELECT f.id, f.insertdatetime, f.title, e.path, nullif(p.UserName, rl.UserName) as username, coalesce(w.icon, e.icon) AS icon, f.idleMilliseconds, s.id AS SessionID'
                            + '  FROM Focus f'
                            + '       INNER JOIN Window w ON f.windowid = w.id'
                            + '       INNER JOIN Process p ON w.ProcessID = p.id'
                            + '       INNER JOIN Executable e ON p.ExecutableID = e.id'
                            + '       INNER JOIN Session s ON p.SessionID = s.id'
                            + '       INNER JOIN RunLocation rl ON s.runlocationid = rl.id'
//                              + ' WHERE s.id = :SessionID' // BUG?!?: any WHERE clause seems to yield only 1 row
                            + ' ORDER BY substr(coalesce(f.updatedatetime, f.insertdatetime), 1, 10) DESC, substr(coalesce(f.updatedatetime, f.insertdatetime), 12) ASC');
      try
        if not Rows.EOF then begin
          TitleIndex := Rows.FieldIndex['title'];
          PathIndex := Rows.FieldIndex['path'];
          UserIndex := Rows.FieldIndex['username'];
          IDIndex := Rows.FieldIndex['id'];
          IconIndex := Rows.FieldIndex['icon'];
          while not Rows.EOF do begin
            // WORKAROUND: since the WHERE-clause doesn't seem to work, we'll check the condition here
            if Rows.FieldAsInteger('SessionID') = integer(SessionNode.Data) then begin
              Node := tvwTime.Items.AddChildObject(SessionNode,
                                                  Format('%s %s (%s; %s)',
                                                        [Copy(Rows.FieldAsString('insertdatetime'), 12, 5),
                                                         Rows.FieldAsString(TitleIndex),
                                                         ExtractFileName(Rows.FieldAsString(PathIndex)),
                                                         Rows.FieldAsString(UserIndex)]),
                                                  Pointer(Rows.FieldAsInteger(IdIndex)));
              Blob := Rows.FieldAsBlob(IconIndex);
              if Assigned(Blob) and (Blob.Size > 0) then begin
                Icon := TIcon.Create;
                try
                  try
                    Blob.Position := 0;
                    Icon.LoadFromStream(Blob);
                    Node.ImageIndex := tvwTime.Images.AddIcon(Icon);
                    Node.SelectedIndex := Node.ImageIndex;
                  except
                    Node.ImageIndex := -1;
                    Node.SelectedIndex := -1;
                  end;
                finally
                  Icon.Free;
                end;
              end else begin
                Node.ImageIndex := -1;
                Node.SelectedIndex := -1;
              end;
            end{if SessionID};
            Rows.Next;
          end;
        end;
      finally
        Rows.Free;
      end;
    end{for SessionIndex};
  end{for LocationIndex};

  tvwTime.Items[0].Expand(True);
end;

{ ------------------------------------------------------------------------------------------------ }
procedure TfrmMain.scbChartContainerResize(Sender: TObject);
begin
  DrawChart(Date);
end;

{ ------------------------------------------------------------------------------------------------ }
procedure TfrmMain.DrawChart(Date: TDate; FocusID: TLargeInteger = 0);
var
  Rows: TSQLiteTable;
  First, Last: TDateTime;
  Bmp: TBitmap;
begin
  Bmp := TBitmap.Create;
  try
    FDB.AddParamDate(':Date', Date);
    Rows := FDB.GetTable( 'SELECT min(TimeUTC) AS first'
                        + ',      max(TimeUTC) AS last'
                        + '  FROM v_Timeline'
                        + ' WHERE DateUTC = :Date');
    try
      if Rows.Count = 1 then begin
        First :=  Rows.FieldAsDateTime('first');
        Last :=   Rows.FieldAsDateTime('last');
      end else begin
        First := 0;
        Last  := 0;
      end;
    finally
      Rows.Free;
    end;

    Bmp.Height := Bmp.Canvas.TextHeight('|') * Round((Last - First) / 96);

  finally
    imgChart.Picture.Assign(Bmp);
    Bmp.Free;
  end;
end;



end.

Added SnapViewer/src/MainForm.dfm.















































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 429
  ClientWidth = 713
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object Splitter1: TSplitter
    Left = 185
    Top = 0
    Width = 8
    Height = 429
  end
  object Panel1: TPanel
    Left = 0
    Top = 0
    Width = 185
    Height = 429
    Align = alLeft
    BevelOuter = bvNone
    TabOrder = 0
    ExplicitLeft = 2
    object TreeView1: TTreeView
      AlignWithMargins = True
      Left = 3
      Top = 3
      Width = 179
      Height = 423
      Align = alClient
      Indent = 19
      TabOrder = 0
      Items.NodeData = {
        0301000000260000000000000000000000FFFFFFFFFFFFFFFF00000000000000
        0001000000010432003000300038003E0000000000000000000000FFFFFFFFFF
        FFFFFF00000000000000000000000001103000310020002800310020006A0061
        006E002D00370020006A0061006E002900}
      ExplicitLeft = 16
      ExplicitTop = 48
      ExplicitWidth = 121
      ExplicitHeight = 97
    end
  end
  object Panel2: TPanel
    Left = 193
    Top = 0
    Width = 520
    Height = 429
    Align = alClient
    BevelOuter = bvNone
    TabOrder = 1
    ExplicitLeft = 312
    ExplicitTop = 120
    ExplicitWidth = 137
    ExplicitHeight = 169
    object Splitter2: TSplitter
      Left = 0
      Top = 336
      Width = 520
      Height = 8
      Cursor = crVSplit
      Align = alBottom
      ExplicitTop = 41
    end
    object PaintBox1: TPaintBox
      Left = 208
      Top = 160
      Width = 105
      Height = 105
    end
    object Panel4: TPanel
      Left = 0
      Top = 344
      Width = 520
      Height = 85
      Align = alBottom
      BevelInner = bvLowered
      TabOrder = 0
    end
    object ScrollBox1: TScrollBox
      Left = 0
      Top = 0
      Width = 520
      Height = 336
      Align = alClient
      Color = clBtnFace
      ParentColor = False
      TabOrder = 1
      ExplicitLeft = 1
      ExplicitTop = 1
      ExplicitWidth = 518
      ExplicitHeight = 334
      object Panel3: TPanel
        Left = 0
        Top = 0
        Width = 457
        Height = 305
        BevelOuter = bvNone
        Color = clWindow
        ParentBackground = False
        TabOrder = 0
        DesignSize = (
          457
          305)
        object Panel5: TPanel
          Left = 16
          Top = 16
          Width = 73
          Height = 273
          TabOrder = 0
        end
        inline fraTimeline1: TfraTimeline
          Left = 136
          Top = 0
          Width = 156
          Height = 305
          Anchors = [akLeft, akTop, akBottom]
          Color = clBtnFace
          ParentBackground = False
          ParentColor = False
          TabOrder = 1
          ExplicitLeft = 136
          ExplicitHeight = 305
        end
      end
    end
  end
end

Added SnapViewer/src/MainForm.pas.







































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
unit MainForm;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, ComCtrls, TimelineFrame;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    Splitter1: TSplitter;
    Panel2: TPanel;
    TreeView1: TTreeView;
    Splitter2: TSplitter;
    Panel4: TPanel;
    ScrollBox1: TScrollBox;
    Panel3: TPanel;
    Panel5: TPanel;
    PaintBox1: TPaintBox;
    fraTimeline1: TfraTimeline;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

end.

Added SnapViewer/src/SnapViewer.dpr.































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
program SnapViewer;

uses
  Forms,
  MainForm in 'MainForm.pas' {Form1},
  TimelineFrame in 'TimelineFrame.pas' {fraTimeline: TFrame};

{$R *.res}

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

Added SnapViewer/src/SnapViewer.dproj.





































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
	<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
		<PropertyGroup>
			<ProjectGuid>{39CAD32E-64D9-4F14-B380-77BE7551F673}</ProjectGuid>
			<ProjectVersion>12.0</ProjectVersion>
			<MainSource>SnapViewer.dpr</MainSource>
			<Config Condition="'$(Config)'==''">Debug</Config>
			<DCC_DCCCompiler>DCC32</DCC_DCCCompiler>
		</PropertyGroup>
		<PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
			<Base>true</Base>
		</PropertyGroup>
		<PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_1)'!=''">
			<Cfg_1>true</Cfg_1>
			<CfgParent>Base</CfgParent>
			<Base>true</Base>
		</PropertyGroup>
		<PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_2)'!=''">
			<Cfg_2>true</Cfg_2>
			<CfgParent>Base</CfgParent>
			<Base>true</Base>
		</PropertyGroup>
		<PropertyGroup Condition="'$(Base)'!=''">
			<DCC_DcuOutput>..\out\DCU\</DCC_DcuOutput>
			<DCC_ExeOutput>..\out\</DCC_ExeOutput>
			<DCC_UnitSearchPath>..\..\..\..\..\..\_Common\Delphi;..\..\..\..\..\..\_Common\Delphi\PNGImage;..\..\..\..\..\..\_Common\Delphi\SQLite;$(DCC_UnitSearchPath)</DCC_UnitSearchPath>
			<DCC_DependencyCheckOutputName>..\out\SnapViewer.exe</DCC_DependencyCheckOutputName>
			<DCC_ImageBase>00400000</DCC_ImageBase>
			<DCC_UnitAlias>WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;$(DCC_UnitAlias)</DCC_UnitAlias>
			<DCC_Platform>x86</DCC_Platform>
			<DCC_E>false</DCC_E>
			<DCC_N>false</DCC_N>
			<DCC_S>false</DCC_S>
			<DCC_F>false</DCC_F>
			<DCC_K>false</DCC_K>
		</PropertyGroup>
		<PropertyGroup Condition="'$(Cfg_1)'!=''">
			<DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
			<DCC_Define>RELEASE;$(DCC_Define)</DCC_Define>
			<DCC_SymbolReferenceInfo>0</DCC_SymbolReferenceInfo>
			<DCC_DebugInformation>false</DCC_DebugInformation>
		</PropertyGroup>
		<PropertyGroup Condition="'$(Cfg_2)'!=''">
			<DCC_Define>DEBUG;$(DCC_Define)</DCC_Define>
		</PropertyGroup>
		<ItemGroup>
			<DelphiCompile Include="SnapViewer.dpr">
				<MainSource>MainSource</MainSource>
			</DelphiCompile>
			<DCCReference Include="MainForm.pas">
				<Form>Form1</Form>
			</DCCReference>
			<DCCReference Include="TimelineFrame.pas">
				<Form>fraTimeline</Form>
				<DesignClass>TFrame</DesignClass>
			</DCCReference>
			<BuildConfiguration Include="Base">
				<Key>Base</Key>
			</BuildConfiguration>
			<BuildConfiguration Include="Debug">
				<Key>Cfg_2</Key>
				<CfgParent>Base</CfgParent>
			</BuildConfiguration>
			<BuildConfiguration Include="Release">
				<Key>Cfg_1</Key>
				<CfgParent>Base</CfgParent>
			</BuildConfiguration>
		</ItemGroup>
		<Import Project="$(BDS)\Bin\CodeGear.Delphi.Targets" Condition="Exists('$(BDS)\Bin\CodeGear.Delphi.Targets')"/>
		<ProjectExtensions>
			<Borland.Personality>Delphi.Personality.12</Borland.Personality>
			<Borland.ProjectType/>
			<BorlandProject>
				<Delphi.Personality>
					<Parameters>
						<Parameters Name="UseLauncher">False</Parameters>
						<Parameters Name="LoadAllSymbols">True</Parameters>
						<Parameters Name="LoadUnspecifiedSymbols">False</Parameters>
					</Parameters>
					<VersionInfo>
						<VersionInfo Name="IncludeVerInfo">False</VersionInfo>
						<VersionInfo Name="AutoIncBuild">False</VersionInfo>
						<VersionInfo Name="MajorVer">1</VersionInfo>
						<VersionInfo Name="MinorVer">0</VersionInfo>
						<VersionInfo Name="Release">0</VersionInfo>
						<VersionInfo Name="Build">0</VersionInfo>
						<VersionInfo Name="Debug">False</VersionInfo>
						<VersionInfo Name="PreRelease">False</VersionInfo>
						<VersionInfo Name="Special">False</VersionInfo>
						<VersionInfo Name="Private">False</VersionInfo>
						<VersionInfo Name="DLL">False</VersionInfo>
						<VersionInfo Name="Locale">1043</VersionInfo>
						<VersionInfo Name="CodePage">1252</VersionInfo>
					</VersionInfo>
					<VersionInfoKeys>
						<VersionInfoKeys Name="CompanyName"/>
						<VersionInfoKeys Name="FileDescription"/>
						<VersionInfoKeys Name="FileVersion">1.0.0.0</VersionInfoKeys>
						<VersionInfoKeys Name="InternalName"/>
						<VersionInfoKeys Name="LegalCopyright"/>
						<VersionInfoKeys Name="LegalTrademarks"/>
						<VersionInfoKeys Name="OriginalFilename"/>
						<VersionInfoKeys Name="ProductName"/>
						<VersionInfoKeys Name="ProductVersion">1.0.0.0</VersionInfoKeys>
						<VersionInfoKeys Name="Comments"/>
					</VersionInfoKeys>
					<Source>
						<Source Name="MainSource">SnapViewer.dpr</Source>
					</Source>
				</Delphi.Personality>
				<ModelSupport>False</ModelSupport>
			</BorlandProject>
			<ProjectFileVersion>12</ProjectFileVersion>
		</ProjectExtensions>
	</Project>

Added SnapViewer/src/SnapViewer.res.

cannot compute difference between binary files

Added SnapViewer/src/TimelineFrame.dfm.





































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
object fraTimeline: TfraTimeline
  Left = 0
  Top = 0
  Width = 156
  Height = 328
  TabOrder = 0
  DesignSize = (
    156
    328)
  object imgIcon: TImage
    Left = 0
    Top = 0
    Width = 32
    Height = 32
  end
  object Label1: TLabel
    Left = 32
    Top = 0
    Width = 124
    Height = 32
    Alignment = taCenter
    Anchors = [akLeft, akTop, akRight]
    AutoSize = False
    Caption = 'Application caption'
    Color = clInactiveCaption
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clInactiveCaptionText
    Font.Height = -11
    Font.Name = 'Tahoma'
    Font.Style = []
    ParentColor = False
    ParentFont = False
  end
end

Added SnapViewer/src/TimelineFrame.pas.















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
unit TimelineFrame;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
  Dialogs, StdCtrls, ExtCtrls;

type
  TfraTimeline = class(TFrame)
    imgIcon: TImage;
    Label1: TLabel;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

implementation

{$R *.dfm}

end.

Added SnapViewer/src/activity.pas.



















































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
unit Activity;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, sqlite3conn, sqldb, graphics, db, controls;

type

  TProcess = class;
  TScreenshot = class;
  TWindow = class;

  { TActivityDay }

  TActivityDay = class
  private
    FDB: TSQLite3Connection;
    FDate: TDateTime;
    FFirstActivity: TDateTime;
    FLastActivity: TDateTime;
    FProcesses: TList;
    FScreenshots: TList;

    function GetProcessCount: integer;
    function GetProcess(Index: integer): TProcess;
    function GetScreenshotCount: integer;
    function GetScreenshot(Index: integer): TScreenshot;
  public
    constructor Create(DB: TSQLite3Connection; Date: TDateTime);
    destructor  Destroy; override;

    procedure Paint(Canvas: TCanvas; Container: TWinControl);

    property Date: TDateTime                          read FDate;
    property FirstActivityTime: TDateTime             read FFirstActivity;
    property LastActivityTime: TDateTime              read FLastActivity;
    property ProcessCount: integer                    read GetProcessCount;
    property Processes[Index: integer]: TProcess      read GetProcess;
    property ScreenshotCount: integer                 read GetScreenshotCount;
    property Screenshots[Index: integer]: TScreenshot read GetScreenshot;
  end;

  { TProcess }

  TProcess = class
  private
    FDB: TSQLite3Connection;
    FID: integer;
    FExeName: string;
    FIcon: TIcon;
    FTitle: string;
    FStartTime: TDateTime;
    FEndTime: TDateTime;
    FWindows: TList;

    function GetIcon: TIcon;
    function GetWindowCount: integer;
    function GetWindow(Index: integer): TWindow;
  public
    constructor Create(FRow: TSQLQuery);
    destructor  Destroy; override;

    property ExeName: string                  read FExeName;
    property Title: string                    read FTitle;
    property Icon: TIcon                      read GetIcon;
    property StartTime: TDateTime             read FStartTime;
    property EndTime: TDateTime               read FEndTime;
    property WindowCount: integer             read GetWindowCount;
    property Windows[Index: integer]: TWindow read GetWindow;
  end;

  TWindow = class
  private
    FDB: TSQLite3Connection;
    FID: integer;
    FTitle: string;
    FClassName: string;
    FIcon: TIcon;
    FStartTime: TDateTime;
    FEndTime: TDateTime;
    FScreenshots: TList;

    function GetIcon: TIcon;
    function GetShotCount: integer;
    function GetShot(Index: integer): TScreenshot;
  public
    constructor Create(FRow: TSQLQuery);
    destructor  Destroy; override;

    property Title: string                            read FTitle;
    property Icon: TIcon                              read GetIcon;
    property StartTime: TDateTime                     read FStartTime;
    property EndTime: TDateTime                       read FEndTime;
    property ScreenshotCount: integer                 read GetShotCount;
    property Screenshots[Index: integer]: TScreenshot read GetShot;
  end;

  TScreenshot = class
  private
    FDB: TSQLite3Connection;
    FID: integer;
    FCaption: string;
    FTimestamp: TDateTime;
    FPicture: TPicture;

    function GetPicture: TPicture;
  public
    constructor Create(FRow: TSQLQuery);
    destructor  Destroy; override;

    property Caption: string        read FCaption;
    property Timestamp: TDateTime   read FTimestamp;
    property Picture: TPicture      read GetPicture;
  end;

implementation
uses
  DateUtils, Math;


{ TActivityDay }

constructor TActivityDay.Create(DB: TSQLite3Connection; Date: TDateTime);
var
  Query: TSQLQuery;
begin
  FDB := DB;

  Query := TSQLQuery.Create(nil);
  try
    Query.DataBase := DB;
    Query.Transaction := DB.Transaction;
    Query.SQL.Text := 'SELECT * FROM Processes WHERE InsertDateTime BETWEEN :Date AND :NextDate';
    Query.Params.CreateParam(ftString, ':Date', ptInput);
    Query.Params.CreateParam(ftString, ':NextDate, ptInput);
  finally
    Query.Free;
  end;
end;

destructor TActivityDay.Destroy;
begin
  inherited Destroy;
end;

function TActivityDay.GetProcessCount: integer;
begin
  Result := FProcesses.Count;
end;

function TActivityDay.GetProcess(Index: integer): TProcess;
begin
  Result := TProcess(FProcesses[Index]);
end;

function TActivityDay.GetScreenshotCount: integer;
begin
  Result := FScreenshots.Count;
end;

function TActivityDay.GetScreenshot(Index: integer): TScreenshot;
begin
  Result := TScreenshot(FScreenshots[Index]);
end;

procedure TActivityDay.Paint(Canvas: TCanvas; Container: TWinControl);
var
  StartTime, StopTime: TDateTime;
  Duration: Integer;
begin
  // TODO: eerst kijken hoeveel tijd weergegeven moet worden ==> dat bepaalt de hoogte van de container
  if FFirstActivity < FDate then
    StartTime := FDate
  else
    StartTime := FFirstActivity;

  if FLastActivity > (FDate + 1) then
    StopTime := FDate + 1
  else
    StopTime := FLastActivity;

  Duration := Ceil(MinuteSpan(StopTime, StartTime));
  Duration := Duration / 15 * Canvas.GetTextHeight('|TextHeight|'); // op het kwartier nauwkeurig, waarbij 1 kwartier ~= 1 regel tekst

  Container.Height := Duration;

  // TODO: dan kijken hoeveel processen er maximaal tegelijkertijd getoond moeten worden;
  //  dat bepaalt de breedte van elk proces en/of de breedte van de container
  // TODO: maak hier een recursieve functie van...
  MaxCount := 0;
  for i := 0 to Self.ProcessCount - 1 do begin
    // TODO: kijk nu welke andere processen er overlappen

  end;
end;

end.

Added SnapViewer/src/f_main.lfm.













































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
object frmMain: TfrmMain
  Left = 318
  Height = 484
  Top = 188
  Width = 680
  Caption = 'Snapshot viewer'
  ClientHeight = 484
  ClientWidth = 680
  OnActivate = FormActivate
  OnCreate = FormCreate
  OnDeactivate = FormDeactivate
  Position = poScreenCenter
  LCLVersion = '0.9.28.2'
  object pspLeftRight: TPairSplitter
    Left = 0
    Height = 461
    Top = 0
    Width = 680
    Align = alClient
    Position = 288
    object pssLeft: TPairSplitterSide
      Cursor = crArrow
      Left = 0
      Height = 461
      Top = 0
      Width = 288
      ClientWidth = 288
      ClientHeight = 461
      object tvwPeriod: TTreeView
        Left = 0
        Height = 461
        Top = 0
        Width = 288
        Align = alClient
        DefaultItemHeight = 17
        ReadOnly = True
        TabOrder = 0
        OnDeletion = tvwPeriodDeletion
        OnSelectionChanged = tvwPeriodSelectionChanged
        Options = [tvoAutoItemHeight, tvoHideSelection, tvoKeepCollapsedNodes, tvoReadOnly, tvoShowButtons, tvoShowLines, tvoShowRoot, tvoToolTips]
        Items.Data = {
          F9FFFFFF020002000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF050000000000
          000001070000005765656B203334FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000
          00000000000000130000006D61616E646167203233206175677573747573FFFF
          FFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000001300000064696E7364
          6167203234206175677573747573FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000
          0000000000000014000000776F656E73646167203235206175677573747573FF
          FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000000015000000646F6E64
          6572646167203236206175677573747573FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
          FF000000000000000000130000007672696A6461672032372061756775737475
          73FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF050000000000000001070000005765
          656B203335FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000001300
          00006D61616E646167203330206175677573747573FFFFFFFFFFFFFFFFFFFFFF
          FFFFFFFFFF0000000000000000001300000064696E7364616720333120617567
          7573747573FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000001400
          0000776F656E7364616720312073657074656D626572FFFFFFFFFFFFFFFFFFFF
          FFFFFFFFFFFF00000000000000000015000000646F6E64657264616720322073
          657074656D626572FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000
          00130000007672696A64616720332073657074656D626572
        }
      end
    end
    object pssRight: TPairSplitterSide
      Cursor = crArrow
      Left = 293
      Height = 461
      Top = 0
      Width = 387
      ClientWidth = 387
      ClientHeight = 461
      object pspTopBottom: TPairSplitter
        Cursor = crVSplit
        Left = 0
        Height = 461
        Top = 0
        Width = 387
        Align = alClient
        Position = 232
        SplitterType = pstVertical
        object pssTop: TPairSplitterSide
          Cursor = crArrow
          Left = 0
          Height = 232
          Top = 0
          Width = 387
          ClientWidth = 387
          ClientHeight = 232
          object scbContents: TScrollBox
            Left = 0
            Height = 232
            Top = 0
            Width = 387
            Align = alClient
            ClientHeight = 228
            ClientWidth = 383
            TabOrder = 0
            object pbxActivity: TPaintBox
              Left = 0
              Height = 150
              Top = 0
              Width = 383
              Align = alTop
              OnClick = pbxActivityClick
              OnPaint = pbxActivityPaint
            end
          end
        end
        object pssBottom: TPairSplitterSide
          Cursor = crArrow
          Left = 0
          Height = 224
          Top = 237
          Width = 387
          ClientWidth = 387
          ClientHeight = 224
          object pnlViewer: TPanel
            Left = 0
            Height = 224
            Top = 0
            Width = 387
            Align = alClient
            BevelOuter = bvLowered
            ClientHeight = 224
            ClientWidth = 387
            TabOrder = 0
            object imgSnapshot: TImage
              Left = 1
              Height = 222
              Top = 1
              Width = 385
              Align = alClient
              Proportional = True
              Stretch = True
            end
          end
        end
      end
    end
  end
  object sbrMain: TStatusBar
    Left = 0
    Height = 23
    Top = 461
    Width = 680
    Panels = <    
      item
        Width = 300
      end    
      item
        Text = 'SQLite v0.0'
        Width = 100
      end    
      item
        Text = 'No snapshots'
        Width = 300
      end>
    SimplePanel = False
  end
  object cnnDB: TSQLite3Connection
    Connected = False
    LoginPrompt = False
    DatabaseName = 'C:\Documents and Settings\All Users\Application Data\Voronw毛\Snapshooter\activity.sqlite'
    KeepConnection = False
    Transaction = SQLTransaction1
    Options = []
    left = 24
    top = 402
  end
  object SQLTransaction1: TSQLTransaction
    Active = False
    Action = caNone
    Database = cnnDB
    left = 96
    top = 402
  end
  object qryPeriods: TSQLQuery
    IndexName = 'DEFAULT_ORDER'
    AutoCalcFields = False
    Database = cnnDB
    Transaction = SQLTransaction1
    ReadOnly = True
    SQL.Strings = (
      '  SELECT 0 + strftime(''%Y'', coalesce(UpdateDateTime, InsertDateTime)) AS year'
      '  ,      0 + strftime(''%W'', coalesce(UpdateDateTime, InsertDateTime)) AS week'
      '  ,      date(MIN(coalesce(UpdateDateTime, InsertDateTime))) AS first_day'
      '  ,      date(MAX(coalesce(UpdateDateTime, InsertDateTime))) AS last_day'
      '    FROM Focus'
      'GROUP BY year'
      ',        week'
      'ORDER BY year DESC'
      ',        week DESC;'
    )
    Params = <>
    UpdateMode = upWhereKeyOnly
    left = 168
    top = 402
  end
end

Added SnapViewer/src/f_main.pas.





























































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
unit F_Main;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, sqlite3conn, sqldb, FileUtil, LResources, Forms,
  Controls, Graphics, Dialogs, ComCtrls, PairSplitter, ExtCtrls;

type

  { TfrmMain }

  TfrmMain = class(TForm)
    imgSnapshot: TImage;
    pnlViewer: TPanel;
    pspLeftRight: TPairSplitter;
    pspTopBottom: TPairSplitter;
    pssLeft: TPairSplitterSide;
    pssRight: TPairSplitterSide;
    pssTop: TPairSplitterSide;
    pssBottom: TPairSplitterSide;
    pbxActivity: TPaintBox;
    sbrMain: TStatusBar;
    scbContents: TScrollBox;
    cnnDB: TSQLite3Connection;
    qryPeriods: TSQLQuery;
    SQLTransaction1: TSQLTransaction;
    tvwPeriod: TTreeView;
    procedure FormActivate(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDeactivate(Sender: TObject);
    procedure pbxActivityClick(Sender: TObject);
    procedure pbxActivityPaint(Sender: TObject);
    procedure tvwPeriodDeletion(Sender: TObject; Node: TTreeNode);
    procedure tvwPeriodSelectionChanged(Sender: TObject);
  private
    FSelDate: TDate;

    procedure FillPeriods;
    { private declarations }
  public
    { public declarations }
  end; 

var
  frmMain: TfrmMain;

implementation
uses
  SQLite3db, dateutils;

{ TfrmMain }

procedure TfrmMain.FormCreate(Sender: TObject);
var
  Query: TSQLQuery;
begin
  Self.DoubleBuffered := True;

  Query := TSQLQuery.Create(nil);
  try
    Query.DataBase := cnnDB;
    Query.Transaction := SQLTransaction1;
    Query.ReadOnly := True;
    Query.SQL.Add('SELECT sqlite_version()');
    Query.Active := True;
    if not Query.EOF then begin
      sbrMain.Panels[1].Text := 'SQLite v' + Query.Fields[0].AsString;
    end;
  finally
    Query.Free;
  end;

  FillPeriods;
end;

procedure TfrmMain.FormActivate(Sender: TObject);
begin
  pbxActivity.Invalidate;
end;

procedure TfrmMain.FormDeactivate(Sender: TObject);
begin
  pbxActivity.Invalidate;
end;

procedure TfrmMain.pbxActivityClick(Sender: TObject);
begin

end;

procedure TfrmMain.pbxActivityPaint(Sender: TObject);
begin
  if FSelDate = 0 then begin
    Exit;
  end;

  if Self.Active then begin
    pbxActivity.Canvas.Brush.Color := clHighlight;
    pbxActivity.Canvas.FillRect(pbxActivity.BoundsRect);
    pbxActivity.Canvas.Font.Color := clHighlightText;
  end else begin
    pbxActivity.Canvas.Brush.Color := clBtnFace;
    pbxActivity.Canvas.Font.Color := clBtnText;
  end;
  pbxActivity.Canvas.TextOut(0, 0, DateToStr(FSelDate));
end;

procedure TfrmMain.tvwPeriodDeletion(Sender: TObject; Node: TTreeNode);
begin
  if Assigned(Node.Data) then begin
    Dispose(PDate(Node.Data));
  end;
end;

procedure TfrmMain.tvwPeriodSelectionChanged(Sender: TObject);
var
  SelDate: TDate;
  Rows: TSQLQuery;
begin
  if Assigned(tvwPeriod.Selected) and Assigned(tvwPeriod.Selected.Data) then begin
    SelDate := PDate(tvwPeriod.Selected.Data)^;
    if SelDate <> FSelDate then begin
      FSelDate := SelDate;
      sbrMain.Panels[2].Text := FormatDateTime('dddddd', FSelDate);

      // TODO: select the appropriate data

      pbxActivity.Invalidate;
      pssRight.Show;
    end;
  end else begin
    if FSelDate <> 0 then begin
      pssRight.Hide;
      FSelDate := 0;
      sbrMain.Panels[2].Text := '(no snapshots)';
    end;
  end;
end;

procedure TfrmMain.FillPeriods;
var
  PrevYear, Year, Week: integer;
  nodeYear, nodeWeek, nodeDay: TTreeNode;
  FirstDay, LastDay: string;
  FirstDate, LastDate, ThisDate: TDate;
  IntDate: integer;
  PThisDate: PDate;
begin
  tvwPeriod.Items.Clear;

  PrevYear := -1;

  qryPeriods.Active:= True;
  try
    while not qryPeriods.EOF do begin
      Year := qryPeriods.FieldByName('year').AsInteger;
      Week := qryPeriods.FieldByName('week').AsInteger;

      if Week = 0 then begin
        Dec(Year);
        Week := 53;
      end;
      if Year <> PrevYear then begin
        nodeYear := tvwPeriod.Items.Add(nil, IntToStr(Year));
        PrevYear := Year;
      end;
      nodeWeek := tvwPeriod.Items.AddChild(nodeYear, Format('Week %d', [Week]));
      qryPeriods.Next;

      FirstDay := qryPeriods.FieldByName('first_day').AsString;
      FirstDate := EncodeDate(StrToInt(Copy(FirstDay, 1, 4)), StrToInt(Copy(
        FirstDay, 6, 2)), StrToInt(Copy(FirstDay, 9, 2)));

      LastDay := qryPeriods.FieldByName('last_day').AsString;
      LastDate := EncodeDate(StrToInt(Copy(FirstDay, 1, 4)), StrToInt(Copy(
        LastDay, 6, 2)), StrToInt(Copy(LastDay, 9, 2)));

      for IntDate := Trunc(FirstDate) to Trunc(LastDate) do begin
        ThisDate := TDateTime(IntDate);
        nodeDay := tvwPeriod.Items.AddChild(nodeWeek, FormatDateTime('dddddd',
          ThisDate));
        New(PThisDate);
        PThisDate^ := ThisDate;
        nodeDay.Data := PThisDate;
        if ThisDate = Date then begin
           nodeDay.Expand(True);
           tvwPeriod.Selected := nodeDay;
        end{if};
      end{for};
    end{while};
  finally
    qryPeriods.Active := False;
  end;
  if (tvwPeriod.Items.Count > 0) and (tvwPeriod.Selected = nil) then begin
     tvwPeriod.Selected := tvwPeriod.Items.Item[0];
  end;
end;

initialization
  {$I f_main.lrs}

end.

Added SnapViewer/src/prj/fpc/SnapViewer.ico.

cannot compute difference between binary files

Added SnapViewer/src/prj/fpc/SnapViewer.lpi.











































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
<?xml version="1.0"?>
<CONFIG>
  <ProjectOptions>
    <PathDelim Value="\"/>
    <Version Value="7"/>
    <General>
      <MainUnit Value="0"/>
      <TargetFileExt Value=".exe"/>
      <Title Value="SnapViewer"/>
      <Icon Value="0"/>
      <UseXPManifest Value="True"/>
      <ActiveEditorIndexAtStart Value="2"/>
    </General>
    <VersionInfo>
      <UseVersionInfo Value="True"/>
      <AutoIncrementBuild Value="True"/>
      <CurrentMajorRevNr Value="1"/>
      <CurrentBuildNr Value="77"/>
      <Comments Value="http://martijn.coppoolse.com/software/"/>
      <CompanyName Value="Voronw毛"/>
      <InternalName Value="SnapViewer"/>
      <LegalCopyright Value="漏 Martijn Coppoolse"/>
      <OriginalFilename Value="snapviewer"/>
      <ProductName Value="TimeSnapshooter"/>
    </VersionInfo>
    <PublishOptions>
      <Version Value="2"/>
      <IgnoreBinaries Value="False"/>
      <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
      <ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
    </PublishOptions>
    <RunParams>
      <local>
        <FormatVersion Value="1"/>
        <LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
      </local>
    </RunParams>
    <RequiredPackages Count="3">
      <Item1>
        <PackageName Value="FCL"/>
        <MinVersion Major="1" Valid="True"/>
      </Item1>
      <Item2>
        <PackageName Value="SQLDBLaz"/>
        <MinVersion Major="1" Release="1" Valid="True"/>
      </Item2>
      <Item3>
        <PackageName Value="LCL"/>
      </Item3>
    </RequiredPackages>
    <Units Count="5">
      <Unit0>
        <Filename Value="SnapViewer.lpr"/>
        <IsPartOfProject Value="True"/>
        <UnitName Value="SnapViewer"/>
        <CursorPos X="93" Y="10"/>
        <TopLine Value="1"/>
        <EditorIndex Value="0"/>
        <UsageCount Value="28"/>
        <Loaded Value="True"/>
      </Unit0>
      <Unit1>
        <Filename Value="..\..\f_main.pas"/>
        <IsPartOfProject Value="True"/>
        <ComponentName Value="frmMain"/>
        <ResourceBaseClass Value="Form"/>
        <UnitName Value="F_Main"/>
        <CursorPos X="1" Y="1"/>
        <TopLine Value="1"/>
        <EditorIndex Value="1"/>
        <UsageCount Value="28"/>
        <Loaded Value="True"/>
      </Unit1>
      <Unit2>
        <Filename Value="..\..\activity.pas"/>
        <IsPartOfProject Value="True"/>
        <UnitName Value="Activity"/>
        <CursorPos X="64" Y="8"/>
        <TopLine Value="1"/>
        <EditorIndex Value="2"/>
        <UsageCount Value="25"/>
        <Loaded Value="True"/>
      </Unit2>
      <Unit3>
        <Filename Value="..\..\..\..\..\..\..\..\..\Run\Prog\IDE\Lazarus\lcl\controls.pp"/>
        <UnitName Value="Controls"/>
        <CursorPos X="3" Y="77"/>
        <TopLine Value="58"/>
        <UsageCount Value="10"/>
      </Unit3>
      <Unit4>
        <Filename Value="..\..\..\..\..\..\..\..\..\Run\Prog\IDE\Lazarus\fpc\2.2.4\source\packages\fcl-db\src\base\db.pas"/>
        <UnitName Value="db"/>
        <CursorPos X="35" Y="1657"/>
        <TopLine Value="1638"/>
        <UsageCount Value="10"/>
      </Unit4>
    </Units>
    <JumpHistory Count="30" HistoryIndex="29">
      <Position1>
        <Filename Value="..\..\f_main.pas"/>
        <Caret Line="101" Column="24" TopLine="91"/>
      </Position1>
      <Position2>
        <Filename Value="..\..\f_main.pas"/>
        <Caret Line="102" Column="28" TopLine="91"/>
      </Position2>
      <Position3>
        <Filename Value="..\..\f_main.pas"/>
        <Caret Line="112" Column="5" TopLine="91"/>
      </Position3>
      <Position4>
        <Filename Value="..\..\f_main.pas"/>
        <Caret Line="175" Column="31" TopLine="156"/>
      </Position4>
      <Position5>
        <Filename Value="..\..\f_main.pas"/>
        <Caret Line="102" Column="3" TopLine="75"/>
      </Position5>
      <Position6>
        <Filename Value="..\..\f_main.pas"/>
        <Caret Line="86" Column="3" TopLine="78"/>
      </Position6>
      <Position7>
        <Filename Value="..\..\activity.pas"/>
        <Caret Line="21" Column="43" TopLine="14"/>
      </Position7>
      <Position8>
        <Filename Value="..\..\activity.pas"/>
        <Caret Line="87" Column="46" TopLine="50"/>
      </Position8>
      <Position9>
        <Filename Value="..\..\activity.pas"/>
        <Caret Line="14" Column="14" TopLine="1"/>
      </Position9>
      <Position10>
        <Filename Value="..\..\activity.pas"/>
        <Caret Line="39" Column="45" TopLine="1"/>
      </Position10>
      <Position11>
        <Filename Value="..\..\activity.pas"/>
        <Caret Line="33" Column="29" TopLine="13"/>
      </Position11>
      <Position12>
        <Filename Value="..\..\activity.pas"/>
        <Caret Line="34" Column="55" TopLine="14"/>
      </Position12>
      <Position13>
        <Filename Value="..\..\activity.pas"/>
        <Caret Line="20" Column="5" TopLine="14"/>
      </Position13>
      <Position14>
        <Filename Value="..\..\activity.pas"/>
        <Caret Line="36" Column="60" TopLine="17"/>
      </Position14>
      <Position15>
        <Filename Value="..\..\activity.pas"/>
        <Caret Line="14" Column="19" TopLine="7"/>
      </Position15>
      <Position16>
        <Filename Value="..\..\activity.pas"/>
        <Caret Line="66" Column="47" TopLine="46"/>
      </Position16>
      <Position17>
        <Filename Value="..\..\activity.pas"/>
        <Caret Line="92" Column="55" TopLine="72"/>
      </Position17>
      <Position18>
        <Filename Value="..\..\activity.pas"/>
        <Caret Line="105" Column="5" TopLine="78"/>
      </Position18>
      <Position19>
        <Filename Value="..\..\activity.pas"/>
        <Caret Line="57" Column="14" TopLine="36"/>
      </Position19>
      <Position20>
        <Filename Value="..\..\activity.pas"/>
        <Caret Line="119" Column="1" TopLine="83"/>
      </Position20>
      <Position21>
        <Filename Value="..\..\activity.pas"/>
        <Caret Line="32" Column="5" TopLine="1"/>
      </Position21>
      <Position22>
        <Filename Value="..\..\activity.pas"/>
        <Caret Line="135" Column="24" TopLine="112"/>
      </Position22>
      <Position23>
        <Filename Value="..\..\activity.pas"/>
        <Caret Line="135" Column="23" TopLine="112"/>
      </Position23>
      <Position24>
        <Filename Value="..\..\activity.pas"/>
        <Caret Line="167" Column="30" TopLine="135"/>
      </Position24>
      <Position25>
        <Filename Value="..\..\activity.pas"/>
        <Caret Line="170" Column="3" TopLine="137"/>
      </Position25>
      <Position26>
        <Filename Value="..\..\activity.pas"/>
        <Caret Line="121" Column="18" TopLine="111"/>
      </Position26>
      <Position27>
        <Filename Value="SnapViewer.lpr"/>
        <Caret Line="10" Column="16" TopLine="1"/>
      </Position27>
      <Position28>
        <Filename Value="..\..\f_main.pas"/>
        <Caret Line="103" Column="25" TopLine="94"/>
      </Position28>
      <Position29>
        <Filename Value="..\..\f_main.pas"/>
        <Caret Line="1" Column="1" TopLine="1"/>
      </Position29>
      <Position30>
        <Filename Value="..\..\activity.pas"/>
        <Caret Line="192" Column="51" TopLine="161"/>
      </Position30>
    </JumpHistory>
  </ProjectOptions>
  <CompilerOptions>
    <Version Value="8"/>
    <PathDelim Value="\"/>
    <Target>
      <Filename Value="..\..\..\out\SnapViewer.exe"/>
    </Target>
    <SearchPaths>
      <IncludeFiles Value="$(ProjOutDir)\"/>
      <OtherUnitFiles Value="C:\MC\Code\Projects\Voronwe\GUI\FrontEnd\SnapViewer\src\"/>
    </SearchPaths>
    <Linking>
      <Options>
        <Win32>
          <GraphicApplication Value="True"/>
        </Win32>
      </Options>
    </Linking>
    <Other>
      <CompilerPath Value="$(CompPath)"/>
      <ExecuteAfter>
        <Command Value="&quot;C:\MC\Run\Util\Compression\UPX\upx.exe&quot; --best -vk $(TargetFile)"/>
        <ShowAllMessages Value="True"/>
        <CompileReasons Compile="False" Run="False"/>
      </ExecuteAfter>
    </Other>
  </CompilerOptions>
  <Debugging>
    <Exceptions Count="3">
      <Item1>
        <Name Value="EAbort"/>
      </Item1>
      <Item2>
        <Name Value="ECodetoolError"/>
      </Item2>
      <Item3>
        <Name Value="EFOpenError"/>
      </Item3>
    </Exceptions>
  </Debugging>
</CONFIG>

Added SnapViewer/src/prj/fpc/SnapViewer.lpr.











































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
program SnapViewer;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Interfaces, // this includes the LCL widgetset
  Forms, F_Main in '..\..\F_Main.pas', LResources, SQLDBLaz, Activity in '..\..\Activity.pas'
  { you can add units after this };

{$IFDEF WINDOWS}{$R SnapViewer.rc}{$ENDIF}

begin
  {$I SnapViewer.lrs}
  Application.Initialize;
  Application.CreateForm(TfrmMain, frmMain);
  Application.Run;
end.

Added SnapViewer/src/prj/fpc/SnapViewer.lrs.







































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
LazarusResources.Add('MAINICON','ICO',[
  #0#0#1#0#9#0'00'#0#0#1#0#8#0#168#14#0#0#150#0#0#0'  '#0#0#1#0#8#0#168#8#0#0'>'
  +#15#0#0#24#24#0#0#1#0#8#0#200#6#0#0#230#23#0#0#16#16#0#0#1#0#8#0'h'#5#0#0#174
  +#30#0#0#0#0#0#0#1#0' '#0#252'o'#0#0#22'$'#0#0'00'#0#0#1#0' '#0#168'%'#0#0#18
  +#148#0#0'  '#0#0#1#0' '#0#168#16#0#0#186#185#0#0#24#24#0#0#1#0' '#0#136#9#0#0
  +'b'#202#0#0#16#16#0#0#1#0' '#0'h'#4#0#0#234#211#0#0'('#0#0#0'0'#0#0#0'`'#0#0
  +#0#1#0#8#0#0#0#0#0#0#9#0#0#0#0#0#0#0#0#0#0#0#1#0#0#0#1#0#0#0#0#0#0'yeO'#0'yx'
  +'y'#0#149#129'm'#0#154#133'o'#0#153#135't'#0#154#136's'#0#155#140'|'#0#163
  +#143'{'#0#165#144'}'#0#168#149'z'#0#136#135#137#0#135#136#138#0#151#149#151#0
  +#156#152#148#0#152#150#152#0#154#153#154#0#157#155#153#0#157#157#158#0#170
  +#150#130#0#173#154#135#0#169#155#140#0#177#158#135#0#171#158#145#0#161#158
  +#159#0#175#163#143#0#179#163#141#0#190#165#139#0#175#161#146#0#174#163#148#0
  +#176#162#144#0#177#164#146#0#188#170#145#0#182#166#152#0#179#167#156#0#179
  +#168#155#0#181#168#155#0#178#170#158#0#182#170#157#0#191#175#154#0#184#173
  +#157#0#191#176#154#0#159#159#160#0#160#158#160#0#161#161#161#0#164#162#164#0
  +#165#164#165#0#175#170#167#0#165#165#168#0#168#167#169#0#170#170#173#0#174
  +#169#172#0#174#173#174#0#182#171#163#0#184#170#160#0#185#174#161#0#188#175
  +#163#0#185#172#164#0#188#175#164#0#186#176#162#0#188#177#163#0#186#177#165#0
  +#188#177#166#0#189#179#169#0#191#184#174#0#175#175#176#0#177#176#177#0#180
  +#177#178#0#179#178#181#0#181#178#181#0#180#180#181#0#186#181#180#0#180#180
  +#184#0#184#182#184#0#183#184#186#0#185#185#185#0#189#186#186#0#186#186#189#0
  +#190#189#190#0#193#175#151#0#193#174#152#0#193#179#157#0#194#180#162#0#203
  +#183#160#0#197#185#167#0#202#186#165#0#193#179#170#0#193#181#169#0#193#181
  +#173#0#200#183#169#0#194#184#169#0#197#185#169#0#197#188#171#0#194#185#173#0
  +#197#185#173#0#199#188#174#0#201#188#171#0#194#185#177#0#197#186#177#0#197
  +#189#178#0#195#187#181#0#197#189#180#0#203#189#178#0#200#190#181#0#194#188
  +#187#0#206#193#171#0#210#196#172#0#199#192#182#0#201#193#177#0#205#194#178#0
  +#206#196#178#0#206#195#180#0#207#197#180#0#195#193#189#0#202#193#185#0#205
  +#193#186#0#200#193#190#0#205#194#188#0#204#197#189#0#209#197#178#0#213#201
  +#179#0#219#202#180#0#208#196#186#0#209#198#189#0#212#199#189#0#210#201#185#0
  +#213#203#186#0#215#205#187#0#212#201#189#0#213#205#188#0#216#206#186#0#220
  +#209#188#0#229#207#183#0#233#207#187#0#228#210#187#0#190#190#192#0#192#191
  +#193#0#193#190#196#0#191#193#194#0#193#193#193#0#197#193#193#0#195#194#196#0
  +#197#193#196#0#195#196#197#0#198#198#198#0#201#194#193#0#202#197#192#0#206
  +#197#192#0#202#197#197#0#204#200#196#0#199#199#201#0#203#199#200#0#198#200
  +#202#0#202#202#202#0#205#200#200#0#207#204#202#0#204#203#207#0#206#205#206#0
  +#209#198#194#0#209#202#194#0#214#203#195#0#211#204#192#0#210#202#198#0#212
  +#203#197#0#214#205#197#0#216#203#193#0#216#206#193#0#210#203#200#0#210#205
  +#201#0#214#205#202#0#211#206#207#0#214#209#199#0#221#212#194#0#214#208#203#0
  +#211#209#207#0#212#209#206#0#219#210#201#0#202#202#208#0#204#208#209#0#210
  +#208#210#0#212#209#209#0#214#211#212#0#213#213#213#0#216#210#210#0#217#213
  +#209#0#222#214#210#0#217#213#213#0#222#215#212#0#220#217#212#0#218#218#219#0
  +#222#221#218#0#219#219#220#0#220#219#220#0#219#221#221#0#220#220#221#0#224
  +#214#195#0#227#217#197#0#227#213#202#0#224#213#205#0#225#217#201#0#227#220
  +#203#0#225#217#205#0#229#216#204#0#226#220#205#0#229#221#206#0#232#222#204#0
  +#228#220#209#0#233#219#208#0#234#221#210#0#225#222#219#0#234#225#205#0#230
  +#224#210#0#232#225#210#0#236#226#209#0#233#228#211#0#239#229#209#0#233#226
  +#213#0#236#224#213#0#233#228#214#0#237#229#213#0#231#225#217#0#226#224#222#0
  +#228#225#222#0#230#228#221#0#234#229#218#0#238#232#221#0#242#229#208#0#240
  +#226#214#0#241#231#212#0#244#232#214#0#241#227#216#0#242#228#216#0#244#235
  +#219#0#248#238#219#0#252#241#222#0#222#222#224#0#225#224#224#0#228#226#224#0
  +#230#228#225#0#229#229#229#0#232#230#224#0#239#233#225#0#235#235#235#0#242
  +#237#226#0#249#239#225#0#246#240#229#0#251#243#227#0#254#250#228#0#246#242
  +#233#0#249#243#233#0#253#251#235#0#244#244#244#0#254#253#243#0#249#249#249#0
  +#254#254#254#0#255#255#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#182#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255','#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#182#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255','#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#182#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255','#0#0#0#0#0#0#0#0#0#0#0#0#0#0#174#231#231#231#231#231#231#231#231#231
  +#231#231#231#231#231#231#231#231#231#231#208#202#202#197'zz'#128'z'#165#208
  ,#208#227#227#14#0#0#0#0#0#0#0#0#0#0#0#0#0#0#182#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#236#150'B'#18',11,,'#15','
  +#157#236#18#0#0#0#0#0#0#0#0#0#0#0#0#0#0#182#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#235#135'B1'#137#170#186#186#186#186#170
  +#143'2'#18#18#2#0#0#0#0#0#0#0#0#0#0#0#0#0#0#174#231#231#231#231#231#231#231
  +#231#231#231#231#231#231#231#231#217'k/'#135#148#163'X677776?r'#148#135#11#11
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#182#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#253#157#135#148#147'6'#29'<l'#128'`<'#174#146'@%"b'#148'4'#18#0
  +#0#0#0#0#0#0#0#0#0#0#0#182#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#143#135#169'k'#30#30#128#204#211#202'l<'#235#222#236#184'k%6'#163'B'
  +','#0#0#0#0#0#0#0#0#0#0#0#174#231#231#231#231#231#231#231#231#231#231#231#231
  +#227'@h'#169'7'#30#166'S'#26#172#201#204#174#128#222#222#236#168'<b`5'#163'B'
  +'1'#0#0#0#0#0#0#0#0#0#0#182#255#255#255#255#255#255#255#255#255#255#255#255
  +#236#143#169'6'#30'x'#166#130'QZ'#204#204#217#236#240#222#235#147'l'#235#182
  +'b?'#148'4'#0#0#0#0#0#0#0#0#0#0#182#255#255#255#255#255#255#255#255#255#255
  +#255#253#152#152'X'#21'xxj'#130#195#195#200#204#211#224#222#240#222#174#163
  +#184#236#184'@?q,'#0#0#0#0#0#0#0#0#0#174#231#231#231#231#231#231#231#231#231
  +#231#217#163'hr'#21'iyjxx'#166#195#195#204#211#240#240#240#236#222#222#222
  +#236#190#174'<lI1'#0#0#0#0#0#0#0#0#182#255#255#255#255#255#255#255#255#255
  +#255#253#177#148'6'#29#10'Qijx'#172#195#195#202#211#214#224#240#240#240#236
  +#222#222#201'`=?q,'#0#0#0#0#0#0#0#0#182#255#255#255#255#255#255#255#255#255
  +#255#242#177#163#23'xZ Qxx'#166#195#195#195#211#217#211#240#240#240#240#222
  +#222#146'<'#146'<'#147'3'#0#0#0#0#0#0#0#0#174#231#231#231#231#231#231#231#231
  +#231#231#197#157'b<'#200#196#134'yxy'#195#172#195#200#204#204#217#214#240#240
  +#240#236#236#236#236#236'bbB'#18#0#0#0#0#0#0#0#182#255#255#255#255#255#255
  +#255#255#255#255#235#182'?l'#226#195#134'y'#172#172#172#172#196#172'jZ'#200
  +#217#211#224#222#240#240#222#222#236#146'?h'#18#0#0#0#0#0#0#0#182#255#255#255
  +#255#255#255#255#255#255#255#235#174'b'#128#226#210#195#134#195#210#172#172
  +#172#172'Q'#4#200#211#214#240#214#240#240#236#222#222#184'`'#143','#0#0#0#0#0
  +#0#0#174#231#231#231#231#231#231#231#231#231#231#169#174'X'#195#229#229#210
  +#210#195#210#210#195#172#131'Q'#3'x'#195#200#200#202#202#202#202#211#190#201
  +'@'#146'4'#0#0#0#0#0#0#0#182#255#255#255#255#255#255#255#255#255#255#235#174
  +'`O'#22'U'#229#226#215#214#210#210'x'#10#3#1#4#8#8#8#8#8#8#20'lZ'#29'('#146
  +'1'#0#0#0#0#0#0#0#182#255#255#255#255#255#255#255#255#255#255#235#174'<'#195
  +#250#246#233#233#244#246#244#243#214#240'i'#6#200#210#210#217#214#214#240#214
  +#204#204#201'`'#143','#0#0#0#0#0#0#0#174#231#231#231#231#231#231#231#231#231
  +#231#163#163'<w'#233#233#246#233#246#244#248#244#248#240'U'#6#130#195#166#166
  +#200#166#200#172#195#195#161'Zq'#18#0#0#0#0#0#0#0#182#255#255#255#255#255#255
  +#255#255#255#255#235#182'?`'#233#247#250#247#246#244#248#248#248#244#146#20
  +#211#211#200#200#166#195#166#195#195#168'n=L'#13#0#0#0#0#0#0#0#182#255#255
  +#255#255#255#255#255#255#255#255#236#148#148'`'#226#250#172#210#247#246#249
  +#250#248#244#168'%'#240#232#217#211#202#200'xZn'#200'Z`B,'#0#0#0#0#0#0#0#174
  +#231#231#231#231#231#231#231#231#231#231#198#148#163'XyPR'#202#247#246#249
  +#244#248#248#168'7'#232#240#240#240#217#211#211'i'#25'Z<'#147#24#0#0#0#0#0#0
  +#0#0#182#255#255#255#255#255#255#255#255#255#255#253#157#174#147'YS'#202#250
  +#247#247#247#249#248#244#172'%'#243#243#232#240#214#217#211#202#128'Z<b,'#0#0
  +#0#0#0#0#0#0#182#255#255#255#255#255#255#255#255#255#255#253#182#169#169'b'
  +#134#247#252#247#247#246#246#246#232#128'%'#232#243#240#232#214#217#211#204
  +#204'ZXI'#0#0#0#0#0#0#0#0#0#174#231#231#231#231#231#231#231#231#231#227#217
  +#206'h'#186#128'X'#134#246#252#250#210#226#233#232'`'#21#224#243#232#240#232
  +#217#211#204'lR'#148','#0#0#0#0#0#0#0#0#0#182#255#255#255#255#255#255#255#255
  +#255#255#255#255#236#143#198'b`'#132#249#201'Q'#210#247#229'X'#8#232#243#243
  +#130'R'#202#214#128'`'#147'I'#0#0#0#0#0#0#0#0#0#0#182#255#255#255#255#255#255
  +#255#255#255#255#255#255#253#157#150#209#147'R'#134#27'U'#252#250#233'R'#7
  +#224#243#243#206'`l'#128'@'#147'bB'#0#0#0#0#0#0#0#0#0#0#174#231#231#231#231
  +#231#231#231#231#231#231#231#227#227#208#147#146#222'z@U'#134#233#233#233'%'
  +#7#246#249#249#243#172'``'#163'qB'#0#0#0#0#0#0#0#0#0#0#0#182#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#253#177#148#209#158'XXUjySP'#217#202
  +#172'`?'#147#163'IB'#0#0#0#0#0#0#0#0#0#0#0#0#182#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#253#235#138#157#185#163'X66```Xk'#163#169
  +#148',3'#0#0#0#0#0#0#0#0#0#0#0#0#0#174#231#231#231#231#231#231#231#231#231
  +#231#231#231#231#227#217#217#208#185#147#135'q'#182#182#186#198#184#209#198
  +#157'hBI'#24#0#0#0#0#0#0#0#0#0#0#0#0#0#0#182#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#253#239#235#150#137#135#136#136'JBJ'
  ,#143#182#209#18#0#0#0#0#0#0#0#0#0#0#0#0#0#0#182#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#253#253#242#236#182'*'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#174#231#231#231#231
  +#231#231#231#231#231#231#231#231#231#231#231#231#231#227#227#231#231#231#231
  +#208'444442'#135#18#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#182#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#253#135
  +#255#255#253#242#235'B'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#182#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#242#135#255#253#239#235'B,'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#174#231#231#231
  +#231#231#231#231#231#231#231#231#231#231#231#231#231#231#231#231#231#231#231
  +#231#202#135#253#239#235#135','#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#182#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#239#135#236#236#138','#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#182#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#253#242'B'#236#138#24#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#182#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#253#235'B'#157'*'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#182#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#253#242#235#136','#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#182#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#253
  +#253#242#135#18#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#182#182#182#182
  +#182#182#182#182#182#182#182#182#182#182#182#182#182#182#182#182#182#182#182
  +#177#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#255#255#255#255#255#0#0#255
  +#255#255#255#255#255#0#0#240#0#0#0#3#255#0#0#240#0#0#0#3#255#0#0#240#0#0#0#3
  +#255#0#0#240#0#0#0#3#255#0#0#240#0#0#0#3#255#0#0#240#0#0#0#3#255#0#0#240#0#0
  +#0#1#255#0#0#240#0#0#0#0#255#0#0#240#0#0#0#0#127#0#0#240#0#0#0#0'?'#0#0#240#0
  +#0#0#0'?'#0#0#240#0#0#0#0#31#0#0#240#0#0#0#0#15#0#0#240#0#0#0#0#15#0#0#240#0
  +#0#0#0#15#0#0#240#0#0#0#0#7#0#0#240#0#0#0#0#7#0#0#240#0#0#0#0#7#0#0#240#0#0#0
  +#0#7#0#0#240#0#0#0#0#7#0#0#240#0#0#0#0#7#0#0#240#0#0#0#0#7#0#0#240#0#0#0#0#7
  +#0#0#240#0#0#0#0#7#0#0#240#0#0#0#0#15#0#0#240#0#0#0#0#15#0#0#240#0#0#0#0#31#0
  +#0#240#0#0#0#0#31#0#0#240#0#0#0#0'?'#0#0#240#0#0#0#0'?'#0#0#240#0#0#0#0#127#0
  +#0#240#0#0#0#0#255#0#0#240#0#0#0#1#255#0#0#240#0#0#0#3#255#0#0#240#0#0#0#3
  +#255#0#0#240#0#0#0#3#255#0#0#240#0#0#0#7#255#0#0#240#0#0#0#15#255#0#0#240#0#0
  +#0#15#255#0#0#240#0#0#0#31#255#0#0#240#0#0#0'?'#255#0#0#240#0#0#0#127#255#0#0
  +#240#0#0#0#255#255#0#0#240#0#0#1#255#255#0#0#240#0#0#3#255#255#0#0#240#0#0#15
  +#255#255#0#0'('#0#0#0' '#0#0#0'@'#0#0#0#1#0#8#0#0#0#0#0#0#4#0#0#0#0#0#0#0#0#0
  +#0#0#1#0#0#0#1#0#0#0#0#0#0'xsu'#0#137'xc'#0#140'|f'#0#157#141'y'#0#145#145
  +#145#0#148#146#146#0#148#147#148#0#150#148#149#0#152#149#145#0#156#154#149#0
  +#156#153#154#0#157#157#157#0#168#155#140#0#171#159#143#0#161#154#150#0#171
  +#159#144#0#173#161#146#0#174#163#149#0#175#164#151#0#174#167#159#0#178#166
  +#145#0#177#165#149#0#177#166#153#0#180#169#155#0#181#171#157#0#182#173#158#0
  +#186#173#152#0#185#171#156#0#184#172#156#0#161#161#161#0#165#162#165#0#167
  +#165#166#0#170#167#168#0#170#170#170#0#174#170#170#0#170#168#172#0#173#170
  +#172#0#182#171#160#0#182#173#165#0#185#174#161#0#180#175#168#0#187#176#163#0
  +#189#178#162#0#183#177#171#0#184#177#169#0#190#182#169#0#186#180#173#0#177
  +#177#177#0#181#181#181#0#184#179#176#0#185#181#177#0#184#181#182#0#191#184
  +#178#0#190#185#183#0#186#181#184#0#187#187#187#0#188#186#187#0#189#186#188#0
  +#189#188#188#0#192#180#162#0#196#181#163#0#192#182#167#0#195#184#167#0#192
  +#181#171#0#192#183#174#0#197#186#169#0#198#187#174#0#198#189#172#0#200#189
  +#170#0#195#187#179#0#193#188#183#0#199#190#182#0#194#190#186#0#194#190#189#0
  +#196#191#190#0#199#192#180#0#203#192#177#0#200#192#180#0#207#199#188#0#208
  +#200#186#0#210#202#189#0#211#204#189#0#215#207#190#0#217#207#189#0#215#208
  +#189#0#194#192#192#0#196#194#193#0#197#197#197#0#201#196#193#0#200#197#198#0
  +#201#200#198#0#202#199#201#0#203#200#200#0#206#204#205#0#209#200#192#0#213
  +#205#192#0#208#204#201#0#208#205#205#0#216#208#193#0#217#209#198#0#212#209
  +#206#0#221#214#202#0#220#214#204#0#209#209#209#0#212#209#208#0#213#213#213#0
  +#218#215#214#0#217#216#213#0#218#218#218#0#221#218#218#0#221#221#221#0#229
  +#220#199#0#227#220#200#0#228#221#202#0#225#218#205#0#227#220#206#0#229#222
  +#205#0#230#223#210#0#224#220#212#0#230#222#213#0#229#224#205#0#234#225#203#0
  +#231#225#209#0#230#224#215#0#233#226#209#0#236#228#212#0#238#232#213#0#229
  +#225#219#0#238#234#218#0#240#233#215#0#241#232#218#0#242#238#223#0#245#236
  +#223#0#226#226#226#0#229#228#229#0#232#231#230#0#237#238#238#0#246#240#225#0
  +#246#242#228#0#246#244#230#0#248#241#224#0#249#246#234#0#252#246#235#0#251
  +#247#238#0#252#246#236#0#255#250#237#0#240#240#240#0#244#244#244#0#252#248
  ,#242#0#255#254#243#0#255#254#244#0#249#249#249#0#254#254#254#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#255#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'o'#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#30#0#0#0#0#0#0#0#0#0'l~~~~~~~~~~~~~'
  +'~~~~~~~~'#10#0#0#0#0#0#0#0#0#0'o'#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#30#0#0#0#0#0#0#0#0#0'l~~~~~~~~~'
  +'~~~~~~~~~~~~'#10#0#0#0#0#0#0#0#0#0'o'#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#147'^'#30#8#11';'#7#0#0#0#0#0#0#0#0#0'l~~~~~~~~~~~~'
  +'~~F'#15'#WbW!'#1#0#0#0#0#0#0#0#0#0'o'#255#255#255#255#255#255#255#255#255
  +#255#255#255#255'^;])'#19#16#19',V'#30#0#0#0#0#0#0#0#0'l~~~~~~~~~~~~Q3]'#14
  +#22'Q'#131'|F&K#'#0#0#0#0#0#0#0'o'#255#255#255#255#255#255#255#255#255#255
  +#255#255'4^'#17'Dz'#130#141#145#149#128'3V'#7#0#0#0#0#0#0'l~~~~~~~~~~~Q63'#22
  +'pqz'#129#141#145#149'Q3 '#0#0#0#0#0#0'o'#255#255#255#255#255#255#255#255#255
  +#255#255'^b'#26'Q|qqDD'#145#145'x@3'#0#0#0#0#0#0'l~~~~~~~~~~~&o'#14#131#131
  +'{'#27#2#2#4#4'='#27'V'#7#0#0#0#0#0'o'#255#255#255#255#255#255#255#255#255
  +#255#255'Wo'#16#133#146#139'q'#27#22'UUT'#27'V'#7#0#0#0#0#0'l~~~~~~~~~~~F^(f'
  +#146#146#145'N<'#129'~Q&3'#0#0#0#0#0#0'o'#255#255#255#255#255#255#255#255#255
  +#255#255#136'\/<'#149#146#139'D@'#139#127'?'#19'%'#0#0#0#0#0#0'l~~~~~~~~~~~~'
  +'3i(g'#149#142'D<'#131'd'#26'K!'#0#0#0#0#0#0'o'#255#255#255#255#255#255#255
  +#255#255#255#255#255#136'bb'#26'<d<'#17'D'#14'F;'#0#0#0#0#0#0#0'l~~~~~~~~~~~'
  +'~~OO^,'#19#13#17',W4'#0#0#0#0#0#0#0#0'o'#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#134'W\jkjY'#11#0#0#0#0#0#0#0#0#0'l~~~~~~~~~~~~~~~q_/&&O'
  +#6#0#0#0#0#0#0#0#0#0'o'#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#30#0#0#0#0#0#0#0#0#0'l~~~~~~~~~~~~~~~~~~~~l'
  +#8#0#0#0#0#0#0#0#0#0'o'#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#147'jW;'#7#0#0#0#0#0#0#0#0#0'l~~~~~~~~~~~~~~~q%#"#4'#11#0#0
  +#0#0#0#0#0#0#0'o'#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#148'j'#148#147'h"'#0#0#0#0#0#0#0#0#0#0'l~~~~~~~~~~~~~~~xl'#148'o4'#0#0#0#0#0
  +#0#0#0#0#0#0'o'#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#148'jl4'#0#0#0#0#0#0#0#0#0#0#0#0'o'#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#134'W4'#0#0#0#0#0#0#0#0#0#0#0#0#0'o'#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255'j4'#0#0#0#0#0#0#0#0#0#0#0#0#0#0'jjj'
  +'jjjjjjjjjjjjjW'#0#0#0#0#0#0#0#0#0#0#0#0#255#255#255#255#255#255#255#255#224
  +#0#0'?'#224#0#0'?'#224#0#0'?'#224#0#0'?'#224#0#0'?'#224#0#0'?'#224#0#0#31#224
  +#0#0#15#224#0#0#7#224#0#0#7#224#0#0#7#224#0#0#3#224#0#0#3#224#0#0#7#224#0#0#7
  +#224#0#0#7#224#0#0#15#224#0#0#31#224#0#0'?'#224#0#0'?'#224#0#0'?'#224#0#0'?'
  +#224#0#0'?'#224#0#0'?'#224#0#0#127#224#0#0#255#224#0#1#255#224#0#3#255#224#0
  +#7#255#224#0#15#255'('#0#0#0#24#0#0#0'0'#0#0#0#1#0#8#0#0#0#0#0'@'#2#0#0#0#0#0
  +#0#0#0#0#0#0#1#0#0#0#1#0#0#0#0#0#0#137'w`'#0#146#129'k'#0#150#134'q'#0#150
  +#149#148#0#152#152#152#0#166#152#134#0#168#153#136#0#170#157#138#0#174#159
  +#139#0#170#157#140#0#174#159#140#0#174#161#142#0#178#165#141#0#173#161#145#0
  +#178#167#147#0#178#164#150#0#181#168#148#0#184#174#152#0#185#176#155#0#172
  +#169#166#0#185#174#160#0#188#178#162#0#189#180#163#0#190#179#166#0#189#181
  +#166#0#180#180#180#0#185#185#186#0#189#189#189#0#192#181#163#0#192#182#168#0
  +#199#189#171#0#192#185#173#0#199#190#174#0#200#189#172#0#196#189#180#0#200
  +#191#183#0#201#192#176#0#205#195#177#0#205#197#183#0#203#195#185#0#207#199
  +#187#0#202#198#191#0#208#198#183#0#209#201#182#0#208#199#187#0#214#205#187#0
  +#216#208#186#0#203#199#193#0#205#201#194#0#207#207#207#0#217#208#192#0#221
  +#212#192#0#216#210#198#0#215#210#203#0#210#209#207#0#217#210#201#0#222#217
  +#201#0#207#207#208#0#210#210#210#0#213#212#212#0#224#216#201#0#226#220#207#0
  +#230#221#206#0#225#220#208#0#229#221#208#0#227#223#218#0#230#224#205#0#232
  +#227#210#0#236#228#212#0#238#232#213#0#241#237#219#0#240#234#222#0#242#236
  +#223#0#226#226#226#0#232#232#233#0#237#235#232#0#238#238#238#0#247#242#224#0
  ,#245#241#228#0#249#248#235#0#245#243#242#0#247#246#244#0#255#254#249#0#254
  +#254#254#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#255#255#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'<'#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#5#0#0#0#0#0#0#0'7EEEEEEEEEEEEEEE'#4#0#0#0#0#0#0
  +#0'<'#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#5#0#0#0#0#0
  +#0#0'7EEEEEEEEEE?+'#17#11#24#20#0#0#0#0#0#0#0'<'#255#255#255#255#255#255#255
  +#255#255'L'#30#18'4?)'#14'0'#0#0#0#0#0#0'7EEEEEEEEA'#29#13'/FNI4'#16#0#0#0#0
  +#0#0'<'#255#255#255#255#255#255#255#255'B'#24',C4'#11'4@)$'#0#0#0#0#0'7EEEEE'
  +'EEE&'#31'E.'#6#1#2#3#31#16#0#0#0#0#0'<'#255#255#255#255#255#255#255#255'6&H'
  +'N6'#6#31'.-'#16#0#0#0#0#0'7EEEEEEEE3'#31'9PA'#7'9I%#'#0#0#0#0#0'<'#255#255
  +#255#255#255#255#255#255'R)'#24'@7'#6'4,'#12#0#0#0#0#0#0'7EEEEEEEEE6'#24#24
  +'&'#11#19#14'0'#0#0#0#0#0#0'<'#255#255#255#255#255#255#255#255#255#255'Q7'#21
  +#7' '#20#0#0#0#0#0#0#0'7EEEEEEEEEEEEEFE'#4#0#0#0#0#0#0#0'<'#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#5#0#0#0#0#0#0#0'7EEEEEEEEEEEE?7'
  +','#0#0#0#0#0#0#0#0'<'#255#255#255#255#255#255#255#255#255#255'<'#26#26#26#26
  +#0#0#0#0#0#0#0#0'7EEEEEEEEEE0J'#255'L'#28#0#0#0#0#0#0#0#0'<'#255#255#255#255
  +#255#255#255#255#255#255'<JL'#28#0#0#0#0#0#0#0#0#0'<'#255#255#255#255#255#255
  +#255#255#255#255'<:'#28#0#0#0#0#0#0#0#0#0#0'<'#255#255#255#255#255#255#255
  +#255#255'L;'#27#0#0#0#0#0#0#0#0#0#0#0'222222222;:'#28#0#0#0#0#0#0#0#0#0#255
  +#255#255#0#255#255#255#0#224#0#15#0#224#0#15#0#224#0#15#0#224#0#15#0#224#0#7
  +#0#224#0#7#0#224#0#3#0#224#0#3#0#224#0#3#0#224#0#3#0#224#0#7#0#224#0#7#0#224
  +#0#15#0#224#0#15#0#224#0#15#0#224#0#31#0#224#0#31#0#224#0#31#0#224#0'?'#0#224
  +#0#127#0#224#0#255#0#224#1#255#0'('#0#0#0#16#0#0#0' '#0#0#0#1#0#8#0#0#0#0#0#0
  +#1#0#0#0#0#0#0#0#0#0#0#0#1#0#0#0#1#0#0#0#0#0#0'zzz'#0#148#132'n'#0#161#147'}'
  +#0#141#141#141#0#149#149#148#0#170#155#135#0#175#162#142#0#179#163#143#0#177
  +#164#144#0#185#173#153#0#163#163#163#0#167#165#160#0#164#164#164#0#178#172
  +#165#0#186#175#160#0#176#175#174#0#183#177#167#0#189#177#160#0#190#178#165#0
  +#178#178#178#0#180#180#179#0#183#183#183#0#184#184#182#0#184#184#184#0#189
  +#188#187#0#189#189#189#0#197#187#168#0#196#186#173#0#198#188#174#0#199#191
  +#177#0#200#190#177#0#192#191#190#0#202#193#174#0#202#193#178#0#205#196#179#0
  +#204#198#191#0#207#201#188#0#208#199#181#0#214#204#186#0#210#203#189#0#212
  +#204#191#0#216#207#186#0#192#192#192#0#206#200#192#0#207#207#207#0#215#207
  +#192#0#209#204#196#0#217#207#192#0#223#213#197#0#217#212#205#0#222#216#203#0
  +#222#222#222#0#224#215#196#0#226#219#200#0#228#221#203#0#225#220#213#0#232
  +#225#206#0#231#224#209#0#236#227#209#0#238#228#211#0#232#228#212#0#230#227
  +#221#0#236#231#218#0#224#224#225#0#230#231#230#0#239#236#224#0#236#233#230#0
  +#233#233#233#0#238#238#239#0#244#240#226#0#251#251#251#0#254#254#254#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#255#255#255#0#0#1#1#1#1#1#1#1#1#1#1#1#1#0#0#0#0#4#255#255#255#255#255
  +#255#255#255#255#255#13#0#0#0#0#5'<<<<<<<<<<'#13#0#0#0#0#13#255#255#255#255
  +#255#255#255'>'#29#19#14#0#0#0#0#16'<<<<<<'''#29'5:'#29','#0#0#0#20#255#255
  +#255#255#255'C"*97?'#31'2'#0#0#20'<<<<<*&6'#10#2#3#8#19#0#0#23#255#255#255
  +#255#255'8.F'''#6#29'"'#18#0#0#23'<<<<<1''C3'#8'<"$'#0#0#25#255#255#255#255
  +#255#255'2$'''#7'!'#30#0#0#0#25'<<<<<<<.'#18#9#17#0#0#0#0'+'#255#255#255#255
  +#255#255#255#255'E@+'#0#0#0#0' <<<<<<<.'#22#24#25#0#0#0#0'+'#255#255#255#255
  +#255#255#255'4D-D'#0#0#0#0'+'#255#255#255#255#255#255#255'@+A'#0#0#0#0#0'+++'
  +'+++'#25'+'#25'E'#0#0#0#0#0#128#7#0#0#128#7#0#0#128#7#0#0#128#7#0#0#128#3#0#0
  +#128#1#0#0#128#1#0#0#128#1#0#0#128#1#0#0#128#3#0#0#128#7#0#0#128#7#0#0#128#7
  +#0#0#128#7#0#0#128#15#0#0#128#31#0#0#137'PNG'#13#10#26#10#0#0#0#13'IHDR'#0#0
  +#1#0#0#0#1#0#8#6#0#0#0'\r'#168'f'#0#0' '#0'IDATx'#156#236#189'y'#220'dUy'#239
  +#251']k'#15'U'#245#206#253#246#251#246'<'#208#208#244#192#216'4 80'#169#24'@'
  +'D'#137#198#24#16#146#16#189'!'#198#168#25'n'#204'I'#142'^'#147'{<'#185#159
  +#220#228'&'#231#28'O'#244#28#163'q"&&qH'#162#8#196'Y'#17#194'('#210't3'#211
  +#243#252#142'5'#238'a'#173#251#199#218'k'#239'U'#213#13'6C7/'#244#254'i'#241
  +'V'#237#218'SU'#215#243'['#207#243'{'#158#245','#193#209#133'p'#254#10#231'5'
  +'='#207'K'#188#188#161#159'f'#155'v'#222';'#220'>%'#142'2'#252#163'|~'#217
  +#243#240'8<'#25#148'x'#249#163#215#216'5'#144'f'#127'U'#207'_('#9#225#152#224
  +'h'#19#128#151'='#2#231#225#146'@'#137#227#11#214#240'U'#246'H'#179#191'I'
  +#246'<'#237'y'#207#30'S'#226'('#225'h'#19#128#15#132'@'#213'y'#248#217#163'$'
  +#128#227#11#214#144']'#3'O'#128#216#249#27';'#175'%%'#17#28'u'#28#11#2#168#2
  +#3#206#163#130#241#4#228'Q'#190'v'#137#185#5'w'#244'w'#141'?'#6':@'#4#180#157
  +#231'Q'#246#158#160'$'#129#163#134#163'I'#0#1#230#31'/'#0#6#129#197'Z'#235
  +#175#31#197#235#149'x'#137'abb'#130'm'#219#182#165'?'#249#201'O'#246'}'#225
  +#11'_'#248#247#187#238#186#235#206#233#233#233#251#128#221#24'2hS'#16#129#13
  +#15'J'#18'x'#1'q4'#221#240#0#232#3#134#128'1J'#2'xI#M'#205' '#172#181#206#255
  +'*'#165#242#215'B'#8#180#214#249'v)%J)'#148'R'#249'9'#236#254#246#24'{\'#165
  +'RAJ'#201#204#204#12#155'6m'#234'|'#236'c'#31#251#203#127#254#231#127#254'"0'
  +#9#180'0D`I'#192#10#135'%^'#0#148#4'P'#226'g'#194'5~'#165'Tn'#236'J'#169#252
  +'=0'#198'l'#141#222'5'#244'4M'#243#231'I'#146#228#207#163'("'#138#162#252#248
  +#193#193'A'#6#7#7#17'B'#240#229'/'#127'y'#239'G?'#250#209#15'l'#217#178#229
  +'N'#160#129'!'#130#136#146#4'^P'#148#4'P'#226#136#224#26#186'k'#224#174#145
  +#187'^'#192#225#246's='#134'4M'#243'G'#146'$t:'#29#218#237'6'#157'N'#135#254
  +#254'~V'#175'^'#205#204#204#12#31#249#200'G'#254#215#199'?'#254#241#191#162
  +#240#6'"'#138#172'AI'#2#207#19#165#16'W'#226#136#224'y^'#254'\J'#243#179#17
  +'B '#132#200#223#215'Zwm'#147'R'#230#175#221#135#148#18#207#243#240'<'#15#223
  +#247#241'}'#159'J'#165'B'#173'V'#163'V'#171'q'#240#224'A~'#252#227#31'S'#175
  +#215#249'o'#255#237#191#253#250'''>'#241#137'/'#0#11'1'#3'J'#136#209#174'l:'
  +#185#196#243'@I'#0'%'#142#24'.'#9'X#?'#28#9#184#239#187'$`'#13'_k'#157'?'#151
  +'R'#230'$`'#137'`'#222#188'y'#8'!'#216#188'y3'#247#222'{/'#215'_'#127#253#217
  +#159#252#228''''#255#22'X@I'#2'/('#142'v'#26#176#196#203#12'.'#9'@'#225#250
  +#131#209#8'<'#207';d'#155#21#4#15#247#218#158#207#243'<'#130' '#200#195#136
  +#193#193'A'#148'R'#236#218#181#139#254#254'~~'#245'W'#127'u'#163#16#226#211
  +#239'z'#215#187'n'#0#246#245#220'V'#25#14'<G'#148#30'@'#137#231#5';'#138#219
  +#145#222#221#246'L'#225#192#225#246'w'#255#6'A'#192#224#224' }}}l'#217#178
  +#133#201#201'I~'#237#215'~'#237#236#191#249#155#191#249'$0N'#233#9#188' ('#9
  +#160#196'sBo8`Gv'#171#15#0'G'#172#9#216's'#184#225'@'#24#134'yH'#224#251'>'
  +#247#221'w'#31'Q'#20#241'+'#191#242'+'#175#248#194#23#190#240#183#148'$'#240
  +#130#160'$'#128#18#207#25#189#194#160'5xK'#4'G'#170#9#244#254'u'#5#194'Z'#173
  +'F'#181'Ze'#207#158'=<'#250#232#163#8'!'#184#246#218'k'#207#254#220#231'>'
  +#247')Lv'#169'$'#129#231#129#146#0'J</Xc'#21'Bte'#2#128#220#160#237'~'#135'#'
  +#1#224#16#143#224'p'#164#224#251'>O>'#249'$B'#8#162'('#226#186#235#174';'#247
  +#179#159#253#236''')I'#224'y'#161'$'#128#18'/('#172#161#247#146#128'- z'#166
  ,'p'#192'n'#235'M'#19'J)'#169'T*LLLp'#240#224'A'#148'RDQ'#196#245#215'_'#127
  +#254#199'?'#254#241#191#6#230'S'#146#192'sBI'#0'%^'#16#28'N'#19'p'#141#221'j'
  +#3'O'#231#9#184'a'#131#251#218'M'#17'*'#165'x'#240#193#7#17'B'#208'h4'#136
  +#162#136#27'o'#188#241#130'O}'#234'S'#159#160' '#129#10'%'#9#28'1J'#2'('#241
  +#130#225#233'4'#1#251#218#166#255#172'ko'#183#247'z'#0'n'#24' '#132#160'Z'
  +#173#230#153#129#173'['#183#18#199'1'#157'N'#135#153#153#25#218#237'67'#220
  +'p'#195'k>'#255#249#207#255'/`'#148#146#4#158#21'J'#2'('#241#130#194#146#192
  +#211'i'#2#150#4'\'#175#160#215#240']M'#161#247'u'#146'$4'#26#13#164#148#180
  +'Z-Z'#173#22#237'v'#155'w'#190#243#157#175#254#220#231'>'#247#9'J'#18'xV('#9
  +#160#196#11#14#215#19'8'#156'&'#240't$`a'#183#247#134#1'VK'#168#215#235#248
  +#190'O'#20'E'#212#235'u'#26#141#6#237'v'#155#235#174#187#238#130'O}'#234'S'
  +#255#19#152'GI'#2'G'#132#146#0'J'#28'u<'#157'&'#208'K'#2'n'#252#239#10#128'n'
  +#141#128#214#154'V'#171'E'#24#134#128#153']'#216'l6s'#18#184#225#134#27'.'
  +#250#204'g>'#243#215#148'$pD('#9#160#196'QAo'#201#240'3i'#2'.'#9#184#4' '#132
  +#200'I'#192#13#19#246#237#219#215'uNK'#2#179#179#179#180#219'm~'#249#151#127
  +#249#162#155'n'#186#233#227#192#8'%'#9'<#J'#2'(q'#212#208#155#25'8'#18'M'#192
  +#221#199#13#3',!'#4'A'#192#196#196#4'@'#215#220#1#151#4#26#141#6#215'\s'#205
  +#133'_'#252#226#23#255#154#146#4#158#17'%'#1#148'8'#170#176'"'#158#251#250
  +#153'4'#129#222#186#0#215#248'mf`zz'#26#207#243#168'V'#171#248#190#159'7"I'
  +#211#148'f'#179#153'?'#222#241#142'w\|'#211'M7}'#140#146#4#158#22#229'l'#192
  +#18#199#28#214#248#161#152#29#8#228'$`'#9#195#157'0T'#169'T'#186#142'M'#146
  +#164'k{'#146'$]$`'#207'}'#205'5'#215#188'Vk'#253#223#223#249#206'w'#190#191
  +#247'6(f'#17#30#183'3'#9'K'#2'(qL`'#167#9'['#216'Q'#222'v'#9'rI'#160#215';p='
  +#1#187'_'#187#221#206#179#3#22#182#187#16'@'#179#217#204#167#28'_{'#237#181
  +#175#23'B'#252#229#181#215'^'#251#1#138'Ejl'#179#209#227#186#245'x'#25#2#148
  +'8f'#232#21#6'-z'#13#222'%'#4'7'#20#176#175'm'#223#193' '#8#242#2#161'0'#12
  +#243'pC)E'#146'$'#180#219'm'#26#141#6#245'z'#157'k'#174#185#230#13#159#255
  +#252#231#255'?L8'#208#143'iW'#31'R,^s\.VSz'#0'%'#142'),'#9'Xo'#192#29#249#221
  +'f!.'#9'XX2'#176#162#159'K'#24'6-h'#201#196'z'#3#141'F#'#23#21#223#249#206'w'
  +'^'#166#181#214#215'_'#127#253#7'1'#131#159'5z'#219#153'4'#229'8CI'#0'%'#230
  +#4'z'#13#223'v'#18#238'M'#1#186'-'#197'+'#149#10'i'#154#230'a'#128'%'#1#11
  +#219't'#180#213'j'#229#199'^w'#221'u'#151'''I'#162'o'#184#225#134'?'#12#195
  +#208's'#186#18#187'$p'#220#132#2'%'#1#148'xQ'#208#171#9'@A'#2'n'#202#208#21#2
  +']'#221#192#206')p'#225#238'gG'#253'$IrO'#192'^'#239#250#235#175#191'"MS'#253
  +#238'w'#191#251'?'#135'ah['#147#187'+'#23#149#4'P'#162#196#209#198#211#145
  +#128';'#202#187#219#161'{a'#18'{'#142'^X'#2#136#162#8#173'u'#238#9#180#219
  +#237'|'#159'w'#189#235']oL'#211'T'#221'x'#227#141#31#162'0'#250#222#199#203
  +#30'%'#1#148'xQ'#209#171#9'X'#244#142#252#22#238#243#222's'#184#239#247#134#3
  +'q'#28'w'#173'K'#160#181#230#215#127#253#215#223#20'EQ'#242#190#247#189#239
  +#255#162'X'#180#212#146#193'q'#17#10#148#4'Pb'#206#193'*'#249#135#131'[I'#216
  +'{'#140#187#207'3'#9#131'V'#19#16'B'#240'['#191#245'[W'#11'!'#244#251#222#247
  +#190#15'i'#173']'#2#128#227#128#4'J'#2'(1'''#240'tu'#2'n'#3#145#222#21#135#14
  +'w'#14#247#216#159#165#9#216'e'#202#222#251#222#247#254'<'#16#255#214'o'#253
  +#214'G0'#4#224#226'eM'#2'%'#1#148#152'38'#156'&'#208#187#144'ho'#167#225#195
  +#157#195#253#235#30'g'#21#255'$IH'#211#148'N'#167#195#236#236',Q'#20#241#222
  +#247#190#247#23'='#207'K'#223#243#158#247#252#137#189#180's'#218#151'-'#9#148
  +#4'PbN'#193']X'#164#183#14#192#146#129#148#242#144#24#191#247#28#189#176#169
  +#194'^'#18'h'#181'Zh'#173'i4'#26#252#198'o'#252#198'5J'#169#244#189#239'}'
  +#239#127#201#14'sY'#198#21#10'_6('#9#160#196#156#198#211#145#192#225'B'#0#23
  +#189'$'#224#166#20'mv'#0#140'.'#16#199'1333'#0#252#230'o'#254#230'ui'#154#166
  +#239#127#255#251#255#31#12#1#244#150#13#191#172#136#160'$'#128#18's'#14#214
  +'x'#147'$9l<'#255't'#2#225#211#157#167#183#142#0#232#210#4#180#214'y'#143'A'
  +#128#27'o'#188#241'W'#226'8N'#127#239#247'~'#239'/0e'#194'-'#12#17#196#152
  +#149#137#237#13#188#228'I'#224#152#18#192'#'#143'<'#194#30#230#243#196#142
  +#214#177#188'l'#137#151#8#132#2#173#1'-'#240'G5'#205'>IMo'''#216#183#11#166
  +'Z'#212#167'Z'#204'LN'#211'h4'#142#248#156#135#211#4#194'0'#236#210#4','#169
  +'X'#18#232#239#239#231#253#239#127#255#175#165'i'#170'>'#248#193#15#254'w'#12
  +#9#184#174#136'%'#129#146#0#158#13#214#172'Y'#195#26#224#194'5'#199#242#170
  +'%^'#138'H'#211#148'('#138#136#162'~'#166#7#23'399'#201#222#189'{9P'#169'Q'
  +#175#215#159'Q'#3#232'Eo'#138#16#138':'#129'8'#142'I'#211'4'#175'B'#180#217#1
  +#128#223#253#221#223'}w'#167#211#225#195#31#254#240#255#12#130#192#139#227
  +#216'=m'#194#203' '#20'(C'#128#18's'#22#135'k'#24#250'\'#209#155'"'#180#176
  +#154#128'%'#1#219'r|zz'#26#128'?'#252#195'?|w'#146'$'#252#197'_'#252#197''''
  +#192#16'F'#134#222#154#129#151'$J'#2'(1'#231#209#219'@'#228#185#162#183';'
  ,#145'{nK'#2'`'#234#12'Z'#173'V'#222'`'#228#195#31#254#240#187#227'8N'#255#244
  +'O'#255#244#19#152#148'`o'#213#224'K'#150#4'J'#2'(1''a'#215#0'8'#26'p'#187#14
  +'A'#17#14'DQD'#165'R'#233#170#19#152#153#153'Ak'#205'G?'#250#209#27#131' '
  +#224'O'#254#228'O'#254''''#198#253'O)'#166#15#191'd'#235#4'J'#2'(1g'#209'['
  +#236#227#22#1#5'A'#240#156#207#219#155#29#0#242#243'Ya'#208'NG'#182#19#136
  +#132#16#252#241#31#255#241#141#195#195#195#225#239#254#238#239#254'9'#133#7
  +'`'#241#146'$'#129#146#0'J'#204'i'#184#179#0#181#214'y'#10#240#233#186#11#29
  +')'#236#241#182'@'#200'='#159'M'#13#186#158'@'#189'^'#199#243'<'#222#245#174
  +'w'#221' '#132#8'~'#231'w~'#231#163#28#26#2#188#228'H'#160'l'#9'VbN'#195#205
  +#249#247#182#20#127#190#232'm''V'#169'T'#8#130#160#171#255#160#205#14'4'#155
  +'M'#166#167#167'i'#183#219'\p'#229#197#215#253#254#239#255#254#31#0'C'#20#221
  +#134#221#214'b/'#25#148#30'@'#137'9'#15#183#4#24#12')'#204#204#204'P'#171#213
  +#158#246#152'4M'#243#178'b'#235#206'?'#29'l'#131#17#128#190#190'>'#250#250
  +#250#16'B'#208'j'#181#178'Td'#148#175'A'#152#166')['#166'w'#240#7#127#240#7
  +#191#178'l'#217#178#193#247#189#239'}'#127'D1'#234'w'#236#229'y'#137'x'#2'%'
  +#1#148#152#179'p'#141#214'M'#9'*'#165#248#218#215#190#198#208#208#208'!U'#129
  +'B'#8#218#237'v'#238#198#131#233' '#236'v'#27#238#213#22'j'#181'Z>'#250#247
  +#245#245'188'#200#252#249#243#25#28#28'dll'#140'y'#243#230#229'm'#202'Z'#173
  +#22#203#247#12'033'#195#141'7'#222#248'V'#165#148#255#129#15'|'#224#131#206
  +#233'^R$pL'#9#224#225#135#31'f'#183#156#207#19#219#203'J'#192#18#135'B'#216
  +'h:'#21#200#17'MT'#21'D}1C'#187#239'GO'#205#18'MuhM'#183#168#215#27'LOO'#211
  +'j'#153#223#145#213#7#220'EG'#220#197'E'#128#174#215#189#179#10#237#228'#('
  +#26#145#216#150#227'A'#16#208#223#223#207#192#192#0#131#131#131',]'#186#148
  +#179'O;'#151'j'#181'J'#146'$'#188#251#221#239'~3'#144'~'#224#3#31#248'O'#206
  +'Gy'#201#144#192#209#140'W'#2'L|4'#4#140#1#139#181#214'_?'#138#215'+'#241'2C'
  +#167#211#161#221'nS'#175#215#153#156#156'd'#223#190'}'#204#204#204'033C'#171
  +#213#234#154':'#220#171#236#187#175#221#198#162#135'+'#8#178#253#5',)'#216
  +#252#191#221'n'''#12'Y'#175'b||'#156#211'N;'#141'%K'#150'0<<'#140#16#130#15
  +'~'#240#131#159#248#203#191#252#203#191#0'f'#129'&f'#2#145'M'#23#206'Y'#148
  +'!@'#137'9'#11'w'#161#208'J'#165#194#208#208#16'q'#28#231#221'~l'#157#128'-'
  +#240'q'#195#4'wUa'#247#185#251#23#186'g'#23'Z'#131'w'#9#193#234#3'v'#229'!;g'
  +#224#206';'#239'DJ'#201#242#229#203#217#176'a'#3#127#254#231#127'~'#227#232
  +#232'h'#231'C'#31#250#208#255#160#24#245'mk'#177'9'#139#146#0'J'#204'Y'#244
  +'.'#21'^'#171#213#24#29#29'%'#8#130#188#199#31#144#191'o'#247#175'V'#171#249
  +#244'_7,p'#13#223#205'"'#184#6#239'V'#3#218#249#8#189#4#16#199'q'#238#17#236
  +#222#189#155']'#187'vq'#254#249#231#243'G'#127#244'G'#239#159#157#157#157#254
  +#179'?'#251#179#207'Rt'#24#142#152#195'('#9#160#196#156#133#29#189#195'0'#204
  +#21#127#207#243#232#235#235#203#221'qw'#209#208#195#185#249'O'#215'\'#212#21
  +#24#221#250#130'g"'#3'w'#253#193'V'#171'E'#28#199#244#247#247#211'l6'#185#231
  +#158'{'#152#158#158#230#163#31#253#232#135#155#205#230#129#143'}'#236'c'#255
  +#130#25#253'['#28#218'fl'#206#160#212#0'J'#204'Y'#216#20'^130'#202#139'sz'#11
  +#130'z]|'#139#222#9'E'#189#5'E'#246'='#27'Z'#184'!'#0#20')B{M'#235#13'X]'#160
  +#217'l'#230'i'#194'z'#189#206#169#167#158#202#178'e'#203#212'9'#231#156#243
  +#214''''#159'|'#242'.`'#2'#'#10#206'I'#18'('#9#160#196#156#134#29#133#173#209
  +#245#246#12#132#238#22#226#22#150#8#172#194#239#22#17#245#198#249#246#28#214
  +#192#237#232#239'z'#2#189#239'Yo'#192#134#2#237'v'#155#217#217'Yfgg9'#255#252
  +#243#217#180'i'#211#193#203'.'#187#236'B'#165#212#1#140'0'#216'f'#14'f'#4#158
  +'_='#229#207'>w'#128#169#146#234#3#6'?'#242#145#143'\{'#20#175'W'#226'e'#8
  +#215#181#183'i9)%'#190#239#231#185'{'#155#178's'#31'6,'#176#207#237'_'#171#7
  +#248#190#255#180'b'#161#27'V'#184#2#163#187'J'#177'[Jl_['#29'brr'#146#11'.'
  +#184#160'ovv'#182'y'#199#29'w'#252'$'#251'('#17's'#208#11'(='#128#18#199#13
  +'\'#239#193'>'#183#163#188#235#13#216#247#221#12#129#187#191#235#17#216#134
  +'"V'#148#236't:LNNr'#198#25'g'#176'o'#223#190#214')'#167#156'r'#1#176#31#152
  +#196#164#7#231'TV'#160#156#11'P'#226#184#129#29#169#237#195#213#13'z'#5'C;'
  +#234#187#30#3#144'?'#183#251#251#190'O'#24#134#185''''#18#134'!'#131#131#131
  +'LNNr'#194#9''''#212#22'-Z'#180#4#179#12'y'#136#17#221#231#212'\'#129'c^'#9
  +#184'K'#143#241#196#206'#'#239#233'V'#226#248#134'p'#231#218#185#14#244's'#28
  +#186'T'#146#165#1'}'#157'?'#127'>'#16#194#222#148#7#210#195#216'y?j'#159#224
  +'B'#253#20#23'^x'#225#216#151#190#244'%'#31'ck>'#166#177#232#156#209#2#142')'
  +#1#172']'#187#150#181#192'%'#235#230#31#203#203#150'(qX'#244#10#138#174#240
  +#215#219'~'#220#13#1'zS'#133'n'#213#160#21'+'#219#237'6'#163'#'#227#156'w'
  +#222'y'#235#190#244#165'/'#253#7#134#178#236'c'#206'h'#1'e'#8'P'#226#184#133
  +#219#3#192'.7~'#184#158#129#189#127'{'#197'B7\'#176'"d'#24#134#164'i'#202#149
  +'W^'#249#30#10#195#23#28#207'!@'#137#18's'#13#189#141'El+2'#155':'#132#194
  ,#232#237'('#239#190#238'='#135'%'#146' '#8#16'Bp'#194#9''''#12'P'#24#255#156
  +'CI'#0'%J'#244#192#247#253'<'#28#176'F'#238#22#24#185'K'#151')'#165#186'f'#28
  +#246#246#30#200'<'#135'Z'#246#136'(V'#25#154#19'(C'#128#18'%8'#188''''#240't'
  +#165#196#189#213#135#174'W`3'#4#214#131#200'z'#13#214'0'#245'0'#1's'#204#230
  +#230#212#205#148'('#241'b'#226#217'j'#2'?'#171#136#200#129'm'#27#22'0'#199'R'
  +#129'e'#8'P'#162#132#131'g'#163#9#0']'#229#198#238'L'#195' '#8#220'P'#160'FQ'
  +#7'`'#9'`N'#164#2'K'#15#160'D'#137#159#1#183'l'#216#226'p'#11#142#246'z'#2
  +#206#254'U'#186#9#224'h'#150#224'?+'#148#4'P'#162#196'a'#240'l5'#129#222#208
  +#160''''#4'p'#9#192#206#145#153#19'a'#192'1'#13#1#182'l'#217'b*'#1'w'#148#149
  +#128'%'#142#15#156#184'LA'#247#200'/)'#218#135#191#232'a'#192'1%'#128'u'#235
  +#214#177#14'x'#237#250#177'cy'#217#18'%'#158#23'z+'#6'm3'#146#195'5'#21#233
  +#221'>44d'#159#10#186#139#129#230#132#7'P'#134#0'%J'#252#12#244#134#3#238'tc'
  +#11#183'}'#217#211#181#31#183#187'R'#18'@'#137#18'/-'#244#146#128#219#31#224
  +#153'4'#129'g@I'#0'%J'#188#148#240't$'#224'f'#1#14#215'v|.'#163'$'#128#18'%'
  +#158#5#14'G'#2'@'#190#158#128#221#231'0'#153#128'9'#137#178#16#168'D'#137'g'
  +#9#187#230#160#133#239#251'y'#135' w'#238#192'K'#1's'#159#162'J'#148#152#131
  +#248'Y'#154#192'Ka'#244#135#146#0'J'#148'x'#206'x&M'#192']'#140't.'#163'$'
  +#128#18'%^@'#244'.F:'#215'qL5'#128#205#155'7'#179'K'#141#241#248#142#250#177
  +#188'l'#137#18'/'#26'NZ6'#240'b'#223#194'3'#226#152#18#192#250#245#235'Y'#15
  +#188#238#212#241'cy'#217#18'%'#142':z'#171#5'mU`'#24#134'/'#210#29#29#25#202
  +',@'#137#18'/'#0#172#30'`'#137#160#20#1'K'#148'(1'#231'Qz'#0'%^'#146#176#147
  +'o'#234#141#6#251#14#28'`'#231#190'}'#180'fg'#137#226#136'4II'#243#6#158' '
  +#133'Dz'#30'a'#16'P'#173'TX'#184'p!'#11#198#198#152'72'#146#183#240'z'#161
  +#208#235#9#204'u'#148#4'Pb'#206'Ck'#205#228#212#20'?}'#244#17#166#246#31#160
  +#29#199't'#226#152'Tkj}'#253#12#14#12'R'#27#30#166#127'`'#136'QO'#226#11#129
  +#20#26#161'M'#3#254'Dk'#218#26#210'8&'#238'D<'#182's'#23#15'<'#250'('#245#153
  +#25'$'#16'x'#30#149'0ddx'#152'3N='#149#133#11#22#28#146#226'{'#185#162'$'#128
  +#18's'#18'S'#211#211#220'}'#223'}LNO'#211'N'#18#250#6#6#25'_'#186#140#21#235
  +#22' '#165#135#231'{'#8#173'h'#181#219'4'#163#136'4I'#136#218'-Zi'#138#234
  +#180#209'J'#161#149#6#1'BHD'#181#146#213#234#251#140#140#143#179'$\B%'#172
  +#162#129'T'#165#164'I'#204#228'l'#131'o'#223'y'''#179'SST|'#159#249#243#230
  +'q'#246'Yg'#177'd'#209#162'g'#29#211#191'T'#8#164'$'#128#18's'#6'{'#247#239
  +#231#238'{'#239'e'#182#213'&'#236#239'c'#229#202'U,Z'#189#134#192#243#233#180
  +'[4'#155#13#14'L'#30#164'=3K'#146#196#164'I'#138'Rv'#197#30#0'gE'#159'l'#163
  +'Fc'#254#175#205'>v'#229#31#180'!'#18')'#241'|'#159'Z'#173#143#218#240'0k'
  +#214#174#195#243'|'#146'$fbf'#134'['#190#247'}'#218#205#6'#'#131#3#156#187
  +#241'lNZ'#181#234'%c'#220'G'#130'ru'#224#18'/*'#218#237'6'#223#191#253'v&gg'
  +#233#27#28'f'#229#137'''Q'#173'V'#137#162#136#250#236#12'S'#245'Y'#226'F'#157
  +'$'#142#209#26#132#20'x'#210#182#231#242#8#7#250#241#130#0#207#147'T'#132#7
  +'B'#144#135#244#154#204#3#16#217'KM;II'#226#132'$'#142'h'#205'L'#19'E'#29'T'
  +#146#18''''#9'i'#154#0#2'?'#8#168'T'#170#12#12#204#163#127't'#136#170#231'1'
  +#211'j'#176#227#241#199#153#157#158'b'#193#232'|^w'#209'E'#140#205'?'#178'%'
  +#238#132#16#191#1'l'#3'v'#3#7#128#25#204'J'#193'/'#250#250#0#165#7'P'#226'E'
  +#193#206#221#187#185#227#238#187'Q'#158#199#170#147'Nf'#197#224#16'Q'#212'ab'
  +'f'#138#214#182#6'I'#212'@'#163#17#194'L'#177#173#142#14#18#132#198#141#239
  +'D'#17'*M'#209#192#222#157';'#152#153#158'!U'#9#158#148'H'#207#199#183#203'u'
  +'y'#30'Z'#155'P@cr'#243#181'j'#13'?'#8#24#30#31'g'#213#201'kQ'#206'"'#31#173
  +'f'#131#201#153#25'f'#14#30#160#211'nR'#159#153#134#221#130'J'#165#194#192
  +#208' '''#174'?'#133#154#231#177#127#255#20#255#248'o'#255#134'P'#138'Wl'#220
  +#200#134#211'O'#127#201#164#253'zqL='#128'M'#155'6}}'''#243'yt'#199#236'Q'
  +#188'l'#137#185#140#230#212#14'd}'#23''''#175'Z'#194#9''''#158#132#244'<'#234
  +#211#211'L'#213'gI'#154#205#204'5'#151'x'#181#26'a'#165#10'Z'#211'n'#183#153
  +#153'8'#200#222']'#187'QiB'#187#209'@'#169#132#190#254'A'#134#134'F'#240'2M'
  +#192#15'B'#164#12#241'*'#21#164#223#143#20#130'8IH'#226#6'q'#212'&'#141'c'
  +#132'NMo.'#15#26#141'&'#157'v'#147'Z_'#31#195#163#243#241#195#128#21#171'N'
  +#164#175'o'#0#180#166'9;'#195#158#221';'#153#158#158#166#211'n'#1'P'#173#214
  +#24#153'7'#202#216#130#133'4'#163#14'O='#242'0'#143'='#181#11#209#191#128'E'
  +''''#158#141#232'!'#130#147#151#13#242#134'S'#23#205'Y'#15#160#12#1'J'#28#19
  +'l'#219#177#131#219#239#186#155'yK'#151#177'|'#233'R'#146'8'#230#224#244#20
  +#237'V'#19#162#8#17#134'H'#233'S'#169'T'#136#147#152#153#137#9'v'#237#216'N}'
  +'z'#154#164#211'fxd'#132#209#209'1'#6#6'G'#24#24'[H*$'#224#211'J'#20'q+!U'#10
  +#165'5i'#170#208'J'#161#20#164'J'#129#4'i'#219'uI'#219#177'W '#1#157'&'#4#18
  +'<'#161#153#158#218'C'#218'n'#210#137#218't:-'#230'-X'#200#216#226#165#172'Z'
  +#177#2#207#243#169#207'N'#179's'#219'V&''&'#136':m'#164#231'34<'#204#216#146
  ,'eT<'#143#199#30'}'#152#3'{vs'#218#218'u\r'#225#133']:'#193'\'#14#1'J'#2'(qT'
  +'1=3'#195#173#223#249'6'#3#11#23's'#226#138#149#180';'#29'&'#166#167#136':'
  +#29#0'D'#182#136#6#192#244#193#131'l}'#242#9'f&'#14#18#250'>K'#150',cl|'#17
  +#181#209#5#196#8#234#145#166'S'#143#232't"'#18#173#209'J!'#156#24'_d'#241#127
  +'6'#29''''#211#2'D'#214#127#215#136#131#10#129' ;'#22'H'#205#158'H)'#169#4'>'
  +#232#20'_(Z3'#251#232'4gi6f'#233#27#28'`'#233'I'#171'Y'#127#210'j'#162'Tqp'
  +#223'^'#182'>'#241'8'#245#198',h'#24#24#28'b'#193#138#21#212'<'#159'-['#30'b'
  +#250#192#1'.'#189#248'b'#214#175']k'''#5#149#4'@I'#0#199#21#148'R'#220#242
  +#173'o'#17#9#201#234#181#235'QJqpj'#130'('#234#152#152'[H'#130'0$'#138'"v<'
  +#245'$['#159'x'#28#31#205#242'e+Xz'#226#26#130#190'!'#26#29#197#244't'#155'v'
  +'''2'#181#245#144#27#184#200'Fr'#207#19'Y'#161#143#196#19#2'O'#8'DM'#226'!'
  +#232#175'VPZ'#19#199#177'Q'#255#133#0#173'I'#181'B'#153#228#128')'#24'j'#27
  +#207'!V'#153#247#160'M)'#175#239'y'#248#164'D'#173#131#212''''#246#211'j'#214
  +#25#25#27#227#172#179#206'bt|'#156#253#251#246#243#248'c'#143'0=1'#129#214
  +#154#161#225'a'#22#174'X'#137#210#154'-'#247#223'G '#4'o'#189#234'*F'#231#205
  +'+'#9#128#146#0#142#27'l'#223#185#147#31#221'}'#15#235'O?'#147'Z_'#31#19#7
  +#247'So'#181#192'.'#160#25#4#180#154'M'#30'}h'#19'{w'#237'`|d'#30#171'O^'#199
  +#216#226#229'LF'#154#201#201#22#173'N'#132'R'#26#1'xR '#164#200#12'^'#18'z'
  +#30'~'#213'#'#12'<|O'#226'y'#18#207#247#168#137#140#20#164'@'#3#223#190#227
  +'?X4'#127#148#179'N=%'''#1#132'05'#2'hC'#2'*E)M+U'#164'Z'#147#164#138'8I'#137
  +#154')'#137'JI'#18#5#218'\W'#234#132#230#228'.'#166''''#246#17'T'#2'V'#159'~'
  +#6''''#173':'#145#217#233'i'#30#219#242#16'S'#147#19'h`'#222#232#24#203'W'
  +#172'`'#223#190#189'l~'#240#167'|'#233#139'_'#252#251#251#239#186#251#239#146
  +'8'#222'AI'#0'%^'#174'PZs'#243'm'#183#17#206#31'g'#245#137''''#209#152#153'a'
  +'bv'#134'4'#137#209'Z'#211#23#4#204#182';<'#252#211#159#176'k'#251'6V,Y'#202
  +#186'3'#207#166#218'7'#196#238'z'#135#153#137#6#137'R'#8'm'#140'^z&n'#15'|'
  +#159#176#230#17#4#30#149#192#167'?'#240#8'|'#207#180#231#206#188#0'O`R'#128#8
  +#2')iF'#17#191#244'{'#255#153'3'#215#173#225#191#190#239'F:q'#132#210#134'P'
  +#148#206#242#131#152'*'#195'T'#169#204'30'#158'@'#170'4i'#146#210'L'#18#162
  +'T'#145#196#138'V36d'#128'!'#152'N}'#31#7'wmE'#145#178'~'#227'9'#172'=y-'#147
  +#7#246#179#229#161#159'2;3C'#24#132',X'#180#152#209#177'1~'#250#192'O'#184
  +#245#230'o|'#255'G'#223#253#222#127#217#189'}'#251#22#230#16#1#148'i'#192#18
  +'/'#8'f'#235'un'#251#193#15'8u'#195#217'T'#251'jLML'#16'w:T<'#129#244#170#164
  +'J'#177#249#161#7'yt'#243'f'#150'/Y'#204'UW^MT'#25'`'#239#190#6#245#253#7#209
  +'Z#'#17'fD'#151#130#208#243#9#251'}*'#161'O'#173#18'2'#16'x'#132#129#143#239
  +'K'#2'O'#154#234'>L'#173#191#13#245#181#206#198'3)'#17'@'#24#134#248#158#135
  +#198#144#138#204#22#227#145#136#140#4#204#177#190'g'#222#241#181'F'#251#30'h'
  +'L'#153#177'R'#168'T'#145#166')Q'#127'H#I'#233't'#18#218#173#132'p`!'#203#214
  +'-$'#154#221#207#230'{'#238'c'#243'}'#247'r'#225#197#151'p'#209'k_'#207#150
  +#199#30'g'#219'#'#155#217#177'm+SS'#147#156'|'#202'i,Z'#184#232#194#149'+W~'
  +#250#174';'#238#252#208#143#191#255#253#175#198'Q'#244#162#252';'#245#162'$'
  +#128#18#207#27#247'?'#248' {'#235#13'^y'#225#197't'#162#152#217#233'i'#0#252
  +'0'#160#226#213'x'#242#241#199#184#247#174';'#25#172'Vy'#195'eo'#164'60'#143
  +'m'#251#26#204'6'#14' '#208'H!'#17#158'1'#254'J'#24'R'#237#247#169'U'#3#134
  +#194#128'J'#24#16#6#30#129#20'&'#238#183#214#14#20#149#127#186'x'#13'y'#181
  +#159#159'U'#250#169#188#18#176#168#10#20#25#25#168#236'p'#141#194'u'#136'='#1
  +#158#239#161#164'Dy'#30#129#175#232#211#154#184#146#210#232'O'#136'"E'#179#19
  +#131#24'g'#229#250#5'4'#166'v'#242#157'[naht'#30#175#186#248'u'#172'\'#182
  +#140#251#239#190#139#137#3#251'x'#252#161#7'Y'#186#234'D'#222#248#182#183'/['
  +#184'h'#209#255'X'#176'h'#225#153#15'o'#222#242#225#159#222'sO'#233#1#148'xi'
  +#227#27#183#221#198#162#21''''#240#138'sNajf'#150#168#211'Az>a'#16#210'j'#181
  +#249#225#247#191#203#174#167#158#226#188's'#206'e'#241#170'5l'#155'j'#243#228
  +#147#7#0#240'2M '#240'=*a@m'#208'g'#164'Z'#161#26#134'TBI'#197#247#241'<'#219
  +'b'#203'\'#175'k1='#173#209'v'#133'=M'#177'$'#151'0'#158#129'N4i'#172's'#179
  +#22']gPh'#4#210#146#134#201#13'd'#132'`'#230#16'Hm'#182#11'i'#132'F'#180'FJA'
  +#160'$*'#208'D'#21#159'z'#148#208#142#19'du9'#3'#'#139#153#216#243#4#255#250
  +#165'/r'#198#198#179'9'#247#213#175#230#169#173#219'x|'#211#3'l{'#244#17#230
  +#141#142'r'#241'k/'#29'X'#184'h'#241#7#250#250'o]'#178'l'#229#138'_'#191#249
  +#203'_'#153':*'#255'0G'#136#146#0'J<''('#173#185#229';'#223#230#212#13'g126'
  +#198'T'#189#129#214#26#207#247#169'x'#30'O'#236#216#198#15'n'#185#153#177#161
  +'!'#174'~'#235'/r '#18'lzr'#130'D)'#164'0q'#187#153#133#23#208'?'#20'0R'#173
  +#210'W'#13#168#4'>'#129'/'#17'R'#228'n'#190#173#243#207'a'#13#221#142#236#202
  +#190'!'#156'Q>['#174'K'#8't'#230#198#155'RbI^#LF'#14':'#247#29#242#203'h'#13
  +')'#26#145#211#131#217#219'z!BB'#213#151#132#129'G'#156#6#212';'#9#29'_'#178
  ,#224#196#181#140#204'_'#202#150'M'#247#177'm'#235'S\r'#233'e,x'#205'E'#220'w'
  +#247#157'L'#30'<H'#167#211'a'#229#154#181'\=<'#242#246'[n'#254#250#194'+'#127
  +#225'm'#255#135#31#132#143'~'#245#239#254#238'EY('#244#152#138#128#15'>'#248
  +#224#215'w'#136#249'<'#178#173#236#9#248'R'#134'J'#19#170#141'Gx'#251#21#175
  +#163'6'#208#207't'#171'C''U'#160#21#18#193#29'?'#254'!'#247#254#248'v^}'#222
  +'+Y'#176'r'#29#143#236#152#162#209'l'#25'%]@%'#12#25#28#169'P'#9'='#170'A'
  +#192'H'#173'B'#173#226#19'x^f'#248'"7r3q'#7#199'H'#157'I='#217#253'8KtB'#150
  +#194'ku:'#188#235'?}'#148#211#215#172#230#255'|'#215'/'#209'h'#155#244'c'#24
  +#4'H)'#28'R1'#207'U'#22#2'hU\Wd'#158'@'#182#1#165#139#231#8#227'1x~'#128#4
  +#154#237#14#141'$'#161#29#165'DI'#138'J5'#7#183'='#198#174#237'O'#240'sW\'
  +#193#178'e+'#184#243#206';'#216#191'g'#23#158#239#179'r'#205':4p'#203'W'#191
  +#188'y'#203#150#135#127#205#243#253';'#191#246#197'/'#230'Tv'#172'Pf'#1'J<+D'
  +'q'#204'7'#191#247'=^'#127#193#133#212'*!'#179'QB'#172#21#169#148#180#218#17
  +#255#242#143#255'@s'#242' '#175'{'#253'e'#204#136'*'#219'wN'#162#148'6'#213
  +'x'#158#160#191'Z'#229#224#212#30'~x'#239#189#188#243'-W'#178'f'#233'"'#200
  +#202#127#5#214#176'@g'#11'lt'#25#191'.'#188#1'w'#184'tW'#227#5'#'#246'%i'#194
  +#239#252#215#255#193#178#133#227#188#231#218#159#231'`'#179'I'#191#239#211'W'
  +#171#18#4'funw'#6#161'r/'#6#14'A'#184#175#179'-'#217#220#130'Z%'#228#7#247'<'
  +#192'}['#30#230'W'#175#190#146#192#243'H'#149'&J'#18#154#137'"U'#130#217#253
  +'{xt'#211#253'j'#241#202#21#242#194'K^'#199'cO<'#206#19#155#30#4#1'+N^K'#181
  +#175#198'-_'#253#202#182#7'~'#242#147#223#243#252#224#159#255#229#239#255#254
  +#152#146#192'Ks'#6'C'#137#23#5'Q'#28's'#235#247#191#207#207']|'#9'}'#149#16
  +#173'5'#129#132#190'JH'#210'n'#243#247#159#249#20'~'#154'p'#249#149'ocg['#178
  +'u'#251'A'#148'2)'#189' '#240#24#28#174#178't'#225' }'#149#128'['#127'x;_'
  +#187#245'6'#250'jF'#169#23'Y'#26'O9'#177#188#13#199#15''''#244#137#174'W'#14
  +#178'NA'#3'}5'#206'?'#227'T'#250#171'U'#162'8'#166#211#142'i'#196'i'#214#172
  +#211#30#167#10#227'/'#174#8#186'p'#253#13'D'#215#30#8'S'#23'09['#231#19#255
  +#248'U~t'#239'O@'#171#188'8)'#244'='#134#171#1#3#1#140',\'#200#186'3_'#213
  +#217#183'sw'#252#141#175'~'#153'S'#215#174#227#204#179#207'Az'#146'm'#15'o'
  +#161'q'#224' '#151#189#229#173'+6'#156#181#241'/'#147'8'#250#133'7'#253#226
  +#219#143#233'\'#227#146#0'J'#28#17#146'$'#225#230#239'}'#143'K/'#186#152#138
  +'o~'#163'R'#8'j'#190#207#158#221'{'#248#244#255#254#4#203#23'-'#228#149#23']'
  +#198#230#29#211#28'<PG'#10#137#231'K'#170'a'#200#188#209'>'#150#140#244'3'
  +#212#31'r'#209#185#27#184#250#181#23#241#245#239#254#136#255'x'#232#17'*a`by'
  +'t'#238#242'kMV'#8#164#16#194#217#158#153#166#29#160'E'#254'?k'#166'Y^P'#10
  +'|'#207'CJ'#15#149#149#254'j'#221#237'U'#20#156'b'#189#11#157#147#131#245'8'
  +#236#205'd'#252'd'#178#16#2#170'~'#192#215#190#245'}v'#236#222#205'uW]'#193
  +'@_'#127#166'3d3'#24#129'J'#224'1'#16'zT'#135'+'#226#180#243'^'#211#145#194
  +#239'|'#241's'#159'adt>g'#157's'#30'A'#24#178'}'#251'V'#166#247#238#225#13'o'
  +'~'#203#210'3'#206#220#240#255#166'Ir'#245#155#223#241#142'cF'#2'%'#1#148#248
  +#153'PJ'#241#205#239'~'#151'K/'#188'07~'#139#199#183'n'#229'o>'#245'IN_w'#10
  +'kN?'#143'M['#15#208#236't'#144#2'|_2X'#171'0'#127#188#143'%#'#3#140#14#245
  +#209'W'#9#9#3#201#13'o'#187#138#225#129'~>'#251#207'_'#165#29#199#8'$'#202
  +#250#225'YnN'#138#130#12'ta'#222'Hk'#244#162'W'#217#7#132#227'=d'#132'"'#16
  +'ham9'#163#17'k'#209#153'P('#133'%'#17#225'x'#23']'#28#128'V'#198#253#175'H'
  +#143#199#246#236#227#223#190#251#3#206#223'p:'#175#127#229#185'tb7'#163'g'
  +#238'['#10'I %'#195'a *'#21'_'#174'9kc{l|a'#243#31'>'#247#25#141#244#216'p'
  +#206'yT*Uv'#237#218#193#204#190'}\~FO'#183#139#0#0' '#0'IDAT'#245'['#151#175
  +'_'#191#254'O'#163#168's'#249'['#174#185#230#152#216'fI'#0'%~&'#190#249#237
  +'o'#243#234'W'#190#138#190#158#30#247#143'<'#241#4#159#254#236'g'#184#228#213
  +#23#176'p'#213'z6?u'#128'('#138#145'BP'#241'}'#6#134#171#140#206#239'c'#225
  +'P?C'#253#21#194#208'4'#238#136#226#132'UK'#23#243#142'+.'#229#238#7'6s'#235
  +#15'~L'#24#250'X3'#23#185#249#22#3#181#204#13#211#221#234#198#255#221'a'#130
  +#208#153#238' '#133's'#222'bW'#173#178'c'#157#227#13#17#24#195#21#152#231#246
  +'8K'#30'Z'#153#9'D_'#254#198#173't:'#17#239#184#236#245#4#158#151'-'#10#170
  +'Q'#232'|'#222#130#221'&'#165#144'}'#158#240'<'#129#127#242#186'S'#163#181
  +#235'O'#171#127#229#31#190#168#227'4e'#195#217#175' '#12'+'#236#218#185#157
  +'v'#179#206#27#223#250#246#213#203#150'/'#255'P'#179#209'Xy'#245#181#215#30
  +#245#165#133'J'#2'('#241#140#184#249#223#255#157'S'#207#220'@'#173#191#143'X'
  +#21#209#242#227'['#183#242#153'/|'#158#215#191#225'r'#252#5'+y'#248#169#3'$'
  +#169'BJA5'#8#24#158'We'#241'p?'#139#134#251#24#168#133#248#190#135#231#180
  +#234#233#196'1'#191#240's'#175'c'#245#9'+'#248#252#191#220#204#222#253#7#241
  +'='#9'Ze'#14#184#200#205'Vd'#138'{'#183#173#219'X'#221#192#166#243'D'#150#187
  +'7B'#189'D'#246'D'#243#206#222#5'4'#152#130#2#163'A'#228'j?'#178'(@'#192'\3'
  ,#12'}'#238'~p3'#223#187#235'^.}'#213'y'#156#177'f'#181#25#253#179#16'Ed'#30
  +#134#178'*'#131#6#129#22'RJQ'#243#164'''H'#253#147#214#172#141#207'<s'#227
  +#204#215#254#233#239#149#18'p'#230#198's'#240#164#199#214'G'#31'A'#165#9'W'
  +#189#249#234'W'#140#143#143'}'#172#221'j-'#248#249#163'L'#2'%'#1#148'xZ<'#176
  +'i'#19#11'W'#156#192#192#188'Q'#147#234'K'#12#1#236#218#191#159#191#253#252
  +#231'x'#221'E'#151' '#7#199'yj'#235#1#148#6#207#19#212#194#128#225#249'U'#22
  +#12#245'32X'#165#26#6'E'#235'mA^l'#147'$)C'#131#253'\'#127#213#229'$I'#194
  +#238#201')'#147#158's'#13'_'#27#131#210#185#177'['#5#224'P'#161#220'p'#130
  +#176#188'`'#12#175'k}'#190#194#142'D'#198#20'6'#132#16#217'0'#175',U8'#174
  +#130'='#159')@4'#237#200'v'#237#219#207#178'E'#11'y'#243#27'^k:'#19')U'#184#9
  +#25'a'#9'G'#200'TZ'#162'M'#157#178#244'<'#207'S*'#9'N^'#183'.>'#235#172'sf'
  +#255#229#31#255'A'#247#15#14'q'#250'Y'#27#1#216#250#200#22#6#199#198#184#226
  +'MW]Q'#171'U'#255'K'#187#221#238#127#161#254'='#15#135#163')6x'#152'T`'#5#147
  +#14#28#252#200'G>r'#237'Q'#188'^'#137#23#16#245'F'#131#135#182#239'`'#205#218
  +#245#212#27'M@'#18'T'#2':'#237#22#159#252#244#167#217'p'#218#153#140'.;'#137
  +#199#182#30'Dg'#198'_'#13#3#134#231#215'X44'#192#240'@'#213#212#238'{'#30'B'
  +#232'|'#132#204#139#245#132#17#22'OX'#182#132'+.z'#21#139#230#207'#M'#179'r\'
  +''''#29#7#228#148'`,'#177#200#1#232'|'#223'"V'#183#255#13'|'#143'M'#143'<N'
  +#163#217#226#148#147'O'#160#29#197'x'#190'G'#127#24#224'y^F'#12#238#232'n'#3
  +#133#238#180#159#209#20#173#254' HU'#202#170'eKx'#253#249#231'2'#210#223'G'
  +#146'*7%Q'#164'1)8A)'#165#179'~'#134'Zd'#31'Gk-'#198#23','#136#5#168#255#248
  +#241#237#149#11'.y-'#137#16#28#216#187#135#250#244#20#167#158'v'#6#192#250
  +#199#30'}'#164'~'#202#153'g'#222#243#240#166'MGe'#161#129#210#3'(q'#8#180#214
  +#220#246#195#31#178#254#148'S'#152#153#154'"'#141'c'#20#154'f'#167#195''''
  +#255#246#211#156#176'l'#25#203'NZ'#207'#'#219#14#162#148#198#147#152#145#127
  +'^'#149#133#131#253#12#246#133#4#129#143'''%'#184#10#190#9#137#17#142#210#174
  +#209#244#215'j'#142#186'_'#24'~w'#169#143'5L'#153#239'K'#158#30't'#247'+'#158
  +#217'9'#253#136'\'#239#203#208']WlFi'#215'l'#139#172#130#232#185''''#165'5'
  +#129#239'S'#173#134#166#152'Xf'#156#228'*'#133#206#247#152#221#163#169'mRZd3'
  +#156'%Z'#251'q'#156#132#235'N='#189#179'`|'#188#241#165#155'>'#207#234#147'V'
  +#179'p'#209#18#218#205'&'#143'n'#217#204#171'/'#184#176'v'#198#153#27'~'#187
  +#221'j]'#245#230'_'#250#165#163'2X'#31#211'R'#224#159#254#244#167'l'#23#227
  +'<'#178'}'#230'X^'#182#196#179'D}'#199#189#188#237#141#151#208#156'm'#144#164
  +#9'aX'#193#19#130#127#250#210#151#232#15'C'#214#159'y>'#15'<'#185#159'8V'#248
  +#158' '#172#4#12#142'T'#24#31#232#163#191#22#18#248#129')'#193#213#133#11'm'
  +#226'cs~'#27#31#139'L'#154'O'#178'|<'#224#24#182'm'#228#227#168#250'N'#133
  +#160#245#1're_'#136'b'#212'v'#142'+t'#253'l'#172#179'#t'#246'~'#154#25#175#6
  +#132'r'#189#8#157'o'#207#239'Kd='#4#180'r'#10#131#178#208#198#169#26#212'Y'
  +#22'C97'#148#205'Z'#200#188#24#169#149#214'Rh'#237#199'q'#172'7'#156'sn'#235
  +';'#183#221'"'#255#253#155#223#168']~'#197#149'|'#247'['#183'159'#193#190#189
  +'{'#184#244'Mo^'#188's'#199#142#247#28'<x'#240#142#159#191#246#218#29'_'#190
  +#233#166'C%'#141#231#129'cJ'#0#167#159'~:'#167#3'W'#156#182#232'X^'#182#196
  +#179#192#246#157';yx'#225':'#148#210'4'#235'3'#4#149#10#190#239#243#227#219
  +#127'Dk'#226#0#151'_'#249'V6'#239#156'D'#169#148'0'#144#198#237#31#173#178'`'
  +#192'('#253'f'#228#23#249#178'\v'#244#151#2#180#25#250#243#216#219#245#244
  +#237'H'#155#199#228'Y'#252'-'#178'i'#190#153#223#156#223#167'k'#236#135#164#2
  +'1~'#182'/'#189'\'#3'8'#244#191#230'$^'#182'A9'#199#185#161#138#133#157'A'
  +#224'e'#179#17']b*'#218#142#155#237'*['#149'Hd'#133'ME'#233#176'-v'#212'"'
  +#211'('#164#208#218'OS'#165'_s'#209#197#141#127#255#230#205#222#182#167#158
  +#12'7'#158's'#30#183#255#224#187#236#222#177#131'5g'#204#231#210#203'.'#191
  +#248'K'#127#247#133#223#142#162#232'C@'#227#136#255'1'#143#0'e'#8'P"'#135'R'
  +#138';'#238#191#159#229#139#22#179'o'#226#0#169'N'#241#164#228#137#237#219
  +#184#247#199'?'#228'u'#175#191#140'''''[4'#154#29'<!'#8#3#159#193#225#10#227
  +#253'}'#153#241'{x'#162#24']'#237#232'/'#177'DP'#140#146#185'5'#228#142#191
  +'3'#178'k''l'#200'6'#22'9'#255#222'#'#138')'#192'9t'#161#19#24#253'@d'#231
  +#176'"a'#247#232'^X|v'#15#218#138#131'"'#15#29#28'I '#235'-'#144#165'&'#173
  +'G'#225'D'#21#194#185''''#209#203'$'#230#187#16'F'#227#212'Bk'#229#165'i'#226
  +'{~('#207#185#224#162#250#191'~'#237'+i'#138#230#164#211#206'@'#165')'#219#30
  +'}'#132#211'N?'#157#13'g'#159'}}'#167#211'y'#235#155#127#233#29'/'#232#160']'
  +#18'@'#137#28#183'|'#235'['#172'9'#229'4&''''L'#23#159#212#180#228#254#209'm'
  +#183#240#154'W'#190#154#25'Y'#229#224#129'Y3'#133'7'#240#233#31#170'06Pc'#168
  +#175'B'#224'w'#167#220'TW'#154'Ng'#142'x'#246's;'#196'&'#156#198#30']'#174'{'
  +'w'#30'^'#229'f'#175#187#22#244#148#194#166#11#179'~'#129#153#213'z'#158#151
  +#247#235#23#142#21#23#165'>'#135#10#129#144#133#26#142#240'g'#254#22#18#161
  ,'v'#9#193'V'#17'*'#157'u'#28#178#23#17'9'#129#184#158'GFB&'#31'b&'#24#9#141
  +#240#146'$'#14#230#143#204#211'g'#156#190#161'~'#235#215#255#149'U+V0:6Ncv'
  +#150'];'#182's'#241#207']>'#127't'#254#232'/w'#218#157#179'_'#200#212'`I'#0
  +'%'#0#152#153#157'E'#12#13'#'#132#160#222'j'#130#214#248#158#199#29'?'#250'!'
  +#227'#'#195',=a-'#219'wL"'#133'i'#220#209'7'#16#178'`'#176#198#200'@'#149#160
  +#226'#'#165'4'#134#161#141#241'['#177'^'#139#172#25#167#9#232's'#3'7'#171#251
  +#22'Kyuiy'#14#180'.'#246#17#206#255#204'k'#199'@'#179'v`v'#200#182#161'D'#161
  +#246';U='#217#155#174'&('#243':_'#187#173#200#8'8'#27#139'{'#2#148'V('#157'B'
  +'V'#174','#232'&/'#251#177#242'{'#179#30#144#128#142#210'R'#8#164#253#134'4x'
  +'I'#28#7'kO=5N'#147#180'u'#215#29'?'#230#172'W'#156'GP'#13#217#187'g7C'#181
  +#26#23'\t'#241'Ei'#154'^'#17'''q'#245#200#255'e'#159#25'%'#1#148#0#224#182
  +#239'}'#143#229'K'#150'r kl'#233#7#1'Om}'#138#189';w'#240#234#215'\'#194'c'
  +#187#167'I'#149'Bz&'#238#31#26#168'2'#216'oR}'#178'kym'#199#200#173#251#141
  +#171#164#219#248#217#169#206#203'57'#199#237#207'G'#250#194#144#11#159#192'e'
  +#139'n#u_'#21'-'#194#237#149#201']'#253#226#188#135#251'6'#178#243'g$'#224'*'
  +#7'6|('#242#153'2'#127#207#158#203'^G'#233#174#169'JyB1'''#165#236#18#157#172
  +'F@'#163#188'$I'#253'W\xQ'#243#129#251#238'I'#26#141#6'+O^G'#154'$<'#249#248
  +#163#156's'#206'+'#188#19'N\'#245#142'v'#171'}'#201#213#215'\'#243#130'd'#5
  +'J'#2'('#193#214#237#219#25'Y'#186#156'V'#179'A'#28'Ey\'#251#192'}'#247'p'
  +#254#185#175#224'`'#226'Qo'#180#241#132#160#226'{'#12#14#135#140#245#215#232
  +#171#4'f'#26#175' S'#199#173#222'%pk'#242'm'#26#160#136#191'3'#247' '#183#229
  +',+'#224'x'#228'E'#12'^'#4#225'Z'#216#232#159#252#248#156#22'r'#146'('#178#7
  +#158''''#17#217#253#9#1#161';'#228#131#227#166#155#210'_O'#144#181#22'7'#174
  +'}'#238#252'[.'#200#201#160#128#245'B'#242'1_'#23#30'B'#151#231#1'dw'#130#0
  +'*2'#11#5#180#22'!d'#179#30#132#167#181#246#135'j}'#172']wJ'#227#219#183'~'
  +#147#245''''#175'e`h'#152#153#169')f'#219'-^'#253#154#11#215'H)'#174#140#226
  +#232#5')'#16'*'#9#160#4'w'#221#127'?'#139#198#198#153#152#158#6'!'#8#130#128
  +''''#182'lf'#164#191#159'e'''#174'c'#247#30#179#221#247'=j'#131'!'#243#251'k'
  +#244'WL'#170#207'f'#230'D'#230#226'[C'#233#142#222')'#216'A'#219#132#152'U'
  +#225'2S'#17#197'Xi'''#234#24'n'#16#197#136#171#237#153#139#137';'#214#186#173
  +#2#127'H'#200#224#196#224'@>'#233#199#14#215#249'U-'#153'8'#161#132'D'#27#215
  +#190'+2'#16'&'#247#239#26'<&'#139'`'#230'.'#22#190#141'+\'#130#209#14#242#203
  +#211#165#7#8#173#145#218#16#129'L'#146#196'_'#127#234#233'q'#187#209#232'l'
  +#223#246#20#235#214#159#138'@'#176'g'#219'S'#172'Z'#187#150#19'OZ'#253#198'N'
  +#187#253#134#23#194#11'('#9#224'8'#199#227'O>'#201#252#21#171#168#207'N'#163
  +#148'Q'#253';'#157#14#143'o'#217#204'9'#175#190#144#29'3-'#146'4'#197#147#208
  +'?Te'#193'P'#31#3#253#21#252#192#207'&'#218'd'#208'v'#160#182'u'#252#128'V'
  +#249#204'>'#215#185'/,'#166#136#137'-'#138#216#217#186#201#206#168#159#185
  +#244'=6'#157'Aug'#2#28#152#248#220#185#128'#'#7'H'#180'yd'#238#135#27'\(g'
  +#231#220'u'#183#4'!'#139'@'#196#13'hLG#'#247#218#150#168#138#157'm'#200'dNg'
  +''''#30#217'U'#143#165'0'#217'I!'#207#216#176#177'q'#219#173#223#212#243#198
  +#198#25#158'7'#143'f'#189'N'#163'>'#203#185#231#157#191#194#243#188#203#162
  +'('#26'z'#154#127#214'#FI'#0#199'9'#238'{'#240'A'#198#231#141'0q`'#26#29#153
  +#216#127#203'O'#31'`'#217#146#197#244#247#207#231#224#129'Y'#132#16'T'#130
  +#128#184#209#198#19'0<'#216#143#231#217#152#216#252'G'#219'2'#191#158#148#154
  +#221#199#245#250#243'V[y'#173#190'5'#180#204#8#181's'#144'('#194#3'WX'#203
  +#175'a'#255'*'#10#227#204#144#159#187''''#216#183#166'^'#24#167#149#239'4('
  +#151'H2'#211'v^'#22#197'M'#217#231'w'#200#4#231#10'B8'#170#135'03'#12#201#179
  +#2#8'{oB'#8#164#231#139'j'#24#138'}'#211'3b6'#142#165#16#200'4M'#130#165'+V'
  +#164#181'j'#173'}'#223'}'#247'p'#242#250'S'#145'R'#178#127#231#14#150#175'Z'
  +#197#138#149'+'#223#208#238#180'/}'#190'^'#192'1-'#4'z'#224#129#7#216#161#23
  +#240#240#182#233'cy'#217#18'O'#131'N}'#146#141'''/'#165'^'#159'A'#169#14'~'
  +#173'Fk'#186#197#158#29#219#185#234'MW'#243#196#238'i'#226'DS'#173'x'#132'}'
  +#30#127#253#217'/'#208#142':'#188#251'mo'#230'u'#231#159#139#244'%'#157'(.'
  +#242#234#185#205'k'#208#142'!#2'#133'='#243#3#10'C'#200'GP'#129'F'#169'.'#135
  +#185#235'^'#205#169#186'$>'''#163'@'#151#129#219'sJ)3'#151'_'#20#252#146#159
  +#217#222#143'=G6'#219'P'#22#19#138#220#189#173'~'#161'3W'#199#22#250'h'#232
  +#170#248'+N]'#140#250#133'8'#232#146#19'BJ'#161'+A'#192#129'z'#131'/'#223#250
  +'#'#239#203#183'}W'#190#241#226'W%'#191#242#150'7'#234#168#19'i'#149'*'#255
  +#204's'#207'k'#253#232#187#223#174#158'q'#198#6'18<'#194#244#212'$'#237#217
  +#25#206'8s'#195#242#167#158'|'#242#226'8'#142'n'#5#158'sg'#225'cJ'#0'g'#156
  +'q'#6'g'#0'W'#156'YV'#2#206#5'|'#237#230#155'Y4'#255#20'vn'#223#10'h'#130'0d'
  +#211#166'{Y'#177't)Am'#152#214#222#253'T'#2#143'j'#224'32'#216#199#213#151'^'
  +#196'M'#255#250'M>'#252'W'#31#231'['#175#184#147#235'~'#225'-'#156#177'j'#5
  ,'Q'#154#144#196'iW'#200#15'`+'#251#128#174#217'qR'#184#239';:'#2#134#8'z'#155
  +'~'#185#200#133'9'#156#183#243#235#234'.'#247#222'v'#5'.'#234#17#220'8'#31
  +#180'2'#133':'#182#181#184'p'#174'!1'#243#254#15#177#237'\;'#176#181#13#186
  +#235#254#237#127#237#231#20#2#210#212#145#4#179'k'#133'a@'#146#164'|'#231'?'
  +#238#21#255't'#235'w'#228#19#219'w'#136#211#215#174'Q'#231#158#178'N'#167'i*'
  +#180#16'R)'#229'/'#154'?'#214#25#26#28'loz'#240#129#218#234'5'#235#184#231
  +#206#219#153#156#156'd'#229#202#149#140'/Xp'#241#254'}'#251'/'#184#250#218'k'
  +#191#241#149#155'nzN'#147#133#202#182#224#199'):'#157#14#162'R#'#142'"'#210
  +'$'#193#243'}'#226'8f'#223#238']\y'#197'Ul'#159'nf'#19'_$'#181#129#128#161'j'
  +#200#155'_{'#17#151#156#179#145#127#188#229'[|'#249#182#239'p'#223#31#255#25
  +'W'#190#246'5'#252#226'e'#151'2:o('#155#205'g'#160#173#209#137'l5^'#155'5'#19
  +#206#251'V'#223'S:'#223'/'#183#232'LTt$'#248#194#248'4y'#247#222'.'#171#205
  +'!'#186#188'~K'#6'y'#180#145#143#228#218#229#141#156#8#138'J'#198#30'a'#210
  +#222#157'6'#198'o'#230'.'#138'\'#11'QJu'#241#149#214#5#9#184#247'!='#201#230
  +#199#158#20'_'#249#214#247#229#157'?'#217'$'#150','#28#215#239#187#238#23#211
  +'K'#206#221#168'|'#223#215'q'#28#11#132#16'B S'#165#188'S7ll'#222's'#199#237
  +#213#141#27#207#17#253#131'C4'#27'u'#188#209#249#172'['#187#238#228#221#187
  +'v'#157#147'&'#201'w'#129#217'#'#252#167#239'B'#169#1#28#167#248#222#237#183
  +#179'|'#197'J'#14'NO'#161'5'#248#181'>vm}'#138#5#163#163#4'}'#195#212#167#154
  +'x'#18'*'#190'G_5'#164#175#234#19#197'1CC'#131#252#198'5o'#227#227#127#252#7
  +#188#250#236'3'#249#231#155#191#197'_}'#230#239'H'#149#234'2'#208'B'#175#215
  +#185'Q'#20'^'#186#29'5'#133#153'<'''#172#135#224#248#12'V'#201#23#174#133#219
  +#176#194#202#5#133#210#158#27#185#163#206#155#209'^'#22#210#187#19'6'#228#231
  +#204#11#2#200#141'_A'#190#142'`'#175#166'Pd'#30'tf'#220'E9'#176'%'#30#251'Y'
  +#221#10'E{'#9#223#247#216'51'#197#159'}'#234'&'#249#208'cO'#138#183'_'#254'z'
  +#245#127#255#246'{'#210#203'_s'#190#6'D'#28'''B'#26'!Qh'#141'T*'#245#151',\'
  +#164#2'?h'#239#221#189#131#165#171'ND)'#197#204#204'4'''#173'>'#217#239#239
  +#239#191' '#138#162#179#158'ku`'#233#1#28#167#152'm'#181'Y'#228'{tfg'#243'^'
  +#252'['#159'x'#156#243#207'~'#5'{f'#218#164'J'#17#4#146#218'@'#200'p'#173'B'
  +#224'yH!H'#210#212#204#227'_'#178#152#255#252#27'7p'#201'y'#27'3'#13#192'X'
  +#144#202#244#0'c'#144#153'6'#144#137'b.l'#243#14'a^8q9'#20'Q'#186#245#237#139
  +#5'?'#204#27#154'n'#211#236#133'I'#5#250'2[`'#4#28#18#200#220#243#236#220'v'
  +#228#215'Y'#204'n'#220#127'm2'#0#185#147#145'W'#247'g'#132#228#4#0'V;P'#221
  +#239'[G'#198#240'M'#150'$'#205#194#129#209#129'>'#174'y'#227#27#212#138'%'#11
  +#245#250#147'N'#208'q'#146#210#234'Dd'#204'&'#10'"'#17'f'#202#1#218';i'#245
  +#201#237#219#127#244#163#218#229'o|'#19'O'#134'!'#173'f'#147#177#5#11'Y'#190
  +'b'#229#25#15'o'#222#188#182'Z'#171#222#1'<'#235#5#7'K'#15#224'8'#196#190#3#7
  +#24'^'#188#132'f'#163'N'#154#166'x'#178#198#204#196'A'#2'!X'#180#236#4#166
  +#167#154#8'a'#22#232#172#213#2'*'#161'Yc'#15#200#221#231'v'#212'!N'#18'.8'
  +#247',.8w#Z+'#148#173#6#178'n'#175#181#3#243'c'#206#175'_'#24#191#29#245#237
  +#251'E'#246#160#171#3#160'vB'#136#174'LC'#129#188#163#176#182#186'Bq'#19#174
  +#162' D7q'#228'W'#204#157#1'3g'#193#246#7#204'3'#1'B'#224#9#153'{'#18'R'#200
  +#226#216#204'['#176#130#163#245'N'#138'+'#20#27#148#214#132'A'#200'e'#23#190
  +'R'#175'Y'#181#146'v'''#22'i'#170#178#229#207#165#19#166#216#251#145'"MS'#255
  +#164#147'V'#167#245#233#233#216#151#130#145'y'#243#137#227#152'8'#142'X'#189
  +'z'#245'|!'#197'9q'#20#15'>'#171#31'A'#134#146#0#142'C'#220'}'#239#189','#28
  +#29'e'#226#128'Y'#163'/'#24#8#216#250#212'S'#172'<a'#21#211')'#196'ij'#218'{'
  +#13#132#12'U*T'#3'?[R'#11'\#'#213'Z'#211#238#196't'#178#209#203#154#178'D'
  +#247#24#191'{L'#222''''#143'C'#141'?s'#219#29'5'#192#166#219'l,'#173']'#31
  +#251'0'#2#161#27'2X'#17#176'8D'#20'u'#4#216#241'?;'#174#184'ES'#232'#'#138
  +#227#17'v'#26'S'#247'g'#207#197#197',$('#190#3#151'b'#10#253'"'#15'P'#180#166
  +#19'E$IjIG'#216'kI!'#17'B'#8')s'#245'@'#10#132#172#214#170',X'#184#168's'#223
  +#253#247's'#194#170#19#17#2#154#205#6'K'#150'.'#165#127'`'#224#204'$I'#206'}'
  +#203#181#207#190#147'pI'#0#199'!Z'#169#233#145#223#233#180#145'R'#146#166')'
  +#211#19#19#172'8i'#13#147#179'-'#192#180#212#170'U}'#170'v'#244#215#186'0q;'
  +#2#23#138'^'#145#237#179#175#161'k'#20't'#10#1'{'#140#191'@'#247#168'O'#158
  +'Ft'#247#207#13#206#209#22#204'&'''#158#7#180'R'#216#149#135#193#148#1#11'z'
  +#186#9#218#161'?'#251#227#214#26#228'w$d^'#184#147#230#159#223#222'\'#241')'
  +#180#13#19'r'#189'##'#16#153#137#132#2#164'gB'#146'|'#152'w'#196#1'i'#175'%'
  +#165'9Vf'#164#147#241'F'#146#166#222'I'#235'O'#233'<'#241#248'cz`h'#136#176
  +'R!'#234't'#168'V'#170',['#182'lm'''#234#156#136#210#221'm'#155#143#0'%'#1#28
  +'g'#152#154#158'f`'#254'|'#166#26#13#148'Rx'#158#199#204#193#9#250#194#144
  +#129#254'a'#154#179#17#158''''#169#246#7#12'UB'#194#160#144#137#236#168'g'#23
  +#216#176#150#154'9'#201#185#249#230'.u~'#160#195#25#224'F'#212#249#14']'#209
  ,#127'^'#206'['#148#225#230#198'o]'#255#220#248#29#147#213#197#177#26#179'@'
  +#135'('#134#127#172#136'h'#201#201#234#3#197#12#2#10#247#187'8a'#17'>'#216
  +#251'w'#164#253#162',Y'#154#135']'#212'T'#136#252#218#197#180''''#145'owG|;'
  +#234#231#159#200#190#239#217#243'H'#137#214#222#146#133#11'U'#26#199'Q'#167
  +#211'ahx'#30'i'#154#146#170#132#165'K'#151#141#8'85I'#146'g=?'#160'$'#128#227
  +#12'w'#223#127#31#11#230#143#209'8p'#0#208#132#131#131#236#218#185#131'e'#203
  +'W0'#155'h'#148'J'#241#165#164#26'zTB'#191'X'#182#203#10'f'#142#193'['#177#13
  +'ll^'#4#1'F'#1'3Uu*w'#181'5y'#239']'#167'pG'#228#180'P8'#217#197#150'l'#15'-'
  +#138'I6'#249#230#194#133'G['#173#192#169#228#19#238#249'A'#11#157'u'#244'q`'
  +#7#227#252#14#157#251#18#238'}'#155#253#20#154'TiR'#165#242#191'I'#154#146
  +#168#132'8M'#137#147#148'('#142#137#226#132'(N'#204#235'$'#209'q'#154#232'8I'
  +'HR'#149#31#163#148'*'#30#246'{'#205'<+!'#242#255#144'}<'#25#248#129#24#31'_'
  +#16'm'#217#178#153#165#203#151#131#134'v'#187#205#162#197#139#9#194'pM'#146
  +#196'g>'#219#181#4#142'i'#22#224#254#251#239'g'#187#24#231#225#173'e%'#224
  +#139#5'9'#185#159'K'#150#173#164#213'j"'#132'DkMcv'#134#245#171#215#176#255
  +'`'#147'DiB)'#8'|'#31'_zh'#173'I'#181#137'q'#5'd9{;P'#234'"'#141'G1'#178'f]?'
  +#1#199#229#206',7'#31#249'3K7%'#179#162'K'#212#19#249#16#236#132#16#182'h'
  +#192'!'#163'^'#228'b'#163#180#181#245#178'H'#209'i{'#230#238'#'#243'6'#31'N8'
  +#163'2/"'#213#138'4'#205#214#15#212#198#216'{'#166#248#2#16'9q'#127#241'L'#16
  +#130#211#27#209'T'#14#184#221#136#149#171#23'h'#141#144'Yv45'#197'I'#166#225
  +#168#249'PJi'#210'$'#149#203'N:)~d'#243'C'#172'?'#229'T<'#223'#'#137'c'#250
  +#251#251#153'?'#127#236#164'}'#251#246'.'#171'j'#237#3'1G'#136'cJ'#0#27'6l`'
  +#3#240#166'3'#151#30#203#203#150#200#160#181#230#159'n'#222'J'#26'E&'#205#23
  +#134't'#234#179#168'(bl'#193'b&'#247'4'#8'='#143'j'#191#207'Ph'#212#255'\'#9
  +#23#228#197';'#185#177#168#226'in'#180'9'#19'8'#6#237#188#238'2?aF'#231#174
  +#130#155#252'f-'#171'd'#198'OQ; '#156#214#224#246#222#172'+'#159#199#232#232
  +#188#248#199#205#195#139'l'#187#141#235#181#214#164#169'"V*'#27#157'St'#154
  +#146'j'#157#175#19#16#1'!'#16'i'#171'%'#184#19'~'#4#213#236#186'y'#181#129'['
  +#143'@'#177#222'@oh`'#215'J'#176'_Y'#254#25#236'5'#16#136#172#171#186#16#136
  +'D'#165'r'#241#216#130#232#174#131'?H'#180#16'~'#181'Z'#163#221'n'#225'{'#30
  +'c'#227#227#11'wn'#223#190'D'#247#171'*s'#149#0'J'#188#184#152#152#154'bhl'
  +#140#169'F'#29#180'&'#240'|'#166'f'#166#153'7o'#148'T'#250'&%'#232'I'#170#190
  +'G'#24#250'N'#252'L.|iD'#151'A'#155#183#15#29#177#193#198#252#246#231#157#171
  +'c]'#130'@^'#199#127'H'#129#142'9'#143#182#231#207#141#171#251':'#238#21#237
  +#25'l'#166#193#30' '#173#184#134#169#222'KSE'#164#21#198'%7'#174'x'#170'Un'
  +#133#214#224'-'#236#243#138'c'#188#14#211#153#216'?'#151#26'D'#183'8If'#248
  +#144'y&='#251#230#127#11#10#209#197'y'#132#204#166'2'#10#132#240#164#144#181
  +#193'A'#134#134#135#163#137#153'i'#127'ph'#136'f'#166#229',\0'#222#231#249
  +#222#234'$'#137#7'x'#22'U'#129#165#6'p'#28#225#193'G'#31'etp'#152#214#244'4h'
  +#8#6#6#216#191'w/cc'#227#204'D)Z'#129#239'I'#170#149#128#138'_'#252'P'#187'&'
  +#222#153'-'#206#143#188#232#167'['#236#236#192'V'#248#229#214#217#189'{n'#252
  +']!B'#241#223#222#26#2#215#147#232#242'&4y*OC'#182'.`'#5#180'&Nb&'#155'm'#14
  +#204'6'#152'i6'#153'i6'#153'm'#181'hE'#29#226'4!U'#138#200'1'#254'n'#152#145
  +'Xv'#25#191'5l'#145#169#247'='#163#190#147#1#16#158'Dz'#18#233#153'l'#138#148
  +#153#194'/'#157'}'#176#194#31#24#29'Q'#228#235#26#154#204#128#176'"'#161#16
  +'R'#200#145#145'y'#241#214'G'#30'fx|!'#26'M'#28#199#140#206#31#195#243#189'e'
  +'I'#154#174#127'6U'#129'%'#1#28'G'#168'OO'#131#132'v'#167#13#2'|'#223'G'#169
  +#148#145#145'y'#180#163#196#20#187'T%5O:'#171#231'h'#208#234#208#25'o'#128'5'
  +'~'#221'='#232'u'#147#133'('#178#2#135'%'#9'g_'#19''''#23#219#28#137#175#216
  +#185#144#244#156'Q'#223#22#254'XO@'#19#167')'#251'&'#247#241#200#214#29#236
  +#157'i0qp'#130#250'L'#155'F'#156#210#210#217'R'#225#218#184#245#145#195'&'
  +#197#200'/'#156#243#218#224#193'^Kf'#198'/'#177#243#249#205'['#133#225'Ji'
  +#188#14'/'#155#145'('#179'e'#6#243#5'G'#157'l'#128#176#21#139#182#14' {'#238
  +'{'#18#145#213#30#203'<'#130#209'r'#209#178#229'i'#20#199#204#31#30'F'#10'I'
  +#146#196#12#12#14#18#134#149#133'i'#154#142'*'#173#143#216#174'K'#2'8'#142
  +#144'('#211#160'C+'#133#144#146#246'l'#155#168#217'`l'#209'b'#218#13#211#10
  +','#244'|'#130#222'f'#31#174'2'#158'['#157#29#165'E'#22#134#23'#'#189#27#135
  +#219'!'#185#168#4#214']<`'#211'}Z'#20#251#235'<'#154'?'#212#193#239#173#9#144
  +#25'I'#165'J'#209#142'cf[-'#166#235'M'#234#173'6'#211#141#22'S'#245'z^!'#152
  +#210'1"^6'#226#187#163#189'5'#252'('#19#239#236#168'^'#220#245#161#233'= [S'
  +#212#26#190#204#211'zR'#22'^C'#215#223#140#24#164#204'Gv'#227#17#8#15')=,'
  +#233#136#140')<!'#241#132#241' '#164#148'B+%'#22#205#159#159#30#216#189'K'
  +#197'q'#140#31#4'('#165#9'<'#143#249#163#163#11'U'#154'.'#208'Z'#5'G'#250#155
  +'(5'#128#227#4'Zk'#162'$%MS#'#230'II'#170#218#168'T'#161#180' I'#20'BB'#24'H'
  ,'|'#223#203#163'Q'#199#140#139'A'#188#24#222'{'#174#225#210#130#213#1#28#29
  +#193#9#29#186'd'#132'.'#145#15'z'#231#13#216'x'#187#136#144#141'qj'#173#137
  +#147#132'vd'#210'n'#169'R'#5'}h'#141#206'RnV'#193#151#137'0'#11'y'#218'%1'#29
  +'1'#209#196#253#130#10#238#228#30#235'odn~'#206'\'#24#137#158#172#252'WZa'
  +#176';'#166#23#136'lQ'#4'G'#28#236#154#156'T|<'#145#233#30'^'#254'}'#137#204
  +'c('#4#3'a'#238'X'#246#15#244#163#149'J'#149#214#210#247'}'#162'(BJ'#143#193
  +#161#161#193'd'#235#214#17#165'T'#8#180'9'#2#148#4'p'#156'@)#'#217'7'#227#14
  +'Z+'#188#236#199'88<'#140#144'>'#10'M '#141#241#135'^V'#248'j'''#184#216#26
  +#251#204'B'#141'pW'#148#254#128'k'#252'dv^'#8'{'#249#136#153'W'#207'Q0'#138
  +'-!$+'#15#234#13#236'3X/]c'#234#233#163'('#162#19#199'DI'#138';3'#216#172#224
  +#163#243'p NS'#210#182'"M5'#158'tj'#16#186#180#5'A%'#187'OWL,'#140#186#219'`'
  +'M'#149#158#241#231#5#150#0'('#246#203#157'v'#243'Z'#217'md'#197'G'#133#184
  +#225#172'c`I'#192#21'<'#5#160#133#148'"'#151'S'#5'Z'#132#149'*'#3'CCI'#181#18
  +#6#149'JH'#167#221'F'#10#168#213'j'#213'4M'#231#161#169#1'G'#180#254'^I'#0
  +#199#9#234#141#6#253#253#243#232#204#206#162'5'#4'A'#192#254#253#251#25#25#25
  +'E'#225#161#149#198#239#151#244#249#30#210#19#133'6'#167#187'3'#231#186#203
  +#253'/4'#250#188'4'#184'G+'#176'EDE'#156#175#187#9'!'#247#242#187'C'#131#194
  +#205'.F'#254'(M'#232#196#9'q6'#218'+mg'#228';'#247#151#253'UJ'#19#165')Q'#146
  +#160#178#152#223't'#255'3&'#30'"'#242'Q'#191'k'#26#179'('#12#191'{'#148'.'
  +#196':['#218#155#171#251#246's'#138#194'L'#243#227#133'I['#10#236'<'#132#194
  +#189#23'='#231'vT'#15#203#4#185#167#145#135#30#26#225#251#30#149#176#146'>'
  +#181's'#7#213'Z'#31#211#211#211'('#173#24#28#26#242'}'#223'_'#144'*u"'#176
  +#183#247'7p8'#148#26#192'q'#130#189#251#246'Q'#27#233'#'#142'c4'#224#213#250
  +#152#157#153#198#247'<f'#147'$_'#240#195#183#163#191'#'#219#219#185#241#135
  +#147#1#173'bW'#196#253#206'v'#138#249#251'v'#182'^'#241#171#239#141#241#201
  +'c'#141#194#235'5'#175#163'$f'#166#217'b'#166#217#162#29'E$'#202#138#146#189
  +'2'#161'Y'#188'3'#213':'#15'u'#162#196#220#159#163'b'#228#15#235#238#231#239
  +'X'#17#174#203' m'#140'.'#240#188'"n'#207'V'#245'('#132#189'\'#192#147'E'#198
  +' {'#152'8>S'#245'e'#161'#'#8'w'#127#27'f8a'#130#213#10#236#228' )'#164#176
  +#175'k'#181#154#218#179'c'''#225#192' '#2'A'#170#20#3#253#253'x'#158'7O'#165
  +'i'#237'H3'#1#199#212#3#184#239#190#251#216'.'#198#217#242#212'snaV'#226'9bf'
  +#247'C\y'#209#233'L&'#9'h'#141#231'{'#168'4Ez'#146'N'#148#228#6#165'3'#163'U'
  +#170'p'#215#181#210#153#203#139'#'#217#147#215#234#152#151#153'f`'#139#133#28
  +#216#240#192#154'^'#206#10#185''''#144#189#161#139#216'Y'#163#137#162#132'Vl'
  +'f'#205#21'!'#136#245'<'#12'L+Rc'#228'Qf'#252'Z'#131#239'C'#154#166'f'#244
  +#199#246')0'#139'uj!'#136#186'n'#210'<'#175'89~m'#141#209#186#250'Yx '#4#197
  +#140'D{l'#158')0'#159'Af'#194#160#192#168#255'yer~N'#151#229'0'#213'~'#206'P'
  +#156#207#28#204#189#8#236#254'Bf1'#201#208#192#128#222'79E'#16'V'#140#222#161
  +'4'#213'j'#13'!E'#191'R'#170#170#180'zz'#206'vpL'#9#224#172#179#206#226','
  +#224#170#13#203#142#229'eK'#0#183'|{'#31'B'#128'JM'#235'8)='#164''''#169#132
  +'U$'#16'x'#146'0'#139#255'};/='#19#213'Tn'#232#182#167#191#129';AXh'#149#147
  +#129#176#225'@'#215'(_'#236#236#234#9#8#129#22#238#170#192#130'(Nh'#199#145
  +')'#210#209#246#189#140#152#242#185#7#185#143#145'y E@"D'#214#238#219#243'2'
  +#163'5'#163')'#18'3'#207#1#178'u'#12#237#194#161'Ee'#160#13'E'#172'bo'#197'?'
  +#215#24'3St'#164#4'+'#2#136'|'#221#1#145#147'@'#246#157'dwg'#142#145't'#177
  +#164#157#246#151#127#207'N'#4#144#221#159#253#14#236'w'#212'?oT'#201#153'Y'
  +#250#178#201'ZJk'#194'J'#5#129#168'j'#173#171#238#228#162'gB'#169#1#28''''
  +#136#227#24#129#204']c)%'#158#231'S'#173#214'P'#218'4'#164#240'$H)'#186#220
  +#127'('#196#177#2'N'#236#223#179'5'#31#159's'#14#232#174#157#183'a'#128#171#1
  +#218'_jlc'#252'$'#201'g'#28#186#18#129'['#139'`Gu'#13't'#176#205'@'#28#7'?+'
  +#182#145'Bf'#205'L'#28'#'#207#208'e'#216#217#13#201'.'#23#221'Q'#246#209#166
  +#146#15'Y'#196#250'Y'#224'o'''#7#230#130#161'('#206'o'#190'?mH"'#207#30#8#242
  +#250'^{/'#194'='#194#232#11#246#211':EH'#218'^j'#176#214#167'<)'#181#239#249
  +#153'D'#162#240'}'#31#13#129'@'#7#130#146#0'J8PJ!E'#150#13#192'L'#149#13#130
  +#128#202#224#16#141#204'8d'#22#227#226#140#140#185#223#155#11'y:'#207#230#185
  +#6'~'#168'i'#29#206#255','#244#245#226#149'I'#213'u'#226#148'8I'#242#251#235
  +':'#170#203#248'u'#150#9'PD'#20'B'#165'u:'#236'H'#25#250'>I'#146#144'$'#9#2
  +#145#175'c`'#236','#27#245']'#18'sG}7'#30#199'Z]O'#13'@f'#236'^'#151#216'W'
  +#220#179#204#9'"'#11#143#236#249#164#204'='#9#153#187#19#150'P'#204#250#1#249
  +'=Z'#175#198#134'"'#249#205'j'#17#6#190#18'Rh'#233'I'#235#4#25#242#6'_i'#29
  +'('#165#142'H'#223'+'#9#224'8'#129'R'#10'O'#171#220'X'#16#224'y>'#181'0'#164
  +#30#169'\'#216#170#4'>h'#149#25'bf`'#217#143'7'#8#188#172'v^'#231'#V'#161#20
  +#184#206'n'#230'!'#168#220'3>$;`'#206'm'#12#223'('#245#26't'#30#209'w'#141
  +#252#169'V'#248#158'G'#16#248#153'>a>G'#168#11'R'#18#153#1'k'#4'a'#224#243
  ,#227#251'7'#241'7_'#185#133#153#201#25#254'W'#223'Wx'#251#27'.'#166#18#14#16
  +#132'>'#213' '#204#230#6'P'#24#166#173#238's'#12'9w'#185#133#204'&E'#217#215
  +#153'w`'#179#21#14'Y'#228'N|'#17#7#228#159'W@'#145'A'#208'd'#158'N'#225#214
  +'{'#158'!'#159'8'#142's'#242#176#222#151#148#26#223#151'B)2B'#243'4'#184'u'#2
  +'Yh'#161#181#135#179#128#210#207'BI'#0#199#13#156#245#237#1#251#131#243'<'#31
  +#149#198#16'j'#250'|'#159'o|'#255'v'#190'}'#231#221#132#129'['#209'&QJ'#177
  +'a'#221'Z~'#254#13#23#23#163'`'#22'{'#231'CM>'#236#23'#'#171#187'6@'#190#15
  +#144'$)'#237'8&U*?W'#238#195#235#226'>'#181'6'#203#148'?'#177'm''?}'#248')'
  +#146'4'#201'Gp['#225#231'KSo'#175#181#233#0'T'#9'|>'#255#141'o'#179'{'#207#1
  +#194'0'#224#223#127't'#15#3#181#26'kNX'#193#208#142'>'#2#223'sbv'#227#246#131
  +#205#231#23#139#137'Z/'#161#183#137'G'#161#214'['#253#192'|'#4#27'jh'#17'"D'
  +#230#29#200','#208#144#217#136#31#26#199#223#247'<'#189#254#132'e:'#240'}@'
  +#227'{'#146#253#147#211#252#209#199#254#183'l'#212'['#156#176'h'#145#201#6'd'
  +#223#162#20#146'_'#242#235#213#8#0#0' '#0'IDAT'#184#234#13#241#217'kNLS'#149
  +'-(h'#191#206#220#11#145#217#183'&'#142'x'#181#160#146#0#142'#'#184's'#231'l'
  +#172#223#136#163'l'#241#12#243#163#174'7['#153'Q'#218#223#144'q?'#181#214#204
  +'6Z'#217#232'o'#172#212#157'q'#7#228#189#2'r'#235'-.'#151'Ci'#232#196#17'Q'
  +#156#20'.'#179#214#228#147'f'#181#187#127'q`'#156#166'l'#221#181#155'NlV"2'
  +#13'9'#20'J'#21#186'E'#148#164'H)'#8'='#143#217'F+o'#178')'#133#228#145#167
  +'v'#178's'#239#4#213'lEc)'#5'I'#170#241#132' Q)B'#8#210'l'#26#161#16#144#164
  +#169'i'#252#169#205#186#129#230'Z'#154#208#147#164#202#16#159'R'#217#154#130
  +'B'#211#137#19#170'YYn'#162'R3Jg'#233#195'8I'#132#148#166#171#178'Rf'#22#226
  +#240#208#0#127#245#225#15#232'j'#24#146'*'#19'b$iJ'#163#217#166'Z'#169#224'y'
  +'^'#166#197#152'/)J'#18':'#157#24')e'#166#217#200'B/'#196#16#151'r'#191#232
  +'#'#26#255'K'#2'8n '#132'$'#181#14'{f'#185'Jk'#210'('#194#147'5'#148#210#164
  +'*'#229#173#151'^'#204'/'#252#220#197#216'6'#220'6%g'#4'2'#15#149'u'#255#181
  +'=B'#15'c'#227']/'#220#168'?Q)'#237'81'#11#136#228'N'#132'u'#253#187#15'P'
  +#186'h2'#26'%1''._'#194'{'#222#249#243#180'uJ'#28#167#166#161'&Y'#236','#139
  +#248'X'#8'A'#24'z'#252#228#129#135#249#211'O'#253'=33u^s'#214#233#188#234#204
  +'S'#168'VB'#22#140#141'06o'#156#190#225'*'#158#29#186#5'TD67@Ch:q'#20'"'#158
  +#235#198#187#217#2#179#161'x_'#20#251'Z'#183#222'|'#22#149#127'`!'#205#236'('
  +#153'U'#4#214#27'M'#130' @'#8'X<>'#159#155#254#235#135'T'#182'n'#170#206#245
  +#7#147'y'#212#190#144'*'#138#146','#20#210'B'#131'PVl'#21#160#149#234')'#162
  +#250#217'('#9#224'8'#129#231'y'#164#216'%'#175#204#200#162'REgv'#6#127#254#0
  +'i'#156#165#211#180#194#147#30'Z'#137'|'#162#175#204#172#221'L'#164#193'q'
  +#245#13#220'f'#152#189#161#190#253')'#182#147'$'#19#249#156'4'#158'u'#251#237
  +#233'2'#7'B'#21#213'C'#180'Q'#249'1J''DQLs'#166'C'#167#211#200#179#21#133#177
  +#21#241#251#9'K'#151#243#182#215']'#192'O'#30'}'#130#11'7'#158#206#129#201'i'
  +'|'#223'3'#211'r='#143'('#30#202#132#193'l'#25#240#188#235#177#128#208#24#145
  +','#140#182'P'#248'!'#247#128'l'#250'Oh'#144'N'#175#177'\D$'#179'\'#173#139
  +'s'#9#145#175#141'6'#221#234#136#190#192#215#3#181#26#131#3'}'#248'v'#218#176
  +#243#189#21#238#189'M$'#154#244'f'#18'''Bk'#157'i5Y'#157#130#249#158#20't;'#3
  +#207#132#146#0#142#19#248#190'OGiS'#134#10'hm'#26'a'#180#219'-'#134#164#204
  +#230#6#20#139']'#22#182#233','#218#217'U'#4#228#140'2'#185#253#219''''#133#28
  +#166#180#166#19#199'$i'#154#27#184'='#149#182'B#'#197'v;'#242'k'#173'ic'#250
  +#239#217#139#228#139#131'd?'#252'4['#135' O'#161#229#170';4'#219#13#194#192
  +''''#12#130'ld'#180#222#143#202#250#244'5'#241#242#197'H'#237#8#30#26'=#2'#6
  +'n'#213#247'|'#25#144'<Q'#239#142#242#230'~L( '#243#179#229'D'#17#10#210'H'
  +#11#161'AV'#178'Y'#0#217#129'RH'#210'TS'#9#2#179'Na'#151#140#216#253#189'd'
  +#159#16'!'#132#246#165#212'Q'#212#150'i'#154#138'4I'#179'9'#9#144'$'#9'@'#130
  +'$'#229#208','#237'aqL'#9#224#222'{'#239'e'#155#28#231#161#178#18#240#152#163
  +#190'k??'#183#192#8'KZC'#154'U'#215#181':'#29#6#17#196#169#162#157'*'#6'R'
  +#141'''s;3>h'#177'&'#8#249'4]'#187#234#143'C'#4']'#149#190#152'8'#186#147#152
  +#186'}w'#130#159#21#247#236's{'#172#210#166#13'W'#164'M|m{'#243'Y'#163#211
  +#128#231'Kj'#131'!'#190'?'#236#156'G'#228'*'#189#29'%+'#253#21'*'#213#10#10
  +#24#30#30' V'#154'j'#24'0'#127't'#152'y#'#163'T'#251'C'#138#214#251#20'#|'
  +#166#238'w'#173'>'#148'g'#3#204#189'Z3'#149#217'{'#249#241'B'#128#214#132']$'
  +'!@km'#253#7#211#225'G`'#243#150#190#231#209'_'#173#18#132'>"'#207'6'#144#31
  +'k'#189#9#156'k'#249'R'#232#169#137'I/MSZY'#25#183#144#130#168#211'Ak'#221
  +#145#200'D'#8#217#213#1#253#233'pL'#9'`'#227#198#141'l'#4#222#178'a'#249#177
  +#188'l'#9#224#193#205'>{Zm<'#207#168#206'I'#18#227#249#30#168#148#225#138'O'
  +#28'I'#211#239#206')N!'#251#173#230'='#127#172#231'+'#180#233#210#139';'#162
  +#235'l}?'#179'%N'#141#203#15#214#253'U'#249'H'#173#236#170#188#238#241#153
  +#250''''#156'T'#165#192#184#223#150'%'#164#20#224'y'#4#190'G'#181#154#25#168
  ,#141#187'E1b'#10'!'#24#244'C'#6#251#251#144'B'#176'pl'#30'A'#224'S'#9'C'#22
  +',Z'#192#252#161#26#161'o'#12#206#186#216#194'V'#246#229#130'('#249#249#157
  +#233'~y'#7' ('#190'+'#145#143#254#238'='#21#6'\'#228']'#132#153'hU'#208'(BH|'
  +'_'#18#248'N'#11'6'#138'k'#219#138'IK'#14'Y'#4#161'g'#235'u'#233'{>q'#28#1#2
  +'Oz4'#155'MT'#154'vD'#16#198'0'#7'='#128#18'/'#30#198#199#198#216#186#233'!'
  +#252' '#0#13'Q'#189#206#232#216'8'#141#137#131'y'#245#155#249'E'#230#129'8`'
  +#13#19'r'#11'3'#27#243'F'#24#144'-'#164#233#4#255'Q'#18#19#167#137'cHE'#254
  +#193','#31#230#132#168#218#144#135'B'#163#180#162#227't'#245'v'#221#137#194
  +'Y'#23'T'#164#221'b'#171#251#138':'#253'l'#204'$'#8#141#251'/'#132'``x'#152
  +'8I'#9#195'>'#250#251'+T+'#21'|'#207#239'J'#227'u'#213#223#231#164#210#173#1
  +#8#235#12#229']'#128#138'0'#193'z)'#249'=X'#227#205#194#162#220#237#183#149
  +#134#214#203'p'#22#30'q?'#171#151#127#191#194#146#148#22'f'#177'E'#237#1#237
  +#168'#'#198#199#199#137#234#29's_'#158'G'#189'Q''I'#146'Y!DG'#231#203'''?3'
  +#202#217#128#199#9'FGFh6'#26'T'#7#7#208'@'#167#221'f'#197#202#19#152#154#156
  +'B%f'#192#136#148#19#251#219''']'#170'^'#183#219'^'#204#2'$'#183#208'N'#146
  +#144'$'#169'c'#252#228#228#160'3y'#219#133'F'#147'f'#198#223#214'F'#189#234
  +']'#189'G'#8'L'#214'!K'#185#153'N>'#133'fak'#13#164'5'#127#129#211#22#220#132
  +#13#158'oJ'#130#171#210't'#216'q'#141#223#246#224#203#141'?{'#207'N'#253#149
  +'YN'#223#198#249#182#237#151'g'#186#244#228']~<Od'#15's-O'#8'|'#233#229#251
  +'yN'#139'0s'#140#151'i/'#230#30'|a'#219#153'g'#239'g'#237#193#164#20#218#185
  +'7'#157#2#205'F'#195'['#181'j'#21#237#246'L^'#147'03='#157'&q<'#233'y^['#10
  +'Yz'#0'%'#10#152#254#127#10'?0E*q'#28#161#210#148#217#250#12'R'''#248#158#151
  +#27#188#214#153#235#157'W'#3#246#20#243#184'Z_'#166#216'km'#230#27#164'i'#230
  +'A8'#220'a'#133'4gq'#177#252#188'J'#255#255#237#157'gp]'#231'y'#231#127#239
  +'i'#183#161']'#128#0#216'{'#19'UhJ'#148'eK'#178'dK'#178'%'#171#187#200'N'#214
  +'Z'#199#201'&3'#217'|'#200'L'#242'y'#203#151#253#224#217#236'$'#153'L'#178';'
  +#155#172'c;'#142'('#217'VTM'#217#180'd'#177'Ib'#17#216'@'#130' '#9#162#131
  +#232#23#189#220'v'#206#187#31#206'y'#207'9'#23',")'#182#8#231#175#161#128'{'
  +#250#189#184#207#255#233#207#235'i~'#233#166''''#229#156#251#248#209'tO'#176
  +'-'#2'_]'#161'$@'''#3#1#150#190#171#29#180#249#162#4'_'#11#200'BY'#13#248'Z;'
  +'\'#248#19'"'#132#144'fW'#199#1#190#0#251'n'#3's'#220#131'0'#25#250#150#130
  +#240'H'#11#127#135#192#173#190#16#222'H'#164#160#1#201'/'#226#146#186#166#203
  +'\'#174#192#232#216#168#145'+'#218'n'#143#135#166#227'8'#14#211#211#211'y'
  +#205'0&'#133'&f_{'#233#165#136#0'"'#4#16'B`h'#2#195'p'#255#228'E'#219#205#163
  +#199#19'I'#191'9H'#226#182#211#26#190'/'#31#152#176#170'cO'#181#236#186#22
  +#172#240'v'#187#163#185#220#252'~'#176#31'@'#21#6#251'V'#133#7#127#177#13'O'
  +#248#29'G'#5#252#130#24#132'/bB'#9#191#155#171#143#133#223#151'/L'#194#143#25
  +#248#26'Y'#11#185#5'^u'#158'/'#156's'#5#218#187#143#210#252#190#240#19#8#187
  +'[{'#19#18't'#223''''#15'j'#1#212'>'#191#206#223'w)'#130'c'#221#253#4#239'5'
  +#244#158#149'['#225#198'N@'#10#164'['#157#232#22#6'h'#154'`6'#155#149#8'M'
  +#215#133#192#246#130#128#182'm31>>c'#24#198#164'&'#180#179#151#251#189#136#8
  +'`'#30'AH'#135#184'i'#162#235#238#138'2V,NUm'#29#189'='#157#164#151#173#197
  +#145'A'#157#127#216#180'W'#138'~'#142#3#0#158'Fwg'#13#186#253#4#225#229#187
  +#212'l?'#213#176#227#159'-'#213#224#14#135#172'r;'#160'T'#16'|'#161'Q'#254
  +#181#11#139#240#235'@'#144#129#144#224#170'a'#29#193'4'#29#239#23'4'#161#251
  +')O%'#148#174#16#186#129'>-D'#0#2#175#6'B'#136#208'u'#2#193#247#175'1'#199
  +#247'W'#212#229'z'#12#162'$'#253#25'n'#246#241#137'N]'#223#219#142#247#236
  +#254'Z'#132#2'@'#147'B'#8'i'#8#156#129#254'^'#163#186#174'N'#139'Y&'#197#162
  +'['#24#148'/'#20#200'd2'#163#134#174#143'".o'#30' D'#4'0'#175'P'#158'*#'#239
  +'HL'#211' '#151#203'265'#129'a'#26'LMN'#178#220'4'#25#203#185#169'A'#199'v'
  +#167#6#171'D'#152#20'^'#245#143'k'#237#187#240#204#235#130'7h'#20#194'&?('#31
  +#192'_57T'#234#235'.'#187'%'#201'IYB,a='#168#228'H'#138#176#198#23'^'#195#143
  +#251'\J'#155#130#18#200#210'I'#187#142'tk'#5#130#145#219'*'#170#31#212#248
  +#251'7'#10#237'WK'#130#7#245#254#190'a_b'#238#7#214#135#247't%'#238'C'#200
  +#250#240#181':'#4#21#188'!'#161''''#236'"'#4#164#226#230#4#221#207#222#251'h'
  +'%`w'#180#183#199#12#203'brr'#210#173'A'#208't&'#198'3d'#179#217'1'#203#178
  +#198't]?'#127'y'#131#139' '#10#2#206'#'#220#190'q#S#'#147'$'#146')'#132#16'L'
  +#14#15#179'b'#253#6'FGG'#16'8'#254':vn'#172'N'#197#3'$8'#162'D'#131'K'#220
  +#130#154#162#237#174#172#19' '#228#195'{'#130'&'#145#222'`'#17#252#184#128'-'
  +'%Y'#199#181#2#2'>'#9#9#127'H'#251#11#220#217#253'!Q'#162'$BO '#252#193'j'
  +#191#238'u-'#211#164'"'#17#243#175#175'Ya'#255'=8'#217#159#29#160#205#177#0
  +'|K@u'#10#18#16#12's'#231#6#168'1^'#238'q'#134'p'#3#135'nC'#144#215#147#160
  +#226#14'~'#156#192's'#11'Be'#213#130' '#224#231'm'#149#2'!5!'#164#238#241'@'
  +#255#240#144#177'j'#253#6'2'#227#227#160'i'#24#166#193#224#224#16#197'bqH7'
  ,#140'q'#129#136#8' '#194#249#168#175#171'cbb'#152'dU'#149'K'#0#19#19'T'#151
  +'W095'#133'c'#231']'#173#25#14#196'y'#230#171'CHRqu'#146#237#173#165#231'kjo'
  +#159#175#253#241'b'#136#161#234'A|'#179#127'N'#174'?8'#209#191'FIN\'#201'{HK'
  +'j'#234'L'#205'5'#179'u='#24#197#133'p'#187#13#239#217#180#158'?'#250#189#231
  +'=a'#146#132#206#242#180#171#231#143'+'#127#223#155#209''''#132#22#242#235#3
  +#173#175'i'#154#183#8'8'#193#220#127#245'<'#154#27#189'7'#8'HA'#21#232#184
  +#214#134#26#9#170'&'#1#171#243'4'#132#208#189#245#4#130'x'#131#159'B'#4#16#18
  +#13#164'&pr'#249#2#131#195#195#230#130#202'4'#211'##n'#236#198#145#12#12#14
  +#228'l'#199#238'5tc\'#8'qYE@p'#131']'#128#134#134#6#186#205':N'#180'E'#149
  +#128'7'#11'ff'#148'E'#203'W '#132' '#159#203'"'#128't'#237#2#186#187#187'I/]'
  +'E'#193#150#152#182#227#171'%'#233#149#230#10'!'#208'$~'#224#174#232'8'#168
  +'2\e'#198#139#240#141'$'#222#212'^'#207#13#240'V'#23#154'u'#164#151'\'#8#230
  +#18#248#218#223#171#153'w'#235#231#221'M'#2'W'#192's'#222'1'#22#202'(&d'#182
  +#11#28#159#20'\A'#182'%'#148#165#146'$'#18#9#6#199''''#208'4'#29#161#11#175
  +'r'#209#23'C'#151#7'd@'#6#161#160#128'z'#184#192'X'#247#139#13#132#23#24#13
  +#213#16#200'`'#8#136'2'#243#149#171'"4U'#11#128#31'HT1'#128#128#252#132#255
  +#187#226'1'#13#181'.'#160'?'#150#193#233#233#233#214#203'*'#211#134#174#9#242
  +#249','#186#166#145#207#231#25#232#239#31#183'LkX'#211#244#166#203#205#0#192
  +#13'&'#128#173'['#183#178#21#248#198#230#229'7'#242#182#17'B'#248#213#142'^'
  +#16#2#203#138'1;3'#195#236#212#20#181#245#139#25#27#30'd'#205#250#141#228'r'
  +#249#146#232#182#173#186#2'E0|C'#218#182#251#133#23'a'#191'_'#6#229#190#194
  +'%'#10'5'#212#202'Q'#234'_'#186#17#1#247#188#192'OVp}'#245#210'm'#22#225#201
  +'='#194#215#204'JN5'#207#252#246#149#191#166#249#177#1#183#138#217#161#204
  +#212#177'+'#226'^'#197#157#142'fh'#161#165#186#220#235#249'fx('#210#175#133
  +#246#3#190'V'#247#133'W'#185#5#202#18#241']'#134'R'#255'>xo'#202'U'#8#249#254
  +#202'@r'#137#208'm'#188#12#219#229'.K'#170#149'V'#236#227#205#205#241#186#133
  +#11#153#157#158#194'v'#28'b'#150'Ifd'#132#225#225#225'~'#211#180#250'u]'#187
  +#172#245#0#20'"'#23'`'#158'a'#243#29'w264HY'#170#12#128#190's=l'#216#180#137
  +#129#193#1'D'#209#237'7W'#26#221#9'U'#240')'#225'wg'#10'z'#219#188'}'#225#185
  +'@PZ'#240#227#246#235#184#218'?'#27#170#13#240#213#223'\'#211'?'#244#172#22
  +'A'#208#15#230#250#239#2#161'+?<'#28'3'#8'4'#172'!'#4#154'n'#16#183'bT'#167
  +#18'T'#167#146#152#166#229#147#132'*'#238'qc'#7#202#252'w'#133'Z'#23#193#245
  +#148#169#174#136'%'#28'P'#12#150#253#210#130#227#213'{'#17#202'U'#208#2#23'@'
  +#4#227'z'#2'W '#240'H'#252#138'b'#239#19#21#158#21#160'y'#181#153#237']]'#230
  +'m'#155'n'#167#127'x'#8#183#140#216#160#231'\'#15#133'B'#174#207'0'#141'!M'
  +#211'.;'#3#0#17#1#204';,Y'#180#136#153#201#9'R55h'#154#198#248#248#24#150'ib'
  +'&'#226#12'f'#134'0'#13#221'['#9'H'#217#157'>'#5#184'C1'#8#162#246#170#172'G'
  +#173#15#8#202#213#247#166#9'{G9^'#208'O'#165#8'K'#227#5#4#150#183#146#26'J'
  +#23#236'p'#15#209#252'/kX'#240'|a'#211#2#237#138''''#220#224#250#229#241#152
  +'E'#170',I<'#145#192'4'#141'@'#240'='#141#172'y'#18#232#167#254#212'v'#194's'
  +#251'=B'#208#220#24#128'.'#4#134#26'#'#230#159#27#206#8#224#199#19'J'#158'3'
  +#180'?'#204'v%3'#188'<'#15'B'#8#159#129#29#192#233#235#239#215#10#142'c%'#147
  +'I&3'#25't'#221#157#212#212#211#213'5'#141#164#203'4'#204'!!D'#241'J'#190#15
  +#17#1#204'3h'#154#134#1#152'V'#12#221'4'#201#231'sLON'#178'l'#229'j:Z'#206'`'
  +#25#186#31'4'#11#195#145#132'ZsCu'#2'RQB`'#230#251'%'#194#184'1'#132#156'T'
  +#173#5#193#249'"t!%'#247#234#219'n'#133#246#171#168#127#136#135'J'#132'*'#172
  +'n]'#18#209#252#242'ZE'#20#186'a`'#154'&'#166#161#251'Sz'#252#6#30#165#233'K'
  +#132'_'#5#253'B)9_'#211#135#142#15#185#8#238#185'!'#173#239'M'#0#10#172#147
  +'`'#127#216#197#1#223#13#144's6+:q<z'#181#27#14#31#178#150#175'\-fgf('#22#10
  +#232#154#206#228#212#20'==='#3#177'X'#188'G'#215#245'cW'#226#255'CD'#0#243#18
  +'wm'#218#196'tf'#130#178#242'r'#164'#'#233#238#236#224#238'-['#24#24#28#160
  +#152#207#162#27'FH@'#221#232#149#244'Sq2'#8#130'y'#187#195'}''N'#137#240';^'
  +#147'OH'#243#207#233#5#240#131'^a!'#247#182#7#191#7'^'#181'Zz;'#156#130'S'#17
  +'t'#208#2#161#19'J'#167#10#223#194#152#155#226'S>'#190#18#181#18'rPB'#237#157
  +#236'['#13#8#191#144'(h'#10#10#185' '#170'7@'#132#222#134'o'#221#4#219'J\'
  +#128#11#188'mO'#232#213#202#235#142'm'#219#242'tkkl'#235'=w'#211#219#223#135
  +#16#2#195'4'#233#236#234'bjr'#162#203#138#197'zu]'#31#255#132'?'#253'y'#136#8
  +'`'#30'b'#221#154'5'#140#140#244'QU['#135#166#235#140#142#12'St UUEkk'#11#150
  +'i'#134':'#212#130#225#155'np'#15#194#26#223'0'#12'LC'#247'K{'#221#189#210
  +#127#157#13'w'#247#5#250#148#146'-sc'#1'"0'#136'}!T'#129'?1'#247'ghQ'#14'-'
  +#180#216'&s'#10'z'#212#249#190'E'#17'N'#185#185#194#31#222#238'kz'#175'>@x$'
  +#160#135#8'H'#11'='#127'i'#250#208'E'#136#130#130#247'*'#207#223#134'(5'#183
  +#2#135#202#255#160#237#230'3g'#12'='#22'7'#133'a21<'#228'Nx'#178'mZ['#206#204
  +#128'l3'#13#179#23'q'#249#249#127#133#136#0#230'!4M#a'#24#232#134'A,'#30#167
  ,#144#207#211';'#216#207'}_'#252'"m'#173'g'#17#142#227#205#152#247#4#217'QR'
  +#236'Y'#3#128'a'#154#152#134#201#169#246'N'#154#219':]a'#146'^'#232'P*'#211
  +'?X'#176'C'#225'<a'#167#212#217#176'Ju'#170'/'#204#190'v'#13#251#211'!?'#30
  +'%'#228#222'R'#221#254#176#14#17'D'#249#253'b!O'#216#17#238#241'%'#169'9'#225
  +'F'#27#194#150#130#238#197#18#2#203'",'#248#231#19#130'O_'#193'e'#195#158#10
  +#249'B'#145']'#199#154'E_f'#140'9o?'#12'%'#252#14'`'#239';x ~'#255#253#15'0'
  +#154#25#198#182'mt'#195'`dd'#132#238#174#206#158'x<'#217'a'#24#198#161'7'#182
  +'m'#187#236#252#191#255']'#184#210#19'"|6'#240#208#253#247'3'#212's'#142#234
  +#234#133' '#4'}m'#173',\'#180#148'\'#161'Hw'#223'94]G'#243#4#217#205#10'H'
  +#164'G'#12#169'X'#140#129#241'I'#182#253#234']'#254#250#199#219'x{'#215#135
  +#254#180'`%'#252#174#233#239'}'#187'C'#254#187#250#169#150#184'A'#4'6'#193
  +#220#192'_'#160'M'#131#185#255'J+'#251#154#221#187#134#239#247#171#175#180'w'
  +#204#220'1'#222'"'#8#14#4#190'>'#161#200'>'#148'\'#219'%'#149#192'y'#15'G'
  +#238#133#8#5#249'B'#194'>'#151#224#230'l'#162'wh'#132#255#245'O?'#211#254#226
  +#127#254#157#254'o'#191';'#160#149'VS'#134#3'*'#174#240#247#15#12'h'#195'c'
  +#227#177#165#203#151#211#219#221#141#208'4t]'#231#204#153#211#246#244#212'T'
  +#139'e'#197#186#13#195#184#170#226#154#136#0#230')'#22#212#212'0;9N'#170#186
  +#28#211#180#152#158#153'fxh'#128#141'wn'#230#248#225#6'?2'#30#206#219#197'b'
  +#22'v'#177#200#219#187'?'#228#175#254#239#143'y'#247#195#253'l^'#191#142'o>'
  +#246'Ut]'#248'>'#191'D'#146'wT%`'#240#239'B~'#176#170#181#183'$'#190'v'#151
  +#254'~'#207#1#16#165#26#25'u'#158'w'#148'v'#161'}'#190#224'+"QZ:te_'#224'='
  +#190#0#212#154#127'n*Pu'#20#10#175#2'P'#248#251#132#166#250#14'J'#181#187'_'
  +#188'''.'#190':'#199#242#133#181#252#229#127#250#158'S'#153'J'#201#255#253
  +#242'+'#218'_'#254#213#255#209'?>yF'#157'}'#30#1#188#187'sgb'#221#166';'#196
  +#216#216'8'#179#179'3'#24#186';'#253#231'Tss'#198#176'b'#173#150'ev'#137#171
  +'0'#255#225'&T'#2'v'#137'Z'#142'w'#140#222#200#219'F'#184#8#166'3P'#157#201
  +'PY'#149'fx'#176#159#182#150'3l'#190#247#11'4'#30':H'#251#185#30#234#22#212
  +'S'#176#29#239#203','#216#127#244#4#175#252#250'='#206#245#13'r'#219#154#149
  +'|'#247#137'G'#217#178'i'#131';'#143#174'X'#240'#'#254'RBQ:~'#165#159#146'h'
  +#161#26#244'q'''#241':B'#248#133'0'#185#144#239#12#130#152#16'8'#222'NMh~N'
  +#204#13'E'#4#139'qh'#8#247#186#130'R'#179'BM'#225#155#163#146'U'#166'A(O'#219
  +#235#186#147#202#255'G'#160'II'#137#171#17#206'`'#8#143#148#164#170'q'#244#31
  +'9X'#9#201#191#23'\'#136#2'4M'#240#200#150#219#229'}'#27#214'8o'#236#250'P{'
  +#243#253#189#218#127#249#219#127#212#191#180'u'#179#248#254#179'O'#20#151'/'
  +#172#245'}'#255#225'LF'#235#236#233#137#255#254'c'#143's'#166#233'8B'#8'L'
  +#211#164#249'T3C'#3#3'g'#203'**'#218#12#211'l'#184#210#232#191#194'M'#169#4
  +#252#230'=+n'#228'm#\'#4#182'}''?{'#245'UV'#223'q'''#163#163#25#198#199#199
  +#152#153#156'`'#211#231#238#225'dC'#3'+'#159'~'#134'Y'#12#144#146'|'#161#192
  +'K'#191#250'-'#163#19#147#252#224#155'O'#243#240#189'[H'#198'c'#228#11#5#236
  +#162#141#134#171#174'b'#184#211'|'#133#12#204#226#176#214#247#181#175#230#10
  +#180#154#199'_'#210#227#239#17#14#18'_'#203#250#166#188#22#14#238'iA$_'#153
  +#229'*u'#167#5'5'#251#129'I'#239#5#252'B'#129'A'#149#234'S'#145'~!'#220'rd'
  +#21#201#247'#'#18#190#201'/'#2'm'#31#250#233#31's'#129#207'yn'#226'C!'#149
  +#140#243#189''''#31'u'#30#190'w'#139#252#197#142#157#226'7{>'#210#22#164'+'
  +#181'?}'#225#217'"`'#3#246#246#223#238'H'#174#191's'#179'('#228#178'LMM'#162
  +#27#6#249'|'#158#163'G'#143#142#11'M'#156#140#197'b'#237#154#208#166#175#248
  +#143#239'!j'#7#158#199#208'u'#157'%u'#181#204#206#204'PU'#149'fxh'#144#150
  +#211#205#220#243#133#251'9u'#252'(mm],['#181#156'B'#177#128#161'k'#252#217'w'
  +#158'''QQ'#206#138#250'Z'#242#249#2#217'|>'#148#254#15#198'y'#171#213#190#206
  +#147#6'Q'#186'Yx'#194'o'#225#154#217'Jc*?'#222#143#200#135'f'#242#169'H='#132
  +#167#245#4#199'*&'#8#230#1#132'Z'#127#253's'#240'I'#194#207#14'hA'#218'/'#28
  +'lT'#207#171#133#6#136'^'#236#173']H'#248'/'#1#159#22#150#214'V'#203#191'|'
  +#241'['#206#19#15'|'#222'^PU'#169#28''''#251'\_'#175#214#221#215#31#127#241
  +#137'g8u'#250'$ '#176'L'#147'S'#167#154#233#233#234'<'#147'L'#150#181#24#134
  +#249#225#235#219#182#217#23#189#203''' '#138#1#204's|'#229'K'#15#209'{'#182
  +#133'EK'#150'b'#24'&c'#163'#'#140'e2<'#246#248#19#28';'#188#31#167'Pp'#191
  +#252#192#198#181#171'XZ'#147'&'#155#205#249'k'#250'I$'#142'p'#181#127'N'#18
  +#164#253#132#187'WA'#189#20#190#131#31#136'R'#176#6#222#5#180#168#167#169#221
  +'_C'#130#172#5#130#29#8#223#156#20#158#10#24#170#250'~U'#175#175#142#243'o'
  +#225'SNP'#179#31'z'#30'5'#20#164'$'#208#231#189')'#151'4'#174'^'#248'C'#175
  +#229#166'U'#203#156#186't'#133#141#231#251#191#185#253#157#228#131#143'~ULOM'
  +'05'#146'A7t'#242#133#2#31'74L'#224#200#230'X<'#214'j'#232#218#21#231#254#195
  +#136#8'`'#158#195'0'#12#150'.\'#200#240#208'055'#11'@'#194#169#166'F'#150'-_'
  +#137#145'L'#210#212#212#232#206#11#20#130'b'#161'H'#209'q'#149#141' 0m'#221
  ,#138#21'q~'#212#223#23#203#224#165#184#136#164#184#188#160#132#221#243#253'5'
  +'5Zk'#142#246'W'#164#224#7#253'4 '#148#138#11'['#6#222'uQn'#4#202'u'#8#185#10
  +#130#160#29#151'p'#154'14'#197#23'e'#9#132#204#127#174'X'#240'/'#133'p'#240
  +#175'x'#228'x'#163#153'-'#22'c'#183#173'[G'#199#217#22#132'&'#136'Y1Z'#206
  +#156#166#179#173#237't'#178#172#172#217'4'#204'='#175'o{'#249#138'J'#127#231
  +'""'#128#8'<'#242#208'C'#244#247'tQ'#191'x1V,'#198#212#228#20#205'g'#207#242
  +#149#199#159#228#196#241#227'L'#142#143'a'#232#134'''P'#174'0'#149'T'#245#135
  +#166#7#151#168#182'p'#209#127#137'f'#15'~'#139#5#250#221#215#206#254#239'Bx'
  +#157'q2H'#223#17#238#195#15#4#29'5'#255'OmS'#199#169'Q_~}'#128#8'H'#200#175
  +#216'S'#215'S'#228#226'=o'#168#129'G'#132#4#31#25#202#26'\9.'#164#253#149#211
  +#228#0#197#217#217'Y'#249#206#142#29#169'G'#30#127#146#238#238'nfgg1'#13#147
  +#153#217#25#246#239#223'?'#130'&'#26'c'#241#248#25#195#208'?u4="'#128#8#232
  +#186#206#253'['#183#210#211#221'M'#253#242#21#8'M'#208'y'#186#153#242'T'#138
  +#187#182'n'#229#131'='#187'Pk'#210#185'_z'#233'k?'#213'9'#152'W'#219#195'R'
  +#17#22#146#16#25#196#188#141'VX'#24#9#29'('#130#224'_'#152#12#2'"'#145'!S=D'
  +#24#254'O'#205'7'#247#193#253#146#251'E'#187#234'2'#190'V'#15'b'#8#193',AB'
  +#221'}'#222'c+'#195'Dr'#129'g'#190'l\'#208#244#247'~wp'#3#127#197#159#191#254
  +'zb'#237#166#219#245#154#154'4=]'#29'h'#186#142'iZ'#28'9rX'#246'tu'#158'(K'
  +#149#159'2Mk'#247#167#213#254#16#17'@'#4#15#183'm'#216#192#228'H'#134'D2Eyy9'
  +#197'B'#158'#'#13#7#185#247#11#247'c%'#147#156'<q'#12'SwW'#211#209#189#229
  +#197'|'#248#131'='#5'H1'#215#253#7'J'#181'sx'#174#191':'#212#23'f%'#192#161
  +#168'}8'#18#31#212#234#135#238'!Bm'#189#234#28'U'#177#167#133#131'}aR'#241
  +#230#251#11#129#30'^!H='#203'\'#159'_'#6#191'_C'#205'?7'#231'_l<y'#210#28#26
  +#27'M<'#240#165#135'9u'#230#12#142'c'#19#179'L'#6#135#135'8'#176'o_'#183#21
  +#139#31#139#197'bM'#134#174'_'#147#169':'#17#1'D'#0#220'/'#253'sO<AK'#227'1V'
  +#172'Z'#139'iY'#140'f'#134#232#232#234#228#209#175'?Ecc#}'#131#3#238'Xq_'#144
  +#2'm'#168#198'{'#129#18#232#208#197'U'#10'='#180')'#230#189#14'"'#255#1'T'
  +#212'?'#252'l~'#137'n'#137#182#15#2'x'#190'?'#238#187#0#238#11'5'#136'+|'#158
  +#230'G'#252#3'R'#18's'#238#229'{'#22#161#7#187'Z'#159'_^,'#15'X*'#252#133#177
  +#137#9'^}'#235#205#212#19#207'<'#207#200#240'0S'#153#12#134'n"'#132#198#158
  +#221#187#178#227'ccG'#202#202#202#155'L'#211#218#251'i"'#255'aD'#4#16#193'G:'
  +#157'f'#209#130#26#6#7#7#168'_'#190#2#132#160#181#233#4#216'6'#143'<'#245#12
  +#7'?'#216'C'#177#144#247'W'#183'q'#131#1#129#228'K'#199#13#243#135#133'?'#168
  +#234#11#138'p,'#188'Sq'#127'Q+'#250#248#129':_ C'#193#190#144#208'{'#167'{'
  +#234']i~e'#198'k'#129#150#215'B'#194#29'2'#253'}'#173'~'#129#160#159#31'`'
  +#188#144#5's'#237'>j%'#244#190#230#151#210#177'_'#250#197#207'S'#15#127#237#9
  +#189','#153#162#179#237','#186#174#17#175'('#231#248#137'F'#26#143#28'iJ'#149
  +#151#187#218#223#208#175':'#239'?'#23'7'#180#14#224#224#193#131't'#233'u'#28
  +'o'#31#185#145#183#141'p'#5#144#178#154#153#246'}'#188#240#244'cL'#165#211
  +#140'eF8'#210'p'#144#135#31'y'#140#222#206'N>'#216#187#135#207#223#255'%'#247
  +#155#235#4#13'?'#224'u'#10#218#174#144'I'#188#192#160'&pp5'#141#226#138#156
  +#239#187'{3'#254'<'#191'^'#9#188'D'#248's'#255'T'#147#188#230#175'R,'#144#238
  +'j'#25'>I'#4'&'#135'j['#246#202'y='#151'DI'#188'?'#134'LJ'#159'p'#188'7'#237
  +#253#238#205'A'#12'U'#248'I'#181#214#9#23#239#218#185#232'g'#201#249#164'!'
  +#221'*'#195#176#233'o'#3#197'W^{='#169#197#147#214#157#155'n'#231'h'#227'1l'
  +#199'!Q^'#206'p_'#31#239#253#246#183#231#12#211'<'#156'L&'#27'M'#211'<x'#181
  +'U'#127#23#194'5$'#181#243'`'#2'I'#160#2'X'#0','#146'Rn'#191#142#247#139'p'
  +#141#144#25#25#225#213#237#219#217#178'u+'#167'O'#158'$;;C'#253#162'%l'#249
  +#252'}'#188#187#253'm'#18'V'#140';6oq'#199#130'K'#7#199'v'#203'~'#243#2'wi0'
  +#137#27#149#247#175'(K4l'#204'W'#193'^d^E'#234#17'h'#186'7'#154#11#25#140#225
  +#18#154#215#141#167#242#252#238'6'#191#129'G'#16#172#209#167'2'#0'j'#196'whF'
  +#128'J'#233#233#224#165#255'\'#129#215#188#215#254#10#193#132#220#9'>'#189
  +#144'8'#142#227#132#133'^'#8'a'#19#8#127'a'#215#129#253#214#161'#GS'#223#253
  +#222#247'9'#219#222#198#196'`?'#134'a'#162#197#227#188#252'/?'#153'i:v'#236
  +#183'U55'#239#166'Re'#219#222'z'#229#149'k:Q7r'#1'"'#156#135#234't'#154'{n'
  +#191#157#150#150#179#172#219'p'#27#134'a1'#216#223'KK'#235'Y'#158'z'#238#155
  +#140'MM'#210#218'r'#26#221'pGv"'#130#138'>5'#17#183#180' @'#4#18'5'#7'%9'#249
  +#144#249#31#238#220#11#26'uB'#177#1'?'#216#231#5#252'B~|x'#152'g8. '#194#215
  +#241#30'Ry2'#132#246#139#144#212'_c'#179'_'#2#142'g1'#217'@'#225'Ds'#179#177
  +#255#192#193#228#247#190#255#3#134#6#7#152#24#28'D'#215#13#18'U'#149#236#249
  +#221#187#197#19'G'#143#30'.'#175#172'<'#146#136''''#182#27'W1'#240#227#147#16
  +#17'@'#132#243' '#132#224#158'-[ ;K&3'#193#226'U'#171#17'B'#208'v'#242#4']'
  +#157#237'|'#237#169'gh'#239'h'#167#171#253#172';eWh'#196'BK`iz`6'#7#213'{'
  +#174#144'Z%'#247'q'#133#191'`'#23#221'c'#180'@'#242'D '#221#161#24#0#190#185
  ,#31#200#173#10#16#170#168'}`'#218#187#134'B'#16#31#16'^P'#208'/!V'#254#127'h'
  +#178'O'#201#231'p'#145#207#199'q'#164#187#14#226#229'CzCU'#194'f'#127#161#181
  +#189']'#251#229'[o'#149'='#255#237#239#138#204#200#8#231#186':'#208't'#141'T'
  +':M'#211#145'#'#236#252#221#239'Z'#226#201#212#199#137'D'#242#176'i'#154#231
  +#174#165#233#175#16#17'@'#132#11'B'#8#193#11#207'?OO'#219')b'#137'8u'#11#23
  +#129#132#19#199#142'01:'#202'cO?'#203#201#147'Mtuv'#248#19#132#132'p'#173#128
  +#152#138#180#139#192#15#14'kZ'#21'h'#139#153'&GO'#183#242#195#127#222'Fk'#247
  +'0'#150'a '#230#4#17#129#243'"'#255#202#18#240#219#127'C'#255#243#239#21'D'#8
  +'J'#131#135'~'#252'AY'#22#165'Q'#255'p'#144#241'b'#4#240#206#222#6#254#252
  +#135#127#207#240#248#228#229'~'#156#225#160#159#13#20':'#186#186#180#159#252
  +#252#149#242'g'#191#245#130#208'4'#141#206#214#22#4#144'J'#167'9'#215#217#193
  +#235#255#246'j'#183'c'#219#251'**'#202#15#199'b'#177#247'_'#223#182#237'S'
  +#231#252'/'#132#136#0'"\'#20#150'e'#241#31#190#253'-'#154#14#30'`'#209#146'e'
  +#212#212#214'b'#23'm'#26#143#28#194')'#20'y'#252#217#231'in:Ag{;'#166#225#166
  +#171#132#231#2'X^'#193#140'?'#229'Z'#168'i?'#158#198#214'u'#178#133#2#239#238
  +#251#152#201#201'Y'#146#21'q'#239#174#158#200'*'#141'=7'#229'(T'#206'@z'#166
  +#189#230'O'#244#13#204#248#185'+'#251#132#174#165#186#3')'#181#16#230#22#248
  +'\'#202#244#143#151'''hjm'#227#23';v^'#214#231'(]'#0#216'R'#202'bk{'#187#254
  +#163#151#254#181#252#153'o|['#171#170#172#162#173#163#13')%'#137#170'*'#166
  +'FG'#248#249'+'#219#134#199'GG?'#170#172'J7'#152#150#245#171'7^~y'#230'r'#255
  +'fW'#138#136#0'"\'#18'eee<'#251#245#175#179#239#131'=,_'#181#134#202't'#154
  +'B>'#199#177'C'#7#17#142#228#201'o|'#139#214#179'ghk9'#141'e'#154'n'#138'P'
  +#15'Y'#3#2'bB'#248#197#174'Js'#199'L'#131'='#13#199'h'#235#234#229#241#7'?'
  +#207#170#250#5#216#142#27#27#11#155#242#162'D'#23#11#21#208'/I'#249#5#225'D'
  +#165#225'K'#221#3#207#1')'#153#215#23'X'#9#226#138#132#31#224'+'#155'7'#241
  +#224#150';'#217#241#193'~'#218#206#245#127#226'g'#24#22#254#166'S'#167#244
  +#159#253#242#151'e'#207#189#240'{ZMu'#13#173#237#173'8'#185','#137#138'*'#138
  +'E'#155'W^'#222'6y'#174#179'k_euuC<'#22'{'#195'4'#204'k'#238#247#135#17#17'@'
  +#132'KB'#8#193#210#197#139'y'#244#129#7#216#191'g7'#171#215#172#163#178#170
  +#154'|.'#203#145#134#3#20#243'9'#158'{'#225#187#12#14#13#210#220#212#136#174
  +'i'#232'Bw'#203#134'C'#193#183#152'W|#q'#27#144'zG''x'#127#255'aV/_'#200'C'
  +#247'n'#198'v'#138#190#166#150'2'#24#219#225#11'|'#240'D('#173#174'^'#135#133
  +#186#228'8?P'#168#142#151#4'D'#17#10#12#206#185#199''''#17#128#174'k'#188#248
  +#244#215'p'#28#248#231#215#127#141#227'\'#218'5'#151'R'#218#142#227#216#187
  +'>'#248#192#220#254#222'{'#169#223#255#254#15'DUE'#5#173#29#173#216'Y'#155'D'
  +'e%'#14#146'W'#254#229#167'3'#167#142#31#223'W'#153#174'>'#144'L$_3-k'#224'z'
  +#248#253'aD'#4#16#225#19'!'#132'`'#227#250#245#220#190'n-'#251'?'#252#128#213
  +#235#214#147#174'Y@!'#159#231'h'#195'A2C'#131'|'#227';'#223'%'#155#157#165
  +#225#192'>'#192#193#208#12'4Mw'#207''''#8#188#169#197'5w~x'#144#177#137#9#190
  +'z'#255#23#168'J%q$l'#196#157#226#0#0#15#159'IDAT'#193#192'NMC'#18'T'#248'y'
  +#15'Q'#18#169#247'6'#134#178#3#129#127#175#4'Z'#247#198'v'#169#135#8#199#12
  +#130#26#193#0'^'#246#242#178#176'q'#213'2'#158'x'#232'>>nlbo'#211#169'K'#30
  +#235'8'#142#253#202#235#175'['#199#154#155#19#127#248#199#127'"4'#4'm'#157
  +#237'8'#142'C'#178'2'#133#148#130'_'#252#236#167#179'G'#27'>'#222'W'#145'N'
  +#127#148'L%'#247#153#150#217#249#218'K/]'#241#144#207'+ED'#0#17'.'#11#154#166
  +#241#208#131#15'r'#219#154#213'|'#180'g7'#171#214#174#167#174#190#158'b'#177
  +#200#241'#'#135'9y'#250'4_}'#242#25'*'#210#213#236#255'`'#15#19'S'#19'X'#134
  +#137#174#233'n'#254#221#251#207'2'#13#154#219#186#217'{'#232#24'w'#223#182
  +#158'{'#239#216'@'#174#224#198#183#220'%'#8#130'9'#255#193'8'#175'Pv'#128#144
  +#176'k!'#159'>'#172#193#189#252'~'#161'P'#4'G'#186#147'~'#252#179'C'#25#6#255
  +#248#171#251'L'#190#253#213'/S'#147#174#228#229#215#223#161'P'#188'pe'#238
  +#232#248'8'#255#244#211#159#196#166#10#5#235';/~'#159#193#161#12#237#221#157
  +'HGRUV'#142#237'8'#188#244#227#31#205'4'#236#223#255'QyU'#250#163'd2'#245#145
  +'eZ{^'#127#233#218#148#250'~'#18'nh%'#224#129#3#7#232#210#235'hl'#203#220#200
  +#219'F'#184#134#144'2'#193#248#184#206#224#155'o'#243#252#211'Oa'#152'&'#253
  +'}'#189#180'5'#157'`zd'#132#135#30#254'2'#189#231'zx'#255#221#29#172'\'#189
  +#158#21'k'#214'!'#165#227#150#9'j'#18'[J'#28#233#176'n'#197'r'#30'{'#224#1
  +#132#16#238'2'#227#194#173#238#147#154#170#196#11'E'#244#253#146':WR%'#30'Y'
  +#200'p'#181#157#240#11#2#5#130#162'm'#243#195#255#247#18#235'W,'#225#15#159
  +#251':'#182'c'#251'k'#27'H'#247#141#16#190't'#184'%/'#252#250'R'#168#173#172
  +#224'{'#223'x'#138'}'#13#199'('#218'6j'#170#145#187'&'#2'4'#157':'#197'['#219
  +#223#230#161#175'=n'#220'u'#251#29't'#182#183#147#153#24'G'#8'AuE'#5#153#137
  +'I~'#246#163#127#156'lnl'#252#168'"'#157#222#159'J'#166'>'#180',k'#215#245
  +#138#248'_'#8'W'#201'}'#151#133#168#18#240'3'#10#199'q8t'#244#8#187#247#237
  ,'g'#235#151#30'F:6'#221'-g'#200#231'sTTV'#177#249#158#207'#4'#193#222#157#239
  +'a'#23#29#238#222#186#149'X<'#129'c'#219'8'#142#131#174#235#20'm'#137'i'#26
  +#238#154#3#158#208#250#221'y'#254'H'#239'`'#177'N'#225#21#23#8'!'#209'5'#29
  +#188'y'#128#170'zO'#13#15#209#132#192#208'u'#178#133'<'#127#254'?'#254#134'U'
  +'K'#22#243#223#255#236#7#174#214#151#129#175#175#205#169#252#131#171#23#6'9'
  +''''#136#152#205'f'#249#197#155'o0'#152#201#240#248'3'#207#145#174'J'#211#214
  +#217'Ivv'#6']'#215#169'.'#175#160#189#189#157#159#254#228'GC='#29#29#7'*'#211
  +#213#251#147#201#228'~'#211'4w'#191#241#242#167'o'#241#189#18'D.@'#132'+'#134
  +#166'il'#221'r7'#255#241#133#23'8'#188'w73'#19#179'l'#190#231'^***'#153#156
  +#24'g'#255#7#187#25#29#25#230#241#167#158'e'#249#186'u|'#184'{''mgN'#163#9#13
  +#203'r'#199#127#154#134#134't'#164#239#183#235#254'z'#221'A+p'#144#239#15'/'
  +#198#225'JZ'#176'%H7'#6#197'C'#238'>'#195'0'#220#238'E'#15#194'_'#250'+4'#232
  +'C'#237#251#20#159'GX'#248#143#30'o'#228#175#255#225#239#137#151'U'#240#189
  +#31#252'1'#201'x'#130#214#142'v'#10#185','#177'X'#140#218#234#26#14#29'>'#196
  +'?'#252#221#223't'#247'tv'#188'_US'#179';'#149'J'#189#18#139#197'v'#221'h'
  +#225#135'h(h'#132#171#132#16#130#186#218'Z'#254#232#197#23'y'#249#151#191'dd'
  +'d'#128#251#190'p?'#157#221#157#244#180#157#229#196#209'#'#244#245#156#227's'
  +'woe'#213#138#149'|'#184'g7'#189'{v'#178#241#174#207#177#168#174#14#199#145
  +'8'#142#29'T'#246'y'#154#222#149#230#185#193#190' g'#239#199#3#180#192'E'#8
  +'b'#5#161'H'#129#8#10#11#221'J?'#220'& E4!'#27#255'Z'#152#193'='#189#231#216
  +#190'c'#7#211#185#28'O'#127#251';,^'#188#132#129#254'~'#166#167'&'#136'i'#130
  +#138#202'J'#144#240#230'k'#175#218#239#188#253#214'Y'#219#182#247#215','#168
  +';'#16#143#199#223'0Mk'#224#181#151#254#245#186#7#252'.'#132#136#0'"\5'#132
  +#16'TVT'#240#135'/'#190#200#155#219#183#243#155'_'#189#201#227#207'<'#199#146
  +'EK9q'#236#16#195#131#3#236#221#245';'#150#175#223#192#215#159'|'#138#190#190
  +'^>'#218#187#151#246'D'#156#219#239#188#139#234#234#26'l'#199'A:'#142''''#224
  +#174#160#186#166#186#219#16'$'#244#160'x('#200#252#205#237#29#152#243'Z'#4
  +#179#3#144#161'b"'#169#172#7#135#240' R'#239#150#238#165#175#240'3'#24#204#12
  +#179#227#189#223#209#209#211#195#131#143'<'#202#230';'#238'`j6K_o'#31#197'b'
  +#1#211#140#145'J'#165#232#238#239'g'#219'O~4{h'#255#190#19#137'TYCU:} '#158
  +'H'#188'e'#26#198#216'k/'#253#235'uM'#245']'#10'Q'#12' '#194'5A'#161'Xd'#239
  +#135#31'r'#168#177#145#173#15#127#133'Mk'#215'r'#178#229#12']gNS,'#20'('#175
  +#168'`'#253#166';'#168#174#169#225#228#153#211#156'9v'#148#242#242'r6m'#186
  +#131#5#181#181#0'H'#219#241#214#246#240#132'ZS'#150#129#138#9#4#175#133#16
  +#193#204#127#188#213'{5'#215#180'7u'#157'\'#190#192'_'#252#240'oY'#190'x'#17
  +#255#237'O'#255' T'#237#231'V'#17#170#159#138'L.'#212#186'{)'#244#247#247#243
  +#222#158'='#180'wu'#178#233#206#187'x'#240#193#135#208#12#139#137#201#9'r'
  +#185#28#142'm'#19#139#197#208'5'#141#247#223#127#143'W^'#250#217#240'P_'#223
  +#241'dy'#249#145#152#21';859'#249#155'C'#31'}t]'#139'|.'#7#145#5#16#225#154
  +#192'4'#12#190#252#165'/q'#215#29'w'#240#218'[or'#186#241'(O<'#249#12'+'#151
  +'.'#229#248#209#163'd'#134#7'9'#218'p'#128#202't5k'#215'od'#195#183'^'#160
  +#165#173#141#134#134#131#196'L'#147'U'#27'6'#178'r'#241'RbV'#204#29'9'#174'z'
  +#244'UE`P'#16#16#212#4#132#234#0#130#3'$BH$'#14#217'B'#1#199'k'#218'q'#227#13
  +#248#193'@'#132#202'5'#248'W'#253'D'#216#182#205#169#150#22#246#29'<'#200#192
  +'H'#134#141#155'n'#231'O'#158'|'#138'dY'#138#201#153','#249#153#25#164#148
  +#196#227#9'b1'#139#238#174'N^'#253#249#203#188#251#235#237']'#192'I+'#30'?:6'
  +#156'ys'#176#183#183'e$'#147#185'n'#229#189'W'#130#200#2#136'pM!'#165'$'#151
  +#207#179'k'#207'n'#142'57'#179#241#246';'#185#239#139#247#147#25#30#226'T'
  +#211#9'&&'#198#209'5'#157#138't'#154#213'k'#215#147#174'N3'#212'?'#192#225
  +#195#13'd'#167#167#169#171#171'c'#237#186'u'#212#214#212'bZ'#22#142#227#248
  +#203#142#187#194#238#14#252#212']'#159#1']'#185#7#154#240#3#129#134#166'aK'
  +#201'/w'#236'b'#217#210'E<v'#207#157#216#142'Z'#241''''#156'L'#20#254#143'K'
  +#9'B'#127#127'?'#135#142#30#165#249'l'#11#194'4'#185#251#139#247#179'y'#195
  +'F'#202'b'#22#249#162'M'#206#182#201#22#221#133'Q'#226#150#197#248#228#4#219
  +#223'z'#147#3'{wS[]'#205'{'#239#239#220#142#148#199#250#187#186'v'#140#141
  +#141'u'#216#182'='#14#204#0#133#235#249#183#184#28'D'#4#16#225#186#192#182'm'
  +'2##l'#223#241#27#6'3'#163#220#247#232#163'lX'#189#134#193#254'>'#206#158'9'
  +#197#212#196'$'#8'H'#149'U'#176'|'#229'Jjj'#235#208#145'455'#209#217#209#142
  +'t'#28#234'k'#235'X'#185'j'#21#181#11#22#144'L'#149#161'i'#26#142#227'x#'#201
  +#189't'#158'7'#253#167#196'5'#16#18'!4b'#166#9#184#139#148'jBz'#21#137#194
  +#147#251#160#214'`.r'#185#28#189'}}'#28'on'#166#189#179#131'l'#209'f'#233#138
  +#21#220#247#249'/'#176#184#174#22#203#203':HG'#146'sl'#28#4#186#161'3'#157
  +#203#243#254#251#239#243#219'_o'#135'|'#158#141#155'6'#177'~'#237'Z'#254#232
  +#15'~'#240'_'#167'&'''#27's'#185'\70'#12'L'#16#17'@'#132#207':'#164#148#20#10
  ,#5#26'O'#156'`'#223#193#131#228#28#135#7#191#242#8#203#150#173' 34HGk'#11#227
  +#227#227'8'#142#141'e'#197'H'#215'/d'#201#162'E'#148#149#149'3'#155#205#210
  +'z'#230#12#3#3'}L'#140#141#145#174#170'$]U'#205#210'eK'#169#169'^@*'#153#194
  +#138'[X'#166#137#144'n'#29#129#171#204#29'?'#224#231'f'#2#188#133'?.'#242#140
  +#197'b'#145#153'l'#150#254#190'>Z;:'#232#31#26'd`p'#144'dy'#5#245#11#23'q'
  +#199']w'#177#184#190#158'J'#203'D'#2#250#5#174'1S,'#178#251#131#15#216#254
  +#206';L'#140#140#176'v'#205#26#214#173']'#203#134'u'#235#216#180'q#'#201'd'
  +#242#207#164#148#157'@'#31#243#153#0#246#237#219#183#189#195#172#167#177'%'
  +#170#4#156'W'#144#18#187'8'#195'xo+'#211'C'#157',]P'#193#151#191#250#21'6'
  +#174'YGvv'#150#206#158'.F'#250'z'#201#231#243#8'M`Yq'#170'jk'#169'_'#176#128
  +'dY'#5'H'#201#248#248#24'mm'#173'd'#179'YF'#134#6'AJRe'#229#196#19#9#18#177
  +'8eeiRUe'#148'['#22#177'X'#12'C'#215#252#244#159'#%'#197'\'#142#217'\'#150
  +#177#209'I'#166#166'F'#153#201#231#152#158#158'flt'#20'GJ'#210#181#181#196
  +#227'q'#214'o'#216'H]}=e'#169'rt'#211'@'#22#139'$uAB?_'#244#199'gf'#216#185
  +#247#3#222#254#205'o'#232#236#234'%'#153#174''''#189'p'#25'e'#233':'#202'j'
  +#151#161#155'e'#220#181'~'#1#191#191'u'#245#127#6#186#152#239#4#16'Y'#0#243
  +#27#142#227'03;'#203#129#131#7'9'#209#220#204#216#244'4'#171#215'o`'#203'=[I'
  +'&'#146#140#141'd'#232';'#215#195#228#196#4'E'#187#8'HL'#195'"'#22#143'Q^'
  +#179#128'ty'#5#229#229#229#228#139#5'lGbh'#130#206#222'^'#134'{'#251'('#218
  +#197'`m'#0#130#168#190#219#168#231#14'.'#149#142't+'#17'M'#147#218#154'E'#172
  +'Z'#181#132#162#132#152'e'#145'J%)'#22'm'#138#133#2#142#227#214#11#24#166#137
  +'e'#153'$-'#147'J'#211#240#173#136#179#221#221#188#183's'''#31#127'|'#16'''_'
  +'`'#213#202#21#172'Y'#179#134#165'+V'#178#229#182#219'H'#165'R'#232'!'#194#16
  +'BD'#4'@D'#0#17'<8'#142#195'l6'#203#137#166'&N'#156'<IWO'#15'e'#233'j6l'#186
  +#157#181#235#214'c'#234':'#147#147#19#12#143#142'052B'#161#144's'#163#249#2
  +'t'#221#192'0ML'#195#196'*K'#17'K$H'#154#22#166'ia'#24#6#154#161'ch'#154'?'
  +#240'S'#193#246#150'/'#179'm'#27#219'v'#5#189'P(0[,'#224'xS'#130#19#166#129
  +'iZX'#177#24#241'x'#130'D2IYY'#18#11#24#205'd'#248#184#161#129'}'#7#246#211
  +#219#211'CUy'#25'+V'#172'`'#197#242#21#172'X'#190#156#219'6l '#153'H'#148#8
  +#190'BD'#0#17#1'D'#184#0#28#199'!'#159#207's'#182#189#157#179'g'#207#210#218
  +#209#206#232#216#24#229#233'j'#150#175'Z'#205#186'u'#27'H'#166#146'H'#219'fv'
  +'f'#154#209#169')r'#227#227#228#11#5#28#233#22#16#129#215#227#23#154#26#28'^'
  +'eH'#21#1#9#181#212#151':'#206#178#16'BC'#215#221#217#5#134'iR'#153'LQV^'#142
  +'aY'#216#182#195#200#208' ''N'#28#231#212#201'&'#250'{'#207#17'3'#12#22'-\'
  +#196#138#229#203'YX_'#207#210'%KX'#187'z5'#177'X'#204#171'A'#184'0"'#2#136#8
  +' '#194'% ='#205'<'#155#205'r'#166#165#133#142#206'N'#186'zz'#24#204#12#163
  +#155'&U'#233'j'#22'-Y'#202#162#149'+I'''#203'0'#12#3#137#196#177'm'#242#249
  +#28'3'#249'<'#197'B'#1#219#182'qr'#14#200#188#251#205#182'bA'#134'@'#211'1t'
  +#29#205'0I'#153'&V'#204'B7L'#215'5'#144#14#185'\'#129#161#209#17'z:'#218#233
  +#233#238'd'#168#175#159#217#233')R'#201'$'#245'u'#245',Y'#188#152#186#218'Z'
  +#22'-\'#200#154#213#171'I'#165'R'#24#186#238#247'&\'#10#17#1'D'#4#16#225'2!'
  +#165#164'X,'#146#205#229'h'#239#232#224'\o/'#3#131#131#12#14#13'16>'#206'l.K'
  +#170#188#130'D*EYY9'#181'uuT'#215'/$'#153'JQ'#22#139#161#155'&1]'#243'g'#0'H'
  +#160#224'H'#242#158#127'?'#153#205'252'#204'p&'#195#208'@?'#147#227#19#140
  +#143#143'259'#129#174#233'$'#19'qj'#170#170#169'YPC'#237#130#5'TU'#165#169'['
  +#176#128#149'+V'#144'J&1'#12#227#178#132'>'#140#136#0'"'#2#136'p'#21#144#210
  +#13#218#229#11#5#178#217','#221'==dFF'#24#25#29'ebb'#156#201#201')&'#167#167
  +#152#205'f'#201#231#243#20'm'#155#162#231#227';'#142#237#207#11#144#222#180
  +'!wB'#144#134#169#27#232#186'N2'#17'#'#149','#163#188#162#156#242#178'r'#202
  +#203#203')/+#]U'#197#242'e'#203'H$'#18#238#196'c'#175'C'#241'jq+'#19'@T'#10
  +#28#225#150#133#16#2']'#215'I'#232':'#137'x'#156#170#202'J'#223']('#20#10#228
  +#11#5#6#6#7#201#229'r'#228'r9'#166#11#5#236'l'#150'b'#177#232'V'#16':A'#131
  +#157'K'#0':'#186#174'c$'#18#164'L'#19#211#178#136#199'b,'#172#175#199'2M'#191
  +'}8<r'#252#179#142#136#0'"'#252#187#129#223#233#167'i'#152#166'I'#18'|R'#0'<'
  +#127'>'#244'{'#248'\'#130'y'#1#225#185#2#243'E'#208'/'#134#136#0'"'#252#187
  +'G$'#204'W'#143#27'J'#0'{'#246#236#161'7'#185#152'#Q%`'#132'y'#130'-'#235'jn'
  +#246'#\'#18'Q'#16'0B'#132#235#140'[9'#8#24#205#4#140#16'a'#30'#"'#128#8#17
  +#230'1"'#2#136#16'a'#30'#"'#128#8#17#230'1"'#2#136#16'a'#30'#"'#128#8#17#230
  +'1"'#2#136#16'a'#30'#"'#128#8#17#230'1nh%'#224#238#221#187'9'#151'\'#202#209
  +#150#225#27'y'#219#8#17'n'#26'>'#183'n'#193#205'~'#132'K"'#170#4#140#16#225
  +':#'#170#4#140#16'!'#194'-'#137#136#0'"D'#152#199#136#8' B'#132'y'#140#136#0
  +'"D'#152#199#136#8' B'#132'y'#140#136#0'"D'#152#199#136#8' B'#132'y'#140#136
  +#0'"D'#152#199#184#161#149#128#187'v'#237#226'\r)G'#206#246#222#200#219'F'
  +#136'p'#211#176'e'#237#226#155#253#8#151'DT'#9#24'!'#194'uFT'#9#24'!B'#132'['
  ,#18#17#1'D'#136'0'#143#17#17'@'#132#8#243#24#17#1'D'#136'0'#143#17#17'@'#132
  +#8#243#24#17#1'D'#136'0'#143#17#17'@'#132#8#243#24#17#1'D'#136'0'#143'qC+'#1
  +'w'#238#220'Io'#217#18#14#159#233#187#145#183#141#16#225#166#225#238#245#139
  +'n'#246'#\'#18'Q%`'#132#8#215#25'Q%`'#132#8#17'nID'#4#16'!'#194'<FD'#0#17'"'
  +#204'cD'#4#16'!'#194'<FD'#0#17'"'#204'cD'#4#16'!'#194'<'#198#245'$'#0'9'#231
  +#159's'#29#239#21'!'#194#173#140'"'#238#247#127#174'L'#220't\o'#11'@'#189#209
  +'"'#183'@'#206'3B'#132#155#132'<'#238#247#191#200'-$'#252'pc'#8#192#198'}'
  +#227#185#235'|'#175#8#17'nUdq'#191#255'E\y'#184'e'#8#224'z'#150#2'+'#179#191
  +#136#203#128'Y!'#196'S@'#26#168#4'R@'#28#208#185#190#21#137#17'"'#220'H('#165
  +#151#5#166#129'q`'#202'{'#157#167#212#29#184#233#184'Q'#4#144#195#253'0'#198
  +#188#237#5#220#15#197#186#206#207#16'!'#194#205#128#175#244#128'I\'#18#152'&'
  +#176#2#230#21#1#20'p?'#8#229'n'#228'q?'#148#24'n'#191'@'#148#137#136#240'Y'
  +#131#250#222#231#8','#1'e'#5#20#152''''#4#0#165'.'#128'z'#157'#'#208#252#6
  +#145#249#31#225#179#7#21#248'V'#223'}E'#4'a'#23#224#150#192#245#22'>'#205#251
  +#167#227#10#187'I '#248#202#247#143#8' '#194'g'#13'*'#210#175#2#224'*'#11#166
  +#130#128#14#183#8#9'\o'#11' '#156#255'W'#31#136'"'#5'AD'#0#17'>'#155#152'['
  +#255'2'#247#223'-a'#254#3#252#127#197'"'#246#180#3#31#140#20#0#0#0#0'IEND'
  +#174'B`'#130'('#0#0#0'0'#0#0#0'`'#0#0#0#1#0' '#0#0#0#0#0#128'%'#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1#0#0#0#15#0#0#0#31#0#0
  +#0''''#0#0#0''''#0#0#0''''#0#0#0''''#0#0#0''''#0#0#0''''#0#0#0''''#0#0#0''''
  +#0#0#0''''#0#0#0''''#0#0#0''''#0#0#0''''#0#0#0''''#0#0#0''''#0#0#0''''#0#0#0
  +''''#0#0#0''''#0#0#0''''#0#0#0''''#0#0#0''''#0#0#0''''#0#0#0''''#0#0#0''''#0
  +#0#0''''#0#0#0''''#0#0#0''''#0#0#0''''#0#0#0''''#0#0#0''''#0#0#0''''#0#0#0
  +''''#0#0#0'!'#0#0#0#17#0#0#0#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#6#0#0#0';'#0#0#0'f'#0#0#0'v'
  +#0#0#0'v'#0#0#0'v'#0#0#0'v'#0#0#0'v'#0#0#0'v'#0#0#0'v'#0#0#0'v'#0#0#0'v'#0#0
  +#0'v'#0#0#0'v'#0#0#0'v'#0#0#0'v'#0#0#0'v'#0#0#0'v'#0#0#0'v'#0#0#0'v'#0#0#0'v'
  +#0#0#0'v'#0#0#0'v'#0#0#0'v'#0#0#0'v'#0#0#0'v'#0#0#0'v'#0#0#0'v'#0#0#0'v'#0#0
  +#0'v'#0#0#0'v'#0#0#0'v'#0#0#0'v'#0#0#0'r'#0#0#0'\'#0#0#0'/'#0#0#0#10#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#206#206#206#31#214#214#214#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255'ttt'#172#0#0#0'?'#0#0#0#14#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206#206#206#31#214#214
  +#214#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255'ttt'#173#0#0
  +#0'?'#0#0#0#14#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#206#206#206#31#214#214#214#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255'ttt'#173#0#0#0'?'#0#0#0#14#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#206#206#206#31#212#209#207#255#243#229#217#255#243#229#217#255#243#229#217
  +#255#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255#243#229
  +#217#255#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255#243
  +#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255
  +#243#229#217#255#243#229#217#255#234#221#209#255#230#216#205#255#229#216#204
  +#255#227#213#202#255#208#196#186#255#212#199#189#255#212#199#189#255#210#198
  +#188#255#216#203#193#255#233#219#208#255#235#222#210#255#240#226#214#255#241
  +#227#215#255'nhb'#173#0#0#0'?'#0#0#0#14#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206#206#206#31#214#214#214
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#224#224#224#255#199#199#200#255#177#176#177#255#158#157#159#255#162#160
  +#163#255#165#165#168#255#165#165#168#255#164#163#166#255#160#158#160#255#153
  +#151#152#255#165#164#164#255#203#203#203#255#230#230#230#255'nnn'#176#0#0#0
  +'D'#0#0#0#17#0#0#0#1#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#206#206#206#31#214#214#214#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#254#254#254#255#254#254
  +#254#255#255#255#255#255#222#221#223#255#191#190#191#255#179#178#181#255#165
  +#165#168#255#193#190#196#255#211#207#207#255#218#213#213#255#217#211#211#255
  +#216#211#211#255#217#213#214#255#211#208#210#255#195#194#196#255#170#170#174
  +#255#152#151#154#255#155#153#154#255'MKM'#191#1#0#2'Y'#0#0#0#29#0#0#0#7'AAE'
  +#2#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#206#206#206#31#212#209#207#255#243#229#217#255#243#229#217#255#243#229#217
  +#255#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255#243#229
  +#217#255#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255#243
  +#229#217#255#242#228#216#255#241#227#216#255#236#224#213#255#200#191#182#255
  +#175#170#167#255#189#185#187#255#203#198#197#255#212#203#197#255#194#181#173
  +#255#184#170#160#255#184#174#159#255#184#173#157#255#184#173#158#255#185#174
  +#160#255#184#174#162#255#188#176#166#255#204#192#186#255#207#200#200#255#188
  +#185#187#255'yxz'#226'347'#149#27#28#28'E225'#27'&(*'#11'::='#2#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206#206#206#31#214#214#214
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#253#253#253#255
  +#248#248#248#255#202#201#202#255#187#187#190#255#205#201#202#255#207#197#191
  +#255#186#175#162#255#174#163#148#255#189#178#163#255#201#194#179#255#211#204
  +#192#255#199#188#173#255#186#177#162#255#213#210#206#255#203#199#192#255#191
  +#185#174#255#178#170#158#255#179#167#156#255#198#188#180#255#206#200#200#253
  +#164#162#164#227'YZ['#150'())G99;'#27'EDH'#8'JDJ'#2#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206#206#206#31#214#214#214#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#254#254#254#255#250#250#250#255#199#199#200#255#192
  +#191#193#255#215#209#204#255#203#189#178#255#175#161#146#255#178#165#146#255
  +#211#201#184#255#229#222#207#255#228#221#207#255#227#220#206#255#206#195#180
  +#255#187#177#163#255#222#220#218#255#226#225#224#255#224#224#222#255#217#215
  +#210#255#199#192#182#255#179#168#155#255#187#175#163#255#207#198#193#253#178
  +#175#177#232']^a'#154'(%+H?9@'#26'JDJ'#8#1#0#6#3#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#206#206#206#31#212#209#207#255#243#229#217#255#243#229
  +#217#255#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255#243
  +#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255
  +#242#228#216#255#241#228#216#255#194#185#178#255#192#189#187#255#214#205#202
  +#255#183#170#157#255#176#164#146#255#216#208#190#255#196#183#159#255#182#166
  +#142#255#217#209#193#255#226#218#204#255#227#220#206#255#214#209#199#255#209
  +#202#195#255#229#227#224#255#227#224#222#255#225#223#222#255#211#207#200#255
  +#188#177#164#255#197#189#178#255#191#184#174#255#186#174#162#255#208#198#194
  +#253#177#174#176#230'_^a'#144'(&)='#7#5#11#20#1#0#6#6#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#206#206#206#31#214#214#214#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#251#251#251#255#233#233#233#255#190#190#193#255#211#204#203#255#189#175
  +#165#255#176#162#144#255#214#203#179#255#216#207#186#255#215#205#187#255#192
  +#179#157#255#196#187#168#255#228#220#205#255#230#223#209#255#231#225#217#255
  +#231#227#222#255#230#228#225#255#229#226#224#255#223#220#217#255#204#198#190
  +#255#201#194#185#255#220#218#213#255#219#217#213#255#194#187#179#255#188#177
  +#167#255#200#194#189#251#159#159#159#213'OPTu'#24#22#27'('#2#2#2#11#0#0#0#1#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206#206#206#31#214#214#214#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  ,#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#253#253#253#255#247#247#247#255#199#199#203#255#203#199#200#255#192#179#170
  +#255#170#158#141#255#211#199#176#255#212#200#176#255#210#198#176#255#215#206
  +#187#255#224#216#197#255#224#215#197#255#226#218#200#255#229#222#207#255#232
  +#226#214#255#231#226#218#255#230#229#222#255#230#229#225#255#227#225#221#255
  +#214#208#204#255#209#205#200#255#221#219#215#255#223#222#219#255#219#216#212
  +#255#192#185#175#255#191#181#170#254#195#189#189#247#131#129#128#182'224R'#5
  +#5#6#21#0#0#0#3#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206#206#206#31#212
  +#209#207#255#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255
  +#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217
  +#255#243#229#217#255#240#226#215#255#215#205#199#255#191#188#190#255#200#193
  +#188#255#169#156#142#255#205#192#170#255#217#205#184#255#209#196#174#255#211
  +#197#173#255#214#202#181#255#221#211#191#255#223#213#195#255#224#216#199#255
  +#227#220#203#255#232#226#211#255#232#227#216#255#231#229#222#255#231#230#226
  +#255#230#229#227#255#229#227#224#255#228#225#222#255#227#224#221#255#223#222
  +#218#255#223#222#219#255#214#211#206#255#187#179#167#255#199#190#181#253#178
  +#174#174#230'SRV'#131#18#15#19'('#10#7#10#7#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#206#206#206#31#214#214#214#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#247#247#247#255#202#202#208#255
  +#202#196#196#255#185#172#164#255#175#163#143#255#168#149'z'#255#191#176#154
  +#255#207#195#172#255#210#197#173#255#214#201#178#255#220#211#191#255#223#214
  +#196#255#224#215#197#255#227#218#201#255#232#224#209#255#233#228#214#255#233
  +#228#219#255#232#229#223#255#230#229#226#255#230#228#226#255#229#227#224#255
  +#227#225#222#255#225#223#221#255#219#215#211#255#195#187#174#255#185#175#163
  +#255#189#178#168#255#194#191#187#246#128'~'#127#180'$$&D'#2#2#3#13#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206#206#206#31#214#214#214#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#239#239
  +#239#255#204#203#207#255#207#201#198#255#171#158#145#255#211#200#177#255#200
  +#186#162#255#188#170#145#255#194#181#159#255#209#196#171#255#214#201#180#255
  +#221#210#192#255#223#214#195#255#224#214#195#255#225#216#199#255#229#221#206
  +#255#232#225#211#255#233#228#215#255#232#229#220#255#232#230#224#255#231#230
  +#226#255#230#229#226#255#228#226#223#255#228#226#223#255#204#197#189#255#190
  +#179#167#255#204#199#189#255#186#176#165#255#204#194#188#252#163#157#161#223
  +',''+d'#2#2#2#22#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206#206#206#31#212
  +#209#207#255#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255
  +#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217
  +#255#243#229#217#255#221#210#201#255#204#201#200#255#195#187#181#255#193#182
  +#163#255#228#216#195#255#230#219#198#255#224#212#187#255#219#206#182#255#214
  +#202#180#255#218#207#185#255#222#212#193#255#222#213#194#255#224#214#195#255
  +#224#215#197#255#229#222#206#255#231#222#207#255#232#225#210#255#234#228#215
  +#255#233#228#218#255#232#229#223#255#231#229#226#255#230#228#227#255#228#226
  +#224#255#227#225#223#255#226#224#223#255#224#222#219#255#196#190#181#255#197
  +#186#176#254#178#176#176#247'KKK'#142#7#7#6' '#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#206#206#206#31#214#214#214#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#223#223#225#255#212#210#210
  +#255#191#183#176#255#206#196#178#255#237#225#205#255#228#215#194#255#223#209
  +#184#255#221#208#184#255#221#210#188#255#223#214#195#255#222#213#193#255#222
  +#214#193#255#223#214#195#255#221#212#193#255#207#194#176#255#196#180#160#255
  +#227#219#202#255#232#227#212#255#233#227#213#255#232#227#216#255#231#228#220
  +#255#230#228#222#255#230#227#223#255#228#225#222#255#226#223#221#255#225#224
  +#222#255#204#200#192#255#190#180#169#255#193#189#187#253'qoq'#172#12#11#12'2'
  +#0#0#0#2#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206#206#206#31#214#214#214#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#217#218#219#255#213#210#209#255#193#183#175#255#214#203#186#255#239#229
  +#211#255#236#225#205#255#231#218#197#255#223#210#187#255#225#214#193#255#229
  +#220#204#255#224#215#195#255#222#212#191#255#222#212#193#255#220#212#193#255
  +#193#178#160#255#154#136's'#255#225#218#200#255#233#227#212#255#234#228#213
  +#255#235#229#216#255#234#229#218#255#232#229#220#255#231#229#224#255#230#228
  +#225#255#228#226#223#255#227#225#222#255#214#211#204#255#194#184#174#255#203
  +#198#196#255'zwz'#181#13#12#13'9'#0#0#0#3#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206
  ,#206#206#31#212#209#207#255#243#229#217#255#243#229#217#255#243#229#217#255
  +#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217
  +#255#243#229#217#255#243#229#217#255#214#208#203#255#213#208#205#255#194#182
  +#171#255#225#213#195#255#243#235#218#255#239#231#212#255#236#225#205#255#232
  +#220#200#255#230#219#199#255#232#223#205#255#230#221#204#255#225#215#196#255
  +#224#214#194#255#217#207#189#255#193#177#157#255#149#130'm'#255#211#201#182
  +#255#225#216#199#255#224#214#199#255#226#216#202#255#227#217#203#255#227#218
  +#205#255#227#218#206#255#225#216#205#255#225#219#208#255#227#223#217#255#219
  +#216#210#255#194#186#174#255#204#200#197#254#138#137#141#183#15#15#21'A'#0#0
  +#6#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206#206#206#31#214#214#214#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#222#222#224#255#213#209#206#255#199#187#175#255#193#175#151#255#177#158#135
  +#255#203#188#166#255#243#232#215#255#241#231#212#255#238#228#212#255#236#228
  +#214#255#232#223#206#255#232#223#206#255#212#199#180#255#170#150#130#255#149
  +#129'm'#255'yeO'#255#154#133'o'#255#163#143'{'#255#163#143'{'#255#165#144'|'
  +#255#166#145'}'#255#165#145'~'#255#163#143'{'#255#173#154#135#255#208#196#181
  +#255#195#183#167#255#176#163#144#255#184#173#157#255#203#197#192#255#135#134
  +#137#184#15#15#20'A'#0#0#6#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206#206#206#31
  +#214#214#214#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#223#223#225#255#213#209#208#255#190#179#166#255#227
  +#214#195#255#252#250#237#255#252#243#226#255#249#238#220#255#247#236#221#255
  +#247#239#226#255#249#242#229#255#245#240#230#255#242#236#225#255#240#233#222
  +#255#237#230#216#255#200#187#169#255#158#141'y'#255#226#217#198#255#236#227
  +#209#255#233#225#207#255#233#226#209#255#233#228#211#255#235#230#214#255#236
  +#230#216#255#233#228#213#255#226#221#205#255#227#221#207#255#224#218#207#255
  +#195#186#172#255#202#196#193#255#131#130#133#184#14#14#19'A'#0#0#5#4#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#206#206#206#31#212#209#207#255#243#229#217#255#243
  +#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255
  +#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255#210#203#198
  +#255#206#201#198#255#187#176#165#255#212#196#174#255#248#239#219#255#252#241
  +#223#255#254#242#223#255#250#242#224#255#247#240#226#255#250#243#230#255#248
  +#242#232#255#246#241#232#255#245#240#231#255#238#231#220#255#198#185#171#255
  +#153#135't'#255#215#206#188#255#222#213#194#255#220#210#192#255#221#210#192
  +#255#221#210#194#255#221#212#195#255#221#212#195#255#222#214#196#255#221#214
  +#197#255#220#213#197#255#213#205#190#255#193#182#168#255#196#193#188#253'oln'
  +#181#11#11#11'9'#0#0#0#3#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206#206#206#31#214
  +#214#214#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#219#221#221#255#211#209#207#255#188#178#172#255#204#188
  +#168#255#246#238#216#255#255#251#230#255#255#251#233#255#254#245#225#255#250
  +#240#225#255#248#241#229#255#248#242#232#255#247#243#234#255#246#242#233#255
  +#242#236#228#255#208#197#186#255#168#152#137#255#230#224#210#255#231#224#210
  +#255#225#217#201#255#222#214#198#255#221#212#196#255#220#211#195#255#220#210
  +#194#255#222#212#195#255#222#212#196#255#220#212#196#255#204#195#179#255#186
  +#176#162#255#190#186#185#251'dbe'#171#10#10#10'2'#0#0#0#2#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#206#206#206#31#214#214#214#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#225#226#226#255#205#202
  +#201#255#205#196#192#255#203#188#173#255#243#230#208#255#251#247#237#255#221
  +#213#196#255#239#230#208#255#254#248#226#255#251#242#229#255#249#241#231#255
  +#248#243#233#255#247#243#234#255#243#238#230#255#215#206#196#255#182#170#157
  +#255#237#231#222#255#239#233#222#255#234#227#215#255#231#224#212#255#228#221
  +#207#255#225#218#203#255#213#203#187#255#195#182#164#255#207#197#180#255#223
  +#215#199#255#197#188#171#255#195#184#173#255#185#179#181#249'VTW'#140#8#8#8
  +#28#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206#206#206#31#212#209#207#255
  +#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217
  +#255#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255#243#229
  +#217#255#224#213#205#255#200#194#194#255#210#203#200#255#192#182#174#255#221
  +#202#182#255#193#174#152#255#196#181#160#255#225#219#201#255#253#249#227#255
  +#255#246#229#255#250#243#230#255#248#242#231#255#249#244#235#255#245#239#230
  +#255#217#208#197#255#184#172#161#255#239#233#225#255#241#235#226#255#237#232
  +#221#255#235#229#218#255#233#227#215#255#231#224#211#255#231#224#211#255#202
  ,#192#176#255#176#161#141#255#198#185#167#255#188#176#163#255#202#193#185#255
  +#152#149#150#232'/11['#3#4#4#16#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206
  +#206#206#31#214#214#214#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#241#241#241#255#206#205#206#255#216#210
  +#209#255#205#194#187#255#200#183#169#255#204#183#160#255#227#221#206#255#253
  +#251#234#255#255#250#227#255#255#248#226#255#253#247#228#255#250#243#229#255
  +#248#242#232#255#244#239#228#255#216#206#195#255#184#172#158#255#239#234#225
  +#255#241#237#228#255#238#234#223#255#237#231#220#255#235#228#216#255#233#226
  +#213#255#232#224#210#255#228#220#206#255#213#204#188#255#195#185#169#255#188
  +#175#164#255#194#187#184#252#136#134#136#192'!! 3'#16#17#15#7#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#206#206#206#31#214#214#214#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#249#248#249
  +#255#217#217#219#255#211#206#207#255#215#208#203#255#197#187#178#255#231#211
  +#189#255#253#245#229#255#255#253#241#255#255#251#230#255#255#251#228#255#254
  +#246#225#255#253#242#226#255#249#239#225#255#245#235#222#255#212#201#189#255
  +#181#168#155#255#238#234#223#255#241#237#226#255#238#233#222#255#238#231#219
  +#255#236#229#216#255#233#226#213#255#229#221#207#255#228#220#206#255#227#220
  +#205#255#194#184#169#255#194#179#171#254#183#179#178#244'NNR'#127#17#17#17#31
  +#11#11#10#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206#206#206#31#212#209
  +#207#255#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255#243
  +#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255
  +#243#229#217#255#241#227#215#255#229#217#209#255#195#189#189#255#218#211#210
  +#255#208#199#190#255#195#182#171#255#230#209#186#255#252#245#229#255#254#254
  +#242#255#255#255#238#255#233#226#207#255#241#228#208#255#252#240#222#255#242
  +#232#215#255#202#189#173#255#169#154#141#255#240#233#221#255#243#237#226#255
  +#239#232#220#255#238#232#219#255#239#232#219#255#234#226#214#255#229#222#209
  +#255#231#223#207#255#204#194#179#255#195#180#168#255#201#193#190#248#136#134
  +#136#187'./0@'#29#30#31#9#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206
  +#206#206#31#214#214#214#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#254#254#254#255#250#250#250#255#226#226
  +#226#255#195#195#193#255#218#213#208#255#197#188#181#255#197#184#172#255#229
  +#207#183#255#253#243#232#255#220#213#200#255#192#176#153#255#234#227#206#255
  +#254#247#226#255#245#233#215#255#198#184#169#255#158#143#127#255#239#231#217
  +#255#244#238#226#255#241#236#224#255#216#205#190#255#192#180#162#255#225#217
  +#202#255#235#229#215#255#211#202#187#255#192#181#169#255#205#195#186#251#177
  +#171#171#221'bcdm"!"'#29#23#21#23#3#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#206#206#206#31#214#214#214#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#253#253#253#255
  +#245#245#246#255#210#208#210#255#201#197#199#255#226#222#216#255#203#194#185
  +#255#194#182#169#255#233#207#187#255#190#165#139#255#200#188#169#255#254#253
  +#247#255#255#252#231#255#247#237#216#255#194#178#163#255#155#139'|'#255#238
  +#230#215#255#243#238#226#255#241#236#227#255#230#223#211#255#197#185#167#255
  +#208#197#179#255#210#201#186#255#193#182#170#255#209#198#191#254#190#180#182
  +#236'}x|'#144#147#146#150'1'#162#162#166#10#4#5#5#1#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#206#206#206#31#212#209#207#255#243#229#217#255#243#229
  +#217#255#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255#243
  +#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255
  +#242#228#217#255#242#228#217#255#233#220#211#255#201#194#191#255#209#202#199
  +#255#230#224#220#255#206#194#189#255#194#184#176#255#206#186#167#255#230#210
  +#187#255#247#234#211#255#252#245#225#255#245#239#220#255#182#166#152#255#152
  +#139'}'#255#247#241#230#255#251#245#233#255#249#243#231#255#243#235#223#255
  +#222#213#198#255#196#185#170#255#197#185#171#255#214#203#195#253#196#190#190
  +#240#132#128#131#158#149#145#152'='#160#160#165#16#158#160#163#2#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206#206#206#31#214#214#214#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#253#253#253#255#242
  +#243#243#255#209#208#210#255#197#193#196#255#226#221#217#255#211#199#195#255
  +#193#181#172#255#190#181#168#255#202#187#167#255#212#194#172#255#218#200#178
  +#255#203#183#160#255#191#175#154#255#236#226#210#255#229#220#204#255#217#207
  ,#192#255#199#188#175#255#191#179#169#255#206#194#187#255#211#203#199#252#179
  +#177#176#234'||~'#155#147#147#148'?'#168#165#170#18#168#163#171#4#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206#206#206#31#214#214
  +#214#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#254#254#254#255#254#254#254
  +#255#254#254#254#255#244#244#245#255#222#222#224#255#191#195#197#255#202#202
  +#199#255#222#215#212#255#213#204#198#255#194#181#174#255#182#171#163#255#188
  +#175#163#255#197#185#169#255#200#188#175#255#196#184#173#255#195#182#172#255
  +#201#189#180#255#210#202#193#255#216#209#203#255#203#196#198#255#154#150#154
  +#229'wuw'#149#145#145#145'>'#162#162#165#19#161#161#166#5#27#26'$'#1#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206#206#206#31#212
  +#209#207#255#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255
  +#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217
  +#255#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255#243#229
  +#217#255#242#228#217#255#241#227#216#255#237#224#214#255#225#214#206#255#203
  +#194#192#255#188#187#187#255#194#194#191#255#214#211#212#255#212#210#209#255
  +#218#213#209#255#222#214#210#255#224#218#213#255#223#217#213#255#217#212#208
  +#255#207#204#202#255#196#193#193#255#180#177#178#255#187#181#179#255'vsq'#182
  +'<;=NQNR'#23'^ac'#3#29'!"'#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#206#206#206#31#214#214#214#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#254#254#254#255#251#251#251#255#246#246#246#255#236#235#237#255#220
  +#219#220#255#198#200#202#255#193#192#195#255#189#190#193#255#190#189#192#255
  +#187#187#190#255#185#186#188#255#180#180#184#255#183#184#186#255#195#196#197
  +#255#212#212#214#255#225#224#225#255'nnn'#176#13#13#13'C'#15#15#15#13#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#206#206#206#31#214#214#214#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#254#254#254#255#251
  +#251#251#255#249#249#249#255#245#245#245#255#240#240#240#255#229#229#229#255
  +#212#212#213#255'\\]'#149#0#0#0'!'#0#0#0#5#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206#206#206#31#212#209
  +#207#255#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255#243
  +#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255
  +#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217
  +#255#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255#243#229
  +#217#255#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255#231
  +#219#209#255#174#174#174#255#174#174#174#255#174#174#174#255#174#174#174#255
  +#174#174#174#255#174#174#174#255#185#185#186#255#131#131#132#203#28#28#28'T'
  +#0#0#0#11#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206#206#206#31#214#214#214#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#241#241#241#255#190#190#190
  +#255#255#255#255#255#253#253#253#255#246#246#246#255#236#236#236#255#219#219
  +#219#255#172#172#173#230'AAAz'#3#3#3#23#148#148#148#2#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206
  +#206#206#31#214#214#214#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#254#254#254#255#238#238#238#255#190#190#190#255#253#253#253#255#247#247#247
  +#255#236#236#236#255#219#219#220#255#178#178#179#232'III'#128#1#1#1#26#0#0#0
  +#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206#206#206#31#212#209#207#255#243#229#217#255
  ,#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217
  +#255#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255#243#229
  +#217#255#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255#243
  +#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255#243#229#217#255
  +#243#229#217#255#243#229#217#255#243#229#217#255#231#219#209#255#189#189#189
  +#255#247#247#247#255#237#237#237#255#220#220#220#255#186#186#187#235'VVV'#138
  +#1#1#1#29#0#0#0#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206#206#206#31#214#214
  +#214#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#253#253#253#255#233
  +#233#233#255#187#187#187#255#233#233#233#255#220#220#221#255#188#188#189#237
  +'[[['#143#1#1#1#28#0#0#0#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206
  +#206#206#31#214#214#214#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#254#254#254#255
  +#248#248#248#255#233#233#233#255#184#184#184#255#221#221#221#255#187#188#188
  +#238'XYY'#146#2#2#2#30#0#0#0#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#206#206#206#31#214#214#214#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#254#254
  +#254#255#246#246#246#255#224#224#224#255#181#181#181#255#195#195#195#242'iii'
  +#159#0#0#0#31#0#0#0#5#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#206#206#206#31#214#214#214#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#249#249#249#255#248#248
  +#248#255#240#240#240#255#219#219#219#255#189#189#191#244'rrr'#165#2#2#2'#'#0
  +#0#0#5#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#206#206#206#31#214#214#214#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#249#249#249#255#249#249#249#255#248#248#248
  +#255#237#237#237#255#189#189#190#244'eee'#162#2#2#2#30#0#0#0#5#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#214#214#214#31
  +#214#214#214#255#214#214#214#255#214#214#214#255#214#214#214#255#214#214#214
  +#255#214#214#214#255#214#214#214#255#214#214#214#255#214#214#214#255#214#214
  +#214#255#214#214#214#255#214#214#214#255#214#214#214#255#214#214#214#255#214
  +#214#214#255#214#214#214#255#214#214#214#255#214#214#214#255#214#214#214#255
  +#214#214#214#255#214#214#214#255#214#214#214#255#214#214#214#255#201#205#206
  +#237'a|}b'#0#0#0#22'???'#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#224#0#0#0#0#255#0#0#224#0#0#0#0#255#0#0#224#0#0#0#0#255#0#0#224#0
  +#0#0#0#255#0#0#224#0#0#0#0#255#0#0#224#0#0#0#0#255#0#0#224#0#0#0#0'?'#0#0#224
  +#0#0#0#0'?'#0#0#224#0#0#0#0#31#0#0#224#0#0#0#0#15#0#0#224#0#0#0#0#7#0#0#224#0
  +#0#0#0#7#0#0#224#0#0#0#0#3#0#0#224#0#0#0#0#3#0#0#224#0#0#0#0#3#0#0#224#0#0#0
  +#0#3#0#0#224#0#0#0#0#1#0#0#224#0#0#0#0#1#0#0#224#0#0#0#0#1#0#0#224#0#0#0#0#1
  +#0#0#224#0#0#0#0#1#0#0#224#0#0#0#0#1#0#0#224#0#0#0#0#1#0#0#224#0#0#0#0#1#0#0
  +#224#0#0#0#0#1#0#0#224#0#0#0#0#1#0#0#224#0#0#0#0#3#0#0#224#0#0#0#0#3#0#0#224
  +#0#0#0#0#3#0#0#224#0#0#0#0#7#0#0#224#0#0#0#0#7#0#0#224#0#0#0#0#7#0#0#224#0#0
  +#0#0#15#0#0#224#0#0#0#0#31#0#0#224#0#0#0#0#31#0#0#224#0#0#0#0'?'#0#0#224#0#0
  ,#0#0#255#0#0#224#0#0#0#0#255#0#0#224#0#0#0#1#255#0#0#224#0#0#0#1#255#0#0#224
  +#0#0#0#3#255#0#0#224#0#0#0#7#255#0#0#224#0#0#0#15#255#0#0#224#0#0#0#31#255#0
  +#0#224#0#0#0'?'#255#0#0#224#0#0#0#127#255#0#0#224#0#0#0#255#255#0#0#224#0#0#1
  +#255#255#0#0'('#0#0#0' '#0#0#0'@'#0#0#0#1#0' '#0#0#0#0#0#128#16#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1#0#0#0#11#0#0#0#26#0#0#0' '#0#0
  +#0' '#0#0#0' '#0#0#0' '#0#0#0' '#0#0#0' '#0#0#0' '#0#0#0' '#0#0#0' '#0#0#0' '
  +#0#0#0' '#0#0#0' '#0#0#0' '#0#0#0' '#0#0#0' '#0#0#0' '#0#0#0' '#0#0#0' '#0#0
  +#0' '#0#0#0' '#0#0#0#27#0#0#0#14#0#0#0#2#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#3#0#0#0'!'#0#0#0'N'#0#0#0'`'#0#0#0'`'#0#0#0'`'#0#0#0'`'#0
  +#0#0'`'#0#0#0'`'#0#0#0'`'#0#0#0'`'#0#0#0'`'#0#0#0'`'#0#0#0'`'#0#0#0'`'#0#0#0
  +'`'#0#0#0'`'#0#0#0'`'#0#0#0'`'#0#0#0'`'#0#0#0'`'#0#0#0'`'#0#0#0'`'#0#0#0'R'#0
  +#0#0'*'#0#0#0#7#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#214#214#214
  +#31#221#221#221#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255'ooo'#165#0#0#0'8'#0#0#0
  +#10#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#214#214#214#31#218#216
  +#213#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236
  +#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255
  +#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212
  +#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228
  +#212#255#236#228#212#255#236#228#212#255'gc\'#165#0#0#0'8'#0#0#0#10#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#214#214#214#31#221#221#221#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255'ooo'#165#0#0#0'8'#0#0#0#10#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#214#214#214#31#218#216#213#255#236#228#212#255#236#228
  +#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236
  +#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255
  +#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212
  +#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228
  +#212#255'gc\'#165#0#0#0'8'#0#0#0#10#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#214#214#214#31#221#221#221#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#253#253#253#255#240#240#240#255#206#205#205
  +#255#167#165#166#255#150#148#148#255#156#154#155#255#189#188#188#255'^]^'#169
  +#1#1#1':'#0#0#0#10#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#214#214
  +#214#31#218#216#213#255#236#228#212#255#236#228#212#255#236#228#212#255#236
  +#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255
  +#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212
  +#255#232#224#208#255#199#192#180#255#161#154#150#255#174#170#170#255#194#192
  +#193#255#207#204#204#255#196#194#195#255#171#167#168#255'_Z\'#215#26#23#24's'
  +#14#12#12#25#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#214#214#214#31
  +#221#221#221#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#253#253#253#255#209
  +#206#207#255#189#186#188#255#202#200#199#255#180#175#168#255#176#165#151#255
  +#171#159#144#255#175#164#151#255#183#177#171#255#192#190#190#251#144#141#144
  +#208'0./f'#20#18#18#18#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#214#214#214#31
  +#218#216#213#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212
  +#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228
  +#212#255#236#228#212#255#236#228#212#255#236#228#212#255#210#202#189#255#184
  +#180#177#255#201#200#197#255#171#159#143#255#177#166#149#255#215#207#190#255
  +#241#232#217#255#230#224#215#255#199#190#182#255#182#171#160#255#196#191#190
  +#253#146#144#149#198'.,-O'#22#20#20#9#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#214#214
  +#214#31#221#221#221#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#248#248#248#255#186#181#184
  +#255#207#205#205#255#173#162#147#255#198#189#172#255#234#225#203#255#238#232
  +#213#255#248#241#224#255#252#246#235#255#252#249#243#255#229#225#219#254#192
  ,#183#174#254#194#189#187#248'`\`'#167'#'#31'!$'#29#26#27#1#0#0#0#0#0#0#0#0#0
  +#0#0#0#214#214#214#31#218#216#213#255#236#228#212#255#236#228#212#255#236#228
  +#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236
  +#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#213#205#192#255
  +#190#185#183#255#186#183#178#255#178#166#149#255#229#220#199#255#227#220#200
  +#255#232#226#208#255#240#234#215#255#248#241#225#255#252#246#236#255#252#248
  +#242#254#209#200#192#254#184#179#176#254#148#145#148#211'1-/L'#30#25#27#6#0#0
  +#0#0#0#0#0#0#0#0#0#0#214#214#214#31#221#221#221#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#203#200#200#255#209#208#209#255#181#171#157#255#208#200#186#255#231#225#209
  +#255#228#221#202#255#229#223#204#255#200#189#170#255#198#187#170#255#251#246
  +#234#255#251#247#238#254#230#222#213#254#192#181#171#254#179#176#177#238'968'
  +'{'#29#26#27#12#0#0#0#0#0#0#0#0#0#0#0#0#214#214#214#31#218#216#213#255#236
  +#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255
  +#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212
  +#255#236#228#212#255#182#174#166#255#217#216#214#255#172#160#145#255#241#233
  +#219#255#242#238#223#255#229#224#205#255#186#173#152#255#137'xc'#255#140'|f'
  +#255#158#142'y'#255#156#140'y'#254#196#181#163#253#184#172#156#254#193#189
  +#186#248'A=>'#143'"'#29#31#15#0#0#0#0#0#0#0#0#0#0#0#0#214#214#214#31#221#221
  +#221#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#195#192#192#255#221#218#218#255#173#161#147
  +#255#245#236#223#255#252#247#235#255#246#242#229#255#227#220#206#255#185#171
  +#156#255#178#166#145#255#215#208#189#255#216#207#189#253#219#207#189#253#184
  +#172#156#254#194#190#187#249'FCC'#143'($$'#15#0#0#0#0#0#0#0#0#0#0#0#0#214#214
  +#214#31#218#216#213#255#236#228#212#255#236#228#212#255#236#228#212#255#236
  +#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255
  +#236#228#212#255#236#228#212#255#236#228#212#255#195#187#179#255#208#205#204
  +#255#185#174#162#255#221#214#202#255#255#250#237#255#255#251#238#255#248#246
  +#234#255#203#192#177#255#190#179#162#255#238#234#218#255#232#227#209#254#211
  +#204#189#253#183#174#159#254#180#175#173#238'JFG{2..'#12#0#0#0#0#0#0#0#0#0#0
  +#0#0#214#214#214#31#221#221#221#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#232#231#231#255
  +#202#199#202#255#186#180#175#255#188#178#162#255#255#254#244#255#255#250#237
  +#255#247#243#229#255#198#187#174#255#192#182#167#255#245#241#228#255#240#232
  +#215#254#195#184#167#254#174#167#159#254#156#152#154#209'LGIL<68'#6#0#0#0#0#0
  +#0#0#0#0#0#0#0#214#214#214#31#218#216#213#255#236#228#212#255#236#228#212#255
  +#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212
  +#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#233#225
  +#209#255#191#184#178#255#212#209#206#255#185#175#161#255#220#214#204#255#255
  +#254#243#255#246#244#230#255#196#185#169#255#190#179#162#255#246#240#225#255
  +#216#208#193#254#181#172#158#254#193#189#184#246'|wz'#165'LFI#HBD'#1#0#0#0#0
  +#0#0#0#0#0#0#0#0#214#214#214#31#221#221#221#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#232#231#230#255#207#205#207#255#208#204#201#255#180#169#155#255
  +#187#176#163#255#217#209#198#255#192#180#162#255#175#163#146#255#191#183#168
  +#255#172#161#145#255#193#188#183#253#168#165#166#194'_XYNMEE'#9#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#214#214#214#31#218#216#213#255#236#228#212#255#236#228#212
  +#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228
  +#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236
  +#228#212#255#235#227#211#255#207#199#188#255#201#196#193#255#208#204#201#255
  +#186#180#172#255#177#166#153#255#168#155#140#255#174#163#149#255#184#177#169
  +#255#196#193#191#249#166#164#165#202'hacdVMO'#18#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#214#214#214#31#221#221#221#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#252#252#252#255#229#228#229#255#198#196#197#255#202
  +#199#201#255#212#210#209#255#218#215#214#255#212#209#208#255#200#197#198#255
  +#137#133#135#213'JEFr?99'#25#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#214#214#214#31#218#216#213#255#236#228#212#255#236#228#212#255#236#228#212
  +#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228
  ,#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236
  +#228#212#255#236#228#212#255#235#227#211#255#229#221#206#255#210#202#190#255
  +#189#181#171#255#181#172#164#255#183#175#166#255#200#192#180#255'd`Z'#169#4#4
  +#4':'#0#0#0#10#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#214#214#214#31
  +#221#221#221#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255'ooo'#165#0#0#0'8'#0#0#0#10#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#214#214#214#31#218#216#213#255
  +#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212
  +#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228
  +#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236
  +#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255
  +#236#228#212#255#224#220#212#255'\\\'#165#0#0#0'8'#0#0#0#10#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#214#214#214#31#221#221#221#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#253#254#254#255#238#239#239#255#211#211#211#255#199#199#199#255
  +#187#187#187#255'PPP'#159#0#0#0'0'#0#0#0#8#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#214#214#214#31#218#216#213#255#236#228#212#255#236#228#212#255
  +#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212
  +#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228
  +#212#255#236#228#212#255#236#228#212#255#236#228#212#255#225#218#205#255#176
  +#176#176#255#170#170#170#255#169#169#169#255#171#171#171#255#179#179#179#254
  +'PPP'#142#0#0#0#29#0#0#0#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#214#214#214#31#221#221#221#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#244#244#244#255#209#209#209#255
  +#244#244#244#255#237#237#237#255#209#209#209#254#144#144#144#193'+++E'#0#0#0
  +#9#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#214#214#214#31#218
  +#216#213#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255
  +#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212
  +#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228
  +#212#255#236#228#212#255#230#223#210#255#217#217#217#255#245#245#245#255#222
  +#222#222#254#161#161#161#198'666K'#0#0#0#11#159#159#159#1#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#214#214#214#31#221#221#221#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#245#245#245#255#210#210#210#255#219#219#219#254#164#164#164#206':::Q'#0
  +#0#0#13#143#143#143#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#214#214#214#31#221#221#221#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#252#252#252#255#226#226#226#255#196#196
  +#196#254#168#168#168#214'???W'#0#0#0#14#127#127#127#1#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#214#214#214#31#221#221#221
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#250#250#250#255#214#214#214#254#170#170#170#223'IIIa'#0#0#0#17'ooo'#2#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#214#214#214#31#214#214#214#255#214#214#214#255#214#214#214#255#214#214#214
  +#255#214#214#214#255#214#214#214#255#214#214#214#255#214#214#214#255#214#214
  +#214#255#214#214#214#255#214#214#214#255#214#214#214#255#214#214#214#255#214
  +#214#214#255#214#214#214#255#212#212#212#254#190#190#190#222'aaaW'#0#0#0#13
  +'___'#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#192#0#0#15#192#0#0#15#192#0#0#15#192#0#0#15#192#0#0#15#192#0#0#15#192#0#0
  +#15#192#0#0#15#192#0#0#7#192#0#0#3#192#0#0#1#192#0#0#1#192#0#0#1#192#0#0#1
  +#192#0#0#1#192#0#0#1#192#0#0#1#192#0#0#1#192#0#0#3#192#0#0#7#192#0#0#15#192#0
  +#0#15#192#0#0#15#192#0#0#15#192#0#0#15#192#0#0#15#192#0#0#31#192#0#0#31#192#0
  ,#0'?'#192#0#0#127#192#0#0#255#192#0#1#255'('#0#0#0#24#0#0#0'0'#0#0#0#1#0' '#0
  +#0#0#0#0'`'#9#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#10#0#0#0#25#0#0#0' '#0#0#0' '#0#0#0' '#0#0#0' '#0#0#0' '#0#0#0' '#0#0#0' '
  +#0#0#0' '#0#0#0' '#0#0#0' '#0#0#0' '#0#0#0' '#0#0#0' '#0#0#0' '#0#0#0#25#0#0
  +#0#10#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#2#0#0#0#30#0#0#0'L'#0#0#0
  +'`'#0#0#0'`'#0#0#0'`'#0#0#0'`'#0#0#0'`'#0#0#0'`'#0#0#0'`'#0#0#0'`'#0#0#0'`'#0
  +#0#0'`'#0#0#0'`'#0#0#0'`'#0#0#0'`'#0#0#0'`'#0#0#0'L'#0#0#0#31#0#0#0#3#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#207#207#207#21#213#213#213#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255'555'#129
  +#0#0#0'*'#0#0#0#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#207#207#207#21#210#209#207
  +#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228
  +#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236
  +#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255
  +#236#228#212#255'1/,'#129#0#0#0'*'#0#0#0#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#207#207#207#21#213#213#213#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255'555'#129#0#0#0'*'#0#0#0#4#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#207#207#207#21#210#209#207#255#236#228#212#255#236
  +#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255
  +#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#230#222#207
  +#255#208#199#183#255#181#168#148#255#174#159#140#255#190#179#166#255#132#127
  +'y'#170#19#18#17'3'#0#0#0#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#207#207#207#21
  +#213#213#213#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#237#235#232#255#192#182#168#255#184#174#152#255#221#212#192#255#230
  +#221#206#255#207#199#187#255#173#161#145#254#174#167#159#162#176#170#164#18#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#207#207#207#21#210#209#207#255#236#228#212#255
  +#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212
  +#255#236#228#212#255#236#228#212#255#230#222#208#255#192#181#163#255#178#165
  +#141#255#216#208#186#255#238#232#213#255#247#242#224#255#242#236#223#255#216
  +#210#199#254#179#165#151#254#200#192#185'h'#204#197#191#6#0#0#0#0#0#0#0#0#0#0
  +#0#0#207#207#207#21#213#213#213#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#227#223#218#255#189#180#163#255#210#201#181#255#230#224#205#255
  +#218#209#192#255#174#159#139#255#218#209#193#255#226#220#207#254#208#199#187
  +#254#178#166#154#181#174#162#150#14#0#0#0#0#0#0#0#0#0#0#0#0#207#207#207#21
  +#210#209#207#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212
  +#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#205#195
  +#177#255#199#189#171#255#232#227#210#255#215#207#187#255#167#154#133#255#137
  +'w`'#255#146#129'k'#255#150#134'q'#254#200#188#172#253#172#157#141#232#167
  +#152#135#19#0#0#0#0#0#0#0#0#0#0#0#0#207#207#207#21#213#213#213#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#216#210#202#255#202#192#177#255
  +#240#234#222#255#245#241#228#255#218#211#200#255#167#152#134#255#200#191#173
  +#255#213#204#187#253#209#198#183#253#169#156#138#232#164#150#132#19#0#0#0#0#0
  +#0#0#0#0#0#0#0#207#207#207#21#210#209#207#255#236#228#212#255#236#228#212#255
  +#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212
  +#255#236#228#212#255#217#208#193#255#199#190#174#255#222#218#202#255#249#248
  +#235#255#226#220#208#255#168#153#136#255#223#217#201#255#241#237#219#254#201
  +#193#176#253#173#163#150#181#171#160#148#14#0#0#0#0#0#0#0#0#0#0#0#0#207#207
  +#207#21#213#212#212#255#255#254#249#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#247#246#244#255#203#195#185#255#189#181#166#255#224#221#209#255#218#211#199
  +#255#166#152#135#255#216#211#196#255#209#201#183#254#174#161#142#254#190#185
  +#180'h'#194#190#187#6#0#0#0#0#0#0#0#0#0#0#0#0#207#207#207#21#210#209#207#255
  +#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212
  +#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#224#216
  +#201#255#188#178#162#255#190#182#166#255#205#197#183#255#170#157#138#255#185
  +#176#155#255#178#167#147#254#172#166#155#162#172#167#158#18#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#207#207#207#21#213#213#213#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  ,#255#255#255#255#255#255#255#255#255#255#255#255#255#245#243#242#255#215#210
  +#203#255#185#174#160#255#170#157#140#255#192#185#173#255#131#127'{'#170#18#18
  +#17'3'#0#0#0#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#207#207#207#21#210#209#207#255
  +#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212
  +#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228
  +#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236
  +#228#212#255'1/,'#129#0#0#0'*'#0#0#0#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#207
  +#207#207#21#213#213#213#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#253#253
  +#253#255#253#253#253#255#253#253#253#255'444'#129#0#0#0'*'#0#0#0#4#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#207#207#207#21#210#209#207#255#236#228#212#255#236#228
  +#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236
  +#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255
  +#236#228#212#255#228#221#208#255#217#211#201#255#205#201#194#255'*)(x'#0#0#0
  +'$'#0#0#0#3#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#207#207#207#21#213#213#213#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#211#211#211#255#180#180#180#255#180#180#180#255#180#180#180#255#180
  +#180#180#255'%%%_'#0#0#0#20#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#207#207
  +#207#21#210#209#207#255#236#228#212#255#236#228#212#255#236#228#212#255#236
  +#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255#236#228#212#255
  +#236#228#212#255#236#228#212#255#203#199#193#255#226#226#226#255#254#254#254
  +#255#232#232#233#255#150#150#150#159#26#26#26')'#0#0#0#5#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#207#207#207#21#213#213#213#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#211#211#211#255
  +#226#226#226#255#233#233#234#255#154#154#154#165#31#31#31'.'#0#0#0#6#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#207#207#207#21#213#213#213#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#211#211#211#255#207#207#208#255#158#158#158#170'$$$2'#0#0#0#7#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#207#207#207#21#213#213#213#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#238#238
  +#238#255#208#208#210#255#152#152#153#175')))7'#0#0#0#7#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#207#207#207#21#207#207#207#255#207
  +#207#207#255#207#207#207#255#207#207#207#255#207#207#207#255#207#207#207#255
  +#207#207#207#255#207#207#207#255#207#207#207#255#207#207#207#255#207#207#207
  +#255#159#159#159#180'///;'#0#0#0#8#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#0#0#0#0#0#0#224#0#3#0#192#0#3#0#192#0#3#0#192#0#3#0#192#0#3#0#192#0#3#0
  +#192#0#3#0#192#0#1#0#192#0#1#0#192#0#1#0#192#0#1#0#192#0#1#0#192#0#1#0#192#0
  +#3#0#192#0#3#0#192#0#3#0#192#0#3#0#192#0#3#0#192#0#3#0#192#0#7#0#192#0#15#0
  +#192#0#31#0#192#0'?'#0#192#0#127#0'('#0#0#0#16#0#0#0' '#0#0#0#1#0' '#0#0#0#0
  +#0'@'#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'zzz'#255'zzz'#255'zzz'
  +#255'zzz'#255'zzz'#255'zzz'#255'zzz'#255'zzz'#255'zzz'#255'zzz'#255'zzz'#255
  +'zzz'#255'zzz/'#0#0#0#0#0#0#0#0#0#0#0#0#141#141#141#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#164#164#164
  +#255#134#134#134'/'#0#0#0#0#0#0#0#0#0#0#0#0#149#149#148#255#239#229#211#255
  +#239#229#211#255#239#229#211#255#239#229#211#255#239#229#211#255#239#229#211
  +#255#239#229#211#255#239#229#211#255#239#229#211#255#239#229#211#255#167#165
  +#160#255#144#144#144'/'#0#0#0#0#0#0#0#0#0#0#0#0#163#163#163#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#253#253#252#255#230#227#221#255#198#188#174#255#190#179#165#255#178
  +#172#165#255#174#169#164'2'#0#0#0#0#0#0#0#0#0#0#0#0#176#175#174#255#239#229
  +#211#255#239#229#211#255#239#229#211#255#239#229#211#255#239#229#211#255#238
  +#228#211#255#214#204#187#255#197#187#168#255#224#215#196#255#231#224#209#255
  +#196#186#173#255#185#176#165#176#186#177#167#22#0#0#0#0#0#0#0#0#178#178#178
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#236#233#230#255#202#193#178#255#216#207#186#255#232#225#206#255#228
  +#221#203#255#236#231#218#255#200#190#177#255#189#179#168#143#189#179#169#7#0
  +#0#0#0#180#180#179#255#239#229#211#255#239#229#211#255#239#229#211#255#239
  +#229#211#255#239#229#211#255#215#204#186#255#208#199#181#255#226#219#200#255
  ,#185#173#153#255#148#132'n'#255#161#147'}'#255#179#163#143#255#175#160#145
  +#205#174#160#145#12#0#0#0#0#183#183#183#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#225#220#213#255#215#207#192
  +#255#244#240#226#255#211#203#189#255#170#155#135#255#197#187#168#255#206#196
  +#179#255#173#160#142#214#169#155#137#13#0#0#0#0#184#184#182#255#239#229#211
  +#255#239#229#211#255#239#229#211#255#239#229#211#255#239#229#211#255#223#213
  +#197#255#212#204#191#255#239#236#224#255#222#216#203#255#177#165#144#255#232
  +#228#212#255#205#196#179#255#176#166#155#162#174#164#154#9#0#0#0#0#188#188
  +#188#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#251#251#251#255#217#212#204#255#207#201#188#255#210#203#189#255
  +#175#162#142#255#202#193#174#255#187#177#161#209#198#194#190')'#201#198#196#1
  +#0#0#0#0#189#188#187#255#239#229#211#255#239#229#211#255#239#229#211#255#239
  +#229#211#255#239#229#211#255#239#229#211#255#236#227#209#255#217#207#192#255
  +#189#177#160#255#177#164#145#255#183#177#167#255#205#203#199'7'#210#208#205#1
  +#0#0#0#0#0#0#0#0#192#192#192#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#238#238#239#255#224#224#225#255#195#195#195#255#186#186#186'/'#0#0#0
  +#0#0#0#0#0#0#0#0#0#192#191#190#255#239#229#211#255#239#229#211#255#239#229
  +#211#255#239#229#211#255#239#229#211#255#239#229#211#255#239#229#211#255#209
  +#204#196#255#184#184#184#255#184#184#184#255#185#185#185#255#186#186#186'/'#0
  +#0#0#0#0#0#0#0#0#0#0#0#195#195#195#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#222#222#222#255#233#233#233#255#207#207#207#250#212#212#212#133#221#221#221
  +#17#0#0#0#0#0#0#0#0#0#0#0#0#195#195#195#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#253#253#253#255#253#253#253
  +#255#225#225#225#255#192#192#192#253#214#215#213#151#227#229#226#26#0#0#0#0#0
  +#0#0#0#0#0#0#0#0#0#0#0#192#192#192#255#192#192#192#255#192#192#192#255#192
  +#192#192#255#192#192#192#255#192#192#192#255#192#192#192#255#192#192#192#255
  +#191#191#191#253#224#224#224#170#245#245#245'%'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  +#0#128#3#0#0#128#3#0#0#128#3#0#0#128#3#0#0#128#1#0#0#128#0#0#0#128#0#0#0#128
  +#0#0#0#128#0#0#0#128#0#0#0#128#1#0#0#128#3#0#0#128#3#0#0#128#3#0#0#128#7#0#0
  +#128#15#0#0
]);

Added SnapViewer/src/prj/fpc/SnapViewer.manifest.



































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
 <assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="CompanyName.ProductName.YourApp" type="win32"/>
 <description>Your application description here.</description>
 <dependency>
  <dependentAssembly>
   <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/>
  </dependentAssembly>
 </dependency>
 <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
  <security>
   <requestedPrivileges>
    <requestedExecutionLevel level="asInvoker" uiAccess="false"/>
   </requestedPrivileges>
  </security>
 </trustInfo>
</assembly>

Added SnapViewer/src/prj/fpc/SnapViewer.rc.



































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
1 VERSIONINFO
FILEVERSION 0,1,0,77
PRODUCTVERSION 1,0,0,0
{
 BLOCK "StringFileInfo"
 {
  BLOCK "040904E4"
  {
   VALUE "Comments", "http://martijn.coppoolse.com/software/\000"
   VALUE "CompanyName", "Voronw毛\000"
   VALUE "FileDescription", "\000"
   VALUE "FileVersion", "0.1.0.77\000"
   VALUE "InternalName", "SnapViewer\000"
   VALUE "LegalCopyright", "漏 Martijn Coppoolse\000"
   VALUE "LegalTrademarks", "\000"
   VALUE "OriginalFilename", "snapviewer\000"
   VALUE "ProductName", "TimeSnapshooter\000"
   VALUE "ProductVersion", "1.0.0.0\000"
  }
 }
 BLOCK "VarFileInfo"
 {
  VALUE "Translation", 0x0409, 0x04E4
 }
}

#define RT_MANIFEST  24
#define CREATEPROCESS_MANIFEST_RESOURCE_ID 1
#define ISOLATIONAWARE_MANIFEST_RESOURCE_ID 2
#define ISOLATIONAWARE_NOSTATICIMPORT_MANIFEST_RESOURCE_ID 3

CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "SnapViewer.manifest"
MAINICON ICON "SnapViewer.ico"

Added SnapViewer/src/prj/fpc/f_main.lrs.





















































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
{ This is an automatically generated lazarus resource file }

LazarusResources.Add('TfrmMain','FORMDATA',[
  'TPF0'#8'TfrmMain'#7'frmMain'#4'Left'#3'>'#1#6'Height'#3#228#1#3'Top'#3#188#0
  +#5'Width'#3#168#2#7'Caption'#6#15'Snapshot viewer'#12'ClientHeight'#3#228#1
  +#11'ClientWidth'#3#168#2#10'OnActivate'#7#12'FormActivate'#8'OnCreate'#7#10
  +'FormCreate'#12'OnDeactivate'#7#14'FormDeactivate'#8'Position'#7#14'poScreen'
  +'Center'#10'LCLVersion'#6#8'0.9.28.2'#0#13'TPairSplitter'#12'pspLeftRight'#4
  +'Left'#2#0#6'Height'#3#205#1#3'Top'#2#0#5'Width'#3#168#2#5'Align'#7#8'alClie'
  +'nt'#8'Position'#3' '#1#0#17'TPairSplitterSide'#7'pssLeft'#6'Cursor'#7#7'crA'
  +'rrow'#4'Left'#2#0#6'Height'#3#205#1#3'Top'#2#0#5'Width'#3' '#1#11'ClientWid'
  +'th'#3' '#1#12'ClientHeight'#3#205#1#0#9'TTreeView'#9'tvwPeriod'#4'Left'#2#0
  +#6'Height'#3#205#1#3'Top'#2#0#5'Width'#3' '#1#5'Align'#7#8'alClient'#17'Defa'
  +'ultItemHeight'#2#17#8'ReadOnly'#9#8'TabOrder'#2#0#10'OnDeletion'#7#17'tvwPe'
  +'riodDeletion'#18'OnSelectionChanged'#7#25'tvwPeriodSelectionChanged'#7'Opti'
  +'ons'#11#17'tvoAutoItemHeight'#16'tvoHideSelection'#21'tvoKeepCollapsedNodes'
  +#11'tvoReadOnly'#14'tvoShowButtons'#12'tvoShowLines'#11'tvoShowRoot'#11'tvoT'
  +'oolTips'#0#10'Items.Data'#10'8'#2#0#0#249#255#255#255#2#0#2#0#0#0#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#5#0#0#0#0#0#0#0#1#7
  +#0#0#0'Week 34'#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#0#0#0#0#0#0#0#0#0#19#0#0#0'maandag 23 augustus'#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#255#0#0#0#0#0#0#0#0#0#19#0#0#0'dinsdag '
  +'24 augustus'#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
  +#0#0#0#0#0#0#0#0#0#20#0#0#0'woensdag 25 augustus'#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#0#0#0#0#0#0#0#0#0#21#0#0#0'donderdag 26'
  +' augustus'#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#0
  +#0#0#0#0#0#0#0#0#19#0#0#0'vrijdag 27 augustus'#255#255#255#255#255#255#255
  +#255#255#255#255#255#255#255#255#255#5#0#0#0#0#0#0#0#1#7#0#0#0'Week 35'#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#0#0#0#0#0#0#0#0
  +#0#19#0#0#0'maandag 30 augustus'#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#255#0#0#0#0#0#0#0#0#0#19#0#0#0'dinsdag 31 augustus'#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#0#0#0#0#0#0#0#0#0#20
  +#0#0#0'woensdag 1 september'#255#255#255#255#255#255#255#255#255#255#255#255
  +#255#255#255#255#0#0#0#0#0#0#0#0#0#21#0#0#0'donderdag 2 september'#255#255
  +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#0#0#0#0#0#0#0#0#0#19
  +#0#0#0'vrijdag 3 september'#0#0#0#17'TPairSplitterSide'#8'pssRight'#6'Cursor'
  +#7#7'crArrow'#4'Left'#3'%'#1#6'Height'#3#205#1#3'Top'#2#0#5'Width'#3#131#1#11
  +'ClientWidth'#3#131#1#12'ClientHeight'#3#205#1#0#13'TPairSplitter'#12'pspTop'
  +'Bottom'#6'Cursor'#7#8'crVSplit'#4'Left'#2#0#6'Height'#3#205#1#3'Top'#2#0#5
  +'Width'#3#131#1#5'Align'#7#8'alClient'#8'Position'#3#232#0#12'SplitterType'#7
  +#11'pstVertical'#0#17'TPairSplitterSide'#6'pssTop'#6'Cursor'#7#7'crArrow'#4
  +'Left'#2#0#6'Height'#3#232#0#3'Top'#2#0#5'Width'#3#131#1#11'ClientWidth'#3
  +#131#1#12'ClientHeight'#3#232#0#0#10'TScrollBox'#11'scbContents'#4'Left'#2#0
  +#6'Height'#3#232#0#3'Top'#2#0#5'Width'#3#131#1#5'Align'#7#8'alClient'#12'Cli'
  +'entHeight'#3#228#0#11'ClientWidth'#3#127#1#8'TabOrder'#2#0#0#9'TPaintBox'#11
  +'pbxActivity'#4'Left'#2#0#6'Height'#3#150#0#3'Top'#2#0#5'Width'#3#127#1#5'Al'
  +'ign'#7#5'alTop'#7'OnClick'#7#16'pbxActivityClick'#7'OnPaint'#7#16'pbxActivi'
  +'tyPaint'#0#0#0#0#17'TPairSplitterSide'#9'pssBottom'#6'Cursor'#7#7'crArrow'#4
  +'Left'#2#0#6'Height'#3#224#0#3'Top'#3#237#0#5'Width'#3#131#1#11'ClientWidth'
  +#3#131#1#12'ClientHeight'#3#224#0#0#6'TPanel'#9'pnlViewer'#4'Left'#2#0#6'Hei'
  +'ght'#3#224#0#3'Top'#2#0#5'Width'#3#131#1#5'Align'#7#8'alClient'#10'BevelOut'
  +'er'#7#9'bvLowered'#12'ClientHeight'#3#224#0#11'ClientWidth'#3#131#1#8'TabOr'
  +'der'#2#0#0#6'TImage'#11'imgSnapshot'#4'Left'#2#1#6'Height'#3#222#0#3'Top'#2
  +#1#5'Width'#3#129#1#5'Align'#7#8'alClient'#12'Proportional'#9#7'Stretch'#9#0
  +#0#0#0#0#0#0#10'TStatusBar'#7'sbrMain'#4'Left'#2#0#6'Height'#2#23#3'Top'#3
  +#205#1#5'Width'#3#168#2#6'Panels'#14#1#5'Width'#3','#1#0#1#4'Text'#6#11'SQLi'
  +'te v0.0'#5'Width'#2'd'#0#1#4'Text'#6#12'No snapshots'#5'Width'#3','#1#0#0#11
  +'SimplePanel'#8#0#0#18'TSQLite3Connection'#5'cnnDB'#9'Connected'#8#11'LoginP'
  +'rompt'#8#12'DatabaseName'#6'YC:\Documents and Settings\All Users\Applicatio'
  +'n Data\Voronw'#195#171'\Snapshooter\activity.sqlite'#14'KeepConnection'#8#11
  +'Transaction'#7#15'SQLTransaction1'#7'Options'#11#0#4'left'#2#24#3'top'#3#146
  +#1#0#0#15'TSQLTransaction'#15'SQLTransaction1'#6'Active'#8#6'Action'#7#6'caN'
  +'one'#8'Database'#7#5'cnnDB'#4'left'#2'`'#3'top'#3#146#1#0#0#9'TSQLQuery'#10
  +'qryPeriods'#9'IndexName'#6#13'DEFAULT_ORDER'#14'AutoCalcFields'#8#8'Databas'
  +'e'#7#5'cnnDB'#11'Transaction'#7#15'SQLTransaction1'#8'ReadOnly'#9#11'SQL.St'
  +'rings'#1#6'M  SELECT 0 + strftime(''%Y'', coalesce(UpdateDateTime, InsertDa'
  +'teTime)) AS year'#6'M  ,      0 + strftime(''%W'', coalesce(UpdateDateTime,'
  ,' InsertDateTime)) AS week'#6'I  ,      date(MIN(coalesce(UpdateDateTime, In'
  +'sertDateTime))) AS first_day'#6'H  ,      date(MAX(coalesce(UpdateDateTime,'
  +' InsertDateTime))) AS last_day'#6#14'    FROM Focus'#6#13'GROUP BY year'#6
  +#13',        week'#6#18'ORDER BY year DESC'#6#19',        week DESC;'#0#6'Pa'
  +'rams'#14#0#10'UpdateMode'#7#14'upWhereKeyOnly'#4'left'#3#168#0#3'top'#3#146
  +#1#0#0#0
]);

Added Snapshooter/doc/Projecturen.sql.



















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
CREATE TABLE Projecten
( id 			INTEGER PRIMARY KEY
, naam			TEXT NOT NULL
, omschrijving	TEXT
, opdrachtgever TEXT NOT NULL
, external_id	TEXT
, etc.
);


CREATE TABLE Bestedingen
( id 			INTEGER PRIMARY KEY
, project_id	INTEGER NOT NULL CONSTRAINT fk_bestedingen_project REFERENCES Projecten(id)
, datum			TEXT NOT NULL
, tijd			TEXT
, taak_id		INTEGER CONSTRAINT fk_bestedingen_taak REFERENCES Taken(id)
, aantal_uren	REAL
, activiteiten	TEXT
, etc.
);

CREATE TABLE Taken
( id				INTEGER PRIMARY KEY
, project_id		INTEGER NOT NULL CONSTRAINT fk_taak_project REFERENCES Projecten(id)
, naam				TEXT NOT NULL
, omschrijving		TEXT
, budget_uren		INTEGER
, budget_geld		REAL
, etc.
);


CREATE TABLE Aanwezigheid
( id 			INTEGER PRIMARY KEY
, datum			TEXT NOT NULL
, tijd			TEXT
, aantal_uren	INTEGER NOT NULL
, opmerkingen	TEXT
, etc.
);
 

Added Snapshooter/doc/SnapViewer-display.txt.























































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
// VOOR DE BESTAANDE DATABASE:
// TODO: update Window.LastUpdateDateTime gebaseerd op max(coalesce(Window.LastUpdateDateTime, Window.InsertDateTime), coalesce(Focus.UpdateDateTime, Focus.InsertDateTime))
// TODO: update Process.LastUpdateDateTime gebaseerd op max(etc., coalesce(Window.*DateTime))
// TODO: update Session.LastUpdateDateTime gebaseerd op max(etc., coalesce(Process.*DateTime))

{
Per dag:
* Selecteer eerst begin en eind van elke sessie:
	-- vervang hieronder "'now', 'localtime'" door ":Datum"
	SELECT *
	  FROM Session
	 WHERE RunLocationID = :RunLocationID
	   AND ((Session.InsertDateTime >= date('now', 'localtime') AND Session.InsertDateTime < date('now', 'localtime', '+1 day'))
			OR (Session.LastUpdateDateTime >= date('now', 'localtime') AND Session.LastUpdateDateTime < date('now', 'localtime', '+1 day'))
			OR (Session.InsertDateTime < date('now', 'localtime') AND Session.LastUpdateDateTime >= date('now', 'localtime', '+1 day'));
  - maak o.b. daarvan de sessie-vakken aan;
    - een sessie die gisteren begon, wordt weergegeven vanaf het begin van het dagvak (dus vanaf de eerste andere gebeurtenis);
    - een sessie die doorloopt naar morgen, wordt weergegeven tot het einde van het dagvak (dus t/m het einde van de laatste andere gebeurtenis);
  - evt. gedeeltelijk weergegeven sessie weergeven met kringeltjes, een icoontje of een kleurverloopje of zo.

* Selecteer per sessie vervolgens begin en eind van alle processen die daarbij horen;
  - voor elk gevonden proces:
    - maak een balk;
	- geef het icoon van de executable weer links- of rechtsboven in de hoek;
    - rek evt. de sessie uit tot het einde van het laatst bekende proces;
    - als het een bestaande procesbalk overlapt, dan ernaast plaatsen.

* Selecteer per proces vervolgens begin en eind van alle bijbehorende windows;
  - en voor elk gevonden window:
    - maak een balk;
	- geef het icoon van het window weer links- of rechtsboven in de hoek
	- rek evt. de procesbalk uit tot de laatste registratie van het window;
	- rek evt. de sessie uit tot het einde van het laatst bekende proces;
	- als het een bestaand window overlapt:
		- is het het parent window: dan er gedeeltelijk overheen plaatsen;
		- anders: het nieuwe window ernaast zetten.
		- in alle gevallen: de breedte van het proces aanpassen, en alle overlappende processen opschuiven;

* Selecteer alle focusopnames van een window;
  - per focusmoment:
    - maak een (bij voorkeur doorschijnend, anders een border-only) balkje, en plaats dat binnen de gefocuste tijd (in het proces?).
	- als er van dat moment een screenshot is, toon dan een snapshot-icoon, of zelfs een thumbnail,
	  binnen de rechterkant van de focusbalk.
	
* Selecteer alle focusmomenten, behalve die waarvan de idle time minder is dan de interval sinds de vorige focus;
  - in de speciale user-balk, kleur alle idle-gedeeltes in; vanaf elk vroegst bekende idle-moment
    tot het volgende bekende idle-moment, en geef een verloopje weer tussen het laatst bekende 
	idle-moment, en het eerstvolgende idle-moment.

}
	
type
	TDbPanel = class(TPanel)
		protected
			FDbId: int64;
			FChildren: TList;
			
			function  GetBegin: TDateTime; virtual;
			function  GetEnd: TDateTime; virtual;
		public
			constructor Create(Owner: TComponent; ID: int64); virtual;
			
			procedure PositionChildren; virtual;
			
			property DateTimeBegin: TDateTime		read GetBegin;
			property DateTimeEnd: TDateTime			read GetEnd;
	end;
	
	TSessionPanel = class(TDbPanel)
		private
			const FTableName = 'Session';
		protected
			FTopTime: TDateTime;
			FBottomTime: TDateTime;
			
			function  GetProcessCount: integer;
			function  GetProcess(Index: integer): TProcessPanel;
		public
			constructor Create(Owner: TComponent; ID: int64); override;
			
			property ProcessCount: integer						read GetProcessCount;
			property Processes[index: integer]: TProcessPanel	read GetProcess;
	end;
	
	TProcessPanel = class(TDbPanel)
		private 
			const FTableName = 'Process';
		protected
			function  GetParent: TSessionPanel; override;
		public
			constructor Create(Owner: TComponent; ID: int64); override;
	end;
	
	TWindowPanel = class(TDbPanel)
		private
			const FTableName = 'Window';
		protected
			function  GetParent: TProcessPanel; override;
		public
			constructor Create(Owner: TComponent; ID: int64); override;
	end;
	
{ ------------------------------------------------------------------------------------------------ }
procedure TDbPanel.PositionChildren;
var
	Child, Overlap: TDbPanel;
	MaxRight: integer;
	Gaps: TSpaceList; // TODO: figure out what the horizontal gaps are, where the current child could fit
begin
	Self.Width := Parent.ClientWidth;
	// TODO: get list of overlapping processes; make sure the current one starts at the leftmost 
	//        available position to the right of the overlapping processes
	for i := 0 to FChildren.Count - 1 do begin
		Child := TDbPanel(FChildren[i]);
		
		// Position the element vertically
		DecodeTime(Child.DateTimeBegin, Hours, Minutes, Seconds, Milliseconds);
		Child.Top := (Hours * 4) + (Minutes div 15);
		DecodeTime(Child.DateTimeBegin, Hours, Minutes, Seconds, Milliseconds);
		Child.Height := ((Hours * 4) + (Minutes div 15)) - Child.Top;
		
		// Prepare to position the child horizontally
		MaxRight := 0;
		Gaps := TSpaceList.Create;
		try
			Gaps.Add(0, Self.Width); // Self.InnerWidth? Self.ClientWidth?
			// Loop through the preceding children, to find any overlaps
			for j := 0 to i - 1 do begin
				Overlap := TDbPanel(FChildren[j]);
				
				if ((Overlap.Top < Child.Top) and ((Overlap.Top + Overlap.Height) > (Child.Top + Child.Height)))
						or ((Overlap.Top >= Child.Top) and (Overlap.Top < (Child.Top + Child.Height)))
						or (((Overlap.Top + Overlap.Height) >= Child.Top) and ((Overlap.Top + Overlap.Height) < (Child.Top + Child.Height)))
						then begin
					// this one overlaps; remove its space from the available gaps
					Gaps.Exclude(Overlap.Left, Overlap.Left + Overlap.Width);
					// and keep track of the rightmost edge
					MaxRight := Max(MaxRight, Overlap.Left + Overlap.Width);
				end;
			end;
			// Figure out the first space where the child would fit
			for g := 0 to Gaps.Count - 1 do begin
				if Gaps.Width[g] >= Child.Width then begin
					Child.Left := Gaps.Left[g];
					Break;
				end;
			end;
			// If the child couldn't fit in any of the gaps, put it at the extreme right
			if g >= Gaps.Count then begin
				Child.Left := MaxRight;
			end;
		finally
			Gaps.Free;
		end;
		
		// Prevent clipping of the child
		if Child.Left + Child.Width > Self.Width then begin // Self.InnerWidth? Self.ClientWidth?
			Self.Width := Self.Width + ((Child.Left + Child.Width) - Self.ClientWidth);
		end;
	end;
end;
	
{ ------------------------------------------------------------------------------------------------ }
constructor TSessionPanel.Create(Owner: TComponent; ID: int64);
var
	SessionBar: TPanel;
	RowIndex, i: integer;
	MaxX: integer;
begin
	inherited Create(Owner);
	
	// Include the processes
	FDB.AddParamInt(':SessionID', id);
	Processes := FDB.GetTable('SELECT id FROM Process WHERE SessionID = :SessionID ORDER BY InsertDateTime ASC, LastUpdateDateTime ASC');
	try
		for RowIndex := 0 to Processes.Count - 1 do begin
			Processes.MoveTo(RowIndex);
			ProcessPanel := TProcessPanel.Create(Self, Processes.FieldAsInteger('id'));
			FChildren.Add(ProcessPanel);
		end;
	finally
		Processes.Free;
	end;
	
	PositionChildren;
end;

Added Snapshooter/doc/SnapViewer.txt.







































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
Interface
=========

[Week  |v|] (2008/42; 13-19 oktober)
_________________________

 - Maandag
   路 09:12 Helpdesk - Borland Developer Studio 2006 [bds.exe]
   路 10:07 Microsoft Excel - Weekuren.xls [EXCEL.EXE]
   路 10:12 Netvibes (195) - Mozilla Firefox [firefox.exe]
 + Dinsdag
 + Woensdag
 + Donderdag
 + Vrijdag
_________________________


Bij selectie van...
* Weekdag: toon timeline van die dag;
  - hoogte van viewport (scrollable): instelbaar minimaal aantal uren binnen 1 window? (standaard 1 TextHeight per kwartier)
  - bovenkant window = vroegste registratie die dag
  - onderkant window = laatste registratie die dag
  - balk voor elk proces -- onder elkaar als het kan, anders naast elkaar
  - binnen procesbalk: blok voor elk openstaand venster (InsertDateTime t/m LastUpdateDateTime); wederom onder elkaar als het kan, anders naast
  - aparte balk voor idle-registratie (meest linkse balk?)
* Tijdstip:
  - highlight balk van bijbehorend proces en window; evt. met thumbnail van screenshot?
  - in vak onder tijdlijn, verkleinde versie van de screenshot. Dubbelklik = open volledig shot
  - teken rode lijn op geselecteerd tijdstip


Opbouwen tijdlijn
=================
* Mee te nemen events
  - Start/shutdown OS  (Session.StartupTime, Session.PreviousShutdownTime) -- HKLM\System\CurrentControlSet\Control\Windows >> ShutdownTime
  - Start/einde sessies (Session.InsertDateTime, Session.LastUpdateDateTime)
  - Start/einde processen (coalesce(Process.StartupTime, Process.InsertDateTime), coalesce(Process.TerminateTime, Process.LastUpdateDateTime)
  - Eerste/laatste registratie van elk window (Window.InsertDateTime, Window.LastUpdateDateTime)
  - Start/stop idle user (Focus.InsertDateTime - Focus.IdleMilliseconds)
  - Focus-snapshots

CREATE TABLE Timeline
( id					INTEGER PRIMARY KEY
, DateTime				TEXT NOT NULL
, Bias					INTEGER NOT NULL
, Subject				TEXT -- 'System', 'Session', 'Process', 'Window', 'User', 'Desktop'
, Verb					TEXT -- 'startup', 'start', 'first seen', 'last seen', 'terminate', 'shutdown', 'capture', 'idle', 'active'
, Description			TEXT
, SessionID				INTEGER CONSTRAINT fk_Timeline_Session REFERENCES Session(id)
, ExecutableID			INTEGER CONSTRAINT fk_Timeline_Executable REFERENCES Executable(id)
, ProcessID				INTEGER CONSTRAINT fk_Timeline_Process REFERENCES Process(id)
, WindowID				INTEGER CONSTRAINT fk_Timeline_Window REFERENCES Window(id)
, FocusID				INTEGER CONSTRAINT fk_Timeline_Focus REFERENCES Focus(id)
, InsertDateTime		TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
);


Overig
======
* Overal de "T" uit de datum/tijd halen?
* Executable: 
  + Name NOT NULL = ExtractFileName(Path)
  + Path NOT NULL = IncludePathDelimiter(ExtractFilePath(Path))
* Window: Icon BLOB
* Misschien voor elk gevonden GetForegroundWindow, GetParent registreren tot die nil teruggeeft?


================================================================================
CREATE VIEW v_Timeline AS

SELECT DISTINCT date(StartupTime, TimeZoneBias || ' minutes') AS DateUTC
,      time(StartupTime, TimeZoneBias || ' minutes') AS TimeUTC
,      TimeZoneBias AS Bias
,      'System' AS Subject
,      'begin' AS Verb
,      NULL AS Description
,      NULL AS SessionID
,      NULL AS ExecutableID
,      NULL AS ProcessID
,      NULL AS WindowID
,      NULL AS FocusID
  FROM Session
  
UNION

SELECT DISTINCT date(PreviousShutdownTime) AS DateUTC
,      time(PreviousShutdownTime) AS TimeUTC
,      TimeZoneBias AS Bias
,      'System' AS Subject
,      'end' AS Verb
,      NULL AS Description
,      NULL AS SessionID
,      NULL AS ExecutableID
,      NULL AS ProcessID
,      NULL AS WindowID
,      NULL AS FocusID
  FROM Session
 WHERE PreviousShutdownTime IS NOT NULL
 
UNION

SELECT date(InsertDateTime, TimeZoneBias || ' minutes')
,      time(InsertDateTime, TimeZoneBias || ' minutes')
,      TimeZoneBias
,      'Session'
,      'begin'
,      NULL
,      id
,      NULL
,      NULL
,      NULL
,      NULL
  FROM Session

UNION

SELECT date(coalesce(LastUpdateDateTime, InsertDateTime), TimeZoneBias || ' minutes')
,      time(coalesce(LastUpdateDateTime, InsertDateTime), TimeZoneBias || ' minutes')
,      TimeZoneBias
,      'Session'
,      'end'
,      NULL
,      id
,      NULL
,      NULL
,      NULL
,      NULL
  FROM Session

UNION

SELECT date(coalesce(t.StartupTime, t.InsertDateTime), s.TimeZoneBias || ' minutes')
,      time(coalesce(t.StartupTime, t.InsertDateTime), s.TimeZoneBias || ' minutes')
,      s.TimeZoneBias
,      'Process'
,      'begin'
,      coalesce(e.Description, t.WindowTitle) || ' [' || e.Name || ']'
,      s.id
,      t.ExecutableID
,      t.id
,      NULL
,      NULL
  FROM Process t
       INNER JOIN Session s
	           ON t.SessionID = s.id
	   INNER JOIN Executable e
			   ON t.ExecutableID = e.id

UNION

-- TODO: if the end time is unknown, then use the MAX of children's end times (windows)
SELECT date(coalesce(t.TerminateTime, t.LastUpdateDateTime, t.InsertDateTime), s.TimeZoneBias || ' minutes')
,      time(coalesce(t.TerminateTime, t.LastUpdateDateTime, t.InsertDateTime), s.TimeZoneBias || ' minutes')
,      s.TimeZoneBias
,      'Process'
,      'end'
,      coalesce(e.Description, t.WindowTitle) || ' [' || e.Name || ']'
,      s.id
,      t.ExecutableID
,      t.id
,      NULL
,      NULL
  FROM Process t
       INNER JOIN Session s
	           ON t.SessionID = s.id
	   INNER JOIN Executable e
			   ON t.ExecutableID = e.id

UNION

SELECT date(t.InsertDateTime, s.TimeZoneBias || ' minutes')
,      time(t.InsertDateTime, s.TimeZoneBias || ' minutes')
,      s.TimeZoneBias
,      'Window'
,      'begin'
,      trim(t.Title) || ' [' || t.Class || ']'
,      s.id
,      p.ExecutableID
,      p.id
,      t.id
,      NULL
  FROM Window t
	   INNER JOIN Process p
	           ON t.ProcessID = p.id
       INNER JOIN Session s
	           ON p.SessionID = s.id

UNION

-- TODO: if the end time is unknown, then use the MAX of children's end times (focus)
SELECT date(coalesce(t.LastUpdateDateTime, t.InsertDateTime), s.TimeZoneBias || ' minutes')
,      time(coalesce(t.LastUpdateDateTime, t.InsertDateTime), s.TimeZoneBias || ' minutes')
,      s.TimeZoneBias
,      'Window'
,      'end'
,      trim(t.Title) || ' [' || t.Class || ']'
,      s.id
,      p.ExecutableID
,      p.id
,      t.id
,      NULL
  FROM Window t
	   INNER JOIN Process p
	           ON t.ProcessID = p.id
       INNER JOIN Session s
	           ON p.SessionID = s.id

UNION

SELECT date(t.InsertDateTime, s.TimeZoneBias || ' minutes')
,      time(t.InsertDateTime, s.TimeZoneBias || ' minutes')
,      s.TimeZoneBias
,      'Desktop'
,      'capture'
,      nullif(t.Title, '')
,      s.id
,      p.ExecutableID
,      p.id
,      w.id
,      t.id
  FROM Focus t
	   INNER JOIN Window w
	           ON t.WindowID = w.id
	   INNER JOIN Process p
	           ON w.ProcessID = p.id
       INNER JOIN Session s
	           ON p.SessionID = s.id

UNION

SELECT DISTINCT date(t.InsertDateTime, '-' || (t.IdleMilliseconds / 1000) || ' seconds', s.TimeZoneBias || ' minutes')
,      time(t.InsertDateTime, '-' || (t.IdleMilliseconds / 1000) || ' seconds', s.TimeZoneBias || ' minutes')
,      s.TimeZoneBias
,      'User'
,      'Idle'
,      p.UserName
,      s.id
,      NULL
,      NULL
,      NULL
,      NULL
  FROM Focus t
	   INNER JOIN Window w
	           ON t.WindowID = w.id
	   INNER JOIN Process p
	           ON w.ProcessID = p.id
       INNER JOIN Session s
	           ON p.SessionID = s.id
 WHERE t.IdleMilliseconds > 300000


ORDER BY DateUTC
,        TimeUTC
,        Verb ASC
,        ProcessID
,        WindowID
;


================================================================================
SELECT b.*
,      e.DateUTC AS EndDateUTC
,      e.TimeUTC AS EndTimeUTC
,      e.Bias AS EndBias
,      nullif(e.Description, b.Description) AS EndDescription
  FROM v_Timeline b, v_Timeline e
 WHERE b.Verb = 'begin'
   AND e.Verb = 'end'
   AND b.Subject = e.Subject
   AND ifnull(b.SessionID, 0) = ifnull(e.SessionID, 0)
   AND ifnull(b.ExecutableID, 0) = ifnull(e.ExecutableID, 0)
   AND ifnull(b.ProcessID, 0) = ifnull(e.ProcessID, 0)
   AND ifnull(b.WindowID, 0) = ifnull(e.WindowID, 0)
   AND ifnull(b.FocusID, 0) = ifnull(e.FocusID, 0)

Added Snapshooter/doc/TaskHours.sql.







































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
CREATE TABLE Hours
( id 				INTEGER PRIMARY KEY
, Date				TEXT(10) NOT NULL
, ProjectID			INTEGER NOT NULL CONSTRAINT fk_hours_project REFERENCES Projects(id)
, TaskID			INTEGER CONSTRAINT fk_hours_task REFERENCES Tasks(id)
, Hours				FLOAT
, AdministrationID	INTEGER
, InsertDateTime	TEXT NOT NULL
, UpdateDateTime	TEXT
);

CREATE TABLE Administrations
( id 				INTEGER PRIMARY KEY
, Name				TEXT NOT NULL
, Description		TEXT
, ShadowOfID		INTEGER CONSTRAINT fk_administration_shadowing REFERENCES Administrations(id)
, InsertDateTime	TEXT NOT NULL
, UpdateDateTime	TEXT
);

Added Snapshooter/doc/TaskShooter-extra.js.





























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// Determine the (currently known) working times for today

function getWorkTimes() {
	// Adjust query string with current date as start-min and start-max
	var today = new Date();
	today.setHours(0, 0, 0, 0);
	var startMin = getXMLFormattedDateTime(today);
	today.setDate(today.getDate() + 1);
	var startMax = getXMLFormattedDateTime(today);
	
	// Get today's working hours from Google Calendar
	// TODO: set up some error handling
	var xmlDoc = getDOMDoc(download('https://www.google.com/calendar/feeds/mkeqbnk2k81fai4l3hubuqqav0%40group.calendar.google.com/private-9df59598523ff53a6637df9115b89c98/full?q=DGMR&singleevents=true&start-min=' + startMin + '&start-max=' + startMax, 'binary stream'));
	xmlDoc.setProperty('SelectionNamespaces', 'xmlns:atom="http://www.w3.org/2005/Atom" xmlns:gd="http://schemas.google.com/g/2005"');
	var now = getXMLFormattedDateTime(new Date());
	// Find the current working time span
	var xmlEntry = xmlDoc.selectSingleNode('(/atom:feed/atom:entry[atom:title="DGMR"])[gd:when/@startTime < "' + now + '" and gd:when/@endTime > "' + now + '"]');
	if (!xmlEntry) {
		// No current one; take the next
		xmlEntry = xmlDoc.selectSingleNode('(/atom:feed/atom:entry[atom:title="DGMR"])[gd:when/@startTime > "' + now + '"]');
	}
	if (!xmlEntry) {
		// No next one either!  Then take the last known one, if any...
		xmlEntry = xmlDoc.selectSingleNode('(/atom:feed/atom:entry[atom:title="DGMR"])[position() = last()]');
	}
	if (!xmlEntry) {
		// No working time span for today!
		throw new Error('It seems we\'ve got ourselves a holiday today!');
	} else {
		var xmlWhen = xmlEntry.selectSingleNode('gd:when');
		
		// TODO: notify the user of the remaining time...
		return  { startTime: getDateTimeFromXML(xmlWhen.getAttribute('startTime'))
				, endTime: getDateTimeFromXML(xmlWhen.getAttribute('endTime'))
				};
	}
}



/*

<?xml version='1.0' encoding='UTF-8'?>
<feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:batch='http://schemas.google.com/gdata/batch' xmlns:gCal='http://schemas.google.com/gCal/2005' xmlns:gd='http://schemas.google.com/g/2005'>
	<id>http://www.google.com/calendar/feeds/mkeqbnk2k81fai4l3hubuqqav0%40group.calendar.google.com/private-9df59598523ff53a6637df9115b89c98/full</id>
	<updated>2008-12-02T11:43:50.000Z</updated>
	<category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event'/>
	<title type='text'>Werk</title>
	<subtitle type='text'/>
	<link rel='alternate' type='text/html' href='http://www.google.com/calendar/embed?src=mkeqbnk2k81fai4l3hubuqqav0@group.calendar.google.com'/>
	<link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://www.google.com/calendar/feeds/mkeqbnk2k81fai4l3hubuqqav0%40group.calendar.google.com/private-9df59598523ff53a6637df9115b89c98/full'/>
	<link rel='http://schemas.google.com/g/2005#batch' type='application/atom+xml' href='http://www.google.com/calendar/feeds/mkeqbnk2k81fai4l3hubuqqav0%40group.calendar.google.com/private-9df59598523ff53a6637df9115b89c98/full/batch'/>
	<link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/mkeqbnk2k81fai4l3hubuqqav0%40group.calendar.google.com/private-9df59598523ff53a6637df9115b89c98/full?q=DGMR&amp;max-results=25&amp;start-min=2008-12-02T00%3A00%3A00&amp;singleevents=true&amp;start-max=2008-12-03T00%3A00%3A00'/>
	<author>
		<name>Martijn Coppoolse</name>
		<email>tinus.coppoolse@gmail.com</email>
	</author>
	<generator version='1.0' uri='http://www.google.com/calendar'>Google Calendar</generator>
	<openSearch:totalResults>1</openSearch:totalResults>
	<openSearch:startIndex>1</openSearch:startIndex>
	<openSearch:itemsPerPage>25</openSearch:itemsPerPage>
	<gd:where valueString='Den Haag, NL'/>
	<gCal:timezone value='Europe/Amsterdam'/>
	<gCal:timesCleaned value='0'/>
	<entry>
		<id>http://www.google.com/calendar/feeds/mkeqbnk2k81fai4l3hubuqqav0%40group.calendar.google.com/private-9df59598523ff53a6637df9115b89c98/full/t03nqre0gs1s6e85ke6rrl4euc_20081202T073000Z</id>
		<published>2008-06-19T07:16:17.000Z</published>
		<updated>2008-12-02T11:43:50.000Z</updated>
		<category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event'/>
		<title type='text'>DGMR</title>
		<content type='text'/>
		<link rel='alternate' type='text/html' href='http://www.google.com/calendar/event?eid=dDAzbnFyZTBnczFzNmU4NWtlNnJybDRldWNfMjAwODEyMDJUMDczMDAwWiBta2VxYm5rMms4MWZhaTRsM2h1YnVxcWF2MEBn' title='alternate'/>
		<link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/mkeqbnk2k81fai4l3hubuqqav0%40group.calendar.google.com/private-9df59598523ff53a6637df9115b89c98/full/t03nqre0gs1s6e85ke6rrl4euc_20081202T073000Z'/>
		<author>
			<name>Martijn Coppoolse</name>
			<email>tinus.coppoolse@gmail.com</email>
		</author>
		<gd:originalEvent id='t03nqre0gs1s6e85ke6rrl4euc' href='http://www.google.com/calendar/feeds/mkeqbnk2k81fai4l3hubuqqav0%40group.calendar.google.com/private-9df59598523ff53a6637df9115b89c98/full/t03nqre0gs1s6e85ke6rrl4euc'>
			<gd:when startTime='2008-12-02T08:30:00.000+01:00'/>
		</gd:originalEvent>
		<gd:comments>
			<gd:feedLink href='http://www.google.com/calendar/feeds/mkeqbnk2k81fai4l3hubuqqav0%40group.calendar.google.com/private-9df59598523ff53a6637df9115b89c98/full/t03nqre0gs1s6e85ke6rrl4euc_20081202T073000Z/comments'/>
		</gd:comments>
		<gd:eventStatus value='http://schemas.google.com/g/2005#event.confirmed'/>
		<gd:transparency value='http://schemas.google.com/g/2005#event.opaque'/>
		<gCal:uid value='t03nqre0gs1s6e85ke6rrl4euc@google.com'/>
		<gCal:sequence value='0'/>
		<gd:when startTime='2008-12-02T10:30:00.000+01:00' endTime='2008-12-02T18:30:00.000+01:00'/>
		<gd:who rel='http://schemas.google.com/g/2005#event.organizer' valueString='Werk' email='mkeqbnk2k81fai4l3hubuqqav0@group.calendar.google.com'/>
		<gd:where valueString='Eisenhowerlaan 112, Den Haag, NL'/>
	</entry>
</feed>

*/

Added Snapshooter/doc/TaskShooter.sql.































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
CREATE TABLE Projects
( id				INTEGER PRIMARY KEY
, ParentProjectID	INTEGER CONSTRAINT fk_project_parent REFERENCES Projects(id)
, Name				TEXT NOT NULL
, Description		TEXT
, ExternalID		TEXT -- projectnummer in Profit
, InsertDateTime	TEXT NOT NULL
, UpdateDateTime	TEXT
);

CREATE TABLE Tasks
( id				INTEGER PRIMARY KEY
, ProjectID			INTEGER CONSTRAINT fk_task_project REFERENCES Projects(id)
, Name				TEXT NOT NULL
, Description		TEXT
, InsertDateTime	TEXT NOT NULL
, UpdateDateTime	TEXT
);

CREATE TABLE Activity
( id				INTEGER PRIMARY KEY
, ProjectID			INTEGER CONSTRAINT fk_activity_project REFERENCES Projects(id)
, TaskID			INTEGER CONSTRAINT fk_activity_task REFERENCES Tasks(id)
, Verb				TEXT NOT NULL -- 'start', 'end', 'pause', 'resume'
, Description		TEXT
, InsertDateTime	TEXT NOT NULL
, UpdateDateTime	TEXT
);

/*
[Projecten]

[lstProjects]	+-Project-------------+   +-Taak----------------+
[           ]	| Naam: [           ] |   | Naam: [           ] |
[           ]   | Omschrijving:       |   | Omschrijving:       |
[           ]	| [                 ] |	  | [                 ] |
[           ]	| [                 ] |	  | [                 ] |
[           ]	| +-lstTaken--------+ |   | +-lstActiviteiten-+ |
[           ]	| [                 ] |   | [                 ] |
[           ]	| [                 ] |   | [                 ] |
[           ]	| [                 ] |   | [                 ] |
[           ]	| [                 ] |   | [                 ] |
[           ]	| [_________________] |   | [_________________] |
[___________]   +---------------------+   +---------------------+


*/

Added Snapshooter/doc/WorkMinder.rar.

cannot compute difference between binary files

Added Snapshooter/doc/WorkMinder.txt.



>
1
DateTime	Screenshot	hWnd	Caption	Classname	PID	Path	Description	IdleMS

Added Snapshooter/doc/janitor.sql.





















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
CREATE TABLE Janitor
( id 			INTEGER PRIMARY KEY
, FocusID		INTEGER NOT NULL UNIQUE CONSTRAINT fk_Janitor_Focus REFERENCES Focus(id)
, Converted		INTEGER -- NULL = not yet necessary; 1 = yes; 0 = no, wasn't advantageous
, Downsized		INTEGER -- NULL = not yet necessary; 1 = yes; 0 = no, an error occurred (see Remarks)
, Deleted		INTEGER -- NULL = not yet necessary; 1 = yes; 0 = no, unable to (see Remarks)
, Remarks		TEXT -- error messages and such
);

INSERT INTO Janitor
(FocusID, Converted)
SELECT id, 1
  FROM Focus
 WHERE ScreenShotFile LIKE '%.jpg';

-- to add to all three selection queries
SELECT *
  FROM Focus f
       LEFT JOIN Janitor j
              ON f.ID = j.FocusID
 WHERE j.Converted IS NULL; -- or Downsize IS NULL or Deleted IS NULL

-- update janitor table after each action
UPDATE Janitor
   SET Converted = :Success
   ,   Remarks = :Remarks
 WHERE FocusID = :FocusID;

-- if that didn't alter any row, then try an insert:
INSERT INTO Janitor
(FocusID, Converted, Remarks)
SELECT :FocusID, :Success, :Remarks;


CREATE TABLE Janitor_Errors
( id 			INTEGER PRIMARY KEY
, class_name	TEXT NOT NULL
, message		TEXT NOT NULL
, focus_id		INTEGER CONSTRAINT fk_Error_Focus REFERENCES Focus(id)
, details		TEXT
, timestamp		TEXT(20)
);

Added Snapshooter/doc/todo.txt.





























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
[TODO]
- Error-tabel maken (zie janitor.sql), en vullen zodra er een fout optreedt -- of misschien toch maar een error log bijhouden naast de database?  (IncludeTrailingPathDelimiter(FBasePath) + 'error.log')
	procedure ReportError(E: Exception; FocusID: int64; Details: string = '');
	begin
	  try
		FDB.AddParamText(':ClassName', E.ClassName);
		FDB.AddParamText(':Message', E.Message);
		FDB.AddParamInt(':FocusID', FocusID, 0);
		FDB.AddParamText(':Details', Details, '');
		FDB.AddParamDateTime(':DateTime', Now);
		FDB.ExecSQL('INSERT INTO Janitor_Errors (class_name, message, focus_id, details, timestamp)'
				  + 'VALUES (:ClassName, :Message, :FocusID, :Details, :DateTime)');
	  except
		// skip for now. TODO: write to file?
	  end;
	end;
- VACUUM uit Stop halen; bij het opstarten NextVacuumTime := (Today + 1) + EncodeTime(0, 15); en na 
  elke tmrScreenshot waarbij het werkstation gelocked is, controleren of NextVacuumTime geweest is; 
  zo ja, dan VACUUM uitvoeren, NextVacuumTime op de volgende ochtend instellen, en de FJanitor aan 
  de gang zetten, als die tenminste Terminated was.
- Pause/Continue/Stop werkend krijgen, ook met de aparte thread
- Janitor: na verwijderen elk bestand, kijken of de parent dir leeg is; zo ja, verwijder die dir (en zo voorts tot de FBasePath)

[DONE]
- DONE: in TImageJanitor: na converteren van elke afbeelding, checken of we nog niet Terminated zijn.
  Zo ja, dan meteen stoppen; zo nee, dan 5 secondes adempauze voor de rest van de PC
- DONE: TImageJanitor lage prio geven
- DONE: (Sorteer)volgorde veranderen: oudste het eerst verwijderen/converteren/verkleinen
- DONE: In aparte tabel bijhouden wat de status van elke screenshot is (zie janitor.sql)
- DONE: in tmrScreenshot: geen screenshot maken als desktop gelocked is

Added Snapshooter/res/CreateDatabase.sql.







































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
CREATE TABLE IF NOT EXISTS Session
( ID					INTEGER PRIMARY KEY
, RunLocationID			INTEGER NOT NULL CONSTRAINT fk_session_runlocation REFERENCES RunLocation(ID)
, Version				CHAR
, DbVersion				CHAR
, TimeZoneBias			INTEGER
, StartupTime			CHAR NOT NULL
, PreviousShutdownTime	CHAR
, IsActive				INTEGER NOT NULL
, UnloadModeID			INTEGER CONSTRAINT fk_session_unloadmode REFERENCES UnloadMode(ID)
, Remarks				CHAR
, InsertDateTime		CHAR(20) NOT NULL DEFAULT CURRENT_TIMESTAMP
, LastUpdateDateTime	CHAR(20)
);

CREATE TABLE IF NOT EXISTS RunLocation
( ID				INTEGER PRIMARY KEY
, Computername		CHAR NOT NULL
, Username			CHAR NOT NULL
, Path				CHAR NOT NULL
, InsertDateTime	CHAR(25) NOT NULL DEFAULT CURRENT_TIMESTAMP
, UNIQUE (Computername, Username, Path)
);

CREATE TABLE IF NOT EXISTS UnloadMode
( ID				INTEGER PRIMARY KEY
, Code				CHAR
, Description		CHAR
);

CREATE TABLE IF NOT EXISTS Executable
( ID				INTEGER PRIMARY KEY
, RunLocationID		INTEGER CONSTRAINT fk_executable_runlocation REFERENCES RunLocation(ID)
, Name              CHAR
, Path				CHAR NOT NULL
, FileDateTime		CHAR(20)
, LatestVersion		CHAR
, Description		CHAR
, Icon				BINARY
, Company			CHAR
, Remarks			CHAR
, InsertDateTime	CHAR(25) NOT NULL DEFAULT CURRENT_TIMESTAMP
, UpdateDateTime	CHAR(25)
, UNIQUE (RunLocationID, Path)
);

CREATE TABLE IF NOT EXISTS Process
( ID					INTEGER PRIMARY KEY
, SessionID				INTEGER NOT NULL CONSTRAINT fk_process_session REFERENCES Session(ID)
, SysProcessID			INTEGER NOT NULL
, StartupTime			CHAR(20)
, TerminateTime 		CHAR(20)
, ExecutableID			INTEGER NOT NULL CONSTRAINT fk_process_executable REFERENCES Executable(ID)
, UserName				CHAR
, Version				CHAR
, Description			CHAR
, WindowTitle			CHAR
, InsertDateTime		CHAR(20) NOT NULL DEFAULT CURRENT_TIMESTAMP
, LastUpdateDateTime	CHAR(20)
, UNIQUE (SessionID, SysProcessID, StartupTime)
);

CREATE TABLE IF NOT EXISTS Window
( ID					INTEGER PRIMARY KEY
, ProcessID				INTEGER NOT NULL CONSTRAINT fk_window_process REFERENCES Process(ID)
, Handle				INTEGER NOT NULL
, Title					CHAR
, Class					CHAR
, Icon 					BLOB
, InsertDateTime		CHAR(20) NOT NULL DEFAULT CURRENT_TIMESTAMP
, LastUpdateDateTime	CHAR(20)
, UNIQUE (ProcessID, Handle)
);

CREATE TABLE IF NOT EXISTS Focus
( ID					INTEGER PRIMARY KEY
, WindowID				INTEGER NOT NULL CONSTRAINT fk_focus_window REFERENCES Window(ID)
, Title					CHAR
, WindowState			INTEGER
, Top					INTEGER
, Left					INTEGER
, Right					INTEGER
, Bottom				INTEGER
, IdleMilliseconds		CHAR(20) -- GetLastInputInfo
, ScreenshotFile		CHAR
, InsertDateTime		CHAR(20) NOT NULL DEFAULT CURRENT_TIMESTAMP
, UpdateDateTime		CHAR(20)
);

INSERT INTO UnloadMode VALUES (0, 'vbFormControlMenu', 'User has chosen Close command from Control menu box on form.');

INSERT INTO UnloadMode VALUES (1, 'vbFormCode', 'Unload method invoked from code.');

INSERT INTO UnloadMode VALUES (2, 'vbAppWindows', 'Current Windows session ending.');

INSERT INTO UnloadMode VALUES (3, 'vbAppTaskManager', 'Windows Task Manager is closing the application.');

INSERT INTO UnloadMode VALUES (4, 'vbFormMDIForm', 'MDI child form is closing because the MDI form is closing.');

INSERT INTO UnloadMode VALUES (5, 'vbFormOwner', 'The owner of the form is closing.');

INSERT INTO UnloadMode VALUES (100, 'ServiceDestroyed', 'The service was destroyed.');

INSERT INTO UnloadMode VALUES (101, 'ServiceShutdown', 'The service was shutdown.');

INSERT INTO UnloadMode VALUES (102, 'ServiceStopped', 'The service was stopped.');


-- Foreign Key Preventing insert
CREATE TRIGGER fki_Session_RunLocationID_RunLocation_ID
BEFORE INSERT ON [Session]
FOR EACH ROW BEGIN
  SELECT RAISE(ROLLBACK, 'insert on table "Session" violates foreign key constraint "fki_Session_RunLocationID_RunLocation_ID"')
  WHERE (SELECT ID FROM RunLocation WHERE ID = NEW.RunLocationID) IS NULL;
END;

-- Foreign key preventing update
CREATE TRIGGER fku_Session_RunLocationID_RunLocation_ID
BEFORE UPDATE ON [Session]
FOR EACH ROW BEGIN
    SELECT RAISE(ROLLBACK, 'update on table "Session" violates foreign key constraint "fku_Session_RunLocationID_RunLocation_ID"')
      WHERE (SELECT ID FROM RunLocation WHERE ID = NEW.RunLocationID) IS NULL;
END;

-- Foreign key preventing delete
CREATE TRIGGER fkd_Session_RunLocationID_RunLocation_ID
BEFORE DELETE ON RunLocation
FOR EACH ROW BEGIN
  SELECT RAISE(ROLLBACK, 'delete on table "RunLocation" violates foreign key constraint "fkd_Session_RunLocationID_RunLocation_ID"')
  WHERE (SELECT RunLocationID FROM Session WHERE RunLocationID = OLD.ID) IS NOT NULL;
END;

-- Foreign Key Preventing insert
CREATE TRIGGER fki_Session_UnloadModeID_UnloadMode_ID
BEFORE INSERT ON [Session]
FOR EACH ROW BEGIN
  SELECT RAISE(ROLLBACK, 'insert on table "Session" violates foreign key constraint "fki_Session_UnloadModeID_UnloadMode_ID"')
  WHERE NEW.UnloadModeID IS NOT NULL AND (SELECT ID FROM UnloadMode WHERE ID = NEW.UnloadModeID) IS NULL;
END;

-- Foreign key preventing update
CREATE TRIGGER fku_Session_UnloadModeID_UnloadMode_ID
BEFORE UPDATE ON [Session]
FOR EACH ROW BEGIN
    SELECT RAISE(ROLLBACK, 'update on table "Session" violates foreign key constraint "fku_Session_UnloadModeID_UnloadMode_ID"')
      WHERE NEW.UnloadModeID IS NOT NULL AND (SELECT ID FROM UnloadMode WHERE ID = NEW.UnloadModeID) IS NULL;
END;

-- Foreign key preventing delete
CREATE TRIGGER fkd_Session_UnloadModeID_UnloadMode_ID
BEFORE DELETE ON UnloadMode
FOR EACH ROW BEGIN
  SELECT RAISE(ROLLBACK, 'delete on table "UnloadMode" violates foreign key constraint "fkd_Session_UnloadModeID_UnloadMode_ID"')
  WHERE (SELECT UnloadModeID FROM Session WHERE UnloadModeID = OLD.ID) IS NOT NULL;
END;

-- Foreign Key Preventing insert
CREATE TRIGGER fki_Executable_RunLocationID_RunLocation_ID
BEFORE INSERT ON [Executable]
FOR EACH ROW BEGIN
  SELECT RAISE(ROLLBACK, 'insert on table "Executable" violates foreign key constraint "fki_Executable_RunLocationID_RunLocation_ID"')
  WHERE NEW.RunLocationID IS NOT NULL AND (SELECT ID FROM RunLocation WHERE ID = NEW.RunLocationID) IS NULL;
END;

-- Foreign key preventing update
CREATE TRIGGER fku_Executable_RunLocationID_RunLocation_ID
BEFORE UPDATE ON [Executable]
FOR EACH ROW BEGIN
    SELECT RAISE(ROLLBACK, 'update on table "Executable" violates foreign key constraint "fku_Executable_RunLocationID_RunLocation_ID"')
      WHERE NEW.RunLocationID IS NOT NULL AND (SELECT ID FROM RunLocation WHERE ID = NEW.RunLocationID) IS NULL;
END;

-- Foreign key preventing delete
CREATE TRIGGER fkd_Executable_RunLocationID_RunLocation_ID
BEFORE DELETE ON RunLocation
FOR EACH ROW BEGIN
  SELECT RAISE(ROLLBACK, 'delete on table "RunLocation" violates foreign key constraint "fkd_Executable_RunLocationID_RunLocation_ID"')
  WHERE (SELECT RunLocationID FROM Executable WHERE RunLocationID = OLD.ID) IS NOT NULL;
END;

-- Foreign Key Preventing insert
CREATE TRIGGER fki_Process_SessionID_Session_ID
BEFORE INSERT ON [Process]
FOR EACH ROW BEGIN
  SELECT RAISE(ROLLBACK, 'insert on table "Process" violates foreign key constraint "fki_Process_SessionID_Session_ID"')
  WHERE (SELECT ID FROM Session WHERE ID = NEW.SessionID) IS NULL;
END;

-- Foreign key preventing update
CREATE TRIGGER fku_Process_SessionID_Session_ID
BEFORE UPDATE ON [Process]
FOR EACH ROW BEGIN
    SELECT RAISE(ROLLBACK, 'update on table "Process" violates foreign key constraint "fku_Process_SessionID_Session_ID"')
      WHERE (SELECT ID FROM Session WHERE ID = NEW.SessionID) IS NULL;
END;

-- Foreign key preventing delete
CREATE TRIGGER fkd_Process_SessionID_Session_ID
BEFORE DELETE ON Session
FOR EACH ROW BEGIN
  SELECT RAISE(ROLLBACK, 'delete on table "Session" violates foreign key constraint "fkd_Process_SessionID_Session_ID"')
  WHERE (SELECT SessionID FROM Process WHERE SessionID = OLD.ID) IS NOT NULL;
END;

-- Foreign Key Preventing insert
CREATE TRIGGER fki_Process_ExecutableID_Executable_ID
BEFORE INSERT ON [Process]
FOR EACH ROW BEGIN
  SELECT RAISE(ROLLBACK, 'insert on table "Process" violates foreign key constraint "fki_Process_ExecutableID_Executable_ID"')
  WHERE (SELECT ID FROM Executable WHERE ID = NEW.ExecutableID) IS NULL;
END;

-- Foreign key preventing update
CREATE TRIGGER fku_Process_ExecutableID_Executable_ID
BEFORE UPDATE ON [Process]
FOR EACH ROW BEGIN
    SELECT RAISE(ROLLBACK, 'update on table "Process" violates foreign key constraint "fku_Process_ExecutableID_Executable_ID"')
      WHERE (SELECT ID FROM Executable WHERE ID = NEW.ExecutableID) IS NULL;
END;

-- Foreign key preventing delete
CREATE TRIGGER fkd_Process_ExecutableID_Executable_ID
BEFORE DELETE ON Executable
FOR EACH ROW BEGIN
  SELECT RAISE(ROLLBACK, 'delete on table "Executable" violates foreign key constraint "fkd_Process_ExecutableID_Executable_ID"')
  WHERE (SELECT ExecutableID FROM Process WHERE ExecutableID = OLD.ID) IS NOT NULL;
END;

-- Foreign Key Preventing insert
CREATE TRIGGER fki_Window_ProcessID_Process_ID
BEFORE INSERT ON [Window]
FOR EACH ROW BEGIN
  SELECT RAISE(ROLLBACK, 'insert on table "Window" violates foreign key constraint "fki_Window_ProcessID_Process_ID"')
  WHERE (SELECT ID FROM Process WHERE ID = NEW.ProcessID) IS NULL;
END;

-- Foreign key preventing update
CREATE TRIGGER fku_Window_ProcessID_Process_ID
BEFORE UPDATE ON [Window]
FOR EACH ROW BEGIN
    SELECT RAISE(ROLLBACK, 'update on table "Window" violates foreign key constraint "fku_Window_ProcessID_Process_ID"')
      WHERE (SELECT ID FROM Process WHERE ID = NEW.ProcessID) IS NULL;
END;

-- Foreign key preventing delete
CREATE TRIGGER fkd_Window_ProcessID_Process_ID
BEFORE DELETE ON Process
FOR EACH ROW BEGIN
  SELECT RAISE(ROLLBACK, 'delete on table "Process" violates foreign key constraint "fkd_Window_ProcessID_Process_ID"')
  WHERE (SELECT ProcessID FROM Window WHERE ProcessID = OLD.ID) IS NOT NULL;
END;

-- Foreign Key Preventing insert
CREATE TRIGGER fki_Focus_WindowID_Window_ID
BEFORE INSERT ON [Focus]
FOR EACH ROW BEGIN
  SELECT RAISE(ROLLBACK, 'insert on table "Focus" violates foreign key constraint "fki_Focus_WindowID_Window_ID"')
  WHERE (SELECT ID FROM [Window] WHERE ID = NEW.WindowID) IS NULL;
END;

-- Foreign key preventing update
CREATE TRIGGER fku_Focus_WindowID_Window_ID
BEFORE UPDATE ON [Focus]
FOR EACH ROW BEGIN
    SELECT RAISE(ROLLBACK, 'update on table "Focus" violates foreign key constraint "fku_Focus_WindowID_Window_ID"')
      WHERE (SELECT ID FROM Window WHERE ID = NEW.WindowID) IS NULL;
END;

-- Foreign key preventing delete
CREATE TRIGGER fkd_Focus_WindowID_Window_ID
BEFORE DELETE ON Window
FOR EACH ROW BEGIN
  SELECT RAISE(ROLLBACK, 'delete on table "Window" violates foreign key constraint "fkd_Focus_WindowID_Window_ID"')
  WHERE (SELECT WindowID FROM Focus WHERE WindowID = OLD.ID) IS NOT NULL;
END;

Added Snapshooter/res/Snapshooter.mc.

































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
; /* -------------------------------------------------------------------------
; HEADER SECTION
;*/
SeverityNames=(Success=0x0:       STATUS_SEVERITY_SUCCESS
               Informational=0x1: STATUS_SEVERITY_INFORMATIONAL
               Warning=0x2:       STATUS_SEVERITY_WARNING
               Error=0x3:         STATUS_SEVERITY_ERROR
              )

FacilityNames=(System=0x0:  FACILITY_SYSTEM
               Runtime=0x2: FACILITY_RUNTIME
               Stubs=0x3:   FACILITY_STUBS
               Io=0x4:      FACILITY_IO_ERROR_CODE
              )

LanguageNames=(English=0x409:MSG00409)
;LanguageNames=(German=0x407:MSG00407)

;
;/* -------------------------------------------------------------------------
; MESSAGE DEFINITION SECTION
;*/

MessageIdTypedef=WORD

;/*
; The message in the LogMessage call is shown in event log.
;  LogMessage('Your message goes here', EVENTLOG_SUCCESS, 0, 1);
;  LogMessage('Your message goes here', EVENTLOG_INFORMATION_TYPE, 0, 2);
;  LogMessage('Your message goes here', EVENTLOG_WARNING_TYPE, 0, 3);
;  LogMessage('Your message goes here', EVENTLOG_ERROR_TYPE, 0, 4);
; The message in the LogMessage call is not shown in event log.
;  LogMessage('Your message goes here SUCC', EVENTLOG_SUCCESS, 0, 5);
;  LogMessage('Your message goes here INFO', EVENTLOG_INFORMATION_TYPE, 0, 6);
;  LogMessage('Your message goes here WARN', EVENTLOG_WARNING_TYPE, 0, 7);
;  LogMessage('Your message goes here ERRO', EVENTLOG_ERROR_TYPE, 0, 8);
;*/

MessageId=0x1
Severity=Success
Facility=Application
SymbolicName=CATEGORY_SUCCESS
Language=English
%1
.

MessageId=0x2
Severity=Success
Facility=Application
SymbolicName=CATEGORY_INFORMATION
Language=English
%1
.

MessageId=0x3
Severity=Success
Facility=Application
SymbolicName=CATEGORY_WARNING
Language=English
%1
.

MessageId=0x4
Severity=Success
Facility=Application
SymbolicName=CATEGORY_ERROR
Language=English
%1
.

MessageId=0x5
Severity=Success
Facility=Application
SymbolicName=CATEGORY_SUCCESS
Language=English
Here is id5 success message
.

MessageId=0x6
Severity=Success
Facility=Application
SymbolicName=CATEGORY_INFORMATION
Language=English
Here is id6 information message
.

MessageId=0x7
Severity=Success
Facility=Application
SymbolicName=CATEGORY_WARNING
Language=English
Here is id5 warning message
.

MessageId=0x8
Severity=Success
Facility=Application
SymbolicName=CATEGORY_ERROR
Language=English
Here is id5 error message
.

;/*
; For some reason Severity <> Success doesn't work properly ???
;MessageId=0x6
;Severity=Informational
;Facility=Application
;SymbolicName=CATEGORY_INFORMATION
;Language=English
;Here is id6 information message
;.
;
;MessageId=0x7
;Severity=Warning
;Facility=Application
;SymbolicName=CATEGORY_WARNING
;Language=English
;Here is id5 warning message
;.
;
;MessageId=0x8
;Severity=Error
;Facility=Application
;SymbolicName=CATEGORY_ERROR
;Language=English
;Here is id5 error message
;.
;*/

Added Snapshooter/res/camera.ico.

cannot compute difference between binary files

Added Snapshooter/src/ImageJanitor.pas.

































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
unit ImageJanitor;

interface
uses
  SvcMgr, Classes, IniFiles,
  SQLiteTable3, RegExpr;

type
  TImageJanitor = class(TThread)
  private
    type
      TScreenshotHandler = function(FocusID: Int64; Filename: string; JanitorID: Int64 = 0): boolean of object;
    var
      FService: TService;
      FDB: TSQLiteDatabase;
      FBasePath: string;
      FConfig: TIniFile;
      FRexDateTerm: TRegExpr;
      FRexSpaceTest: TRegExpr;

    function  ProcessScreenshotsByAge(ConfigName, DefaultValue, SqlCondition: string; ProcessScreenshot: TScreenshotHandler): integer;
    function  ProcessScreenshotsBySpace(ConfigName, DefaultValue, SqlCondition: string; ProcessScreenshot: TScreenshotHandler): integer;

    function  DeleteScreenshot(FocusID: Int64; Filename: string; JanitorID: Int64 = 0): boolean;
    function  DownsizeScreenshot(FocusID: Int64; Filename: string; JanitorID: Int64 = 0): boolean;
    function  ConvertScreenshot(FocusID: Int64; Filename: string; JanitorID: Int64 = 0): boolean;
  public
    constructor Create(Service: TService; DBFile: string); reintroduce;
    destructor  Destroy(); override;

    procedure Execute; override;
    procedure OldExecute;

    property Terminated;
  end;

implementation

uses
  SysUtils, Windows, Graphics, JPEG, Types, PNGImage;

{ ================================================================================================ }
{ TImageJanitor }

{ ------------------------------------------------------------------------------------------------ }
constructor TImageJanitor.Create(Service: TService; DBFile: string);
begin
  inherited Create(True);

  FService := Service;
  FBasePath := IncludeTrailingPathDelimiter(ExtractFilePath(DBFile));
  FConfig := TIniFile.Create(FBasePath + 'config.ini');
  FDB := TSQLiteDatabase.Create(DBFile);
  FDB.SetTimeout(60000);

  if not FDB.TableExists('Janitor') then begin
    // Create the janitor table if it doesn't exist
    FDB.ExecSQL('CREATE TABLE Janitor'#13#10
              + '( id             INTEGER PRIMARY KEY'#13#10
              + ', FocusID        INTEGER NOT NULL UNIQUE CONSTRAINT fk_Janitor_Focus REFERENCES Focus(id)'#13#10
              + ', Converted      INTEGER -- NULL = not yet necessary; 1 = yes; 0 = no, wasn''t advantageous'#13#10
              + ', Downsized      INTEGER -- NULL = not yet necessary; 1 = yes; 0 = no, an error occurred (see Remarks)'#13#10
              + ', Deleted        INTEGER -- NULL = not yet necessary; 1 = yes; 0 = no, unable to (see Remarks)'#13#10
              + ', Remarks        TEXT -- error messages and such'#13#10
              + ');');
    // Mark all screenshots that have been converted, as such
    FDB.ExecSQL('INSERT INTO Janitor'
              + '(FocusID, Converted)'
              + 'SELECT id, 1'
              + '  FROM Focus'
              + ' WHERE ScreenShotFile LIKE ''%.jpg'';');
  end;
end;
{ ------------------------------------------------------------------------------------------------ }
destructor TImageJanitor.Destroy;
begin
  if Assigned(FRexDateTerm)   then FreeAndNil(FRexDateTerm);
  if Assigned(FRexSpaceTest)  then FreeAndNil(FRexSpaceTest);
  if Assigned(FDB)            then FreeAndNil(FDB);
  if Assigned(FConfig)        then FreeAndNil(FConfig);

  inherited;
end;

{ ------------------------------------------------------------------------------------------------ }
// returns file size in bytes or -1 if not found.
function FileSize(fileName: string): Int64;
var
  sr : TSearchRec;
begin
  if FindFirst(fileName, faAnyFile, sr) = 0 then begin
    Result := Int64(sr.FindData.nFileSizeHigh) shl Int64(32) + Int64(sr.FindData.nFileSizeLow)
  end else begin
    Result := -1;
  end;
  SysUtils.FindClose(sr) ;
end;

{ ------------------------------------------------------------------------------------------------ }
procedure TImageJanitor.OldExecute;
var
  IDs: TStringList;
  Rows: TSQLiteTable;
  FocusID: Int64;
  Filename: string;
  Bitmap: TBitmap;
  JPG: TJPEGImage;
  SizeTest: TStream;
  Picture: TPicture;
begin
  // Delete all screenshots older than 1 year
  Rows := FDB.GetTable('   SELECT f.id'
                     + '   ,      f.ScreenshotFile'
                     + '     FROM Focus f'
                     + '          LEFT JOIN Janitor j'
                     + '                 ON f.ID = j.FocusID'
                     + '    WHERE f.ScreenshotFile IS NOT NULL'
                     + '      AND date(f.InsertDateTime) < date("now", "localtime", "-1 year")'
                     + '      AND ifnull(j.Deleted, 0) = 0'
                     + ' ORDER BY f.id ASC');
  try
    IDs := TStringList.Create;
    try
      // Try to delete each file, and keep track of the IDs of the ones that succeeded
      while not (Rows.EOF or Self.Terminated) do begin
        FocusID := Rows.FieldAsInteger(0);
        Filename := Rows.FieldAsString(1);
        if FileExists(FBasePath + Filename) then begin
          FileSetAttr(FBasePath + Filename, FileGetAttr(FBasePath + Filename) and not (faReadOnly or faSysFile));
          if SysUtils.DeleteFile(FBasePath + Filename) then begin
            IDs.Add(IntToStr(FocusID));
          end;
        end;
        Rows.Next;
      end;
      // Update the database with the files that were successfully deleted
      if IDs.Count > 0 then begin
        FDB.BeginTransaction;
        try
          FDB.ExecSQL(Format('UPDATE Focus'
                           + '   SET UpdateDateTime = :DateTime'
                           + ' WHERE id IN (%s)', [IDs.DelimitedText]));
          FDB.ExecSQL(Format('UPDATE Janitor'
                           + '   SET Deleted = 1'
                           + ' WHERE FocusID IN (%s)', [IDs.DelimitedText]));
          FDB.ExecSQL(Format('INSERT INTO Janitor (FocusID, Deleted)'
                           + '  SELECT id, 1'
                           + '    FROM Focus'
                           + '   WHERE id IN (%s)'
                           + '     AND id NOT IN (SELECT FocusID FROM Janitor)', [IDs.DelimitedText]));
          FDB.Commit;
        except
          FDB.Rollback;
          raise;
        end;
      end;
    finally
      IDs.Free;
    end;
  finally
    Rows.Free;
  end;
  if Self.Terminated then begin
    Exit;
  end;


  // Convert all screenshots older than 1 month to JPG (if that makes them smaller)
  Rows := FDB.GetTable('   SELECT f.id'
                     + '   ,      f.ScreenshotFile'
                     + '     FROM Focus f'
                     + '          LEFT JOIN Janitor j'
                     + '                 ON f.ID = j.FocusID'
                     + '    WHERE f.ScreenshotFile IS NOT NULL' // it's a screenshot
                     + '      AND date(f.InsertDateTime) < date("now", "localtime", "-1 month")' // more than a month old
                     + '      AND j.Converted IS NULL' // that hasn't been converted yet
                     + '      AND ifnull(j.Deleted, 0) = 0' // and that hasn't been deleted yet
                     + ' ORDER BY f.id ASC');
  try
    while not (Rows.EOF or Self.Terminated) do begin
      FocusID := Rows.FieldAsInteger(0);
      Filename := Rows.FieldAsString(1);
      try
        if FileExists(FBasePath + Filename) then begin
          JPG := TJPEGImage.Create;
          try
            // Load the picture, assign it to a bitmap, then to the JPG (can't assign a PNG to a JPG)
            Picture := TPicture.Create;
            try
              Picture.LoadFromFile(FBasePath + Filename);
              Bitmap := TBitmap.Create;
              try
                Bitmap.Assign(Picture.Graphic);
                JPG.Assign(Bitmap);
              finally
                Bitmap.Free;
              end;
            finally
              Picture.Free;
            end;
            // Now, see if the image is smaller in JPG
            SizeTest := TMemoryStream.Create;
            try
              JPG.SaveToStream(SizeTest);
              if SizeTest.Size < FileSize(FBasePath + Filename) then begin
                // The JPG is smaller than the existing file; so delete the file, save the new JPG, and update the database
                FileSetAttr(FBasePath + Filename, FileGetAttr(FBasePath + Filename) and not (faReadOnly or faSysFile));
                if SysUtils.DeleteFile(FBasePath + Filename) then begin
                  JPG.SaveToFile(ChangeFileExt(FBasePath + Filename, '.jpg'));
                  FDB.BeginTransaction;
                  try
                    FDB.AddParamText(':NewFilename', ChangeFileExt(Filename, '.jpg'));
                    FDB.AddParamDateTime(':DateTime', Now);
                    FDB.AddParamInt(':ID', FocusID);
                    FDB.ExecSQL('UPDATE Focus'
                              + '   SET ScreenshotFile = :NewFilename'
                              + '   ,   UpdateDateTime = :DateTime'
                              + ' WHERE id = :ID');
                    FDB.AddParamInt(':ID', FocusID);
                    FDB.ExecSQL('UPDATE Janitor'
                              + '   SET Converted = 1'
                              + ' WHERE FocusID = :ID');
                    if FDB.GetLastChangedRows = 0 then begin
                      FDB.AddParamInt(':ID', FocusID);
                      FDB.ExecSQL('INSERT INTO Janitor (FocusID, Converted) VALUES (:ID, 1)');
                    end;
                    FDB.Commit;
                  except
                    FDB.Rollback;
                    raise;
                  end;
                end;
              end else begin
                // A JPG would be larger than the current bitmap; so just record that we've already tried converting this one
                FDB.AddParamInt(':ID', FocusID);
                FDB.ExecSQL('UPDATE Janitor'
                          + '   SET Converted = 0'
                          + ' WHERE FocusID = :ID');
                if FDB.GetLastChangedRows = 0 then begin
                  FDB.AddParamInt(':ID', FocusID);
                  FDB.ExecSQL('INSERT INTO Janitor (FocusID, Converted) VALUES (:ID, 0)');
                end;
              end;
            finally
              SizeTest.Free;
            end;
          finally
            JPG.Free;
          end;
        end;
      except
        on E: Exception do begin
          // TODO: write to event log!
          Assert(False, E.Message);
        end;
      end;
      // Give the machine a breather
      if not Self.Terminated then Sleep(2500);
      Rows.Next;
    end;
  finally
    Rows.Free;
  end;
  if Self.Terminated then begin
    Exit;
  end;


  // Reduce all screen shots older than 3 months to half their dimensions
  Rows := FDB.GetTable('   SELECT f.id'
                     + '   ,      f.ScreenshotFile'
                     + '     FROM Focus f'
                     + '          LEFT JOIN Janitor j'
                     + '                 ON f.ID = j.FocusID'
                     + '    WHERE f.ScreenshotFile IS NOT NULL' // it's a screen shot
                     + '      AND date(f.InsertDateTime) < date("now", "localtime", "-3 month")' // at least 3 months old
                     + '      AND ifnull(j.Downsized, 0) = 0' // that hasn't been downsized yet
                     + '      AND ifnull(j.Deleted, 0) = 0' // and that hasn't been deleted yet
                     + ' ORDER BY f.id ASC');
  try
    while not (Rows.EOF or Self.Terminated) do begin
      FocusID := Rows.FieldAsInteger(0);
      Filename := Rows.FieldAsString(1);
      try
        if FileExists(Filename) then begin
          Picture := TPicture.Create;
          try
            Picture.LoadFromFile(FBasePath + Filename);
            if (Picture.Width >= 1280) and (Picture.Height >= 1024) then begin
              Picture.Bitmap.Canvas.StretchDraw(Rect(0, 0, Picture.Width, Picture.Height), Picture.Graphic);
              Picture.Graphic.SetSize(Picture.Width div 2, Picture.Height div 2);
              Picture.SaveToFile('_(new)_' + FBasePath + Filename);
              // Update the database to show that we've already resized this one
              FDB.AddParamInt(':ID', FocusID);
              FDB.ExecSQL('UPDATE Janitor'
                        + '   SET Downsized = 1'
                        + ' WHERE FocusID = :ID');
              if FDB.GetLastChangedRows = 0 then begin
                FDB.AddParamInt(':ID', FocusID);
                FDB.ExecSQL('INSERT INTO Janitor (FocusID, Downsized) VALUES (:ID, 1)');
              end;
            end;
          finally
            Picture.Free;
          end;
        end;
      except
        on E: Exception do begin
          // TODO: write to event log!
          Assert(False, E.Message);
        end;
      end;
      // Give the machine a breather
      if not Self.Terminated then Sleep(2500);
      Rows.Next;
    end;
  finally
    Rows.Free;
  end;

  FreeAndNil(FDB);
end{OldExecute};

{ ------------------------------------------------------------------------------------------------ }
procedure TImageJanitor.Execute;
begin
  inherited;

  // Check time-based actions
  ProcessScreenshotsByAge('DeleteAfter', '', '', DeleteScreenshot);
  ProcessScreenshotsByAge('ResizeAfter', '3 months', 'coalesce(j.Downsized, 0) = 0', DownsizeScreenshot);
  ProcessScreenshotsByAge('ConvertAfter', '1.5 weeks', 'j.Converted IS NULL', ConvertScreenshot);

  // Then, check the disk space-based actions
  ProcessScreenshotsBySpace('ConvertWhen', 'available < 10%', 'j.Converted IS NULL', ConvertScreenshot);
  ProcessScreenshotsBySpace('ResizeWhen', 'available < 5%', 'coalesce(j.Downsized, 0) = 0', DownsizeScreenshot);
  ProcessScreenshotsBySpace('DeleteWhen', 'available < 100MB', '', DeleteScreenshot);
end;

{ ------------------------------------------------------------------------------------------------ }
function TImageJanitor.ProcessScreenshotsByAge(ConfigName, DefaultValue, SqlCondition: string;
                                               ProcessScreenshot: TScreenshotHandler): integer;
var
  Limit: string;
  Rows: TSQLiteTable;
begin
  Result := 0;
  try

    if not Assigned(FRexDateTerm) then begin
      FRexDateTerm := TRegExpr.Create;
      FRexDateTerm.ModifierI := True; // Case-insensitive
      FRexDateTerm.Expression := '^((\d+)\s*(day|week|month|year)s?)(;\s*(.*))?$';
    end;

    Limit := FConfig.ReadString('Janitor', ConfigName, DefaultValue);
    if FRexDateTerm.Exec(Limit) then begin
      FDB.AddParamText(':Modifiers', '-' + FRexDateTerm.Match[1]);
      if Length(SqlCondition) > 0 then begin
        SqlCondition := ' AND ' + SqlCondition;
      end;
      Rows := FDB.GetTable('   SELECT f.id AS focus_id'
                          +'   ,      f.screenshotfile'
                          +'   ,      j.id AS janitor_id'
                          +'     FROM Focus f'
                          +'          LEFT JOIN Janitor j'
                          +'                 ON f.id = j.focus_id'
                          +'    WHERE f.screenshotfile IS NOT NULL'
                          +'      AND f.InsertDateTime < date(''now'', ''localtime'', :Modifiers)'
                          +'      AND coalesce(j.Deleted, 0) = 0'
                          + SqlCondition
                          +' ORDER BY f.InsertDateTime ASC');
      try
        while not Rows.EOF do begin
          if ProcessScreenshot(Rows.FieldAsInteger('focus_id'),
                               Rows.FieldAsString('screenshotfile'),
                               Rows.FieldAsInteger('janitor_id', 0)) then begin
            // TODO: keep track of successful IDs, and update them all at once later on
            Inc(Result);
          end;
          Rows.Next
        end;
      finally
        Rows.Free;
      end;
    end else if Length(Limit) > 0 then begin
      FService.LogMessage(Format('Expression not valid (%s, Janitor, %s="%s").',
                                [FConfig.Filename, ConfigName, Limit]),
                          EVENTLOG_WARNING_TYPE, 0, 1);
    end;
  except
    on E: Exception do begin
      FService.LogMessage(Format('%s while processing screen shot (%s, Janitor, %s="%s"): %s',
                                [E.ClassName, FConfig.Filename, ConfigName, Limit, E.Message]),
                          EVENTLOG_WARNING_TYPE, 0, 1);
      raise;
    end;
  end;
end{ProcessScreenshotsByAge};

{ ------------------------------------------------------------------------------------------------ }
function TImageJanitor.ProcessScreenshotsBySpace(ConfigName, DefaultValue, SqlCondition: string;
                                                 ProcessScreenshot: TScreenshotHandler): integer;
var
  Condition, Identifier, Operator, LimitUnit: string;
  LimitValue, Multiplier: TLargeInteger;
  Rows: TSQLiteTable;
  { -------------------------------------------------------------------------------------------- }
  function NeedFreeSpace: boolean;
  var
    Value, FreeAvailable, TotalAvailable, FreeTotal: TLargeInteger;
    PFT: PLargeInteger;
  begin
    FreeAvailable := 0;
    TotalAvailable := 0;
    FreeTotal := 0;
    if Identifier = 'free' then
      PFT := @FreeTotal
    else
      PFT := nil;
    if not GetDiskFreeSpaceEx(PChar(FBasePath), FreeAvailable, TotalAvailable, PFT) then begin
      Result := False;
      FService.LogMessage(Format('Unable to determine free disk space (%s, Janitor, %s): %s',
                                [FConfig.Filename, ConfigName, SysErrorMessage(GetLastError)]),
                          EVENTLOG_WARNING_TYPE, 0, 1);
      Exit;
    end;
    if Identifier = 'used' then begin
      // TODO: add the filesize field to the database, populate on insert and update it after resizing and converting the file
      Value := FDB.GetTableValue('SELECT SUM(f.filesize) FROM Focus f LEFT JOIN Janitor j ON f.id = j.FocusID WHERE f.screenshotfile IS NOT NULL AND coalesce(j.Deleted, 0) = 0');
    end else if Identifier = 'available' then begin
      Value := FreeAvailable;
    end else if Identifier = 'free' then begin
      Value := FreeTotal;
    end else begin
      Result := False;
      FService.LogMessage(Format('Identifier "%s" not recognized (%s, Janitor, %s="%s").',
                                [Identifier, FConfig.Filename, ConfigName, Condition]),
                          EVENTLOG_WARNING_TYPE, 0, 1);
      Exit;
    end;
    if LimitUnit = '%' then begin
      Value := Value div TotalAvailable;
    end;
    if Operator = '<' then
      Result := Value < LimitValue
    else if Operator = '>' then
      Result := Value > LimitValue
    else if (Operator = '=') or (Operator = '==') then
      Result := Value = LimitValue
    else if (Operator = '<=') or (Operator = '=<') then
      Result := Value <= LimitValue
    else if (Operator = '>=') or (Operator = '=>') then
      Result := Value >= LimitValue
    else begin
      Result := False;
      FService.LogMessage(Format('Operator "%s" not valid (%s, Janitor, %s="%s").',
                                [Operator, FConfig.Filename, ConfigName, Condition]),
                          EVENTLOG_WARNING_TYPE, 0, 1);
      Exit;
    end;
  end{NeedFreeSpace};
  { -------------------------------------------------------------------------------------------- }
begin
  Result := 0;
  try

    if not Assigned(FRexSpaceTest) then begin
      FRexSpaceTest := TRegExpr.Create;
      FRexSpaceTest.ModifierI := True; // Case-insensitive
      FRexSpaceTest.Expression := '^(used|available|free)(\s*space)?\s*([<>=]{1,2})\s*(\d+)\s*(%|[KMGTPE]b?)?';
    end;

    Condition := FConfig.ReadString('Janitor', ConfigName, DefaultValue);
    if FRexSpaceTest.Exec(Condition) then begin
      // parse the condition into its components
      Identifier := LowerCase(FRexSpaceTest.Match[1]);
      Operator   := FRexSpaceTest.Match[3];
      LimitValue := StrToInt(FRexSpaceTest.Match[4]);
      LimitUnit  := FRexSpaceTest.Match[5];
      if Length(LimitUnit) > 0 then begin
        case LowerCase(LimitUnit)[1] of
          'k': Multiplier := 1000;
          'm': Multiplier := 1000000;
          'g': Multiplier := 1000000000;
          't': Multiplier := 1000000000000;
          'p': Multiplier := 1000000000000000;
          'e': Multiplier := 1000000000000000000;
          else Multiplier := 1;
        end;
        if Multiplier > 1 then begin
          LimitValue := LimitValue * Multiplier;
        end;
      end;

      if NeedFreeSpace() then begin
        // Get the full list of screenshot files that could be processed
        if Length(SqlCondition) > 0 then begin
          SqlCondition := ' AND ' + SqlCondition;
        end;
        Rows := FDB.GetTable('   SELECT f.id AS focus_id'
                            +'   ,      f.screenshotfile'
                            +'   ,      j.id AS janitor_id'
                            +'     FROM Focus f'
                            +'          LEFT JOIN Janitor j'
                            +'                 ON f.id = j.focus_id'
                            +'    WHERE f.screenshotfile IS NOT NULL'
                            +'      AND coalesce(j.Deleted, 0) = 0'
                            + SqlCondition
                            +' ORDER BY f.InsertDateTime ASC');
        try
          while not Rows.EOF do begin
            if ProcessScreenshot(Rows.FieldAsInteger('focus_id'), Rows.FieldAsString('screenshotfile'), Rows.FieldAsInteger('janitor_id', 0)) then begin
              Inc(Result);
            end;
            if not NeedFreeSpace() then Break;
            Rows.Next
          end;
        finally
          Rows.Free;
        end;
      end{if};
    end else if Length(Condition) > 0 then begin
      FService.LogMessage(Format('Expression not valid (%s, Janitor, %s="%s").',
                                [FConfig.Filename, ConfigName, Condition]),
                          EVENTLOG_WARNING_TYPE, 0, 1);
    end;
  except
    on E: Exception do begin
      FService.LogMessage(Format('%s while processing screen shot (%s, Janitor, %s="%s"): %s',
                                [E.ClassName, FConfig.Filename, ConfigName, Condition, E.Message]),
                          EVENTLOG_WARNING_TYPE, 0, 1);
      raise;
    end;
  end;
end{ProcessScreenshotsBySpace};

{ ------------------------------------------------------------------------------------------------ }
function TImageJanitor.DeleteScreenshot(FocusID: Int64; Filename: string; JanitorID: Int64 = 0): boolean;
var
  Msg: string;
begin
  Result := False;
  Msg := '';
  try
    // Try deleting the file
    Result := not FileExists(FBasePath + Filename);
    if Result = False then begin
      FileSetAttr(FBasePath + Filename, FileGetAttr(FBasePath + Filename) and not (faReadOnly or faSysFile));
      Result := DeleteFile(PChar(FBasePath + Filename));
      if not Result then begin
        Msg := Format('Unable to delete file "%s" (%d): ', [Filename, FocusID]) + SysErrorMessage(GetLastError);
      end;
    end;
  except
    on E: Exception do begin
      Msg := E.Message;
    end;
  end;

  // Record that the screenshot file has been deleted
  FDB.AddParamInt(':Value', integer(Result));
  FDB.AddParamText(':Msg', FormatDateTime('yyyy-MM-dd hh:nn:ss', Now) + ' ' + Msg, '');
  if JanitorID = 0 then begin
    FDB.AddParamInt(':FocusID', FocusID);
    FDB.ExecSQL('INSERT INTO janitor (focus_id, deleted) VALUES (:FocusID, :Value)');
  end else begin
    FDB.AddParamInt(':JanitorID', JanitorID);
    FDB.ExecSQL('UPDATE Janitor SET deleted = :Value, remarks = coalesce(remarks || '''#13#10''' || :Msg, :Msg, remarks) WHERE janitor_id = :JanitorID');
  end;
end;

{ ------------------------------------------------------------------------------------------------ }
function TImageJanitor.DownsizeScreenshot(FocusID: Int64; Filename: string; JanitorID: Int64 = 0): boolean;
var
  Msg: string;
begin
  Result := False;
  Msg := '';
  try
    Result := False; // TODO: actually resize the screenshot
    if not Result then begin
      Msg := Format('Unable to resize file "%s" (%d): ', [Filename, FocusID]) + SysErrorMessage(GetLastError);
    end;
  except
    on E: Exception do begin
      Msg := E.Message;
    end;
  end;

  // Record that the screenshot file has been resized
  FDB.AddParamInt(':Value', integer(Result));
  FDB.AddParamText(':Msg', FormatDateTime('yyyy-MM-dd hh:nn:ss', Now) + ' ' + Msg, '');
  if JanitorID = 0 then begin
    FDB.AddParamInt(':FocusID', FocusID);
    FDB.ExecSQL('INSERT INTO janitor (focus_id, downsized) VALUES (:FocusID, :Value)');
  end else begin
    FDB.AddParamInt(':JanitorID', JanitorID);
    FDB.ExecSQL('UPDATE Janitor SET downsized = :Value, remarks = coalesce(remarks || '''#13#10''' || :Msg, :Msg, remarks) WHERE janitor_id = :JanitorID');
  end;

  // TODO: Update the screenshot's filesize

end;

{ ------------------------------------------------------------------------------------------------ }
function TImageJanitor.ConvertScreenshot(FocusID: Int64; Filename: string; JanitorID: Int64 = 0): boolean;
var
  Msg: string;
begin
  Result := False;
  Msg := '';
  try
    Result := False; // TODO: actually convert the screenshot
    if not Result then begin
      Msg := Format('Unable to convert file "%s" (%d): ', [Filename, FocusID]) + SysErrorMessage(GetLastError);
    end;
  except
    on E: Exception do begin
      Msg := E.Message;
    end;
  end;
  
  // Record that the screenshot file has been converted
  FDB.AddParamInt(':Value', integer(Result));
  FDB.AddParamText(':Msg', FormatDateTime('yyyy-MM-dd hh:nn:ss', Now) + ' ' + Msg, '');
  if JanitorID = 0 then begin
    FDB.AddParamInt(':FocusID', FocusID);
    FDB.ExecSQL('INSERT INTO janitor (focus_id, converted) VALUES (:FocusID, :Value)');
  end else begin
    FDB.AddParamInt(':JanitorID', JanitorID);
    FDB.ExecSQL('UPDATE Janitor SET converted = :Value, remarks = coalesce(remarks || '''#13#10''' || :Msg, :Msg, remarks) WHERE janitor_id = :JanitorID');
  end;
  
  // TODO: update both filename and filesize
  
end;

end.

Added Snapshooter/src/MainService.dfm.













































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
object svcSnapshooter: TsvcSnapshooter
  OldCreateOrder = False
  OnCreate = ServiceCreate
  OnDestroy = ServiceDestroy
  DisplayName = 'Snapshooter'
  Interactive = True
  AfterInstall = ServiceAfterInstall
  OnContinue = ServiceContinue
  OnExecute = ServiceExecute
  OnPause = ServicePause
  OnShutdown = ServiceShutdown
  OnStop = ServiceStop
  Height = 150
  Width = 215
  object tmrScreenshot: TTimer
    Enabled = False
    Interval = 60000
    OnTimer = tmrScreenshotTimer
    Left = 32
    Top = 16
  end
end

Added Snapshooter/src/MainService.pas.















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
unit MainService;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs, ExtCtrls,
  L_VersionInfoW, SQLiteTable3, ImageJanitor;

const
  cAppName: string = 'Snapshooter';
  
  SERVICE_CONTROL_STOP                  = $00000001;
  {$EXTERNALSYM SERVICE_CONTROL_STOP}
  SERVICE_CONTROL_PAUSE                 = $00000002;
  {$EXTERNALSYM SERVICE_CONTROL_PAUSE}
  SERVICE_CONTROL_CONTINUE              = $00000003;
  {$EXTERNALSYM SERVICE_CONTROL_CONTINUE}
  SERVICE_CONTROL_INTERROGATE           = $00000004;
  {$EXTERNALSYM SERVICE_CONTROL_INTERROGATE}
  SERVICE_CONTROL_SHUTDOWN              = $00000005;
  {$EXTERNALSYM SERVICE_CONTROL_SHUTDOWN}
  SERVICE_CONTROL_PARAMCHANGE           = $00000006;
  {$EXTERNALSYM SERVICE_CONTROL_PARAMCHANGE}
  SERVICE_CONTROL_NETBINDADD            = $00000007;
  {$EXTERNALSYM SERVICE_CONTROL_NETBINDADD}
  SERVICE_CONTROL_NETBINDREMOVE         = $00000008;
  {$EXTERNALSYM SERVICE_CONTROL_NETBINDREMOVE}
  SERVICE_CONTROL_NETBINDENABLE         = $00000009;
  {$EXTERNALSYM SERVICE_CONTROL_NETBINDENABLE}
  SERVICE_CONTROL_NETBINDDISABLE        = $0000000A;
  {$EXTERNALSYM SERVICE_CONTROL_NETBINDDISABLE}
  SERVICE_CONTROL_DEVICEEVENT           = $0000000B;
  {$EXTERNALSYM SERVICE_CONTROL_DEVICEEVENT}
  SERVICE_CONTROL_HARDWAREPROFILECHANGE = $0000000C;
  {$EXTERNALSYM SERVICE_CONTROL_HARDWAREPROFILECHANGE}
  SERVICE_CONTROL_POWEREVENT            = $0000000D;
  {$EXTERNALSYM SERVICE_CONTROL_POWEREVENT}
  SERVICE_CONTROL_SESSIONCHANGE         = $0000000E;
  {$EXTERNALSYM SERVICE_CONTROL_SESSIONCHANGE}


type
  LPVOID = Pointer;

  TsvcSnapshooter = class(TService)
    tmrScreenshot: TTimer;
    procedure ServiceStop(Sender: TService; var Stopped: Boolean);
    procedure ServiceShutdown(Sender: TService);
    procedure ServiceAfterInstall(Sender: TService);
    procedure ServiceCreate(Sender: TObject);
    procedure ServiceDestroy(Sender: TObject);
    procedure ServiceExecute(Sender: TService);
    procedure ServicePause(Sender: TService; var Paused: Boolean);
    procedure ServiceContinue(Sender: TService; var Continued: Boolean);
    procedure tmrScreenshotTimer(Sender: TObject);
  private
  type
    SERVICE_STATUS_HANDLE = THandle;

    LPHANDLER_FUNCTION_EX = function (dwControl, dwEventType: DWORD;
      lpEventData, lpContext: LPVOID): DWORD; stdcall;
    {$EXTERNALSYM LPHANDLER_FUNCTION_EX}
    THandlerFunctionEx = LPHANDLER_FUNCTION_EX;
  var
    { Private declarations }
    FVersionInfo: TFileVersionInfo;
    FBasePath: string;
    FDB: TSQLiteDatabase;
    FJanitor: TImageJanitor;

    FRunLocationID: Int64;
    FSessionID: Int64;

    FExecutableIDs: TList;
    FProcessIDs: TStringList;
    FWindowIDs: TStringList;

    function RegisterServiceCtrlHandlerExA(lpServiceName: LPCSTR;
      lpHandlerProc: LPHANDLER_FUNCTION_EX; lpContext: LPVOID): SERVICE_STATUS_HANDLE; stdcall;
    {$EXTERNALSYM RegisterServiceCtrlHandlerExA}
    function RegisterServiceCtrlHandlerExW(lpServiceName: LPCWSTR;
      lpHandlerProc: LPHANDLER_FUNCTION_EX; lpContext: LPVOID): SERVICE_STATUS_HANDLE; stdcall;
    {$EXTERNALSYM RegisterServiceCtrlHandlerExW}

    {$IFDEF UNICODE}
    function RegisterServiceCtrlHandlerEx(lpServiceName: LPCWSTR;
      lpHandlerProc: LPHANDLER_FUNCTION_EX; lpContext: LPVOID): SERVICE_STATUS_HANDLE; stdcall;
    {$EXTERNALSYM RegisterServiceCtrlHandlerEx}
    {$ELSE}
    function RegisterServiceCtrlHandlerEx(lpServiceName: LPCSTR;
      lpHandlerProc: LPHANDLER_FUNCTION_EX; lpContext: LPVOID): SERVICE_STATUS_HANDLE; stdcall;
    {$EXTERNALSYM RegisterServiceCtrlHandlerEx}
    {$ENDIF}

    function  ControllerEx(dwControl, dwEventType: DWORD; lpEventData, lpContext: LPVOID): DWORD;

    function  DescribeWindow(WindowHandle: HWND; IsFocused: boolean = false; Filename: WideString = ''): boolean;
    function  DoRecordExecutable(FullPath: WideString; out FileVersion, FileDescription: WideString): int64;
    function  DoRecordProcess(SysProcessID: integer; ExecutableID: int64; FileVersion, FileDescription, WindowTitle: WideString): int64;
    function  DoRecordWindow(ProcessID: int64; WindowHandle: hWnd; WindowTitle: WideString; WindowClass: string): int64;
    function  DoRecordFocus(WindowID: int64; WindowHandle: hWnd; WindowTitle: WideString; ScreenshotFile: Widestring = ''): int64;
    procedure DoCloseSession(UnloadModeID: int64);
    function  SafeFilename(Filename: widestring): widestring;
    function  SaveScreenshot(BMPImage: TBitmap; ActiveWindow: HWND; ShotTime: TDateTime): widestring;
    procedure UpdateExistingProcessesAndWindows;
  protected
    { Protected declarations }
  public
    function GetServiceController: TServiceController; override;
    { Public declarations }

    class function  IconStreamFromHandle(IconHandle: THandle): TStream;
    class function  NormalizePathName(Path: WideString): WideString;
  end;

var
  svcSnapshooter: TsvcSnapshooter;

implementation

uses
  WideStrings, Registry, PsAPI, ShellAPI, DateUtils,
  PNGImage,
  L_ShellFolders, L_WindowInfo, L_UserInfo, L_Capture, L_DateTime, L_ProcessInfo, L_GetLongPath,
  U_SQL;

{$R *.DFM}
{$R SQL.res}

function RegisterServiceCtrlHandlerExA; external advapi32 name 'RegisterServiceCtrlHandlerExA';
function RegisterServiceCtrlHandlerExW; external advapi32 name 'RegisterServiceCtrlHandlerExW';

{$IFDEF UNICODE}
function RegisterServiceCtrlHandlerEx; external advapi32 name 'RegisterServiceCtrlHandlerExW';
{$ELSE}
function RegisterServiceCtrlHandlerEx; external advapi32 name 'RegisterServiceCtrlHandlerExA';
{$ENDIF}


var
  EnumeratedWindows: array of cardinal;

{ ================================================================================================ }

function EnumWindowProc(hWnd: THandle; lParam: Integer): Boolean; winapi;
begin
  if IsWindow(hWnd) then begin
    SetLength(EnumeratedWindows, Length(EnumeratedWindows) + 1);
    EnumeratedWindows[High(EnumeratedWindows)] := hWnd;
    Result := True;
  end else begin
    Result := False;
  end;
end;

{ ================================================================================================ }

function HandlerEx(dwControl, dwEventType: DWORD; lpEventData, lpContext: LPVOID): DWORD; stdcall;
begin
  Result := svcSnapshooter.ControllerEx(dwControl, dwEventType, lpEventData, lpContext);
end;

{ ------------------------------------------------------------------------------------------------ }
procedure ServiceController(CtrlCode: DWord); stdcall;
begin
  svcSnapshooter.Controller(CtrlCode);
end;
{ ------------------------------------------------------------------------------------------------ }
function TsvcSnapshooter.GetServiceController: TServiceController;
begin
  Result := ServiceController;
end;

{ ------------------------------------------------------------------------------------------------ }

procedure TsvcSnapshooter.ServiceAfterInstall(Sender: TService);
var
  Reg: TRegistry;
begin
  Reg := TRegistry.Create(KEY_READ or KEY_WRITE);
  try
    Reg.RootKey := HKEY_LOCAL_MACHINE;
    if Reg.OpenKey('\SYSTEM\CurrentControlSet\Services\' + Name, False) then begin
      Reg.WriteString('Description', 'Automatically takes screen shots of the desktop while in use.');
      Reg.CloseKey;
    end;
  finally
    Reg.Free;
  end;
end;

{ ------------------------------------------------------------------------------------------------ }

procedure TsvcSnapshooter.ServiceCreate(Sender: TObject);
var
  TZ: TTimeZone;
  InsertDateTime: string;
  SQLRes: TResourceStream;
  SQLFile: TStringList;
  i: Integer;
  StrStr: TStringStream;
begin
  // Determine the base path
  FVersionInfo := TFileVersionInfo.Create(ParamStr(0));
  FBasePath := IncludeTrailingPathDelimiter(IncludeTrailingPathDelimiter(
                L_ShellFolders.GetFolderPath(CSIDL_COMMON_APPDATA)) + FVersionInfo.CompanyName) + FVersionInfo.ProductName;
  ForceDirectories(FBasePath);

  // Open the database, or create it if it doesn't exist
  FDB := TSQLiteDatabase.Create(IncludeTrailingPathDelimiter(FBasePath) + 'activity.sqlite');
  FDB.SetTimeout(2500);
  if not FDB.TableExists('Focus') then begin
    SQLFile := TStringList.Create;
    try
      SQLFile.LineBreak := #13#10#13#10;
      StrStr := TStringStream.Create('');
      try
        SQLRes := TResourceStream.Create(HInstance, 'CreateDatabase', RT_RCDATA);
        try
          StrStr.CopyFrom(SQLRes, SQLRes.Size);
        finally
          SQLRes.Free;
        end;
        StrStr.Position := 0;
        SQLFile.Text := StrStr.ReadString(StrStr.Size);
      finally
        StrStr.Free;
      end;
      try
        for i := 0 to SQLFile.Count - 1 do begin
          if Length(SQLFile.Strings[i]) > 0 then begin
            FDB.ExecSQL(SQLFile.Strings[i]);
          end;
        end;
      except
        on E: Exception do begin
          FDB.Free;
          RenameFile(IncludeTrailingPathDelimiter(FBasePath) + 'activity.sqlite', IncludeTrailingPathDelimiter(FBasePath) + 'activity-errors.sqlite');
          raise;
        end;
      end;
    finally
      SQLFile.Free;
    end;
  end;

  TZ := TTimeZone.Create;
  try
    InsertDateTime := FormatDateTime('yyyy-MM-dd hh:nn:ss', Now, FDB.FormatSettings);
    // Ascertain current RunLocation (create it if it doesn't exist)
    FDB.AddParamText(':ComputerName', UpperCase(GetCurrentComputerName));
    FDB.AddParamText(':UserName', LowerCase(GetCurrentUserName));
    FDB.AddParamText(':Path', NormalizePathName(ParamStr(0)));
    FRunLocationID := FDB.GetTableValue('SELECT id FROM RunLocation WHERE upper(computername) = :ComputerName AND lower(username) = :UserName AND path = :Path');
    if FRunLocationID = 0 then begin
      FDB.AddParamText(':ComputerName', GetCurrentComputerName);
      FDB.AddParamText(':UserName', GetCurrentUserName);
      FDB.AddParamText(':Path', ParamStr(0));
      FDB.AddParamText(':InsertDateTime', InsertDateTime + TZ.GetFormattedBias);
      FDB.ExecSQL('INSERT INTO RunLocation(computername, username, path, insertdatetime) VALUES (:ComputerName, :UserName, :Path, :InsertDateTime)');
      FRunLocationID := FDB.GetLastInsertRowID;
    end;

    // Close any open sessions
    FDB.AddParamText(':Remarks', Format('Session closed from RunLocation(%d) on %s', [FRunLocationID, InsertDateTime + TZ.GetFormattedBias]));
    FDB.ExecSQL('UPDATE Session SET isactive = 0, remarks = ifnull(Remarks || '''#13#10''' || :Remarks, :Remarks) WHERE isactive = 1');

    // Create new Session
    FDB.AddParamText(':DBVersion', FDB.GetTableString('SELECT sqlite_version()'));
    FDB.AddParamInt(':RunLocationID', FRunLocationID);
    FDB.AddParamText(':Version', FVersionInfo.FileVersion);
    FDB.AddParamInt(':TimezoneBias', TZ.CurrentBias);
    FDB.AddParamDateTime(':StartupTime', GetSystemStartupTime);
    FDB.AddParamDateTime(':PreviousShutdownTime', GetSystemLastShutdownTime, 0);
    FDB.AddParamText(':InsertDateTime', InsertDateTime);
    FDB.ExecSQL('INSERT INTO Session(runlocationid, version, dbversion, timezonebias, startuptime, previousshutdowntime, isactive, insertdatetime) ' +
                'VALUES (:RunLocationID, :Version, :DBVersion, :TimezoneBias, :StartupTime, :PreviousShutdownTime, 1, :InsertDateTime)');
    FSessionID := FDB.GetLastInsertRowID;
  finally
    TZ.Free;
  end;

  // TODO: set up to respond to special service requests
  RegisterServiceCtrlHandlerEx(PChar(Self.Name), @HandlerEx);
end {TsvcSnapshooter.ServiceCreate};
{ ------------------------------------------------------------------------------------------------ }
procedure TsvcSnapshooter.ServiceDestroy(Sender: TObject);
begin
  FreeAndNil(FVersionInfo);
  if Assigned(FDB) then begin
    DoCloseSession(100);
  end;
end{TsvcSnapshooter.ServiceDestroy};

{ ------------------------------------------------------------------------------------------------ }

procedure TsvcSnapshooter.ServiceExecute(Sender: TService);
begin
  if Assigned(tmrScreenshot.OnTimer) then
    tmrScreenshot.OnTimer(tmrScreenshot);
  tmrScreenshot.Enabled := True;

  // TODO: make cleanup intervals optional and adjustable
  FJanitor := TImageJanitor.Create(IncludeTrailingPathDelimiter(FBasePath) + 'activity.sqlite');
  FJanitor.FreeOnTerminate := False;
  FJanitor.Priority := tpIdle;
  FJanitor.Execute;

  while not Terminated do begin
    ServiceThread.ProcessRequests(True);
    Sleep(100);
  end;

  tmrScreenshot.Enabled := False;
end{TsvcSnapshooter.ServiceExecute};

{ ------------------------------------------------------------------------------------------------ }

function TsvcSnapshooter.ControllerEx(dwControl, dwEventType: DWORD; lpEventData, lpContext: LPVOID): DWORD;
begin
  case dwControl of
    SERVICE_CONTROL_INTERROGATE:
      Result := NO_ERROR;
    SERVICE_CONTROL_POWEREVENT: begin
      // record power event
      case dwEventType of
        PBT_APMRESUMEAUTOMATIC: begin
          // TODO: record waking up
        end;
        PBT_APMSUSPEND: begin
          // TODO: record going to sleep
        end;
      end;
      // TODO: Result := DWORD(True); 
    end;
    SERVICE_CONTROL_SESSIONCHANGE: begin
      // TODO: record session event
      case dwEventType of
        WTS_CONSOLE_CONNECT: ;    // A session was connected to the console terminal.
        WTS_CONSOLE_DISCONNECT: ; // A session was disconnected from the console terminal.
        WTS_REMOTE_CONNECT: ;     // A session was connected to the remote terminal.
        WTS_REMOTE_DISCONNECT: ;  // A session was disconnected from the remote terminal.
        WTS_SESSION_LOGON: ;      // A user has logged on to the session.
        WTS_SESSION_LOGOFF: ;     // A user has logged off the session.
        WTS_SESSION_LOCK: ;       // A session has been locked.
        WTS_SESSION_UNLOCK: ;     // A session has been unlocked.
//        WTS_SESSION_REMOTE_CONTROL: ;  
      end;
      // TODO: Result := DWORD(True);
    end
    else
      Result := ERROR_CALL_NOT_IMPLEMENTED;  
  end;
end;


{ ------------------------------------------------------------------------------------------------ }

procedure TsvcSnapshooter.ServicePause(Sender: TService; var Paused: Boolean);
begin
  tmrScreenshot.Enabled := False;
  if Assigned(FJanitor) and (not FJanitor.Terminated) then begin
    FJanitor.Suspend;
  end;
  Paused := True;
end{TsvcSnapshooter.ServicePause};
{ ------------------------------------------------------------------------------------------------ }
procedure TsvcSnapshooter.ServiceContinue(Sender: TService; var Continued: Boolean);
begin
  if Assigned(FJanitor) and (not FJanitor.Terminated) and FJanitor.Suspended then begin
    FJanitor.Resume;
  end;
  tmrScreenshot.Enabled := True;
  Continued := True;
end{TsvcSnapshooter.ServiceContinue};

{ ------------------------------------------------------------------------------------------------ }

procedure TsvcSnapshooter.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
  // What if we're in the middle of saving a snapshot?  Preferably do this on shutdown.
  // TODO: Determine whether we're still processing a snapshot
//  if Assigned(FDB) then begin
//    DoCloseSession(102); // stop
//  end;
  tmrScreenshot.Enabled := False;
  if Assigned(FJanitor) and (not FJanitor.Terminated) then begin
    if FJanitor.Suspended then begin
      FJanitor.Resume;
    end;
    FJanitor.Terminate;
  end;
  Stopped := True;
end;

{ ------------------------------------------------------------------------------------------------ }

procedure TsvcSnapshooter.ServiceShutdown(Sender: TService);
begin
  if Assigned(FDB) then begin
    DoCloseSession(101); // shutdown
  end;
end;

{ ------------------------------------------------------------------------------------------------ }
procedure TsvcSnapshooter.tmrScreenshotTimer(Sender: TObject);
var
  BMPImage: TBitmap;
  ShotTime: TDateTime;
  ActiveWindow, Window: hWnd;
  Filename: string;
  Index, Error: Integer;
begin
  // TODO: don't save screenshot if user's been idle ever since before the last screenshot (optional)
  // TODO: build better exception handling

  try
    // Keep track of what we've stored during this snapshot (to avoid storing it more than once)
    FExecutableIDs := TList.Create;
    FProcessIDs := TStringList.Create;
    FWindowIDs := TStringList.Create;
    try
      ActiveWindow := GetForegroundWindow();

      // Take a screenshot of the entire desktop once every 5 snapshots -- unless the desktop is
      //  locked! (it would end up black)
      if not IsWorkstationLocked then begin
        if TTimer(Sender).Tag = 0 then begin
          // Take screen shot of entire desktop
          ShotTime := Now;
          try
            BMPImage := CaptureWindow();
          except
            on E: Exception do begin
              // If we couldn't make a screen shot, then just log it, and let it be
              Self.LogMessage( Format('%s while trying to capture desktop: "%s"', [E.ClassName, E.Message]), EVENTLOG_WARNING_TYPE);
              BMPImage := nil;
            end;
          end;

          if Assigned(BMPImage) then begin
            Filename := SaveScreenshot(BMPImage, ActiveWindow, ShotTime);

            // Store this window's information in the database
            DescribeWindow(ActiveWindow, True, Copy(Filename, Length(FBasePath) + 2));
          end;

          // The next four turns, don't take a screen shot
          TTimer(Sender).Tag := 5;
        end else begin
          // Decrease the counter until the next screen shot
          TTimer(Sender).Tag := TTimer(Sender).Tag - 1;
        end{if take screenshot};
      end;


      // Enumerate current windows, and save them (and their processes) in the database
      try
        SetLength(EnumeratedWindows, 0);
        if EnumWindows(@EnumWindowProc, 0) then begin
          Error := 0;
        end else begin
          Error := GetLastError;
        end;

        // Store the information on each top-level visible window
        for Index := 0 to High(EnumeratedWindows) do begin
          Window := EnumeratedWindows[Index];
          if IsWindow(Window) then begin
            DescribeWindow(Window, Window = ActiveWindow);
          end;
        end;
        SetLength(EnumeratedWindows, 0);

        if Error <> 0 then begin
          RaiseLastOSError(Error);
        end;
      except
        on E: EOSError do begin
          Self.LogMessage(Format('%s %d while trying to enumerate current windows and processes:'#13#10'%s', [E.ClassName, E.ErrorCode, E.Message]), EVENTLOG_WARNING_TYPE);
        end;
        on E: Exception do begin
          Self.LogMessage(Format('%s while trying to enumerate current windows and processes:'#13#10'%s', [E.ClassName, E.Message]), EVENTLOG_WARNING_TYPE);
        end;
      end;

      // now, update the other still-existing processes and windows in the database
      UpdateExistingProcessesAndWindows;

    finally
      FreeAndNil(FExecutableIDs);
      FreeAndNil(FProcessIDs);
      FreeAndNil(FWindowIDs);
    end;

  except
    on E: Exception do begin
      Self.LogMessage(Format('[%s] %s', [E.ClassName, E.Message]), EVENTLOG_ERROR_TYPE);
    end;
  end;

end{tmrScreenshotTimer};

{ ------------------------------------------------------------------------------------------------ }
function TsvcSnapshooter.DescribeWindow(WindowHandle: HWND; IsFocused: boolean = false; Filename: WideString = ''): boolean;
var
  Title: WideString;
  WindowClass: string;
  SysProcessID: Cardinal;
  ExecutablePath: WideString;
  ExecutableID, DBProcessID, WindowID: Int64;
  FileVersion, FileDescription: WideString;
begin
  Result := False;

  if IsWindow(WindowHandle) then begin
    Title := GetWindowTitle(WindowHandle);
    WindowClass := GetWindowClassName(WindowHandle);
    try
      // Don't record invisible windows
      if IsFocused or ((GetWindowLong(WindowHandle, GWL_STYLE) and WS_VISIBLE) = WS_VISIBLE) then begin

        if GetWindowThreadProcessId(WindowHandle, SysProcessID) <> 0 then begin
          // Retrieve the full path of given process ID's executable
          ExecutablePath := GetProcessPathById(SysProcessID);

          // Insert or update the executable, process, and window in the database, and return their IDs
          ExecutableID := DoRecordExecutable(ExecutablePath, FileVersion, FileDescription);
          DBProcessID := DoRecordProcess(SysProcessID, ExecutableID, FileVersion, FileDescription, Title);
          WindowID := DoRecordWindow(DBProcessID, WindowHandle, Title, WindowClass);

          // Add the currently focused window to the database
          if IsFocused then begin
            DoRecordFocus(WindowID, WindowHandle, Title, Filename);
          end;

          Result := True;
        end;
      end;
    except
      on E: EOSError do begin
        Self.LogMessage(Format('%s %d while trying to describe window %x "%s":'#13#10'%s', [E.ClassName, E.ErrorCode, WindowHandle, Title, E.Message]), EVENTLOG_WARNING_TYPE, 0, E.ErrorCode);
      end;
      on E: Exception do begin
        Self.LogMessage(Format('%s while trying to describe window %x "%s":'#13#10'%s', [E.ClassName, WindowHandle, Title, E.Message]), EVENTLOG_WARNING_TYPE);
      end;
    end;
  end;
end;

{ ------------------------------------------------------------------------------------------------ }
function TsvcSnapshooter.DoRecordExecutable(FullPath: WideString; out FileVersion, FileDescription: WideString): int64;
var
  Stream: TStream;
  Row: TSQLiteTable;
  FileDateTime: TDateTime;
  Version: TFileVersionInfo;
  IconHandle: THandle;
begin
  Stream := nil;
  try
    FullPath := NormalizePathName(FullPath);
  except
    // unable to normalize the path name; we'll make do with what we have
  end;

  FDB.AddParamInt(':RunLocationID', FRunLocationID);
  FDB.AddParamText(':Path', WideLowerCase(FullPath));
  Row := FDB.GetTable('SELECT id, filedatetime, latestversion, description FROM Executable WHERE runlocationid = :RunLocationID AND LOWER(path) = :Path');
  if Row.EOF or (Row.FieldAsInteger(0) = 0) then begin
    FreeAndNil(Row);
    // Add the executable to the database
    FDB.AddParamInt(':RunLocationID', FRunLocationID);
    FDB.AddParamText(':Name', ExtractFileName(FullPath), '');
    FDB.AddParamText(':Path', FullPath);
    if FileAge(FullPath, FileDateTime) then begin
      FDB.AddParamDateTime(':FileDateTime', FileDateTime);
    end else begin
      FDB.AddParamNull(':FileDateTime');
    end;
    Version := TFileVersionInfo.Create(FullPath);
    try
      FileVersion := Version.FileVersion;
      FileDescription := Version.FileDescription;
      FDB.AddParamText(':Version', FileVersion, '');
      FDB.AddParamText(':Description', FileDescription, '');
      FDB.AddParamText(':Company', Version.CompanyName, '');
    finally
      Version.Free;
    end;
    // Include the executable's icon in executable file
    IconHandle := ExtractIconW(HInstance, PWChar(FullPath), 0);
    Stream := IconStreamFromHandle(IconHandle);
    FDB.AddParamBlob(':Icon', Stream);
    FDB.AddParamDateTime(':DateTime', Now);
    FDB.ExecSQL('INSERT INTO Executable (runlocationid, name, path, filedatetime, latestversion, description, company, icon, insertdatetime)'
                + ' VALUES (:RunLocationID, :Name, :Path, :FileDateTime, :Version, :Description, :Company, :Icon, :DateTime)');
    Result := FDB.GetLastInsertRowID;
  end else begin
    // See if the executable has changed since we last saw it; change its last update date/time anyway
    try
      Result := Row.FieldAsInteger(0);
      FileVersion := Row.FieldAsString('latestversion');
      FileDescription := Row.FieldAsString('description');
      if (FExecutableIDs.IndexOf(Pointer(Result)) = -1) and FileAge(FullPath, FileDateTime) then begin
        if Row.FieldAsString('filedatetime') <> FormatDateTime('yyyy-MM-dd hh:nn:ss', FileDateTime, FDB.FormatSettings) then begin
          // The executable's file date/time have changed!  Update its values!
          FDB.AddParamDateTime(':FileDateTime', FileDateTime);
          Version := TFileVersionInfo.Create(FullPath);
          try
            FileVersion := Version.FileVersion;
            FileDescription := Version.FileDescription;
            FDB.AddParamText(':Version', FileVersion, '');
            FDB.AddParamText(':Description', FileDescription, '');
            FDB.AddParamText(':Company', Version.CompanyName, '');
          finally
            Version.Free;
          end;
          // Include the executable's icon in executable file
          IconHandle := ExtractIconW(HInstance, PWChar(FullPath), 0);
          Stream := IconStreamFromHandle(IconHandle);
          FDB.AddParamBlob(':Icon', Stream);
          FDB.AddParamInt(':ID', Result);
          FDB.AddParamDateTime(':DateTime', Now);
          FDB.ExecSQL('UPDATE Executable SET filedatetime = :FileDateTime, latestversion = :Version, description = :Description, company = :Company, icon = :Icon, UpdateDateTime = :DateTime'
                    + ' WHERE id = :ID');
        end else begin
          FDB.AddParamInt(':ID', Result);
          FDB.AddParamDateTime(':DateTime', Now);
          FDB.ExecSQL('UPDATE Executable SET UpdateDateTime = :DateTime'
                    + ' WHERE id = :ID');
        end;
      end;
    finally
      FreeAndNil(Row);
    end;
  end;
  if Assigned(Stream) then begin // Free the icon's blob stream
    FreeAndNil(Stream);
  end;
  FExecutableIDs.Add(Pointer(Result));
end;

{ ------------------------------------------------------------------------------------------------ }
function TsvcSnapshooter.DoRecordProcess(SysProcessID: integer; ExecutableID: int64; FileVersion, FileDescription, WindowTitle: WideString): int64;
var
  ProcessTimes: TProcessTimes;
  StartupTime: string;
  Index: integer;
  SQL: string;
begin
  { 2009-08-23 Martijn: een proces is uniek o.b.v. de SysProcessID 閚 de CreationTime }
  try
    ProcessTimes := GetProcessTimesByID(SysProcessID);
  except
    on E: Exception do begin
      Self.LogMessage(Format('Unable to retrieve process times for process %d: %s.', [SysProcessID, E.Message]), EVENTLOG_WARNING_TYPE);
      ZeroMemory(@ProcessTimes, sizeof(ProcessTimes));
    end;
  end;

  // Check if we haven't already inserted/updated this process during the current snapshot
  StartupTime := FormatDateTime('yyyy-mm-dd hh:nn:ss', ProcessTimes.CreationTime, FDB.FormatSettings);
  Index := FProcessIDs.IndexOfName(IntToStr(SysProcessID) + '_' + StartupTime);
  if Index > -1 then begin
    Result := StrToInt(FProcessIDs.ValueFromIndex[Index]);
    Exit;
  end;

  FDB.AddParamInt(':SessionID', FSessionID);
  FDB.AddParamInt(':SysProcessID', SysProcessID);
  FDB.AddParamText(':StartupTime', StartupTime);
  Result := FDB.GetTableValue('SELECT id FROM Process WHERE sessionid = :SessionID AND sysprocessid = :SysProcessID AND startuptime = :StartupTime');
  if Result = 0 then begin
    // Add the process to the database
    FDB.AddParamInt(':SessionID', FSessionID);
    FDB.AddParamInt(':SysProcessID', SysProcessID);
    if YearOf(ProcessTimes.CreationTime) > 1900 then begin
      FDB.AddParamDateTime(':StartupTime', ProcessTimes.CreationTime);
    end else begin
      FDB.AddParamNull(':StartupTime');
    end;
    if YearOf(ProcessTimes.ExitTime) > 1900 then begin
      FDB.AddParamDateTime(':TerminateTime', ProcessTimes.ExitTime);
    end else begin
      FDB.AddParamNull(':TerminateTime');
    end;
    FDB.AddParamInt(':ExecutableID', ExecutableID);
    try
      FDB.AddParamText(':UserName', GetProcessUserNameById(SysProcessID), '');
    except
      on E: Exception do begin
        Self.LogMessage(Format('Unable to retrieve username for process %d.', [SysProcessID]), EVENTLOG_WARNING_TYPE);
        FDB.AddParamNull(':UserName');
      end;
    end;
    FDB.AddParamText(':FileVersion', FileVersion, '');
    FDB.AddParamText(':FileDescription', FileDescription, '');
    FDB.AddParamText(':WindowTitle', WindowTitle);
    FDB.AddParamDateTime(':DateTime', Now);
    FDB.ExecSQL('INSERT INTO Process (sessionid, sysprocessid, startuptime, terminatetime, executableid, username, version, description, windowtitle, insertdatetime)'
                + ' VALUES (:SessionID, :SysProcessID, :StartupTime, :TerminateTime, :ExecutableID, :UserName, :FileVersion, :FileDescription, :WindowTitle, :DateTime)');
    Result := FDB.GetLastInsertRowID;
  end else begin
    SQL := 'UPDATE Process'
          + ' SET LastUpdateDateTime = :DateTime'
          + '%s'
          + ' WHERE id = :ID';

    // Store the process's exit time
    if YearOf(ProcessTimes.ExitTime) > 1900 then begin
      FDB.AddParamDateTime(':TerminateDateTime', ProcessTimes.ExitTime);
      SQL := Format(SQL, [', TerminateTime = :TerminateDateTime']);
    end else begin
      SQL := Format(SQL, ['']);
    end;

    // Update the process's updatedatetime
    FDB.AddParamInt(':ID', Result);
    FDB.AddParamDateTime(':DateTime', Now);
    FDB.ExecSQL(SQL);
  end;

  // Remember that we've already stored this process during this snapshot 
  FProcessIDs.Add(Format('%d_%s=%d', [SysProcessID, StartupTime, Result]));
end;

{ ------------------------------------------------------------------------------------------------ }
function TsvcSnapshooter.DoRecordWindow(ProcessID: int64; WindowHandle: hWnd; WindowTitle: WideString; WindowClass: string): int64;
var
  Index: integer;
  Stream: TStream;
  Icon: TIcon;
begin
  // Check if we haven't already inserted/updated this window during the current snapshot
  Index := FWindowIDs.IndexOfObject(TObject(WindowHandle));
  if Index > -1 then begin
    Result := StrToInt(FWindowIDs.Strings[Index]);
    Exit;
  end;

  Stream := nil;
  try
    FDB.AddParamInt(':ProcessID', ProcessID);
    FDB.AddParamInt(':hWnd', WindowHandle);
    Result := FDB.GetTableValue('SELECT id FROM Window WHERE processid = :ProcessID AND handle = :hWnd');
    if Result = 0 then begin
      // Add the window to the database
      FDB.AddParamInt(':ProcessID', ProcessID);
      FDB.AddParamInt(':hWnd', WindowHandle);
      FDB.AddParamText(':Title', WindowTitle);
      FDB.AddParamText(':Class', WindowClass);
      // Determine icon for window
      Icon := GetWindowIcon(WindowHandle);
      if Assigned(Icon) then begin
        try
          Stream := TMemoryStream.Create;
          Icon.SaveToStream(Stream);
          FDB.AddParamBlob(':Icon', Stream);
        finally
          FreeAndNil(Icon);
        end;
      end else begin
        Stream := nil;
        FDB.AddParamNull(':Icon');
      end;
      FDB.AddParamDateTime(':DateTime', Now);
      FDB.ExecSQL('INSERT INTO Window (processid, handle, title, class, icon, insertdatetime)'
                  + ' VALUES (:ProcessID, :hWnd, :Title, :Class, :Icon, :DateTime)');
      Result := FDB.GetLastInsertRowID;
    end else begin
      // Update the window' lastupdatedatetime
      FDB.AddParamInt(':ID', Result);
      FDB.AddParamText(':Title', WindowTitle);
      FDB.AddParamDateTime(':DateTime', Now);
      FDB.ExecSQL('UPDATE Window SET Title = :Title, LastUpdateDateTime = :DateTime'
                + ' WHERE id = :ID');
    end;
  finally
    if Assigned(Stream) then begin
      FreeAndNil(Stream);
    end;
  end;

  // Remember that we've already stored this window during this snapshot
  FWindowIDs.AddObject(IntToStr(Result), TObject(WindowHandle));
end;

{ ------------------------------------------------------------------------------------------------ }
function TsvcSnapshooter.DoRecordFocus(WindowID: int64; WindowHandle: hWnd; WindowTitle: WideString;
  ScreenshotFile: Widestring): int64;
var
  Prev: TSQLiteTable;
  WP: WindowPlacement;
begin
  Prev := FDB.GetTable('SELECT * FROM Focus ORDER BY id DESC LIMIT 1');
  try
    if (Length(ScreenshotFile) > 0) and (Length(Prev.FieldAsString('ScreenshotFile')) > 0) then begin
      Result := 0; // always perform an insert
    end else if (WindowID = Prev.FieldAsInteger('WindowID')) and (WindowTitle = Prev.FieldAsString('Title')) then begin
      Result := Prev.FieldAsInteger('id');
    end else begin
      Result := 0;
    end;

    FDB.AddParamInt(':WindowID', WindowID);
    FDB.AddParamText(':Title', WindowTitle);
    WP.length := sizeof(WP);
    if GetWindowPlacement(WindowHandle, @WP) then begin
      FDB.AddParamInt(':WindowState', WP.showCmd);
      FDB.AddParamInt(':Top', WP.rcNormalPosition.Top);
      FDB.AddParamInt(':Left', WP.rcNormalPosition.Left);
      FDB.AddParamInt(':Right', WP.rcNormalPosition.Right);
      FDB.AddParamInt(':Bottom', WP.rcNormalPosition.Bottom);
    end else begin
      FDB.AddParamNull(':WindowState');
      FDB.AddParamNull(':Top');
      FDB.AddParamNull(':Left');
      FDB.AddParamNull(':Right');
      FDB.AddParamNull(':Bottom');
    end;
    FDB.AddParamInt(':IdleMilliseconds', GetIdleMilliseconds);
    FDB.AddParamText(':Filename', ScreenshotFile, '');
    FDB.AddParamDateTime(':DateTime', Now);

    if Result = 0 then begin
      FDB.ExecSQL('INSERT INTO Focus (windowid, title, windowstate, top, left, right, bottom, idlemilliseconds, screenshotfile, insertdatetime)'
                  + ' VALUES (:WindowID, :Title, :WindowState, :Top, :Left, :Right, :Bottom, :IdleMilliseconds, :Filename, :DateTime)');
      Result := FDB.GetLastInsertRowID;
    end else begin
      FDB.AddParamInt(':ID', Result);
      if Length(ScreenshotFile) = 0 then begin
        FDB.AddParamText(':Filename', Prev.FieldAsString('ScreenshotFile'), '');
      end;
      FDB.ExecSQL('UPDATE Focus'
                + '   SET title = :Title'
                + '   ,   idlemilliseconds = :IdleMilliseconds'
                + '   ,   screenshotfile = :Filename'
                + '   ,   updatedatetime = :DateTime'
                + ' WHERE id = :ID');
    end;
  finally
    Prev.Free;
  end;
end{TsvcSnapshooter.DoRecordFocus};

{ ------------------------------------------------------------------------------------------------ }
procedure TsvcSnapshooter.DoCloseSession(UnloadModeID: int64);
begin
  try
    if Assigned(FJanitor) then begin
      if not FJanitor.Terminated then begin
        FJanitor.Priority := tpNormal;
        if FJanitor.Suspended then begin
          FJanitor.Resume;
        end;
        FJanitor.Terminate;
        FJanitor.WaitFor;
      end;
      FreeAndNil(FJanitor);
    end;

    FDB.AddParamInt(':SessionID', FSessionID);
    FDB.AddParamInt(':UnloadModeID', UnloadModeID);
    FDB.AddParamDateTime(':DateTime', Now);
    FDB.ExecSQL('UPDATE Session'
              + '   SET isactive = 0, unloadmodeid = :UnloadModeID, lastupdatedatetime = :DateTime'
              + ' WHERE id = :SessionID');

    FDB.ExecSQL('VACUUM');
  finally
    if FDB.isTransactionOpen then begin
      FDB.Commit;
    end;
    FreeAndNil(FDB);
  end;
end{TsvcSnapshooter.DoCloseSession};


{ ------------------------------------------------------------------------------------------------ }
class function TsvcSnapshooter.IconStreamFromHandle(IconHandle: THandle): TStream;
var
  Icon: TIcon;
begin
  if IconHandle = 0 then begin
    Result := nil;
  end else begin
    Icon := TIcon.Create;
    try
      Icon.Handle := IconHandle;
      Result := TMemoryStream.Create();
      Icon.SaveToStream(Result);
    finally
      Icon.Free;
    end;
  end;
end;

{ ------------------------------------------------------------------------------------------------ }
class function TsvcSnapshooter.NormalizePathName(Path: WideString): WideString;
var
  Buffer: WideString;
  Size, RetVal: integer;
  FilenameStart: PWChar;
begin
  // Get the full path name to the file
  Size := MAX_PATH;
  repeat
    SetLength(Buffer, Size);
    RetVal := GetFullPathNameW(PWChar(Path), Size, PWChar(Buffer), FilenameStart);
    if RetVal = 0 then begin
      RaiseLastOSError;
    end else if RetVal > Size then begin
      Size := RetVal;
    end else begin
      Result := Copy(Buffer, 1, RetVal);
      Break;
    end;
  until RetVal < Size;

  Result := GetLongPath(Result);
end;

{ ------------------------------------------------------------------------------------------------ }
procedure TsvcSnapshooter.UpdateExistingProcessesAndWindows;
var
  ProcessIDsToUpdate, WindowIDsToUpdate: TStringList;
  Row: TSQLiteTable;
  DBProcessID, WindowID: Int64;
  SysProcessID: integer;
  StartupTime: string;
  WindowHandle: hWnd;
  Index: Integer;
  Handle: THandle;
begin
  ProcessIDsToUpdate := TStringList.Create;
  WindowIDsToUpdate := TStringList.Create;
  try
    // Check all registered processes and windows for the current session, to see if they
    //  still exist.  Update last update time of those who do.
    FDB.AddParamInt(':SessionID', FSessionID);
    Row := FDB.GetTable('SELECT p.id AS processid, p.SysProcessID, p.StartupTime, w.id AS windowid, w.Handle'
                      + '  FROM Process p'
                      + '       LEFT JOIN Window w'
                      + '              ON p.id = w.processid'
                      + ' WHERE p.SessionID = :SessionID'
                      + '   AND p.TerminateTime IS NULL');
    try
      while not Row.EOF do begin
        // --- PROCESS ---
        DBProcessID := Row.FieldAsInteger(0);
        if ProcessIDsToUpdate.IndexOf(IntToStr(DBProcessID)) = -1 then begin
          SysProcessID := Row.FieldAsInteger(1);
          StartupTime := Row.FieldAsString(2);

          // Check if we haven't already inserted/updated this process during the current snapshot
          Index := FProcessIDs.IndexOfName(IntToStr(SysProcessID) + '_' + StartupTime);
          if Index = -1 then begin
            // Check if this process still exists
            Handle := OpenProcess(0, False, SysProcessID);
            if Handle <> 0 then begin
              CloseHandle(Handle);
              ProcessIDsToUpdate.Add(IntToStr(DBProcessID));
            end;
          end;
        end;

        // --- WINDOW ---
        WindowID := Row.FieldAsInteger(3);
        if WindowIDsToUpdate.IndexOf(IntToStr(WindowID)) = -1 then begin
          WindowHandle := Row.FieldAsInteger(4);

          // Check if we haven't already inserted/updated this window during the current snapshot
          Index := FWindowIDs.IndexOfObject(TObject(WindowHandle));
          if (Index = -1) and IsWindow(WindowHandle) then begin
            WindowIDsToUpdate.Add(IntToStr(WindowID));
          end;
        end;

        Row.Next;
      end;
    finally
      Row.Free;
    end;

    if ProcessIDsToUpdate.Count > 0 then begin
      FDB.AddParamDateTime(':DateTime', Now);
      FDB.ExecSQL('UPDATE Process SET LastUpdateDateTime = :DateTime WHERE id in (' + ProcessIDsToUpdate.DelimitedText + ')');
    end;
    if WindowIDsToUpdate.Count > 0 then begin
      FDB.AddParamDateTime(':DateTime', Now);
      FDB.ExecSQL('UPDATE Window SET LastUpdateDateTime = :DateTime WHERE id in (' + WindowIDsToUpdate.DelimitedText + ')');
    end;
  finally
    ProcessIDsToUpdate.Free;
    WindowIDsToUpdate.Free;
  end;
end;

{ ------------------------------------------------------------------------------------------------ }
function TsvcSnapshooter.SaveScreenshot(BMPImage: TBitmap; ActiveWindow: HWND; ShotTime: TDateTime): widestring;
var
  FilePath: string;
  UserName: WideString;
  ExecutablePath: WideString;
  ProcessID: Cardinal;
  WindowClass: string;
  Title: WideString;
  PNGImage: TPNGObject;
begin
  try
    // Assemble a filename for the screen shot
    // Retrieve title of foreground window, and use that in the file name
    if IsWindow(ActiveWindow) then begin
      Title := GetWindowTitle(ActiveWindow);
      WindowClass := GetWindowClassName(ActiveWindow);
      if GetWindowThreadProcessId(ActiveWindow, ProcessID) <> 0 then begin
        // Retrieve the full path of given process ID's executable
        ExecutablePath := GetProcessPathById(ProcessID);
        UserName := GetProcessUserNameById(ProcessID, True);
      end else begin
        ExecutablePath := '';
        UserName := '';
      end;
      // Remove any unacceptable file characters
      Result := Title;
      if Length(Result) > 0 then begin
        Result := ' - ' + SafeFilename(Result);
      end;
    end else begin
      Title := '';
      Result := '';
      WindowClass := '';
      ExecutablePath := '';
      UserName := '';
    end;

    // Prepare path based on current date
    FilePath := FormatDateTime('yyyy\MM\dd (ddd)', ShotTime);
    ForceDirectories(IncludeTrailingPathDelimiter(FBasePath) + FilePath);
    Result := WideFormat('%s\%s\%s%s', [FBasePath, FilePath, FormatDateTime('yyyy-MM-dd (ddd) hh.nn.ss', ShotTime), Result]);
    if Length(Result) > 255 then begin
      Result := Copy(Result, 1, 255);
    end;

    // save image as PNG to save space while retaining the full image quality
    try
      PNGImage := TPNGObject.Create;
      try
        PNGImage.Assign(BMPImage);
        // Store some metadata of the screen shot into the picture
        if Length(Title) > 0 then begin
          PNGImage.AddtEXt('Title', Title);
        end;
        PNGImage.AddzTXt('Author', UserName); // TODO: make this an iTXt
        if Length(ExecutablePath) > 0 then begin
          PNGImage.AddztXt('Source', ExecutablePath);
        end;
        (PNGImage.Chunks.Add(TChunktIME) as TChunktIME).DateTime := ShotTime + (GetCurrentTimeZoneBias / 1440);
        PNGImage.AddtEXt('Creation Time', FormatDateTime('yyyy-MM-dd hh:nn:ss.zzz', ShotTime, FDB.FormatSettings));
        PNGImage.AddtEXt('Software', Format('%s v%s', [Application.Title, FVersionInfo.FileVersion]));
        if (Length(ExecutablePath) + Length(WindowClass)) > 0 then begin
          // TODO: include active application's description and version info (if available)
          PNGImage.AddzTXt('Comment', Format('Class: "%s"', [WindowClass]));
        end;
        PNGImage.CompressionLevel := 9; // maximum compression
        PNGImage.SaveToFile(Result + '.png');
        Result := Result + '.png';
      finally
        PNGImage.Free;
      end;
    except
      on E: Exception do begin
        // We couldn't save the file to PNG; log the error, and try to save it as BMP
        Self.LogMessage(Format('%s while trying to save PNG screenshot:'#13''#10'%s', [E.ClassName, E.Message]), EVENTLOG_WARNING_TYPE);
        BMPImage.SaveToFile(Result + '.bmp');
        Result := Result + '.bmp';
      end;
    end;
    {try}
  finally
    BMPImage.Free;
  end;
end;

{ ------------------------------------------------------------------------------------------------ }
function TsvcSnapshooter.SafeFilename(Filename: widestring): widestring;
const
  IllegalChars: widestring = '*?<>\|/:"';
  Replacements: widestring = 'た___=''';
var
  c: widechar;
  i, ci: Integer;
begin
  SetLength(Result, Length(Filename));
  for i := 1 to Length(Filename) do begin
    c := Filename[i];
    if c < ' ' then begin
       Result[i] := '_';
    end else begin
      ci := Pos(c, IllegalChars);
      if ci > 0 then begin
        Result[i] := Replacements[ci];
      end else begin
        Result[i] := c;
      end;
    end;
  end;
end;

end.

Added Snapshooter/src/SQL.rc.



>
1
CreateDatabase RCDATA "..\res\CreateDatabase.sql"

Added Snapshooter/src/Snapshooter.bdsproj.

































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
<?xml version="1.0" encoding="utf-8"?>
<BorlandProject>
	<PersonalityInfo>
		<Option>
			<Option Name="Personality">Delphi.Personality</Option>
			<Option Name="ProjectType"></Option>
			<Option Name="Version">1.0</Option>
			<Option Name="GUID">{F3179F8D-EF3A-40DF-8974-6642AB838B52}</Option>
		</Option>
	</PersonalityInfo>
	<Delphi.Personality>
		<Source>
			<Source Name="MainSource">Snapshooter.dpr</Source>
		</Source>
		<FileVersion>
			<FileVersion Name="Version">7.0</FileVersion>
		</FileVersion>
		<Compiler>
			<Compiler Name="A">8</Compiler>
			<Compiler Name="B">0</Compiler>
			<Compiler Name="C">0</Compiler>
			<Compiler Name="D">0</Compiler>
			<Compiler Name="E">0</Compiler>
			<Compiler Name="F">0</Compiler>
			<Compiler Name="G">1</Compiler>
			<Compiler Name="H">1</Compiler>
			<Compiler Name="I">1</Compiler>
			<Compiler Name="J">0</Compiler>
			<Compiler Name="K">0</Compiler>
			<Compiler Name="L">0</Compiler>
			<Compiler Name="M">0</Compiler>
			<Compiler Name="N">1</Compiler>
			<Compiler Name="O">1</Compiler>
			<Compiler Name="P">1</Compiler>
			<Compiler Name="Q">0</Compiler>
			<Compiler Name="R">0</Compiler>
			<Compiler Name="S">0</Compiler>
			<Compiler Name="T">0</Compiler>
			<Compiler Name="U">0</Compiler>
			<Compiler Name="V">1</Compiler>
			<Compiler Name="W">0</Compiler>
			<Compiler Name="X">1</Compiler>
			<Compiler Name="Y">0</Compiler>
			<Compiler Name="Z">1</Compiler>
			<Compiler Name="ShowHints">True</Compiler>
			<Compiler Name="ShowWarnings">True</Compiler>
			<Compiler Name="UnitAliases">WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;</Compiler>
			<Compiler Name="NamespacePrefix"></Compiler>
			<Compiler Name="GenerateDocumentation">False</Compiler>
			<Compiler Name="DefaultNamespace"></Compiler>
			<Compiler Name="SymbolDeprecated">True</Compiler>
			<Compiler Name="SymbolLibrary">True</Compiler>
			<Compiler Name="SymbolPlatform">False</Compiler>
			<Compiler Name="SymbolExperimental">True</Compiler>
			<Compiler Name="UnitLibrary">True</Compiler>
			<Compiler Name="UnitPlatform">False</Compiler>
			<Compiler Name="UnitDeprecated">True</Compiler>
			<Compiler Name="UnitExperimental">True</Compiler>
			<Compiler Name="HResultCompat">True</Compiler>
			<Compiler Name="HidingMember">True</Compiler>
			<Compiler Name="HiddenVirtual">True</Compiler>
			<Compiler Name="Garbage">True</Compiler>
			<Compiler Name="BoundsError">True</Compiler>
			<Compiler Name="ZeroNilCompat">True</Compiler>
			<Compiler Name="StringConstTruncated">True</Compiler>
			<Compiler Name="ForLoopVarVarPar">True</Compiler>
			<Compiler Name="TypedConstVarPar">True</Compiler>
			<Compiler Name="AsgToTypedConst">True</Compiler>
			<Compiler Name="CaseLabelRange">True</Compiler>
			<Compiler Name="ForVariable">True</Compiler>
			<Compiler Name="ConstructingAbstract">True</Compiler>
			<Compiler Name="ComparisonFalse">True</Compiler>
			<Compiler Name="ComparisonTrue">True</Compiler>
			<Compiler Name="ComparingSignedUnsigned">True</Compiler>
			<Compiler Name="CombiningSignedUnsigned">True</Compiler>
			<Compiler Name="UnsupportedConstruct">True</Compiler>
			<Compiler Name="FileOpen">True</Compiler>
			<Compiler Name="FileOpenUnitSrc">True</Compiler>
			<Compiler Name="BadGlobalSymbol">True</Compiler>
			<Compiler Name="DuplicateConstructorDestructor">True</Compiler>
			<Compiler Name="InvalidDirective">True</Compiler>
			<Compiler Name="PackageNoLink">True</Compiler>
			<Compiler Name="PackageThreadVar">True</Compiler>
			<Compiler Name="ImplicitImport">True</Compiler>
			<Compiler Name="HPPEMITIgnored">True</Compiler>
			<Compiler Name="NoRetVal">True</Compiler>
			<Compiler Name="UseBeforeDef">True</Compiler>
			<Compiler Name="ForLoopVarUndef">True</Compiler>
			<Compiler Name="UnitNameMismatch">True</Compiler>
			<Compiler Name="NoCFGFileFound">True</Compiler>
			<Compiler Name="ImplicitVariants">True</Compiler>
			<Compiler Name="UnicodeToLocale">True</Compiler>
			<Compiler Name="LocaleToUnicode">True</Compiler>
			<Compiler Name="ImagebaseMultiple">True</Compiler>
			<Compiler Name="SuspiciousTypecast">True</Compiler>
			<Compiler Name="PrivatePropAccessor">True</Compiler>
			<Compiler Name="UnsafeType">False</Compiler>
			<Compiler Name="UnsafeCode">False</Compiler>
			<Compiler Name="UnsafeCast">False</Compiler>
			<Compiler Name="OptionTruncated">True</Compiler>
			<Compiler Name="WideCharReduced">True</Compiler>
			<Compiler Name="DuplicatesIgnored">True</Compiler>
			<Compiler Name="UnitInitSeq">True</Compiler>
			<Compiler Name="LocalPInvoke">True</Compiler>
			<Compiler Name="MessageDirective">True</Compiler>
			<Compiler Name="CodePage"></Compiler>
		</Compiler>
		<Linker>
			<Linker Name="MapFile">0</Linker>
			<Linker Name="OutputObjs">0</Linker>
			<Linker Name="GenerateHpps">False</Linker>
			<Linker Name="ConsoleApp">1</Linker>
			<Linker Name="DebugInfo">False</Linker>
			<Linker Name="RemoteSymbols">False</Linker>
			<Linker Name="GenerateDRC">False</Linker>
			<Linker Name="MinStackSize">16384</Linker>
			<Linker Name="MaxStackSize">1048576</Linker>
			<Linker Name="ImageBase">4194304</Linker>
			<Linker Name="ExeDescription"></Linker>
		</Linker>
		<Directories>
			<Directories Name="OutputDir">..\Out</Directories>
			<Directories Name="UnitOutputDir">..\Out\DCU</Directories>
			<Directories Name="PackageDLLOutputDir"></Directories>
			<Directories Name="PackageDCPOutputDir"></Directories>
			<Directories Name="SearchPath">F:\MM\Code\Common\Delphi\;F:\MM\Code\Common\Delphi\PNGImage;F:\MM\Code\Common\Delphi\SQLite\</Directories>
			<Directories Name="Packages">vcl;rtl;vclx;dbrtl;vcldb;adortl;dbxcds;dbexpress;vclib;ibxpress;xmlrtl;vclactnband;inet;vclie;inetdbbde;inetdbxpress;IndyCore;IndySystem;dclOfficeXP;VclSmp;soaprtl;dsnap;IndyProtocols;bdertl;teeui;teedb;tee;vcldbx;TMSD2006;Scit;DL_Geo_100;DL_Base_100;S303_r100;B305_r100;DL_Control_100;DL_GDI_100;RaizeComponentsVcl</Directories>
			<Directories Name="Conditionals"></Directories>
			<Directories Name="DebugSourceDirs"></Directories>
			<Directories Name="UsePackages">False</Directories>
		</Directories>
		<Parameters>
			<Parameters Name="RunParams"></Parameters>
			<Parameters Name="HostApplication"></Parameters>
			<Parameters Name="Launcher"></Parameters>
			<Parameters Name="UseLauncher">False</Parameters>
			<Parameters Name="DebugCWD"></Parameters>
			<Parameters Name="Debug Symbols Search Path"></Parameters>
			<Parameters Name="LoadAllSymbols">True</Parameters>
			<Parameters Name="LoadUnspecifiedSymbols">False</Parameters>
		</Parameters>
		<Language>
			<Language Name="ActiveLang"></Language>
			<Language Name="ProjectLang">$00000000</Language>
			<Language Name="RootDir"></Language>
		</Language>
		<VersionInfo>
			<VersionInfo Name="IncludeVerInfo">True</VersionInfo>
			<VersionInfo Name="AutoIncBuild">True</VersionInfo>
			<VersionInfo Name="MajorVer">1</VersionInfo>
			<VersionInfo Name="MinorVer">0</VersionInfo>
			<VersionInfo Name="Release">0</VersionInfo>
			<VersionInfo Name="Build">196</VersionInfo>
			<VersionInfo Name="Debug">True</VersionInfo>
			<VersionInfo Name="PreRelease">True</VersionInfo>
			<VersionInfo Name="Special">False</VersionInfo>
			<VersionInfo Name="Private">False</VersionInfo>
			<VersionInfo Name="DLL">False</VersionInfo>
			<VersionInfo Name="Locale">1043</VersionInfo>
			<VersionInfo Name="CodePage">1252</VersionInfo>
		</VersionInfo>
		<VersionInfoKeys>
			<VersionInfoKeys Name="CompanyName">Voronw毛</VersionInfoKeys>
			<VersionInfoKeys Name="FileDescription">Automatically takes snapshots of the currently active desktop.</VersionInfoKeys>
			<VersionInfoKeys Name="FileVersion">1.0.0.196</VersionInfoKeys>
			<VersionInfoKeys Name="InternalName">Snapshooter</VersionInfoKeys>
			<VersionInfoKeys Name="LegalCopyright">漏 Martijn Coppoolse</VersionInfoKeys>
			<VersionInfoKeys Name="LegalTrademarks"></VersionInfoKeys>
			<VersionInfoKeys Name="OriginalFilename">Snapshooter.exe</VersionInfoKeys>
			<VersionInfoKeys Name="ProductName">Snapshooter</VersionInfoKeys>
			<VersionInfoKeys Name="ProductVersion">1.0.0.0</VersionInfoKeys>
			<VersionInfoKeys Name="Comments">http://martijn.coppoolse.com/software</VersionInfoKeys>
		</VersionInfoKeys>  
    
    
    
    
    
    
    
    
    
    
    
    
    <Excluded_Packages>
      <Excluded_Packages Name="C:\Program Files\Prog\Borland\BDS\4.0\Bin\vclshlctrls100.bpl">Win32 Shell Controls</Excluded_Packages>
    </Excluded_Packages>
  </Delphi.Personality>
	<StarTeamAssociation></StarTeamAssociation>
	<StarTeamNonRelativeFiles></StarTeamNonRelativeFiles>
</BorlandProject>

Added Snapshooter/src/Snapshooter.cfg.





























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
-$A8
-$B-
-$C-
-$D-
-$E-
-$F-
-$G+
-$H+
-$I+
-$J-
-$K-
-$L-
-$M-
-$N+
-$O+
-$P+
-$Q-
-$R-
-$S-
-$T-
-$U-
-$V+
-$W-
-$X+
-$Y-
-$Z1
-cg
-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
-H+
-W+
-M
-$M16384,1048576
-K$00400000
-E"..\Out"
-N0"..\Out\DCU"
-LE"C:\Program Files\Prog\Borland\BDS\4.0\Bin"
-LN"F:\MM\Code\Projects\Borland\Bpl"
-U"F:\MM\Code\Common\Delphi\;F:\MM\Code\Common\Delphi\PNGImage;F:\MM\Code\Common\Delphi\SQLite\"
-O"F:\MM\Code\Common\Delphi\;F:\MM\Code\Common\Delphi\PNGImage;F:\MM\Code\Common\Delphi\SQLite\"
-I"F:\MM\Code\Common\Delphi\;F:\MM\Code\Common\Delphi\PNGImage;F:\MM\Code\Common\Delphi\SQLite\"
-R"F:\MM\Code\Common\Delphi\;F:\MM\Code\Common\Delphi\PNGImage;F:\MM\Code\Common\Delphi\SQLite\"
-w-SYMBOL_PLATFORM
-w-UNIT_PLATFORM
-w-UNSAFE_TYPE
-w-UNSAFE_CODE
-w-UNSAFE_CAST

Added Snapshooter/src/Snapshooter.dpr.































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
program Snapshooter;

uses
  SvcMgr,
  MainService in 'MainService.pas' {svcSnapshooter: TService},
  U_SQL in 'U_SQL.pas',
  ImageJanitor in 'ImageJanitor.pas';

{$R *.RES}

begin
  // Windows 2003 Server requires StartServiceCtrlDispatcher to be
  // called before CoRegisterClassObject, which can be called indirectly
  // by Application.Initialize. TServiceApplication.DelayInitialize allows
  // Application.Initialize to be called from TService.Main (after
  // StartServiceCtrlDispatcher has been called).
  //
  // Delayed initialization of the Application object may affect
  // events which then occur prior to initialization, such as
  // TService.OnCreate. It is only recommended if the ServiceApplication
  // registers a class object with OLE and is intended for use with
  // Windows 2003 Server.
  //
  // Application.DelayInitialize := True;
  //
  if not Application.DelayInitialize or Application.Installing then
    Application.Initialize;
  Application.Title := 'Snapshooter';
  Application.CreateForm(TsvcSnapshooter, svcSnapshooter);
  Application.Run;
end.

Added Snapshooter/src/Snapshooter.res.

cannot compute difference between binary files

Added Snapshooter/src/U_SQL.pas.



































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
unit U_SQL;

interface
  resourcestring
    scCreateTableSession = '';
    scCreateTableRunLocation = '';
    scCreateTableUnloadMode = '';
    scCreateTableExecutable = '';
    scCreateTableProcess = '';
    scCreateTableWindow = '';
    scCreateTableFocus = '';


implementation

end.

Added Snapshooter/src/sql.RES.

cannot compute difference between binary files