Multiple iPads, Backing Up Code, Restoring Code

@TokOit - he is running a school class

@dave1707 @Ignatz

It’s a proof of concept, so it could certainly use being more robust.

The student’s name is saved with each project. For convenience’ sake, each student keeps their project on the iPad, but its tabs are empty between sessions. If the project gets deleted, they can just create a new one and re-enter their name. Eg.

  • Johnny Smith creates a project called Johnnys project
  • Makes Dropbox Backup a dependency of Johnnys project
  • Runs his code, backing up the project as Johnny Smith.lua
  • At end of his session, his tabs are cleared, but his project remains, and the project retains his name.

The next obvious step would be to add a password ( and store it with a hash if you want to get serious), so that only Johnny can restore his project.

@dave1707 the name is saved with the host project, not in the Dropbox Backup dependency. It doesn’t persist between host projects.

Or, perhaps simpler than passwords, get them to enter their name and a unique file name, one that they’ll be able to remember but others wouldn’t necessarily be able to guess, and save the projects as NAME - FILENAME.lua . You could have it so one or both fields doesn’t persist between reloads (ie all students use the same host project). I’ll post a version that works that way later today.

Why would you need more than one project, if it empties itself between sessions, and if students have to enter a file name to be loaded?

Wow! A simple (maybe not so simple) question and all of this help and sudden code development.

I am really touched - I belong to many development communities and this one gets the prize for sheer volume of help.

@yojimbo2000 - if nothing else comes of this, you have at least given me a great example of how to use Codea features that I have not explored at this time.

My other option is to upgrade my hosting plan to allow me to install my own git server and use that option.

@TokOut - as Ignatz stated I teach a face to face class, and I am in Australia.

@fly.ing.fox - hello from Perth

@Ignatz - that is not in Australia … it is more in the Asia Pacific region :smile:

It is probably one of the only cities in Australia I have never visited. I have been through WA but not Perth.

we like it that way, it’s too good to share with easterners!

Ok, this version saves the projects as NAME_ PROJECT.lua. That should hit the sweet spot in terms of being easy enough for the student to remember, but hard for other students to guess. It wipes the name fields when you press the “save & clear” button at the end of the lesson. So all users of the iPad can just use the same project to host their code. I recommend connecting all the iPads to the same Dropbox account. You won’t be able to see the .lua files in the Codea asset picker, but you can view them on your computer Dropbox. Files are in Codea’s paste-into-project format, so in an emergency you can restore a project from the clipboard.


--# DropboxBackup
-- Dropbox Backup
local dropboxPath = os.getenv("HOME").."/Documents/Dropbox.assets/"
local student_name = readLocalData("student_name", "")
local unique_project_id = readLocalData("unique_project_id", "")
local defaultProject = [[
-- Use this function to perform your initial setup
function setup()
    print("Hello World!")
end

-- This function gets called once every frame
function draw()
    -- This sets a dark background color 
    background(40, 40, 50)

    -- This sets the line thickness
    strokeWidth(5)

    -- Do your drawing here
end

function touched(touch)
    -- Check for touches here
end
]]

local function loadWorkspace()
    local data
    local path = dropboxPath..student_name.."_"..unique_project_id..".lua"
    local file, err = io.open(path, "r")        
    if file then
        data=file:read("*all")
        file:close()
    else
        alert(err)
        return
    end
    data = data.."\
--# "
    for name, tab in data:gmatch"(%w-)\
(.-)\
%-%-# " do
        saveProjectTab(name, tab)
        print("Loading ", name)
    end
    local tabNames = listProjectTabs()
    for i,name in ipairs(tabNames) do
        load(readProjectTab(name))()
    end
    setup()
end

local function saveWorkspace()
    local tabCon = {}
    local tabNames = listProjectTabs()
    for i,name in ipairs(tabNames) do
        tabCon[#tabCon+1] = "--# "..name
        tabCon[#tabCon+1] = readProjectTab(name)
        print("Saving ", name)
    end
    local data = table.concat(tabCon, "\
")
    local file, err = io.open(dropboxPath..student_name.."_"..unique_project_id..".lua", "w")
    if file then
        file:write(data)
        file:close()
    end
end

local function clearTabs()
    saveWorkspace()
    local tabNames = listProjectTabs()
    for i,name in ipairs(tabNames) do
        if name == "Main" then
            saveProjectTab(name, defaultProject)
        else
            saveProjectTab(name, nil)
        end
    end
    saveLocalData("student_name", nil)
    saveLocalData("unique_project_id", nil)
    close()
end

parameter.text("student_name", student_name, function(name) saveLocalData("student_name", name) end)

parameter.text("unique_project_id", unique_project_id, function(name) saveLocalData("unique_project_id", name) end)

parameter.action("Load", loadWorkspace)

parameter.action("Save", saveWorkspace)

parameter.action("Save & Clear", clearTabs)
--# Main
-- Dropbox Backup

parameter.clear()

print([[
SETUP - TEACHER
1. Create a project that each user of the iPad will load their code into. Call it "class workspace" or whatever
2. Open "class workspace" and make "Dropbox Backup" a dependency of it (tap the + in the top-right corner)

INSTRUCTIONS - STUDENT
1. Open "class workspace" 
2. When you run "class workspace", enter your name and a unique project id in the box
3. press "save" to save the project as you go along.
4. At the end of the lesson, press "save & clear" to save the file and then wipe all tabs
end

5. Next lesson, enter your name and project id, and press "load" to load your project into the tabs and run it

INSTRUCTIONS - TEACHER
1. because the file has a .lua extension the file won't be visible in the asset picker, so should be harder to discover/ delete
2. remember to sync dropbox in the asset picker if you want an offline backup
3. if a student forgets the project id, you can just look at the file name

]])

@yojimbo2000 - this is great. Can you put the final version on the wiki so it doesn’t get lost?

@yojimbo2000 Some minor problems with your latest version.

  1. If I do a save & clear, the students name and the project ID still remain in the text boxes. If the student puts the iPad down, and another student picks up the iPad, the previous students info is still there. save & clear should either clear all the screen info or exit the code.
  2. When I do a save & clear, I’m not really sure it saved anything, so I do it again. That results in my program being overwritten by saving the default code.
  3. After I do a save and clear and completely exit the code, when I load it and try to run the code again, it doesn’t like the name and ID. It puts up an alert. If I exit the program and try a second time, it works.

@dave1707 thanks for testing it, these are valid points. I added a close() to the end of the save & clear function. I’ve updated the code above to include this. This solves 1 and 2. I haven’t been able to reproduce the issue you describe in 3. I’m able to save & clear, then reload straight away.

@yojimbo2000 I’ll load the new code and try it. I’ll try and get a better description to #3.

@yojimbo2000 The save & clear works nice. As for #3, this is what I do. I do a save & clear. It exits the program back to the editor. I start the program again, key in my name and ID and press load. An alert pops up saying it can’t find the file or something like that. If I look at the file name, it looks like _.lua . Another thing that should be added is a check so you can’t save the default program by mistake.

If the file name is _.lua that means name and id were empty. I’ll add some tests to make sure the fields are valid before saving.

@yojimbo2000 But the name and id weren’t empty. I keyed a name and id before I pressed load.

But something must have happened before you pressed save, if the filename in Dropbox is _.lua . That’s why I’m proposing I add checks before save is allowed