把共同开销拆成每人应付与结清路径。
---
name: shared-expense-bill-splitter-and-settle-up-planner
description: 把共同开销拆成每人应付与结清路径。
---
# 分账与结清规划器
你是「分账与结清规划器」技能助手。上方 description 为中文任务说明。下方保留原技能完整正文(含脚本与代码);执行时遵循中文说明与原文技术细节。
# Shared Expense Bill Splitter and Settle-Up Planner
You turn a messy list of shared spending into a fair, checkable split and the shortest possible list of payments. You keep the ledger as a CSV the group can edit in any spreadsheet, apply the split rule each line really needs (who was there, who ordered what, who stayed fewer nights), convert currencies at rates the group agrees on, and settle everyone with the fewest transfers. Every cent is accounted for, and anyone can trace their own number line by line.
## Files in this skill
- `scripts/settle_up.py` - reads the CSV ledger, splits each line in integer cents (largest-remainder rounding), computes paid/share/net per person, and searches all zero-sum subgroups to find the minimum number of transfers (exact up to 18 people with a balance, greedy beyond) (Python 3.8+ standard library only)
- `references/split-methods.md` - the CSV format, which split to use for which cost, itemized bills with tax and tip, exclusions, payers, refunds and repayments
- `references/settle-up-and-currency.md` - why the minimum can be below "people - 1", how the search works, rounding, exchange rates and card fees, payment etiquette
- `templates/settle-up-summary.md` - the summary to hand back and paste into the group chat
- `examples/lisbon-trip.csv` - 5 friends, 11 lines: shares by nights, an excluded person, an itemized dinner, a USD booking, premium seats, two payers, a refund, GBP snacks and a repayment already made
- `examples/lisbon-settle-output.md` - the real output of the planner on that ledger
- `examples/flat-october.csv` - 6 flatmates where the minimum (4 transfers) beats paying largest debt to largest credit (5)
## Workflow
### 1. Collect the ledger
Ask for every shared cost with: what, who paid (and how much each, if several people paid), the amount and currency, and who it was for. Ask the questions that change the split: Did anyone arrive late or leave early? Did anyone skip a meal or an activity? Was a dinner shared or ordered individually? Has anyone already paid someone back? Agree the base currency and the rates (one rate per currency for the whole trip unless the group wants card statement rates). Write it as the CSV in `references/split-methods.md`, with `# people:` so typos in names are caught.
### 2. Run the planner
```
python3 scripts/settle_up.py examples/lisbon-trip.csv
python3 scripts/settle_up.py flat.csv --base GBP --rates EUR=0.86 --detail Ben
python3 scripts/settle_up.py ledger.csv --json
python3 scripts/settle_up.py --self-test
```
Exit 0 = plan printed (read the Warnings section), 2 = the ledger has an error (sums that do not match, missing rate, unknown split or name) - fix the line it names. If you cannot run code, follow the same steps by hand: convert each line to base cents, split, sum paid minus share per person, then match debtors to creditors, looking first for people or small groups whose balances cancel exactly.
### 3. Check the result with the group
- The check line must read `nets add up to 0.00`; paid and shares must be equal.
- Read the balances aloud in plain words ("Ana paid 990.00, her share is 377.31 and Eli already gave her 100.00, so she gets back 512.69").
- Point out lines that drive the result and are easy to dispute (shares by nights, itemized meals, a refund, a repayment), and offer `--detail <name>` for anyone who wants their own breakdown.
- If someone prefers to pay someone else (or cannot pay a person directly), rerun after adding the agreed transfer as a `payment` line; the plan recomputes the rest.
### 4. Deliver
Fill `templates/settle-up-summary.md`: totals, the balances table, the numbered transfers, the assumptions (rates, who was excluded where, how tax/tip was spread), and the short group-chat message. Suggest marking each transfer as done by adding it to the ledger as a `payment` line, so a second run shows everyone at 0.00.
## Example result
On `examples/lisbon-trip.csv` (5 people, 1,583.07 EUR spent) Ana paid the apartment and the fado tickets and gets back 512.69 EUR; the plan is 4 transfers: Ben pays Ana 243.17, Dara pays Ana 140.94, Eli pays Ana 128.58 and Eli pays Cem 0.85 (Eli's earlier 100.00 repayment is already counted). On `examples/flat-october.csv` Bo and Finn cancel each other out, so 6 flatmates settle in 4 transfers where paying largest debt to largest credit would take 5.
## Rules
- Never invent amounts, rates or who took part; ask, or mark the line as an assumption in the summary.
- Use one agreed rate per currency and show it; do not mix live rates into a finished split.
- Keep all arithmetic in cents and show where rounding cents went (largest remainder, ties to the person listed first).
- Do not judge spending; flag only lines that look like duplicates, typos or missing participants.
- A repayment is a `payment` line, never a negative expense; a refund is a negative expense shared by the same people as the original cost.
- Present the plan as a proposal; the group can swap who pays whom as long as each person's net is unchanged.
FILE:references/split-methods.md
# Split methods and CSV format
## Columns
`date,description,paid_by,amount,currency,split,participants,details` - header row required; any spreadsheet can export it. Optional comment lines before the header:
```
# people: Ana, Ben, Cem, Dara, Eli (strict list: a misspelt name is an error)
# base: EUR
# rates: USD=0.92, GBP=1.16 (1 USD = 0.92 EUR)
```
Without `# people:` everyone named anywhere in the file is a member and `all` means all of them; names are matched case-insensitively.
## Choosing a split
| Cost | Split | Example `participants` / `details` |
|---|---|---|
| Groceries, taxi, fuel, shared tickets | `equal` | `all`, `Ana;Ben`, `all-Eli` |
| Accommodation when people stayed different nights, rooms of different size | `shares` | `Ana:3;Ben:3;Dara:2` (nights or room weights) |
| Tickets with different prices, a known per-person amount | `exact` | `Ana:30;Ben:45` (others in participants split the rest equally) |
| Agreed percentages (rent by income, wine for those who drank) | `percent` | `Ana:25;Ben:25;Dara:50` (must total 100) |
| Restaurant bill where people ordered separately | `itemized` | `Ana:31;Ben:28.50;shared:42` |
| Someone already paid someone back | `payment` | participants = the one recipient |
## Itemized bills
- `details` lists each person's items before tax, service and tip; `shared` is the sum of starters, bottles or anything everyone shared (split equally among `participants`).
- `amount` is the final bill. The difference (amount - items) is tax, service and tip, spread in proportion to what each person had, so a person who ordered more pays more tip. The output shows it as `+17.3% tax/tip`.
- If the items add up to more than the bill (a discount or a typo), the planner stops; enter the discount by lowering the item prices it applied to.
## Exclusions and partial participation
- `all-Eli` or `all except Eli` = everyone but Eli; chain several: `all-Bo-Finn`.
- For people present part of the time, use `shares` with nights or days instead of excluding them.
- A child or a guest paid for by one member: list them under the member's name (`shares` weight 1.5) or add them to `# people:` and settle with their parent.
## Payers
- One payer: `Ana`. Several payers on one bill: `Ben:40;Cem:20` (amounts in the row currency, must add up to `amount`).
- A card shared by a couple: treat the couple as one person or split the payer amount.
## Refunds, deposits, repayments
- Refund received after a cancellation: negative `amount`, `paid_by` = who received the money, same participants as the original cost.
- Deposit returned by a landlord: negative `amount` split the same way as the deposit.
- Money handed over between members: `payment` (from `paid_by` to the one person in `participants`). Record settle-up transfers the same way; rerunning then shows who is still open.
## Common mistakes the planner catches
- Exact amounts or percentages that do not add up, payer amounts that differ from the bill, items over the bill.
- A currency without a rate, an unknown split word, a misspelt name when `# people:` is set.
- Two identical lines (same date, description, amount and payer) - reported as a warning, not removed.
- Zero amounts - skipped with a warning.
FILE:references/settle-up-and-currency.md
# Settle-up and currency
## Net balance
For every person: `net = paid + payments sent - share - payments received`. Positive = gets money back, negative = owes. The nets always add up to exactly 0.00 because every line is split in integer cents that sum to the line total.
## Why "fewest transfers" can be less than people - 1
- Any group with k people who have a balance can settle in at most k - 1 transfers (each transfer clears at least one person).
- If the group splits into subgroups whose balances each add up to zero, each subgroup settles on its own: with g such subgroups the minimum is k - g. Example: Bo +300 and Finn -300 cancel, so 6 flatmates need 4 transfers, not 5.
- Paying the largest debt to the largest credit (the usual app approach) does not look for these subgroups and can take more transfers.
- Finding the best split into zero-sum subgroups is a hard problem in general; the planner solves it exactly for up to 18 people with a non-zero balance (dynamic programming over subsets, under a second) and falls back to the greedy plan above that, saying so.
- Within each subgroup the plan pays largest debt to largest credit, which uses exactly (subgroup size - 1) transfers.
- Several plans can have the same minimum count; any of them is fair, because each person's total in or out is fixed by their net.
## Rounding
- Each line is converted to base cents once (`amount x rate`, rounded half up), then split with the largest-remainder method: everyone gets the rounded-down amount, and the leftover cents go to the largest fractions, ties to the person listed first in `# people:`.
- Over a whole trip this moves at most a few cents per person; say so if someone asks why 10.00 / 3 is 3.34 for one person.
## Exchange rates
- Agree one rate per currency before splitting: the rate on the day most costs were paid, the average of the trip, or the rate on the payer's card statement (which includes the bank's markup).
- If the payer's card charged a foreign transaction fee, either include it in the amount (the group shares it) or leave it out (the payer absorbs it) - decide once for the whole trip.
- Enter amounts in the currency actually paid and let the planner convert; do not pre-convert some lines by hand.
- Settle in the base currency. If someone pays in another currency, convert the transfer at the same agreed rate and record it as a `payment` line in that currency.
## Payment etiquette
- Send the group-chat message with the transfers and a link to the ledger; give people a day or two to dispute a line before paying.
- Small transfers (under ~2 EUR/USD) can be waived or rolled into the next shared cost if both people agree - record that as a `payment` line so the ledger stays exact.
- When everyone has paid, add each transfer as a `payment` line and rerun: every net should be 0.00.
FILE:templates/settle-up-summary.md
# Settle-up: <trip / flat / event>, <dates>
**Group:** <Ana, Ben, Cem, Dara, Eli> **Base currency:** <EUR> **Total spent:** <1,583.07 EUR> over <11> lines
**Rates agreed:** <1 USD = 0.92 EUR, 1 GBP = 1.16 EUR (trip average)>
## Balances
| Person | Paid | Fair share | Already sent / received | Net |
|---|---|---|---|---|
| <Ana> | <990.00> | <377.31> | <received 100.00> | <+512.69 gets back> |
| <Ben> | <64.00> | <307.17> | <-> | <-243.17 owes> |
## Transfers (<n>, the minimum possible)
1. <Ben pays Ana 243.17 EUR>
2. <Dara pays Ana 140.94 EUR>
3. <...>
## How lines were split
- <Apartment: by nights, Dara and Eli 2 of 3 nights>
- <Airport taxi: everyone except Eli (came by train)>
- <Dinner: itemized, 17.3% tax and tip spread by what each person ordered; starters 42.00 shared>
- <Palace tickets refund: back to Ben and Cem, who paid for them>
- <Eli's 100.00 to Ana is already counted>
## Assumptions and open points
- <rates above; card fees not included>
- <check line 5 (surf lesson): was Ben in?>
## Group chat message
```
Settle-up (<EUR>, <11> lines, rates: <USD 0.92, GBP 1.16>):
- <Ben -> Ana: 243.17 EUR>
- <Dara -> Ana: 140.94 EUR>
Full table: <link to the sheet>. Shout within 2 days if a line is wrong.
```
**When paid:** add each transfer as a `payment` line and rerun - every net should read 0.00.
FILE:examples/lisbon-trip.csv
# people: Ana, Ben, Cem, Dara, Eli
# base: EUR
# rates: USD=0.92, GBP=1.16
date,description,paid_by,amount,currency,split,participants,details
2026-10-02,Apartment 3 nights (Dara and Eli 2 nights),Ana,840.00,EUR,shares,all,Ana:3;Ben:3;Cem:3;Dara:2;Eli:2
2026-10-02,Airport taxi (Eli came by train),Ben,48.00,EUR,equal,all-Eli,
2026-10-02,Groceries for the flat,Eli,63.75,EUR,equal,all,
2026-10-03,Dinner at Taberna do Mar,Cem,212.40,EUR,itemized,all,Ana:31;Ben:28.50;Cem:24;Dara:36;Eli:19.50;shared:42
2026-10-03,Surf lesson (booked on a US site),Dara,180.00,USD,equal,Ana;Dara;Eli,
2026-10-03,Fado tickets (premium seats for Dara and Eli),Ana,150.00,EUR,exact,all-Cem,Ana:30;Ben:30;Dara:45;Eli:45
2026-10-04,Train to Sintra,Ben:40;Cem:20,60.00,EUR,equal,all,
2026-10-04,Wine for the flat,Dara,36.00,EUR,percent,,Ana:25;Ben:25;Dara:50
2026-10-04,Palace tickets refunded (rain),Ben,-24.00,EUR,equal,Ben;Cem,
2026-10-05,Snacks at the London layover,Cem,27.00,GBP,equal,all,
2026-10-05,Eli paid Ana back for the apartment,Eli,100.00,EUR,payment,Ana,
FILE:examples/lisbon-settle-output.md
# Settle-up plan
Base currency: EUR People: 5 Lines: 11 Total spent: 1,583.07 EUR
Rates used: 1 GBP = 1.16 EUR, 1 USD = 0.92 EUR
## Expenses
| # | Date | What | Paid by | Amount | In EUR | Split | Among |
|---|---|---|---|---|---|---|---|
| 1 | 2026-10-02 | Apartment 3 nights (Dara and Eli 2 nights) | Ana | 840.00 EUR | 840.00 | shares | all |
| 2 | 2026-10-02 | Airport taxi (Eli came by train) | Ben | 48.00 EUR | 48.00 | equal | Ana, Ben, Cem, Dara |
| 3 | 2026-10-02 | Groceries for the flat | Eli | 63.75 EUR | 63.75 | equal | all |
| 4 | 2026-10-03 | Dinner at Taberna do Mar | Cem | 212.40 EUR | 212.40 | itemized (+17.3% tax/tip) | all |
| 5 | 2026-10-03 | Surf lesson (booked on a US site) | Dara | 180.00 USD | 165.60 | equal | Ana, Dara, Eli |
| 6 | 2026-10-03 | Fado tickets (premium seats for Dara and Eli) | Ana | 150.00 EUR | 150.00 | exact | Ana, Ben, Dara, Eli |
| 7 | 2026-10-04 | Train to Sintra | Ben 40.00, Cem 20.00 | 60.00 EUR | 60.00 | equal | all |
| 8 | 2026-10-04 | Wine for the flat | Dara | 36.00 EUR | 36.00 | percent | Ana, Ben, Dara |
| 9 | 2026-10-04 | Palace tickets refunded (rain) | Ben | -24.00 EUR | -24.00 | equal | Ben, Cem |
| 10 | 2026-10-05 | Snacks at the London layover | Cem | 27.00 GBP | 31.32 | equal | all |
| 11 | 2026-10-05 | Eli paid Ana back for the apartment | Eli | 100.00 EUR | 100.00 | payment | to Ana |
## Balances
| Person | Paid | Share | Sent | Received | Net |
|---|---|---|---|---|---|
| Ana | 990.00 | 377.31 | 0.00 | 100.00 | 512.69 (gets back) |
| Ben | 64.00 | 307.17 | 0.00 | 0.00 | -243.17 (owes) |
| Cem | 263.72 | 262.87 | 0.00 | 0.00 | 0.85 (gets back) |
| Dara | 201.60 | 342.54 | 0.00 | 0.00 | -140.94 (owes) |
| Eli | 63.75 | 293.18 | 100.00 | 0.00 | -129.43 (owes) |
Check: nets add up to 0.00 (paid 1,583.07 = shares 1,583.07).
## Transfers (4)
1. Ben pays Ana **243.17 EUR**
2. Dara pays Ana **140.94 EUR**
3. Eli pays Ana **128.58 EUR**
4. Eli pays Cem **0.85 EUR**
Minimum possible: 4 transfers for 5 people with a balance (no smaller subgroup evens out on its own).
## Message for the group chat
```
Settle-up (EUR, 11 lines, rates: GBP 1.16, USD 0.92):
- Ben -> Ana: 243.17 EUR
- Dara -> Ana: 140.94 EUR
- Eli -> Ana: 128.58 EUR
- Eli -> Cem: 0.85 EUR
Full table in the shared sheet. Shout within 2 days if a line is wrong.
```
FILE:examples/flat-october.csv
# people: Asha, Bo, Chen, Dev, Ema, Finn
# base: EUR
date,description,paid_by,amount,currency,split,participants,details
2026-10-01,Festival tickets for Bo and Finn,Bo,600,EUR,exact,Bo;Finn,Bo:300;Finn:300
2026-10-31,October groceries (Bo and Finn on tour),Asha,800,EUR,equal,all-Bo-Finn,
2026-10-31,Electricity Sep-Oct (Bo and Finn on tour),Chen,600,EUR,equal,all-Bo-Finn,
2026-10-20,Second-hand sofa (Dev and Ema's part),Asha,250,EUR,exact,Dev;Ema,Dev:150;Ema:100
FILE:scripts/settle_up.py
#!/usr/bin/env python3
"""Shared expense bill splitter and settle-up planner (Python 3.8+ standard library only).
Reads a CSV ledger of shared costs (a trip, a flat, an event), splits every line in
integer cents, and finds the SMALLEST possible number of transfers that settles the group
(exact search over zero-sum subgroups, not just "at most people - 1").
CSV columns (header row required, extra columns ignored):
date,description,paid_by,amount,currency,split,participants,details
paid_by Ana one payer
Ana:40;Ben:20 several payers (amounts in the row currency, must add up)
amount total in the row currency; negative = refund received by paid_by
currency blank = base currency
split equal | shares | exact | percent | itemized | payment
participants all | Ana;Ben;Cem | all-Eli (everyone except Eli) | blank = names in details
details shares: Ana:3;Ben:2 (people in participants but not listed get 1)
exact: Ana:30;Ben:45 (rest, if any, split equally among the other participants)
percent: Ana:50;Ben:30;Cem:20 (must total 100)
itemized: Ana:18;Ben:22.50;shared:12 (item prices before tax/tip; "shared"
items are split equally; amount - items = tax/service/tip, split in
proportion to what each person ordered)
payment: (none) paid_by gave `amount` to the one person in participants
Comment lines at the top set the group and the rates (or use the CLI flags):
# people: Ana, Ben, Cem
# base: EUR
# rates: USD=0.92, GBP=1.16 (1 unit of that currency = rate units of base)
Usage:
python3 settle_up.py ledger.csv [--base EUR] [--rates USD=0.92,GBP=1.16] [--people Ana,Ben]
[--detail Ana] [--json]
python3 settle_up.py --self-test
Exit codes: 0 = settled plan printed, 2 = bad input (unknown split, sums that do not
match, missing exchange rate, unknown person in a strict list).
"""
import argparse
import csv
import io
import json
import re
import sys
from decimal import Decimal, ROUND_HALF_UP, InvalidOperation
MAX_EXACT = 18 # people with a non-zero balance for the exact minimum search (2^18 states)
SPLITS = ("equal", "shares", "exact", "percent", "itemized", "payment")
class LedgerError(ValueError):
pass
def dec(s, what):
try:
return Decimal(str(s).replace(",", "").strip())
except (InvalidOperation, AttributeError):
raise LedgerError("%s: %r is not a number" % (what, s))
def to_cents(amount):
return int((amount * 100).quantize(Decimal("1"), rounding=ROUND_HALF_UP))
def fmt(cents, cur=""):
sign = "-" if cents < 0 else ""
c = abs(cents)
s = "%s%d.%02d" % (sign, c // 100, c % 100)
s = re.sub(r"(\d)(?=(\d{3})+\.)", r"\1,", s)
return (s + " " + cur).strip()
def allocate(total, weights, order):
"""Split integer `total` cents in proportion to `weights` (dict name -> Decimal >= 0).
Largest remainder method; ties go to the earlier name in `order`. Sum is exact."""
names = [n for n in order if n in weights]
wsum = sum(weights[n] for n in names)
if wsum <= 0:
raise LedgerError("weights add up to zero")
sign = -1 if total < 0 else 1
t = abs(total)
raw = {n: Decimal(t) * weights[n] / wsum for n in names}
base = {n: int(raw[n]) for n in names}
left = t - sum(base.values())
rank = sorted(names, key=lambda n: (-(raw[n] - base[n]), order.index(n)))
for n in rank[:left]:
base[n] += 1
return {n: sign * v for n, v in base.items() if v}
def parse_pairs(text, what):
out = {}
for part in [p for p in re.split(r"[;|]", text or "") if p.strip()]:
if ":" not in part:
raise LedgerError("%s: %r should look like Name:value" % (what, part.strip()))
k, v = part.split(":", 1)
k = k.strip()
out[k] = out.get(k, Decimal(0)) + dec(v, what)
return out
class Ledger:
def __init__(self, text, base=None, rates=None, people=None):
self.warnings = []
self.base = base
self.rates = {}
self.people = []
self._canon = {}
header_people = None
body = []
for line in text.splitlines():
s = line.strip()
if s.startswith("#"):
m = re.match(r"#\s*(people|base|rates?)\s*:\s*(.*)$", s, re.I)
if m:
key, val = m.group(1).lower(), m.group(2)
if key == "people":
header_people = [p.strip() for p in re.split(r"[,;]", val) if p.strip()]
elif key == "base" and not self.base:
self.base = val.strip().upper()
elif key.startswith("rate"):
self._add_rates(val)
continue
body.append(line)
self.base = (self.base or "EUR").upper()
if rates:
self._add_rates(rates)
self.rates[self.base] = Decimal(1)
for p in (people or header_people or []):
self._person(p, declare=True)
self.strict = bool(people or header_people)
rows = list(csv.DictReader(io.StringIO("\n".join(body))))
if not rows:
raise LedgerError("no expense rows found (need a header row and at least one line)")
need = {"description", "paid_by", "amount", "split"}
cols = {c.strip().lower() for c in rows[0].keys() if c}
if not need <= cols:
raise LedgerError("missing CSV columns: %s" % ", ".join(sorted(need - cols)))
self.rows = []
for r in rows:
r = {(k or "").strip().lower(): (v or "").strip() for k, v in r.items()}
if not any(r.values()):
continue
self.rows.append(r)
# first pass: learn every name when no people list was given
if not self.strict:
for r in self.rows:
for p in self._names_in(r):
self._person(p, declare=True)
self.lines = [self._line(n, r) for n, r in enumerate(self.rows, 1)]
self._check_duplicates()
# -- people and rates
def _add_rates(self, text):
for part in re.split(r"[,;]", text):
if not part.strip():
continue
if "=" not in part:
raise LedgerError("rate %r should look like USD=0.92" % part.strip())
k, v = part.split("=", 1)
r = dec(v, "rate " + k.strip())
if r <= 0:
raise LedgerError("rate for %s must be positive" % k.strip())
self.rates[k.strip().upper()] = r
def _person(self, name, declare=False):
key = name.strip().lower()
if not key:
raise LedgerError("empty person name")
if key in self._canon:
canon = self._canon[key]
if canon != name.strip() and declare:
self.warnings.append("'%s' and '%s' treated as the same person" % (canon, name.strip()))
return canon
if not declare:
raise LedgerError("unknown person %r (not in the people list)" % name.strip())
self._canon[key] = name.strip()
self.people.append(name.strip())
return name.strip()
def _names_in(self, r):
names = []
pb = r.get("paid_by", "")
names += list(parse_pairs(pb, "paid_by").keys()) if ":" in pb else [pb]
part = r.get("participants", "")
if part and not part.lower().startswith("all"):
names += [p for p in re.split(r"[;|]", part) if p.strip()]
if r.get("split", "").lower() != "payment":
names += [k for k in parse_pairs(r.get("details", ""), "details") if k.lower() != "shared"]
return [n for n in names if n.strip()]
def _participants(self, r, ln):
part = r.get("participants", "").strip()
if not part:
return None
if part.lower().startswith("all"):
rest = part[3:].strip()
excl = []
if rest:
rest = re.sub(r"^(except|but|without)\s+", "", rest.lstrip("-").strip(), flags=re.I)
excl = [self._person(x) for x in re.split(r"[-;|,]", rest) if x.strip()]
return [p for p in self.people if p not in excl]
return [self._person(p) for p in re.split(r"[;|]", part) if p.strip()]
# -- one CSV line -> paid / share in base cents
def _line(self, ln, r):
desc = r.get("description") or "line %d" % ln
where = "line %d (%s)" % (ln, desc)
split = (r.get("split") or "equal").lower()
if split not in SPLITS:
raise LedgerError("%s: unknown split %r (use %s)" % (where, split, ", ".join(SPLITS)))
cur = (r.get("currency") or self.base).upper()
if cur not in self.rates:
raise LedgerError("%s: no exchange rate for %s (add '# rates: %s=...' or --rates)" % (where, cur, cur))
amount = dec(r.get("amount"), where + " amount")
if amount == 0:
self.warnings.append("%s has amount 0 and was skipped" % where)
total = to_cents(amount * self.rates[cur])
# payers
pb = r.get("paid_by", "")
if ":" in pb:
pays = {self._person(k): v for k, v in parse_pairs(pb, where + " paid_by").items()}
if sum(pays.values()) != amount:
raise LedgerError("%s: payers add up to %s but amount is %s" % (where, sum(pays.values()), amount))
paid = allocate(total, {k: abs(v) for k, v in pays.items()}, self.people) if total else {}
if total < 0:
paid = {k: -abs(v) for k, v in paid.items()}
else:
paid = {self._person(pb): total} if total else {}
people = self._participants(r, ln)
details = parse_pairs(r.get("details", ""), where + " details") if split != "payment" else {}
share = {}
if split == "payment":
if not people or len(people) != 1:
raise LedgerError("%s: a payment needs exactly one recipient in participants" % where)
share = {people[0]: total}
elif split == "equal":
people = people or self.people
share = allocate(total, {p: Decimal(1) for p in people}, self.people)
elif split == "shares":
d = {self._person(k): v for k, v in details.items()}
people = people or list(d)
w = {p: d.get(p, Decimal(1)) for p in people}
extra = [p for p in d if p not in people]
if extra:
raise LedgerError("%s: %s in details but not in participants" % (where, ", ".join(extra)))
if any(v < 0 for v in w.values()):
raise LedgerError("%s: shares cannot be negative" % where)
share = allocate(total, w, self.people)
elif split == "percent":
d = {self._person(k): v for k, v in details.items()}
if sum(d.values()) != 100:
raise LedgerError("%s: percentages add up to %s, not 100" % (where, sum(d.values())))
people = list(d)
share = allocate(total, d, self.people)
elif split == "exact":
d = {self._person(k): v for k, v in details.items()}
people = people or list(d)
fixed = sum(d.values())
rest_people = [p for p in people if p not in d]
if fixed > abs(amount) or (fixed != abs(amount) and not rest_people):
raise LedgerError("%s: exact amounts add up to %s but the bill is %s" % (where, fixed, amount))
w = dict(d)
if rest_people:
each = (abs(amount) - fixed) / len(rest_people)
for p in rest_people:
w[p] = each
share = allocate(total, w, self.people)
elif split == "itemized":
people = people or self.people
shared = details.pop("shared", details.pop("Shared", Decimal(0)))
d = {self._person(k): v for k, v in details.items()}
items = sum(d.values()) + shared
if items > abs(amount):
raise LedgerError("%s: items add up to %s, more than the bill %s" % (where, items, amount))
per = {p: d.get(p, Decimal(0)) + (shared / len(people) if shared else 0) for p in people}
for p in d:
if p not in per:
per[p] = d[p]
if sum(per.values()) <= 0:
raise LedgerError("%s: no items to split" % where)
# tax/tip proportional to each person's items == allocate the total by item weights
share = allocate(total, per, self.people)
rec = {"n": ln, "date": r.get("date", ""), "desc": desc, "split": split, "currency": cur,
"amount": amount, "total": total, "paid": paid, "share": share,
"among": sorted(share, key=self.people.index)}
if split == "itemized":
rec["extra_pct"] = (abs(amount) - items) / items * 100 if items else Decimal(0)
if sum(paid.values()) != sum(share.values()):
raise LedgerError("%s: internal rounding error" % where) # never expected
return rec
def _check_duplicates(self):
seen = {}
for l in self.lines:
key = (l["date"], l["desc"].lower(), l["total"], tuple(sorted(l["paid"])))
if key in seen:
self.warnings.append("line %d looks like a duplicate of line %d (%s, %s)" % (l["n"], seen[key], l["desc"], fmt(l["total"], self.base)))
else:
seen[key] = l["n"]
def balances(self):
b = {p: {"paid": 0, "share": 0, "sent": 0, "received": 0} for p in self.people}
for l in self.lines:
if l["split"] == "payment":
for p, c in l["paid"].items():
b[p]["sent"] += c
for p, c in l["share"].items():
b[p]["received"] += c
else:
for p, c in l["paid"].items():
b[p]["paid"] += c
for p, c in l["share"].items():
b[p]["share"] += c
for p in b:
b[p]["net"] = b[p]["paid"] + b[p]["sent"] - b[p]["share"] - b[p]["received"]
return b
# ----------------------------------------------------------------------------- settle-up
def greedy(net, order):
"""Largest debtor pays largest creditor until everyone is even (at most k-1 transfers)."""
cred = {p: v for p, v in net.items() if v > 0}
debt = {p: -v for p, v in net.items() if v < 0}
out = []
while cred and debt:
c = max(cred, key=lambda p: (cred[p], -order.index(p)))
d = max(debt, key=lambda p: (debt[p], -order.index(p)))
x = min(cred[c], debt[d])
out.append((d, c, x))
cred[c] -= x
debt[d] -= x
if not cred[c]:
del cred[c]
if not debt[d]:
del debt[d]
return out
def minimal(net, order):
"""Fewest transfers: n - (max number of disjoint zero-sum groups). Returns (transfers, groups, exact)."""
people = [p for p in order if net.get(p)]
n = len(people)
if n == 0:
return [], [], True
if n > MAX_EXACT:
return greedy(net, order), [people], False
vals = [net[p] for p in people]
size = 1 << n
sums = [0] * size
for m in range(1, size):
low = m & -m
sums[m] = sums[m ^ low] + vals[low.bit_length() - 1]
dp = [0] * size
for m in range(1, size):
best = 0
mm = m
while mm:
low = mm & -mm
v = dp[m ^ low]
if v > best:
best = v
mm ^= low
dp[m] = best + (1 if sums[m] == 0 else 0)
# walk down, cutting a group at each zero-sum checkpoint
groups, m, last = [], size - 1, size - 1
while m:
mm, pick = m, None
target = dp[m] - (1 if sums[m] == 0 else 0)
while mm:
low = mm & -mm
if dp[m ^ low] == target:
pick = low
break
mm ^= low
m ^= pick
if sums[m] == 0:
groups.append(last ^ m)
last = m
out, named = [], []
for g in reversed(groups):
members = [people[i] for i in range(n) if g >> i & 1]
named.append(members)
out += greedy({p: net[p] for p in members}, order)
return out, named, True
# ----------------------------------------------------------------------------- output
def render(led, detail=None):
b = led.balances()
net = {p: b[p]["net"] for p in led.people}
tr, groups, exact = minimal(net, led.people)
gr = greedy(net, led.people)
B = led.base
o = ["# Settle-up plan", "",
"Base currency: %s People: %d Lines: %d Total spent: %s" % (
B, len(led.people), len(led.lines),
fmt(sum(l["total"] for l in led.lines if l["split"] != "payment"), B))]
others = sorted(c for c in led.rates if c != B)
if others:
o.append("Rates used: " + ", ".join("1 %s = %s %s" % (c, led.rates[c].normalize(), B) for c in others))
o += ["", "## Expenses", "", "| # | Date | What | Paid by | Amount | In %s | Split | Among |" % B, "|---|---|---|---|---|---|---|---|"]
for l in led.lines:
payer = ", ".join("%s %s" % (p, fmt(c)) if len(l["paid"]) > 1 else p for p, c in l["paid"].items())
among = "all" if len(l["among"]) == len(led.people) and l["split"] != "payment" else ", ".join(l["among"])
split = l["split"] + (" (+%.1f%% tax/tip)" % l["extra_pct"] if l["split"] == "itemized" else "")
if l["split"] == "payment":
among = "to " + among
o.append("| %d | %s | %s | %s | %s %s | %s | %s | %s |" % (l["n"], l["date"], l["desc"].replace("|", "/"), payer,
fmt(to_cents(l["amount"])), l["currency"], fmt(l["total"]), split, among))
o += ["", "## Balances", "", "| Person | Paid | Share | Sent | Received | Net |", "|---|---|---|---|---|---|"]
for p in led.people:
x = b[p]
state = "gets back" if x["net"] > 0 else ("owes" if x["net"] < 0 else "even")
o.append("| %s | %s | %s | %s | %s | %s (%s) |" % (p, fmt(x["paid"]), fmt(x["share"]), fmt(x["sent"]), fmt(x["received"]),
fmt(x["net"]), state))
o.append("")
o.append("Check: nets add up to %s (paid %s = shares %s)." % (fmt(sum(net.values())), fmt(sum(x["paid"] for x in b.values())),
fmt(sum(x["share"] for x in b.values()))))
nz = sum(1 for v in net.values() if v)
o += ["", "## Transfers (%d)" % len(tr), ""]
if not tr:
o.append("Everyone is even. Nothing to pay.")
else:
for i, (d, c, x) in enumerate(tr, 1):
o.append("%d. %s pays %s **%s**" % (i, d, c, fmt(x, B)))
o.append("")
if exact:
if len(groups) > 1:
o.append("Minimum possible: %d transfers. The group splits into %d sets that settle among themselves (%s), so %d people need only %d transfers; paying largest debt to largest credit would take %d." % (
len(tr), len(groups), "; ".join(" + ".join(g) for g in groups), nz, len(tr), len(gr)))
else:
o.append("Minimum possible: %d transfers for %d people with a balance (no smaller subgroup evens out on its own)." % (len(tr), nz))
else:
o.append("%d people have a balance; exact minimum search skipped (limit %d), greedy plan uses at most %d transfers." % (nz, MAX_EXACT, nz - 1))
if detail:
p = led._person(detail)
o += ["", "## Detail: %s" % p, "", "| # | What | Paid | Share | Running net |", "|---|---|---|---|---|"]
run = 0
for l in led.lines:
pd, sh = l["paid"].get(p, 0), l["share"].get(p, 0)
if not pd and not sh:
continue
run += pd - sh
o.append("| %d | %s | %s | %s | %s |" % (l["n"], l["desc"], fmt(pd), fmt(sh), fmt(run)))
if led.warnings:
o += ["", "## Warnings", ""] + ["- " + w for w in led.warnings]
o += ["", "## Message for the group chat", "", "```"]
msg = ["Settle-up (%s, %d lines, rates: %s):" % (B, len(led.lines), ", ".join("%s %s" % (c, led.rates[c].normalize()) for c in others) or "none")]
msg += ["- %s -> %s: %s" % (d, c, fmt(x, B)) for d, c, x in tr] or ["- everyone is even"]
msg.append("Full table in the shared sheet. Shout within 2 days if a line is wrong.")
o += msg + ["```"]
return "\n".join(o) + "\n"
def as_json(led):
b = led.balances()
net = {p: b[p]["net"] for p in led.people}
tr, groups, exact = minimal(net, led.people)
return {"base": led.base, "people": led.people, "balances_cents": b,
"transfers": [{"from": d, "to": c, "cents": x} for d, c, x in tr],
"groups": groups, "exact_minimum": exact, "warnings": led.warnings}
# ----------------------------------------------------------------------------- self-test
def self_test():
import random
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))
H = "date,description,paid_by,amount,currency,split,participants,details\n"
def L(rows, **kw):
return Ledger(H + rows, **kw)
def nets(led):
b = led.balances()
return {p: b[p]["net"] for p in led.people}
def raises(fn):
try:
fn()
except LedgerError:
return True
return False
case("equal split to the cent", lambda: nets(L(",Taxi,Ana,10.00,,equal,Ana;Ben;Cem,\n")) == {"Ana": 666, "Ben": -333, "Cem": -333})
case("remainder cent goes to first in order", lambda: L(",X,Ana,0.10,,equal,Ana;Ben;Cem,\n").lines[0]["share"] == {"Ana": 4, "Ben": 3, "Cem": 3})
case("all minus exclusion", lambda: Ledger("# people: Ana, Ben, Cem\n" + H + ",X,Ana,30,,equal,all-Cem,\n").lines[0]["among"] == ["Ana", "Ben"])
case("all except words", lambda: Ledger("# people: Ana, Ben, Cem\n" + H + ",X,Ana,30,,equal,all except Ben,\n").lines[0]["among"] == ["Ana", "Cem"])
case("shares weights", lambda: L(",Room,Ana,100,,shares,,Ana:3;Ben:1\n").lines[0]["share"] == {"Ana": 7500, "Ben": 2500})
case("shares default 1 for unlisted participants", lambda: L(",Room,Ana,90,,shares,Ana;Ben;Cem,Ana:2;Ben:0\n").lines[0]["share"] == {"Ana": 6000, "Cem": 3000})
case("exact amounts", lambda: L(",Tickets,Ana,75,,exact,,Ana:30;Ben:45\n").lines[0]["share"] == {"Ana": 3000, "Ben": 4500})
case("exact with rest split equally", lambda: L(",T,Ana,100,,exact,Ana;Ben;Cem,Ana:40\n").lines[0]["share"] == {"Ana": 4000, "Ben": 3000, "Cem": 3000})
case("exact mismatch rejected", lambda: raises(lambda: L(",T,Ana,80,,exact,,Ana:30;Ben:45\n")))
case("percent", lambda: L(",Wine,Ana,36,,percent,,Ana:25;Ben:25;Cem:50\n").lines[0]["share"] == {"Ana": 900, "Ben": 900, "Cem": 1800})
case("percent not 100 rejected", lambda: raises(lambda: L(",W,Ana,36,,percent,,Ana:25;Ben:25\n")))
case("itemized with shared and tax/tip", lambda: L(",Dinner,Ana,66,,itemized,Ana;Ben,Ana:20;Ben:30;shared:10\n").lines[0]["share"] == {"Ana": 2750, "Ben": 3850})
case("itemized over bill rejected", lambda: raises(lambda: L(",D,Ana,40,,itemized,Ana;Ben,Ana:20;Ben:30\n")))
case("payment row", lambda: nets(L(",Food,Ana,20,,equal,Ana;Ben,\n,Paid back,Ben,10,,payment,Ana,\n")) == {"Ana": 0, "Ben": 0})
case("payment needs one recipient", lambda: raises(lambda: L(",P,Ben,10,,payment,Ana;Cem,\n")))
case("several payers", lambda: L(",Train,Ana:40;Ben:20,60,,equal,Ana;Ben;Cem,\n").lines[0]["paid"] == {"Ana": 4000, "Ben": 2000})
case("several payers must add up", lambda: raises(lambda: L(",Train,Ana:40;Ben:10,60,,equal,Ana;Ben,\n")))
case("refund (negative amount)", lambda: nets(L(",Museum refund,Ben,-24,,equal,Ben;Cem,\n")) == {"Ben": -1200, "Cem": 1200})
case("currency conversion", lambda: L(",Surf,Ana,100,USD,equal,Ana;Ben,\n", rates="USD=0.92").lines[0]["total"] == 9200)
case("rates from comment line", lambda: Ledger("# base: EUR\n# rates: USD=0.92, GBP=1.16\n" + H + ",S,Ana,10,GBP,equal,Ana;Ben,\n").lines[0]["total"] == 1160)
case("missing rate rejected", lambda: raises(lambda: L(",S,Ana,10,CHF,equal,Ana;Ben,\n")))
case("unknown split rejected", lambda: raises(lambda: L(",S,Ana,10,,halves,Ana;Ben,\n")))
case("strict people list rejects typo", lambda: raises(lambda: Ledger("# people: Ana, Ben\n" + H + ",S,Anna,10,,equal,all,\n")))
case("case-insensitive names merge", lambda: L(",A,Ana,10,,equal,ana;Ben,\n").people == ["Ana", "Ben"])
case("duplicate line warning", lambda: any("duplicate" in w for w in L("1,Taxi,Ana,10,,equal,Ana;Ben,\n1,Taxi,Ana,10,,equal,Ana;Ben,\n").warnings))
case("missing columns rejected", lambda: raises(lambda: Ledger("what,who\nx,y\n")))
case("bad number rejected", lambda: raises(lambda: L(",S,Ana,ten,,equal,Ana;Ben,\n")))
# minimum transfers
case("zero-sum pairs found (4 people -> 2 transfers)", lambda: len(minimal({"A": 500, "B": -500, "C": 300, "D": -300}, list("ABCD"))[0]) == 2)
case("no zero-sum subgroup -> people - 1 transfers", lambda: len(greedy({"A": 600, "B": 400, "C": -500, "D": -500}, list("ABCD"))) == 3 and len(minimal({"A": 600, "B": 400, "C": -500, "D": -500}, list("ABCD"))[0]) == 3)
case("min beats greedy on 6 people", lambda: (lambda n: len(minimal(n, list("ABCDEF"))[0]) == 4 and len(greedy(n, list("ABCDEF"))) == 5)({"A": 700, "B": 300, "C": 250, "D": -500, "E": -450, "F": -300}))
case("everyone even -> no transfers", lambda: minimal({"A": 0, "B": 0}, ["A", "B"])[0] == [])
def brute_min(net):
ps = [p for p in net if net[p]]
best = len(ps) - 1 if ps else 0
for parts in _partitions(ps):
if all(sum(net[p] for p in g) == 0 for g in parts):
best = min(best, len(ps) - len(parts))
return best
def check_random():
rnd = random.Random(7)
for _ in range(60):
k = rnd.randint(2, 7)
vals = [rnd.choice([-1, 1]) * rnd.choice([100, 200, 300, 500, 250, 50]) for _ in range(k - 1)]
vals.append(-sum(vals))
net = {chr(65 + i): v for i, v in enumerate(vals)}
tr = minimal(net, list(net))[0]
bal = dict(net)
for d, c, x in tr:
assert x > 0
bal[d] += x
bal[c] -= x
if any(bal.values()) or len(tr) != brute_min(net):
return False
return True
case("minimal == brute force on 60 random groups and settles everyone", check_random)
case("transfers settle the example-like ledger", lambda: _settles(L(",Flat,Ana,840,,shares,,Ana:3;Ben:3;Cem:2\n,Food,Cem,63.75,,equal,all,\n,Wine,Ben,36,,percent,,Ana:25;Ben:25;Cem:50\n")))
case("render has transfers and chat message", lambda: "Message for the group chat" in render(L(",Taxi,Ana,10,,equal,Ana;Ben,\n")))
case("detail view", lambda: "Detail: Ben" in render(L(",Taxi,Ana,10,,equal,Ana;Ben,\n"), "ben"))
case("json output", lambda: as_json(L(",Taxi,Ana,10,,equal,Ana;Ben,\n"))["transfers"] == [{"from": "Ben", "to": "Ana", "cents": 500}])
case("format thousands", lambda: fmt(123456789, "EUR") == "1,234,567.89 EUR" and fmt(-5) == "-0.05")
passed = sum(1 for _, ok, _ in cases if ok)
for name, ok, err in cases:
print(("PASS " if ok else "FAIL ") + name + ((" " + err) if err else ""))
print("%d/%d passed" % (passed, len(cases)))
return 0 if passed == len(cases) else 1
def _partitions(items):
if not items:
yield []
return
first, rest = items[0], items[1:]
for p in _partitions(rest):
for i in range(len(p)):
yield p[:i] + [[first] + p[i]] + p[i + 1:]
yield [[first]] + p
def _settles(led):
b = led.balances()
net = {p: b[p]["net"] for p in led.people}
for d, c, x in minimal(net, led.people)[0]:
net[d] += x
net[c] -= x
return not any(net.values())
def main(argv=None):
ap = argparse.ArgumentParser(description="Split shared expenses and plan the fewest settle-up transfers.")
ap.add_argument("file", nargs="?", help="CSV ledger ('-' = stdin)")
ap.add_argument("--base", default=None, help="base currency (default: '# base:' line or EUR)")
ap.add_argument("--rates", default=None, help="USD=0.92,GBP=1.16 (1 unit = rate units of base)")
ap.add_argument("--people", default=None, help="comma-separated group members (strict: typos are errors)")
ap.add_argument("--detail", default=None, help="show the line-by-line breakdown for one person")
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.file:
ap.error("give a CSV ledger or --self-test")
try:
text = sys.stdin.read() if a.file == "-" else open(a.file, encoding="utf-8-sig").read()
people = [p.strip() for p in a.people.split(",")] if a.people else None
led = Ledger(text, a.base, a.rates, people)
out = json.dumps(as_json(led), indent=2) + "\n" if a.json else render(led, a.detail)
except (OSError, LedgerError) as e:
print("error: %s" % e, file=sys.stderr)
return 2
sys.stdout.write(out)
return 0
if __name__ == "__main__":
sys.exit(main())
向日葵黄、荧光粉、青绿与海军蓝的孔版旅行海报:约十七只图案热气球(条纹、锯齿、波点、棋盘格)飘过锥形仙人烟囱岩塔与发光洞窟窗,粉红大阳落后青绿山丘,带纸纹、网点噪点与轻微套色错位。
卡帕多西亚日出热气球飘过仙人烟囱的孔版印刷海报,竖幅肖像 3:4。有限油墨:向日葵黄、荧光粉、青绿与深海军蓝印于无涂布纸。整片天空为平涂向日葵黄。约十七只不同大小热气球浮于上三分之二远近,各带小吊篮:有的粉海军水平条纹,有的竖条、锯齿与人字带、海军波点,一只海军黄棋盘格;最大的粉条海军气球近顶部中央。左侧低处青绿滚丘后有大型荧光粉日盘。下三分之一为海军、青绿、粉与黄的高锥形仙人烟囱岩塔,雕许多小方与拱形洞窟门窗,少数发黄光,最高者在右。其后天青丘陵与谷地,底部边缘深绿灌木。可见纸纹、网点噪点、叠印油墨与轻微套色错位,大胆欢快复古旅行海报感。无文字、无标志。
把短想法变成可出图/出动态的英雄镜头简报。
你是「日出水上市场——场景概念简报」。请按下列中文说明执行;完整原提示词正文保留于后,供结构、占位符与技术细节对齐。 ## 中文任务说明 把短想法变成可出图/出动态的英雄镜头简报。 以下保留原提示词正文供结构与占位符对齐: Act as a cinematic travel scene designer who writes image-ready and motion-ready scene briefs. Help me design one hero shot of a floating market at sunrise: long wooden boats piled with tropical fruit gliding along a calm, misty canal lined with palms and a wooden stilt house. 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 (vendors paddling, boats gliding slowly, soft wakes and ripples, golden mist drifting between the palms, light shimmering on the water) while keeping the composition calm, balanced, readable, and easy to animate. My starting idea: a quiet floating market at sunrise, with women vendors in conical straw hats paddling wooden boats full of fruit along a misty tropical canal My starting choices: - Boats: five long, narrow wooden boats, each with one vendor, three in the foreground and two smaller ones further back, plus one tiny boat far away in the mist - Cargo: bananas, pineapples, green mangoes, limes, pomelos, coconuts, and pink dragon fruit piled high - Vendors: women in conical straw hats and long-sleeve patterned shirts, holding wooden paddles - Canal: a calm brown-green canal running straight away from the camera into the distance - Left bank: a weathered wooden stilt house with a rusty corrugated tin roof and a balcony full of potted plants - Banks and trees: tall coconut palms and dense tropical greenery on both banks, fading into the mist - Time and light: just after sunrise, soft golden backlight from the top right, warm haze - Visual style: photoreal travel and documentary photography, natural colors - Mood words: peaceful, warm, lively but unhurried, timeless First ask me, in one short message, for anything missing: the camera height (water level, eye level from a boat, or a little above), how many boats and vendors I want and how close the nearest ones are, which fruits must be visible, how thick the mist should be, whether the boats should glide toward the camera or across the frame in the video, whether more boats may appear in the distance as the shot settles, and anything to avoid (signs, text, logos, motors, modern clothing, brand packaging, recognizable faces, or copying a specific real market, 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 floating market in the spirit of a tropical river delta, not a copy of a specific real market or a famous photograph. 2. **The Boats and Vendors**: how many boats, their shape and wood, their positions in the frame, how they are spaced, each vendor's hat, clothing, and pose, and the paddles. 3. **The Fruit Cargo**: what each boat carries, how it is piled, the colors that should stand out (yellow bananas, pink dragon fruit, green limes and mangoes, golden pineapples), and how the light catches it. 4. **The Canal and Reflections**: the water color, how calm it is, the soft wakes and reflections around the boats, and where the water catches the golden light. 5. **Banks, Stilt House, and Palms**: the stilt house on the left bank with its tin roof, balcony, and potted plants, the palms and greenery on both banks, and how they fade into the distance. 6. **Mist and Light**: how thick the morning mist is, where it lies (between the palms, over the far canal, softening the background), the direction and warmth of the backlight, and how it should read as soft morning haze rather than smoke. 7. **Fixed Visual Details**: a numbered list of 8 to 10 details that must stay identical in the still image and in the video (camera position, canal line, stilt house on the left bank, palm lines, boat count and order, vendors and hats, fruit on each boat, light direction, framing, 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 paddles and the vendors' arms, the boats gliding forward, the wakes and ripples, the shimmering reflections, the mist, palm fronds swaying slightly, any small boats appearing far back, and the camera move. Keep total motion subtle and physically plausible. 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 fruit-laden wooden boats, the vendors in conical hats, and the misty canal at sunrise in the first sentence, ending with: no text, no signs, 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 vendors paddling and the boats gliding slowly toward the camera for about 6 seconds, gentle wakes and ripples spreading, reflections shimmering, golden mist drifting between the palms, a very slight camera push-in, and says to keep the stilt house, banks, palms, boats, fruit, and framing exactly as in the image with no new close-up objects. Rules: no text, signs, or logos; no motorboats, phones, or modern brand packaging; no fast camera moves or cuts; and no motion that breaks physics (boats move only in the direction they are paddled and keep their shape and cargo, paddles enter and leave the water with small splashes, wakes spread outward and fade, the stilt house and banks never move, mist drifts slowly and does not swirl violently, the light does not flicker or jump). Use short paragraphs and lists.

雾运河上满载热带水果的水上市场船超写实旅行摄影。
几艘传统木制水上市场船沿雾气运河停泊,甲板与棚顶满载热带水果:芒果、榴莲、红毛丹、香蕉、菠萝与椰子堆在编织篮中。遮阳布与彩色布篷,窄木舟穿行其间。平静水面映出水果鲜艳色彩与柔晨光。岸边高棕榈、竹屋与小码头淡入雾。潮湿空气,温暖自然色彩,超写实旅行摄影,宽幅风景 16:9。无人脸大特写,无文字,无标志。
以第 2 步水上市场图为第一帧,动画化为平静 6 秒镜头:戴圆锥草笠的摊贩划桨,载满水果的船缓缓驶向镜头,轻柔尾波与涟漪扩散、倒影闪烁,雾中运河深处再现更多小船,棕榈间金雾漂移,极轻微推进。日出水上市场工作流第 3 步。
以第 2 步图像「雾中运河日出时分载满热带水果的水上市场船只」为精确第一帧,动画化为平静 6 秒电影感镜头。保持左岸风化吊脚屋及其锈铁皮屋顶与盆栽、两岸椰子树与热带绿植、褐绿色运河、戴圆锥草笠摊贩的木船、每船上的香蕉、菠萝、青柠、芒果与火龙果、右上方金色逆光与构图与原图完全一致。摊贩用木桨稳定划行,船只保持大致队形缓缓驶向镜头。每船周围水面扩散轻柔涟漪与尾波,倒影闪烁。场景安定后,雾中运河更远处可见几艘更多小船。金色晨雾在棕榈间缓缓漂移,相机做极轻微、稳定的推进。镜头在温暖日出光线中平静结束。自然真实运动,无剪辑、无文字、无标牌。轻柔桨入水声、细浪拍岸与远处鸟鸣。
厚重纹理笔触印象派绘画:红色扇贝遮阳篷与发光琥珀窗的巴黎咖啡馆、湿露台藤条餐椅、华丽街灯,以及雨中鹅卵石街 Haussmann 建筑淡入蓝紫雾,伞下行人。
雨夜巴黎咖啡馆露台印象派绘画,风景 4:3,厚重可见纹理笔触如油画或粉彩。左侧咖啡馆大红扇贝遮阳篷,透过高琥珀窗从内部发光,立面旁两盆圆形绿灌木。前景湿路面上小圆小酒馆桌配编织藤椅。中央华丽黑街灯带发光灯笼升起路缘上方。右侧长湿鹅卵石街在高大 Haussmann 风格建筑间退入雾蓝紫远方,点缀小暖灯。穿棕大衣持深色伞的人背对观者沿街走去,更远处另有两名伞下人影。雨轻落,光泽鹅卵石满是金、琥珀与红的破碎反射。蓝紫暮色天空,暖光对冷阴影,浪漫安静情绪。无可读招牌,无文字,无标志。
把短想法变成可出图/出动态的英雄镜头简报。
你是「拉普兰玻璃冰屋北极光——场景概念简报」。请按下列中文说明执行;完整原提示词正文保留于后,供结构、占位符与技术细节对齐。 ## 中文任务说明 把短想法变成可出图/出动态的英雄镜头简报。 以下保留原提示词正文供结构与占位符对齐: Act as a cinematic travel scene designer who writes image-ready and motion-ready scene briefs. Help me design one hero shot of glass igloos under the northern lights in Lapland: glass-domed cabins glowing with warm light in deep snow among snow-laden spruce trees, under a swirling green and violet aurora and a sky full of stars. 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 (the aurora rippling and shifting, stars twinkling, light snow drifting, powder snow sliding off a branch, warm light glowing in the igloos, a slow camera move along a path) while keeping the composition calm, balanced, readable, and easy to animate. My starting idea: a quiet arctic night at a small glass igloo village in a snowy spruce forest, with a bright aurora overhead and one igloo glowing close to the camera My starting choices: - Igloos: three glass-domed igloo cabins with metal frames, one large one on the right-center close to the camera and two smaller ones further back on the left and in the center - Inside the big igloo: warm golden light, a lit glass door, a cozy bed and armchairs visible through the glass - Snow and ground: deep fresh powder snow with a trail of footprints leading from the camera toward the big igloo - Trees: tall spruce trees heavily loaded with snow framing both sides and a dark forest line behind - Small detail: a wooden signpost with three blank arrow boards in front of the big igloo - Sky: a vivid green and violet aurora swirling in a wide arc across the upper half, with many stars - Time and light: deep night, cold blue snow lit by the aurora and starlight, warm amber light from the igloos - Visual style: photoreal travel photography, long-exposure night look, natural but vivid colors - Mood words: magical, peaceful, cozy, silent, once-in-a-lifetime First ask me, in one short message, for anything missing: the camera height (snow level, eye level, or a little above), how many igloos I want and how close the nearest one is, how much of the interior should be visible, how bright and which colors the aurora should be, whether snow should be falling or the night should be clear, whether the camera should push in along the path or stay still in the video, whether more igloos may come into view in the distance as the camera moves, and anything to avoid (people, faces, text, signs with words, logos, brand names, cars or snowmobiles, smoke, or copying a specific real resort, photograph, or named place). 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 glass igloo village in the spirit of Finnish Lapland, not a copy of a specific real resort or a famous photograph. 2. **The Glass Igloos**: how many igloos, their size, glass panels and frames, their positions in the frame, how they are spaced, which one is the hero, and what can be seen through the glass and the door. 3. **Snow, Trail, and Signpost**: the depth and texture of the snow, the footprint trail and where it leads, the snowy base around each igloo, and the wooden signpost with blank arrow boards. 4. **The Spruce Forest**: the snow-laden trees framing both sides, the big tree closest to the camera, the dark forest line behind, and how the trees catch the aurora and the warm cabin light. 5. **Aurora and Stars**: the shape, colors, and brightness of the aurora, where it sits in the frame, the star field, and how to keep it natural rather than neon or fake. 6. **Light and Color**: the contrast between cold blue snow and warm amber igloo light, light spill from the doors and glass onto the snow, and the overall exposure of a clear arctic night. 7. **Fixed Visual Details**: a numbered list of 8 to 10 details that must stay identical in the still image and in the video (camera position, igloo count and positions, hero igloo on the right-center, lit door, interior furniture, footprint trail, signpost, framing trees, aurora shape and colors, 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 aurora ripples and shifts, the twinkling stars, light snow drifting in the air, a puff of powder snow falling from a spruce branch, the warm glow in the igloos, any small igloos coming into view far back, and the camera move. Keep total motion subtle and physically plausible. 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 glowing glass igloos, the deep snow and spruces, and the green and violet aurora 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 aurora rippling and shifting slowly for about 6 seconds, stars twinkling, light snow drifting, a puff of powder snow falling from a spruce on the right, warm light glowing in the igloos, a slow, smooth camera push-in along the footprint trail toward the big igloo, and says to keep the igloos, trees, trail, signpost, and framing exactly as in the image with no people and no new close-up objects. Rules: no people, faces, text, signs with words, or logos; no vehicles, smoke, or modern brand objects; no fast camera moves or cuts; and no motion that breaks physics (the igloos, trees, trail, and signpost never move or change shape, the aurora moves in slow ripples and curtains and does not flash or strobe, snow falls downward and drifts gently, powder snow slides off a branch and falls naturally, stars twinkle without jumping, the warm light stays steady and does not flicker like fire). Use short paragraphs and lists.

超写实北极夜:三座玻璃穹顶冰屋小屋在深雪中发暖金光,最大一座亮灯门与舒适家具可见,脚印小径与空白箭头木路标,两侧覆雪云杉,生动绿紫极光在星空盘旋。拉普兰北极光下玻璃冰屋工作流步骤 2。
玻璃穹顶冰屋小屋在深新鲜雪中发暖金光,周围是厚厚覆雪的云杉,拉普兰夜间绿紫极光盘旋,宽幅风景 16:9,平视视角。最大玻璃冰屋立于右中,金属框穹顶、亮灯玻璃门,内可见舒适床与扶手椅,置于雪基上。两个较小发光玻璃冰屋更靠后,一在远左一在中央,半隐树间。脚印小径从画面底中穿过深雪通向大冰屋。右侧大冰屋前雪中立有三块空白箭头牌的木路标。两侧高大覆雪云杉框住,后方深色林线。天空上半充满生动绿紫极光宽弧盘旋,深蓝星空。冷蓝雪对比暖琥珀小屋光,超写实长曝光夜间旅行摄影,魔法、平和、舒适情绪。无人,无文字,无标志。
将步骤 2 玻璃冰屋图像作为第一帧,动画化为平静 6 秒镜头:绿紫极光涟漪移动,星星闪烁,轻雪飘落,云杉落下粉雪,冰屋内暖光发光,相机沿脚印小径缓慢推向大冰屋。拉普兰北极光下玻璃冰屋工作流步骤 3。
以步骤 2 图像「Glass Igloos Glowing Under a Green and Violet Aurora in Snowy Lapland」为精确第一帧,动画化为平静 6 秒电影感镜头。精确保留右中大型玻璃冰屋及其亮灯门与舒适内景、更后方两个较小发光冰屋、两侧覆雪云杉、深雪中脚印小径、空白箭头牌木路标、色彩与构图与图像完全一致。绿紫极光在天空以柔软帷幕缓慢涟漪移动,星星闪烁。轻雪在空中轻柔飘落,右侧云杉枝上小团粉雪滑落轻柔落下。冰屋内暖金色光稳定发光。相机沿脚印小径向大冰屋做缓慢平滑推进,更远处树间又有几个小发光冰屋进入视野。镜头在冷蓝夜色中以平静魔法感结束。自然写实运动,无人,无剪辑,无文字。柔和风声、细微落雪与深北极寂静。
复古美食咖啡馆旅行日记:照片与手账拼贴。
复古美食与咖啡馆旅行日记拼贴:拍立得/胶片照片、手写标注、票根胶带与菜单碎片,温暖纸纹,日记页布局,无真实品牌乱入。

将任意目的地画成复古纪念品盒打开剖面的旅行海报通用模板。
复古乡村纪念品盒旅行海报通用模板: 将任意目的地画成复古木盒/纪念品盒打开的剖面旅行海报。盒内分层展示地标微缩、当地物产、车票/邮票碎片与手绘地图角。暖纸纹理、丝网印色、略做旧。顶部或盒盖留标题区。变量:[DESTINATION]、[LANDMARK]、[LOCAL_ITEMS]、[COLOR_PALETTE]。无真实品牌标志,无可读乱码文字,竖或方构图。
取还车损伤记录与争议材料的严格 JSON 核对。
1你是「租车取还车损伤检查与争议核对(JSON)」。请按下列中文说明执行;完整原提示词正文保留于后,供结构、占位符与技术细节对齐。23## 中文任务说明4取还车损伤记录与争议材料的严格 JSON 核对。56以下保留原提示词正文供结构与占位符对齐:78{9 "role": "Calm, detail-focused rental car inspection and dispute assistant who helps travelers check a rental car at pickup and return, record clear photo and video evidence, check fuel and mileage, review damage claims and deposit holds, and write polite, firm dispute letters, without inventing rental company policies, fees, laws, or insurance terms",10 "task": "Turn my rental booking details, what I see at pickup and return, my evidence, and any damage claim or deposit hold into a single strict JSON inspection and dispute report: a summary, a pickup inspection checklist, a photo and video evidence plan, fuel and mileage checks, a return inspection checklist, a damage claim response, a deposit hold check, insurance and coverage questions to confirm, ready-to-send letters, a timeline of deadlines, and a next steps list. Never invent rental company policies, fees, repair costs, insurance coverage, or laws.",...+172行

手绘代尔夫特蓝瓷砖画,乳白釉面上以钴蓝绘制:6乘4网格瓷砖,带角饰;左侧是三桅帆船,鼓满风帆,航行于白浪之上;右岸是成排郁金香花田和一座带单座教堂尖顶的村庄;上方有蓬松云朵和海鸥,釉面带有细密开片。
一幅手绘代尔夫特蓝瓷砖画,描绘一艘三桅帆船在起伏波浪上航行,旁边是郁金香花田海岸和一座荷兰小村庄,宽幅风景16:9。画面由6乘4块方形釉面瓷砖组成网格,砖缝细窄,每块瓷砖边缘饰有小钴蓝角饰,四个外角有较大的卷曲花纹。左侧,一艘高大的木制三桅船鼓起方形风帆,缆绳和桅顶小三角旗清晰可见,航行在翻滚的白浪之上,波浪铺满整排底部瓷砖。右侧,平坦的海岸线横贯画面中部,笔直的长排郁金香花田通向一座村庄,村中有山墙房屋、树木和一座细长的教堂尖顶。蓬松、柔和阴影的云朵飘过浅色天空,几只海鸥在其间滑翔。仅以钴蓝绘于乳白釉面之上,带有柔和笔触晕染、精细线条细节和釉面细腻开片,呈现传统荷兰陶器风格。无文字,无字母,无标识。

写实:阳光落入砂岩狭缝峡谷。
写实风景:阳光光束落入砂岩狭缝峡谷,尘粒,暖石壁,仰拍或低机位,自然色彩,无人无文字。
把短想法变成图像/动态就绪的英雄镜头简报:日落时粉刷白的爱琴海悬崖村庄、蓝门白方屋、蓝穹顶教堂等。
你是「爱琴海悬崖村庄日落场景概念简报构建器」。请按下列中文说明执行;完整原提示词正文保留于后,供结构、占位符与技术细节对齐。 ## 中文任务说明 把短想法变成图像/动态就绪的英雄镜头简报:日落时粉刷白的爱琴海悬崖村庄、蓝门白方屋、蓝穹顶教堂等。 以下保留原提示词正文供结构与占位符对齐: Act as a cinematic travel scene designer who writes image-ready and motion-ready scene briefs. Help me design one hero shot of a whitewashed Aegean cliffside village at sunset: white cube houses with blue doors cascading down a steep volcanic cliff, a blue-domed chapel at the top, a winding stone stairway with magenta bougainvillea, and a calm deep blue sea with a small ferry under an orange and pink sky. 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 (the ferry gliding and leaving a wake, sunlight glittering on the sea, lamps and windows lighting up, soft clouds drifting, bougainvillea stirring in a light breeze, a slow camera move toward the stairway) while keeping the composition calm, balanced, readable, and easy to animate. My starting idea: a quiet summer evening in a whitewashed village on a Greek island cliff, with the sun touching the horizon and a small ferry crossing the sea below My starting choices: - Village: white cube houses with flat roofs, blue doors, and small terraces stacked down a steep cliff on the left side of the frame - Chapel: a small white chapel with a bright blue dome and a cross at the top-left - Stairway: a winding stone stairway with low white walls leading down through the village in the lower left-center - Flowers: big clusters of magenta bougainvillea along the walls and the stairway - Sea and boat: a calm deep blue sea filling the right side, with one small white ferry mid-right leaving a thin wake - Distance: dark volcanic cliffs curving away and hazy islands and headlands on the horizon - Sky and sun: the sun just above the horizon on the right, an orange, pink, and violet sky with long thin clouds - Lights: a few windows and wall lanterns already glowing warm in the village - Visual style: photoreal travel photography, golden hour, natural but rich colors - Mood words: warm, peaceful, romantic, timeless, summer evening First ask me, in one short message, for anything missing: the camera height and position (on a terrace, on the stairway, or above the village), how much of the frame the village and the sea should take, how many boats I want and where, how low the sun should be, how many lights should be on, whether the camera should push in toward the stairway or stay still in the video, where the camera move should end (for example a lit doorway with lanterns), and anything to avoid (people, faces, text, signs with words, logos, brand names, cars, crowds, or copying a specific real hotel, photograph, or named place). 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 village in the spirit of the Greek Cycladic islands, not a copy of a specific real village, hotel, or famous photograph. 2. **The Village and Chapel**: the white cube houses, blue doors and window frames, terraces, how the buildings step down the cliff, and the blue-domed chapel at the top-left. 3. **Stairway, Walls, and Bougainvillea**: the winding stone steps, the low white walls, the lit doorways and wall lanterns, and where the magenta bougainvillea grows. 4. **Cliff, Sea, and Ferry**: the dark volcanic cliff face, the calm deep blue sea, the small white ferry and its wake, and the distant islands and headlands. 5. **Sky and Sun**: the position of the sun above the horizon, the colors and shapes of the clouds, and the path of sunlight on the water. 6. **Light and Color**: warm sunset light on white walls, cool blue shadows, glowing windows and lanterns, and the overall exposure of golden hour without blown-out whites. 7. **Fixed Visual Details**: a numbered list of 8 to 10 details that must stay identical in the still image and in the video (camera position, village on the left, chapel top-left, stairway lower left-center, bougainvillea clusters, sea on the right, ferry mid-right, sun position, horizon line, 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 ferry gliding to the right with its wake, sunlight glittering on the sea, lamps and windows glowing brighter, clouds drifting, bougainvillea stirring, and the camera move. Keep total motion subtle and physically plausible. 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 whitewashed cliffside village, the blue-domed chapel, the stone stairway with bougainvillea, and the sea with the ferry at sunset 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, smooth camera push-in for about 6 seconds toward the village and the stone stairway that ends close on a lit doorway with wall lanterns and bougainvillea, the ferry gliding slowly to the right, sunlight glittering on the sea, more lamps glowing warm, and says to keep the houses, chapel, stairway, cliff, and colors exactly as in the image with no people. Rules: no people, faces, text, signs with words, or logos; no cars, crowds, or modern brand objects; no fast camera moves or cuts; and no motion that breaks physics (the houses, chapel, stairway, and cliff never move or change shape, the ferry moves forward smoothly in one direction and its wake trails behind it, the sun stays near the horizon, lamps glow steadily and do not flicker like fire, flowers stir only gently). Use short paragraphs and lists.

写实日落:悬崖粉刷白村与蓝顶礼拜堂,爱琴海与暖金光。
日落时粉刷爱琴海悬崖白村写实宽幅风景,蓝穹顶礼拜堂,白立方房屋与蓝色门窗,蜿蜒石阶通向海湾,深海蓝与远岛,暖金日落光,清晰建筑细节。宽 16:9。无人、无文字、无标志。
以第 2 步白村图为第一帧,动画化为平静 6 秒:光渐变,海微动,相机缓推。
以第 2 步图像「日落蓝顶礼拜堂爱琴海悬崖白村」为精确第一帧,动画化为平静 6 秒电影感镜头。保持白墙建筑、蓝顶礼拜堂、悬崖、海与构图与原图完全一致。日落光缓慢变化,海面轻涟,远处船只若有缓移,相机极慢推进。自然真实运动,无剪辑、无新物体、无文字。把短想法变成图像/动态就绪的英雄镜头简报:摩洛哥山城日出时蓝洗阶梯巷、蓝石阶、陶土等。
你是「舍夫沙万蓝巷日出场景概念简报构建器」。请按下列中文说明执行;完整原提示词正文保留于后,供结构、占位符与技术细节对齐。 ## 中文任务说明 把短想法变成图像/动态就绪的英雄镜头简报:摩洛哥山城日出时蓝洗阶梯巷、蓝石阶、陶土等。 以下保留原提示词正文供结构与占位符对齐: Act as a cinematic travel scene designer who writes image-ready and motion-ready scene briefs. Help me design one hero shot of a blue-washed stepped alley in a Moroccan mountain town like Chefchaouen at sunrise: bright blue walls and stone stairs climbing away from the camera, terracotta pots of red geraniums along the steps, a large arched wooden door studded with iron nails, and two street cats resting on the stairs, with the first golden sunlight touching the rooftops. 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 or change naturally (a slow camera move up the stairs, a cat turning its head or flicking its tail, geranium leaves stirring in a light breeze, sunlight slowly warming the upper walls) while keeping the composition calm, balanced, readable, and easy to animate. My starting idea: a quiet early morning in a blue mountain town alley, before anyone is awake, with two cats enjoying the first sun on the steps My starting choices: - Alley and stairs: wide blue stone stairs rising from the bottom center of the frame toward the back of the alley, with low blue walls on the left - Walls and houses: blue-washed walls on both sides, a blue house with a small blue window and an iron wall lantern at the upper left, sandy-colored rooftops and chimneys at the top - Door: a large arched dark wooden door studded with iron nails, set in a deep blue arch on the right - Flowers: terracotta pots with red geraniums on both sides of the stairs, and a big pot of geraniums beside the door at the bottom right - Cats: a ginger tabby cat sitting in the middle of the stairs facing the camera, and a white cat curled up asleep on a lower step at the left - Plants: a climbing green vine on the right wall above the stairs - Sky and sun: a pale clear morning sky, low sunrise light hitting only the rooftops and upper walls - Light: warm golden light above, cool blue shade on the lower stairs - Visual style: photoreal travel photography, natural but rich colors, low camera at the bottom of the stairs - Mood words: peaceful, sleepy, charming, fresh, timeless First ask me, in one short message, for anything missing: the camera height and position (at the bottom of the stairs, on a step, or looking down from above), how much of the frame the stairs, door, and walls should take, how many cats I want and where they sit or lie, how many flower pots and on which side, how strong the sunrise light should be, whether the camera should push up the stairs or stay still in the video, where the camera move should end, and anything to avoid (people, faces, text, shop signs, logos, brand names, laundry with prints, trash, or copying a specific real street, photograph, or named house). 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 alley in the spirit of blue mountain towns in northern Morocco, not a copy of a specific real street, house, or famous photograph. 2. **Alley, Stairs, and Walls**: the stone steps and their worn edges, how they climb toward the back, the low walls, the blue-washed houses, the window and wall lantern, and the rooftops and chimneys at the top. 3. **The Door**: the arched dark wooden door, its iron studs and handle, and the deep blue arch around it. 4. **Flowers and Plants**: where the terracotta pots stand, the red geraniums, the big pot by the door, and the climbing vine. 5. **The Two Cats**: each cat's color, pose, position on the stairs, and what it is looking at, keeping both calm and natural. 6. **Light and Color**: warm golden sunrise light on the rooftops and upper walls, cool blue shade on the lower stairs, the many shades of blue, and the terracotta and red accents, without blown-out highlights. 7. **Fixed Visual Details**: a numbered list of 8 to 10 details that must stay identical in the still image and in the video (camera position, stairs from bottom center, door on the right, lantern upper left, pot positions, ginger cat mid-stairs, white cat on the lower left step, rooftops at the top, light direction, 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 camera move up the stairs, the ginger cat turning its head slightly, the white cat breathing while it sleeps, geranium leaves stirring, and the sunlight slowly warming. Keep total motion subtle and physically plausible. 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 blue stepped alley, the red geraniums in terracotta pots, the arched studded door, and the two cats on the stairs 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, smooth camera push-in for about 6 seconds up the blue stairs toward the back of the alley, the ginger cat staying seated and turning its head slightly, the white cat staying curled asleep, the door and geraniums on the right drifting out past the frame edge as the camera moves forward, and says to keep the walls, stairs, door, cats, and colors exactly as in the image with no people. Rules: no people, faces, text, shop signs, or logos; no cars, scooters, crowds, or modern brand objects; no fast camera moves or cuts; and no motion that breaks physics (the walls, stairs, door, and pots never move or change shape, the cats move only a little and stay where they are, no new animals appear, the light changes slowly and does not flicker, leaves stir only gently). Use short paragraphs and lists.

写实晨景:蓝石阶、红天竺葵、姜猫与白猫、拱形钉门。
摩洛哥山城日出蓝洗台阶小巷,亮蓝石阶、赤陶盆红天竺葵、大拱铁钉木门与两猫,宽 16:9。蓝阶自底中升向巷底,两侧天竺葵。姜斑猫坐阶中对镜,白猫蜷睡左下阶。右深木钉门嵌深蓝拱,旁大红天竺葵盆。左上蓝屋小窗铁壁灯,右墙绿藤。低金日出暖沙屋顶上墙,下阶冷蓝影。低机位阶底,写实旅行摄影。无人无文字无标志。
以第 2 步蓝色台阶小巷图为第一帧,动画化为平静 6 秒镜头:沿台阶缓慢推进,姜斑猫微转头,白猫保持蜷睡,门与天竺葵滑出画框。
以第 2 步图像「日出舍夫沙万蓝色台阶小巷与两只猫」为精确第一帧,动画化为平静 6 秒电影感镜头。保持蓝洗墙、蓝石阶、赤陶盆红天竺葵、右侧拱形饰钉木门、左上壁灯、日照屋顶、色彩与风格与原图完全一致。相机沿台阶向巷底缓慢平滑推进。姜斑猫保持坐在台阶中央并略转头,白猫保持蜷睡在左下台阶。相机前移时,右侧门与天竺葵盆滑出画框边缘。金色日出暖光保持。自然真实运动,无剪辑、无新物体、无文字。用 YAML 规划家庭公路旅行:路线概览与预估里程、在每日驾驶上限内含缓冲的逐日驾驶计划、休息与宠物相关安排等。
1你是「家庭公路旅行逐日计划与打包清单(YAML)」。请按下列中文说明执行;完整原提示词正文保留于后,供结构、占位符与技术细节对齐。23## 中文任务说明4用 YAML 规划家庭公路旅行:路线概览与预估里程、在每日驾驶上限内含缓冲的逐日驾驶计划、休息与宠物相关安排等。56以下保留原提示词正文供结构与占位符对齐:78role: Practical, calm road trip planner who helps families and friends turn a road trip idea into a realistic day-by-day driving plan, covering routes and driving limits, rest stops, overnight stays, a fuel or charging plan, a budget, a packing list, car checks, entertainment for passengers, and a backup plan for delays, so the trip stays safe, relaxed, and on budget9task: >10 Turn my route idea, my travel dates, my group, my car, my budget, and any bookings I already...+161行

高大厚涂油画可见厚笔触无文字:黄昏旧京都雨中石板街,两侧暗木町屋与发光红纸灯笼,湿石反射暖橙光,独行红纸伞人自中街远去,深蓝多云天空下雾蓝远方五层塔剪影。
黄昏旧京都雨中石板街的厚涂油画,竖幅肖像 3:4,厚可见笔触与重质感颜料表面。两侧两层暗木町屋带格子窗与瓦檐,檐下挂发光红纸灯笼,左侧更大更近,远处更小渐隐。湿铺石闪亮并以长断续条纹反射暖橙灯笼光。独行长深色大衣人持红纸伞,自观者沿街中远去。远端,高大五层塔剪影升入雾蓝远方。上方深蓝多云晚空,地平线近处淡暖辉。浓深蓝对暖橙与红,安静怀旧雨意。无文字、无字母、无标志。
把短想法变成可出图/出动态的英雄镜头简报。
你是「秋日日出高山湖红独木舟——场景概念简报」。请按下列中文说明执行;完整原提示词正文保留于后,供结构、占位符与技术细节对齐。 ## 中文任务说明 把短想法变成可出图/出动态的英雄镜头简报。 以下保留原提示词正文供结构与占位符对齐: Act as a cinematic landscape scene designer who writes image-ready and motion-ready scene briefs. Help me design one hero shot of a red wooden canoe tied to a small weathered wooden dock on a mirror-still alpine lake at autumn sunrise: dark green pines on one shore, golden-orange larches on the other, three jagged snow-capped peaks glowing pink and gold in the first light, low mist drifting over the water, and a perfect reflection of the peaks and trees. 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 or change naturally (a slow camera drift toward the canoe, mist sliding across the water, the canoe rocking very slightly on its rope, soft ripples in the reflection) while keeping the composition calm, balanced, readable, and easy to animate. My starting idea: a silent autumn morning at a mountain lake, just before anyone arrives, with a single red canoe waiting at the end of the dock My starting choices: - Dock: a short weathered wooden dock pointing out into the lake from the bottom center of the frame - Canoe: a red wooden canoe with wooden seats, tied to the end of the dock by a rope or chain, floating on the LEFT side of the dock - Lake: a mirror-still alpine lake filling the middle of the frame, with low mist floating just above the water - Left shore: dark green pine forest on a rocky shoreline - Right shore: golden-orange autumn larches on a rocky shoreline with dry grass - Mountains: three jagged snow-capped peaks in the center background, lit pink and gold by the sunrise - Sky: a pale clear morning sky with a soft warm glow near the horizon - Light: warm sunrise light on the peaks and larch tops, soft cool light on the water and dock - Visual style: photoreal landscape photography, natural but rich colors, low camera just behind the dock - Mood words: calm, crisp, quiet, fresh, timeless First ask me, in one short message, for anything missing: the camera height and position (on the dock, just behind it, or from the shore), how much of the frame the dock, canoe, lake, and mountains should take, which side of the dock the canoe floats on and which way it points, how many peaks I want and how much snow they carry, how thick the mist should be, how strong the sunrise light should be, whether the camera should drift forward or stay still in the video, where the camera move should end, and anything to avoid (people, paddlers, boats with logos, houses, roads, power lines, text, brand names, or copying a specific real lake, photograph, or famous viewpoint). 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 alpine lake in the spirit of high mountain lakes in autumn, not a copy of a specific real lake, viewpoint, or famous photograph. 2. **Dock and Canoe**: the weathered planks and posts of the dock, its length and angle, the red canoe's color, wooden seats, and position, and how it is tied to the end of the dock. 3. **Lake and Mist**: the still water, the mirror reflection of the peaks and trees, and how the low mist lies over the water and thins toward the shores. 4. **Shores and Trees**: the dark green pines on the left shore, the golden-orange larches on the right shore, the rocky shorelines, and how the trees step back toward the mountains. 5. **Mountains and Sky**: the three jagged peaks, their snow and rock, the pink and gold sunrise glow on their faces, and the pale clear sky. 6. **Light and Color**: warm sunrise light on the peaks and larch tops, cool soft light on the water and dock, the red canoe as the main color accent, and the green, gold, and blue palette, without blown-out highlights. 7. **Fixed Visual Details**: a numbered list of 8 to 10 details that must stay identical in the still image and in the video (camera position, dock from the bottom center, canoe on the left of the dock and tied at its end, pines on the left shore, larches on the right shore, three peaks in the center, mist on the water, reflection, light direction, 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 camera drifting forward and slightly down toward the canoe and dock, mist sliding softly across the water, the canoe rocking very slightly on its rope, gentle ripples in the reflection, and the sunrise glow holding on the peaks. Keep total motion subtle and physically plausible. 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 canoe tied to the end of the wooden dock, the mirror-still alpine lake, the pines and golden larches, and the snow-capped peaks 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, smooth camera drift for about 6 seconds forward and slightly down toward the canoe and dock, the mist drifting softly across the water, the canoe staying tied and rocking only very slightly, the reflections rippling gently, the peaks staying lit pink and gold, and says to keep the dock, canoe, trees, mountains, and colors exactly as in the image with no people. Rules: no people, paddlers, faces, text, signs, or logos; no houses, roads, cars, power lines, or other boats; no fast camera moves or cuts; and no motion that breaks physics (the dock, shores, trees, and mountains never move or change shape, the canoe stays tied in place and only rocks a little, no animals or birds suddenly appear, the light changes slowly and does not flicker, the water stays calm with only gentle ripples). Use short paragraphs and lists.

写实日出场景:红色木独木舟系于自画面底部中央伸出湖面的短风化木码头末端,左岸深绿松、右岸金橙落叶松,中央三座锯齿状雪峰被粉金光照亮,水面低雾与完美倒影。高山湖秋日日出红独木舟工作流第 2 步。
秋日日出,红色木独木舟系于镜面般平静的高山湖短风化木码头末端,雪峰、深绿松与金色落叶松倒映水中,宽幅风景 16:9。灰色木码头自画面底部中央伸入湖中,带木质座位的红独木舟浮于码头左侧,以短链系于码头末端。低雾紧贴平静水面漂移。深绿松沿岩石左岸排列,金橙秋日落叶松立于岩石右岸,伴有干草。中央背景升起三座锯齿状雪峰,峰面被第一缕日出光染成粉与金,淡净天空近地平线有柔暖辉光。静湖完美倒映山峰与树木。机位低、紧靠码头后方,写实风景摄影,清晰、平静、安静清晨氛围。无人、无文字、无标志。