From 7c60227b3b68f35ac4f49279d1e91880c639b1a8 Mon Sep 17 00:00:00 2001 From: Peter Vaiko Date: Mon, 23 Sep 2024 18:51:20 -0400 Subject: [PATCH 1/8] perf: disable block sequencing for island detection Also, use just a Center instead of the whole FieldworkCourse to generate the island detection grid. --- scripts/courseGenerator/Center.lua | 7 +++++++ scripts/courseGenerator/FieldworkContext.lua | 12 ++++++++++++ scripts/courseGenerator/Island.lua | 9 ++++++--- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/scripts/courseGenerator/Center.lua b/scripts/courseGenerator/Center.lua index 0d28ec7e3..ded8b4057 100644 --- a/scripts/courseGenerator/Center.lua +++ b/scripts/courseGenerator/Center.lua @@ -96,6 +96,13 @@ function Center:generate() self.logger:debug('No blocks could be generated') return end + + if self.context:_generateBlocksOnly() then + self.logger:debug('Generating blocks only, no sequencing or connecting paths.') + self.blocks = blocks + self.connectingPaths = {} + return + end -- now connect all blocks -- if there are more than one block, we need to figure out in what sequence those blocks diff --git a/scripts/courseGenerator/FieldworkContext.lua b/scripts/courseGenerator/FieldworkContext.lua index 3930be3c6..913ebe88d 100644 --- a/scripts/courseGenerator/FieldworkContext.lua +++ b/scripts/courseGenerator/FieldworkContext.lua @@ -236,6 +236,18 @@ function FieldworkContext:getHeadlandWorkingWidth() return self.headlandWorkingWidth or self.workingWidth * (1 - self.overlap) end +--- Disable sequencing of blocks, just generate them, with the rows and then stop. +--- Block sequencing uses a genetic algorithm to find the best order of blocks to work on. +--- When we perform an island detection only, we just want a grid across the field, but that may result in many blocks, +--- no need for a CPU intensive, very long running block sequencing. +function FieldworkContext:_setGenerateBlocksOnly() + self.generateBlocksOnly = true +end + +function FieldworkContext:_generateBlocksOnly() + return self.generateBlocksOnly +end + ------------------------------------------------------------------------------------------------------------------------ --- Multi vehicle support ------------------------------------------------------------------------------------------------------------------------ diff --git a/scripts/courseGenerator/Island.lua b/scripts/courseGenerator/Island.lua index 47ccfa226..3c072ed04 100644 --- a/scripts/courseGenerator/Island.lua +++ b/scripts/courseGenerator/Island.lua @@ -170,7 +170,7 @@ function Island:isTooBigToBypass(width) end end ------------------------------------------------------------------------------------------------------------------------- +--------------------------------------------------------------------------------------------------------- --------------- -- Find islands in the game. ------------------------------------------------------------------------------------------------------------------------ function Island.findIslands(field) @@ -179,9 +179,11 @@ function Island.findIslands(field) Island.logger:debug('Generating grid for field with grid spacing %.1f', Island.gridSpacing) local context = CourseGenerator.FieldworkContext(field, Island.gridSpacing, 5, 0) context:setAutoRowAngle(false):setRowAngle(0):setRowWaypointDistance(1) - local course = CourseGenerator.FieldworkCourse(context) + context:_setGenerateBlocksOnly() + local boundary = CourseGenerator.FieldworkCourseHelper.createUsableBoundary(context.field:getBoundary(), context.headlandClockwise) + local center = CourseGenerator.Center(context, boundary, nil, context.startLocation, {}) local islandVertices = {} - for _, b in ipairs(course:getCenter():getBlocks()) do + for _, b in ipairs(center:getBlocks()) do for _, r in ipairs(b:getRows()) do for _, v in ipairs(r) do local isOnField, _ = FSDensityMapUtil.getFieldDataAtWorldPosition(v.x, 0, -v.y) @@ -198,5 +200,6 @@ function Island.findIslands(field) end end end + Island.logger:debug('\t Found %d island vertices', #islandVertices) return islandVertices end \ No newline at end of file From 29db52af32b517f6d5d2a147141a9059002ce2fd Mon Sep 17 00:00:00 2001 From: Peter Vaiko Date: Wed, 25 Sep 2024 12:59:12 -0400 Subject: [PATCH 2/8] fix: add forgotten generate() --- scripts/courseGenerator/Island.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/courseGenerator/Island.lua b/scripts/courseGenerator/Island.lua index 3c072ed04..4ab16b0fa 100644 --- a/scripts/courseGenerator/Island.lua +++ b/scripts/courseGenerator/Island.lua @@ -182,6 +182,7 @@ function Island.findIslands(field) context:_setGenerateBlocksOnly() local boundary = CourseGenerator.FieldworkCourseHelper.createUsableBoundary(context.field:getBoundary(), context.headlandClockwise) local center = CourseGenerator.Center(context, boundary, nil, context.startLocation, {}) + center:generate() local islandVertices = {} for _, b in ipairs(center:getBlocks()) do for _, r in ipairs(b:getRows()) do From 692d669620ed50cff732c9d5589db8cae0f761f5 Mon Sep 17 00:00:00 2001 From: Peter Vaiko Date: Wed, 25 Sep 2024 15:09:05 -0400 Subject: [PATCH 3/8] fix: and splitting... --- scripts/courseGenerator/Block.lua | 5 +++++ scripts/courseGenerator/Island.lua | 7 +++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/scripts/courseGenerator/Block.lua b/scripts/courseGenerator/Block.lua index 6779d90a7..2a87edaf2 100644 --- a/scripts/courseGenerator/Block.lua +++ b/scripts/courseGenerator/Block.lua @@ -81,6 +81,11 @@ function Block:getRows() return self.rowsInWorkSequence end +---@return CourseGenerator.Row[] rows in the order they were created, same direction as they were created +function Block:getUnsequencedRows() + return self.rows +end + ---@return CourseGenerator.Row first row of the block in the work sequence function Block:getFirstRow() return self.rowsInWorkSequence[1] diff --git a/scripts/courseGenerator/Island.lua b/scripts/courseGenerator/Island.lua index 4ab16b0fa..8a1585115 100644 --- a/scripts/courseGenerator/Island.lua +++ b/scripts/courseGenerator/Island.lua @@ -178,14 +178,17 @@ function Island.findIslands(field) -- to end up with a 1x1 grid of nodes covering the islands of the field. Island.logger:debug('Generating grid for field with grid spacing %.1f', Island.gridSpacing) local context = CourseGenerator.FieldworkContext(field, Island.gridSpacing, 5, 0) - context:setAutoRowAngle(false):setRowAngle(0):setRowWaypointDistance(1) + context:setAutoRowAngle(false):setRowAngle(0):setRowWaypointDistance(Island.gridSpacing) context:_setGenerateBlocksOnly() local boundary = CourseGenerator.FieldworkCourseHelper.createUsableBoundary(context.field:getBoundary(), context.headlandClockwise) local center = CourseGenerator.Center(context, boundary, nil, context.startLocation, {}) center:generate() local islandVertices = {} for _, b in ipairs(center:getBlocks()) do - for _, r in ipairs(b:getRows()) do + Island.logger:debug('\t Block %s, %d rows', b, #b:getUnsequencedRows()) + for _, r in ipairs(b:getUnsequencedRows()) do + r:splitEdges(Island.gridSpacing) + Island.logger:debug('\t has %d waypoints', #r) for _, v in ipairs(r) do local isOnField, _ = FSDensityMapUtil.getFieldDataAtWorldPosition(v.x, 0, -v.y) if not isOnField then From 43782f4ceb4f96b4ee5be6600dca65a61d22e31c Mon Sep 17 00:00:00 2001 From: Peter Vaiko Date: Wed, 25 Sep 2024 15:16:52 -0400 Subject: [PATCH 4/8] chore: Lua setup in unit tests updated --- .github/workflows/unit-test.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 4d2112de9..b191c1f2e 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -22,7 +22,10 @@ jobs: - name: Checkout repository uses: actions/checkout@v2 - name: Setup Lua - uses: xpol/setup-lua@v0.3 + uses: leafo/gh-actions-lua@v10 + with: + # because atan2 is deprecated in 5.3 + luaVersion: "5.2.4 - name: Run unit tests run: | cd scripts/test From 94c9bfff19ed59493689609bf5da438b3b28eb67 Mon Sep 17 00:00:00 2001 From: Peter Vaiko Date: Wed, 25 Sep 2024 15:20:55 -0400 Subject: [PATCH 5/8] chore: Lua setup in unit tests typo fixed --- .github/workflows/unit-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index b191c1f2e..65759d282 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -25,7 +25,7 @@ jobs: uses: leafo/gh-actions-lua@v10 with: # because atan2 is deprecated in 5.3 - luaVersion: "5.2.4 + luaVersion: "5.2.4" - name: Run unit tests run: | cd scripts/test From 6ae7f2956f273aa41ca91fd9922a4707456aab38 Mon Sep 17 00:00:00 2001 From: Peter Vaiko Date: Wed, 25 Sep 2024 15:24:09 -0400 Subject: [PATCH 6/8] chore: unit tests switched to Ubuntu Three times is the charm... --- .github/workflows/unit-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 65759d282..2a273747d 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -17,7 +17,7 @@ on: # The list of jobs this workflow executes jobs: test: - runs-on: windows-latest + runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v2 From f63d2ffb17bcd02f7a6f1c24732a2646df87ef6c Mon Sep 17 00:00:00 2001 From: Peter Vaiko Date: Wed, 25 Sep 2024 16:37:59 -0400 Subject: [PATCH 7/8] chore: file manager unit tests migrated to Linux --- scripts/test/CourseManagerTest.lua | 19 ++++++++----------- scripts/test/mock-Courseplay.lua | 1 + scripts/test/mock-GiantsEngine.lua | 8 +++----- 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/scripts/test/CourseManagerTest.lua b/scripts/test/CourseManagerTest.lua index 5fdf75a4f..1330e89b4 100644 --- a/scripts/test/CourseManagerTest.lua +++ b/scripts/test/CourseManagerTest.lua @@ -9,17 +9,15 @@ require('FileSystem') --- Still WIP -- clean up -local workingDir = io.popen"cd":read'*l' -deleteFolder(workingDir .. '\\modSettings') -local coursesDir = 'modSettings\\Courseplay_FS22\\Courses' -os.execute('mkdir ' .. coursesDir) -local mapCoursesDir = workingDir .. '\\' .. coursesDir .. '\\' .. g_currentMission.missionInfo.mapId +local workingDir = io.popen("pwd"):read'*l' +deleteFolder(workingDir .. '/modSettings') +local coursesDir = 'modSettings/Courseplay_FS22/Courses' +os.execute('mkdir -p ' .. coursesDir) ------------------------------------------------------------------------------------------------------------------------ -- File ------------------------------------------------------------------------------------------------------------------------ - local file = File(coursesDir,"testFile") assert(file.name == "testFile") assert(file.parentPath == coursesDir) @@ -35,7 +33,6 @@ assert(not fileExists(file:getFullPath())) ------------------------------------------------------------------------------------------------------------------------ -- Directory ------------------------------------------------------------------------------------------------------------------------ - local dir = Directory(coursesDir,"testDir") assert(dir:isDirectory() == true) assert(next(dir:getEntries(true,true)) == nil) @@ -44,16 +41,16 @@ assert(dir:isEmpty() == true) dir:addFile("testFile") assert(dir.entries["testFile"] ~=nil) -dir:addDirectory("testDir") -assert(dir.entries["testDir"] ~=nil) +dir:addDirectory("testDir2") +assert(dir.entries["testDir2"] ~=nil) assert(dir:isEmpty() == false) dir:delete(true) + ------------------------------------------------------------------------------------------------------------------------ -- FileSystem ------------------------------------------------------------------------------------------------------------------------ - -local fileSystem = FileSystem(workingDir .. '\\' .. coursesDir, g_currentMission.missionInfo.mapId) +local fileSystem = FileSystem(workingDir .. '/' .. coursesDir, g_currentMission.missionInfo.mapId) local currentView = fileSystem.currentDirectoryView --assert(currentView.name == "Singleplayer") diff --git a/scripts/test/mock-Courseplay.lua b/scripts/test/mock-Courseplay.lua index 783ca2138..bc499742e 100644 --- a/scripts/test/mock-Courseplay.lua +++ b/scripts/test/mock-Courseplay.lua @@ -18,6 +18,7 @@ along with this program. If not, see . CpDebug = {} CpDebug.isChannelActive = function () return true end +CpDebug.getText = function () return '' end g_vehicleConfigurations = {} function g_vehicleConfigurations:get() diff --git a/scripts/test/mock-GiantsEngine.lua b/scripts/test/mock-GiantsEngine.lua index f6d5d39dd..f64745188 100644 --- a/scripts/test/mock-GiantsEngine.lua +++ b/scripts/test/mock-GiantsEngine.lua @@ -36,10 +36,10 @@ function createFolder(folder) end function getFiles(folder, callback, object) - for dir in io.popen('dir "' .. folder .. '" /b /ad'):lines() do + for dir in io.popen('ls --file-type "' .. folder .. '" | grep \'/$\' | sed -e \'s/\\///\''):lines() do object[callback](object, dir, true) end - for file in io.popen('dir "' .. folder .. '" /b /a-d'):lines() do + for file in io.popen('ls --file-type "' .. folder .. '" | grep -v \'/$\''):lines() do object[callback](object, file, false) end end @@ -54,9 +54,7 @@ function deleteFile(fullPath) end function deleteFolder(fullPath) - os.execute('del /s /q "' .. fullPath .. '\\*"') - os.execute('for /d %i in ("' .. fullPath .. '\\*") do rd /s /q "%i"') - os.remove(fullPath) + os.execute('rm -rf "' .. fullPath .. '"') end function fileExists(path) From 939051a081cf2056e577e645ef725936109ddbee Mon Sep 17 00:00:00 2001 From: Peter Vaiko Date: Thu, 26 Sep 2024 13:36:45 -0400 Subject: [PATCH 8/8] chore: debug messages removed --- scripts/courseGenerator/Island.lua | 2 -- 1 file changed, 2 deletions(-) diff --git a/scripts/courseGenerator/Island.lua b/scripts/courseGenerator/Island.lua index 8a1585115..df98facab 100644 --- a/scripts/courseGenerator/Island.lua +++ b/scripts/courseGenerator/Island.lua @@ -185,10 +185,8 @@ function Island.findIslands(field) center:generate() local islandVertices = {} for _, b in ipairs(center:getBlocks()) do - Island.logger:debug('\t Block %s, %d rows', b, #b:getUnsequencedRows()) for _, r in ipairs(b:getUnsequencedRows()) do r:splitEdges(Island.gridSpacing) - Island.logger:debug('\t has %d waypoints', #r) for _, v in ipairs(r) do local isOnField, _ = FSDensityMapUtil.getFieldDataAtWorldPosition(v.x, 0, -v.y) if not isOnField then