import SK_PUZZLE_PKG:Model:*; class PuzzleModel /******************************************************* P R O P E R T I E S *******************************************************/ property string PuzzleId get set; property string Description get set; property number ElapsedTime get set; property array of any PuzzleCells; /********************************************************* C O N S T R U C T O R D E C L A R A T I O N *********************************************************/ method PuzzleModel(); /******************************************************* P U B L I C M E T H O D D E C L A I R A T I O N *******************************************************/ method getPuzzle(&p_strPuzzleId As string); method savePuzzle(); method checkCollisionsInPuzzle() Returns array of number; method isPuzzleSolved() Returns boolean; private /******************************************************* P R I V A T E M E T H O D D E C L A I R A T I O N *******************************************************/ method getCells(&p_strPuzzleId As string); method putCells(&p_nbrCellNumber As number, &p_nbrCellValue As number); method getFirstCellInRow(&p_nbrCellNumber As number) Returns number; method getNextCellInRow(&p_nbrCellNumber As number) Returns number; method getLastCellInRow(&p_nbrCellNumber As number) Returns number; method getFirstCellInColumn(&p_nbrCellNumber As number) Returns number; method getNextCellInColumn(&p_nbrCellNumber As number) Returns number; method getLastCellInColumn(&p_nbrCellNumber As number) Returns number; method getFirstCellInBox(&p_nbrCellNumber As number) Returns number; method getNextCellInBox(&p_nbrCellNumber As number) Returns number; method getLastCellInBox(&p_nbrCellNumber As number) Returns number; method checkCollisionsInRow(&p_nbrCellNumber As number) Returns array of number; method checkCollisionsInColumn(&p_nbrCellNumber As number) Returns array of number; method checkCollisionsInBox(&p_nbrCellNumber As number) Returns array of number; /******************************************************* P R I V A T E I N S T A N C E V A R I A B L E S *******************************************************/ instance string &i_strSkPuzzleId; instance string &i_strSkDescr; instance number &i_nbrSkElapsedTime; end-class; /* PuzzleModel */ /********************************************************* C O N S T R U C T O R M E T H O D *********************************************************/ method PuzzleModel end-method; /* PuzzleModel */ /******************************************************* G E T T E R M E T H O D S *******************************************************/ /******************************* Getter Method PuzzleId ******************************/ get PuzzleId /+ Returns String +/ Return &i_strSkPuzzleId; end-get; /* PuzzleId */ /******************************* Getter Method Description ******************************/ get Description /+ Returns String +/ Return &i_strSkDescr; end-get; /* Description */ /******************************* Getter Method ElapsedTime ******************************/ get ElapsedTime /+ Returns Number +/ Return &i_nbrSkElapsedTime; end-get; /* ElapsedTime */ /******************************************************* S E T T E R M E T H O D S *******************************************************/ /******************************* Setter Method PuzzleId ******************************/ set PuzzleId /+ &NewValue as String +/ &i_strSkPuzzleId = &NewValue; end-set; /* PuzzleId */ /******************************* Setter Method Description ******************************/ set Description /+ &NewValue as String +/ &i_strSkDescr = &NewValue; end-set; /* Description */ /******************************* Setter Method ElapsedTime ******************************/ set ElapsedTime /+ &NewValue as Number +/ &i_nbrSkElapsedTime = &NewValue; end-set; /* ElapsedTime */ /******************************************************* P U B L I C M E T H O D S *******************************************************/ /******************************* Method getPuzzle ******************************/ method getPuzzle /+ &p_strPuzzleId as String +/ Local number &i; Local Record &recSkPuzzleTbl; &recSkPuzzleTbl = CreateRecord(Record.SK_PUZZLE_TBL); &recSkPuzzleTbl.SK_PUZZLE_ID.Value = &p_strPuzzleId; If &recSkPuzzleTbl.SelectByKey() Then %This.PuzzleId = &p_strPuzzleId; %This.Description = &recSkPuzzleTbl.SK_DESCR.Value; %This.ElapsedTime = &recSkPuzzleTbl.SK_ELAPSED_TIME.Value; %This.PuzzleCells = CreateArray(); For &i = 1 To 81 %This.PuzzleCells [&i] = create SK_PUZZLE_PKG:Model:CellModel(&i, 0, False); End-For; %This.getCells(&p_strPuzzleId); End-If; end-method; /* getPuzzle */ /******************************* Method savePuzzle ******************************/ method savePuzzle Local number &i; Local Record &recSkPuzzleTbl; &recSkPuzzleTbl = CreateRecord(Record.SK_PUZZLE_TBL); &recSkPuzzleTbl.SK_PUZZLE_ID.Value = %This.PuzzleId; &recSkPuzzleTbl.SK_DESCR.Value = %This.Description; &recSkPuzzleTbl.SK_ELAPSED_TIME.Value = %This.ElapsedTime; &recSkPuzzleTbl.Update(); For &i = 1 To %This.PuzzleCells.Len If %This.PuzzleCells [&i].GivenValue = "N" Then %This.putCells(&i, %This.PuzzleCells [&i].CellValue); End-If; End-For; DoSave(); end-method; /* savePuzzle */ /******************************* Method checkCollisionsInPuzzle ******************************/ method checkCollisionsInPuzzle /+ Returns Array of Number +/ Local number &i, &nbrCellIndex; Local array of number &arrCollidedCells, &arrTempArray; &arrCollidedCells = CreateArrayRept(0, 0); For &nbrCellIndex = 1 To 81 &arrTempArray = %This.checkCollisionsInRow(&nbrCellIndex); For &i = 1 To &arrTempArray.Len If &arrCollidedCells.Find(&arrTempArray [&i]) = 0 Then &arrCollidedCells.Push(&arrTempArray [&i]); End-If; End-For; &arrTempArray = %This.checkCollisionsInColumn(&nbrCellIndex); For &i = 1 To &arrTempArray.Len If &arrCollidedCells.Find(&arrTempArray [&i]) = 0 Then &arrCollidedCells.Push(&arrTempArray [&i]); End-If; End-For; &arrTempArray = %This.checkCollisionsInBox(&nbrCellIndex); For &i = 1 To &arrTempArray.Len If &arrCollidedCells.Find(&arrTempArray [&i]) = 0 Then &arrCollidedCells.Push(&arrTempArray [&i]); End-If; End-For; End-For; Return &arrCollidedCells; end-method; /* checkCollisionsInPuzzle */ /******************************* Method isPuzzleSolved ******************************/ method isPuzzleSolved /+ Returns Boolean +/ Local number &i; Local boolean &blnReturnValue; &blnReturnValue = True; For &i = 1 To %This.PuzzleCells.Len If %This.PuzzleCells [&i].CellValue = 0 Then &blnReturnValue = False; Break; End-If; End-For; Return &blnReturnValue; end-method; /* isPuzzleSolved */ /******************************************************* P R I V A T E M E T H O D S *******************************************************/ /******************************* Method getCells ******************************/ method getCells /+ &p_strPuzzleId as String +/ Local number &nbrSkCellNbr; Local number &nbrSkCellValue; Local string &strSkGivenValue; Local SQL &SQL; &SQL = GetSQL(SQL.SK_CELL_SQL, &p_strPuzzleId); While &SQL.Fetch(&nbrSkCellNbr, &nbrSkCellValue, &strSkGivenValue); %This.PuzzleCells [&nbrSkCellNbr].CellNumber = &nbrSkCellNbr; %This.PuzzleCells [&nbrSkCellNbr].CellValue = &nbrSkCellValue; If &strSkGivenValue = "Y" Then %This.PuzzleCells [&nbrSkCellNbr].GivenValue = True Else %This.PuzzleCells [&nbrSkCellNbr].GivenValue = False End-If; End-While; end-method; /* getCells */ /******************************* Method putCells ******************************/ method putCells /+ &p_nbrCellNumber as Number, +/ /+ &p_nbrCellValue as Number +/ Local Record &recSkCellsTbl; &recSkCellsTbl = CreateRecord(Record.SK_CELLS_TBL); &recSkCellsTbl.SK_PUZZLE_ID.Value = %This.PuzzleId; &recSkCellsTbl.SK_CELL_NBR.Value = &p_nbrCellNumber; &recSkCellsTbl.SK_CELL_VALUE.Value = &p_nbrCellValue; &recSkCellsTbl.SK_GIVEN_FLG.Value = "N"; If &p_nbrCellValue = 0 Then &recSkCellsTbl.Delete(); Else If &recSkCellsTbl.Insert() Then /* Nothing */ Else &recSkCellsTbl.Update(); End-If; End-If; end-method; /* putCells */ /******************************* Method getFirstCellInRow ******************************/ method getFirstCellInRow /+ &p_nbrCellNumber as Number +/ /+ Returns Number +/ Local number &nbrMod9; &nbrMod9 = Mod(&p_nbrCellNumber, 9); If &nbrMod9 = 0 Then &nbrMod9 = 9; End-If; Return &p_nbrCellNumber - &nbrMod9 + 1; end-method; /* getFirstCellInRow */ /******************************* Method getNextCellInRow ******************************/ method getNextCellInRow /+ &p_nbrCellNumber as Number +/ /+ Returns Number +/ Return &p_nbrCellNumber + 1; end-method; /* getNextCellInRow */ /******************************* Method getLastCellInRow ******************************/ method getLastCellInRow /+ &p_nbrCellNumber as Number +/ /+ Returns Number +/ Return %This.getFirstCellInRow(&p_nbrCellNumber) + 8; end-method; /* getLastCellInRow */ /******************************* Method getFirstCellInColumn ******************************/ method getFirstCellInColumn /+ &p_nbrCellNumber as Number +/ /+ Returns Number +/ Local number &nbrMod9; &nbrMod9 = Mod(&p_nbrCellNumber, 9); If &nbrMod9 = 0 Then &nbrMod9 = 9; End-If; Return &nbrMod9; end-method; /* getFirstCellInColumn */ /******************************* Method getNextCellInColumn ******************************/ method getNextCellInColumn /+ &p_nbrCellNumber as Number +/ /+ Returns Number +/ Local number &nbrReturn; &nbrReturn = &p_nbrCellNumber + 9; Return &nbrReturn; end-method; /* getNextCellInColumn */ /******************************* Method getLastCellInColumn ******************************/ method getLastCellInColumn /+ &p_nbrCellNumber as Number +/ /+ Returns Number +/ Return %This.getFirstCellInColumn(&p_nbrCellNumber) + 72; end-method; /* getLastCellInColumn */ /******************************* Method getFirstCellInBox ******************************/ method getFirstCellInBox /+ &p_nbrCellNumber as Number +/ /+ Returns Number +/ Local number &nbrSectionDown, &nbrSectionAccross, &nbrColumn, &nbrStartCell; &nbrSectionDown = Int(((&p_nbrCellNumber - 1) / 27) + 1); &nbrColumn = Mod(&p_nbrCellNumber, 9); If &nbrColumn = 0 Then &nbrColumn = 9; End-If; &nbrSectionAccross = Int(((&nbrColumn - 1) / 3) + 1); &nbrStartCell = ((&nbrSectionDown * 27) + 1 - 27) + ((&nbrSectionAccross - 1) * 3); Return &nbrStartCell; end-method; /* getFirstCellInBox */ /******************************* Method getNextCellInBox ******************************/ method getNextCellInBox /+ &p_nbrCellNumber as Number +/ /+ Returns Number +/ Local number &nbrReturn; &nbrReturn = 0; If Mod(&p_nbrCellNumber, 3) = 0 Then &nbrReturn = &p_nbrCellNumber + 7; Else &nbrReturn = &p_nbrCellNumber + 1; End-If; Return &nbrReturn; end-method; /* getNextCellInBox */ /******************************* Method getLastCellInBox ******************************/ method getLastCellInBox /+ &p_nbrCellNumber as Number +/ /+ Returns Number +/ Return %This.getFirstCellInBox(&p_nbrCellNumber) + 20; end-method; /* getLastCellInBox */ /******************************* Method checkCollisionsInRow ******************************/ method checkCollisionsInRow /+ &p_nbrCellNumber as Number +/ /+ Returns Array of Number +/ Local number &nbrCellIndex, &nbrLastCellInRow; Local array of number &arrCollidedCells; &arrCollidedCells = CreateArrayRept(0, 0); If %This.PuzzleCells [&p_nbrCellNumber].CellValue = 0 Then /* No need to check colliions when value is zero */ Else &nbrCellIndex = %This.getFirstCellInRow(&p_nbrCellNumber); &nbrLastCellInRow = %This.getLastCellInRow(&p_nbrCellNumber); While &nbrCellIndex <= &nbrLastCellInRow If &nbrCellIndex = &p_nbrCellNumber Then /* Nothing */; Else If %This.PuzzleCells [&nbrCellIndex].CellValue = %This.PuzzleCells [&p_nbrCellNumber].CellValue Then &arrCollidedCells.Push(&nbrCellIndex); Else /* Nothing */ End-If; End-If; &nbrCellIndex = %This.getNextCellInRow(&nbrCellIndex); End-While; End-If; Return &arrCollidedCells; end-method; /* checkCollisionsInRow */ /******************************* Method checkCollisionsInColumn ******************************/ method checkCollisionsInColumn /+ &p_nbrCellNumber as Number +/ /+ Returns Array of Number +/ Local number &nbrCellIndex, &nbrLastCellInColumn; Local array of number &arrCollidedCells; &arrCollidedCells = CreateArrayRept(0, 0); If %This.PuzzleCells [&p_nbrCellNumber].CellValue = 0 Then /* No need to check colliions when value is zero */ Else &nbrCellIndex = %This.getFirstCellInColumn(&p_nbrCellNumber); &nbrLastCellInColumn = %This.getLastCellInColumn(&p_nbrCellNumber); While &nbrCellIndex <= &nbrLastCellInColumn If &nbrCellIndex = &p_nbrCellNumber Then /* Nothing */ Else If %This.PuzzleCells [&p_nbrCellNumber].CellValue = %This.PuzzleCells [&nbrCellIndex].CellValue Then &arrCollidedCells.Push(&nbrCellIndex); Else /* Nothing */ End-If; End-If; &nbrCellIndex = %This.getNextCellInColumn(&nbrCellIndex); End-While; End-If; Return &arrCollidedCells; end-method; /* checkCollisionsInColumn */ /******************************* Method checkCollisionsInBox ******************************/ method checkCollisionsInBox /+ &p_nbrCellNumber as Number +/ /+ Returns Array of Number +/ Local number &nbrCellIndex, &nbrLastCellInBox; Local array of number &arrCollidedCells; &arrCollidedCells = CreateArrayRept(0, 0); If %This.PuzzleCells [&p_nbrCellNumber].CellValue = 0 Then /* No need to check colliions when value is zero */ Else &nbrCellIndex = %This.getFirstCellInBox(&p_nbrCellNumber); &nbrLastCellInBox = %This.getLastCellInBox(&p_nbrCellNumber); While &nbrCellIndex <= &nbrLastCellInBox If &nbrCellIndex = &p_nbrCellNumber Then /* Nothing */ Else If %This.PuzzleCells [&p_nbrCellNumber].CellValue = %This.PuzzleCells [&nbrCellIndex].CellValue Then &arrCollidedCells.Push(&nbrCellIndex); Else /* Nothing */ End-If; End-If; &nbrCellIndex = %This.getNextCellInBox(&nbrCellIndex); End-While; End-If; Return &arrCollidedCells; end-method; /* checkCollisionsInBox */