Skip to content
Open

Quiz #19

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
114 commits
Select commit Hold shift + click to select a range
9369dff
with more page
daedaluschan Jul 15, 2024
2225687
path of css and js
daedaluschan Jul 15, 2024
b24ca82
correct the css file name
daedaluschan Jul 15, 2024
50086b7
missing .menu.open
daedaluschan Jul 15, 2024
8fa9ba4
using base.html to avoid repeating html codes
daedaluschan Jul 17, 2024
88093a7
comment out tariff.htlm for now
daedaluschan Jul 18, 2024
4081183
Adding the REST library
daedaluschan Aug 11, 2024
a5d2dc7
remove the tariff endpoint
daedaluschan Aug 11, 2024
a3ac49a
Hello world api endpoint
daedaluschan Aug 11, 2024
d3a06b4
switch to handl api call instead
daedaluschan Aug 18, 2024
1d719f3
try normal web again
daedaluschan Aug 24, 2024
1ea2cc0
useing restplus
daedaluschan Aug 24, 2024
913d14f
try update requirement.txt with no versioing
daedaluschan Aug 24, 2024
574d6bb
use simple web api code
daedaluschan Aug 24, 2024
f0ff9c6
with api key authenication
daedaluschan Aug 24, 2024
ba5c0f8
just changing the hello world msg
daedaluschan Aug 24, 2024
54b82ca
add api spec
daedaluschan Aug 26, 2024
98b583a
include send_from_directory
daedaluschan Aug 26, 2024
fea70de
add operationId in the spec yaml
daedaluschan Aug 26, 2024
aca72f7
api version to 3.1.0
daedaluschan Aug 26, 2024
6a171fb
appi api key part in the yaml
daedaluschan Aug 26, 2024
35fee13
Ignore about api key validation for now
daedaluschan Aug 26, 2024
5d1029c
new tariff end point
daedaluschan Aug 26, 2024
e4d19e1
updated api spec for new tariff end point
daedaluschan Aug 26, 2024
65afb1a
added the import for tariff_utils
daedaluschan Aug 26, 2024
80c756b
octopus tariff api spec
daedaluschan Aug 26, 2024
9614067
try to run request.get
daedaluschan Sep 21, 2024
8ff6201
try again request.get
daedaluschan Sep 21, 2024
cce95ed
change to simulate curl -u on the request.get()
daedaluschan Sep 21, 2024
536f23b
cast str on api_auth
daedaluschan Sep 21, 2024
34df9eb
place the secret retrieve in app.py
daedaluschan Sep 21, 2024
182f91d
correct the env var name
daedaluschan Sep 21, 2024
9a86232
put then auth parameter to carry the api key
daedaluschan Sep 21, 2024
ff967a4
continue to print the data payload
daedaluschan Sep 21, 2024
0cc1308
print out the parsed time value
daedaluschan Sep 21, 2024
d544613
correct the api end point
daedaluschan Sep 21, 2024
b1b30da
switch back
daedaluschan Sep 21, 2024
9a6b800
update requirement.txt
daedaluschan Sep 21, 2024
2446e81
not using dateutil
daedaluschan Sep 21, 2024
1b2fb5d
filter timeslot
daedaluschan Sep 21, 2024
6fdda12
not consider the current timeslot
daedaluschan Sep 21, 2024
5773c2a
calculating consecutive slot and avg tariff
daedaluschan Sep 22, 2024
97bf5d0
first draft completed
daedaluschan Sep 25, 2024
3a072e3
humm
daedaluschan Sep 26, 2024
955059b
hummm....
daedaluschan Sep 26, 2024
30b89d5
debug print
daedaluschan Sep 28, 2024
f7809ea
correct syntx on line 66
daedaluschan Sep 28, 2024
bb09914
parse the time as UTC
daedaluschan Sep 28, 2024
ccc2fd1
corrected time format
daedaluschan Sep 28, 2024
b1b94d5
converting to UK timezone with pytz
daedaluschan Sep 28, 2024
9b4a181
fixed bug
daedaluschan Sep 28, 2024
517c9c9
adding dummy endpoint for demo
daedaluschan Jan 8, 2025
6ce5a50
Merge pull request #1 from daedaluschan/add-dummy-demo-endpoint
daedaluschan Jan 8, 2025
75496b3
specify connection type when
daedaluschan Jan 8, 2025
d156ac5
Merge pull request #2 from daedaluschan/add-dummy-demo-endpoint
daedaluschan Jan 8, 2025
245ea6e
specify connection type if it is not ALL
daedaluschan Jan 8, 2025
82fbbfc
Merge pull request #3 from daedaluschan/add-dummy-demo-endpoint
daedaluschan Jan 8, 2025
15a38f9
add debug msg for the rest call status code
daedaluschan Jan 10, 2025
8cfe898
more trace
daedaluschan Jan 10, 2025
6c0a6e5
tracing different timestamp
daedaluschan Jan 10, 2025
c8faf45
New API endpoint
daedaluschan Feb 26, 2025
ea9b3eb
remove comment
daedaluschan Feb 26, 2025
047e308
upload FIX data dic xml
daedaluschan Aug 17, 2025
c339599
add xml file download route
daedaluschan Aug 17, 2025
e7ed6cd
added fixreft.html
daedaluschan Aug 17, 2025
e89d618
added route for html folder
daedaluschan Aug 17, 2025
5267598
resolve stack limit problem
daedaluschan Aug 17, 2025
d5bea94
Remove XML endpoint and static XML files
daedaluschan Apr 19, 2026
463c7a0
Merge branch 'main' into remove_xml
daedaluschan Apr 19, 2026
73dbb22
Merge pull request #4 from daedaluschan/remove_xml
daedaluschan Apr 19, 2026
9212f83
new_octopus_endpoint
daedaluschan Apr 20, 2026
a8143dc
fix deployment error
daedaluschan May 12, 2026
05daee7
Merge branch 'main' into octopus
daedaluschan May 12, 2026
fb53716
Merge pull request #5 from daedaluschan/octopus
daedaluschan May 12, 2026
620d43b
Clarify backup branch rule scope in AGENTS.md
daedaluschan May 13, 2026
db21c92
Merge pull request #6 from daedaluschan/codex/create-backup-branch-fo…
daedaluschan May 13, 2026
4cdc4b6
Rewrite README for tariff and octopus endpoints
daedaluschan May 13, 2026
2891bd4
Merge pull request #7 from daedaluschan/codex/update-readme-for-/tari…
daedaluschan May 13, 2026
6040067
initial question files structure
daedaluschan May 15, 2026
8103434
Merge pull request #8 from daedaluschan/quiz
daedaluschan May 15, 2026
8271613
Document /octopus endpoint behavior in AGENTS.md
daedaluschan May 16, 2026
6652474
Merge pull request #9 from daedaluschan/codex/create-new-branch-tarif…
daedaluschan May 16, 2026
cc3354f
vocab endpoint
daedaluschan May 16, 2026
2a635fc
Merge pull request #10 from daedaluschan/quiz
daedaluschan May 16, 2026
a813c0e
minor display update
daedaluschan May 16, 2026
d56ab56
highlighting
daedaluschan May 16, 2026
087c2f0
Merge pull request #11 from daedaluschan/quiz
daedaluschan May 16, 2026
3add844
little clean up
daedaluschan May 16, 2026
15c67dd
Merge pull request #12 from daedaluschan/quiz
daedaluschan May 16, 2026
af185b1
Add vocabulary words to word_bank.txt
daedaluschan May 16, 2026
f36e218
Create vocabulary exercise instructions for Year 8
daedaluschan May 16, 2026
bd94e35
Merge pull request #13 from daedaluschan/Gen_q
daedaluschan May 16, 2026
f450489
Add default mixed question-type rule to vocabulary guide
daedaluschan May 16, 2026
4cb33e5
Merge pull request #14 from daedaluschan/codex/rearrange-word_bank.tx…
daedaluschan May 16, 2026
f6dd015
Add 10 mixed-type vocabulary MCQs
daedaluschan May 16, 2026
a673987
Merge branch 'main' into codex/rearrange-word_bank.txt-and-create-age…
daedaluschan May 16, 2026
344f85c
Merge pull request #15 from daedaluschan/codex/rearrange-word_bank.tx…
daedaluschan May 16, 2026
66cb2d1
Add 20 fill-in-the-blank vocabulary questions
daedaluschan May 16, 2026
0f18951
Merge pull request #16 from daedaluschan/codex/add-words-to-word-bank
daedaluschan May 16, 2026
0d0ae45
Improve vocab submit lock, retry feedback, and type filtering
daedaluschan May 16, 2026
df59522
Merge pull request #17 from daedaluschan/codex/update-vocab-endpoint-…
daedaluschan May 16, 2026
d83526e
Improve vocab type filter with checkbox multi-select
daedaluschan May 16, 2026
49bc115
Merge pull request #18 from daedaluschan/codex/improve-multi-select-d…
daedaluschan May 16, 2026
fc99b46
Add 50 new vocabulary MCQs to question bank
daedaluschan May 16, 2026
8fd010f
Merge pull request #19 from daedaluschan/codex/generate-50-multiple-c…
daedaluschan May 16, 2026
cb10920
Trim vocabulary bank to first 50 questions
daedaluschan May 16, 2026
127c3d3
Merge pull request #20 from daedaluschan/codex/review-vocab-endpoint-…
daedaluschan May 16, 2026
697d438
Add safeguard for destructive dataset edits
daedaluschan May 16, 2026
a64aef5
Merge pull request #21 from daedaluschan/codex/review-vocab-endpoint-…
daedaluschan May 16, 2026
34e3ebc
Append 10 vocabulary questions with sequential IDs
daedaluschan May 16, 2026
c3baa32
Merge pull request #23 from daedaluschan/codex/add-vocabulary-questio…
daedaluschan May 16, 2026
4cf5520
Add 20 vocabulary questions and continue ID sequence
daedaluschan May 17, 2026
d8f31f8
Merge pull request #24 from daedaluschan/codex/add-vocabulary-questio…
daedaluschan May 17, 2026
a9e2c99
avoid repeating questions
daedaluschan May 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ ENV/
env.bak/
venv.bak/

# Local Codex state
.codex
.codex/

# Spyder project settings
.spyderproject
.spyproject
Expand Down
113 changes: 113 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# Agent Instructions

- Before merging any branch into `main`, create a backup branch from the branch being merged.
- Name the backup branch `<branch_to_be_merged>_backup`.

- This rule applies to all future merges into `main`.


## Destructive Edit Safeguard

- If a request would delete or overwrite a large portion of a dataset file (for example, removing a broad ID range like "51 to end"), do not execute immediately.
- First, restate the exact impact with concrete counts or ranges (for example, "this will delete questions eng-vocab-0051 through eng-vocab-0175").
- Ask for explicit confirmation before applying the destructive change, unless the user has already confirmed after seeing that impact summary.
- When the user goal is quality cleanup, prefer targeted removal of only the flagged or invalid items instead of bulk truncation.
- After destructive edits, include a short post-change summary of what was removed and what remains.

## Octopus Endpoint Notes

- The `/octopus` endpoint returns an HTML page (not JSON).
- It shows the best (cheapest) continuous upcoming usage window for each supported appliance duration.
- For each suggested window, the UI includes a collapsed-by-default expandable section with a mini table of half-hour slots and their tariff values in `p/kWh`.

## Vocabulary Endpoint Notes

- The `/vocab` endpoint returns an HTML practice page for `static/English/Vocabulary/questions.json`.
- By default, `/vocab` shows 10 randomly sampled questions. Supported quiz sizes are `5`, `10`, `15`, `20`, `25`, and `30`.
- If the requested quiz size is larger than the available question bank, show all available questions.
- The server shuffles the selected question set and shuffles each question's choices before sending them to the page.
- It is acceptable for the HTML document to carry answer metadata such as `correct` and `target_word`, but the page must not visibly display correct answers before marking.
- The main `Submit` button marks the quiz in the browser. Unanswered questions count as wrong.
- After submit, show the score as a fraction such as `7/10`: green for `>= 80%`, amber for `>= 60%` and `< 80%`, and red for `< 60%`.
- On submit, wrong questions should not reveal the correct answer. They should remain answerable and show a per-question `Retry` button until the student selects the correct option.
- When a retry attempt is correct, show `Retry correct` in blue instead of the normal first-attempt `Correct` label.
- Retry marking is client-side only and does not send feedback to the server.
- On submit, send the `target_word` values for questions missed on the first marking attempt to `POST /vocab/feedback` using this payload shape:
```json
{
"missed_target_words": ["example"]
}
```
- Marking should not wait for feedback to complete. The page should show feedback status beside the submit button.
- The `Regenerate` control should request a fresh random set without a full page reload when practical, using `GET /vocab/questions?count=<count>`.

## Study Question Storage

- Store multiple choice study questions under `static/<Subject>/<Category>/questions.json`.
- Use folder names to identify the subject and category, for example `static/English/Vocabulary/questions.json`.
- Each `questions.json` file should contain a raw JSON array of question objects, not an outer wrapper object.
- Do not include `level` or `difficulty` fields unless the schema is intentionally changed later.
- Each question object should use:
- `id`: stable unique id, for example `eng-vocab-0001`.
- `type`: snake_case question type, for example `word_meaning`, `reverse_meaning`, `fill_in_blank`, `alternative_word`, or `part_of_speech`.
- `target_word`: the single canonical vocabulary item being tested.
- `prompt`: object containing the source material shown to the student, such as `meaning` and/or `sentence`.
- `question`: student-facing question text.
- `choices`: array of answer objects, each with `text` and `correct`.
- `explanation`: short explanation of the correct answer.
- Exactly one choice should have `"correct": true`.

## Preparing Vocabulary Question JSON

- When the user provides plain-text vocabulary MCQs, append them to `static/English/Vocabulary/questions.json` unless they specify another subject/category.
- Continue the existing id sequence. For example, if the last id is `eng-vocab-0024`, the next id is `eng-vocab-0025`.
- The same vocabulary word may appear in more than one question as long as the questions are different, for example a word meaning question and a fill-in-the-blank question for the same word.
- Use top-level `target_word` as the single canonical field for the vocabulary item being tested. Do not put `target_word` inside `prompt`, and do not use a separate `word` field.
- Include `target_word` for every vocabulary question type, including reverse-meaning and fill-in-the-blank questions. The app should not expose `target_word` while preparing the student-facing exercise; it is metadata for scoring, review, or future filtering.
- If `target_word` is not explicitly specified in the user's input, infer it from the question using best judgement, usually from the `Word:` line, the correct answer, the highlighted/referenced word, or the blank's correct completion.
- If `target_word` cannot be determined confidently, skip adding that question and report it back to the user.
- Preserve the user's answer option order, but do not store option letters such as `A`, `B`, `C`, `D`, or `E`.
- Convert each answer option to `{ "text": "...", "correct": true/false }`.
- Mark exactly one answer as correct, based on the intended answer from the prompt.
- Add a concise `explanation` for every new question. Explain why the correct answer is correct; do not merely repeat the answer.
- Use ASCII punctuation in JSON strings where practical, including straight quotes rather than curly quotes.
- After editing a question bank, validate it with `python3 -m json.tool static/English/Vocabulary/questions.json`.

Use these mappings for vocabulary question batches:

- `Type 1: Word Meaning MCQ`
- `type`: `word_meaning`
- `target_word`: `<word>`
- `prompt`: `{}`
- `question`: `What does "<word>" mean?`
- `Type 2: Reverse Meaning MCQ`
- `type`: `reverse_meaning`
- `target_word`: `<correct answer>`
- `prompt`: `{ "meaning": "<meaning>" }`
- `question`: `Which word matches the meaning given?`
- `Type 3: Fill in the Blank MCQ`
- `type`: `fill_in_blank`
- `target_word`: `<correct answer>`
- `prompt`: `{ "sentence": "<sentence with ______>" }`
- `question`: `Which word best completes the sentence?`
- `Type 4: Alternative Word MCQ`
- `type`: `alternative_word`
- `target_word`: `<target word>`
- `prompt`: `{ "sentence": "<sentence>" }`
- `question`: `Which word could best replace "<target word>" without changing the meaning?`
- `Type 5: Part of Speech MCQ`
- `type`: `part_of_speech`
- `target_word`: `<target word>`
- `prompt`: `{ "sentence": "<sentence>" }`
- `question`: `In this sentence, what part of speech is "<target word>"?`

Before finishing, check:

- The top level is still a JSON array.
- Every new id is unique and sequential.
- Every new question has `id`, `type`, `target_word`, `prompt`, `question`, `choices`, and `explanation`.
- Every new `target_word` is either provided by the user or confidently inferred; uncertain questions are skipped and reported.
- No prompt uses `target_word` or `word`.
- Every new question has exactly one correct choice.
- Repeated vocabulary is acceptable when the question itself is distinct.
- No new question includes `level` or `difficulty`.
114 changes: 71 additions & 43 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,67 +1,95 @@
[![example-flask](https://github.com/koyeb/example-flask/actions/workflows/deploy.yaml/badge.svg)](https://github.com/koyeb/example-flask/actions)
# Avon Flask API

<div align="center">
<a href="https://koyeb.com">
<img src="https://www.koyeb.com/static/images/icons/koyeb.svg" alt="Logo" width="80" height="80">
</a>
<h3 align="center">Koyeb Serverless Platform</h3>
<p align="center">
Deploy a Flask application on Koyeb
<br />
<a href="https://koyeb.com">Learn more about Koyeb</a>
·
<a href="https://koyeb.com/docs">Explore the documentation</a>
·
<a href="https://koyeb.com/tutorials">Discover our tutorials</a>
</p>
</div>
A small Flask app focused on Octopus Agile tariff planning.

## Endpoints

## About Koyeb and the Flask example application
### `GET /tariff`
Returns the cheapest start time for a device run based on the requested duration.

Koyeb is a developer-friendly serverless platform to deploy apps globally. No-ops, servers, or infrastructure management.
This repository contains a Flask application you can deploy on the Koyeb serverless platform for testing.
**Query parameters**
- `numHours` (required, number): how long the appliance will run.

This example application is designed to show how a Flask application can be deployed on Koyeb.
**Success response**
- `200 OK`
```json
{
"startTime": "2026-05-13 17:00:00"
}
```

## Getting Started
**Error responses**
- `400 Bad Request` when `numHours` is missing or not numeric.
- `502 Bad Gateway` when upstream tariff data cannot be fetched.

Follow the steps below to deploy and run the Flask application on your Koyeb account.
### `GET /octopus`
Renders an HTML page showing best tariff windows for preset durations (`1` to `3.5` hours).

### Requirements
- Uses live Octopus tariff data.
- Displays start/end times, total tariff, and average tariff.
- Highlights cases where the total tariff is negative (credit periods).

You need a Koyeb account to successfully deploy and run this application. If you don't already have an account, you can sign-up for free [here](https://app.koyeb.com/auth/signup).
### `GET /vocab`
Renders an HTML vocabulary practice quiz using `static/English/Vocabulary/questions.json`.

### Deploy using the Koyeb button
- Shows 10 random questions by default.
- Supports quiz sizes of `5`, `10`, `15`, `20`, `25`, and `30`.
- Shuffles the selected questions and each question's answer choices.
- Marks answers in the browser when `Submit` is clicked.
- Counts unanswered questions as wrong.
- Shows the score as a colored fraction: green for `>= 80%`, amber for `>= 60%` and `< 80%`, red for `< 60%`.
- Allows retries for wrong answers without immediately showing the correct answer.
- Shows retry successes as `Retry correct` in blue.
- Sends missed `target_word` values from the first submit attempt to the dummy feedback endpoint.

The fastest way to deploy the Flask application is to click the **Deploy to Koyeb** button below.
**Query parameters**
- `count` (optional, number): requested quiz size. Invalid values fall back to `10`.

[![Deploy to Koyeb](https://www.koyeb.com/static/images/deploy/button.svg)](https://app.koyeb.com/deploy?type=git&repository=github.com/koyeb/example-flask&branch=main&name=flask-on-koyeb)
Example:

Clicking on this button brings you to the Koyeb App creation page with everything pre-set to launch this application.
```text
http://127.0.0.1:5000/vocab?count=15
```

_To modify this application example, you will need to fork this repository. Checkout the [fork and deploy](#fork-and-deploy-to-koyeb) instructions._
### `GET /vocab/questions`
Returns a fresh random vocabulary question set as JSON for the page's regenerate control.

### Fork and deploy to Koyeb
**Query parameters**
- `count` (optional, number): requested quiz size. Allowed values are `5`, `10`, `15`, `20`, `25`, and `30`.

If you want to customize and enhance this application, you need to fork this repository.
### `POST /vocab/feedback`
Dummy endpoint that accepts the vocabulary words missed on the first submit attempt.

If you used the **Deploy to Koyeb** button, you can simply link your service to your forked repository to be able to push changes.
Alternatively, you can manually create the application as described below.
**Request body**
```json
{
"missed_target_words": ["reclusive", "wither"]
}
```

On the [Koyeb Control Panel](https://app.koyeb.com/), on the **Overview** tab, click the **Create Web Service** button to begin.
**Success response**
```json
{
"missed_count": 2,
"status": "received"
}
```

1. Select **GitHub** as the deployment method.
2. In the repositories list, select the repository you just forked.
3. In the **Builder** section, click the **override** toggle associated with the **Run command** and enter `gunicorn app:app` in the field.
4. Choose a name for your App and Service, i.e `flask-on-koyeb`, and click **Deploy**.
## Local run

You land on the deployment page where you can follow the build of your Flask application. Once the build is completed, your application is being deployed and you will be able to access it via `<YOUR_APP_NAME>-<YOUR_ORG_NAME>.koyeb.app`.
```bash
python app.py
```

## Contributing
Default Flask URL:
- `http://127.0.0.1:5000/tariff?numHours=2`
- `http://127.0.0.1:5000/octopus`
- `http://127.0.0.1:5000/vocab`

If you have any questions, ideas or suggestions regarding this application sample, feel free to open an [issue](//github.com//koyeb/example-flask/issues) or fork this repository and open a [pull request](//github.com/koyeb/example-flask/pulls).
## Environment variable

## Contact
Set the Octopus API key before running:

[Koyeb](https://www.koyeb.com) - [@gokoyeb](https://twitter.com/gokoyeb) - [Slack](http://slack.koyeb.com/)
```bash
export OCTOPUS_KEY="your_octopus_api_key"
```
Loading