QuestoryAI 提示词平台QuestoryAI 提示词平台QuestoryAI 提示词平台
TeamsBotsSkillsPromptsPromptmasters
Developers
LoginRegister
CC0 2026 QuestoryAI 提示词平台
GitHub
All Tags

Travel Prompts

112 prompts
Hiking Route Time and Water Planner
Skill

Plans a day hike leg by leg. Estimates time with Naismith's rule and Langmuir's descent corrections, adjusted for terrain, fitness, pack weight and breaks, gives clock times for each leg, checks the finish against sunset and the latest safe start, and works out water to carry between refills and snacks to pack. Flags after-dark finishes, long dry stretches and hard terrain late in the day. Includes a stdlib Python planner with --self-test. 来源:https://prompts.chat/prompts/cmvoxmzkk0001jk08elffowri

---
name: hiking-route-time-and-water-planner
description: Plans a day hike leg by leg. Estimates time with Naismith's rule and Langmuir's descent corrections, adjusted for terrain, fitness, pack weight and breaks, gives clock times for each leg, checks the finish against sunset and the latest safe start, and works out water to carry between refills and snacks to pack. Flags after-dark finishes, long dry stretches and hard terrain late in the day. Includes a stdlib Python planner with --self-test.
---

# Hiking Route Time and Water Planner

You help hikers turn a route into a realistic timetable: when they will reach each point, whether they finish in daylight, and how much water and food to carry. You show the rule behind each number, prefer conservative estimates, and always leave room for a slower day. You are not a substitute for local knowledge, a map or a weather forecast, and you say so when it matters.

## Files in this skill

- `scripts/hike_plan.py` - reads a legs CSV and prints a timetable, daylight check, water per stretch, food and findings (Python 3 standard library only)
- `references/time-rules.md` - Naismith's rule, Langmuir's corrections, terrain/fitness/pack factors, breaks and how to calibrate them
- `references/water-food-and-safety.md` - drinking rates, refill planning and water treatment, snacks, daylight margins, turnaround times and the safety checklist
- `templates/hike-plan.md` - the plan to share with the group and leave with a contact at home
- `examples/eagle-ridge-loop.csv` - a 22 km late-October loop with a scramble section and one refill point

## Workflow

### 1. Split the route into legs
Ask for the route (map app or guidebook), the date, and the group: pace, fitness, youngest or slowest member, pack weight. Split the route at summits, passes, huts, junctions and water sources; for each leg get the distance, ascent and descent (from the app's elevation profile) and the terrain type (road, path, rough, scramble, snow, bushwhack). Mark where water can be refilled. Get the sunset time for the date and place, and the forecast temperature.

### 2. Run the planner
```
python3 scripts/hike_plan.py examples/eagle-ridge-loop.csv --start 09:30 --sunset 17:20 --temp 24 --fitness 1.1 --pack-kg 9
python3 scripts/hike_plan.py my-route.csv --start 07:00 --sunset 20:45 --temp 31 --break-min 15 --json
python3 scripts/hike_plan.py --self-test
```
Exit code 1 means a HIGH finding (finish after sunset), 2 means bad input.

### 3. Adjust the plan
For AFTER_DARK or SMALL_MARGIN: start earlier (the script prints the latest sensible start), shorten the route, or pick a bail-out point and a turnaround time. For LONG_DRY_STRETCH: add a refill, carry more capacity, or move the long climb to the cool morning. For HARD_TERRAIN_LATE: reverse the loop so the scramble comes first. Explain the formulas from `references/time-rules.md` when asked, and suggest calibrating the fitness factor after the first leg.

### 4. Deliver
Fill `templates/hike-plan.md`: timetable with clock times, turnaround time, water and food list, bail-out options and the emergency details to leave with someone at home.

## Example result
For `examples/eagle-ridge-loop.csv` (22.2 km, +1170 m / -1150 m) starting 09:30 at fitness 1.1 and 24 C: 7h08 moving, 8h19 with breaks, finish about 17:49, which is 29 minutes after the 17:20 sunset (HIGH AFTER_DARK; latest sensible start 08:01). The first four legs have no water, so 4.4 L must be carried (MEDIUM LONG_DRY_STRETCH). Starting at 08:00 finishes at 16:19 with 61 minutes to spare; the water stretch remains, so the plan adds a 2 L bladder or a cached bottle at Pine Saddle.

## Rules

- Estimates are a starting point: tell the group to compare the real time on the first leg with the plan and rescale.
- Keep at least 60 minutes of daylight in hand, and a headlamp in every pack all year.
- Never suggest drinking untreated water; recommend filtering or treating any natural source.
- Weather, snow, river crossings and route conditions override any timetable: tell users to check the forecast and local reports, and to turn back when conditions change.
- Do not give medical advice beyond basic hydration and food guidance; point to first-aid training and local rescue numbers.
FILE:references/time-rules.md
# Time Rules

## Naismith's rule (1892)
Allow 1 hour for every 5 km on the flat plus 1 hour for every 600 m of ascent (the original was 3 miles per hour plus 1 hour per 2000 ft).
```
moving minutes = distance_km / pace_kmh * 60 + ascent_m / 10
```
Example: 4.2 km with 380 m of ascent = 50.4 + 38 = 88 minutes before adjustments.

## Langmuir's corrections for descent
Naismith treats descent like the flat. Langmuir refined it:
- gentle descent, 5 to 12 degrees (about 9 to 21 %): subtract 10 minutes per 300 m of descent
- steep descent, more than 12 degrees: add 10 minutes per 300 m of descent
- under 5 degrees: no change
The script estimates the descent angle from the descent and the share of the leg's distance spent going down. It never lets a leg drop below half its flat time.

## Multipliers used by the script
| Factor | Value | When |
|---|---|---|
| Terrain road | 0.9 | Paved or forest road |
| Terrain path | 1.0 | Good footpath |
| Terrain rough | 1.25 | Rocky, rooty, loose or boggy path |
| Terrain scramble | 1.6 | Hands needed, exposed steps |
| Terrain snow | 1.5 | Soft or old snow without crampon work |
| Terrain bushwhack | 1.6 | No path, vegetation |
| Fitness | 0.85 / 1.0 / 1.2 / 1.4 | Fast and fit / average / relaxed or mixed group / young children |
| Pack | +2 % per kg above 10 kg | Overnight or heavy loads |
| Breaks | 10 min per hour (default) | Use 15 to 20 for photo walks, families, big groups |

Terrain multiplies the whole leg, including the climbing time.

## Calibrating
After the first leg, divide the real time by the planned time. If the group took 1h50 for a planned 1h37, the factor is 1.13: rerun with `--fitness` multiplied by that and check the finish again. Groups move at the pace of the slowest person; plan for them.

## Other rules you may meet
- Tranter's corrections: a fitness and fatigue table on top of Naismith, used for long mountain days.
- Tobler's hiking function: speed = 6 * exp(-3.5 * |slope + 0.05|) km/h, used in GIS tools; it gives similar totals on mixed routes.

## Turnaround time
For an out-and-back or a route with a bail-out, set a fixed turnaround time: the latest time you can leave the farthest point and still be back with an hour of daylight. Example: sunset 17:20, keep 60 minutes, the return takes 3h10 -> turn around by 13:10 wherever you are.
FILE:references/water-food-and-safety.md
# Water, Food and Safety

## Drinking rates used by the script
| Temperature | Litres per hour (total time) |
|---|---|
| under 15 C | 0.4 |
| 15 to 24 C | 0.5 |
| 25 to 29 C | 0.75 |
| 30 C and above | 1.0 |
Plus 0.1 L per 100 m of ascent, because climbing makes you sweat more. Needs vary a lot between people; heavy sweaters, children and people at altitude may need more. Drink a little often rather than a lot at once, and add electrolytes (salt tablets, drink mix or salty snacks) on hot days or when drinking more than about 3 L.

## Carry planning
- The start and every leg marked `water_at_end = yes` are refill points.
- Carry = largest amount needed between two refill points plus a 0.5 L reserve.
- More than 3 L (3 kg) is heavy; options are caching water, choosing a route past a hut or spring, or moving the hottest climb to early morning.
- Confirm that springs and huts actually have water at that time of year (many huts close in late autumn; springs dry up in late summer).

## Treating water
Treat all natural water: a hollow-fibre filter (bacteria and protozoa), chlorine dioxide tablets (also viruses, wait the full contact time, often 30 minutes, up to 4 hours for Cryptosporidium), UV pens for clear water, or boiling for 1 minute (3 minutes above 2000 m). Filter cloudy water through a cloth first.

## Food
About 200 to 300 kcal per hour on the move keeps energy steady on a long day: nuts, bars, dried fruit, cheese, sandwiches. The script uses 250 kcal per hour of total time. Pack one extra snack per person as an emergency reserve.

## Daylight
- Get sunset for the exact place and date (weather or astronomy apps). In mountains the sun leaves valleys and east-facing slopes earlier than the official time.
- Civil twilight gives about 20 to 40 minutes of usable light after sunset in mid-latitudes, less in the tropics. Do not plan to use it.
- Keep 60 minutes of daylight in hand (the default `--margin`). Every pack gets a headlamp with charged batteries.

## Safety checklist
- Forecast checked the evening before and the morning of the hike (thunderstorms, wind on ridges, freezing level).
- Route plan, start time, turnaround time and expected return left with someone at home, with who to call and when.
- Map offline on the phone, plus a power bank; paper map and compass on remote routes.
- Layers and a waterproof jacket, hat and gloves above the tree line even in summer, sun protection.
- Small first-aid kit, blister plasters, emergency blanket, whistle.
- Know the local emergency number (112 in Europe, 911 in North America) and the mountain rescue procedure.
- Rule: the group stays together and turns back at the turnaround time, at the first lightning, or when anyone is not feeling well.
FILE:templates/hike-plan.md
# Hike plan: <route name>, <date>

**Group:** <names / number of people>   **Leader:** <name, phone>
**Route:** <22.2 km loop, +1170 m / -1150 m, map link>
**Start:** <08:00 at Eagle Ridge car park>   **Expected finish:** <16:19>   **Sunset:** <17:20>
**Turnaround time:** <13:00 at the summit, whatever happens>
**Latest call-out time for the home contact:** <19:00>

## Timetable
| Leg | km | Up / down m | Terrain | Planned start | Planned end | Water refill |
|---|---|---|---|---|---|---|
| <Car park to Pine Saddle> | <4.2> | <+380 / -20> | <path> | <08:00> | <09:53> | <no> |

Settings used: <pace 5 km/h, fitness 1.1, breaks 10 min/h, 24 C>. Check the first leg and rescale.

## Water and food
- Carry from the start: <4.4 L per person> (no refill until <Spring Hut>)
- Refill at: <Spring Hut tap (open until end of October?), treat stream water>
- Snacks: <2100 kcal per person> + one spare
- Electrolytes: <yes / no>

## Bail-out options
- <After Pine Saddle: forest road back to the car park, 3.5 km, 1h>
- <Skip the ridge traverse: descend the north path from the summit>

## Kit
- <headlamp, layers, waterproof, map offline + power bank, first aid, whistle, filter or tablets>

## Weather and conditions
- Forecast: <checked on ... : dry, 24 C, wind 20 km/h on ridge>
- Notes: <scramble section is wet after rain; avoid if wet>

## Emergency
- Emergency number: <112>   Mountain rescue: <...>
- Home contact: <name, phone>: if no message by <19:00>, call <number> with this plan.
FILE:examples/eagle-ridge-loop.csv
leg,distance_km,ascent_m,descent_m,terrain,water_at_end
Car park to Pine Saddle,4.2,380,20,path,no
Pine Saddle to Eagle Ridge summit,3.1,520,40,rough,no
Eagle Ridge traverse,1.6,120,150,scramble,no
Ridge down to Spring Hut,3.8,30,560,path,yes
Spring Hut to Blue Lake,4.5,80,210,path,no
Blue Lake back to car park,5.0,40,170,road,yes
FILE:scripts/hike_plan.py
#!/usr/bin/env python3
"""Hiking route time and water planner (Python 3 standard library only).

Reads a CSV of route legs and estimates moving time per leg with Naismith's rule
(5 km/h plus 1 hour per 600 m of ascent) and Langmuir's descent corrections,
adjusted for terrain, fitness and pack weight, then adds breaks, gives clock
times for every leg, checks the finish against sunset, and works out how much
water to carry between refill points and how much food to pack.

CSV columns (header required; ; or , separated):
  leg, distance_km, ascent_m, descent_m, terrain, water_at_end
terrain: road | path | rough | scramble | snow | bushwhack   water_at_end: yes/no

Usage:
  python3 hike_plan.py route.csv --start 08:30 --sunset 17:10 --temp 24
  python3 hike_plan.py route.csv --start 07:00 --fitness 1.2 --pack-kg 14 --json
  python3 hike_plan.py --self-test
Exit codes: 0 = plan fine, 1 = HIGH findings (finish after sunset), 2 = bad input.
"""
import argparse, csv, io, json, math, sys

TERRAIN = {"road": 0.9, "path": 1.0, "trail": 1.0, "rough": 1.25, "scramble": 1.6, "snow": 1.5, "bushwhack": 1.6}
REQUIRED = ["leg", "distance_km", "ascent_m", "descent_m", "terrain", "water_at_end"]
SEV = {"HIGH": 0, "MEDIUM": 1, "LOW": 2}


class InputError(Exception):
    pass


def num(v, field, row):
    try:
        x = float(str(v).strip().replace(",", "."))
    except ValueError:
        raise InputError(f"row {row}: {field} '{v}' is not a number")
    if x < 0:
        raise InputError(f"row {row}: {field} cannot be negative")
    return x


def hm(s):
    try:
        h, m = s.strip().split(":")
        h, m = int(h), int(m)
        assert 0 <= h < 24 and 0 <= m < 60
        return h * 60 + m
    except Exception:
        raise InputError(f"time '{s}' must be HH:MM")


def clock(mins):
    mins = int(round(mins))
    day, rem = divmod(mins, 1440)
    return f"{rem // 60:02d}:{rem % 60:02d}" + (f" (+{day}d)" if day else "")


def dur(mins):
    mins = int(round(mins))
    return f"{mins // 60}h{mins % 60:02d}"


def read_legs(text):
    sample = text[:2000]
    delim = ";" if sample.count(";") > sample.count(",") else ","
    rd = csv.DictReader(io.StringIO(text), delimiter=delim)
    if not rd.fieldnames:
        raise InputError("empty CSV")
    fields = [f.strip().lower() for f in rd.fieldnames]
    missing = [c for c in REQUIRED if c not in fields]
    if missing:
        raise InputError("missing columns: " + ", ".join(missing))
    legs = []
    for i, raw in enumerate(rd, start=2):
        r = {k.strip().lower(): (v or "").strip() for k, v in raw.items() if k}
        if not any(r.values()):
            continue
        t = r["terrain"].lower() or "path"
        if t not in TERRAIN:
            raise InputError(f"row {i}: terrain '{t}' must be one of {', '.join(TERRAIN)}")
        w = r["water_at_end"].lower()
        if w not in ("yes", "no", "y", "n", "1", "0", "true", "false", ""):
            raise InputError(f"row {i}: water_at_end must be yes or no")
        legs.append({"leg": r["leg"] or f"Leg {len(legs) + 1}",
                     "distance_km": num(r["distance_km"], "distance_km", i),
                     "ascent_m": num(r["ascent_m"], "ascent_m", i),
                     "descent_m": num(r["descent_m"], "descent_m", i),
                     "terrain": t, "water_at_end": w in ("yes", "y", "1", "true")})
    if not legs:
        raise InputError("no legs in CSV")
    return legs


def water_rate(temp_c):
    """Litres per hour of total time, before the ascent extra."""
    if temp_c < 15:
        return 0.4
    if temp_c < 25:
        return 0.5
    if temp_c < 30:
        return 0.75
    return 1.0


def leg_minutes(leg, pace_kmh):
    d, up, down = leg["distance_km"], leg["ascent_m"], leg["descent_m"]
    flat = d / pace_kmh * 60
    climb = up / 10.0  # Naismith: 60 min per 600 m
    descent_adj = 0.0
    steep = False
    if down > 0 and d > 0:
        horiz = d * 1000 * (down / (up + down))  # share of the leg spent descending
        angle = math.degrees(math.atan(down / horiz)) if horiz > 0 else 90
        if 5 <= angle <= 12:
            descent_adj = -down / 300 * 10   # Langmuir: gentle descent is faster
        elif angle > 12:
            descent_adj = down / 300 * 10    # steep descent is slower
        steep = angle > 14
    if up > 0 and d > 0:
        horiz_up = d * 1000 * (up / (up + down))
        steep = steep or math.degrees(math.atan(up / horiz_up)) > 14  # about 25 %
    return max(flat + climb + descent_adj, flat * 0.5), steep


def plan(legs, start, sunset=None, pace=5.0, fitness=1.0, pack_kg=8.0, break_min=10.0, temp=18.0, margin=60):
    if pace <= 0 or fitness <= 0:
        raise InputError("pace and fitness must be positive")
    pack_factor = 1.0 + max(0.0, pack_kg - 10) * 0.02  # +2 % per kg above 10 kg
    rate = water_rate(temp)
    t = start
    rows, findings = [], []
    stretch, stretches, stretch_legs = 0.0, [], []
    for leg in legs:
        base, steep = leg_minutes(leg, pace)
        moving = base * TERRAIN[leg["terrain"]] * fitness * pack_factor
        total = moving * (1 + break_min / 60)
        water = total / 60 * rate + leg["ascent_m"] / 100 * 0.1
        t_start, t = t, t + total
        rows.append({**leg, "moving_min": round(moving), "with_breaks_min": round(total),
                     "start": clock(t_start), "end": clock(t), "end_min": t, "water_l": round(water, 2), "steep": steep})
        stretch += water
        stretch_legs.append(leg["leg"])
        if leg["water_at_end"]:
            stretches.append((stretch, stretch_legs)); stretch, stretch_legs = 0.0, []
        if steep:
            findings.append(("LOW", "STEEP_LEG", f"{leg['leg']}: average gradient over 25 %; expect slower going than the formula and take care on the descent"))
    if stretch_legs:
        stretches.append((stretch, stretch_legs))
    moving_total = sum(r["moving_min"] for r in rows)
    total = t - start
    carry = max(s for s, _ in stretches) + 0.5
    for s, names in stretches:
        if s + 0.5 > 3.0:
            findings.append(("MEDIUM", "LONG_DRY_STRETCH", f"{' -> '.join(names)}: {s + 0.5:.1f} L to carry with no refill; add a refill, cache water or start earlier in the cool"))
    summary = {
        "distance_km": round(sum(l["distance_km"] for l in legs), 1),
        "ascent_m": round(sum(l["ascent_m"] for l in legs)),
        "descent_m": round(sum(l["descent_m"] for l in legs)),
        "moving_min": round(moving_total), "total_min": round(total),
        "start": clock(start), "finish": clock(t),
        "water_total_l": round(sum(r["water_l"] for r in rows), 1),
        "carry_max_l": round(carry, 1),
        "food_kcal": int(round(total / 60 * 250, -1)),
        "water_rate_l_per_h": rate, "pack_factor": round(pack_factor, 2),
    }
    if sunset is not None:
        left = sunset - t
        summary["sunset"] = clock(sunset)
        summary["minutes_before_sunset"] = round(left)
        summary["latest_start"] = clock(sunset - margin - total)
        if left < 0:
            findings.append(("HIGH", "AFTER_DARK", f"finish {clock(t)} is {dur(-left)} after sunset {clock(sunset)}; start by {summary['latest_start']}, shorten the route or plan a bail-out"))
        elif left < margin:
            findings.append(("MEDIUM", "SMALL_MARGIN", f"finish {clock(t)} leaves only {round(left)} min before sunset (target {margin}); start by {summary['latest_start']} and carry a headlamp"))
        for r in rows:
            if r["terrain"] in ("scramble", "snow") and r["end_min"] > sunset - 120:
                findings.append(("MEDIUM", "HARD_TERRAIN_LATE", f"{r['leg']} ({r['terrain']}) ends at {r['end']}, within 2 h of sunset; tired legs and fading light on hard ground"))
    if moving_total > 8 * 60:
        findings.append(("LOW", "LONG_DAY", f"{dur(moving_total)} moving time; check that everyone has done a day this long recently"))
    if temp >= 28 and any(l["ascent_m"] >= 300 for l in legs):
        findings.append(("MEDIUM", "HEAT", f"{temp:g} C with big climbs: start at first light, rest in shade, electrolytes with the water"))
    findings.sort(key=lambda f: SEV[f[0]])
    for r in rows:
        r.pop("end_min")
    return {"legs": rows, "summary": summary, "stretches": [{"legs": n, "litres": round(s + 0.5, 1)} for s, n in stretches],
            "findings": [{"severity": a, "code": b, "message": c} for a, b, c in findings]}


def to_markdown(p, args):
    s = p["summary"]
    out = ["# Hike plan", "",
           f"Settings: pace {args.pace:g} km/h, fitness x{args.fitness:g}, pack {args.pack_kg:g} kg (x{s['pack_factor']}), breaks {args.break_min:g} min per hour, {args.temp:g} C",
           "",
           f"Route: {s['distance_km']} km, +{s['ascent_m']} m / -{s['descent_m']} m; moving {dur(s['moving_min'])}, with breaks {dur(s['total_min'])}",
           f"Start {s['start']}, finish about {s['finish']}" + (f"; sunset {s['sunset']}, " + (f"{s['minutes_before_sunset']} min to spare" if s['minutes_before_sunset'] >= 0 else f"{dur(-s['minutes_before_sunset'])} AFTER sunset") + f"; latest sensible start {s['latest_start']}" if "sunset" in s else ""),
           "", "| Leg | km | Up m | Down m | Terrain | Moving | With breaks | Start | End | Water L | Refill at end |",
           "|---|---|---|---|---|---|---|---|---|---|---|"]
    for r in p["legs"]:
        out.append(f"| {r['leg']} | {r['distance_km']:g} | {r['ascent_m']:g} | {r['descent_m']:g} | {r['terrain']} | {dur(r['moving_min'])} | "
                   f"{dur(r['with_breaks_min'])} | {r['start']} | {r['end']} | {r['water_l']:.1f} | {'yes' if r['water_at_end'] else 'no'} |")
    out += ["", "## Water and food",
            f"- Drinking rate {s['water_rate_l_per_h']} L/h at this temperature plus 0.1 L per 100 m of climbing; total about {s['water_total_l']} L",
            f"- Carry at most {s['carry_max_l']} L (largest stretch between refills, incl. 0.5 L reserve); treat stream water"]
    for st in p["stretches"]:
        out.append(f"  - {' -> '.join(st['legs'])}: {st['litres']} L")
    out.append(f"- Food: about {s['food_kcal']} kcal of snacks (about 250 kcal per hour on the move), plus a spare")
    out += ["", "## Findings"]
    out += [f"- {f['severity']} {f['code']}: {f['message']}" for f in p["findings"]] or ["- none"]
    out += ["", "Estimates only: check them against your group's real pace on the first leg and adjust."]
    return "\n".join(out)


def self_test():
    res = []

    def check(name, cond):
        res.append(cond)
        print(("PASS " if cond else "FAIL ") + name)

    def L(d, up, down, terrain="path", water="no", name="x"):
        return {"leg": name, "distance_km": d, "ascent_m": up, "descent_m": down, "terrain": terrain, "water_at_end": water == "yes"}

    check("flat 10 km at 5 km/h = 120 min", round(leg_minutes(L(10, 0, 0), 5)[0]) == 120)
    check("Naismith 600 m climb adds 60 min", round(leg_minutes(L(5, 600, 0), 5)[0]) == 120)
    g = leg_minutes(L(6, 0, 900), 5)[0]  # angle ~8.5 deg: gentle
    check("gentle descent is faster (Langmuir)", round(g) == 72 - 30)
    st = leg_minutes(L(2, 0, 600), 5)  # ~16.7 deg: steep
    check("steep descent is slower and flagged", round(st[0]) == 24 + 20 and st[1])
    check("steep ascent flagged", leg_minutes(L(1, 400, 0), 5)[1])
    check("descent never below half the flat time", leg_minutes(L(10, 0, 1500), 5)[0] >= 60)
    p = plan([L(10, 0, 0)], hm("08:00"), break_min=0)
    check("finish time no breaks", p["summary"]["finish"] == "10:00")
    p = plan([L(10, 0, 0)], hm("08:00"), break_min=10)
    check("10 min break per hour", p["summary"]["total_min"] == 140)
    check("terrain multiplier", plan([L(10, 0, 0, "scramble")], 0, break_min=0)["summary"]["moving_min"] == 192)
    check("fitness multiplier", plan([L(10, 0, 0)], 0, fitness=1.2, break_min=0)["summary"]["moving_min"] == 144)
    check("pack over 10 kg slows", plan([L(10, 0, 0)], 0, pack_kg=15, break_min=0)["summary"]["moving_min"] == 132)
    p = plan([L(10, 0, 0)], hm("15:00"), sunset=hm("16:30"), break_min=0)
    check("AFTER_DARK HIGH", p["findings"][0]["code"] == "AFTER_DARK" and p["findings"][0]["severity"] == "HIGH")
    check("latest start", p["summary"]["latest_start"] == "13:30")
    p = plan([L(10, 0, 0)], hm("14:00"), sunset=hm("16:30"), break_min=0)
    check("SMALL_MARGIN", [f["code"] for f in p["findings"]] == ["SMALL_MARGIN"])
    check("no finding with time to spare", plan([L(10, 0, 0)], hm("08:00"), sunset=hm("18:00"))["findings"] == [])
    check("HARD_TERRAIN_LATE", any(f["code"] == "HARD_TERRAIN_LATE" for f in
          plan([L(3, 0, 0, "scramble")], hm("13:00"), sunset=hm("15:00"))["findings"]))
    check("water rate by temperature", [water_rate(t) for t in (10, 20, 27, 33)] == [0.4, 0.5, 0.75, 1.0])
    p = plan([L(10, 0, 0, water="yes"), L(10, 0, 0)], 0, temp=20, break_min=0)
    check("water per leg", p["legs"][0]["water_l"] == 1.0)
    check("carry = largest stretch + reserve", p["summary"]["carry_max_l"] == 1.5)
    p = plan([L(10, 500, 0), L(10, 0, 500)], 0, temp=31, break_min=0)
    check("LONG_DRY_STRETCH and HEAT", {"LONG_DRY_STRETCH", "HEAT"} <= {f["code"] for f in p["findings"]})
    check("LONG_DAY", any(f["code"] == "LONG_DAY" for f in plan([L(45, 0, 0)], 0)["findings"]))
    check("food kcal", plan([L(10, 0, 0)], 0, break_min=0)["summary"]["food_kcal"] == 500)
    check("clock wraps past midnight", clock(1500) == "01:00 (+1d)")
    legs = read_legs("leg;distance_km;ascent_m;descent_m;terrain;water_at_end\nA;3,5;200;0;Path;yes\n")
    check("semicolon CSV + decimal comma", legs[0]["distance_km"] == 3.5 and legs[0]["water_at_end"])
    for bad, why in [("leg,distance_km\nA,1\n", "missing columns"),
                     ("leg,distance_km,ascent_m,descent_m,terrain,water_at_end\nA,x,0,0,path,no\n", "non-number"),
                     ("leg,distance_km,ascent_m,descent_m,terrain,water_at_end\nA,1,-5,0,path,no\n", "negative"),
                     ("leg,distance_km,ascent_m,descent_m,terrain,water_at_end\nA,1,0,0,lava,no\n", "unknown terrain")]:
        try:
            read_legs(bad); check("rejects " + why, False)
        except InputError:
            check("rejects " + why, True)
    try:
        hm("25:00"); check("rejects bad time", False)
    except InputError:
        check("rejects bad time", True)
    passed = sum(res)
    print(f"{passed}/{len(res)} passed")
    return 0 if passed == len(res) else 1


def main():
    ap = argparse.ArgumentParser(description="Hiking route time and water planner")
    ap.add_argument("csv", nargs="?", help="legs CSV")
    ap.add_argument("--start", help="start time HH:MM")
    ap.add_argument("--sunset", help="sunset time HH:MM")
    ap.add_argument("--pace", type=float, default=5.0, help="flat walking speed km/h (default 5)")
    ap.add_argument("--fitness", type=float, default=1.0, help="time multiplier: 0.85 fast, 1.0 average, 1.2 relaxed, 1.4 with young kids")
    ap.add_argument("--pack-kg", type=float, default=8.0, help="pack weight; +2%% time per kg above 10")
    ap.add_argument("--break-min", type=float, default=10.0, help="break minutes per hour of walking (default 10)")
    ap.add_argument("--temp", type=float, default=18.0, help="expected daytime temperature C")
    ap.add_argument("--margin", type=int, default=60, help="minutes of daylight to keep in hand (default 60)")
    ap.add_argument("--json", action="store_true")
    ap.add_argument("--self-test", action="store_true")
    a = ap.parse_args()
    if a.self_test:
        return self_test()
    if not a.csv or not a.start:
        ap.error("give a CSV and --start, or --self-test")
    try:
        with open(a.csv, encoding="utf-8-sig") as fh:
            legs = read_legs(fh.read())
        p = plan(legs, hm(a.start), hm(a.sunset) if a.sunset else None, a.pace, a.fitness, a.pack_kg, a.break_min, a.temp, a.margin)
    except (OSError, InputError) as e:
        print(f"error: {e}", file=sys.stderr)
        return 2
    print(json.dumps(p, indent=2) if a.json else to_markdown(p, a))
    return 1 if any(f["severity"] == "HIGH" for f in p["findings"]) else 0


if __name__ == "__main__":
    sys.exit(main())
TravelPythonPlanning+2
F@import-252f10c83610ebca1a059c0b
0
Study Abroad Departure Countdown Plan (YAML)
Text

Turn your destination, program, and dates into a YAML study abroad countdown: a document and visa deadline check, a week-by-week plan from 10 weeks out, money and banking setup, health and insurance steps, housing and arrival logistics, packing within luggage limits, things to pause at home, a departure day timeline, and a first-week checklist. 来源:https://prompts.chat/prompts/cmvqcnxkm0009lc08qcb67mok

1role: Organized, encouraging study abroad advisor who helps students turn the chaotic months before leaving for a semester or degree in another country into a calm, week-by-week countdown so nothing important is missed and arrival week goes smoothly
2task: >
3 Turn my destination, program, dates, and situation into a complete departure plan as YAML:
4 a document and deadline check, a week-by-week countdown from 10 weeks before departure to the
5 day I fly, money and banking setup, health and insurance steps, housing and arrival logistics,
6 a phone and digital setup, a packing plan by category with weight limits, things to close or
7 pause at home, a departure day timeline, and a first-week-after-arrival checklist.
8
9inputs:
10 home_country: ${home_country:Canada}
...+110 more lines
TravelPlanningYAML+3
F@import-252f10c83610ebca1a059c0b
0
Stone Farmhouse at the End of Lavender Rows in Provence at Sunrise
Image
Stone Farmhouse at the End of Lavender Rows in Provence at Sunrise

Photoreal sunrise landscape: long purple lavender rows converging along a central dirt path toward a two-story stone farmhouse with a terracotta roof and pale blue shutters in the right third, a tall cypress beside it, a lone oak on the left, a low sun at the far left, and rolling blue hills. Step 2 of the Provence Lavender Farmhouse workflow. 来源:https://prompts.chat/prompts/cmvqcs7uz0001i9086qavf1hh

Long straight rows of purple lavender lead toward an old two-story stone farmhouse in Provence at sunrise, seen from a low viewpoint at the end of a central dirt path, in a wide landscape 16:9 frame. The rounded lavender rows fill the whole lower half of the image and converge toward the middle distance, with narrow brown dirt paths between them and one path running straight up the center. The farmhouse stands in the right third: rough beige stone walls, a brown-terracotta tile roof, and small windows with pale blue shutters, with green shrubs in front of it. A single tall, dark green cypress tree rises right beside the house on its right side. In the left middle distance, a lone round green oak tree stands on a gentle grassy rise. The low sun sits just above the hills at the far left, glowing gold with a soft lens glow and light morning haze, casting warm light across the tops of the lavender. Rolling blue hills stretch across the horizon, and a few small white clouds float in a pale blue sky that warms to peach near the sun. Photoreal landscape photography, wide angle, natural colors, peaceful mood. No people, no text, no logos.
WorkflowRealismTravel+3
F@import-252f10c83610ebca1a059c0b
0
Provence Lavender Farmhouse Scene Concept Brief Builder
Text

Build an image-ready and motion-ready brief for one hero shot of an old stone farmhouse at the end of purple lavender rows in Provence at sunrise: farmhouse and trees, lavender rows, landscape depth, light, fixed details, a motion map, and two prompt seeds: a 16:9 still image and an image-to-video animation. 来源:https://prompts.chat/prompts/cmvqcudn0000ala08deykq1je

Act as a cinematic landscape designer who writes image-ready and motion-ready scene briefs. Help me design one hero shot of an old stone farmhouse at the end of long rows of purple lavender in Provence at sunrise. The shot will first be generated as a still image and then animated into a short video that uses that image as its first frame. Your brief must make the still image rich in elements that can move naturally (lavender rows swaying in a light breeze, morning haze drifting over the hills, the low sun's glow slowly brightening, small clouds drifting, bees over the flowers, a bird or two crossing the sky) while keeping the composition calm, readable, and easy to animate.

My starting choices:
- Farmhouse: a two-story old stone farmhouse with a terracotta tile roof and pale blue shutters
- Trees: one tall dark cypress right beside the house and a lone round oak tree on a grassy rise
- Lavender field: long straight rows of purple lavender with dirt paths between them, converging toward the house
- Landscape: gentle rolling hills fading to blue in the distance
- Time and light: sunrise with the sun just above the hills, warm golden light, long shadows, light haze
- Visual style: photoreal landscape photography, natural colors
- Mood words: peaceful, warm, fragrant, timeless

First ask me, in one short message, for anything missing: the camera position I prefer (low at the end of a lavender row, standing height on the path, or slightly elevated), which side of the frame the farmhouse and the oak tree should sit on, where the sun should be, how much haze I want, and anything to avoid (people, cars, tractors, fences, signs, birds that would have to fly convincingly, text, logos, or copying a specific real photograph).

Then produce the brief with these sections:

1. **Scene Overview**: two or three sentences describing the place, the time, the light, and the feeling of the moment. Describe an imagined Provence scene in the spirit of the region, not a copy of a specific photograph or a named farm.

2. **Farmhouse and Trees**: the farmhouse's position and size in the frame, its stone walls, roof, shutters, windows, and the shrubs around it, the cypress and oak trees and where they stand, and how the low sun lights each of them.

3. **Lavender Rows and Foreground**: the number of rows visible, the central path, how the rows converge toward the vanishing point, the color of the flowers in sun and shade, and the texture of the closest stems.

4. **Landscape and Depth**: the depth layers from the foreground lavender to the farmhouse, the oak on its rise, the middle-distance greenery, and the hills on the horizon, and how haze softens each layer.

5. **Light and Sky**: the sun's position and height, the glow and lens warmth around it, the sky gradient, the shape and position of the clouds, the length and direction of the shadows along the rows.

6. **Fixed Visual Details**: a numbered list of 8 to 10 details that must stay identical in the still image and in the video (farmhouse position, roof and shutter colors, cypress position, oak position, row direction and central path, sun position, horizon line, cloud layout, camera position, framing).

7. **Motion Map**: a table of every element that can move in the video, with columns: element, type of motion, direction, speed (very slow, slow, medium), and how strongly it should move. Include the lavender, the haze, the sun glow, the clouds, the trees, bees or birds, and the camera move. Keep total motion subtle and physically plausible, with one wind direction.

8. **Prompt Seed A - Hero Still Image**: a ready-to-paste image prompt under 170 words for a wide landscape 16:9 frame, with the lavender rows, the stone farmhouse, and the sunrise in the first sentence, ending with: no people, no text, no logos.

9. **Prompt Seed B - Image-to-Video Animation**: a ready-to-paste video prompt under 120 words that starts from the hero still as the first frame, describes the lavender swaying, the haze drifting, the glow brightening, small clouds drifting, one very slow push-in along the central row for about 6 seconds, and says to keep the farmhouse, trees, rows, and framing exactly as in the image with no new objects.

Rules: no people, vehicles, or farm machinery; no text, signs, or logos; no fast camera moves or cuts; and no motion that breaks physics (all plants bend the same way in the wind, the house and trees never move or change shape, the sun does not jump, shadows stay consistent with the sun). Use short paragraphs and lists.
Image To VideoWorkflowTravel+2
F@import-252f10c83610ebca1a059c0b
0
Video
Provence Lavender Farmhouse at Sunrise (Image-to-Video Animation)

Animate the step 2 lavender farmhouse image as the first frame into a calm 6-second shot: the lavender sways in a light breeze, the camera pushes slowly down the central row toward the stone farmhouse, the sun glow brightens, haze drifts, small birds cross the sky, and bees hover over the rows. Step 3 of the Provence Lavender Farmhouse workflow. 来源:https://prompts.chat/prompts/cmvqcv6ek000dlc08ocww82lv

Start from the step 2 image "Stone Farmhouse at the End of Lavender Rows in Provence at Sunrise" as the exact first frame, and animate it into a calm 6-second cinematic shot. Keep the stone farmhouse with its terracotta roof and pale blue shutters in the right third, the tall cypress beside it, the lone oak tree on the left, the converging lavender rows and central path, the low sun at the far left, the horizon line, and the composition exactly as in the image. A gentle breeze makes the lavender rows sway softly, all in the same direction. The camera makes a very slow, steady push-in along the central row toward the farmhouse. The sun's golden glow slowly brightens and thin morning haze drifts across the hills on the left. A couple of small birds fly across the sky from right to left above the house, a few bees drift over the lavender in the foreground, and the small white clouds drift slightly. Natural, realistic motion, no cuts, no people, no new buildings or objects, no text. Soft sound of a light breeze, distant birdsong, and buzzing bees.
Video GenerationImage To VideoWorkflow+2
F@import-252f10c83610ebca1a059c0b
0
Wedding Guest Logistics Plan Builder (YAML)
Text

Turn your wedding date, venues, and guest list into a YAML guest logistics plan: RSVP fields and chase plan, guest groups, hotel room blocks, arrivals and shuttle runs, a welcome pack, meal and dietary tracking, seating rules, accessibility and family needs, a communication timeline, a day-of guest flow, contingencies, and task owners. 来源:https://prompts.chat/prompts/cmvrs1ab1000bjt07tgxjaii5

1role: Warm, detail-minded wedding logistics coordinator who helps couples and their families get every guest invited, housed, transported, seated, fed, and informed on time, so the wedding weekend runs smoothly and nobody is left stranded or confused
2task: >
3 Turn my wedding details, guest list summary, and venues into a complete guest logistics plan as YAML:
4 an RSVP and guest data plan, a guest group breakdown, accommodation and room block steps, travel
5 and shuttle schedules, a welcome and information pack outline, meal and dietary tracking, seating
6 plan rules, accessibility and family needs, a communication timeline from save-the-dates to the day
7 after, a day-of guest flow, and a contingency plan for weather, delays, and no-shows.
8
9inputs:
10 wedding_date: ${wedding_date:a Saturday in mid-June}
...+112 more lines
TravelPlanningYAML+3
F@import-252f10c83610ebca1a059c0b
0
Photoreal Yellow Kayak in a Bioluminescent Bay Under the Milky Way
Image
Photoreal Yellow Kayak in a Bioluminescent Bay Under the Milky Way

Photoreal long-exposure night shot: an empty yellow sea kayak in the center of a calm tropical bay, electric-blue bioluminescent trails swirling behind it toward the lower left, a dark mangrove shoreline on the left, the Milky Way arching over the upper right, and a few tiny distant lights on the horizon. 来源:https://prompts.chat/prompts/cmvrs3v4o000jjt07vjf9beoz

A photorealistic night photograph of a single empty yellow sea kayak floating on a calm tropical bay that glows with electric-blue bioluminescent plankton, under the Milky Way, in a wide landscape 16:9 frame. The long yellow kayak sits in the center of the frame, angled toward the upper right, with black round deck hatches, a dark open cockpit, and thin deck lines; no paddle and no person. Behind and around it, bright electric-blue glowing trails swirl and spread across the dark water toward the lower left corner, like light ribbons stirred up by its passage. A dark silhouette of a mangrove tree line runs along the left shore, its tangled roots just above the waterline, tapering into a low horizon near the center. The Milky Way arches across the upper right of the sky with soft dust lanes and a pale glow, over a dense field of tiny stars in deep navy blue. The water is glassy and dark, with faint star reflections and gentle ripples, and a few tiny warm lights twinkle on the far horizon at the right. Long-exposure astrophotography look, wide-angle lens, sharp detail, natural colors, quiet and magical mood. No people, no text.
PhotorealisticRealismTravel+2
F@import-252f10c83610ebca1a059c0b
0
Dutch Windmill Canal Scene Concept Brief Builder
Text

Build an image-ready and motion-ready brief for one hero shot of brick windmills along a straight, calm Dutch polder canal at sunrise: windmills, canal reflections, banks and rowboat, landscape depth, light, fixed details, a motion map, and two prompt seeds: a 16:9 still image and an image-to-video animation. 来源:https://prompts.chat/prompts/cmvrs5rv8000rjt07k5dr2kuk

Act as a cinematic landscape designer who writes image-ready and motion-ready scene briefs. Help me design one hero shot of traditional brick windmills standing along a straight, calm Dutch polder canal at sunrise. The shot will first be generated as a still image and then animated into a short video that uses that image as its first frame. Your brief must make the still image rich in elements that can move naturally (windmill sails turning slowly, mirror reflections shimmering on the canal, reeds swaying at the water's edge, low morning mist over the meadows, the soft sunrise glow) while keeping the composition calm, readable, and easy to animate.

My starting choices:
- Windmills: five round tapered brick windmills with dark caps and wooden lattice sails, standing in a row along one bank
- Canal: a long straight canal with still, mirror-like water receding to a vanishing point
- Banks: grass and reeds on both sides, a narrow dirt path along a grassy dike on the opposite bank
- Foreground detail: a small dark wooden rowboat moored at the water's edge
- Landscape: flat green meadows with low mist and a distant line of trees
- Time and light: sunrise, soft pink, lilac, and gold sky with a warm glow near the horizon
- Visual style: photoreal landscape photography, natural colors
- Mood words: peaceful, quiet, timeless, fresh

First ask me, in one short message, for anything missing: the camera position I prefer (low at the water's edge, standing height on the bank, or slightly elevated), which bank the windmills should stand on, how close the nearest windmill should be, where the sunrise glow should sit, how much mist I want, and anything to avoid (people, cyclists, boats in motion, cars, modern wind turbines, power lines, signs, text, logos, or copying a specific real photograph).

Then produce the brief with these sections:

1. **Scene Overview**: two or three sentences describing the place, the time, the light, and the feeling of the moment. Describe an imagined polder scene in the spirit of the Netherlands, not a copy of a specific photograph or a named landmark.

2. **Windmills**: how many windmills, which bank they stand on, the size of the nearest one in the frame, their brick bodies, caps, small windows, lattice sails and the angle of the sails, the wooden tail or brace structure, and how the low light falls on them.

3. **Canal and Reflections**: the line of the canal toward the vanishing point, how still the water is, which shapes are mirrored, and how the sky colors appear in the water.

4. **Banks and Foreground**: the reeds and grass on each bank, the dike path, the moored rowboat and its rope, and the texture of the closest plants.

5. **Landscape and Depth**: the depth layers from the foreground boat and reeds to the nearest windmill, the receding windmills, the meadows, and the distant tree line, and how mist softens each layer.

6. **Light and Sky**: the position of the sunrise glow, the sky gradient from lilac to pink to gold, the shape of the thin clouds, and how soft the shadows are.

7. **Fixed Visual Details**: a numbered list of 8 to 10 details that must stay identical in the still image and in the video (number and bank of the windmills, nearest windmill position and sail angle, canal line, rowboat position, dike path, horizon line, glow position, cloud layout, camera position, framing).

8. **Motion Map**: a table of every element that can move in the video, with columns: element, type of motion, direction, speed (very slow, slow, medium), and how strongly it should move. Include the sails of each windmill, the reflections, the reeds, the mist, the light, the rowboat, and the camera move. Keep total motion subtle and physically plausible, with one wind direction and all sails turning the same way.

9. **Prompt Seed A - Hero Still Image**: a ready-to-paste image prompt under 170 words for a wide landscape 16:9 frame, with the windmills, the canal, and the sunrise in the first sentence, ending with: no people, no text, no logos.

10. **Prompt Seed B - Image-to-Video Animation**: a ready-to-paste video prompt under 120 words that starts from the hero still as the first frame, describes the sails turning slowly, the reflections shimmering, the reeds swaying, one very slow push-in along the canal for about 6 seconds, and says to keep the windmills, canal, banks, boat, and framing exactly as in the image with no new objects.

Rules: no people, animals that must move convincingly, vehicles, or modern turbines; no text, signs, or logos; no fast camera moves or cuts; and no motion that breaks physics (sails rotate around their hub without changing shape, buildings never move, reflections follow the objects above them, the light does not jump). Use short paragraphs and lists.
Image To VideoWorkflowTravel+2
F@import-252f10c83610ebca1a059c0b
0
Five Brick Windmills Along a Misty Dutch Canal at Sunrise
Image
Five Brick Windmills Along a Misty Dutch Canal at Sunrise

Photoreal sunrise landscape: five brick windmills with dark caps and lattice sails in a row along the left bank of a straight, mirror-calm polder canal, the nearest one large on the left with a wooden tail brace, a small wooden rowboat moored lower left, a grassy dike path with reeds on the right, low mist over the meadow, and a pink, lilac, and gold sky. Step 2 of the Dutch Windmill Canal workflow. 来源:https://prompts.chat/prompts/cmvrs6p0i000vjt07oj6jfvoc

Five traditional brick windmills stand in a row along the left bank of a long, straight, calm Dutch polder canal at sunrise, seen from a low viewpoint at the water's edge, in a wide landscape 16:9 frame. The nearest windmill is large in the left third: a round, tapered brown brick body with small windows, a dark cap, and four wooden lattice sails in a tilted X shape, with a long wooden tail and brace poles slanting down to the ground on its left side. The other four windmills recede along the same left bank toward a vanishing point near the center, each smaller and softer in the mist. The canal runs straight into the distance with mirror-like reflections of the windmills and the sky. In the lower left, a small dark wooden rowboat is moored among green reeds, tied with a rope. On the right bank, a grassy dike with tall reeds along the water and a narrow dirt path runs into the distance, beside a flat meadow with low morning mist and a faint distant tree line. The sky glows soft lilac, pink, and gold with thin streaky clouds, brightest near the horizon just right of center. Photoreal landscape photography, wide angle, natural colors, peaceful mood. No people, no text, no logos.
WorkflowRealismTravel+3
F@import-252f10c83610ebca1a059c0b
0
Video
Dutch Windmill Canal at Sunrise (Image-to-Video Animation)

Animate the step 2 Dutch windmill canal image as the first frame into a calm 6-second shot: the nearest windmill's lattice sails turn clearly while the distant sails turn too, the camera pushes slowly along the canal, reflections shimmer, reeds sway, the moored rowboat stays still, and the soft pink and gold sunrise light holds. Step 3 of the Dutch Windmill Canal workflow. 来源:https://prompts.chat/prompts/cmvrs7pdv000zjt072vfungbm

Start from the step 2 image "Five Brick Windmills Along a Misty Dutch Canal at Sunrise" as the exact first frame, and animate it into a calm 6-second cinematic shot. Keep the five brick windmills on the left bank, the large nearest windmill in the left third with its wooden tail brace, the straight canal, the moored rowboat in the lower left, the grassy dike path and reeds on the right bank, the misty meadow, the horizon line, and the composition exactly as in the image. In a gentle breeze, the lattice sails of the nearest windmill turn slowly and clearly around their hub, and the sails of the distant windmills turn too, all in the same direction. The camera makes a very slow, steady push-in along the canal toward the vanishing point. The mirror reflections on the canal shimmer softly, the reeds along both banks sway gently, and the rowboat stays still at its mooring. The light stays a soft pink and gold sunrise glow. Natural, realistic motion, no cuts, no people, no new buildings or objects, no text. Soft sound of a light breeze, creaking sails, and distant birdsong.
Video GenerationImage To VideoWorkflow+2
F@import-252f10c83610ebca1a059c0b
0
Family Camping Weekend Plan Builder (YAML)
Text

Turn your family, campground, dates, and gear into a YAML camping weekend plan: booking and rules to confirm, weather, water, fire, and lost-child safety, a packing list by category with own, borrow, rent, or buy, campsite setup, kid-friendly meals and a cooler plan, a daily schedule around naps with rainy-day backups, sleep tips, family jobs, leave-no-trace pack-up, and a post-trip review. 来源:https://prompts.chat/prompts/cmvt7rii70009lb07a9gjqzzw

1role: Friendly, safety-minded family camping planner who helps parents organize a relaxed campground weekend with children, from booking and packing to meals, sleep, activities, and leaving no trace, so the trip is fun for the kids and manageable for the adults
2task: >
3 Turn my family, destination, dates, and gear into a complete family camping weekend plan as YAML:
4 a trip summary with readiness and risks, a booking and permits checklist, a weather and safety plan,
5 a shared and per-person packing list by category, a campsite setup plan, a simple meal plan with a
6 cooler and food storage strategy, a kid-friendly schedule for each day with quiet times and backup
7 rainy-day ideas, sleep and comfort tips for children, chores for every family member, a pack-up and
8 leave-no-trace checklist, and a short post-trip review.
9
10inputs:
...+113 more lines
TravelPlanningYAML+3
F@import-252f10c83610ebca1a059c0b
0
Loose Watercolor of Venetian Gondolas on the Grand Canal at Dawn
Image
Loose Watercolor of Venetian Gondolas on the Grand Canal at Dawn

Loose watercolor on textured paper: three covered black gondolas moored beside red-and-white striped mooring poles on the Grand Canal at dawn, a domed baroque basilica silhouette and hazy palazzos with a bell tower across the water, a soft peach and lavender sky, and broken violet and pink reflections in calm water. 来源:https://prompts.chat/prompts/cmvt7v626000llb071xrwy3b9

A loose, atmospheric watercolor painting of covered gondolas moored on the Grand Canal in Venice at dawn, in a landscape 4:3 frame on textured cold-press watercolor paper. In the lower left, three long black gondolas rest side by side, wrapped in dark blue-grey covers, one with a pale tan tarp, the front gondola's curved prow and metal prow ornament rising at the far left edge. Tall wooden mooring poles with red-and-white spiral stripes and small pointed caps stand in the water across the middle and right of the frame, some linked to the gondolas by sagging ropes and chains. Across the canal, a hazy, softly painted skyline of old palazzos stretches to the right, with a slender bell tower, and on the left a large domed baroque basilica with smaller domes and lanterns, in the spirit of Santa Maria della Salute, silhouetted against the light. The sky glows in soft peach, apricot, and lavender washes with drifting clouds. The calm water reflects the poles, gondolas, and sky in broken vertical strokes of violet, pink, and white. Visible brushstrokes, wet-in-wet blooms, granulating pigments, soft edges, and white paper showing through. Peaceful, romantic early-morning mood. No people, no text, no signature.
CreativeArtTravel+2
F@import-252f10c83610ebca1a059c0b
0
Bamboo Forest Firefly Path Scene Concept Brief Builder
Text

Turn a short idea into an image-ready and motion-ready brief for one hero shot of a stepping-stone path through a tall bamboo forest at dusk with fireflies and a small wooden footbridge: path and stream, bamboo walls and canopy, bridge, fireflies, light and mist, fixed details, a motion map, and two prompt seeds: a 16:9 still image and an image-to-video animation. 来源:https://prompts.chat/prompts/cmvt7w7re000plb07zmr3pqjj

Act as a cinematic landscape designer who writes image-ready and motion-ready scene briefs. Help me design one hero shot of a quiet footpath through a tall bamboo forest at dusk, lit by fireflies. The shot will first be generated as a still image and then animated into a short video that uses that image as its first frame. Your brief must make the still image rich in elements that can move naturally (fireflies drifting and blinking, bamboo stems and leaves swaying, low mist rolling over the ground, a shallow stream glinting, the last blue light of twilight) while keeping the composition calm, symmetrical, readable, and easy to animate.

My starting idea: a stone path between tall bamboo at dusk, with fireflies and a little wooden bridge

My starting choices:
- Path: an old stepping-stone path running straight away from the camera toward the center of the frame
- Bamboo: tall, dense green bamboo stems rising on both sides, their tops closing into a canopy with a gap of sky in the middle
- Water: a shallow stream trickling down the middle of the path over stones
- Focal point: a small arched wooden footbridge with railings crossing in the middle distance
- Fireflies: many small glowing yellow-green fireflies scattered through the air and the undergrowth
- Atmosphere: low mist hanging around the bridge and over the path
- Time and light: deep blue twilight just after sunset, a few clouds in the sky gap
- Visual style: photoreal night landscape photography, natural colors
- Mood words: calm, magical, hushed, inviting

First ask me, in one short message, for anything missing: the camera height (low near the stones, standing eye level, or slightly raised), how centered and symmetrical I want the path, how bright and how many fireflies, how much mist, whether the bridge should be close or far, and anything to avoid (people, animals, lanterns, buildings, text, logos, or copying a specific real photograph or a named landmark).

Then produce the brief with these sections:

1. **Scene Overview**: two or three sentences on the place, the moment, the light, and the feeling. Describe an imagined bamboo forest in an East Asian spirit, not a copy of a specific photograph or a famous real grove.

2. **Path and Stream**: the shape and line of the stepping stones toward the vanishing point, the stone texture and moss, how the shallow stream runs down the path from under the bridge, and where the water catches light.

3. **Bamboo Walls and Canopy**: stem thickness, spacing, and nodes on each side, how they rise and lean inward, the leaf canopy, the gap of sky, and the ferns and grasses at their feet.

4. **The Footbridge**: size in the frame, shape of the arch, the wooden railings, the darker opening under it, and how mist gathers around it.

5. **Fireflies**: density, size, color, how they are spread through the air, the undergrowth, and the depth layers, and how their glow should read against the dark bamboo without looking like stars or bokeh dust.

6. **Light, Sky, and Mist**: the twilight sky gradient in the canopy gap, the cool blue ambient light, the warm-green firefly accents, the layers of mist, and how soft the shadows are.

7. **Fixed Visual Details**: a numbered list of 8 to 10 details that must stay identical in the still image and in the video (path line, stream position, bridge position and shape, bamboo walls on both sides, sky gap shape, mist zones, camera position, framing, overall firefly distribution).

8. **Motion Map**: a table of every element that can move in the video, with columns: element, type of motion, direction, speed (very slow, slow, medium), and how strongly it should move. Include the fireflies (drift and blink), the bamboo stems and leaves, the mist, the stream, the light, and the camera move. Keep total motion subtle and physically plausible, with one breeze direction.

9. **Prompt Seed A - Hero Still Image**: a ready-to-paste image prompt under 170 words for a wide landscape 16:9 frame, with the bamboo path, the fireflies, and the footbridge at dusk in the first sentence, ending with: no people, no text, no logos.

10. **Prompt Seed B - Image-to-Video Animation**: a ready-to-paste video prompt under 120 words that starts from the hero still as the first frame, describes the fireflies drifting and blinking, the bamboo swaying gently, the mist rolling low, the stream glinting, one very slow dolly forward along the path toward the bridge for about 6 seconds, and says to keep the path, bamboo, bridge, sky, and framing exactly as in the image with no new objects.

Rules: no people, animals, lanterns, or buildings; no text, signs, or logos; no fast camera moves or cuts; and no motion that breaks physics (bamboo bends from the base and does not stretch, the bridge and stones never move, fireflies drift slowly and do not streak, the light does not jump). Use short paragraphs and lists.
Image To VideoWorkflowTravel+2
F@import-252f10c83610ebca1a059c0b
0
Bamboo Forest Footpath with Fireflies and a Wooden Footbridge at Dusk
Image
Bamboo Forest Footpath with Fireflies and a Wooden Footbridge at Dusk

Photoreal dusk landscape: a stepping-stone path runs straight ahead between tall bamboo walls toward a small arched wooden footbridge, a shallow stream trickles down the middle of the path from under the bridge, hundreds of yellow-green fireflies glow in the air and undergrowth, low mist hangs around the bridge, and a deep blue twilight sky shows through the canopy. Step 2 of the Bamboo Forest Firefly Path workflow. 来源:https://prompts.chat/prompts/cmvt7x383000tlb07f8k2q3rr

A quiet stepping-stone footpath runs straight ahead through a tall bamboo forest at dusk, lit by hundreds of glowing fireflies, toward a small arched wooden footbridge in the middle distance, seen from a low, centered viewpoint at the start of the path, in a wide landscape 16:9 frame. Large flat grey stepping stones lead from the bottom center of the frame toward the bridge, with a shallow stream trickling down the middle of the path over small stones, flowing out from under the bridge and catching faint blue light. Dense walls of tall, slender green bamboo with visible nodes rise on both sides and lean slightly inward, their leafy tops framing a narrow gap of deep blue twilight sky with soft clouds at the top center. The small wooden bridge has a gentle arch and simple railings, with a pale opening beneath it. Low white mist hangs around the bridge and drifts over the path and the undergrowth. Many tiny yellow-green fireflies glow scattered through the air, among the bamboo, and over the ferns, grasses, and mossy rocks along both edges of the path. Cool blue twilight ambience with warm green-yellow firefly accents, photoreal night landscape photography, natural colors, calm and magical mood. No people, no text, no logos.
WorkflowRealismTravel+2
F@import-252f10c83610ebca1a059c0b
0
Video
Bamboo Forest Fireflies at Dusk (Image-to-Video Animation)

Animate the step 2 bamboo forest footpath image as the first frame into a calm 6-second shot: the camera dollies slowly along the stepping stones toward the wooden footbridge, fireflies drift and blink, bamboo sways gently, low mist rolls over the path, the stream glints, and the deep blue twilight holds. Step 3 of the Bamboo Forest Firefly Path workflow. 来源:https://prompts.chat/prompts/cmvt7y64e000xlb07godow8qd

Start from the step 2 image "Bamboo Forest Footpath with Fireflies and a Wooden Footbridge at Dusk" as the exact first frame, and animate it into a calm 6-second cinematic shot. Keep the stepping-stone path, the shallow stream running down its center, the small arched wooden footbridge in the middle distance, the tall bamboo walls on both sides, the gap of deep blue twilight sky, the mist around the bridge, and the composition exactly as in the image. The camera makes a very slow, smooth dolly forward along the path toward the bridge. The yellow-green fireflies drift gently through the air and blink softly on and off at different times. The bamboo stems and leaves sway slightly in a light breeze, all in the same direction. Low mist rolls slowly over the path and around the bridge, and the stream glints and ripples as it flows toward the camera. The cool blue twilight light stays steady. Natural, realistic motion, no cuts, no people, no animals, no new objects, no text. Soft sound of trickling water, rustling bamboo leaves, and evening insects.
Video GenerationImage To VideoWorkflow+2
F@import-252f10c83610ebca1a059c0b
0
Mid-Century Travel Poster of a Norwegian Fjord with a Red Ferry
Image
Mid-Century Travel Poster of a Norwegian Fjord with a Red Ferry

Flat mid-century screen-print travel poster in portrait 3:4, no text: a big mustard sun disc in a pale yellow sky, steep grey and green cliffs with snow patches and a thin white waterfall framing the fjord, snowy peaks at its end, deep teal water with white wave lines, a small red-and-white ferry with a wake in the lower left, and red wooden houses with white roofs on the right shore. 来源:https://prompts.chat/prompts/cmvun3oa0000hjn08yiiahois

A mid-century modern travel poster illustration of a Norwegian fjord with a small red ferry, in a portrait 3:4 frame, in a flat screen-print style with no text. A large, perfectly round mustard-yellow sun disc hangs at the top center in a pale butter-yellow sky. Steep cliffs rise on both sides like a gateway: on the left, tall slate-grey rock faces with olive-green grassy ledges and white snow patches, with a long, thin white waterfall tumbling down the cliff into the water; on the right, a grey cliff with snow on its upper slopes and a dark green forested hillside below. At the far end of the fjord, sharp snow-covered mountain peaks in white and pale grey close the view in the center. The deep teal-blue water fills the lower third, drawn with simple white and light-blue wave lines and reflections. In the lower left foreground, a small red-and-white ferry with a white cabin, a red upper deck, and a short mast sails toward the right, leaving a white wake trailing behind it to the left. On a grassy point along the right shore sits a small village of about six red wooden houses with white roofs, with a few dark green trees and a pale rocky shoreline. Limited palette of slate grey, teal blue, olive and forest green, red, cream, and mustard yellow, crisp simplified shapes, subtle halftone and visible paper grain texture, vintage 1950s travel advertising mood. No text, no lettering, no logos.
ArtTravelVisual+2
F@import-252f10c83610ebca1a059c0b
0
Snowy Mountain Onsen at Dusk Scene Concept Brief Builder
Text

Turn a short idea into an image-ready and motion-ready brief for one hero shot of a steaming outdoor hot spring beside a snowy traditional mountain inn at blue hour: pool and rocks, steam, the inn and its lit windows, stone lanterns, pines and mountain, light and snowfall, fixed details, a motion map, and two prompt seeds: a 16:9 still image and an image-to-video animation. 来源:https://prompts.chat/prompts/cmvun5gx9000pjn08nc45hr3k

Act as a cinematic landscape designer who writes image-ready and motion-ready scene briefs. Help me design one hero shot of a steaming outdoor hot spring (onsen) beside a traditional mountain inn during snowfall at dusk. The shot will first be generated as a still image and then animated into a short video that uses that image as its first frame. Your brief must make the still image rich in elements that can move naturally (steam drifting and curling over the water, snowflakes falling, soft snow slipping off a pine branch, gentle ripples on the pool, the warm glow of lanterns and windows) while keeping the composition calm, balanced, readable, and easy to animate.

My starting idea: a steaming rock-lined hot spring in the snow next to an old wooden inn, at blue hour, with stone lanterns

My starting choices:
- Pool: a natural outdoor pool of clear teal water framed by dark volcanic rocks capped with snow, filling the center and foreground
- Steam: thick white steam rising from the water and drifting to one side
- Inn: a two-storey traditional Japanese wooden inn on the right with snow-covered tiled roofs and rows of warmly lit windows
- Lanterns: two snow-capped stone lanterns glowing softly, one small on the left rocks and one larger near the inn
- Trees and mountains: snow-laden pine trees behind the pool and a dark forested mountain slope on the left
- Weather: large soft snowflakes falling slowly
- Time and light: deep blue twilight just after sunset, warm amber light from the inn and lanterns
- Visual style: photoreal travel and landscape photography, natural colors
- Mood words: quiet, warm, peaceful, wintry, inviting

First ask me, in one short message, for anything missing: the camera height (low near the water, eye level, or slightly raised), how much of the frame the inn should take, how dense the steam and snowfall should be, how bright the windows and lanterns are, whether I want one small natural event in the video (for example a clump of snow sliding off a pine branch into the pool), and anything to avoid (people, bathers, animals, text, signs, logos, or copying a specific real inn, photograph, or named landmark).

Then produce the brief with these sections:

1. **Scene Overview**: two or three sentences on the place, the moment, the light, and the feeling. Describe an imagined mountain hot spring inn in a Japanese spirit, not a copy of a specific real ryokan or a famous photograph.

2. **The Pool and Rocks**: the pool's shape and size in the frame, the water color and clarity, the dark rocks around it and the snow on their tops, and where the water catches warm and cool light.

3. **Steam**: how thick it is, where it rises most, which way it drifts, how it softens the background, and how it should read as warm vapor rather than fog or smoke.

4. **The Inn**: its position, number of storeys, roof shape and the snow on it, the wooden walls, the rows of lit windows, and how much detail is visible through the steam and snow.

5. **Lanterns, Trees, and Mountain**: the two stone lanterns with snow caps and their glow, the snow-laden pines behind the pool (including one branch above the water that could shed snow), and the dark mountain slope against the sky.

6. **Light, Sky, and Snow**: the deep blue twilight sky, the cool ambient light on the snow, the warm amber accents from the windows and lanterns, the size and density of the falling snowflakes, and how soft the shadows are.

7. **Fixed Visual Details**: a numbered list of 8 to 10 details that must stay identical in the still image and in the video (pool shape and position, rock edges, inn position and roofline, window pattern, both lantern positions, pine trees, mountain silhouette, camera position, framing, overall steam zone).

8. **Motion Map**: a table of every element that can move in the video, with columns: element, type of motion, direction, speed (very slow, slow, medium), and how strongly it should move. Include the steam, the snowfall, the water surface, the lantern and window glow, one optional snow clump falling from a pine branch into the pool with a small splash and ripples, and the camera move. Keep total motion subtle and physically plausible, with one gentle air direction.

9. **Prompt Seed A - Hero Still Image**: a ready-to-paste image prompt under 170 words for a wide landscape 16:9 frame, with the steaming hot spring, the snowy inn, and the stone lanterns at blue hour in the first sentence, ending with: no people, no text, no logos.

10. **Prompt Seed B - Image-to-Video Animation**: a ready-to-paste video prompt under 120 words that starts from the hero still as the first frame, describes the steam drifting and curling, snow falling, the steady glow of lanterns and windows, a slow gentle push-in toward the pool and the inn for about 6 seconds, and (if I want it) one clump of snow falling from a pine branch into the pool with a small splash and spreading ripples, and says to keep the pool, rocks, inn, lanterns, trees, and framing exactly as in the image with no new objects.

Rules: no people, bathers, or animals; no text, signs, or logos; no fast camera moves or cuts; and no motion that breaks physics (rocks, lanterns, and the inn never move, steam rises and drifts and does not pour downward, snow falls slowly and evenly, a falling snow clump drops straight down under gravity and makes only a small splash, the light does not flicker or jump). Use short paragraphs and lists.
Image To VideoWorkflowTravel+2
F@import-252f10c83610ebca1a059c0b
0
Steaming Outdoor Hot Spring Beside a Snowy Mountain Inn at Blue Hour
Image
Steaming Outdoor Hot Spring Beside a Snowy Mountain Inn at Blue Hour

Photoreal blue-hour snowfall scene: a steaming rock-lined hot spring of clear teal water fills the foreground, framed by dark snow-capped rocks, with a small glowing stone lantern on the left, a larger one beside a two-storey wooden inn with snowy tiled roofs and warmly lit windows on the right, snow-laden pines, and a dark mountain slope under a deep blue sky. Step 2 of the Snowy Mountain Onsen at Dusk workflow. 来源:https://prompts.chat/prompts/cmvun6fxo000tjn083mk5fz8o

A steaming outdoor hot spring pool beside a traditional Japanese mountain inn during gentle snowfall at blue hour, lit by two glowing stone lanterns, seen from a low viewpoint at the edge of the water, in a wide landscape 16:9 frame. A natural pool of clear teal water with a faint green glow fills the center and lower middle of the frame, framed by dark, rounded volcanic rocks with thick caps of fresh snow in the foreground and along both sides. Thick white steam rises from the water, strongest over the left and center of the pool, drifting up and softening the trees behind. On the left rocks stands a small snow-capped stone lantern with a warm glowing window; on the right, close to the inn, stands a larger stone lantern with a wide snow-covered cap, also glowing warm amber. On the right side of the frame rises a two-storey traditional wooden inn with dark timber walls, deep eaves, and snow-covered tiled roofs, its long rows of paper and glass windows glowing warm amber from inside. Behind the pool, tall pine trees are heavy with snow, and on the left a dark forested mountain slope rises against a deep blue twilight sky. Large soft snowflakes fall across the whole scene. Cool blue ambient light with warm amber accents from the windows and lanterns, photoreal travel and landscape photography, natural colors, quiet, warm, and peaceful mood. No people, no text, no logos.
WorkflowRealismTravel+2
F@import-252f10c83610ebca1a059c0b
0
Video
Snowy Mountain Onsen at Dusk (Image-to-Video Animation)

Animate the step 2 hot spring image as the first frame into a calm 6-second shot: a slow push-in toward the pool and the inn, steam drifting and curling over the teal water, snow falling, lanterns and windows glowing steadily, and a clump of snow dropping from a pine branch into the pool with a small splash and spreading ripples. Step 3 of the Snowy Mountain Onsen at Dusk workflow. 来源:https://prompts.chat/prompts/cmvun7ckk000xjn08ddmrusqv

Start from the step 2 image "Steaming Outdoor Hot Spring Beside a Snowy Mountain Inn at Blue Hour" as the exact first frame, and animate it into a calm 6-second cinematic shot. Keep the teal hot spring pool, the dark snow-capped rocks around it, the small stone lantern on the left, the larger stone lantern on the right, the two-storey wooden inn with its snowy roofs and warmly lit windows, the snow-laden pine trees, the dark mountain slope, the deep blue twilight sky, and the composition exactly as in the image. The camera makes a slow, gentle push-in toward the pool and the inn. Thick white steam drifts and curls slowly over the water and rises toward the trees. Large soft snowflakes keep falling evenly across the scene. The lanterns and the inn windows glow steadily without flickering. About two thirds of the way through, a small clump of snow slips off a pine branch above the pool and drops straight down into the water near the center, making a small white splash and soft ripples that spread outward and fade. The shot ends calm, with the steam still drifting. Natural, realistic motion, no cuts, no people, no animals, no new objects, no text. Soft sound of bubbling water, a quiet splash, and the hush of falling snow.
Video GenerationImage To VideoWorkflow+2
F@import-252f10c83610ebca1a059c0b
0
Commute Cost Comparison Calculator
Skill

Compares commute options - car (fuel or EV), transit, bike, e-bike, walking, day-share mixes and park-and-ride legs - per month and year with cash cost, door-to-door time, time cost at your own hourly value, cost per trip and CO2. Picks pass vs pay-per-ride for the days you ride, separates car running costs from fixed costs, and shows the break-even value of an hour. Includes a stdlib Python calculator with --self-test. 来源:https://prompts.chat/prompts/cmvunjt9s0009ju0859cph6yi

---
name: commute-cost-comparison-calculator
description: Compares commute options - car (fuel or EV), transit, bike, e-bike, walking, day-share mixes and park-and-ride legs - per month and year with cash cost, door-to-door time, time cost at your own hourly value, cost per trip and CO2. Picks pass vs pay-per-ride for the days you ride, separates car running costs from fixed costs, and shows the break-even value of an hour. Includes a stdlib Python calculator with --self-test.
---

# Commute Cost Comparison Calculator

You help someone decide how to get to work by putting every option on the same footing: what it costs in cash, how much of their life it takes, and what that time is worth to them. You count what really changes with the choice (fuel, parking, fares, the bike), keep costs they pay anyway out unless they would actually sell the car, and show the trade-off as a clear number: "driving saves 32 lost hours a year and costs $3,697 more, so it pays only if your hour is worth more than $115".

## Files in this skill

- `scripts/commute_cost.py` - reads a scenario JSON (distance, commute days, value of time, options) and prints a comparison table, headline, break-even values of time and per-option notes; supports metric (km, L/100 km) and imperial (mi, mpg), EVs, transit passes with daily caps and employer subsidies, day-share mixes and multi-leg trips (Python 3.8+ standard library only)
- `references/cost-components.md` - every option field, what to include for each mode, where to find the numbers, and typical ranges
- `references/time-value-and-assumptions.md` - how to choose a value of time, usable time on transit, what the totals leave out (health, safety, weather, flexibility) and how to run sensitivity checks
- `templates/commute-comparison.md` - the decision summary to hand back
- `examples/commute.json` - an 11-mile commute with driving, bus + light rail, an e-bike, an e-bike/transit mix and park-and-ride
- `examples/comparison-output.md` - the real output of the calculator for that scenario

## Workflow

### 1. Collect the facts
One-way distance, commute days per week (hybrid work matters a lot) and weeks worked per year, door-to-door minutes per option (including walking, waiting, parking and transfers: ask for a real trip, not the map estimate), and per mode: car fuel economy, fuel or electricity price, parking and tolls, whether they would keep the car anyway; transit fare, pass price, daily cap, employer subsidy; bike or e-bike price, expected life and upkeep. Ask what an hour of their time is worth, or offer a default (half their hourly pay) and show the sensitivity.

### 2. Run the calculator
```
python3 scripts/commute_cost.py examples/commute.json
python3 scripts/commute_cost.py scenario.json --days-per-week 3
python3 scripts/commute_cost.py scenario.json --value-of-time 0 --json
python3 scripts/commute_cost.py --self-test
```
Exit 0 = comparison printed, 2 = bad input (missing field, mix shares not adding up to 1, unknown mode, negative price). Without code, follow the formulas in `references/cost-components.md`.

### 3. Read the result
- The table is sorted by total (cash + time cost); the headline names the cheapest in cash, the cheapest once time counts and the fastest.
- **Break-even value of time** compares every option with the cheapest in cash: an option that costs more is worth it only if your hour is worth more than the number shown. "Never" means it costs more and does not save usable time.
- Time spent on transit that you can use (reading, email) is discounted with `usable_time_share`; the same field can credit bike time that replaces exercise you would do anyway. Say which you used.
- Check the transit note: on 2-3 commute days a week a monthly pass is often dearer than pay-per-ride; the calculator picks the cheaper and says so.

### 4. Deliver
Fill `templates/commute-comparison.md`: recommendation in one sentence, the table, break-even values, what changes the answer (hybrid days, fuel price, parking, value of time), what is not priced, and a trial suggestion (e.g. two weeks of the mix before buying anything).

## Example result
11 miles each way, 5 days a week, 46 weeks, time valued at $20/hour (`examples/commute.json`). Cheapest in cash: bus + light rail at $49/month after a $50 employer subsidy (the $99 pass beats $105 of single fares). Cheapest once time counts: park and ride ($95 cash, $361/month total) because 80 % of the train leg is usable. Driving downtown is fastest (28 min) but costs $357/month with $12/day parking and pays off only if an hour is worth more than $115. The e-bike costs $67/month all-in and emits nothing, but it does not save usable time at these numbers; it wins if the ride replaces gym time. See `examples/comparison-output.md`.

## Rules

- Count only costs that change with the choice; include car insurance, registration and loan costs only if the person would actually give up the car (`count_fixed`).
- Use real door-to-door times, including walking, waiting, parking and transfers.
- Never present the value of time as a fact: it is the person's own choice; show at least one sensitivity run (e.g. `--value-of-time 0` and their wage).
- Keep health, safety and weather out of the money totals but mention them; do not moralize about cars or bikes.
- State every assumption with its number (fuel price, parking, depreciation per mile) so the person can change it.
- Give currency and units as the person uses them; do not mix miles and kilometres in one scenario.
FILE:references/cost-components.md
# Cost components and option fields

Scenario fields: `currency` (USD, EUR, GBP, TRY, ...), `units` (`metric`: km, L/100 km, price per litre; `imperial`: miles, mpg, price per US gallon), `one_way_distance`, `days_per_week` (default 5), `weeks_per_year` (default 46: holidays, sick days, travel), `value_of_time_per_hour`, `options`.

Every option: `name`, `mode`, `minutes_one_way` (door to door), optional `distance_one_way` (defaults to the scenario distance), optional `usable_time_share` (0..1).

## Car (`mode: car`)
| Field | Meaning | Typical |
|---|---|---|
| `fuel_economy_mpg` / `fuel_l_per_100km` | real-world consumption on this route (city driving is worse than the label) | 25-35 mpg / 6-9 L/100 km |
| `fuel_price` | per gallon / per litre | local pump price |
| `fuel: "diesel"` | uses the diesel CO2 factor | petrol default |
| `kwh_per_100` + `electricity_price` | electric car instead of fuel (kWh per 100 mi or km) | 25-35 kWh/100 mi, 16-22 kWh/100 km |
| `grid_kg_co2_per_kwh` | grid intensity for EV CO2 | 0.4 default; 0.05 hydro/nuclear, 0.7 coal-heavy |
| `maintenance_per_distance` | tyres, servicing, repairs per mile/km | $0.08-0.12/mi, 0.05-0.08/km |
| `depreciation_per_distance` | value lost from extra mileage only (not age) | $0.05-0.15/mi |
| `parking_per_day`, `tolls_per_day` | per commute day | workplace parking can dominate |
| `fixed_per_year` + `count_fixed` | insurance, registration, loan interest, age depreciation; counted only when `count_fixed` is true | true only if commuting is the reason to own the car |

Fuel cost = 2 x distance x days / mpg x price (or x L/100 km / 100 x price). CO2: petrol 2.35 kg/L (8.89 kg per US gallon), diesel 2.68 kg/L (10.18 kg/gal), EV kWh x grid factor.

All-in per-mile rates (tax mileage rates, AAA "Your Driving Costs") include fixed costs; they overstate the marginal cost of a commute when the car is kept anyway.

## Transit (`mode: transit`)
| Field | Meaning |
|---|---|
| `fare_per_ride`, `rides_per_day` (default 2) | single fares; add a ride for each paid transfer that is not free |
| `daily_cap` | fare capping per day, if the system has it |
| `monthly_pass` | price per month; the calculator compares 12 passes with pay-per-ride for the actual days and picks the cheaper |
| `subsidy_per_month` | employer or tax-free benefit, deducted (never below zero) |
| `co2_g_per_passenger_km` | default 80 g; electric rail 20-40, diesel bus 80-120 at average load |
| `usable_time_share` | share of the trip you can read or work (seat, no transfer stress): 0.2-0.8 |

## Bike, e-bike, walk (`mode: bike | ebike | walk`)
| Field | Meaning | Typical |
|---|---|---|
| `purchase_price`, `life_years` | spread over the life (default 5 years); not used for walk | e-bike $1,500-3,500 |
| `maintenance_per_year` | tyres, chain, brake pads, battery fund for e-bikes | $100-300 |
| `gear_per_year` | lights, lock, rain gear, helmet replacement | $50-150 |
| `kwh_per_100`, `electricity_price` | e-bike charging | 1-2 kWh per 100 mi |
| `other_per_month` | bike parking, locker, shower membership | 0-30 |
Ownership costs are counted in full even in a mix: you pay for the bike whether you ride 3 or 5 days.

## Mix (`mode: mix`)
`"shares": {"E-bike": 0.6, "Bus + light rail": 0.4}` splits commute days between other options (shares add up to 1). Each part is costed for its own days, so a transit part on 2 days a week usually goes pay-per-ride. Use it for weather-dependent cycling, hybrid driving, or carpool days.

## Multi-leg (`mode: multi`)
`"legs": [ {car leg}, {transit leg} ]` with `transfer_minutes`. Each leg needs its own `distance_one_way` and `minutes_one_way`; costs and minutes are summed. Use it for park and ride, bike + train, or walk + bus.

## Where to get the numbers
- Fuel economy: the car's trip computer over a week of commuting.
- Parking and fares: the operator's price page; check employer benefits (pre-tax transit, parking cash-out).
- Door-to-door time: time one real trip each way at commute hours; add 5 minutes for parking or waiting variability.
FILE:references/time-value-and-assumptions.md
# Value of time and what the totals leave out

## Choosing a value of time
- There is no correct number: it is what an hour of this person's commute is worth to them.
- Common anchor: about half of hourly take-home pay for personal travel (the US Department of Transportation's travel-time guidance uses 50 % of hourly income for personal local trips; business travel is valued at 100 %).
- Someone on a fixed salary who cannot earn more by commuting less may choose a lower value; a freelancer who bills the saved hours may choose a higher one.
- Always show a sensitivity: `--value-of-time 0` (cash only), the chosen value, and their full hourly wage. If the ranking does not change, the decision is robust.

## Usable time
`usable_time_share` discounts time you can use. Rough guide:
| Situation | Share |
|---|---|
| Driving, cycling in traffic, standing on a crowded bus | 0 |
| Bus with a seat, short hops, transfers | 0.2-0.4 |
| Train with a seat and table, 20+ minutes without changes | 0.6-0.8 |
| Bike or walk that replaces exercise you would otherwise do | 0.3-0.7 (say so explicitly) |

## Not in the money totals (mention them)
- **Health:** regular cycling or walking is associated with better cardiovascular health; some people value it highly, others not at all. Use `usable_time_share` if they want it priced.
- **Safety:** road risk per mile differs by mode and route; a protected bike route changes the picture.
- **Weather and season:** use a mix (e.g. 60 % bike days) rather than assuming every day is a bike day.
- **Reliability:** a 40-minute train with a 10-minute spread may beat a 30-minute drive that ranges from 25 to 60; ask about late penalties (childcare pick-up).
- **Flexibility and option value:** having a car for errands on the way, or for emergencies; car share or taxi credits can replace it for rare days (add them as `other_per_month`).
- **Stress and comfort:** do not price it, but ask.

## Sensitivity runs worth doing
- Hybrid work: `--days-per-week 3` often flips pass vs pay-per-ride and makes owning a second car look worse.
- Parking: a change in parking price (or employer parking cash-out) is often the biggest single lever.
- Fuel or electricity price +-25 %.
- Selling a second car: rerun with `count_fixed: true` on the car to see the full saving.

## Sanity checks before presenting
- Cash per trip for driving should be at least fuel + parking per trip.
- Transit cash per month should not exceed the pass price unless the pass does not cover the route.
- Hours per month = minutes one way x 2 x days per month / 60.
- If the "winner" depends on a value of time far from what the person said, say so plainly.
FILE:templates/commute-comparison.md
# Commute options: <home> to <work>

**Trip:** <11 mi each way, 5 days/week, 46 weeks/year>   **Value of time used:** <$20/hour (about half of hourly pay)>
**Recommendation:** <one sentence, e.g. "Park and ride: $95/month cash, 40 min door to door, most of the train ride usable for email">

## Comparison (per month)
| Option | Cash | Door to door | Hours | Time cost | Total | CO2 kg/year |
|---|---|---|---|---|---|---|
| <Park and ride> | <$95> | <40 min> | <25.6> | <$266> | <$361> | <999> |
| <Bus + light rail> | <$49> | <46 min> | <29.4> | <$411> | <$460> | <651> |

## When a dearer option pays off
| Option | Extra per year | Lost hours saved | Worth it above |
|---|---|---|---|
| <Drive downtown> | <$3,697> | <32> | <$115/hour> |

## What would change the answer
- <Hybrid work (3 days): transit pass no longer pays; pay per ride ...>
- <Parking cash-out from the employer would make driving $230/month dearer still>
- <If the e-bike ride replaces the gym, the e-bike moves to ...>

## Not priced
- <health, safety on the route, weather days, reliability, needing the car for school pick-up>

## Assumptions
- <fuel $3.40/gal at 28 mpg; maintenance $0.10/mi; mileage depreciation $0.08/mi; parking $12/day>
- <transit pass $99, employer subsidy $50/month, 30 % of the bus/rail time usable>
- <car kept for weekends, so insurance and registration are not counted>

## Next step
<Try the mix for two weeks before buying the e-bike; time each trip door to door.>
FILE:examples/commute.json
{
  "currency": "USD",
  "units": "imperial",
  "one_way_distance": 11,
  "days_per_week": 5,
  "weeks_per_year": 46,
  "value_of_time_per_hour": 20,
  "options": [
    {
      "name": "Drive downtown",
      "mode": "car",
      "minutes_one_way": 28,
      "fuel_economy_mpg": 28,
      "fuel_price": 3.4,
      "maintenance_per_distance": 0.1,
      "depreciation_per_distance": 0.08,
      "parking_per_day": 12,
      "tolls_per_day": 0,
      "fixed_per_year": 1900,
      "count_fixed": false
    },
    {
      "name": "Bus + light rail",
      "mode": "transit",
      "minutes_one_way": 46,
      "fare_per_ride": 2.75,
      "monthly_pass": 99,
      "subsidy_per_month": 50,
      "usable_time_share": 0.3
    },
    {
      "name": "E-bike",
      "mode": "ebike",
      "minutes_one_way": 42,
      "purchase_price": 2200,
      "life_years": 5,
      "maintenance_per_year": 250,
      "gear_per_year": 100,
      "kwh_per_100": 1.5,
      "electricity_price": 0.17
    },
    {
      "name": "E-bike 3 days, transit 2 days",
      "mode": "mix",
      "shares": {"E-bike": 0.6, "Bus + light rail": 0.4}
    },
    {
      "name": "Park and ride",
      "mode": "multi",
      "transfer_minutes": 6,
      "legs": [
        {"mode": "car", "distance_one_way": 4, "minutes_one_way": 10, "fuel_economy_mpg": 28, "fuel_price": 3.4,
         "maintenance_per_distance": 0.1, "depreciation_per_distance": 0.08, "parking_per_day": 0},
        {"mode": "transit", "distance_one_way": 7, "minutes_one_way": 24, "fare_per_ride": 2.75, "monthly_pass": 99,
         "subsidy_per_month": 50, "usable_time_share": 0.8}
      ]
    }
  ]
}
FILE:examples/comparison-output.md
# Commute cost comparison

One way: 11 mi   Commute days: 19.2/month (230/year)   Value of time: $20.00/hour   Currency: USD

| Option | Cash / month | Cash / year | Per trip | Door to door (one way) | Hours / month | Time cost / month | Total / month | CO2 kg / year |
|---|---|---|---|---|---|---|---|---|
| Park and ride | $95.22 | $1,143 | $2.48 | 40 min | 25.6 | $266 | **$361** | 999 |
| Bus + light rail | $49.00 | $588 | $1.28 | 46 min | 29.4 | $411 | **$460** | 651 |
| E-bike 3 days, transit 2 days | $66.48 | $798 | $1.73 | 44 min | 27.9 | $487 | **$553** | 261 |
| E-bike | $66.91 | $803 | $1.75 | 42 min | 26.8 | $537 | **$604** | 0 |
| Drive downtown | $357 | $4,285 | $9.32 | 28 min | 17.9 | $358 | **$715** | 1,607 |

Sorted by total (cash + time cost).

## Headline

- Cheapest in cash: **Bus + light rail** ($49.00/month).
- Cheapest once time counts: **Park and ride** ($361/month at $20.00/hour).
- Fastest: **Drive downtown** (28 min one way, 17.9 h/month).

## Break-even value of time (vs Bus + light rail, the cheapest in cash)

| Option | Extra cash / year | Lost hours saved / year | Worth it if your hour is worth more than |
|---|---|---|---|
| Drive downtown | $3,697 | 32 | $115/hour |
| E-bike | $215 | none (75 more lost) | never on cost: it does not save usable time |
| E-bike 3 days, transit 2 days | $210 | none (45 more lost) | never on cost: it does not save usable time |
| Park and ride | $555 | 87 | $6.35/hour |

## Notes per option

- **Drive downtown** (car): per month: fuel/energy $51.20, maintenance + depreciation $75.90, parking + tolls $230; fixed costs (insurance, registration) not counted: you keep the car anyway
- **Bus + light rail** (transit): per month: fares $49.00; monthly pass (cheaper than $105/month pay per ride at 19.2 days/month); employer subsidy $50.00/month deducted
- **E-bike** (ebike): per month: bike + upkeep $65.83, fuel/energy $1.08; ownership costs counted in full (they do not shrink on days you do not ride)
- **E-bike 3 days, transit 2 days** (mix): E-bike 60 % of days (11.5/month): ownership costs counted in full (they do not shrink on days you do not ride); Bus + light rail 40 % of days (7.7/month): pay per ride (pass would cost $99.00/month at 7.7 days/month)
- **Park and ride** (multi): leg 2 (transit): monthly pass (cheaper than $105/month pay per ride at 19.2 days/month); leg 2 (transit): employer subsidy $50.00/month deducted

Time cost = hours x value of time x (1 - share of the trip you can use for reading or work). Not included: health benefits, accident risk, weather days and the option value of having a car; see references/time-value-and-assumptions.md.
FILE:scripts/commute_cost.py
#!/usr/bin/env python3
"""Commute cost comparison calculator (Python 3.8+ standard library only).

Compares commute options - car (fuel or electric), transit, bike, e-bike, walking,
day-share mixes ("bike 3 days, train 2 days") and same-day multi-leg trips ("drive to
the station, then train") - per month and per year: cash cost, time spent, time cost at
your own hourly value, total, cost per trip and CO2. For transit it picks the cheaper of
pay-per-ride (with a daily cap) and a monthly pass for the days you actually ride; for
cars it separates running costs from fixed costs you would keep paying anyway. It also
prints break-even values of time: how much an hour must be worth to you before a faster,
dearer option pays off.

Usage:
  python3 commute_cost.py scenario.json [--value-of-time 25] [--days-per-week 3] [--json]
  python3 commute_cost.py --self-test
scenario.json: {"currency": "USD", "units": "imperial"|"metric", "one_way_distance": 11,
  "days_per_week": 5, "weeks_per_year": 46, "value_of_time_per_hour": 20,
  "options": [{"name": "...", "mode": "car|transit|bike|ebike|walk|mix|multi", ...}]}
See references/cost-components.md for every option field.
Exit codes: 0 = comparison printed, 2 = bad input.
"""
import argparse, json, sys

PETROL_CO2 = {"metric": 2.35, "imperial": 8.89}   # kg CO2 per litre / per US gallon burned (diesel: 2.68 / 10.18)
DIESEL_CO2 = {"metric": 2.68, "imperial": 10.18}
KM_PER_UNIT = {"metric": 1.0, "imperial": 1.609344}
LABELS = {"energy": "fuel/energy", "running": "maintenance + depreciation", "parking_tolls": "parking + tolls",
          "fixed": "fixed costs", "fares": "fares", "ownership": "bike + upkeep", "other": "other"}
MODES = {"car", "transit", "bike", "ebike", "walk", "mix", "multi"}
SYMBOLS = {"USD": "$", "EUR": "€", "GBP": "£", "TRY": "₺", "CAD": "C$", "AUD": "A$", "JPY": "¥", "INR": "₹"}


class InputError(Exception):
    pass


def num(o, key, default=None, lo=0.0, hi=None, who=""):
    v = o.get(key, default)
    if v is None:
        raise InputError(f"{who}: '{key}' is required")
    if isinstance(v, bool) or not isinstance(v, (int, float)):
        raise InputError(f"{who}: '{key}' must be a number")
    if v < lo or (hi is not None and v > hi):
        raise InputError(f"{who}: '{key}' = {v} is out of range" + (f" ({lo}..{hi})" if hi is not None else f" (>= {lo})"))
    return float(v)


def car_cost(o, sc, days, who):
    """Annual cost dict for a car over `days` commute days."""
    units = sc["units"]
    d = num(o, "distance_one_way", sc["distance"], who=who) * 2 * days      # user units per year
    if "kwh_per_100" in o:
        kwh = d / 100 * num(o, "kwh_per_100", who=who)
        energy = kwh * num(o, "electricity_price", who=who)
        co2 = kwh * num(o, "grid_kg_co2_per_kwh", 0.4, who=who)
    else:
        if units == "imperial":
            vol = d / num(o, "fuel_economy_mpg", lo=1, who=who)
        else:
            vol = d / 100 * num(o, "fuel_l_per_100km", lo=0.5, who=who)
        energy = vol * num(o, "fuel_price", who=who)
        co2 = vol * (DIESEL_CO2 if o.get("fuel") == "diesel" else PETROL_CO2)[units]
    running = d * (num(o, "maintenance_per_distance", 0, who=who) + num(o, "depreciation_per_distance", 0, who=who))
    daily = days * (num(o, "parking_per_day", 0, who=who) + num(o, "tolls_per_day", 0, who=who))
    fixed = num(o, "fixed_per_year", 0, who=who) if o.get("count_fixed", False) else 0.0
    return {"energy": energy, "running": running, "parking_tolls": daily, "fixed": fixed,
            "co2": co2, "notes": ([] if o.get("count_fixed", False) or not o.get("fixed_per_year") else
                                  ["fixed costs (insurance, registration) not counted: you keep the car anyway"])}


def transit_cost(o, sc, days, who):
    rides = num(o, "rides_per_day", 2, lo=1, who=who)
    fare = num(o, "fare_per_ride", who=who)
    cap = o.get("daily_cap")
    per_day = fare * rides if cap is None else min(fare * rides, num(o, "daily_cap", who=who))
    payg_year = per_day * days
    best, note = payg_year, "pay per ride"
    if o.get("monthly_pass") is not None:
        pass_year = num(o, "monthly_pass", who=who) * 12
        months_days = days / 12
        if pass_year < payg_year:
            best, note = pass_year, f"monthly pass (cheaper than {fmt_plain(payg_year / 12, sc['sym'])}/month pay per ride at {months_days:.1f} days/month)"
        else:
            note = f"pay per ride (pass would cost {fmt_plain(pass_year / 12, sc['sym'])}/month at {months_days:.1f} days/month)"
    subsidy = num(o, "subsidy_per_month", 0, who=who) * 12
    best = max(0.0, best - subsidy)
    km = num(o, "distance_one_way", sc["distance"], who=who) * 2 * days * KM_PER_UNIT[sc["units"]]
    co2 = km * num(o, "co2_g_per_passenger_km", 80, who=who) / 1000
    return {"fares": best, "co2": co2, "notes": [note] + ([f"employer subsidy {fmt_plain(subsidy / 12, sc['sym'])}/month deducted"] if subsidy else [])}


def bike_cost(o, sc, days, who, mode):
    d = num(o, "distance_one_way", sc["distance"], who=who) * 2 * days
    own = 0.0
    if mode != "walk":
        life = num(o, "life_years", 5, lo=0.5, who=who)
        own = num(o, "purchase_price", 0, who=who) / life
    own += num(o, "maintenance_per_year", 0, who=who) + num(o, "gear_per_year", 0, who=who)
    energy = 0.0
    if mode == "ebike":
        kwh = d / 100 * num(o, "kwh_per_100", 1.2, who=who)
        energy = kwh * num(o, "electricity_price", 0, who=who)
    extra = num(o, "other_per_month", 0, who=who) * 12
    return {"ownership": own, "energy": energy, "other": extra, "co2": 0.0,
            "notes": ["ownership costs counted in full (they do not shrink on days you do not ride)"] if own else []}


def option_cost(o, sc, days, who):
    mode = o.get("mode")
    if mode == "car":
        c = car_cost(o, sc, days, who)
    elif mode == "transit":
        c = transit_cost(o, sc, days, who)
    elif mode in ("bike", "ebike", "walk"):
        c = bike_cost(o, sc, days, who, mode)
    else:
        raise InputError(f"{who}: mode '{mode}' is not allowed here (use car, transit, bike, ebike, walk)")
    minutes = num(o, "minutes_one_way", who=who, lo=1)
    cash = sum(v for k, v in c.items() if k not in ("co2", "notes"))
    return {"cash": cash, "minutes": minutes, "co2": c["co2"], "notes": c["notes"],
            "usable": num(o, "usable_time_share", 0, hi=1, who=who),
            "breakdown": {k: v for k, v in c.items() if k not in ("co2", "notes")}}


def evaluate(sc_raw, value_override=None, dpw_override=None):
    if not isinstance(sc_raw, dict) or not isinstance(sc_raw.get("options"), list) or not sc_raw["options"]:
        raise InputError("scenario needs an 'options' list")
    units = sc_raw.get("units", "metric")
    if units not in KM_PER_UNIT:
        raise InputError("units must be 'metric' or 'imperial'")
    cur = sc_raw.get("currency", "USD")
    sc = {"units": units, "distance": num(sc_raw, "one_way_distance", who="scenario", lo=0.1),
          "sym": SYMBOLS.get(cur, f"{cur} ")}
    dpw = dpw_override if dpw_override is not None else num(sc_raw, "days_per_week", 5, lo=0.5, hi=7, who="scenario")
    wpy = num(sc_raw, "weeks_per_year", 46, lo=1, hi=52, who="scenario")
    days = dpw * wpy
    vot = value_override if value_override is not None else num(sc_raw, "value_of_time_per_hour", 0, who="scenario")
    by_name = {}
    for i, o in enumerate(sc_raw["options"]):
        if not isinstance(o, dict) or not o.get("name") or o.get("mode") not in MODES:
            raise InputError(f"option {i + 1}: needs a 'name' and a 'mode' ({', '.join(sorted(MODES))})")
        if o["name"] in by_name:
            raise InputError(f"option name '{o['name']}' is used twice")
        by_name[o["name"]] = o
    results = []
    for o in sc_raw["options"]:
        who = o["name"]
        if o["mode"] == "mix":
            shares = o.get("shares")
            if not isinstance(shares, dict) or not shares:
                raise InputError(f"{who}: mix needs 'shares', e.g. {{\"Bike\": 0.6, \"Transit\": 0.4}}")
            tot = sum(shares.values())
            if abs(tot - 1) > 0.001:
                raise InputError(f"{who}: shares add up to {tot:g}, not 1")
            cash = co2 = hours = eff = 0.0
            notes, parts = [], []
            for nm, sh in shares.items():
                if nm not in by_name or by_name[nm]["mode"] in ("mix",):
                    raise InputError(f"{who}: share '{nm}' must name another non-mix option")
                sub = by_name[nm]
                part = multi_cost(sub, sc, days * sh, nm) if sub["mode"] == "multi" else option_cost(sub, sc, days * sh, nm)
                cash += part["cash"]; co2 += part["co2"]
                h = part["minutes"] * 2 * days * sh / 60
                hours += h; eff += h * (1 - part["usable"])
                parts.append(f"{nm} {sh * 100:.0f} % of days ({days * sh / 12:.1f}/month): {part['notes'][0] if part['notes'] else 'as above'}")
            minutes = hours * 60 / (2 * days)
            results.append(row(who, "mix", cash, minutes, hours, eff, vot, co2, days, parts))
            continue
        part = multi_cost(o, sc, days, who) if o["mode"] == "multi" else option_cost(o, sc, days, who)
        hours = part["minutes"] * 2 * days / 60
        results.append(row(who, o["mode"], part["cash"], part["minutes"], hours, hours * (1 - part["usable"]), vot,
                           part["co2"], days, part["notes"], part.get("breakdown")))
    return {"currency": sc_raw.get("currency", "USD"), "units": units, "one_way_distance": sc["distance"],
            "days_per_year": days, "days_per_month": days / 12, "value_of_time_per_hour": vot,
            "options": results, "break_even": break_even(results)}


def multi_cost(o, sc, days, who):
    legs = o.get("legs")
    if not isinstance(legs, list) or len(legs) < 2:
        raise InputError(f"{who}: multi needs at least two 'legs'")
    cash = co2 = minutes = 0.0
    notes, usable_min = [], 0.0
    for j, leg in enumerate(legs, 1):
        if leg.get("mode") in ("mix", "multi"):
            raise InputError(f"{who} leg {j}: legs cannot be mix or multi")
        if "distance_one_way" not in leg:
            raise InputError(f"{who} leg {j}: each leg needs its own 'distance_one_way'")
        p = option_cost(leg, sc, days, f"{who} leg {j}")
        cash += p["cash"]; co2 += p["co2"]; minutes += p["minutes"]
        usable_min += p["minutes"] * p["usable"]
        notes += [f"leg {j} ({leg['mode']}): {n}" for n in p["notes"]]
    minutes += num(o, "transfer_minutes", 0, who=who)
    return {"cash": cash, "co2": co2, "minutes": minutes, "notes": notes or ["legs summed"],
            "usable": usable_min / minutes if minutes else 0.0}


def row(name, mode, cash, minutes, hours, eff_hours, vot, co2, days, notes, breakdown=None):
    tcost = eff_hours * vot
    return {"name": name, "mode": mode, "cash_year": cash, "cash_month": cash / 12, "minutes_one_way": minutes,
            "hours_month": hours / 12, "lost_hours_month": eff_hours / 12, "time_cost_month": tcost / 12, "total_month": (cash + tcost) / 12,
            "total_year": cash + tcost, "cost_per_trip": cash / (2 * days), "co2_kg_year": co2,
            "notes": notes, "breakdown": breakdown or {}}


def break_even(results):
    """For each option, the hourly value of time at which it ties with the cheapest-cash option.
    Uses lost hours (time you cannot use for reading or work), the same basis as the time cost."""
    base = min(results, key=lambda r: r["cash_year"])
    out = []
    for r in results:
        if r is base:
            continue
        extra = r["cash_year"] - base["cash_year"]
        hours_saved = (base["lost_hours_month"] - r["lost_hours_month"]) * 12
        if hours_saved > 0.01:
            out.append({"option": r["name"], "vs": base["name"], "extra_cash_year": extra,
                        "hours_saved_year": hours_saved, "break_even_per_hour": extra / hours_saved})
        else:
            out.append({"option": r["name"], "vs": base["name"], "extra_cash_year": extra,
                        "hours_saved_year": hours_saved, "break_even_per_hour": None})
    return out


def fmt_plain(v, sym="$"):
    return f"{sym}{v:,.0f}" if abs(v) >= 100 else f"{sym}{v:,.2f}"


def render(res):
    sym = SYMBOLS.get(res["currency"], res["currency"] + " ")
    f = lambda v: fmt_plain(v, sym)
    du = "mi" if res["units"] == "imperial" else "km"
    out = [f"# Commute cost comparison", "",
           f"One way: {res['one_way_distance']:g} {du}   Commute days: {res['days_per_month']:.1f}/month ({res['days_per_year']:.0f}/year)   "
           f"Value of time: {f(res['value_of_time_per_hour'])}/hour   Currency: {res['currency']}", "",
           "| Option | Cash / month | Cash / year | Per trip | Door to door (one way) | Hours / month | Time cost / month | Total / month | CO2 kg / year |",
           "|---|---|---|---|---|---|---|---|---|"]
    rs = res["options"]
    for r in sorted(rs, key=lambda r: r["total_month"]):
        out.append(f"| {r['name']} | {f(r['cash_month'])} | {f(r['cash_year'])} | {f(r['cost_per_trip'])} | {r['minutes_one_way']:.0f} min | "
                   f"{r['hours_month']:.1f} | {f(r['time_cost_month'])} | **{f(r['total_month'])}** | {r['co2_kg_year']:,.0f} |")
    cheapest = min(rs, key=lambda r: r["cash_year"])
    best_total = min(rs, key=lambda r: r["total_year"])
    fastest = min(rs, key=lambda r: r["minutes_one_way"])
    out += ["", "Sorted by total (cash + time cost).", "",
            "## Headline", "",
            f"- Cheapest in cash: **{cheapest['name']}** ({f(cheapest['cash_month'])}/month).",
            f"- Cheapest once time counts: **{best_total['name']}** ({f(best_total['total_month'])}/month at {f(res['value_of_time_per_hour'])}/hour).",
            f"- Fastest: **{fastest['name']}** ({fastest['minutes_one_way']:.0f} min one way, {fastest['hours_month']:.1f} h/month)."]
    out += ["", f"## Break-even value of time (vs {cheapest['name']}, the cheapest in cash)", "",
            "| Option | Extra cash / year | Lost hours saved / year | Worth it if your hour is worth more than |", "|---|---|---|---|"]
    for b in res["break_even"]:
        if b["break_even_per_hour"] is None:
            verdict = "never on cost: it does not save usable time" if b["extra_cash_year"] > 0 else "always: same cash, no more lost time"
            hs = f"{b['hours_saved_year']:.0f}" if b["hours_saved_year"] >= 0 else f"none ({-b['hours_saved_year']:.0f} more lost)"
            out.append(f"| {b['option']} | {f(b['extra_cash_year'])} | {hs} | {verdict} |")
        else:
            out.append(f"| {b['option']} | {f(b['extra_cash_year'])} | {b['hours_saved_year']:.0f} | {f(b['break_even_per_hour'])}/hour |")
    out += ["", "## Notes per option", ""]
    for r in rs:
        bd = ", ".join(f"{LABELS.get(k, k)} {f(v / 12)}" for k, v in r["breakdown"].items() if v) if r["breakdown"] else ""
        out.append(f"- **{r['name']}** ({r['mode']}): " + "; ".join(([f"per month: {bd}"] if bd else []) + r["notes"]))
    out += ["", "Time cost = hours x value of time x (1 - share of the trip you can use for reading or work). "
            "Not included: health benefits, accident risk, weather days and the option value of having a car; "
            "see references/time-value-and-assumptions.md."]
    return "\n".join(out) + "\n"


def self_test():
    base = {"currency": "USD", "units": "metric", "one_way_distance": 10, "days_per_week": 5, "weeks_per_year": 48,
            "value_of_time_per_hour": 20}
    car = {"name": "Car", "mode": "car", "minutes_one_way": 20, "fuel_l_per_100km": 8, "fuel_price": 1.5,
           "maintenance_per_distance": 0.05, "parking_per_day": 5}
    tr = {"name": "Transit", "mode": "transit", "minutes_one_way": 40, "fare_per_ride": 2.5, "monthly_pass": 80}
    bike = {"name": "Bike", "mode": "bike", "minutes_one_way": 35, "purchase_price": 1000, "life_years": 5, "maintenance_per_year": 100}
    def ev(*opts, **kw):
        sc = dict(base, options=list(opts)); sc.update(kw.pop("sc", {}))
        return evaluate(sc, **kw)
    def get(res, n):
        return next(r for r in res["options"] if r["name"] == n)
    cases = []
    def case(name, fn):
        try:
            ok, err = bool(fn()), ""
        except Exception as e:  # noqa
            ok, err = False, repr(e)
        cases.append((name, ok, err))
    # car: 240 days * 20 km = 4800 km; fuel 384 L * 1.5 = 576; maint 240; parking 1200 -> 2016/year
    case("car annual cash (fuel + maintenance + parking)", lambda: abs(get(ev(car), "Car")["cash_year"] - 2016) < 0.01)
    case("car CO2 petrol 2.35 kg/L", lambda: abs(get(ev(car), "Car")["co2_kg_year"] - 384 * 2.35) < 0.01)
    case("diesel CO2 factor", lambda: abs(get(ev(dict(car, fuel="diesel")), "Car")["co2_kg_year"] - 384 * 2.68) < 0.01)
    case("fixed costs excluded unless count_fixed", lambda: get(ev(dict(car, fixed_per_year=1500)), "Car")["cash_year"] == get(ev(car), "Car")["cash_year"])
    case("fixed costs included with count_fixed", lambda: abs(get(ev(dict(car, fixed_per_year=1500, count_fixed=True)), "Car")["cash_year"] - 3516) < 0.01)
    case("EV uses kWh and electricity price", lambda: abs(get(ev(dict(car, kwh_per_100=18, electricity_price=0.3, fuel_l_per_100km=None)), "Car")["breakdown"]["energy"] - 4800 / 100 * 18 * 0.3) < 0.01)
    case("imperial mpg and $/gal", lambda: abs(get(ev({"name": "Car", "mode": "car", "minutes_one_way": 20, "fuel_economy_mpg": 30, "fuel_price": 3.6}, sc={"units": "imperial"}), "Car")["cash_year"] - 4800 / 30 * 3.6) < 0.01)
    case("imperial CO2 8.89 kg/gal", lambda: abs(get(ev({"name": "Car", "mode": "car", "minutes_one_way": 20, "fuel_economy_mpg": 30, "fuel_price": 3.6}, sc={"units": "imperial"}), "Car")["co2_kg_year"] - 160 * 8.89) < 0.01)
    # transit: per ride 5/day*240 = 1200 vs pass 960 -> pass
    case("transit picks monthly pass when cheaper", lambda: abs(get(ev(tr), "Transit")["cash_year"] - 960) < 0.01)
    case("transit picks pay-per-ride at 2 days/week", lambda: abs(get(ev(tr, dpw_override=2), "Transit")["cash_year"] - 5 * 96) < 0.01)
    case("daily cap applied", lambda: abs(get(ev(dict(tr, monthly_pass=None, daily_cap=4)), "Transit")["cash_year"] - 4 * 240) < 0.01)
    case("employer subsidy deducted, never below 0", lambda: get(ev(dict(tr, subsidy_per_month=100)), "Transit")["cash_year"] == 0)
    case("bike ownership spread over life", lambda: abs(get(ev(bike), "Bike")["cash_year"] - 300) < 0.01)
    case("ebike electricity", lambda: abs(get(ev(dict(bike, name="E", mode="ebike", kwh_per_100=1.5, electricity_price=0.3)), "E")["breakdown"]["energy"] - 4800 / 100 * 1.5 * 0.3) < 0.01)
    case("walk has no purchase cost", lambda: get(ev({"name": "Walk", "mode": "walk", "minutes_one_way": 120, "purchase_price": 999}), "Walk")["cash_year"] == 0)
    case("time cost = hours x value", lambda: abs(get(ev(car), "Car")["time_cost_month"] - 20 * 2 * 240 / 60 * 20 / 12) < 0.01)
    case("usable time share discounts transit time", lambda: abs(get(ev(dict(tr, usable_time_share=0.5)), "Transit")["time_cost_month"] - 40 * 2 * 240 / 60 * 20 * 0.5 / 12) < 0.01)
    case("value-of-time override", lambda: get(ev(car, value_override=0), "Car")["time_cost_month"] == 0)
    case("per trip = annual cash / trips", lambda: abs(get(ev(car), "Car")["cost_per_trip"] - 2016 / 480) < 0.001)
    # mix: bike 60 % of days, transit 40 % -> transit 96 days: per ride 480 vs pass 960 -> per ride
    mixo = {"name": "Mix", "mode": "mix", "shares": {"Bike": 0.6, "Transit": 0.4}}
    case("mix: bike ownership full + transit pay-per-ride on its days", lambda: abs(get(ev(bike, tr, mixo), "Mix")["cash_year"] - (300 + 480)) < 0.01)
    case("mix: time weighted by days", lambda: abs(get(ev(bike, tr, mixo), "Mix")["minutes_one_way"] - (0.6 * 35 + 0.4 * 40)) < 0.01)
    multi = {"name": "P+R", "mode": "multi", "transfer_minutes": 5, "legs": [
        {"mode": "car", "distance_one_way": 3, "minutes_one_way": 8, "fuel_l_per_100km": 8, "fuel_price": 1.5, "parking_per_day": 2},
        {"mode": "transit", "distance_one_way": 7, "minutes_one_way": 20, "fare_per_ride": 2.5, "monthly_pass": 80}]}
    case("multi: legs summed + transfer", lambda: (lambda r: abs(r["minutes_one_way"] - 33) < 0.01 and abs(r["cash_year"] - (1440 * 0.08 * 1.5 + 480 + 960)) < 0.01)(get(ev(multi), "P+R")))
    case("break-even: car vs cheapest", lambda: (lambda res: (lambda b: abs(b["break_even_per_hour"] - (2016 - 300) / ((35 - 20) * 2 * 240 / 60)) < 0.01)(next(b for b in res["break_even"] if b["option"] == "Car")))(ev(car, bike)))
    case("break-even uses lost hours (usable transit time)", lambda: next(b for b in ev(dict(tr, usable_time_share=0.75, subsidy_per_month=60), bike)["break_even"] if b["option"] == "Bike")["break_even_per_hour"] is None)
    case("break-even: slower and dearer -> None", lambda: next(b for b in ev(car, tr, bike)["break_even"] if b["option"] == "Transit")["break_even_per_hour"] is None)
    case("render has headline and table", lambda: "Cheapest in cash: **Bike**" in render(ev(car, tr, bike)) and "| Car |" in render(ev(car, tr, bike)))
    case("render uses currency symbol", lambda: "€" in render(ev(car, sc={"currency": "EUR"})))
    def bad(*opts, **sc):
        try:
            ev(*opts, sc=sc); return False
        except InputError:
            return True
    case("mix shares must sum to 1", lambda: bad(bike, tr, dict(mixo, shares={"Bike": 0.6, "Transit": 0.6})))
    case("mix share must name an option", lambda: bad(bike, dict(mixo, shares={"Bike": 0.5, "Train": 0.5})))
    case("unknown mode rejected", lambda: bad({"name": "Boat", "mode": "boat", "minutes_one_way": 5}))
    case("duplicate names rejected", lambda: bad(car, car))
    case("missing fuel economy rejected", lambda: bad({"name": "Car", "mode": "car", "minutes_one_way": 20, "fuel_price": 1.5}))
    case("negative price rejected", lambda: bad(dict(car, fuel_price=-1)))
    case("bad units rejected", lambda: bad(car, units="furlongs"))
    case("usable share above 1 rejected", lambda: bad(dict(tr, usable_time_share=1.5)))
    passed = 0
    for name, ok, err in cases:
        passed += ok
        print(("PASS " if ok else "FAIL ") + name + ("" if ok else f"  {err}"))
    print(f"{passed}/{len(cases)} passed")
    return 0 if passed == len(cases) else 1


def main(argv=None):
    ap = argparse.ArgumentParser(description="Compare commute options per month and year, including time value")
    ap.add_argument("scenario", nargs="?")
    ap.add_argument("--value-of-time", type=float, help="override value_of_time_per_hour")
    ap.add_argument("--days-per-week", type=float, help="override days_per_week (e.g. 3 for hybrid work)")
    ap.add_argument("--json", action="store_true")
    ap.add_argument("--self-test", action="store_true")
    a = ap.parse_args(argv)
    if a.self_test:
        return self_test()
    if not a.scenario:
        ap.error("give a scenario JSON file, or --self-test")
    try:
        with open(a.scenario, encoding="utf-8") as fh:
            sc = json.load(fh)
        if a.days_per_week is not None and not 0.5 <= a.days_per_week <= 7:
            raise InputError("--days-per-week must be 0.5..7")
        res = evaluate(sc, a.value_of_time, a.days_per_week)
    except json.JSONDecodeError as e:
        print(f"error: scenario is not valid JSON: {e}", file=sys.stderr)
        return 2
    except (OSError, InputError, UnicodeDecodeError) as e:
        print(f"error: {e}", file=sys.stderr)
        return 2
    print(json.dumps(res, indent=2) if a.json else render(res), end="" if not a.json else "\n")
    return 0


if __name__ == "__main__":
    sys.exit(main())
TravelPythonBudgeting+2
F@import-252f10c83610ebca1a059c0b
0
Lost or Delayed Airline Luggage Claim Plan (JSON)
Text

When your checked bag is delayed, lost, or damaged, get a strict JSON claim plan: immediate actions, the official report details to keep, a tracking and delivery plan, airline rules and deadlines to confirm officially, an interim essentials expenses log, a contents inventory with values and proof, a damaged bag section, a claim package checklist, a timeline, a polite claim letter, a follow-up message, and an escalation path. Organization help, not legal advice. 来源:https://prompts.chat/prompts/cmvw2k39i0004if08b62i7k6p

1{
2 "role": "Calm, organized traveler-side baggage claim assistant who helps people whose checked luggage is delayed, lost, or damaged on a flight report it correctly, track it, keep reasonable interim expenses documented, and file a complete, well-supported claim with the airline on time, without giving legal advice or inventing airline policies, compensation limits, or deadlines",
3 "task": "Turn my flight, what happened to my bag, what was inside, what I have spent so far, and what the airline has told me into a single strict JSON luggage claim plan: a situation summary, immediate actions at the airport or right after, the official report and reference details to keep, a tracking and follow-up plan, rules and deadlines I must confirm officially, an interim expenses plan, a contents inventory with values and proof, a damaged bag section if relevant, a claim package checklist, a timeline with dates, a polite claim letter, a follow-up message, an escalation path, and mistakes to avoid. Never invent airline rules, compensation amounts, deadlines, or facts I did not give.",
4 "context": {
5 "route_and_flights": "${flights:Lisbon to Chicago with a connection in London, two different airlines on one ticket}",
6 "travel_date": "${travel_date:yesterday}",
7 "where_i_am_now": "${location:at my hotel in Chicago, staying 6 nights for a work conference}",
8 "bag_status": "${bag_status:my checked suitcase did not arrive, the tracker says it is still in London}",
9 "report_filed": "${report:yes, I filed a report at the arrivals baggage desk and got a reference number on a paper slip}",
10 "bag_description": "${bag:large dark blue hard-shell suitcase with a red strap and a luggage tag with my name and phone number}",
...+177 more lines
TravelJSONChecklist+3
F@import-252f10c83610ebca1a059c0b
0
Covered Bridge Autumn Scene Concept Brief Builder
Text

Turn a short idea into an image-ready and motion-ready brief for one hero shot of a red wooden covered bridge over a calm, misty river in peak autumn foliage at sunrise: the bridge, the river and its reflection, low mist, autumn trees and sky, light and color, fixed details, a motion map, and two prompt seeds: a 16:9 still image and an image-to-video animation. 来源:https://prompts.chat/prompts/cmvw2sz6j0001l207c3qvigfq

Act as a cinematic landscape designer who writes image-ready and motion-ready scene briefs. Help me design one hero shot of a red wooden covered bridge over a calm, misty river in peak autumn foliage at sunrise. The shot will first be generated as a still image and then animated into a short video that uses that image as its first frame. Your brief must make the still image rich in elements that can move naturally (low mist drifting over the water, a few leaves falling and floating, soft ripples, light shimmering on the reflection, branches swaying slightly) while keeping the composition calm, balanced, readable, and easy to animate.

My starting idea: a classic red covered bridge over a still river at sunrise, with low mist on the water and blazing autumn trees on both banks

My starting choices:
- Bridge: a long red wooden covered bridge with a dark grey shingled roof, an open entrance with white trim on the left end, resting on stone abutments
- Position: spanning the river slightly right of center, seen from the water level a little downstream
- River: a calm, mirror-still river filling the lower half of the frame, reflecting the bridge and the trees
- Mist: a thin low layer of mist drifting over the water and under the bridge
- Trees: dense orange, red, and yellow maples and birches on both banks, brighter and sunlit on the left, deeper red on the right
- Leaves on the water: many small fallen leaves floating in the foreground
- Time and light: just after sunrise, soft golden light from the left and a clear pale blue sky with warm haze
- Visual style: photoreal landscape and travel photography, natural colors
- Mood words: quiet, crisp, warm, nostalgic, peaceful

First ask me, in one short message, for anything missing: the camera height (just above the water, bank level, or slightly raised), how much of the frame the bridge should take, how thick the mist should be, how many floating leaves I want, whether I want overhanging branches at the top edge to frame the shot, whether the video should include a few leaves falling onto the water and making ripples, and anything to avoid (people, cars, animals, boats, text, signs, logos, or copying a specific real bridge, photograph, or named landmark).

Then produce the brief with these sections:

1. **Scene Overview**: two or three sentences on the place, the moment, the light, and the feeling. Describe an imagined rural covered bridge in a classic countryside spirit, not a copy of a specific real bridge or a famous photograph.

2. **The Covered Bridge**: its length and position in the frame, the red board siding, the shingled roof, the open entrance and its trim, the stone abutments, and how the morning light falls on it.

3. **The River and Reflection**: the water surface, how still it is, how clearly it mirrors the bridge and trees, where it catches warm light, and the floating leaves in the foreground.

4. **Mist**: how thick it is, where it lies (on the water, under the bridge, along the far bank), which way it drifts, and how it should read as soft morning river mist rather than smoke or fog filling the whole frame.

5. **Autumn Trees and Sky**: the colors and density of the foliage on each bank, where the sunlight hits, the edge of the woods against the sky, and the pale blue sky with warm golden haze.

6. **Light and Color**: the direction and warmth of the sunrise light, the cool shadows, the balance of red, orange, and yellow against blue, and how soft the contrast is.

7. **Fixed Visual Details**: a numbered list of 8 to 10 details that must stay identical in the still image and in the video (bridge position and length, roof line, entrance on the left end, stone abutments, both tree lines, river edges, reflection, camera position, framing, overall mist zone).

8. **Motion Map**: a table of every element that can move in the video, with columns: element, type of motion, direction, speed (very slow, slow, medium), and how strongly it should move. Include the mist, a few leaves falling and landing on the water, the floating leaves, the ripples they make, the shimmer on the reflection, a slight sway of branches, and the camera move. Keep total motion subtle and physically plausible, with one gentle air direction.

9. **Prompt Seed A - Hero Still Image**: a ready-to-paste image prompt under 170 words for a wide landscape 16:9 frame, with the red covered bridge, the misty river, and the peak autumn trees at sunrise in the first sentence, ending with: no people, no text, no logos.

10. **Prompt Seed B - Image-to-Video Animation**: a ready-to-paste video prompt under 120 words that starts from the hero still as the first frame, describes a slow gentle push-in toward the bridge for about 6 seconds, mist drifting over the water and under the bridge, a few red and orange maple leaves fluttering down and landing on the water with soft spreading ripples, and the reflection shimmering, and says to keep the bridge, banks, trees, river, and framing exactly as in the image with no new objects.

Rules: no people, cars, boats, or animals; no text, signs, or logos; no fast camera moves or cuts; and no motion that breaks physics (the bridge, stone abutments, and banks never move, the water stays calm and flows gently in one direction, leaves fall slowly and float on the surface, ripples spread outward in circles and fade, mist drifts and does not pour or swirl violently, the light does not flicker or jump). Use short paragraphs and lists.
Image To VideoWorkflowTravel+2
F@import-252f10c83610ebca1a059c0b
0
Red Covered Bridge Over a Misty River in Peak Autumn Foliage
Image
Red Covered Bridge Over a Misty River in Peak Autumn Foliage

Photoreal autumn sunrise scene: a long red wooden covered bridge with a dark grey shingled roof, a white-trimmed entrance on the left end, and stone abutments spans a calm river slightly right of center, with low mist on the water, blazing orange, red, and yellow trees on both banks, a mirror-like reflection, fallen leaves floating in the foreground, and a pale blue sky with golden haze. Step 2 of the Red Covered Bridge in Autumn Mist workflow. 来源:https://prompts.chat/prompts/cmvw2u5ms0001l608ygkolzat

A red wooden covered bridge over a calm, misty river in peak autumn foliage at sunrise, seen from the water level a little downstream, in a wide landscape 16:9 frame. The long bridge, with red vertical board siding and a dark grey shingled roof, spans the river slightly right of center; its open entrance on the left end is framed in white trim, and it rests on grey stone abutments at both ends. A thin layer of low white mist drifts over the water surface and under the bridge. Dense autumn trees crowd both banks: on the left, bright orange, red, and yellow maples lit by the soft golden sun; on the right, deeper red and orange foliage. The still river fills the lower half of the frame and mirrors the bridge and the trees like glass, and many small fallen orange and red leaves float on the water in the foreground. The sky is a clear pale blue with a warm golden haze near the treetops, with soft sunrise light coming from the left. Photoreal landscape and travel photography, natural colors, quiet, crisp, and nostalgic mood. No people, no cars, no text, no logos.
WorkflowRealismTravel+2
F@import-252f10c83610ebca1a059c0b
0
Video
Red Covered Bridge in Autumn Mist (Image-to-Video Animation)

Animate the step 2 covered bridge image as the first frame into a calm 6-second shot: a slow push-in toward the red bridge with overhanging maple branches entering at the top edge, low mist drifting over the water, red and orange leaves fluttering down and landing on the river with spreading circular ripples, and the reflection shimmering in soft sunrise light. Step 3 of the Red Covered Bridge in Autumn Mist workflow. 来源:https://prompts.chat/prompts/cmvw2vdie0001l2085jbv1y81

Start from the step 2 image "Red Covered Bridge Over a Misty River in Peak Autumn Foliage" as the exact first frame, and animate it into a calm 6-second cinematic shot. Keep the red covered bridge with its dark grey shingled roof, the white-trimmed entrance on the left end, the stone abutments, the orange, red, and yellow trees on both banks, the mirror-still river with its reflection, the pale blue sky with golden haze, and the composition exactly as in the image. The camera makes a slow, steady push-in toward the bridge, so the bridge grows larger and moves toward the center of the frame, while a few overhanging orange and red maple branches from the near bank come into view along the top edge as natural foreground framing. Low mist keeps drifting slowly over the water and under the bridge. Several red and orange maple leaves flutter down in front of the bridge and land softly on the water, each making circular ripples that spread outward across the lower foreground and fade, while the reflection of the bridge shimmers gently in the ripples. The shot ends calm in soft golden sunrise light. Natural, realistic motion, no cuts, no people, no animals, no boats, no text. Soft sound of the river, a light breeze in the leaves, and quiet drips as the leaves touch the water.
Video GenerationImage To VideoWorkflow+2
F@import-252f10c83610ebca1a059c0b
0
Previous3 / 5Next