diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java index 09887697b5..5163ede509 100644 --- a/src/com/android/launcher3/CellLayout.java +++ b/src/com/android/launcher3/CellLayout.java @@ -85,6 +85,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; +import java.util.List; import java.util.Stack; public class CellLayout extends ViewGroup { @@ -891,7 +892,7 @@ public class CellLayout extends ViewGroup { * * @param result Array of 2 ints to hold the x and y coordinate of the point */ - void regionToCenterPoint(int cellX, int cellY, int spanX, int spanY, int[] result) { + public void regionToCenterPoint(int cellX, int cellY, int spanX, int spanY, int[] result) { cellToRect(cellX, cellY, spanX, spanY, mTempRect); result[0] = mTempRect.centerX(); result[1] = mTempRect.centerY(); @@ -2340,7 +2341,16 @@ public class CellLayout extends ViewGroup { } Rect r0 = new Rect(cellX, cellY, cellX + spanX, cellY + spanY); Rect r1 = new Rect(); - for (View child: solution.map.keySet()) { + // The views need to be sorted so that the results are deterministic on the views positions + // and not by the views hash which is "random". + // The views are sorted twice, once for the X position and a second time for the Y position + // to ensure same order everytime. + Comparator comparator = Comparator.comparing(view -> + ((CellLayoutLayoutParams) ((View) view).getLayoutParams()).getCellX()) + .thenComparing(view -> + ((CellLayoutLayoutParams) ((View) view).getLayoutParams()).getCellY()); + List views = solution.map.keySet().stream().sorted(comparator).toList(); + for (View child : views) { if (child == ignoreView) continue; CellAndSpan c = solution.map.get(child); CellLayoutLayoutParams lp = (CellLayoutLayoutParams) child.getLayoutParams(); diff --git a/tests/assets/ReorderAlgorithmUnitTest/reorder_algorithm_test_cases b/tests/assets/ReorderAlgorithmUnitTest/reorder_algorithm_test_cases new file mode 100644 index 0000000000..6f92d6c7a8 --- /dev/null +++ b/tests/assets/ReorderAlgorithmUnitTest/reorder_algorithm_test_cases @@ -0,0 +1,1804 @@ +################################################################################################### +# This file contains test case composed of the following tags: +# * # (coments): Lines starting with this character would be ignored. +# * arguments: is set of words separated by spaces that can later be parsed +# * board: represent a workspace, the first line is the dimensions of the board width x height (wxh) +# There are different characters on the board that represent different things: +# * x: The x character represents spaces that would be ignored, for example it can be used in +# the first row if we don't know how wide the smartspace is. +# * i: Represents an icon on the workspace, none in particular just an icon +# * [a-z]: Represents a widget and it can be any number or character +# except any other already in use. The whole continuos are of the same character is the +# area of the widget. +# * [A-Z]: Represents a folder and number of icons in the folder is represented by the order of +# letter in the alphabet, A=2, B=3, C=4 ... etc. +# +# The "arguments:" tag represents where you want to add an item, the format is: +# "x y spanX spanY minSpanX minSpanY type ifSolutionIsPossible" +# +# Test are parsed by CellLayoutTestCaseReader.java and boards are parsed by CellLayoutBoard.java +################################################################################################### +# Test 0 +board: 7x10 +-----de +-----de +-----di +-----ii +-----ii +-----ci +-----ci +-----ii +aaaaaai +iibbbbi +# This represents where you want to add an item, the format is "x y spanX spanY minSpanX minSpanY type ifSolutionIsPossible" +arguments: 1 3 5 4 4 1 widget valid +board: 7x10 +-----cb +-----cb +-----ci +izzzzzi +izzzzzi +azzzzzi +azzzzzi +-----ii +ddddddi +iieeeei +# Test 1 +board: 9x10 +aaaaaaaai +i-----hhj +c-----hhj +c-----hhi +c-----iii +i-----iii +beddddddi +befffffii +iifffffii +iiggggggi +arguments: 3 3 4 6 1 2 widget valid +board: 9x10 +ggggggggi +i-zzzzffe +h-zzzzffe +h-zzzzffi +h-zzzziii +i-zzzziii +dcbbbbbbi +dcaaaaaii +iiaaaaaii +iijjjjjji +# Test 2 +board: 7x6 +aiii--f +acci--f +addi--f +iebi--i +iebiiii +iiiiiii +arguments: 1 1 1 1 1 1 icon valid +board: 7x6 +aiii--f +azeei-f +abbi--f +icdi--i +icdiiii +iiiiiii +# Test 3 +board: 4x10 +-ibg +-ibg +-ibi +-idf +-cdf +-cdi +-cei +-cei +-iii +aaai +arguments: 2 1 1 5 1 1 widget valid +board: 4x10 +if-c +ifzc +ifzi +igzb +egzb +egzi +e-di +e-di +-iii +aaai +# Test 4 +board: 8x8 +i---c--- +a---c--- +a---i--- +ibbbi--- +-------- +-------- +----i--- +ii--i--- +arguments: 1 1 3 6 1 4 widget valid +board: 8x8 +i---c--- +azzzc--- +azzzi--- +izzzbbbi +-zzz---- +-zzz---- +-zzzi--- +ii--i--- +# Test 5 +board: 10x8 +aaaaaaaaai +bbbbbcciii +---------f +---------f +---------f +---------i +iiddddddii +iieeiiiiii +arguments: 2 5 7 1 3 1 widget valid +board: 10x8 +bbbbbbbbbi +eeeeecciii +---------a +---------a +---------a +--zzzzzzzi +iiddddddii +iiffiiiiii +# Test 6 +board: 8x7 +-------i +bbcaaaah +bbcaaaah +bbcaaaai +bbcddddi +bbieeeii +iiiffggi +arguments: 5 1 1 2 1 1 icon valid +board: 8x7 +-----z-i +bbfaaaad +bbfaaaad +bbfaaaai +bbfhhhhi +bbigggii +iiieecci +# Test 7 +board: 10x3 +ii-------i +---------- +-ii----iii +arguments: 1 0 7 1 2 1 widget valid +board: 10x3 +izzzzzzzii +---------- +-ii----iii +# Test 8 +board: 8x9 +aaaaaiii +ibbbbbii +-----ffi +-----eei +-----hhi +-----ggi +-----jji +iiccccii +iidddddi +arguments: 2 2 5 2 3 1 widget valid +board: 8x9 +fffffiii +ihhhhhii +bbzzzzzi +jjzzzzzi +-----ggi +-----cci +-----aai +iiddddii +iieeeeei +# Test 9 +board: 4x8 +--ci +--cd +--cd +--ci +--ii +aaai +aaai +bbbi +arguments: 1 4 2 1 2 1 widget valid +board: 4x8 +--bi +--bc +--bc +--bi +izzi +aaai +aaai +dddi +# Test 10 +board: 8x3 +i----cci +iaaaaaai +iiibbbbi +arguments: 2 1 2 1 1 1 widget valid +board: 8x3 +i-zz-cci +ibbbbbbi +iiiaaaai +# Test 11 +board: 5x10 +----- +----- +----- +----- +----- +----- +----- +----- +i---i +iaaai +arguments: 0 3 3 6 1 2 widget valid +board: 5x10 +----- +----- +----- +zzz-- +zzz-- +zzz-- +zzz-- +zzz-- +zzzii +iaaai +# Test 12 +board: 6x10 +aad-ii +aad-ii +aai-eg +aac-eg +aac-ei +aac-ef +aai-ef +aai-ei +aai-ii +bbiiii +arguments: 1 5 1 4 1 3 widget valid +board: 6x10 +ccb-ii +ccb-ii +cci-fa +cce-fa +cce-fi +ccezfg +ccizfg +ccizfi +ccizii +ddiiii +# Test 13 +board: 10x10 +iaaaaaaiii +i-------ii +i-------ii +i-------ei +i-------ei +b-------ei +b-------ei +b-------ii +biccccccci +iiddddddii +arguments: 0 2 6 1 3 1 widget valid +board: 10x10 +iaaaaaaiii +i-------ii +zzzzzzi-ii +i-------ci +i-------ci +e-------ci +e-------ci +e-------ii +eibbbbbbbi +iiddddddii +# Test 14 +board: 3x6 +--a +--a +--a +--a +--i +iii +arguments: 0 2 1 3 1 3 widget valid +board: 3x6 +--a +--a +z-a +z-a +z-i +iii +# Test 15 +board: 6x7 +------ +-i---i +-i---c +ia---c +ia---i +ia---i +iibbbi +arguments: 2 0 2 3 2 1 widget valid +board: 6x7 +--zz-- +-izz-i +-izz-b +ia---b +ia---i +ia---i +iiccci +# Test 16 +board: 8x6 +bbbiiddi +icccccci +aaaggiii +eeeeeffi +ii----ii +iiihhhhi +arguments: 3 3 2 1 1 1 widget valid +board: 8x6 +ccciiffi +ieeeeeei +ggghhiii +aaaaaddi +ii-zz-ii +iiibbbbi +# Test 17 +board: 4x9 +---i +---i +---d +---d +---i +---i +ibbi +iaai +icci +arguments: 0 2 1 6 1 1 widget valid +board: 4x9 +i--i +i--i +z--d +z--d +z--i +z--i +zaai +zbbi +icci +# Test 18 +board: 7x5 +iaaaaai +----iii +----iii +iiibbbi +iiiccii +arguments: 2 0 4 1 3 1 widget valid +board: 7x5 +ibbbbbi +zzzziii +----iii +iiiccci +iiiaaii +# Test 19 +board: 6x4 +aaaaii +bbi--i +cci--i +iiiddi +arguments: 4 0 1 2 1 1 widget valid +board: 6x4 +cccczi +aai-zi +bbi-ii +iiiddi +# Test 20 +board: 8x5 +bbiaeeei +bbiaiffi +cciddddi +----hhii +iigggggi +arguments: 0 1 1 3 1 1 widget valid +board: 8x5 +bbieccci +bbieiddi +z-iffffi +zaa-ggii +iihhhhhi +# Test 21 +board: 5x4 +i--ii +a--ii +aicci +iibbi +arguments: 1 2 2 1 1 1 widget valid +board: 5x4 +iaaii +bi-ii +bzz-i +iicci +# Test 22 +board: 4x10 +---i +---d +---d +---d +---i +aaai +aaai +aaai +bbbi +ccci +arguments: 2 0 1 1 1 1 icon valid +board: 4x10 +--zi +---d +---d +---d +---i +bbbi +bbbi +bbbi +ccci +aaai +# Test 23 +board: 10x10 +---------- +---------- +---------- +---------- +---------- +---------- +---------- +---------- +---------- +--aaai---i +arguments: 0 0 8 5 5 4 widget valid +board: 10x10 +zzzzzzzz-- +zzzzzzzz-- +zzzzzzzz-- +zzzzzzzz-- +zzzzzzzz-- +---------- +---------- +---------- +---------- +--aaai---i +# Test 24 +board: 4x9 +---b +---b +---b +---b +---b +---c +---c +---i +iaai +arguments: 2 0 1 2 1 1 widget valid +board: 4x9 +--zc +--zc +---c +---c +---c +---a +---a +---i +ibbi +# Test 25 +board: 4x5 +-cci +-bbi +-bbi +-iii +iaai +arguments: 0 1 1 1 1 1 icon valid +board: 4x5 +-bbi +zaai +-aai +-iii +icci +# Test 26 +board: 7x3 +a-----i +a-----i +ibbbbbi +arguments: 0 0 2 1 1 1 widget valid +board: 7x3 +zza---i +--a---i +ibbbbbi +# Test 27 +board: 8x6 +i-----di +------di +------ii +--bbbbii +i-iiccci +i--iiaai +arguments: 5 1 2 3 1 1 widget valid +board: 8x6 +i---d--i +----dzzi +----izzi +aaaaizzi +i-iiccci +i--iibbi +# Test 28 +board: 4x7 +---i +---i +---a +---a +---a +---i +iiii +arguments: 1 2 1 3 1 3 widget valid +board: 4x7 +---i +---i +-z-a +-z-a +-z-a +---i +iiii +# Test 29 +board: 5x10 +ii--b +ii--b +ai--i +ai--i +iiiii +----- +----- +----- +----- +----- +arguments: 1 2 2 5 1 4 widget valid +board: 5x10 +ii--a +ii--a +bzz-i +bzz-i +izzii +-zz-- +-zz-- +-i--- +-i--- +-ii-- +# Test 30 +board: 10x4 +a--------i +a--------i +i--------i +ibbbbbicci +arguments: 7 1 1 2 1 2 widget valid +board: 10x4 +b--------i +b------z-i +i------z-i +iaaaaaicci +# Test 31 +board: 5x3 +a--ii +a--ii +iiiii +arguments: 1 0 3 1 2 1 widget valid +board: 5x3 +azzzi +a-iii +iiiii +# Test 32 +board: 5x9 +----- +----- +----- +----- +----i +----b +----b +----i +aaaii +arguments: 1 0 2 7 2 1 widget valid +board: 5x9 +-zz-- +-zz-- +-zz-- +-zz-- +-zz-i +-zz-a +-zz-a +----i +bbbii +# Test 33 +board: 4x8 +icci +aaai +aaai +iiii +ibbi +---i +---i +dddi +arguments: 2 1 1 6 1 5 icon invalid +board: 4x8 +---- +---- +---- +---- +---- +---- +---- +---- +# Test 34 +board: 7x3 +------i +------i +iaaiiii +arguments: 0 1 4 1 1 1 widget valid +board: 7x3 +------i +zzzz--i +iaaiiii +# Test 35 +board: 5x4 +ii-bi +ai-bi +ai-ii +iiiii +arguments: 1 1 2 1 2 1 widget valid +board: 5x4 +iiiai +bzzai +bi-ii +iiiii +# Test 36 +board: 9x7 +iii--iiii +aai--bbbi +aai--bbbi +aai--ccii +iiiiiiiii +--------- +--------- +arguments: 1 1 6 2 4 2 widget valid +board: 9x7 +iii--iiii +-zzzzzz-i +-zzzzzz-i +bbi--aaai +bbiiiaaai +bbi--cci- +iii--iii- +# Test 37 +board: 6x9 +aai--i +-iii-i +iiiiii +-i---- +-ibbbi +-ibbbi +-iccci +-i---i +iidddi +arguments: 2 2 3 1 2 1 widget valid +board: 6x9 +ddi--i +-iii-i +iizzzi +-iiii- +-iaaai +-iaaai +-iccci +-i---i +iibbbi +# Test 38 +board: 10x6 +---------- +---------- +---------- +---------- +---------- +---------- +arguments: 0 0 6 4 1 2 widget valid +board: 10x6 +zzzzzz---- +zzzzzz---- +zzzzzz---- +zzzzzz---- +---------- +---------- +# Test 39 +board: 3x9 +-bc +-bc +-bd +-bd +-bi +-bi +-ii +aai +iii +arguments: 0 1 1 6 1 4 widget valid +board: 3x9 +-bd +zbd +zbc +zbc +zbi +zbi +zii +aai +iii +# Test 40 +board: 3x3 +--i +--i +aai +arguments: 1 0 1 1 1 1 icon valid +board: 3x3 +-zi +--i +aai +# Test 41 +board: 6x3 +-----i +------ +--i--- +arguments: 0 1 4 1 3 1 widget valid +board: 6x3 +-----i +zzzz-- +--i--- +# Test 42 +board: 5x5 +iaaai +---ii +iibbi +iicci +iiiii +arguments: 1 0 1 2 1 2 icon invalid +board: 5x5 +----- +----- +----- +----- +----- +# Test 43 +board: 3x6 +--i +--i +--b +--b +--i +aai +arguments: 1 2 1 3 1 3 widget valid +board: 3x6 +--i +--i +-za +-za +-zi +bbi +# Test 44 +board: 4x8 +---a +---a +---a +---a +---a +---i +iiii +iiii +arguments: 2 2 1 3 1 3 widget valid +board: 4x8 +---a +---a +--za +--za +--za +---i +iiii +iiii +# Test 45 +board: 9x9 +i-----kki +i-----kki +a-----kki +a-----kki +i-----lli +iicccibbj +idiffibbj +ideeiibbi +iigggihhi +arguments: 2 1 5 3 4 2 widget valid +board: 9x9 +i-----lli +izzzzzlli +fzzzzzlli +fzzzzzlli +i-----jji +iihhhikke +igiccikke +igbbiikki +iiaaaiddi +# Test 46 +board: 9x5 +ab---iggi +ab---iffi +ab---eeei +aicccccci +iiiidddii +arguments: 1 0 2 3 1 3 widget valid +board: 9x5 +bzze-iffi +bzze-iaai +bzze-dddi +bicccccci +iiiigggii +# Test 47 +board: 5x6 +ai--b +ai--b +ai--i +ai--i +iiiii +iiiii +arguments: 2 4 2 1 2 1 widget valid +board: 5x6 +bi--a +bi--a +bi--i +biiii +iizzi +iiiii +# Test 48 +board: 5x4 +----- +-i--- +----i +-iiii +arguments: 1 0 3 2 2 1 widget valid +board: 5x4 +-zzz- +-zzzi +----i +-iiii +# Test 49 +board: 6x3 +i---ii +i---ii +iiaaai +arguments: 2 0 1 1 1 1 icon valid +board: 6x3 +i-z-ii +i---ii +iiaaai +# Test 50 +board: 8x9 +-------- +-------- +-------- +-------- +-------- +-------- +-------- +-------- +-------- +arguments: 1 1 6 7 3 1 widget valid +board: 8x9 +-------- +-zzzzzz- +-zzzzzz- +-zzzzzz- +-zzzzzz- +-zzzzzz- +-zzzzzz- +-zzzzzz- +-------- +# Test 51 +board: 3x6 +--b +--b +--b +--i +iii +aai +arguments: 0 3 1 2 1 2 widget valid +board: 3x6 +--a +--a +i-a +z-i +zii +bbi +# Test 52 +board: 5x8 +a--df +a--df +a--di +a--ei +i--ei +i--ii +ibbbi +iccci +arguments: 1 3 1 3 1 2 widget valid +board: 5x8 +e--cb +e--cb +e--ci +ez-di +iz-di +iz-ii +iaaai +ifffi +# Test 53 +board: 8x3 +aaaai--i +iccci--i +bbbiiiii +arguments: 1 1 3 1 3 1 icon invalid +board: 8x3 +-------- +-------- +-------- +# Test 54 +board: 8x9 +------di +------di +------di +------ii +iaaaaaai +baaaaaai +baaaaaai +baaaaaai +iiccccci +arguments: 3 3 2 1 1 1 widget valid +board: 8x9 +------ai +------ai +------ai +---zz-ii +icccccci +bcccccci +bcccccci +bcccccci +iidddddi +# Test 55 +board: 4x8 +ibbi +iaai +iaai +caai +ciii +iddi +--ii +ieei +arguments: 1 4 1 1 1 1 icon valid +board: 4x8 +iaai +icci +icci +ecci +ezii +ibbi +-iii +iddi +# Test 56 +board: 6x9 +-----i +------ +-i---i +i----i +-----i +--icci +-i-bbi +-i-iii +iiaaai +arguments: 1 0 4 2 4 2 widget valid +board: 6x9 +-zzzzi +-zzzz- +-i---i +i----i +-----i +--icci +-i-bbi +-i-iii +iiaaai +# Test 57 +board: 4x9 +aaai +ibbi +c-ii +c-ei +c-ei +c-ii +c-ii +ciii +iddi +arguments: 1 6 2 2 2 2 widget valid +board: 4x9 +eeei +icci +d-ii +dibi +dibi +diii +dzzi +dzzi +iaai +# Test 58 +board: 3x6 +aai +iii +--b +--b +--i +iii +arguments: 0 1 1 1 1 1 icon valid +board: 3x6 +aai +zii +i-b +--b +--i +iii +# Test 59 +board: 9x6 +iiiiii--i +iaaeii--g +baaeii--g +baaiii--i +icciiiiii +iddiiiffi +arguments: 3 3 5 1 4 1 widget valid +board: 9x6 +iiiiii--i +ibbdiii-a +ebbdiiiia +ebbzzzzzi +icciiiiii +iffiiiggi +# Test 60 +board: 5x8 +iiiii +ii-ii +ai-ii +ai-ii +ai-ii +aibbi +iicci +iiiii +arguments: 2 0 2 2 1 2 widget valid +board: 5x8 +iizzi +iizzi +biiii +biiii +biiii +bicci +iiaai +iiiii +# Test 61 +board: 7x10 +------- +------- +------- +------- +------- +------- +------- +------- +------- +------- +arguments: 2 0 3 8 2 7 widget valid +board: 7x10 +--zzz-- +--zzz-- +--zzz-- +--zzz-- +--zzz-- +--zzz-- +--zzz-- +--zzz-- +------- +------- +# Test 62 +board: 8x8 +aaiiiiii +iiibbbbi +dddi---i +iiii---i +ccci---h +ccci---h +eeei---i +fffigggi +arguments: 1 4 4 2 1 1 widget valid +board: 8x8 +eeiiiiii +iiiaaaai +fffigggi +iiiigggi +-zzzzi-c +-zzzz--c +hhhii--i +dddibbbi +# Test 63 +board: 8x5 +ibbii--d +iiiii--d +aaaii--d +aaaii--i +cccciiii +arguments: 3 2 2 1 2 1 widget valid +board: 8x5 +ibbii--d +iiiii--d +ccczziid +cccii--i +aaaaiiii +# Test 64 +board: 9x5 +iiac--iii +iiac--ffi +biac--eei +biai--iii +iiiiddddi +arguments: 3 1 2 3 2 1 widget valid +board: 9x5 +iif--eiii +iifzzebbi +cifzzeaai +cifzziiii +iiiiddddi +# Test 65 +board: 6x7 +aaaiii +aaaiii +ibbcci +i----f +d----f +d----i +iieeei +arguments: 2 1 1 5 1 4 widget valid +board: 6x7 +aaaiii +aaaiii +i-zbbi +i-zeec +d-z--c +d-z--i +iifffi +# Test 66 +board: 10x10 +aaaaaaaaii +i---ijjjni +i---ijjjni +b---kjjjni +b---kjjjii +b---klliii +b---immmmi +bcccccccci +ieeiddiiii +iffiigghhi +arguments: 2 4 3 4 3 1 widget valid +board: 10x10 +aaaaaaaaii +i---innnci +i---innnci +hzzzknnnci +hzzzknnnii +hzzzkeeiii +hzzziffffi +hddddddddi +ijjilliiii +iggiimmbbi +# Test 67 +board: 3x8 +--i +--i +--i +bai +bai +iai +iai +iii +arguments: 0 0 1 2 1 1 widget valid +board: 3x8 +z-i +z-i +--i +bai +bai +iai +iai +iii +# Test 68 +board: 6x5 +i---ii +ibcaei +ibcaei +ibiaii +iiiddi +arguments: 4 1 1 3 1 1 icon valid +board: 6x5 +i--zii +icadbi +icadbi +icidii +iiieei +# Test 69 +board: 3x7 +a-i +a-b +a-b +a-b +a-i +i-i +iii +arguments: 0 0 1 4 1 1 widget valid +board: 3x7 +zbi +zba +zba +zba +-bi +i-i +iii +# Test 70 +board: 5x10 +---ii +---ii +---ii +aaaai +----- +----- +----- +----- +----- +----- +arguments: 0 5 3 4 3 1 widget valid +board: 5x10 +---ii +---ii +---ii +aaaai +----- +zzz-- +zzz-- +zzz-- +zzz-- +----- +# Test 71 +board: 8x9 +-----i-i +-------- +-------- +-------- +-------- +-------- +-------- +-------- +-------- +arguments: 2 3 5 5 1 4 widget valid +board: 8x9 +-----i-i +-------- +-------- +--zzzzz- +--zzzzz- +--zzzzz- +--zzzzz- +--zzzzz- +-------- +# Test 72 +board: 4x6 +i--d +a--d +a--i +acbi +acbi +iiii +arguments: 0 2 1 3 1 2 widget valid +board: 4x6 +iz-b +cz-b +cz-i +cadi +cadi +iiii +# Test 73 +board: 3x7 +--c +--c +--c +--i +bai +bai +iii +arguments: 1 0 1 2 1 1 widget valid +board: 3x7 +-zb +-zb +--b +--i +cai +cai +iii +# Test 74 +board: 4x7 +---i +---i +---b +---b +---b +---i +iaai +arguments: 2 2 1 3 1 1 widget valid +board: 4x7 +---i +---i +--zb +--zb +--zb +---i +iaai +# Test 75 +board: 4x3 +a--i +a--i +ibbi +arguments: 1 0 1 1 1 1 icon valid +board: 4x3 +bz-i +b--i +iaai +# Test 76 +board: 10x5 +--ai------ +--aii----i +--iii----i +--iii----i +iiiiiibbbi +arguments: 5 2 4 2 3 2 widget valid +board: 10x5 +--bi------ +--bii----i +--iiizzzzi +--iiizzzzi +iiiiiiaaai +# Test 77 +board: 8x10 +-------i +-------e +-------e +-------e +-------e +-------e +-------i +ccibbbii +iaaaaaai +iiiddddi +arguments: 4 2 3 5 3 1 widget valid +board: 8x10 +-------i +-------c +----zzzc +----zzzc +----zzzc +----zzzc +----zzzi +aaibbbii +iddddddi +iiieeeei +# Test 78 +board: 3x9 +aai +i-i +iii +--i +--- +--i +b-i +bii +iii +arguments: 1 1 1 7 1 6 widget valid +board: 3x9 +aai +izi +izi +izi +-z- +izi +bzi +bzi +iii +# Test 79 +board: 6x5 +aaii-i +--i--- +--i--i +iii--i +iiiiii +arguments: 2 3 3 1 3 1 widget valid +board: 6x5 +aaii-i +--i--- +--ii-i +iizzzi +iiiiii +# Test 80 +board: 6x4 +------ +------ +----ii +------ +arguments: 0 0 4 2 3 1 widget valid +board: 6x4 +zzzz-- +zzzz-- +----ii +------ +# Test 81 +board: 5x6 +aaaai +i--ii +b--ii +b--ii +b--ii +iiiii +arguments: 2 3 2 1 1 1 widget valid +board: 5x6 +aaaai +i--ii +b--ii +bizzi +b--ii +iiiii +# Test 82 +board: 6x8 +aaaaii +bbbbbi +icciii +-----i +-----i +ddfffi +ddgggi +eeeeei +arguments: 1 3 2 2 1 1 widget valid +board: 6x8 +bbbbii +gggggi +icciii +-zz--i +-zz--i +eedddi +eefffi +aaaaai +# Test 83 +board: 8x10 +iiaaaaai +------cd +------cd +------ci +------ii +iiiiibbi +-------- +-------- +-------- +-------- +arguments: 2 0 5 3 5 1 widget valid +board: 8x10 +iizzzzzi +--zzzzza +--zzzzza +--dddddi +------bi +iiiii-bi +------b- +------i- +-----cc- +-------- +# Test 84 +board: 6x6 +---aii +---aii +---bbi +---iii +--iiii +i----i +arguments: 2 0 3 4 1 3 widget valid +board: 6x6 +bizzzi +bizzzi +aazzzi +iizzzi +--iiii +i----i +# Test 85 +board: 4x7 +iaai +ii-i +ii-i +ii-i +iiii +---- +---i +arguments: 2 2 1 4 1 2 widget valid +board: 4x7 +iaai +ii-i +iizi +iizi +iizi +--z- +--ii +# Test 86 +board: 4x9 +---- +a--i +a--i +i--i +i--c +i--c +b--i +b--i +iiii +arguments: 0 0 2 7 2 7 widget valid +board: 4x9 +zz-- +zzbi +zzbi +zzii +zzia +zzia +zzci +--ci +iiii +# Test 87 +board: 5x6 +----- +-i--i +----- +----- +----- +----- +arguments: 0 0 3 3 1 2 widget valid +board: 5x6 +zzz-- +zzzii +zzz-- +----- +----- +----- +# Test 88 +board: 5x5 +ii--a +ii--a +-i--i +-i-ii +ii--i +arguments: 0 1 2 3 2 1 widget valid +board: 5x5 +iiiia +zz-ia +zz-ii +zz-ii +ii--i +# Test 89 +board: 5x10 +ccddi +bbbii +eeeei +iajji +faiii +fgggi +fgggi +ihhhi +----i +iikki +arguments: 1 3 1 4 1 2 icon invalid +board: 5x10 +----- +----- +----- +----- +----- +----- +----- +----- +----- +----- +# Test 90 +board: 3x6 +--i +--b +--b +--b +--i +aai +arguments: 1 0 1 2 1 1 widget valid +board: 3x6 +-zi +-za +--a +--a +--i +bbi +# Test 91 +board: 4x8 +---i +---c +---c +---c +---c +---i +aaai +bbbi +arguments: 1 1 1 2 1 2 widget valid +board: 4x8 +---i +-z-c +-z-c +---c +---c +---i +bbbi +aaai +# Test 92 +board: 5x7 +----c +----c +----c +----c +----i +aaaai +ibbii +arguments: 1 1 2 4 1 2 widget valid +board: 5x7 +----b +-zz-b +-zz-b +-zz-b +-zz-i +aaaai +iccii +# Test 93 +board: 5x4 +i--ii +i--ii +i--ii +iiiii +arguments: 2 1 1 2 1 2 widget valid +board: 5x4 +i--ii +i-zii +i-zii +iiiii +# Test 94 +board: 10x5 +aabc---iii +aabc---eei +aabi---ffi +aaii---ggi +iiiiiddddi +arguments: 4 1 3 3 1 3 widget valid +board: 10x5 +ggfe---iii +ggfezzzddi +ggfizzzbbi +ggiizzzaai +iiiiicccci +# Test 95 +board: 9x5 +baffi---i +baeei---i +caiii---i +ciddi---i +iiiiiggii +arguments: 0 0 4 3 3 1 widget valid +board: 9x5 +ezzzdccii +ezzzdggii +fzzzdiiii +fibbi---i +iiiiiaaii +# Test 96 +board: 7x7 +------- +--i---i +------- +------- +------i +------- +------i +arguments: 0 1 5 2 3 1 widget valid +board: 7x7 +------- +zzzzzii +zzzzz-- +------- +------i +------- +------i +# Test 97 +board: 10x4 +i-----ccii +a-----ccii +a-----iddi +iibbbiiiii +arguments: 7 2 1 1 1 1 icon valid +board: 10x4 +i-----ccii +d-----ccii +d---ibbz-i +iiaaaiiiii +# Test 98 +board: 7x9 +--i-iii +ai-icci +ai-iiii +iibbbbi +ii-iiii +-i-ii-i +-i-ii-i +ii-iiii +ii----i +arguments: 1 6 3 2 3 2 widget valid +board: 7x9 +--i-iii +bi-iaai +bi-iiii +iicccci +ii-iiii +-iiii-i +izzzi-i +izzziii +iiii--i +# Test 99 +board: 4x10 +aaii +iiii +---c +---c +---c +---d +---d +---i +ibbi +iiii +arguments: 0 0 2 6 1 2 widget valid +board: 4x10 +zzii +zzii +zz-c +zz-c +zz-c +zz-b +aa-b +ii-i +iddi +iiii +# Test 100 +board: 8x4 +iittt--- +yyyy---i +yyyyi--i +yyyy---i +# This represents where you want to add an item, the format is "x y spanX spanY minSpanX minSpanY type ifSolutionIsPossible" +arguments: 5 1 2 3 1 1 widget valid +board: 8x4 +iittt--- +yyyy-hhi +yyyyihhi +yyyy-hhi \ No newline at end of file diff --git a/tests/src/com/android/launcher3/celllayout/CellLayoutBoard.java b/tests/src/com/android/launcher3/celllayout/CellLayoutBoard.java index cf96f04e37..3c2b49ac3b 100644 --- a/tests/src/com/android/launcher3/celllayout/CellLayoutBoard.java +++ b/tests/src/com/android/launcher3/celllayout/CellLayoutBoard.java @@ -171,6 +171,8 @@ public class CellLayoutBoard implements Comparable { } } + private HashSet mUsedWidgetTypes = new HashSet<>(); + static final int INFINITE = 99999; char[][] mWidget = new char[30][30]; @@ -182,6 +184,8 @@ public class CellLayoutBoard implements Comparable { WidgetRect mMain = null; + int mWidth, mHeight; + CellLayoutBoard() { for (int x = 0; x < mWidget.length; x++) { for (int y = 0; y < mWidget[0].length; y++) { @@ -190,6 +194,17 @@ public class CellLayoutBoard implements Comparable { } } + CellLayoutBoard(int width, int height) { + mWidget = new char[width][height]; + this.mWidth = width; + this.mHeight = height; + for (int x = 0; x < mWidget.length; x++) { + for (int y = 0; y < mWidget[0].length; y++) { + mWidget[x][y] = CellType.EMPTY; + } + } + } + public List getWidgets() { return mWidgetsRects; } @@ -256,6 +271,16 @@ public class CellLayoutBoard implements Comparable { }).collect(Collectors.toList()); } + private char getNextWidgetType() { + for (char type = 'a'; type <= 'z'; type++) { + if (type == 'i') continue; + if (mUsedWidgetTypes.contains(type)) continue; + mUsedWidgetTypes.add(type); + return type; + } + return 'z'; + } + public void addWidget(int x, int y, int spanX, int spanY, char type) { Rect rect = new Rect(x, y + spanY - 1, x + spanX - 1, y); removeOverlappingItems(rect); @@ -268,6 +293,10 @@ public class CellLayoutBoard implements Comparable { } } + public void addWidget(int x, int y, int spanX, int spanY) { + addWidget(x, y, spanX, spanY, getNextWidgetType()); + } + public void addIcon(int x, int y) { Point iconCoord = new Point(x, y); removeOverlappingItems(iconCoord); @@ -367,6 +396,8 @@ public class CellLayoutBoard implements Comparable { } } } + board.mHeight = lines.length; + board.mWidth = lines[0].length(); board.mWidgetsRects = getRects(board.mWidget); board.mWidgetsRects.forEach(widgetRect -> { if (widgetRect.mType == CellType.MAIN_WIDGET) { @@ -380,6 +411,11 @@ public class CellLayoutBoard implements Comparable { public String toString(int maxX, int maxY) { StringBuilder s = new StringBuilder(); + s.append("board: "); + s.append(maxX); + s.append("x"); + s.append(maxY); + s.append("\n"); maxX = Math.min(maxX, mWidget.length); maxY = Math.min(maxY, mWidget[0].length); for (int y = 0; y < maxY; y++) { @@ -391,6 +427,11 @@ public class CellLayoutBoard implements Comparable { return s.toString(); } + @Override + public String toString() { + return toString(mWidth, mHeight); + } + public static List boardListFromString(String boardsStr) { String[] lines = boardsStr.split("\n"); ArrayList individualBoards = new ArrayList<>(); @@ -410,4 +451,12 @@ public class CellLayoutBoard implements Comparable { } return boards; } + + public int getWidth() { + return mWidth; + } + + public int getHeight() { + return mHeight; + } } diff --git a/tests/src/com/android/launcher3/celllayout/CellLayoutTestUtils.java b/tests/src/com/android/launcher3/celllayout/CellLayoutTestUtils.java index e3d07a99f1..0d2f252b07 100644 --- a/tests/src/com/android/launcher3/celllayout/CellLayoutTestUtils.java +++ b/tests/src/com/android/launcher3/celllayout/CellLayoutTestUtils.java @@ -24,12 +24,12 @@ import com.android.launcher3.Launcher; import com.android.launcher3.views.DoubleShadowBubbleTextView; import java.util.ArrayList; +import java.util.List; public class CellLayoutTestUtils { public static ArrayList workspaceToBoards(Launcher launcher) { ArrayList boards = new ArrayList<>(); - int widgetCount = 0; for (CellLayout cellLayout : launcher.getWorkspace().mWorkspaceScreens) { int count = cellLayout.getShortcutsAndWidgets().getChildCount(); @@ -52,11 +52,29 @@ public class CellLayoutTestUtils { } else { // is widget board.addWidget(params.getCellX(), params.getCellY(), params.cellHSpan, - params.cellVSpan, (char) ('a' + widgetCount)); - widgetCount++; + params.cellVSpan); } } } return boards; } + + public static CellLayoutBoard viewsToBoard(List views, int width, int height) { + CellLayoutBoard board = new CellLayoutBoard(); + board.mWidth = width; + board.mHeight = height; + + for (View callView : views) { + CellLayoutLayoutParams params = (CellLayoutLayoutParams) callView.getLayoutParams(); + // is icon + if (callView instanceof DoubleShadowBubbleTextView) { + board.addIcon(params.getCellX(), params.getCellY()); + } else { + // is widget + board.addWidget(params.getCellX(), params.getCellY(), params.cellHSpan, + params.cellVSpan); + } + } + return board; + } } diff --git a/tests/src/com/android/launcher3/celllayout/ReorderAlgorithmUnitTest.java b/tests/src/com/android/launcher3/celllayout/ReorderAlgorithmUnitTest.java new file mode 100644 index 0000000000..e3de500bde --- /dev/null +++ b/tests/src/com/android/launcher3/celllayout/ReorderAlgorithmUnitTest.java @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.launcher3.celllayout; + +import static androidx.test.core.app.ApplicationProvider.getApplicationContext; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import android.content.Context; +import android.graphics.Point; +import android.graphics.Rect; +import android.view.View; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.SmallTest; + +import com.android.launcher3.CellLayout; +import com.android.launcher3.DeviceProfile; +import com.android.launcher3.InvariantDeviceProfile; +import com.android.launcher3.util.ActivityContextWrapper; +import com.android.launcher3.views.DoubleShadowBubbleTextView; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.Random; + +@SmallTest +@RunWith(AndroidJUnit4.class) +public class ReorderAlgorithmUnitTest { + private Context mApplicationContext; + + private int mPrevNumColumns, mPrevNumRows; + + @Test + public void testAllCases() throws IOException { + List testCases = getTestCases( + "ReorderAlgorithmUnitTest/reorder_algorithm_test_cases"); + mApplicationContext = new ActivityContextWrapper(getApplicationContext()); + List failingCases = new ArrayList<>(); + for (int i = 0; i < testCases.size(); i++) { + try { + evaluateTestCase(testCases.get(i)); + } catch (AssertionError e) { + e.printStackTrace(); + failingCases.add(i); + } + } + assertEquals("Some test cases failed " + Arrays.toString(failingCases.toArray()), 0, + failingCases.size()); + } + + private void addViewInCellLayout(CellLayout cellLayout, int cellX, int cellY, int spanX, + int spanY, boolean isWidget) { + View cell = isWidget ? new View(mApplicationContext) : new DoubleShadowBubbleTextView( + mApplicationContext); + cell.setLayoutParams(new CellLayoutLayoutParams(cellX, cellY, spanX, spanY)); + cellLayout.addViewToCellLayout(cell, -1, cell.getId(), + (CellLayoutLayoutParams) cell.getLayoutParams(), true); + } + + public CellLayout createCellLayout(int width, int height) { + Context c = mApplicationContext; + DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(c).getDeviceProfile(c).copy(c); + // modify the device profile. + dp.inv.numColumns = width; + dp.inv.numRows = height; + + CellLayout cl = new CellLayout(getWrappedContext(c, dp)); + // I put a very large number for width and height so that all the items can fit, it doesn't + // need to be exact, just bigger than the sum of cell border + cl.measure(View.MeasureSpec.makeMeasureSpec(10000, View.MeasureSpec.EXACTLY), + View.MeasureSpec.makeMeasureSpec(10000, View.MeasureSpec.EXACTLY)); + + cl.measure(View.MeasureSpec.makeMeasureSpec(cl.getDesiredWidth(), View.MeasureSpec.EXACTLY), + View.MeasureSpec.makeMeasureSpec(cl.getDesiredHeight(), View.MeasureSpec.EXACTLY)); + return cl; + } + + private Context getWrappedContext(Context context, DeviceProfile dp) { + return new ActivityContextWrapper(context) { + public DeviceProfile getDeviceProfile() { + return dp; + } + }; + } + + public CellLayout.ItemConfiguration solve(CellLayoutBoard board, int x, int y, int spanX, + int spanY, int minSpanX, int minSpanY) { + CellLayout cl = createCellLayout(board.getWidth(), board.getHeight()); + + // The views have to be sorted or the result can vary + board.getIcons() + .stream() + .map(CellLayoutBoard.IconPoint::getCoord) + .sorted(Comparator.comparing(p -> ((Point) p).x).thenComparing(p -> ((Point) p).y)) + .forEach(p -> addViewInCellLayout(cl, p.x, p.y, 1, 1, false)); + board.getWidgets().stream() + .sorted(Comparator.comparing(CellLayoutBoard.WidgetRect::getCellX) + .thenComparing(CellLayoutBoard.WidgetRect::getCellY)) + .forEach(widget -> addViewInCellLayout(cl, widget.getCellX(), widget.getCellY(), + widget.getSpanX(), widget.getSpanY(), true)); + + int[] testCaseXYinPixels = new int[2]; + cl.regionToCenterPoint(x, y, spanX, spanY, testCaseXYinPixels); + CellLayout.ItemConfiguration solution = cl.createReorderAlgorithm().calculateReorder( + testCaseXYinPixels[0], testCaseXYinPixels[1], minSpanX, minSpanY, spanX, spanY, + null); + if (solution == null) { + solution = new CellLayout.ItemConfiguration(); + solution.isSolution = false; + } + return solution; + } + + public CellLayoutBoard boardFromSolution(CellLayout.ItemConfiguration solution, int width, + int height) { + // Update the views with solution value + solution.map.forEach((key, val) -> key.setLayoutParams( + new CellLayoutLayoutParams(val.cellX, val.cellY, val.spanX, val.spanY))); + CellLayoutBoard board = CellLayoutTestUtils.viewsToBoard( + new ArrayList<>(solution.map.keySet()), width, height); + board.addWidget(solution.cellX, solution.cellY, solution.spanX, solution.spanY, + 'z'); + return board; + } + + public void evaluateTestCase(ReorderAlgorithmUnitTestCase testCase) { + CellLayout.ItemConfiguration solution = solve(testCase.startBoard, testCase.x, + testCase.y, testCase.spanX, testCase.spanY, testCase.minSpanX, + testCase.minSpanY); + assertEquals("should be a valid solution", solution.isSolution, + testCase.isValidSolution); + if (testCase.isValidSolution) { + CellLayoutBoard finishBoard = boardFromSolution(solution, + testCase.startBoard.getWidth(), testCase.startBoard.getHeight()); + assertTrue("End result and test case result board doesn't match ", + finishBoard.compareTo(testCase.endBoard) == 0); + } + } + + @Before + public void storePreviousValues() { + Context c = new ActivityContextWrapper(getApplicationContext()); + DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(c).getDeviceProfile(c).copy(c); + mPrevNumColumns = dp.inv.numColumns; + mPrevNumRows = dp.inv.numColumns; + } + + @After + public void restorePreviousValues() { + Context c = new ActivityContextWrapper(getApplicationContext()); + DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(c).getDeviceProfile(c).copy(c); + dp.inv.numColumns = mPrevNumColumns; + dp.inv.numRows = mPrevNumRows; + } + + @SuppressWarnings("UnusedMethod") + /** + * Utility function used to generate all the test cases + */ + private ReorderAlgorithmUnitTestCase generateRandomTestCase() { + ReorderAlgorithmUnitTestCase testCase = new ReorderAlgorithmUnitTestCase(); + + int width = getRandom(3, 8); + int height = getRandom(3, 8); + + int targetWidth = getRandom(1, width - 2); + int targetHeight = getRandom(1, height - 2); + + int minTargetWidth = getRandom(1, targetWidth); + int minTargetHeight = getRandom(1, targetHeight); + + int x = getRandom(0, width - targetWidth); + int y = getRandom(0, height - targetHeight); + + CellLayoutBoard board = generateBoard(new CellLayoutBoard(width, height), + new Rect(0, 0, width, height), targetWidth * targetHeight); + + CellLayout.ItemConfiguration solution = solve(board, x, y, targetWidth, targetHeight, + minTargetWidth, minTargetHeight); + + CellLayoutBoard finishBoard = solution.isSolution ? boardFromSolution(solution, + board.getWidth(), board.getHeight()) : new CellLayoutBoard(board.getWidth(), + board.getHeight()); + + + testCase.startBoard = board; + testCase.endBoard = finishBoard; + testCase.isValidSolution = solution.isSolution; + testCase.x = x; + testCase.y = y; + testCase.spanX = targetWidth; + testCase.spanY = targetHeight; + testCase.minSpanX = minTargetWidth; + testCase.minSpanY = minTargetHeight; + testCase.type = solution.area() == 1 ? "icon" : "widget"; + + return testCase; + } + + private int getRandom(int start, int end) { + int random = end == 0 ? 0 : new Random().nextInt(end); + return start + random; + } + + private CellLayoutBoard generateBoard(CellLayoutBoard board, Rect area, + int emptySpaces) { + if (area.height() * area.width() <= 0) return board; + + int width = getRandom(1, area.width() - 1); + int height = getRandom(1, area.height() - 1); + + int x = area.left + getRandom(0, area.width() - width); + int y = area.top + getRandom(0, area.height() - height); + + if (emptySpaces > 0) { + emptySpaces -= width * height; + } else if (width * height > 1) { + board.addWidget(x, y, width, height); + } else { + board.addIcon(x, y); + } + + generateBoard(board, + new Rect(area.left, area.top, area.right, y), emptySpaces); + generateBoard(board, + new Rect(area.left, y, x, area.bottom), emptySpaces); + generateBoard(board, + new Rect(x, y + height, area.right, area.bottom), emptySpaces); + generateBoard(board, + new Rect(x + width, y, area.right, y + height), emptySpaces); + + return board; + } + + private static List getTestCases(String testPath) + throws IOException { + List cases = new ArrayList<>(); + Iterator iterableSection = + CellLayoutTestCaseReader.readFromFile(testPath).parse().iterator(); + while (iterableSection.hasNext()) { + cases.add(ReorderAlgorithmUnitTestCase.readNextCase(iterableSection)); + } + return cases; + } +} diff --git a/tests/src/com/android/launcher3/celllayout/ReorderAlgorithmUnitTestCase.java b/tests/src/com/android/launcher3/celllayout/ReorderAlgorithmUnitTestCase.java new file mode 100644 index 0000000000..4274130702 --- /dev/null +++ b/tests/src/com/android/launcher3/celllayout/ReorderAlgorithmUnitTestCase.java @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.launcher3.celllayout; + +import java.util.Iterator; + +/** + * Represents a test case for {@code ReorderAlgorithmUnitTest}. The test cases are generated from + * text, an example of a test is the following: + * + * board: 10x8 + * aaaaaaaaai + * bbbbbcciii + * ---------f + * ---------f + * ---------f + * ---------i + * iiddddddii + * iieeiiiiii + * arguments: 2 5 7 1 3 1 widget valid + * board: 10x8 + * bbbbbbbbbi + * eeeeecciii + * ---------a + * ---------a + * ---------a + * --zzzzzzzi + * iiddddddii + * iiffiiiiii + * + * + * This represents a Workspace boards and a dragged widget that wants to be dropped on the + * workspace. The endBoard represents the result from such drag + * The first board is the startBoard, the arguments are as follow: cellX, cellY, widget spanX, + * widget spanY, minimum spanX, minimum spanX, type of object being drag (icon, widget, folder ), + * if the resulting board is a valid solution or not reorder was found. + * + * For more information on how to read the board please go to the text file + * reorder_algorithm_test_cases + */ +public class ReorderAlgorithmUnitTestCase { + + CellLayoutBoard startBoard; + + int x, y, spanX, spanY, minSpanX, minSpanY; + String type; + boolean isValidSolution; + CellLayoutBoard endBoard; + + public static ReorderAlgorithmUnitTestCase readNextCase( + Iterator sections) { + ReorderAlgorithmUnitTestCase testCase = new ReorderAlgorithmUnitTestCase(); + CellLayoutTestCaseReader.Board startBoard = + (CellLayoutTestCaseReader.Board) sections.next(); + testCase.startBoard = CellLayoutBoard.boardFromString(startBoard.board); + CellLayoutTestCaseReader.Arguments arguments = + (CellLayoutTestCaseReader.Arguments) sections.next(); + testCase.x = Integer.parseInt(arguments.arguments[0]); + testCase.y = Integer.parseInt(arguments.arguments[1]); + testCase.spanX = Integer.parseInt(arguments.arguments[2]); + testCase.spanY = Integer.parseInt(arguments.arguments[3]); + testCase.minSpanX = Integer.parseInt(arguments.arguments[4]); + testCase.minSpanY = Integer.parseInt(arguments.arguments[5]); + testCase.type = arguments.arguments[6]; + testCase.isValidSolution = arguments.arguments[7].compareTo("valid") == 0; + + CellLayoutTestCaseReader.Board endBoard = (CellLayoutTestCaseReader.Board) sections.next(); + testCase.endBoard = CellLayoutBoard.boardFromString(endBoard.board); + return testCase; + } + + public CellLayoutBoard getStartBoard() { + return startBoard; + } + + public int getX() { + return x; + } + + public void setX(int x) { + this.x = x; + } + + public int getY() { + return y; + } + + public void setY(int y) { + this.y = y; + } + + public int getSpanX() { + return spanX; + } + + public void setSpanX(int spanX) { + this.spanX = spanX; + } + + public int getSpanY() { + return spanY; + } + + public void setSpanY(int spanY) { + this.spanY = spanY; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public boolean isValidSolution() { + return isValidSolution; + } + + public void setValidSolution(boolean validSolution) { + isValidSolution = validSolution; + } + + public CellLayoutBoard getEndBoard() { + return endBoard; + } + + public void setEndBoard(CellLayoutBoard endBoard) { + this.endBoard = endBoard; + } + + @Override + public String toString() { + String valid = isValidSolution ? "valid" : "invalid"; + return startBoard + "arguments: " + x + " " + y + " " + spanX + " " + spanY + " " + minSpanX + + " " + minSpanY + " " + type + " " + valid + "\n" + endBoard; + } +}