説明なし

Gregory Huxley 6df801a403 Make worded questions work again.. 1 週間 前
audio 1686ade99e Update gitignore and More fixes 1 週間 前
fraction 3f8bcdaf28 initial commit 2 週間 前
images 3f8bcdaf28 initial commit 2 週間 前
obsolete ee350c0968 More fixes 1 週間 前
questionGenerators 6df801a403 Make worded questions work again.. 1 週間 前
resources 6df801a403 Make worded questions work again.. 1 週間 前
templates 1686ade99e Update gitignore and More fixes 1 週間 前
timekeeperClientServices f3c61fd3f1 Update timer.php to sent 1440 instead of 30 when Timekeeper is disabled. 1 週間 前
.gitignore 214f331e1d Remove IDE folder.. 1 週間 前
PreHeaderFunctions.php bb3c17237e More fixes 1 週間 前
README.md 6df801a403 Make worded questions work again.. 1 週間 前
TK2.php 6df801a403 Make worded questions work again.. 1 週間 前
TkAnswerStore.php 4c5028103a More fixes 1 週間 前
admin_prefs.php f9bcfa822a Add Readme. And add Per-student limits to admin section. 1 週間 前
answerChecker2.php 6df801a403 Make worded questions work again.. 1 週間 前
e_cron.php bb3c17237e More fixes 1 週間 前
plugin.xml 3b89011b89 More fixes 1 週間 前
timekeeper.php d0cec6e6c3 More fixes 1 週間 前
timekeeper_menu.php 3b89011b89 More fixes 1 週間 前
timekeeper_shortcodes.php 1686ade99e Update gitignore and More fixes 1 週間 前
timekeeper_sql.php 3b89011b89 More fixes 1 週間 前
tk_stats_page.php d0cec6e6c3 More fixes 1 週間 前

README.md

TimeKeeper

An e107 plugin that makes screen time something students earn. Students answer questions (maths, spelling, anagrams, the periodic table); correct answers earn play minutes. A separate program on each student's computer (TimekeeperEnforcement) asks this server how many minutes are left and closes games when there are none.

  • Students answer questions at /e107_plugins/timekeeper/timekeeper.php.
  • Parents/admins get a daily report email, PDF/HTML reports, a stats page, and admin screens for scores, answers and the spelling word list.
  • The enforcement client talks to timekeeperClientServices/timer.php.

Requirements

  • e107 2.x (compatibility="2.0" in plugin.xml)
  • PHP 7.1 or newer, MySQL/MariaDB
  • Apache, if you want the .htaccess-style blocking described under Security
  • Optional: wkhtmltopdf on the server (PDF reports), a text-to-speech server for spelling audio (see Spelling audio), e107 mail configured (daily report emails)

Install

  1. Put the folder at e107_plugins/timekeeper/ (lower case: the URLs assume it).
  2. Admin → Plugin Manager → install TimeKeeper. This creates the tables from timekeeper_sql.php.
  3. Put each student in the TimeKeeper_Student user class (and any teacher in TimeKeeper_Teacher). plugin.xml declares both; check Admin → User Classes that they exist. The code checks them as TIMEKEEPER_STUDENT and TIMEKEEPER_TEACHER.
  4. Admin → TimeKeeper → Preferences: set the Stats / summary key (see Security).
  5. Make audio/ writable by the web server user. The spelling questions save their spoken audio there.
  6. Add words under Admin → TimeKeeper → Spelling Words → Add Words. Each needs a word, a usage sentence and a year level (1–13). Words without a usage sentence are never asked.
  7. Optional: Menu Manager → enable the TimeKeeper menu (timekeeper_menu.php) for the sidebar score box, and Admin → Scheduled Tasks (cron) → enable Send Reports for the daily email.

Per-student limits

Each student has one row in the timekeeper table. Edit them at Admin → TimeKeeper → Student Limits: one form with a row per student, plus an Add a student box (the student needs an e107 account). A row with an invalid value is left unchanged and the problem is shown; the other rows still save. timer.php also creates the row, with the starting values below, the first time the enforcement client asks about a student who has an e107 account.

Column Default Meaning
enabled 1 0 = no limit for this student (the server replies 1440)
freeMins 10 Play minutes every day that don't need earned minutes
enableTime / disableTime 10.00 / 22.00 Allowed play window as HH.MM (22.30 = 10:30 pm). Write minutes as two digits: 9.5 means 9:50, not 9:30
minQuestionCount 100 Questions to answer today before earned minutes can be used
maxDailyPlayTime 1440 Most minutes of play in a day, free and earned
usedMinutes, lastDate 0 Counters kept by the server (the screen shows today's usedMinutes for information)

The window and day boundaries use the time zone set in timekeeperClientServices/timer.php (Australia/Perth). Change it there if you're elsewhere.

How it works

Questions. TK2.php picks a subject from the list in $subjectsList, based on the student's difficulty (all-time question count × last month's accuracy %), then asks the generator in questionGenerators/. A subject unlocks at a difficulty threshold:

Subject Unlocks at
numbers (missing number), spelling 0
addition 10,000
subtraction 20,000
elements (periodic table) 150,000
multiplication 200,000
anagrams 4,000,000

Division, rounding, worded problems and the geography/history/health subjects exist or are stubbed but are switched off (the 0 in $subjectsList in TK2.php). To switch one on, change that 0 to a 1. Worded problems (word_problems) would unlock at 250,000 and use whole-number answers only: pillow cases, sponges, an elephant's dinner, sandwiches, marbles, a day at the beach, cupcakes and sugar bags. The numbers get bigger as the student's accuracy and number of answers grow.

Answers. The expected answer never goes to the browser. The generator stores it in the tkPendingAnswer table (TkAnswerStore.php) and the form carries a random single-use token (checkerData). Answering consumes the token, so a changed token, a stale browser tab, a double submit or an old question gets "That question has expired or was already answered". Tokens last 2 hours.

Scoring. A correct answer adds round(last month's accuracy % ÷ 10) minutes (at least 1). A wrong answer takes one minute off, never below zero. Every answer is written to tkReport.

Play time. The enforcement client calls timer.php once a minute while a game is running. The reply is a number (minutes remaining) or a message explaining why play isn't allowed. The server uses today's free minutes first, then earned minutes (only if minQuestionCount questions were answered today).

Pages and URLs

URL (under /e107_plugins/timekeeper/) Who What
timekeeper.php students, teachers The questions page
timekeeper.php?mode=Generate%20PDF&user=NAME&output=pdf (or html) &range=today logged in: admin, or that student Report of answered questions. range: today, yesterday, pastWeek, pastMonth, pastQuarter, pastYear
timekeeper.php?mode=short&user=NAME&range=today same, or with &key= Question count and accuracy
tk_stats_page.php?user=NAME&key=KEY anyone with the key (anyone at all if no key is set) Per-subject scores and minutes left; refreshes every minute
timekeeperClientServices/timer.php?user=NAME&game=PROCESS the enforcement client Minutes remaining; &peek=1 doesn't use a minute
timekeeperClientServices/games.json the enforcement client Process names to treat as games

Admin area

Admin → TimeKeeper (needs the Plugin Manager permission): Student Limits, Score, Report (every answer), Spelling Words (list, add, and a "Spelling Score" summary showing how many words still need a usage sentence), Geography (data only: unused so far), Preferences. Questions, Pending and Report (Old) are screens for tables from an earlier version.

Database

Table Holds
timekeeper Per-student limits (above)
timekeeperScore Lifetime counts and earned minutes
tkReport Every answer given
tkLastQuestion The question currently on screen, per student
tkPendingAnswer The expected answer behind it (single use)
timekeeperStatistics Minutes played per student, game and day
tk_wordList Spelling and anagram words
tk_countries Country data for the unfinished geography subject
timekeeperPending, timekeeperQuestions, timekeeperReport, timekeeperStats Earlier versions; still listed in plugin.xml

Tables from an earlier install: add any that are missing from timekeeper_sql.php and run SELECT user, COUNT(*) FROM e107_tkLastQuestion GROUP BY user;. If a student has more than one row, DELETE FROM e107_tkLastQuestion; clears them: the next question regenerates.

Spelling audio

questionGenerators/english/spelling2.php asks a text-to-speech server for each word, saves it to audio/<md5 of the word>.mp3, and reuses it. The server address is the TTS_URL constant at the top of that file (an OpenAI-style /v1/audio/speech endpoint). It needs allow_url_fopen. If audio can't be produced, the sentence is shown with the word blanked out instead.

Security

  • Stats key. Set it under Preferences. Without one, tk_stats_page.php shows any student's scores to anyone who knows the username.
  • Reports need a login. A student can only see their own.
  • Keep obsolete/ unreachable. It holds old code that no longer ships. If you deploy by copying the repo, block it in the Apache vhost:

    <Directory /path/to/e107_plugins/timekeeper/obsolete>
      Require all denied
    </Directory>
    

    and check a file in it returns 403. Also consider Options -Indexes for the site root.

  • Nothing the student types or the URL contains is trusted: user names and game names are validated, SQL is escaped, and output is HTML-escaped.

  • This repo is readable without signing in. e_cron.php contains the report email addresses and student account names: don't commit anything private.

Daily report email

e_cron.php emails each student's previous day (questions, accuracy, active study time) to the parent address and the student. The names and addresses are in one block at the top of the file: edit them there. The reporting window is "yesterday, midnight to midnight" ($windowStart, $windowEnd).

PDF and Excel

PDF reports run wkhtmltopdf; install it and make sure the web server user can run it. The Excel worksheet generator in PreHeaderFunctions.php needs lib/PHPExcel.phar, which isn't in the repo, and isn't linked from any page at the moment.

The enforcement client

TimekeeperEnforcement runs as root on each student's computer and needs Java 11+. Its README covers its settings file and a systemd unit.

games.json is a list of names (an array, or an object whose values are the names). Each name is looked for in the full command line of the student's processes: check what a game looks like first with ps -eo user,args | grep -i NAME. It's a deny-list: anything not listed isn't enforced.

Deploy timer.php before the client. If you run the old PHP client (obsolete/), it still works against the new timer.php, but it can't update itself any more.

Troubleshooting

Symptom Likely cause
"That question has expired or was already answered" Stale tab, double click, or a question older than 2 hours: answer the new question
Spelling shows "Audio is unavailable right now" audio/ missing or not writable, TTS server unreachable, or allow_url_fopen off
tk_stats_page.php is blank user isn't a plain username, the student has no timekeeper row yet, or the key is wrong (403)
Report URL gives "Forbidden" Not logged in, or logged in as a different student
Student always gets "You have not answered enough questions to play" Questions needed (minQuestionCount) on the Student Limits screen is higher than they answer in a day (default is 100)
Games close at exactly 0 minutes That's intended: free minutes are used first, then earned ones
Nothing is closed on the student's machine Check the client's log, and that the game name in games.json really appears in ps output