diff --git a/api.lua b/api.lua index f0d62b2..6346c62 100644 --- a/api.lua +++ b/api.lua @@ -19,7 +19,7 @@ function classroom.get_group_students(name) local students = {} for _, student in pairs(group.students) do - if minetest.get_player_by_name(group.students) then + if minetest.get_player_by_name(student) then students[#students + 1] = student end end @@ -27,6 +27,23 @@ function classroom.get_group_students(name) return students end +function classroom.get_students_except(students) + local student_by_name = {} + for _, name in pairs(students) do + student_by_name[name] = true + end + + local retval = {} + for _, player in pairs(minetest.get_connected_players()) do + if not student_by_name[player:get_player_name()] and + true then --not minetest.check_player_privs(player, { teacher = true }) then + retval[#retval + 1] = player:get_player_name() + end + end + + return retval +end + function classroom.get_all_groups() return _groups end @@ -50,6 +67,30 @@ function classroom.create_group(name) return group end +function classroom.add_student_to_group(name, student) + local group = classroom.get_group(name) + if group then + for i=1, #group.students do + if group.students[i] == student then + return + end + end + + group.students[#group.students + 1] = student + end +end + +function classroom.remove_student_from_group(name, student) + local group = classroom.get_group(name) + if group then + for i=1, #group.students do + if group.students[i] == student then + table.remove(group.students, i) + end + end + end +end + function classroom.register_action(name, def) def.name = name _action_by_name[name] = def diff --git a/gui.lua b/gui.lua index b43d36c..8bdad3f 100644 --- a/gui.lua +++ b/gui.lua @@ -87,6 +87,15 @@ sfinv.register_page("classroom:edu", { fs[#fs + 1] = selection_id fs[#fs + 1] = "]" + fs[#fs + 1] = "button[5.25,-0.2;1.4,1;new_group;New Group]" + if context.groupname then + fs[#fs + 1] = "button[6.65,-0.2;1.4,1;edit_group;Edit Group]" + else + fs[#fs + 1] = "box[6.65,-0.1;1.2,0.7;#222]" + fs[#fs + 1] = "label[6.8,0.05;Edit Group]" + fs[#fs + 1] = "tooltip[6.65,-0.2;1.4,1;Please select a group first]" + end + fs[#fs + 1] = "container[5.25,1.1]" fs[#fs + 1] = "box[-0.25,-0.3;3.1,1.15;#666]" fs[#fs + 1] = "label[0,-0.3;Run actions on:]" @@ -207,6 +216,11 @@ sfinv.register_page("classroom:edu", { end end + if fields.new_group then + classroom.show_new_group(player) + return true + end + for _, action in pairs(classroom.get_actions()) do if fields["action_" .. action.name] then local selector @@ -245,3 +259,157 @@ end minetest.register_on_priv_grant(on_grant_revoke) minetest.register_on_priv_revoke(on_grant_revoke) + + +function classroom.show_new_group(player) + if not minetest.check_player_privs(player:get_player_name(), { teacher = true }) then + return + end + + minetest.show_formspec(player:get_player_name(), "classroom:new_group", [[ + size[5,1.8] + field[0.2,0.4;5,1;name;Name;] + button[1.5,1;2,1;create;Create] + ]]) +end + + +minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname ~= "classroom:new_group" or + not minetest.check_player_privs(player:get_player_name(), { teacher = true }) or + not fields.create then + return false + end + + local group = classroom.create_group(fields.name) + if group then + classroom.show_edit_group(player, group.name) + else + classroom.show_new_group(player, fields.name) + end +end) + +local _contexts = {} + +function classroom.show_edit_group(player, groupname) + local name = player:get_player_name() + if not minetest.check_player_privs(name, { teacher = true }) then + return + end + + local context = _contexts[name] or {} + _contexts[name] = context + + context.groupname = groupname or context.groupname + context.index_l = context.index_l or 1 + context.index_r = context.index_r or 1 + + local fs = { + "size[5.55,6]", + "label[0,-0.1;Other students]", + "label[3.3,-0.1;Students in group ", minetest.formspec_escape(context.groupname), "]", + "button[2.25,0.5;1,1;go_right;", minetest.formspec_escape(">"), "]", + "button[2.25,1.5;1,1;go_left;", minetest.formspec_escape("<"), "]", + } + + local members = classroom.get_group_students(groupname) + if #members > 0 then + if context.index_r > #members then + context.index_r = #members + end + fs[#fs + 1] = "textlist[3.25,0.5;2,5.5;right;" + for i, member in pairs(members) do + if i > 1 then + fs[#fs + 1] = "," + end + fs[#fs + 1] = minetest.formspec_escape(member) + end + + fs[#fs + 1] = ";" + fs[#fs + 1] = tostring(context.index_r) + fs[#fs + 1] = "]" + else + fs[#fs + 1] = "label[3.5,0.7;No students]" + end + + local not_members = classroom.get_students_except(members) + if #not_members > 0 then + if context.index_l > #not_members then + context.index_l = #members + end + + fs[#fs + 1] = "textlist[0,0.5;2,5.5;left;" + + for i, member in pairs(not_members) do + if i > 1 then + fs[#fs + 1] = "," + end + fs[#fs + 1] = minetest.formspec_escape(member) + end + + fs[#fs + 1] = ";" + fs[#fs + 1] = tostring(context.index_l) + fs[#fs + 1] = "]" + else + fs[#fs + 1] = "label[0.4,0.7;No students]" + end + + minetest.show_formspec(player:get_player_name(), "classroom:edit_group", table.concat(fs, "")) +end + +minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname ~= "classroom:edit_group" or + not minetest.check_player_privs(player:get_player_name(), { teacher = true }) then + return false + end + + local context = _contexts[player:get_player_name()] + if not context or not context.groupname then + return false + end + + if fields.left then + local evt = minetest.explode_textlist_event(fields.left) + if evt.type == "CHG" then + context.index_l = evt.index + return true + end + end + + if fields.right then + local evt = minetest.explode_textlist_event(fields.right) + if evt.type == "CHG" then + context.index_r = evt.index + return true + end + end + + if fields.quit then + _contexts[player:get_player_name()] = nil + end + + if fields.go_right and context.index_l then + local students = classroom.get_group_students(context.groupname) + local not_members = classroom.get_students_except(students) + local student = not_members[context.index_l] + if student then + classroom.add_student_to_group(context.groupname, student) + classroom.show_edit_group(player, context.groupname) + return true + end + end + + if fields.go_left and context.index_r then + local students = classroom.get_group_students(context.groupname) + local student = students[context.index_r] + if student then + classroom.remove_student_from_group(context.groupname, student) + classroom.show_edit_group(player, context.groupname) + return true + end + end +end) + +minetest.register_on_leaveplayer(function(player) + _contexts[player:get_player_name()] = nil +end) diff --git a/tests/api_spec.lua b/tests/api_spec.lua new file mode 100644 index 0000000..ed14a98 --- /dev/null +++ b/tests/api_spec.lua @@ -0,0 +1,20 @@ +_G.classroom = {} + +require("api") + +describe("classroom", function() + it("groups", function() + assert.is_nil(classroom.get_group("test")) + classroom.create_group("test") + assert.is_not_nil(classroom.get_group("test")) + assert.equals(0, #classroom.get_group("test").students) + classroom.add_student_to_group("test", "user1") + assert.equals(1, #classroom.get_group("test").students) + classroom.add_student_to_group("test", "user1") + assert.equals(1, #classroom.get_group("test").students) + classroom.remove_student_from_group("test", "user2") + assert.equals(1, #classroom.get_group("test").students) + classroom.remove_student_from_group("test", "user1") + assert.equals(0, #classroom.get_group("test").students) + end) +end)