Metadata-Version: 2.4
Name: cardtrio-terminal
Version: 0.2.0
Summary: 144 terminal learning cards with Google Sheets tokens and admin review
License-Expression: MIT
Keywords: education,python,html,javascript,terminal
Classifier: Programming Language :: Python :: 3
Classifier: Environment :: Console
Classifier: Topic :: Education
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# CardTrio

A Python terminal client for three courses, backed by your Google Sheet and a
Google Apps Script admin dashboard. Learners submit code or text for **manual
review**. An administrator's approval unlocks the next step.

| Course | Subject | Lesson cards | Challenges |
| --- | --- | ---: | ---: |
| python96 | Python | 48 | 12 |
| BattleAI | HTML | 48 | 12 |
| microduck | JavaScript | 48 | 12 |

Every card includes a lesson, an example, and a practice problem. Every fourth
card is followed by a challenge. There are **144 cards and 36 challenges** in
total. This is an original standalone implementation with no ICOA dependency.

## 1. Set up Google Apps Script

1. Open your course Google Sheet. Choose **Extensions → Apps Script**.
2. Replace the entire previous `Code.gs` with `apps-script/Code.gs` from this
   project. Remove any earlier versions of `doGet`, `doPost`, or public admin
   helpers in other files so they cannot conflict with these handlers.
3. Add a script file named **Curriculum** and paste `apps-script/Curriculum.gs`.
4. Add an **HTML** file named **Admin** and paste `apps-script/Admin.html`.
5. Optionally enable “Show appsscript.json manifest file” in project settings
   and replace it with the supplied `apps-script/appsscript.json`.
6. Select **setup_** in the editor and run it. Authorize access to the Sheet.
   The trailing underscore is intentional: it keeps this setup helper private
   from web-page RPC calls.
7. Select **Deploy → New deployment → Web app**. Execute as **Me**, and allow
   **Anyone** to access the endpoint. Learners are authenticated by their course
   tokens, and admin actions require a server-validated admin session. If your
   Workspace account does not permit anonymous web-app access, a plain terminal
   client cannot use that deployment without an additional Google sign-in flow.
8. Copy the production URL ending in **`/exec`**, not `/dev`.

`setup_` seeds the full curriculum automatically; a CSV import is not required.
It creates these tabs and validates their headers:

- **Catalog**: lessons, practice, challenges, and reference answers.
- **Tokens**: token, student, courses, active state, optional expiry.
- **Reviews**: submitted work, status, feedback, review time, revision.

The initial admin password is **`admin`**. It is hashed with a random salt and
stored in Script Properties, not in HTML or the Python client. Re-running setup
preserves an existing password and existing data. An existing compatible Catalog
is kept as-is rather than overwritten. Keep the Sheet private to its administrators.

For an unbound Apps Script project, set `SPREADSHEET_ID` in Script Properties to
your Sheet ID before running `setup_`. Do not copy another spreadsheet's ID.

## 2. Open the admin dashboard

Append **`?page=admin`** to your deployed URL:

```text
https://script.google.com/macros/s/YOUR_DEPLOYMENT_ID/exec?page=admin
```

Sign in with `admin`. The dashboard provides:

- A queue filtered by course and review status, with pagination.
- Submitted code rendered as text, the problem, lesson context, and a reference
  answer. Other correct solutions can be approved; exact matching is not required.
- **Approve & unlock next step**, with optional feedback.
- **Request changes**, requiring actionable feedback. The learner can revise
  and submit a new attempt. Earlier attempts remain in the ledger.
- Token issuance for any one course or all three, optional expiration, and
  enable/disable controls.
- A Settings page for changing the admin password. This revokes existing admin
  sessions. Sessions otherwise expire after one hour and can expire earlier if
  Apps Script evicts its cache. Sign in again when prompted.

The dashboard does not run submitted code. HTML is displayed as text, not
rendered as a page. The only network requests made by the learner client target
Google Apps Script and its Google-hosted response redirects.

## 3. Install and run the learner client

Requires Python **3.10 or later**. There are no runtime third-party dependencies.

From the extracted project directory:

```sh
python -m pip install .
cardtrio configure
cardtrio
```

For an already-built wheel:

```sh
python -m pip install dist/cardtrio_terminal-0.2.0-py3-none-any.whl
cardtrio configure
cardtrio
```

On Windows, `py` may be used instead of `python`. If scripts are not on PATH,
use `python -m cardtrio` and `python -m cardtrio configure`.

Configure the **base `/exec` URL without `?page=admin`**. An admin issues access
tokens in the dashboard's Access tokens tab, then provides each learner their
token. Tokens are reusable access codes, not a consumable credit balance.

Shortcuts:

```sh
python96
battleai
microduck
cardtrio --course BattleAI
```

Tokens are entered with a hidden password prompt and are not saved to disk.
`CARDTRIO_TOKEN` and `CARDTRIO_URL` can optionally supply login configuration.
The endpoint is stored in `~/.cardtrio/config.json`. `CARDTRIO_HOME` overrides
the local settings directory.

### During a lesson

- Enter a short answer and press Enter to submit it for review.
- Use **`:multi`** for multiline code. A line containing only `.` ends input.
- Use **`:file PATH`** to submit a UTF-8 source file after preview and confirmation.
- Use **`:hint`** to revisit the lesson rule.
- Use **`:refresh`** to check for an admin decision.
- Use **`:menu`** to change courses, or **`:quit`** to close the program.

Submissions are limited to 8,000 characters. No arbitrary code is executed by
the terminal application or backend. A local outbox preserves unconfirmed
submissions without storing the token. Network retries reuse the request ID,
so a lost response cannot submit the same work twice. If a local retry becomes
obsolete, the retry prompt's `d` option discards only that local retry; it does
not cancel work already received by the administrator.

Approval is required before the next step becomes available. Completion is
derived from the contiguous sequence of approvals in Reviews, keeping progress
and the review decision in one authoritative record. Do not manually reorder
or change review statuses unless intentionally repairing data.

## Updating an earlier draft

Version 0.2 replaces automatic exact-answer grading with manual review. Earlier
`Progress` and `Submissions` tabs are not deleted or imported; they remain an
archive. Manual-review progress starts in the new **Reviews** tab. Existing
compatible Tokens and Catalog tabs are reused. A mismatched header causes setup
to stop rather than replace the sheet's data.

## Curriculum maintenance

The authoring source is `tools/build_curriculum.py`. Regenerate bundled data and
the Apps Script seed after editing it:

```sh
python tools/build_curriculum.py
python -m cardtrio check
python -m cardtrio export --output Catalog.csv
```

The CSV export is optional and useful for editing an existing Catalog. Back up
the Sheet before replacing content. Do not renumber active course steps because
reviews refer to those step numbers. Apps Script source changes require a new
deployment version; simply saving the editor does not update a production `/exec`
deployment.

## Tests

From a source checkout, install the package first or set `PYTHONPATH=src`:

```sh
python -m unittest discover -s tests -p "test_*.py" -v
node tests/test_backend.cjs
```

The backend tests execute the actual Apps Script source with in-memory Google
service doubles. They cover authentication, token permissions, expiration,
manual review, feedback, idempotency, revisions, progression, and header safety.
They do not replace a live Google deployment test.

The optional browser test requires Node.js, Playwright, and Chromium:

```sh
node tests/test_admin_browser.cjs
```

It uses the real HTML and backend with service doubles, checks the review and
token flows, and saves desktop/mobile screenshots in `artifacts/`. Set
`CHROMIUM_PATH` if Chromium is not at `/usr/bin/chromium`.

## PyPI release

The working distribution name is **cardtrio-terminal**. Availability and ownership
have not been verified. Choose a name you control in `pyproject.toml` before
publishing. The installed command names can remain unchanged.

```sh
python -m pip install build twine
python -m build
python -m twine check dist/*
python -m twine upload --repository testpypi dist/*
```

After checking TestPyPI and finalizing your package metadata, publish to your
PyPI account with `python -m twine upload dist/*`. Upload credentials belong in
your publishing environment, not in this package. No PyPI upload or Google
Apps Script deployment is performed merely by installing or running CardTrio.

The MIT license covers this original code and curriculum. There is no ICOA code,
content, branding, or service dependency.

References: [Python packaging](https://packaging.python.org/en/latest/tutorials/packaging-projects/)
and [Apps Script web apps](https://developers.google.com/apps-script/guides/web).
