Icon representing a recipe

Recipe: cleanup v1.0

created by LociOiling

Profile


Name
cleanup v1.0
ID
101925
Shared with
Public
Parent
None
Children
None
Created on
February 27, 2016 at 23:18 PM UTC
Updated on
February 27, 2016 at 23:18 PM UTC
Description

This a demo of using the xpcall function to provide a cleanup routine. The cleanup routine in this recipe can be used in any Lua recipe.

Best for


Code


--[[ cleanup -- cleanup function demo This recipe prints some possibly useful information and then cleans up. Using the Lua function "xpcall" lets your recipe catch errors and user cancels, and treat them in the same way as a normal termination. To use xpcall, organize your recipe into one main function and include a cleanup function. In this example, these functions are called "main" and "cleanup". As shown here, xpcall is generally the last line of the recipe. Call xpcall with names of your main and cleanup functions. Since bugs can happen anywhere, it's probably best to include all initialization inside your main function. If desired, you can group things like seeding the random number generator into a function called "initialize", and then call this function at the beginning of your main function. There are several benefits to using xpcall. Many long-running recipes end up being cancelled by the user. The cleanup routine in this example detects a cancel. A cancel ends up being treated like a normal end to the recipe. In some cases, a coding error, such as a syntax error or specifying a segment that's out of range, will terminate the recipe. The cleanup routine shown here detects errors and applies a user-friendly format to the error information. A good cleanup routine tries to salvage the situation by doing as much normal termination as possible. This might include deleting bands, deselecting segments, restoring secondary structures, resetting the clashing importance, and, of course, restoring the best score. To avoid duplicating termination logic, the main function should always call the cleanup function. When the cleanup function shown in this example is called without arguments, it's a "normal" termination. If the cleanup routine itself hits an error, it will be called again. The cleanup shown here sets and checks a variable to prevent a loop if it encounters an error. (Any loop gets terminated automatically after several iterations, so this is not absolutely required.) Some bugs in the Foldit Lua functions cause a client crash. Unfortunately, the cleanup routine does not get a chance to deal with this type of error. This sample includes two commented-out sections, one in the main function, and one in the cleanup, which will cause a crash is uncommented. Thanks to Bruno Kestemont and Jean-Bob for the logic which parses the error message passed to the cleanup function. ]]-- -- -- model 001 -- standard recipe name and version -- Recipe = "cleanup" Version = "1.0" ReVersion = Recipe .. " v." .. Version function round ( x )--cut all afer 3-rd place return x - x % 0.001 end function main () -- -- model 010 - startup - print recipe name, puzzle name, track -- print ( ReVersion ) print ( "Puzzle: " .. puzzle.GetName () ) print ( "Track: " .. ui.GetTrackName () ) print ( "--" ) local score = current.GetEnergyScore () print ( "score = " .. round ( score ) ) local segcnt = structure.GetCount () print ( "segment count = " .. segcnt ) print ( "score / segment = " .. round ( score / segcnt ) ) local freezes = 0 local phobes = 0 local locks = 0 local mutables = 0 local worstseg = 0 local worstsegscore = 99999 local bestseg = 0 local bestsegscore = -99999 for ii = 1, segcnt do if freeze.IsFrozen ( ii ) then freezes = freezes + 1 end if structure.IsHydrophobic ( ii ) then phobes = phobes + 1 end if structure.IsLocked ( ii ) then locks = locks + 1 end if structure.IsMutable ( ii ) then mutables = mutables + 1 end local segscore = current.GetSegmentEnergyScore ( ii ) if segscore > bestsegscore then bestsegscore = segscore bestseg = ii end if segscore < worstsegscore then worstsegscore = segscore worstseg = ii end end print ( "frozen segments = " .. freezes ) print ( "hydrophobic segments = " .. phobes ) print ( "locked segments = " .. locks ) print ( "mutable segments = " .. mutables ) print ( "best segment = " .. bestseg .. ", score = " .. round ( bestsegscore ) ) print ( "worst segment = " .. worstseg .. ", score = " .. round ( worstsegscore ) ) --[[ -- -- a bad function call can cause a crash -- print ( "call unimplemented function = " .. nonesuch () ) ]]-- -- -- always exit via the cleanup routine -- cleanup () end function cleanup ( error ) -- -- optionally, do not loop if cleanup causes an error -- (any loop here is automatically terminated after a few iterations, however) -- if CLEANUPENTRY ~= nil then return end CLEANUPENTRY = true print ( "---" ) local reason local start, stop, line, msg if error == nil then reason = "complete" else -- -- model 120 - civilized error reporting, -- thanks to Bruno K. and Jean-Bob -- start, stop, line, msg = error:find ( ":(%d+):%s()" ) if msg ~= nil then error = error:sub ( msg, #error ) end if error:find ( "Cancelled" ) ~= nil then reason = "cancelled" else reason = "error" end end -- -- model 100 - print recipe name, puzzle, track, time, score, and gain -- print ( ReVersion .. " " .. reason ) print ( "Puzzle: " .. puzzle.GetName () ) print ( "Track: " .. ui.GetTrackName () ) if reason == "error" then print ( "Unexpected error detected" ) print ( "Error line: " .. line ) print ( "Error: \"" .. error .. "\"" ) end -- -- model 130 - reset clash importance, clear selections, restore structures, etc. -- --[[ -- -- it's possible to crash the cleanup routine -- print ( "call unimplemented function = " .. nonesuch () ) ]]-- end -- main call xpcall ( main, cleanup ) --end of script

Comments


LociOiling Lv 1

This recipe shows how to use the Lua "xpcall" function to provide a cleanup routine. The cleanup function in this recipe can be used in any recipe written using version 2 of the Foldit-Lua interface.

A cleanup function lets your recipe recover when the user cancels it or when it crashes due to a Lua syntax error or an incorrect argument to a Foldit function. Having a cleanup function allows the recipe to always do normal cleanup tasks, such as resetting secondary structure, deleting bands, and restoring the best score.

To avoid duplicating code, the mainline logic in your recipe should simply call the cleanup function when it's done. When the cleanup function in this recipe is called without an argument, it's treated as a normal termination at the end of the recipe.