001: // CTPuzzleDlg.cpp : implementation file

002: //

003: 
004: #include "stdafx.h"
005: #include "CTPuzzle.h"
006: #include "CTPuzzleDlg.h"
007: #include "UKPuzzleDef.h"
008: 
009: #include <math.h>
010: 
011: #ifdef _DEBUG
012: #define new DEBUG_NEW
013: #undef THIS_FILE
014: static char THIS_FILE[] = __FILE__;
015: #endif

016: 
017: /////////////////////////////////////////////////////////////////////////////

018: // CAboutDlg dialog used for App About

019: 
020: class CAboutDlg : public CDialog
021: {
022: public:
023:         CAboutDlg();
024: 
025: // Dialog Data

026:         //{{AFX_DATA(CAboutDlg)

027:         enum { IDD = IDD_ABOUTBOX };
028:         //}}AFX_DATA

029: 
030:         // ClassWizard generated virtual function overrides

031:         //{{AFX_VIRTUAL(CAboutDlg)

032:         protected:
033:         virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

034:         //}}AFX_VIRTUAL

035: 
036: // Implementation

037: protected:
038:         //{{AFX_MSG(CAboutDlg)

039:         //}}AFX_MSG

040:         DECLARE_MESSAGE_MAP()
041: };
042: 
043: CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
044: {
045:         //{{AFX_DATA_INIT(CAboutDlg)

046:         //}}AFX_DATA_INIT

047: }
048: 
049: void CAboutDlg::DoDataExchange(CDataExchange* pDX)
050: {
051:         CDialog::DoDataExchange(pDX);
052:         //{{AFX_DATA_MAP(CAboutDlg)

053:         //}}AFX_DATA_MAP

054: }
055: 
056: BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
057:         //{{AFX_MSG_MAP(CAboutDlg)

058:                 // No message handlers

059:         //}}AFX_MSG_MAP

060: END_MESSAGE_MAP()
061: 
062: /////////////////////////////////////////////////////////////////////////////

063: // CCTPuzzleDlg dialog

064: 
065: CCTPuzzleDlg::CCTPuzzleDlg(CWnd* pParent /*=NULL*/)
066: :CDialog(CCTPuzzleDlg::IDD, pParent),
067:  m_bAdminVectorIsInit(FALSE),
068:  m_nThreadCount(0),
069:  m_nActiveThreads(0),
070:  m_nMaxActiveThreads(0),
071:  m_nTimerID1(0),
072:  m_nTimerID2(0),
073:  m_pPuzzleAdminVector(0),
074:  m_strInCfgFileName("")
075: {
076:         //{{AFX_DATA_INIT(CCTPuzzleDlg)

077:         m_strPastTime = _T("");
078:         m_strSolutions = _T("");
079:         m_strSolutionsPerSecond = _T("");
080:         m_strSolutionsPerSecond2 = _T("");
081:         //}}AFX_DATA_INIT

082:         // Note that LoadIcon does not require a subsequent DestroyIcon in Win32

083:         m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
084:         strcpy(m_szPrompt,"::> ");
085: }
086: 
087: void CCTPuzzleDlg::DoDataExchange(CDataExchange* pDX)
088: {
089:         CDialog::DoDataExchange(pDX);
090:         //{{AFX_DATA_MAP(CCTPuzzleDlg)

091:         DDX_Text(pDX, IDC_PASTTIME, m_strPastTime);
092:         DDX_Text(pDX, IDC_SOLUTIONS, m_strSolutions);
093:         DDX_Text(pDX, IDC_SOLPERSEC, m_strSolutionsPerSecond);
094:         DDX_Text(pDX, IDC_SOLPERSEC2, m_strSolutionsPerSecond2);
095:         //}}AFX_DATA_MAP

096: }
097: 
098: BEGIN_MESSAGE_MAP(CCTPuzzleDlg, CDialog)
099:         //{{AFX_MSG_MAP(CCTPuzzleDlg)

100:         ON_WM_SYSCOMMAND()
101:         ON_WM_PAINT()
102:         ON_WM_QUERYDRAGICON()
103:         ON_BN_CLICKED(IDC_Stop, OnStop)
104:         ON_BN_CLICKED(IDC_Start, OnStart)
105:         ON_BN_CLICKED(IDC_Pause, OnPause)
106:         ON_BN_CLICKED(IDC_Continue, OnContinue)
107:         ON_BN_CLICKED(IDC_CLOSEDIALOG, OnCloseDialog)
108:         ON_WM_CLOSE()
109:         ON_WM_TIMER()
110:         ON_BN_CLICKED(IDC_LOAD_CONFIG, OnLoadConfig)
111:         //}}AFX_MSG_MAP

112:         ON_MESSAGE( WM_UK_WRITE, OnUKWrite )
113:         ON_MESSAGE( WM_UK_NOTIFY, OnUKNotify )
114:         ON_UPDATE_COMMAND_UI(IDC_Stop,OnUpdateButtonStop)
115:         ON_UPDATE_COMMAND_UI(IDC_Start,OnUpdateButtonStart)
116:         ON_UPDATE_COMMAND_UI(IDC_Pause,OnUpdateButtonPause)
117:         ON_UPDATE_COMMAND_UI(IDC_Continue,OnUpdateButtonContinue)
118:         ON_UPDATE_COMMAND_UI(IDC_LOAD_CONFIG,OnUpdateLoadConfig)
119: END_MESSAGE_MAP()
120: 
121: /////////////////////////////////////////////////////////////////////////////

122: // CCTPuzzleDlg message handlers

123: 
124: BOOL CCTPuzzleDlg::OnInitDialog()
125: {
126:         CDialog::OnInitDialog();
127: 
128:         // Add "About..." menu item to system menu.

129: 
130:         // IDM_ABOUTBOX must be in the system command range.

131:         ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
132:         ASSERT(IDM_ABOUTBOX < 0xF000);
133: 
134:         CMenu* pSysMenu = GetSystemMenu(FALSE);
135:         if (pSysMenu != NULL)
136:         {
137:                 CString strAboutMenu;
138:                 strAboutMenu.LoadString(IDS_ABOUTBOX);
139:                 if (!strAboutMenu.IsEmpty())
140:                 {
141:                         pSysMenu->AppendMenu(MF_SEPARATOR);
142:                         pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
143:                 }
144:         }
145: 
146:         // Set the icon for this dialog.  The framework does this automatically

147:         //  when the application's main window is not a dialog

148:         SetIcon(m_hIcon, TRUE);                        // Set big icon

149:         SetIcon(m_hIcon, FALSE);                // Set small icon

150:         
151:         // TODO: Add extra initialization here

152: 
153:         m_nTimerID1 = SetTimer(1,1000,NULL);
154:         m_nTimerID2 = SetTimer(2,1000,NULL);
155: 
156:         //*

157:         #ifdef _DEBUG //*/

158:                 SetPriorityClass(GetCurrentProcess(),NORMAL_PRIORITY_CLASS);
159:         //*

160:         #else

161:                 SetPriorityClass(GetCurrentProcess(),HIGH_PRIORITY_CLASS);
162:         #endif

163:         //*/

164: 
165:         SetDlgItemText(IDC_OutputText,m_szPrompt);
166:         
167:         TCHAR szPATH[_MAX_PATH];
168:         TCHAR szDRIVE[_MAX_DRIVE];
169:         TCHAR szDIR[_MAX_DIR];
170:         TCHAR szFNAME[_MAX_FNAME];
171:         TCHAR szEXT[_MAX_EXT];
172: 
173:         //Windows has different behaviors, setting the current directory

174:         //therefor I set the application path as current directory

175: 
176:         //Application Name and Path

177:         GetModuleFileName(GetModuleHandle(NULL),szPATH,_MAX_PATH);
178: 
179:         _splitpath(szPATH,szDRIVE,szDIR,szFNAME,szEXT);
180:         _makepath(szPATH,szDRIVE,szDIR,NULL,NULL);
181:         SetCurrentDirectory(szPATH);
182: 
183:         CUKIniAccess theIniAccess(".\\MainConfig.ini");
184: 
185:         m_nMaxActiveThreads=theIniAccess.ReadValueDef("Global Parameter","MaxThreads",1);
186:         m_strOutputFileNameBase=theIniAccess.ReadValueDef("Global Parameter","OutputFileNameBase","");
187: 
188:         if (m_strInCfgFileName=="")
189:         {
190:                 CString strConfigFileName=theIniAccess.ReadValueDef("Global Parameter","ConfigFileName","");
191:                 _fullpath( szPATH, strConfigFileName, _MAX_PATH );
192:                 m_strConfigFileName=szPATH;
193:         }
194:         else
195:                 m_strConfigFileName=m_strInCfgFileName;
196: 
197:         WriteLn("Maximum number of active threads = %d",m_nMaxActiveThreads);
198:         WriteLn("Output file name base = %s",(LPCTSTR)m_strOutputFileNameBase);
199:         WriteLn("Active configuration file = %s",(LPCTSTR)m_strConfigFileName);
200: 
201:         return TRUE;  // return TRUE  unless you set the focus to a control

202: }
203: 
204: void CCTPuzzleDlg::OnSysCommand(UINT nID, LPARAM lParam)
205: {
206:         if ((nID & 0xFFF0) == IDM_ABOUTBOX)
207:         {
208:                 CAboutDlg dlgAbout;
209:                 dlgAbout.DoModal();
210:         }
211:         else
212:         {
213:                 CDialog::OnSysCommand(nID, lParam);
214:         }
215: }
216: 
217: // If you add a minimize button to your dialog, you will need the code below

218: //  to draw the icon.  For MFC applications using the document/view model,

219: //  this is automatically done for you by the framework.

220: 
221: void CCTPuzzleDlg::OnPaint() 
222: {
223:         if (IsIconic())
224:         {
225:                 CPaintDC dc(this); // device context for painting

226: 
227:                 SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
228: 
229:                 // Center icon in client rectangle

230:                 int cxIcon = GetSystemMetrics(SM_CXICON);
231:                 int cyIcon = GetSystemMetrics(SM_CYICON);
232:                 CRect rect;
233:                 GetClientRect(&rect);
234:                 int x = (rect.Width() - cxIcon + 1) / 2;
235:                 int y = (rect.Height() - cyIcon + 1) / 2;
236: 
237:                 // Draw the icon

238:                 dc.DrawIcon(x, y, m_hIcon);
239:         }
240:         else
241:         {
242:                 CDialog::OnPaint();
243:         }
244: }
245: 
246: // The system calls this to obtain the cursor to display while the user drags

247: //  the minimized window.

248: HCURSOR CCTPuzzleDlg::OnQueryDragIcon()
249: {
250:         return (HCURSOR) m_hIcon;
251: }
252: 
253: void CCTPuzzleDlg::OnOK() 
254: {
255:         // TODO: Add extra validation here

256: 
257:         return;
258: }
259: 
260: void CCTPuzzleDlg::OnCancel() 
261: {
262:         // TODO: Add extra cleanup here

263: 
264:         CDialog::OnCancel();
265: }
266: 
267: BOOL CCTPuzzleDlg::InitThreads()
268: {
269:         //Cant init twice

270:         if (m_bAdminVectorIsInit)        
271:                 return FALSE;
272: 
273:         CUKIniAccess theIniAccess(m_strConfigFileName);
274: 
275:         //m_nThreadCount=12;//From ini

276:         m_nThreadCount=theIniAccess.ReadValueDef("StoneInfo","StoneCount",12);
277:         //m_nMaxActiveThreads=2;

278:         m_nActiveThreads=0;
279: 
280: 
281:         long nXSize=theIniAccess.ReadValueDef("BlockInfo","XSize",0);
282:         long nYSize=theIniAccess.ReadValueDef("BlockInfo","YSize",0);
283:         long nZSize=theIniAccess.ReadValueDef("BlockInfo","ZSize",0);
284:         long nStones=theIniAccess.ReadValueDef("StoneInfo","StoneCount",0);
285: 
286:         //not implemented yet

287:     //BOOL bEnhSym=theIniAccess.ReadValue("SymetryInfo","EnhancedSymetryCheck",FALSE);

288: 
289:         long nSymetries=theIniAccess.ReadValueDef("SymetryInfo","SymetryPosCount",0);
290: 
291:         long bWriteEveryNSolution=theIniAccess.ReadValueDef("OutputInfo","WriteEveryNSolution",0);
292: 
293:         WriteLn("Number of Threads = %d",m_nThreadCount);
294:         WriteLn("Block Size X*Y*Z=%d*%d*%d",nXSize,nYSize,nZSize);
295:         WriteLn("Number of different stones = %d",nStones);
296:         WriteLn("Number of symetries = %d",nSymetries);
297:         WriteLn("Write one every %d solutions to the output file(s)",bWriteEveryNSolution);
298: 
299:         m_pPuzzleAdminVector=new SUKAdminThread*[m_nThreadCount];
300:         if (!m_pPuzzleAdminVector)
301:                 return FALSE;
302: 
303:         //long nPos=m_nThreadCount-1;

304:         long nPos=0;
305:         
306:         for (int i=0;i<m_nThreadCount;i++)
307:         {
308:                 CString strOutputFile;
309:                 if (m_strOutputFileNameBase!="")
310:                         strOutputFile.Format("%s_%02d.txt",m_strOutputFileNameBase,i);
311:                 else
312:                         strOutputFile="";
313: 
314:                 m_pPuzzleAdminVector[i]=new SUKAdminThread(this,nPos,nPos,m_strConfigFileName,strOutputFile);
315:                 nPos++;
316:                 //nPos--;

317: 
318:                 if (!m_pPuzzleAdminVector[i])
319:                 {
320:                         DeinitThreads();
321:                         return FALSE;
322:                 }
323:         }
324: 
325:         m_bAdminVectorIsInit=TRUE;
326:         return TRUE;
327: }
328: 
329: void CCTPuzzleDlg::DeinitThreads()
330: {
331:         m_bAdminVectorIsInit=FALSE;
332: 
333:         if (m_pPuzzleAdminVector)
334:         {
335:                 for (int i=0;i<m_nThreadCount;i++)
336:                         if (m_pPuzzleAdminVector[i])
337:                         {
338:                                 delete m_pPuzzleAdminVector[i];
339:                                 m_pPuzzleAdminVector[i]=NULL;
340:                         }
341:                 delete[] m_pPuzzleAdminVector;
342:                 m_pPuzzleAdminVector=0;
343:         }
344: }
345: 
346: void CCTPuzzleDlg::OnStart() 
347: {
348:         // TODO: Add your control notification handler code here

349: 
350:         long nStartTime=GetTickCount();
351: 
352:         m_nItemCount=0;
353:         m_nLastItem=0;
354:         m_nState=0;
355: 
356:         if (!InitThreads())
357:         {
358:                 WriteLn("Error on init Threads");
359:                 return;
360:         }
361: 
362:         m_nTimerStart=GetTickCount();
363:         m_nElapsedTime=m_nTimerStart-nStartTime;
364: 
365:         WriteLn("Timeto initialize %.1f sec",m_nElapsedTime/1000.0);
366: 
367:         m_nState=CUKPuzzleAdmin::enRunning;
368:         //SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_BELOW_NORMAL);

369: }
370: 
371: void CCTPuzzleDlg::OnPause() 
372: {
373:         // TODO: Add your control notification handler code here

374:         m_nItemCount=0;
375:         m_nLastItem=0;
376: 
377:         if (!m_bAdminVectorIsInit)        
378:                 return;        
379:         
380:         //SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_HIGHEST);

381: 
382:         for (int i=0;i<m_nThreadCount;i++)
383:         {
384:                 if (m_pPuzzleAdminVector[i] && m_pPuzzleAdminVector[i]->bWasStarted && !m_pPuzzleAdminVector[i]->bWasFinished)
385:                         m_pPuzzleAdminVector[i]->theThread.PausePuzzle();
386:         }
387:         m_nElapsedTime+=(GetTickCount()-m_nTimerStart);
388: 
389:         m_nState=CUKPuzzleAdmin::enPaused;
390: 
391:         //SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_NORMAL);

392: }
393: 
394: void CCTPuzzleDlg::OnContinue() 
395: {
396:         // TODO: Add your control notification handler code here

397:         m_nItemCount=0;
398:         m_nLastItem=0;
399: 
400:         if (!m_bAdminVectorIsInit)        
401:                 return;                
402: 
403:         //SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_HIGHEST);

404: 
405:         m_nTimerStart=GetTickCount();
406: 
407:         for (int i=0;i<m_nThreadCount;i++)
408:         {
409:                 if (m_pPuzzleAdminVector[i] && m_pPuzzleAdminVector[i]->bWasStarted && !m_pPuzzleAdminVector[i]->bWasFinished)
410:                         m_pPuzzleAdminVector[i]->theThread.ContinuePuzzle();
411:         }
412: 
413:         m_nState=CUKPuzzleAdmin::enRunning;
414:         //SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_BELOW_NORMAL);

415: }
416: 
417: void CCTPuzzleDlg::OnStop() 
418: {
419:         int i;
420:         // TODO: Add your control notification handler code here

421:         m_nItemCount=0;
422:         m_nLastItem=0;
423: 
424:         if (!m_bAdminVectorIsInit)        
425:                 return;                
426: 
427:         //SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_HIGHEST);

428: 
429:         BOOL bWasRunning=FALSE;
430:         for (i=0;i<m_nThreadCount;i++)
431:                 if (m_pPuzzleAdminVector[i] && m_pPuzzleAdminVector[i]->bWasStarted && !m_pPuzzleAdminVector[i]->bWasFinished) 
432:                         if (m_pPuzzleAdminVector[i]->theThread.GetProgressState()==CUKPuzzleAdmin::enRunning)
433:                         {
434:                                 //if is running then first stop command pause the process

435:                                 
436:                                 bWasRunning=TRUE;
437:                                 break;
438:                         }
439: 
440:         if (bWasRunning)
441:         {
442:                 OnPause();
443:                 //SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_NORMAL);

444:                 return;
445:         }
446: 
447:         //SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_NORMAL);

448: 
449:         BOOL bError=FALSE;
450:         for (i=0;i<m_nThreadCount;i++)
451:         {
452:                 if (m_pPuzzleAdminVector[i] && m_pPuzzleAdminVector[i]->bWasStarted && !m_pPuzzleAdminVector[i]->bWasFinished)
453:                         if (m_pPuzzleAdminVector[i]->theThread.StopPuzzle()!=UKPUZ_NOERROR)
454:                                 bError=TRUE;
455:         }
456: 
457:         if (bError)
458:                 return;
459: 
460:         DeinitThreads();
461: 
462:         m_nState=0;
463:         m_nTimerStart=0;
464:         m_nElapsedTime=0;
465: }
466: 
467: void __cdecl CCTPuzzleDlg::Write(LPCTSTR strText,...)
468: {
469:         va_list args;
470:         va_start( args, strText);
471: 
472:         CString strTmp;
473:         CString strDlgText;
474:         GetDlgItemText(IDC_OutputText,strDlgText);
475:         strTmp.FormatV(strText,args);
476:         strDlgText+=strTmp;
477:         SetDlgItemText(IDC_OutputText,strDlgText);
478: 
479:         va_end( args);
480: }
481: 
482: void __cdecl CCTPuzzleDlg::WriteLn(LPCTSTR strText,...)
483: {
484:         va_list args;
485:         va_start( args, strText);
486: 
487:         CString strTmp;
488:         CString strDlgText;
489:         GetDlgItemText(IDC_OutputText,strDlgText);
490:         strTmp.FormatV(strText,args);
491:         strDlgText+=strTmp+"\r\n"+m_szPrompt;
492:         SetDlgItemText(IDC_OutputText,strDlgText);
493: 
494:         va_end( args);
495: }
496: 
497: LRESULT CCTPuzzleDlg::OnUKWrite(WPARAM wParam, LPARAM lParam) 
498: {
499:         BSTR bstrText=(BSTR)(LPVOID)lParam;
500:         ASSERT(bstrText);
501:         CString strText(bstrText);
502:         SysFreeString(bstrText);
503:         if (wParam==0)
504:                 Write(strText);
505:         else
506:                 WriteLn(strText);
507:         return 0;
508: }
509: 
510: LRESULT CCTPuzzleDlg::OnUKNotify(WPARAM wParam, LPARAM lParam)
511: {
512:         int i;
513:         switch (wParam)
514:         {
515:                 case enUKPUZZLE_SOLUTIONFOUND:
516:                         break;
517:                 case enUKPUZZLE_FINISHED:
518:                         for (i=0;i<m_nThreadCount;i++)
519:                                 if (m_pPuzzleAdminVector[i])
520:                                         if (!m_pPuzzleAdminVector[i]->bWasFinished && 
521:                                                 m_pPuzzleAdminVector[i]->theThread.GetProgressState()!=CUKPuzzleAdmin::enFinished)
522:                                                 return 0;
523: 
524:                         Beep(2000,500);
525:                         m_nState=CUKPuzzleAdmin::enFinished;
526:                         m_nElapsedTime+=(GetTickCount()-m_nTimerStart);
527:                         m_nTimerStart=GetTickCount();
528:                         break;
529:         }
530: 
531:         return 0;
532: }
533: 
534: void CCTPuzzleDlg::OnCloseDialog() 
535: {
536:         // TODO: Add your control notification handler code here

537:         
538:         PostMessage(WM_CLOSE);
539: }
540: 
541: void CCTPuzzleDlg::OnClose() 
542: {
543:         // TODO: Add your message handler code here and/or call default

544:         //Call it twice, becaus if it is running it will only pause on first call

545:         OnStop();
546:         OnStop();
547: 
548:         if (m_bAdminVectorIsInit && (AfxMessageBox(IDS_ERROR_000,MB_YESNO)==IDNO))
549:                 return;
550:         
551:         if (m_nTimerID1)
552:                 KillTimer(m_nTimerID1);
553:         m_nTimerID1=0;
554: 
555:         if (m_nTimerID2)
556:                 KillTimer(m_nTimerID2);
557:         m_nTimerID2=0;
558: 
559:         CDialog::OnClose();
560: }
561: 
562: void CCTPuzzleDlg::OnTimer(UINT nIDEvent) 
563: {
564:         // TODO: Add your message handler code here and/or call default

565: 
566:         static nCounter=0;
567: 
568:         switch (nIDEvent)
569:         {
570:                 case 1:
571:                         UpdateData(TRUE);
572:                         if (!m_bAdminVectorIsInit)
573:                         {
574:                                 m_strPastTime="0";
575:                                 m_strSolutions="0";
576:                         }
577:                         else
578:                         {
579:                                 int i=0;
580:                                 long nSolutions=0;
581:         
582:                                 CString strTmp;
583: 
584:                                 for (i=0;i<m_nThreadCount;i++)
585:                                 {
586:                                         if (m_pPuzzleAdminVector[i])
587:                                         {
588:                                                 //check if one thread is running and has finished

589:                                                 if (m_pPuzzleAdminVector[i]->bWasStarted && !m_pPuzzleAdminVector[i]->bWasFinished)
590:                                                 {
591:                                                         m_pPuzzleAdminVector[i]->nResultCount=m_pPuzzleAdminVector[i]->theThread.GetSolutions();
592:                                                         if (m_pPuzzleAdminVector[i]->theThread.GetProgressState()==CUKPuzzleAdmin::enFinished)
593:                                                         {
594:                                                                 m_pPuzzleAdminVector[i]->theThread.StopPuzzle();
595:                                                                 m_pPuzzleAdminVector[i]->bWasFinished=TRUE;
596:                                                                 m_nActiveThreads--;
597:                                                                 WriteLn("==> Thread(%d) Stopped ==> %d Threads Running",i,m_nActiveThreads);
598:                                                                 WriteLn("ThreadStat: Elapsed Time=%dsec, Solutions Found=%d",(m_nElapsedTime+GetTickCount()-m_nTimerStart)/1000,m_pPuzzleAdminVector[i]->nResultCount);
599:                                                         }
600:                                                 }
601: 
602:                                                 nSolutions+=m_pPuzzleAdminVector[i]->nResultCount;
603: 
604:                                                 //start next thread

605:                                                 if (m_nActiveThreads<m_nMaxActiveThreads && !m_pPuzzleAdminVector[i]->bWasStarted)
606:                                                 {
607:                                                         m_nActiveThreads++;
608:                                                         if (m_pPuzzleAdminVector[i]->theThread.StartPuzzle()!=UKPUZ_NOERROR)
609:                                                         {
610:                                                                 WriteLn("==> Error on starting Thread(%d)",i);
611:                                                                 OnStop();
612:                                                                 OnStop();
613:                                                                 return;
614:                                                         }
615:                                                         m_pPuzzleAdminVector[i]->bWasStarted=TRUE;
616:                                                         WriteLn("==> Thread(%d) Started ==> %d Threads Running",i,m_nActiveThreads);
617:                                                 }
618:                                         }
619:                                 }
620: 
621:                                 m_nItemCount=min(enSolutionAveraging,m_nItemCount+1);
622:                                 m_nLastItem=(m_nLastItem+1)%enSolutionAveraging;
623:                                 m_nLastResultCount[m_nLastItem]=nSolutions;
624:                                 m_nLastResultTime[m_nLastItem]=GetTickCount();
625: 
626:                                 m_strSolutions.Format("%d    ",nSolutions);
627:                                 DWORD nPastTime=0;
628:                                 CString strInfo;
629: 
630:                                 switch (m_nState)
631:                                 {
632:                                         case CUKPuzzleAdmin::enRunning:                strInfo.LoadString(IDS_RUNNING);nPastTime=m_nElapsedTime+GetTickCount()-m_nTimerStart; break;
633:                                         case CUKPuzzleAdmin::enPaused:                strInfo.LoadString(IDS_PAUSED);nPastTime=m_nElapsedTime; break;
634:                                         case CUKPuzzleAdmin::enFinished:        strInfo.LoadString(IDS_FINISHED);nPastTime=m_nElapsedTime; break;
635:                                         default:                                                        strInfo="unkwown";nPastTime=0; break;
636:                                 }
637:                                 m_strPastTime.Format("%dh %dmin %4.0fsec (%s)    ",nPastTime/3600000,(nPastTime%3600000)/60000,(nPastTime%60000)/1000.0,(LPCTSTR)strInfo);
638: 
639:                                 if (nPastTime>0)
640:                                         m_strSolutionsPerSecond.Format("%.1f    ",nSolutions/(nPastTime/1000.0));
641:                                 else
642:                                         m_strSolutionsPerSecond="0    ";
643: 
644:                                 if (m_nItemCount > 1)
645:                                 {
646:                                         long nDCount=m_nLastResultCount[m_nLastItem]-m_nLastResultCount[(m_nLastItem-m_nItemCount+1+enSolutionAveraging)%enSolutionAveraging];
647:                                         long nDTime=m_nLastResultTime[m_nLastItem]-m_nLastResultTime[(m_nLastItem-m_nItemCount+1+enSolutionAveraging)%enSolutionAveraging];
648: 
649:                                         if (nDCount>0)
650:                                                 m_strSolutionsPerSecond2.Format("%.1f    ",(nDCount*1000.0)/nDTime);
651:                                         else
652:                                                 m_strSolutionsPerSecond2="0    ";
653:                                 }
654:                         }
655:                         UpdateData(FALSE);
656:                         nCounter++;
657:                         if (nCounter==3)
658:                         {
659:                                 InvalidateRect(NULL);
660:                                 nCounter=0;
661:                         }
662:                         break;
663:                 case 2:
664:                         UpdateDialogControls(this,FALSE);
665:                         break;
666:         }
667: 
668:         CDialog::OnTimer(nIDEvent);
669: }
670: 
671: void CCTPuzzleDlg::OnUpdateButtonStop(CCmdUI* pCmdUI)
672: {
673:         if (m_bAdminVectorIsInit)
674:                 pCmdUI->Enable(TRUE);
675:         else
676:                 pCmdUI->Enable(FALSE);
677: }
678: 
679: void CCTPuzzleDlg::OnUpdateButtonStart(CCmdUI* pCmdUI)
680: {
681:         if (m_bAdminVectorIsInit)
682:                 pCmdUI->Enable(FALSE);
683:         else
684:                 pCmdUI->Enable(TRUE);
685: }
686: 
687: void CCTPuzzleDlg::OnUpdateButtonPause(CCmdUI* pCmdUI)
688: {
689:         if (m_pPuzzleAdminVector)
690:                 for (int i=0;i<m_nThreadCount;i++)
691:                         if (m_pPuzzleAdminVector[i] && m_pPuzzleAdminVector[i]->bWasStarted && !m_pPuzzleAdminVector[i]->bWasFinished)
692:                                 if (m_pPuzzleAdminVector[i]->theThread.GetProgressState()==CUKPuzzleAdmin::enRunning)
693:                                 {
694:                                         pCmdUI->Enable(TRUE);
695:                                         return;
696:                                 }
697:         
698:         pCmdUI->Enable(FALSE);
699: }
700: 
701: 
702: void CCTPuzzleDlg::OnUpdateLoadConfig(CCmdUI* pCmdUI)
703: {
704:         //Can only load config if puzzle is not already startet

705:         if (m_bAdminVectorIsInit)
706:                 pCmdUI->Enable(FALSE);
707:         else
708:                 pCmdUI->Enable(TRUE);
709: }
710: 
711: void CCTPuzzleDlg::OnUpdateButtonContinue(CCmdUI* pCmdUI)
712: {
713:         if (m_pPuzzleAdminVector)
714:                 for (int i=0;i<m_nThreadCount;i++)
715:                         if (m_pPuzzleAdminVector[i] && m_pPuzzleAdminVector[i]->bWasStarted && !m_pPuzzleAdminVector[i]->bWasFinished)
716:                                 if (m_pPuzzleAdminVector[i]->theThread.GetProgressState()==CUKPuzzleAdmin::enPaused)
717:                                 {
718:                                         pCmdUI->Enable(TRUE);
719:                                         return;
720:                                 }
721: 
722:         pCmdUI->Enable(FALSE);
723: }
724: 
725: 
726: 
727: void CCTPuzzleDlg::OnLoadConfig() 
728: {
729:         // TODO: Add your control notification handler code here

730:         CFileDialog theDlg(TRUE,"ini",m_strConfigFileName,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,"Ini Dateien (*.ini)|*.ini|Alle Dateien (*.*)|*.*||");
731: 
732:         if (theDlg.DoModal()==IDOK)
733:         {
734:                 m_strConfigFileName=theDlg.GetPathName();
735:                 WriteLn("Active configuration file = %s",(LPCTSTR)m_strConfigFileName);
736:         }
737: }