1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.launcher3.celllayout.testgenerator
17 
18 import android.graphics.Rect
19 import com.android.launcher3.celllayout.board.CellLayoutBoard
20 import java.util.Random
21 
22 /** Generates a random CellLayoutBoard. */
23 open class RandomBoardGenerator(generator: Random) : DeterministicRandomGenerator(generator) {
24 
25     companion object {
26         // This is the max number of widgets because we encode the widgets as letters A-Z and we
27         // already have some of those letter used by other things so 22 is a safe number
28         val MAX_NUMBER_OF_WIDGETS = 22
29     }
30 
31     /**
32      * @param remainingEmptySpaces the maximum number of spaces we will fill with icons and widgets
33      *   meaning that if the number is 100 we will try to fill the board with at most 100 spaces
34      *   usually less than 100.
35      * @return a randomly generated board filled with icons and widgets.
36      */
generateBoardnull37     open fun generateBoard(width: Int, height: Int, remainingEmptySpaces: Int): CellLayoutBoard {
38         val cellLayoutBoard = CellLayoutBoard(width, height)
39         return fillBoard(cellLayoutBoard, Rect(0, 0, width, height), remainingEmptySpaces)
40     }
41 
fillBoardnull42     protected fun fillBoard(
43         board: CellLayoutBoard,
44         area: Rect,
45         remainingEmptySpacesArg: Int
46     ): CellLayoutBoard {
47         var remainingEmptySpaces = remainingEmptySpacesArg
48         if (area.height() * area.width() <= 0) return board
49         val width = getRandom(1, area.width())
50         val height = getRandom(1, area.height())
51         val x = area.left + getRandom(0, area.width() - width)
52         val y = area.top + getRandom(0, area.height() - height)
53         if (remainingEmptySpaces > 0) {
54             remainingEmptySpaces -= width * height
55         }
56 
57         if (board.widgets.size <= MAX_NUMBER_OF_WIDGETS && width * height > 1) {
58             board.addWidget(x, y, width, height)
59         } else {
60             board.addIcon(x, y)
61         }
62 
63         if (remainingEmptySpaces < 0) {
64             // optimization, no need to keep going
65             return board
66         }
67         fillBoard(board, Rect(area.left, area.top, area.right, y), remainingEmptySpaces)
68         fillBoard(board, Rect(area.left, y, x, area.bottom), remainingEmptySpaces)
69         fillBoard(board, Rect(x, y + height, area.right, area.bottom), remainingEmptySpaces)
70         fillBoard(board, Rect(x + width, y, area.right, y + height), remainingEmptySpaces)
71         return board
72     }
73 }
74