Icon representing a recipe

Recipe: Slot Grabber 1.0

created by LociOiling

Profile


Name
Slot Grabber 1.0
ID
103801
Shared with
Public
Parent
None
Children
Created on
August 15, 2020 at 05:26 AM UTC
Updated on
August 15, 2020 at 05:26 AM UTC
Description

Lists the occupied quicksave slots. Optionally, loads one of the occupied slots. Another option creates a named save for each occupied slot. Thanks to BootsMcGraw!

Best for


Code


--[[ Slot Grabber Retrieve the contents of a specified quicksave slot. Optionally, make named saves for each occupied slot. Named saves are similar to manual saves made through the Save Solution or Open/Share Solutions dialogs, and persist even if Foldit crashes. As suggested by BootsMcGraw (and Trigger). version 1.0 - 2020/08/15 - LociOiling ]]-- Recipe = "Slot Grabber" Version = "1.0" ReVersion = Recipe .. " " .. Version -- -- dialog variables -- slotSel = "" saveSlots = false savePrefix = "" -- -- end of dialog variables -- function main () Ident ( ReVersion ) local firstempty = 0 local slotz = {} for ii = 1, 99 do if not save.QuicksaveEmpty ( ii ) then slotz [ #slotz + 1 ] = ii elseif firstempty == 0 then firstempty = ii end end slotset = ListToSet ( slotz ) print ( #slotz .. " quicksave slots occupied" ) print ( "occupied: " .. SetToString ( slotset ) ) if firstempty ~= 0 then print ( "first empty slot = " .. firstempty ) else print ( "no empty slots" ) end if GetParameters ( slotz, slotset ) then if type ( slotSel ) == "number" then save.Quickload ( slotSel ) print ( "Quickloaded slot " .. slotSel ) else print ( "No quickload slot specified" ) end if saveSlots then local startname = ReVersion .. " starting pose" print ( "Making named saves for each occupied slot" ) if savePrefix:len () > 0 then savePrefix = savePrefix .. " " end if firstempty == 0 then print ( "all slots occupied, saving current pose as \"" .. startname .. "\"" ) save.SaveSolution ( startname ) else print ( "saved current pose in slot " .. firstempty ) save.Quicksave ( firstempty ) end local saves = 0 for ii = 1, #slotz do local savename = savePrefix .. "slot " .. slotz [ ii ] save.Quickload ( slotz [ ii ] ) print ( "saving slot " .. slotz [ ii ] .. " as \"" .. savename .. "\"" ) save.SaveSolution ( savename ) saves = saves + 1 end print ( saves .. " slots converted to named saves" ) if firstempty == 0 then print ( "restoring current pose from \"" .. startname .. "\"" ) save.LoadSolutionByName ( ReVersion .. " starting pose" ) else print ( "loading current pose from slot " .. firstempty ) save.Quickload ( firstempty ) end end end cleanup () end function GetParameters ( slotz, slotset ) -- -- slotz - list of occupied quicksave slots -- slotset - set of occupied quicksave slots -- local segCnt = structure.GetCount () local rc = 0 local valerr = "" repeat local dlog = dialog.CreateDialog ( ReVersion ) dlog.puzz = dialog.AddLabel ( "Puzzle: " .. puzzle.GetName () .. " (" .. puzzle.GetPuzzleID () .. ")" ) dlog.trak = dialog.AddLabel ( "Track: " .. ui.GetTrackName () ) dlog.spa = dialog.AddLabel ( "" ) dlog.slots = dialog.AddLabel ( #slotz .. " quicksave slots occupied" ) dlog.slotted = dialog.AddTextbox ( "Occupied slots", SetToString ( slotset ) ) dlog.slotSel = dialog.AddTextbox ( "Quickload slot", slotSel ) if valerr ~= "" then dlog.sp1 = dialog.AddLabel ( "" ) dlog.valerr = dialog.AddLabel ( valerr ) end dlog.saveSlots = dialog.AddCheckbox ( "Save all occupied slots?", saveSlots ) dlog.savePrefix = dialog.AddTextbox ( "Prefix for saves", savePrefix ) dlog.ok = dialog.AddButton ( "OK" , 1 ) dlog.cancel = dialog.AddButton ( "Cancel" , 0 ) rc = dialog.Show ( dlog ) if rc > 0 then saveSlots = dlog.saveSlots.value savePrefix = dlog.savePrefix.value valerr = "" slotSel = dlog.slotSel.value if slotSel:len () > 0 then slotSel = tonumber ( dlog.slotSel.value ) if slotSel >= 1 and slotSel <= 99 then local empty = save.QuicksaveEmpty ( slotSel ) if empty then valerr = "ERROR: empty slot" end else valerr = "ERROR: invalid slot number" end end end until rc == 0 or valerr == "" if rc > 0 then return true else return false end end -- -- ListToSet and SetToString adapted from TvdL -- 02-05-2012 TvdL Free to use for non commercial purposes -- ListToSet = function ( list ) -- retirer doublons local result = {} local ff = 0 local ll = -1 table.sort ( list ) for ii = 1, #list do if list [ ii ] ~= ll + 1 and list [ ii ] ~= ll then -- note: duplicates are removed if ll > 0 then result [ #result + 1 ] = { ff, ll } end ff = list [ ii ] end ll = list [ ii ] end if ll > 0 then result [ #result + 1 ] = { ff, ll } end return result end SetToString = function ( set ) -- pour pouvoir imprimer local line = "" for ii = 1, #set do if ii ~= 1 then line = line .. ", " end line = line .. set [ ii ] [ 1 ] .. "-" .. set [ ii ] [ 2 ] end return line end -- -- Ident - print identifying information at beginning and end of recipe -- -- slugline - first line to print - normally recipe name and version -- -- streamlined version - remove group reporting -- function Ident ( slugline ) local function round ( ii ) return ii - ii % 0.001 end print ( slugline ) print ( "Puzzle: " .. puzzle.GetName () .. " (" .. puzzle.GetPuzzleID () .. ")" ) print ( "Track: " .. ui.GetTrackName () ) local luser = user.GetPlayerName () local scoretype = scoreboard.GetScoreType () local scort = "" if scoretype == 0 then scort = "soloist" elseif scoretype == 1 then scort = "evolver" elseif scoretype == 2 then scort = "all hands" elseif scoretype == 3 then scort = "no score" else scort = "unknown/error" end print ( "User: " .. luser ) print ( "Rank: " .. scoreboard.GetRank ( scoretype ) .. " (" .. scort .. ")" ) end function cleanup ( errmsg ) if CLEANUPENTRY ~= nil then return end CLEANUPENTRY = true print ( "---" ) local reason local start, stop, line, msg if errmsg == nil then reason = "complete" else -- -- civilized error reporting, thanks to Bruno K. and Jean-Bob -- start, stop, line, msg = errmsg:find ( ":(%d+):%s()" ) if msg ~= nil then errmsg = errmsg:sub ( msg, #errmsg ) end if errmsg:find ( "Cancelled" ) ~= nil then reason = "cancelled" else reason = "error" end end Ident ( ReVersion .. " " .. reason ) if reason == "error" then print ( "Unexpected error detected" ) print ( "Error line: " .. line ) print ( "Error: \"" .. errmsg .. "\"" ) end end xpcall ( main, cleanup )

Comments


LociOiling Lv 1

As discussed in chat with Boots McGraw, keyboard shortcuts only allow access to quicksave slots 1 to 8. You're on your own if your recipe stored things in slots 9 to 99.

Slot Grabber first checks to see which quicksave slots are occupied. This gets reported in the the scriptlog and in the dialog.

In the dialog, the "Quickload slot" field is initially blank. If you enter an occupied slot number, that slot will be loaded.

The "Save all occupied slots" checkbox converts each occupied slot to a named save when checked. The "Prefix for saves" textbox adds the text you enter to the save name, otherwise they're just called "slot 1", "slot 2", and so on.

Named saves are available in Open/Share Solutions, also known as the Manage Solutions dialog.

The "Occupied slots" textbox in the dialog is just a list of the occupied slots that you can copy and paste or scroll through. It's in "set" format, to if slot 8 is occupied, but 7 and 9 aren't, you'll see 8-8 listed. It might look like this:

1-3, 8-8, 11-14, 22-22

If all quicksave slots are occupied, an extra named save is created to allow restoring the current pose. Otherwise, the first available slot is used to save and restore the current pose. The current pose may have just been loaded from a slot.

LociOiling Lv 1

The named saves feature was added in part to demonstrate what a recipe can do.

As jeff101 pointed out in chat, quicksaves are also available under Open/Share Solutions if you check "show auto and quick saves". The quicksaves shown are specific to the current track. They names like "Quicksaved Soloist Solution 1".

The "save occupied slots" feature in Slot Grabber adds the saves to the main list, where it will be visible across tracks. This way, you won't need to worry about another recipe using a slot and replacing whatever was in "Quicksaved Soloist Solution 1". You also have the prefix feature, allowing more meaningful names.

A quick test shows that even if you rename "Quicksaved Soloist Solution 1", it gets wiped out as soon as you save to that slot again. One solution to that is to share "Quicksaved Soloist Solution 1" ("Upload for Myself" would work). A shared solution is safe for later download.