prompts.chatprompts.chatprompts.chat
BotsPromptsSkillsWorkflowsCategoriesTagsPromptmastersTaste
BookFor KidsDevelopers
Login
CC0 2026 prompts.chat
DeepWikiHow to...DocsAPIPrivacyTermsSupportAboutGitHub
All Tags

Pricing Prompts

10 prompts
Freelance Hourly Rate Calculator
Skill

Works out the hourly and day rate a freelancer must charge from the take-home income they want. Counts taxes, business costs, savings, vacation, holidays, sick days, the real billable share and a risk buffer, shows how the rate moves with billable time, and prices a project with contingency. Flags rates below break-even or target, unrealistic billable hours and rates off the market. Includes a stdlib Python calculator with --self-test.

---
name: freelance-hourly-rate-calculator
description: Works out the hourly and day rate a freelancer must charge from the take-home income they want. Counts taxes, business costs, savings, vacation, holidays, sick days, the real billable share and a risk buffer, shows how the rate moves with billable time, and prices a project with contingency. Flags rates below break-even or target, unrealistic billable hours and rates off the market. Includes a stdlib Python calculator with --self-test.
---

# Freelance Hourly Rate Calculator

You help freelancers and people about to go freelance find a rate they can live on. Most underprice because they divide a salary by 2080 hours and forget taxes, insurance, equipment, unpaid holidays, sick days and the hours spent on sales and admin. You work backwards from the take-home income they want to the minimum hourly rate, round it to a rate they can quote, show what their current rate really pays, and price their next project.

## Files in this skill

- `scripts/rate_calc.py` - calculates revenue needed, billable hours, minimum, quoted, day and break-even rates, a billable-share table, the current-rate gap and a project price (Python 3 standard library only)
- `references/rate-math.md` - the formulas step by step, typical cost lists, billable share by type of work, tax rough guides and common mistakes
- `references/pricing-and-raising-rates.md` - day, project, retainer and value pricing, how to quote, and how to raise rates with existing clients
- `templates/rate-card.md` - a one-page rate card with hourly, day and package prices and terms
- `examples/ux-designer-rate-plan.json` - a Berlin UX designer who wants 48,000 EUR take-home and currently charges 65 EUR/h

## Workflow

### 1. Collect the numbers
Ask for: the take-home income they want per year (after tax and business costs), savings they want to put aside (pension, emergency fund), their effective tax and social contribution rate (if unknown, use the rough guide in `references/rate-math.md` and tell them to confirm with an accountant), every business cost (insurance, software, equipment, workspace, accountant, marketing, training), hours per week, vacation weeks, public holidays, sick and training days, and the share of working time that is really billable. Also ask for the current rate, typical market rates for their field and region, and an upcoming project estimate if they have one.

### 2. Run the calculator
```
python3 scripts/rate_calc.py examples/ux-designer-rate-plan.json
python3 scripts/rate_calc.py plan.json --round 10 --json
python3 scripts/rate_calc.py --self-test
```
Exit code 1 means HIGH findings, 2 means bad input.

### 3. Explain the result
Lead with the minimum rate and the quoted rate, then walk the chain from take-home to revenue so they see where the money goes. Use the billable-share table to show why 60% billable is the honest default. If the current rate is too low, show the shortfall and the billable hours it would take to close it, then give options from `references/pricing-and-raising-rates.md`: raise rates for new clients first, move to day or project pricing, cut costs, or lower the target.

### 4. Deliver
Fill `templates/rate-card.md` with the hourly, day and package prices, payment terms and the date of the next rate review.

## Example result
For `examples/ux-designer-rate-plan.json`: 48,000 EUR take-home + 7,800 EUR set-asides = 83,284 EUR profit before 33% tax; + 13,500 EUR costs and an 8% risk buffer = 105,200 EUR revenue. 214 working days at 60% billable = 1027 billable hours, so the minimum is 102.41 EUR/h: quote 105 EUR/h or 840 EUR/day. At the current 65 EUR/h, take-home would be 24,311 EUR (23,689 short), and hitting the target would need 94.5% billable time (HIGH BELOW_REQUIRED). The 120 h clinic app redesign with 20% contingency comes to 15,120 EUR instead of 9,360 EUR.

## Rules

- Tax figures are rough guides, not tax advice; tell them to confirm their rate with a local accountant.
- Never assume more than 70% billable time without evidence from their own time tracking.
- Show the formulas and inputs so they can change one assumption and re-run.
- A rate below the market can be raised; a minimum above the market needs a different offer, not just a higher number.
- Use the currency and the tax situation they give; do not mix currencies.
FILE:references/rate-math.md
# Rate Math

## The chain, step by step
1. **Needed after tax** = target take-home + set-asides (pension, emergency fund, savings goals)
2. **Profit before tax** = needed after tax / (1 - effective tax and social contribution rate)
3. **Revenue needed** = (profit before tax + business costs) / (1 - risk buffer)
4. **Working days** = 260 weekdays - vacation weeks x 5 - public holidays - sick days - training days
5. **Billable hours** = working days x hours per week / 5 x billable share
6. **Minimum rate** = revenue needed / billable hours
7. **Quoted rate** = minimum rounded up (to 5 or 10); **day rate** = quoted x hours per day
8. **Break-even rate** = business costs / (1 - buffer) / billable hours (pays the bills, pays you nothing)

Check: take-home at a rate R = (R x billable hours x (1 - buffer) - costs) x (1 - tax) - set-asides.

## Why "salary / 2080" is wrong
2080 = 52 weeks x 40 hours. A freelancer is paid for none of: vacation (20-30 days), public holidays (8-14), sick days (5-10), training (3-10), and the 30-50% of working time spent on sales, proposals, admin, invoicing and learning. A 60,000 salary also comes with employer pension and social contributions, paid leave and equipment. The usual rule of thumb, hourly rate = salary / 1000 to 1200, lands near the result of the full calculation.

## Billable share by type of work
| Situation | Realistic billable share |
|---|---|
| New freelancer, still finding clients | 35-50% |
| Mix of projects, regular clients | 50-65% |
| Long full-time contract with one client | 70-85% (but sales stop, and the gap after the contract is long) |
| Agency-style with heavy account management | 45-60% |

Measure it: track every working hour for 4-8 weeks, then use the real share.

## Typical business costs
- Health, disability and liability insurance (where self-paid)
- Pension contributions if compulsory (or put them in set-asides)
- Hardware with replacement cycle (laptop 3 years, phone 2-3 years), software subscriptions, cloud and domains
- Workspace: coworking, home office share, internet, phone
- Accountant, bank fees, payment provider fees, invoicing tool
- Marketing: website, portfolio, platforms, events, travel to clients
- Training: courses, books, conferences
- Professional memberships, licences, legal templates

## Effective tax and contribution rate (rough guide only)
The effective rate is total income tax and compulsory social contributions divided by profit. It depends on the country, region, legal form, family situation and deductions. As a first rough guess for a single person with profit around 60,000-100,000 in Europe or North America, 25-40% is common; low-tax regimes and flat-rate schemes can be much lower. Always confirm with a local accountant and replace the guess.

## Risk buffer
Covers late or unpaid invoices, gaps between clients, scope that cannot be billed and slow months. 5% for stable retainers, 10-15% for project work with new clients.

## Common mistakes
- Using gross revenue as income (taxes and costs come out later)
- Planning 100% billable hours
- Forgetting VAT/sales tax is not income (rates here are net of VAT)
- Not pricing holidays: every week off has to be paid for by the weeks worked
- Discounting the hourly rate for long projects without a guaranteed volume
FILE:references/pricing-and-raising-rates.md
# Pricing Models and Raising Rates

## Choosing a pricing model
| Model | Use when | Calculation from the minimum rate |
|---|---|---|
| Hourly | Unclear scope, support work, small changes | Quoted rate; bill in 15 or 30 minute steps |
| Day rate | Workshops, embedded work, contracts | Quoted rate x hours per day; half-day = 55-60% of a day (switching cost) |
| Project (fixed price) | Clear deliverables, you estimate well | Estimated hours x (1 + contingency) x quoted rate; list what is included and the number of revisions |
| Retainer | Ongoing work each month | Reserved hours per month x quoted rate, often 5-10% lower for guaranteed volume; unused hours expire |
| Value-based | Your work drives measurable revenue or savings | 5-20% of the first-year value, never below the project price |

Contingency for fixed prices: 10-15% for work you have done many times, 20-30% for new types of work, 30-50% with unclear requirements or many stakeholders.

## Quoting
- Quote a number, not a range; ranges get negotiated to the bottom.
- Show the price per package or deliverable, not the hours, when you price by project.
- Put payment terms on the quote: 30-50% upfront for new clients, net 14 or net 30, late fee, what happens when scope changes.
- Rates are net of VAT/sales tax; say so.

## When the minimum is below the market
Quote at least the market middle for your level. Charging less signals lower quality and leaves no room for slow months.

## When the minimum is above the market
A higher number alone will not sell. Options:
1. Specialise (industry or problem) so you compete with fewer people and can price above the general market.
2. Package outcomes and use project or value pricing.
3. Cut costs that do not bring work.
4. Raise the billable share with retainers and fewer, larger clients.
5. Lower the target for the first year and plan rate increases.

## Raising rates with existing clients
- New clients get the new rate immediately.
- Existing clients: 30-60 days notice, a date, a short reason (more experience, scope, market), no apology.
- Raise by 10-20% at a time, once a year or when you are fully booked for 3+ months.
- Offer the old rate for a prepaid block of hours or a longer retainer if you want to keep a key client.

Sample notice:
> From 1 January, my rate for new work will be 105 EUR per hour (840 EUR per day). Work already agreed stays at the current rate until it is finished. Thank you for the great collaboration this year; I look forward to the next projects.

## Signals that the rate is too low
- You are fully booked for months and nobody pushes back on price.
- You win almost every proposal.
- You cannot take time off or pay for training.
FILE:templates/rate-card.md
# Rate Card - <name>, <role>

**Valid from:** <date>  **Next review:** <date + 12 months>  **Currency:** <EUR>, prices net of VAT

## Rates
| Service | Price |
|---|---|
| Hourly rate | <105> per hour |
| Day rate (8 h) | <840> per day |
| Half day (4 h) | <480> |
| Monthly retainer (<20> h, unused hours expire) | <2,000> per month |

## Packages
| Package | Includes | Price |
|---|---|---|
| <UX audit> | <expert review of 10 key screens, prioritised report, 1 h call> | <2,400> |
| <App redesign> | <research, wireframes, UI for <n> screens, 2 revision rounds, design system> | <15,120> |

## Terms
- Payment: <40% upfront, rest on delivery>, invoices due in <14> days; late fee <x%> per month
- Scope changes: quoted separately before work starts
- Revisions: <2> rounds included, then hourly
- Cancellation: <notice period / fee>
- Travel: <outside city billed at cost + travel time at 50%>

## Behind the numbers (private, do not send)
- Minimum rate: <102.41>/h at <60>% billable (<1027> h/year)
- Break-even rate: <14.29>/h
- Target take-home: <48,000>, revenue needed: <105,200>
FILE:examples/ux-designer-rate-plan.json
{
  "name": "Deniz, freelance UX/UI designer (Berlin)",
  "currency": "EUR",
  "target_net_income": 48000,
  "set_asides": [
    {"name": "retirement", "annual": 6000},
    {"name": "emergency fund top-up", "monthly": 150}
  ],
  "tax": {"effective_rate_pct": 33},
  "business_costs": [
    {"name": "health and care insurance (self-paid)", "monthly": 520},
    {"name": "coworking desk", "monthly": 190},
    {"name": "software (Figma, Adobe, Notion)", "monthly": 95},
    {"name": "laptop and display (3-year write-off)", "annual": 1100},
    {"name": "accountant", "monthly": 110},
    {"name": "liability insurance", "annual": 280},
    {"name": "website, portfolio and domain", "annual": 240},
    {"name": "courses and conferences", "annual": 900}
  ],
  "time": {
    "hours_per_week": 40,
    "vacation_weeks": 5,
    "public_holidays_days": 10,
    "sick_days": 6,
    "training_days": 5,
    "billable_pct": 60,
    "hours_per_day": 8
  },
  "risk_buffer_pct": 8,
  "current_rate": 65,
  "market_rate": {"low": 70, "high": 110},
  "project": {"name": "Clinic booking app redesign", "estimated_hours": 120, "contingency_pct": 20}
}
FILE:scripts/rate_calc.py
#!/usr/bin/env python3
"""Freelance hourly rate calculator (Python 3 standard library only).

Works backwards from the take-home income you want to the hourly and day rate you must charge,
counting taxes, business costs, unpaid time and a risk buffer. Compares the result with your
current rate and the market, and prices a project.

Input JSON (amounts per year unless "monthly" is given):
  {"name": "...", "currency": "EUR",
   "target_net_income": 48000,                      # take-home after tax and costs
   "set_asides": [{"name": "retirement", "annual": 6000}],          (optional, after tax)
   "tax": {"effective_rate_pct": 32},               # income tax + social contributions on profit
   "business_costs": [{"name": "coworking", "monthly": 180}, {"name": "laptop", "annual": 2400}],
   "time": {"hours_per_week": 40, "vacation_weeks": 5, "public_holidays_days": 10,
            "sick_days": 6, "training_days": 5, "billable_pct": 60, "hours_per_day": 8},
   "risk_buffer_pct": 10,                           # unpaid invoices, gaps between clients
   "current_rate": 55, "market_rate": {"low": 60, "high": 95},       (optional)
   "project": {"name": "...", "estimated_hours": 120, "contingency_pct": 20}}  (optional)
Formulas:
  needed after tax   = target net + set-asides
  profit before tax  = needed after tax / (1 - tax rate)
  revenue needed     = (profit before tax + business costs) / (1 - risk buffer)
  working days       = 260 - vacation weeks x 5 - holidays - sick days - training days
  billable hours     = working days x hours per week / 5 x billable %
  minimum rate       = revenue needed / billable hours; quoted rate = minimum rounded up to
                       the next --round (default 5); project price rounded up to 10; day rate = quoted x hours per day
  break-even rate    = business costs / (1 - buffer) / billable hours (no income at all)
  net at a rate      = (rate x billable hours x (1 - buffer) - costs) x (1 - tax) - set-asides
Findings (severity):
  HIGH   NO_TAX            tax rate missing or 0
  HIGH   BELOW_BREAK_EVEN  current rate does not even cover business costs
  HIGH   BELOW_REQUIRED    current rate below the minimum rate (yearly shortfall shown)
  MEDIUM ABOVE_MARKET      minimum rate above the market high: niche, value pricing or lower target
  MEDIUM BILLABLE_HIGH     billable share above 75% of working time
  MEDIUM LONG_HOURS        more than 50 hours per week
  MEDIUM SHORT_VACATION    under 3 weeks of vacation
  LOW    UNDER_MARKET      quoted rate below the market low: you can likely charge more
  LOW    NO_BUFFER         risk buffer 0
  LOW    NO_SICK_DAYS      no sick days planned
  LOW    NO_CONTINGENCY    project quote without contingency
Usage:
  python3 rate_calc.py plan.json
  python3 rate_calc.py plan.json --round 10 --json
  python3 rate_calc.py --self-test
Exit code: 0 no HIGH findings, 1 HIGH findings, 2 bad input.
"""
import argparse
import json
import math
import sys

SEV_ORDER = {"HIGH": 0, "MEDIUM": 1, "LOW": 2}


class DataError(ValueError):
    pass


def annual(item):
    if "annual" in item:
        return float(item["annual"])
    if "monthly" in item:
        return float(item["monthly"]) * 12
    raise DataError(f"cost '{item.get('name', '?')}' needs 'annual' or 'monthly'")


def round_up(x, step):
    return math.ceil(x / step - 1e-9) * step


def calc(cfg, step=5):
    t = cfg.get("time") or {}
    hpw = float(t.get("hours_per_week", 40))
    hpd = float(t.get("hours_per_day", hpw / 5))
    billable = float(t.get("billable_pct", 60)) / 100
    vac, hol = float(t.get("vacation_weeks", 4)), float(t.get("public_holidays_days", 10))
    sick, train = float(t.get("sick_days", 5)), float(t.get("training_days", 0))
    tax = float((cfg.get("tax") or {}).get("effective_rate_pct", 0)) / 100
    buffer = float(cfg.get("risk_buffer_pct", 0)) / 100
    if "target_net_income" not in cfg:
        raise DataError("target_net_income is required")
    net = float(cfg["target_net_income"])
    if not (0 <= tax < 0.9) or not (0 <= buffer < 0.5):
        raise DataError("tax must be 0-90% and risk buffer 0-50%")
    if not (0 < billable <= 1) or hpw <= 0:
        raise DataError("billable_pct must be 1-100 and hours_per_week > 0")
    costs = [{"name": c.get("name", "cost"), "annual": annual(c)} for c in cfg.get("business_costs", [])]
    sets = [{"name": s.get("name", "set-aside"), "annual": annual(s)} for s in cfg.get("set_asides", [])]
    cost_total = sum(c["annual"] for c in costs)
    set_total = sum(s["annual"] for s in sets)
    working_days = 260 - vac * 5 - hol - sick - train
    if working_days <= 0:
        raise DataError("no working days left after vacation, holidays, sick and training days")
    avail = working_days * hpw / 5
    bill_h = avail * billable
    after_tax = net + set_total
    pre_tax = after_tax / (1 - tax)
    revenue = (pre_tax + cost_total) / (1 - buffer)
    min_rate = revenue / bill_h
    rate = round_up(min_rate, step)
    breakeven = cost_total / (1 - buffer) / bill_h

    def net_at(r, hours=bill_h):
        return (r * hours * (1 - buffer) - cost_total) * (1 - tax) - set_total

    sens = []
    for pct in (40, 50, 60, 70, 80):
        h = avail * pct / 100
        sens.append({"billable_pct": pct, "billable_hours": round(h), "min_rate": round(revenue / h, 2)})
    res = {"name": cfg.get("name", "freelancer"), "currency": cfg.get("currency", ""),
           "costs": costs, "set_asides": sets, "business_costs": round(cost_total, 2), "set_aside_total": round(set_total, 2),
           "target_net_income": net, "profit_before_tax": round(pre_tax, 2), "revenue_needed": round(revenue, 2),
           "working_days": working_days, "available_hours": round(avail, 1), "billable_hours": round(bill_h, 1),
           "billable_pct": billable * 100, "min_rate": round(min_rate, 2), "quoted_rate": rate,
           "day_rate": round_up(rate * hpd, step), "hours_per_day": hpd, "break_even_rate": round(breakeven, 2),
           "net_at_quoted": round(net_at(rate), 2), "sensitivity": sens, "findings": []}
    findings = res["findings"]

    def add(sev, code, msg):
        findings.append({"severity": sev, "code": code, "message": msg})

    cur = cfg.get("current_rate")
    cur_info = None
    if cur:
        cur = float(cur)
        hours_needed = revenue / cur
        cur_info = {"rate": cur, "net_income": round(net_at(cur), 2), "shortfall": round(net - net_at(cur), 2),
                    "billable_hours_needed": round(hours_needed), "billable_pct_needed": round(hours_needed / avail * 100, 1)}
        res["current"] = cur_info
    if tax == 0:
        add("HIGH", "NO_TAX", "no tax rate given; income tax and social contributions usually take 25-45% of profit")
    if cur_info and cur < breakeven:
        add("HIGH", "BELOW_BREAK_EVEN", f"current rate {cur:g} is below the break-even rate {breakeven:.2f}; every billed hour loses money")
    elif cur_info and cur < min_rate:
        add("HIGH", "BELOW_REQUIRED", f"current rate {cur:g} is {min_rate - cur:.2f} below the minimum {min_rate:.2f}; take-home falls {cur_info['shortfall']:,.0f} short "
            f"(you would need {cur_info['billable_hours_needed']} billable hours, {cur_info['billable_pct_needed']}% of working time)")
    m = cfg.get("market_rate") or {}
    if m.get("high") and min_rate > float(m["high"]):
        add("MEDIUM", "ABOVE_MARKET", f"minimum rate {min_rate:.2f} is above the market high {m['high']}; specialise, price by value, cut costs or lower the target")
    elif m.get("low") and rate < float(m["low"]):
        add("LOW", "UNDER_MARKET", f"quoted rate {rate:g} is below the market low {m['low']}; quote at least {m['low']}")
    if billable > 0.75:
        add("MEDIUM", "BILLABLE_HIGH", f"{billable * 100:.0f}% billable leaves too little time for sales, admin and learning; 50-70% is realistic")
    if hpw > 50:
        add("MEDIUM", "LONG_HOURS", f"{hpw:g} hours per week is not sustainable for a year")
    if vac < 3:
        add("MEDIUM", "SHORT_VACATION", f"only {vac:g} weeks of vacation planned; nobody pays you for holidays, so price them in")
    if buffer == 0:
        add("LOW", "NO_BUFFER", "no risk buffer for unpaid invoices and gaps between clients; 5-15% is common")
    if sick == 0:
        add("LOW", "NO_SICK_DAYS", "no sick days planned; budget at least 5")
    p = cfg.get("project")
    if p:
        hrs = float(p.get("estimated_hours", 0))
        cont = float(p.get("contingency_pct", 0)) / 100
        res["project"] = {"name": p.get("name", "project"), "estimated_hours": hrs, "contingency_pct": cont * 100,
                          "quoted_hours": round(hrs * (1 + cont), 1), "price": round_up(hrs * (1 + cont) * rate, 10),
                          "price_at_current": round_up(hrs * (1 + cont) * cur, 10) if cur else None}
        if cont == 0:
            add("LOW", "NO_CONTINGENCY", "project estimate has no contingency; add 15-30% for unknowns and revisions")
    findings.sort(key=lambda f: SEV_ORDER[f["severity"]])
    return res


def money(x, cur=""):
    return f"{x:,.0f} {cur}".strip() if abs(x) >= 100 else f"{x:,.2f} {cur}".strip()


def rate_fmt(x, cur=""):
    return f"{x:,.2f} {cur}".strip()


def render(r):
    c = r["currency"]
    out = [f"# Freelance rate plan: {r['name']}", "",
           f"Minimum rate {rate_fmt(r['min_rate'], c)}/h -> quote **{rate_fmt(r['quoted_rate'], c)}/h**, day rate {money(r['day_rate'], c)} ({r['hours_per_day']:g} h)",
           f"Break-even (covers costs, no income): {rate_fmt(r['break_even_rate'], c)}/h | take-home at the quoted rate: {money(r['net_at_quoted'], c)}/year", "",
           "## From take-home to revenue", "| Step | Amount |", "|---|---|",
           f"| Target take-home | {money(r['target_net_income'], c)} |",
           f"| + set-asides ({', '.join(s['name'] for s in r['set_asides']) or 'none'}) | {money(r['set_aside_total'], c)} |",
           f"| = profit before tax | {money(r['profit_before_tax'], c)} |",
           f"| + business costs | {money(r['business_costs'], c)} |",
           f"| = revenue needed (incl. risk buffer) | {money(r['revenue_needed'], c)} |", "",
           "## Time", f"{r['working_days']:g} working days, {r['available_hours']:g} working hours, {r['billable_pct']:g}% billable = **{r['billable_hours']:g} billable hours**", "",
           "| Billable share | Billable hours | Minimum rate |", "|---|---|---|"]
    for s in r["sensitivity"]:
        out.append(f"| {s['billable_pct']}% | {s['billable_hours']} | {rate_fmt(s['min_rate'], c)} |")
    out += ["", "## Business costs", "| Cost | Per year |", "|---|---|"]
    for k in r["costs"]:
        out.append(f"| {k['name']} | {money(k['annual'], c)} |")
    if r.get("current"):
        cu = r["current"]
        out += ["", "## Current rate", f"At {rate_fmt(cu['rate'], c)}/h: take-home {money(cu['net_income'], c)}/year "
                f"({'short by ' + money(cu['shortfall'], c) if cu['shortfall'] > 0 else 'target met'}); target needs {cu['billable_hours_needed']} billable hours ({cu['billable_pct_needed']}% of working time)"]
    if r.get("project"):
        p = r["project"]
        out += ["", f"## Project quote: {p['name']}", f"{p['estimated_hours']:g} h + {p['contingency_pct']:g}% contingency = {p['quoted_hours']:g} h x {rate_fmt(r['quoted_rate'], c)} -> **{money(p['price'], c)}**"
                + (f" (at the current rate: {money(p['price_at_current'], c)})" if p.get("price_at_current") else "")]
    out += ["", "## Findings"]
    if not r["findings"]:
        out.append("- none")
    for f in r["findings"]:
        out.append(f"- {f['severity']} {f['code']}: {f['message']}")
    return "\n".join(out) + "\n"


def self_test():
    tests, ok = [], 0

    def check(name, cond):
        nonlocal ok
        tests.append(name)
        print(("PASS " if cond else "FAIL ") + name)
        ok += bool(cond)

    base = {"target_net_income": 50000, "tax": {"effective_rate_pct": 30}, "business_costs": [{"name": "x", "annual": 10000}],
            "time": {"hours_per_week": 40, "vacation_weeks": 4, "public_holidays_days": 10, "sick_days": 5, "training_days": 5, "billable_pct": 60},
            "risk_buffer_pct": 10}
    r = calc(base)
    check("working days 260-20-10-5-5 = 220", r["working_days"] == 220)
    check("billable hours 220 x 8 x 60% = 1056", r["billable_hours"] == 1056)
    check("profit before tax 50000/0.7", abs(r["profit_before_tax"] - 71428.57) < 0.01)
    check("revenue (71428.57+10000)/0.9", abs(r["revenue_needed"] - 90476.19) < 0.01)
    check("minimum rate 90476.19/1056 = 85.68", abs(r["min_rate"] - 85.68) < 0.01)
    check("quoted rate rounded up to 90", r["quoted_rate"] == 90)
    check("day rate 8 x 90 = 720", r["day_rate"] == 720)
    check("break-even 10000/0.9/1056 = 10.52", abs(r["break_even_rate"] - 10.52) < 0.01)
    check("net at the minimum rate equals target", abs(((r["min_rate"] * 1056 * 0.9 - 10000) * 0.7) - 50000) < 10)
    check("clean plan has no findings", r["findings"] == [])
    check("monthly cost x 12", annual({"monthly": 150}) == 1800)
    check("set-asides raise the rate", calc({**base, "set_asides": [{"name": "pension", "annual": 7000}]})["min_rate"] > r["min_rate"])
    check("sensitivity 50% rate higher than 70%", r["sensitivity"][1]["min_rate"] > r["sensitivity"][3]["min_rate"])

    def codes(**over):
        c = json.loads(json.dumps(base))
        for k, v in over.items():
            if isinstance(v, dict) and isinstance(c.get(k), dict):
                c[k].update(v)
            else:
                c[k] = v
        return {f["code"] for f in calc(c)["findings"]}

    check("no tax HIGH", "NO_TAX" in codes(tax={"effective_rate_pct": 0}))
    check("below required HIGH", "BELOW_REQUIRED" in codes(current_rate=60))
    check("below break-even HIGH", "BELOW_BREAK_EVEN" in codes(current_rate=8))
    check("rate above market MEDIUM", "ABOVE_MARKET" in codes(market_rate={"low": 40, "high": 70}))
    check("rate under market LOW", "UNDER_MARKET" in codes(market_rate={"low": 120, "high": 160}))
    check("billable 85% MEDIUM", "BILLABLE_HIGH" in codes(time={"billable_pct": 85}))
    check("55 h/week MEDIUM", "LONG_HOURS" in codes(time={"hours_per_week": 55}))
    check("2 weeks vacation MEDIUM", "SHORT_VACATION" in codes(time={"vacation_weeks": 2}))
    check("no buffer LOW", "NO_BUFFER" in codes(risk_buffer_pct=0))
    check("no sick days LOW", "NO_SICK_DAYS" in codes(time={"sick_days": 0}))
    check("no contingency LOW", "NO_CONTINGENCY" in codes(project={"estimated_hours": 40, "contingency_pct": 0}))
    p = calc({**base, "project": {"estimated_hours": 100, "contingency_pct": 20}})["project"]
    check("project 120 h x 90 = 10800", p["quoted_hours"] == 120 and p["price"] == 10800)
    for bad, label in (({"tax": {"effective_rate_pct": 95}}, "tax 95% rejected"), ({"time": {"billable_pct": 0}}, "billable 0 rejected"),
                       ({"time": {"vacation_weeks": 60}}, "no working days rejected")):
        try:
            c = json.loads(json.dumps(base))
            for k, v in bad.items():
                c[k].update(v)
            calc(c)
            check(label, False)
        except DataError:
            check(label, True)
    print(f"{ok}/{len(tests)} passed")
    return 0 if ok == len(tests) else 1


def main():
    ap = argparse.ArgumentParser(description="Freelance hourly rate calculator")
    ap.add_argument("plan", nargs="?", help="plan JSON file")
    ap.add_argument("--round", type=float, default=5, help="round the quoted rate up to this step (default 5)")
    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.plan:
        ap.error("plan file required")
    try:
        with open(a.plan, encoding="utf-8") as fh:
            r = calc(json.load(fh), a.round)
    except (OSError, json.JSONDecodeError, DataError, ValueError, TypeError) as e:
        print(f"error: {e}", file=sys.stderr)
        return 2
    print(json.dumps(r, indent=2) if a.json else render(r), end="\n" if a.json else "")
    return 1 if any(f["severity"] == "HIGH" for f in r["findings"]) else 0


if __name__ == "__main__":
    sys.exit(main())
Personal FinancePricingCareer+2
F@f
0
Garage Sale Plan Builder (YAML)
Text

Turn a list of things to sell into a YAML garage sale plan: sorting rules, a quick-sale pricing guide with bundles, a prep timeline, table layout, sign and listing text, cash and payment setup, roles, a day-of schedule, haggling replies, safety, and a plan for unsold items.

1role: Organized, upbeat garage sale planner who helps households clear clutter and earn a fair amount in one well-run day
2task: >
3 Turn my notes about the items I want to sell, my space, and my date into a complete garage sale
4 plan as YAML: a sorting and pricing guide, a prep timeline, a layout of the selling area,
5 signs and listing text, a cash and payment setup, a day-of schedule with roles, haggling rules,
6 safety reminders, and a plan for everything that does not sell.
7
8inputs:
9 sale_date_and_hours: ${date:Saturday, 08:00 to 13:00}
10 location: ${location:driveway and open garage of a house on a quiet residential street}
...+83 more lines
YAMLPlanningPricing+2
F@f
0
Secondhand Item Resale Listing Builder (JSON)
Text

Turn notes and photo descriptions of a used item into a strict JSON resale package: honest condition grade with every defect disclosed, evidence-based quick sale, list and floor prices, a title and description, photo checklist, buyer FAQ, negotiation plan, and safe handover steps.

1{
2 "role": "Experienced secondhand marketplace seller who writes honest, fast-selling listings and prices used items from real evidence",
3 "task": "Turn my notes and photo descriptions of one used item into a complete, honest resale listing package as a single strict JSON object: condition grade, pricing with reasoning, a title and description ready for marketplaces, photo checklist, buyer FAQ, negotiation plan, and safe handover steps.",
4 "context": {
5 "item": "${item:standing desk with electric height adjustment}",
6 "brand_and_model": "${brand_model:unknown brand, about 140 x 70 cm top}",
7 "age_and_usage": "${age_usage:bought three years ago, used daily in a home office}",
8 "seller_notes": "${notes:small scratch on the front edge, one motor makes a light hum, original manual lost}",
9 "photo_descriptions": "${photos:front view, top surface close-up, control panel, legs at full height}",
10 "original_price": "${original_price:450 EUR}",
...+122 more lines
JSONEcommercePricing+2
F@f
0
Menu Food Cost and Pricing Calculator
Skill

For cafes, restaurants, bakeries, and food trucks: turns supplier prices, yields, and recipes into exact cost per portion, food cost percent on the tax-free price, contribution margin, and a suggested price, then applies menu engineering (Star, Plowhorse, Puzzle, Dog) with a tested Python calculator.

---
name: menu-food-cost-calculator
description: Costs recipes and menu items for cafes, restaurants, bakeries, food trucks, and caterers - converts purchase prices and yields into an exact cost per portion, food cost percentage on the tax-free price, contribution margin, and a suggested price at a target food cost, then classifies items with menu engineering (Star, Plowhorse, Puzzle, Dog) and recommends price, portion, and menu changes. Use when a user asks "what does this dish cost me?", "how should I price my menu?", "why is my food cost so high?", or shares recipes with supplier prices.
---

# Menu Food Cost and Pricing Calculator

You help small food businesses know what every plate really costs and price it with confidence. You work from real purchase prices and recipes, you show the math, and you think about margin in money, not only in percentages.

## Files in this skill

- `scripts/cost_menu.py` - costs every recipe from a JSON costing sheet, suggests prices, and runs menu engineering (Python 3 standard library only)
- `references/food-cost-basics.md` - yield, as-purchased versus edible cost, food cost percent, taxes, and common costing mistakes
- `references/pricing-strategies.md` - target-percent pricing, margin-based pricing, rounding, and menu engineering actions
- `templates/recipe-costing-sheet.md` - the JSON costing sheet the script reads, plus the report layout
- `examples/example-cafe-menu.md` - a worked review of a five-item cafe menu

## Workflow

### 1. Collect the inputs
Ask for or confirm:
- Currency, and whether menu prices include VAT or sales tax (and the rate).
- Target food cost percent (typical ranges are in `references/food-cost-basics.md`; default 30).
- For each ingredient: purchase price, pack size and unit, and yield (usable share after trimming, peeling, cooking loss, or spoilage).
- For each item: recipe quantities as prepared amounts, number of portions per batch, current menu price, packaging or garnish per portion, and weekly sales if known.

If something is missing, use a clearly labeled assumption (for example "yield 90 percent assumed for avocados") and list it in the report.

### 2. Build the costing sheet
Fill in `templates/recipe-costing-sheet.md` as JSON. Use units the script knows (g, kg, ml, l, oz, lb, each). If an ingredient is bought by the piece but used by weight, weigh one piece and convert; never mix dimensions.

### 3. Run the calculator
```bash
python3 scripts/cost_menu.py menu.json
python3 scripts/cost_menu.py menu.json --target 28
python3 scripts/cost_menu.py menu.json --json
```
The table shows cost per portion, menu price, net price without tax, food cost percent, contribution margin (net price minus cost), the price at the target food cost (rounded up), and the menu engineering class when weekly sales are given for every item. Errors (unknown ingredients, unit mismatches) and HIGH findings make the exit code 1.

If you cannot run the script, do the same calculation by hand, line by line, and say so.

### 4. Recommend
Use `references/pricing-strategies.md`:
1. Fix data errors first and rerun.
2. For HIGH and WARN items choose between raising the price, trimming the portion, changing an expensive ingredient, or accepting a higher percent because the money margin is strong. Name the trade-off.
3. Use the menu engineering class to decide where an item belongs on the menu and whether to promote, reprice, rework, or remove it.
4. Rerun with the proposed changes to show the before and after.

### 5. Report
Use the report layout in `templates/recipe-costing-sheet.md`, as in `examples/example-cafe-menu.md`.

## Rules
- Show the formula for at least one item so the owner can check it: cost per portion / net price x 100.
- Never treat the price at target as an instruction to lower an existing price; it is a benchmark.
- Do not give tax or legal advice; only apply the tax rate the user provides.
- Respect allergens and dietary claims when suggesting substitutions, and never suggest lowering food safety or quality standards.
- Recheck costs when supplier prices change by more than about 5 percent.
FILE:references/food-cost-basics.md
# Food cost basics

## Key terms

- **As-purchased (AP) cost**: what you pay for the pack, case, or piece.
- **Yield percent**: the usable share after trimming, peeling, deboning, cooking loss, or spoilage. Salmon fillet trimmed of skin and pin bones might yield 85 percent; whole avocados where 1 in 10 is unusable yield 90 percent when counted by the piece.
- **Edible portion (EP) cost** = AP cost per unit / (yield percent / 100). Recipes list prepared, usable quantities, so they are costed at EP cost.
- **Plate cost (cost per portion)** = sum of ingredient EP costs for the batch / portions + extras per portion (packaging, napkin, garnish, sauce cup).
- **Net price** = menu price / (1 + tax rate), when menu prices include VAT or sales tax. Food cost must be measured against the money you keep, not the tax you collect.
- **Food cost percent** = plate cost / net price x 100.
- **Contribution margin** = net price - plate cost. This is the money each sale leaves to pay labor, rent, and profit.

## Worked formula

Salmon fillet bought at 32.00 per kg with 85 percent yield:
- AP cost per g = 32.00 / 1000 = 0.032
- EP cost per g = 0.032 / 0.85 = 0.0376
- 160 g portion = 160 x 0.0376 = 6.02

## Typical food cost targets (rough guide)

| Concept | Typical food cost percent |
| --- | --- |
| Coffee and espresso drinks | 15 to 25 |
| Bakery items | 20 to 30 |
| Cafe brunch dishes | 28 to 35 |
| Casual restaurant mains | 28 to 35 |
| Steak and seafood mains | 35 to 45 |
| Pizza | 20 to 28 |
| Catering trays | 25 to 35 |

Your right target depends on labor, rent, and volume. A low-labor item can run a higher food cost percent and still be very profitable.

## Common costing mistakes

1. Forgetting small items: oil, butter for the pan, salt, garnish, sauces, and takeaway packaging. Add them or use extras_per_portion.
2. Using AP cost without yield for proteins and produce.
3. Measuring food cost against prices that include tax.
4. Costing the recipe card instead of what the kitchen actually plates (portion creep). Weigh five real portions.
5. Old supplier prices. Update the sheet when a price moves by about 5 percent or more.
6. Mixing units: an ingredient bought by the piece but used by weight needs one piece weighed.
7. Ignoring waste and staff meals; track them separately and compare actual food cost (from inventory) with this theoretical cost.

## Theoretical versus actual food cost

This skill calculates theoretical cost: what food should cost if recipes are followed. Actual food cost = (opening inventory + purchases - closing inventory) / net food sales. A gap of more than about 2 to 3 points usually means waste, portion creep, theft, or wrong prices on the sheet.
FILE:references/pricing-strategies.md
# Pricing strategies and menu engineering

## Ways to set a price

1. **Target food cost percent**: price = plate cost / target x (1 + tax rate), rounded up. Simple, and the script's "AT TARGET" column. Weak spot: cheap items end up underpriced and expensive proteins overpriced.
2. **Contribution margin**: decide the money each item must earn (for example at least 5.00 for a main), then price = (plate cost + margin) x (1 + tax rate). Better for high-cost proteins.
3. **Market check**: compare with three to five similar places nearby. Price perception matters as much as cost.
4. **Blend**: start from the target price, check the margin in money, then sanity-check against the market.

## Rounding and presentation

- Round up to the step your menu uses (0.10, 0.50, or whole numbers). Upscale menus often use whole numbers without currency signs; casual menus often end in .50 or .90.
- Avoid many small increases across the whole menu at once; raise the items with the weakest margin first.
- Keep price gaps logical: an oat milk upgrade should cover its extra cost (oat drink often costs about twice as much as dairy milk per liter).

## Menu engineering

Needs weekly sales for every item. The script uses:
- **Popularity line**: an item is popular if it sells at least 70 percent of an equal share (with 5 items, 0.7 x 20 percent = 14 percent of units sold).
- **Margin line**: the sales-weighted average contribution margin.

| Class | Popularity | Margin | What to do |
| --- | --- | --- | --- |
| Star | high | high | Keep quality and portion consistent, place it in the best menu spot, small price increases are usually safe. |
| Plowhorse | high | low | Raise price a little, trim cost (portion, garnish, supplier), or pair it with a high-margin add-on. Do not remove it. |
| Puzzle | low | high | Promote it: better menu placement, a description, staff recommendation, a photo. Check the price is not scaring guests. |
| Dog | low | low | Rework the recipe or price, or remove it, unless it serves a purpose (kids menu, dietary option, signature item). |

## Choosing a fix for a high food cost item

| Option | Good when | Risk |
| --- | --- | --- |
| Raise the price | the item is popular and the market allows it | fewer sales if the jump is large |
| Trim the portion | portions are larger than guests expect | guests notice; keep value perception |
| Swap an ingredient | a cheaper equal-quality option exists | allergen and taste changes; update the menu text |
| Accept a higher percent | the money margin is the highest on the menu | needs volume to pay off |
| Remove the item | it is a Dog with no strategic role | regulars may miss it |

Always rerun the calculator with the proposed change and show before and after.
FILE:templates/recipe-costing-sheet.md
# Recipe costing sheet (input for scripts/cost_menu.py)

Save as `menu.json`. Quantities in recipes are prepared (usable) amounts.

```json
{
  "currency": "EUR",
  "target_food_cost_pct": 30,
  "menu_price_includes_tax_pct": 10,
  "price_rounding": 0.10,
  "ingredients": [
    {"name": "flour", "price": 0.95, "per": "1 kg"},
    {"name": "butter", "price": 9.80, "per": "1 kg"},
    {"name": "eggs", "price": 3.60, "per": "12 each"},
    {"name": "blueberries", "price": 16.00, "per": "1 kg", "yield_pct": 95}
  ],
  "recipes": [
    {
      "name": "Blueberry Muffin",
      "portions": 12,
      "menu_price": 3.20,
      "sold_per_week": 90,
      "extras_per_portion": 0.06,
      "items": [["flour", "500 g"], ["butter", "180 g"], ["eggs", "3 each"], ["blueberries", "300 g"]]
    }
  ]
}
```

Field notes:
- `per`: the pack you buy, as "<amount> <unit>" (g, kg, mg, ml, cl, dl, l, oz, lb, each).
- `yield_pct`: 1 to 100, default 100.
- `menu_price_includes_tax_pct`: 0 if menu prices are shown without tax.
- `sold_per_week`: give it for every item (or none) to get menu engineering classes.
- `extras_per_portion`: packaging, napkins, garnish, sauce cups, in money.

Run: `python3 scripts/cost_menu.py menu.json [--target 30] [--json]`

---

# Menu costing report: <business> - <date>

**Target food cost:** <x>%  **Prices include tax:** <rate or no>  **Currency:** <code>
**Assumptions:** <yields, missing prices, portion weights>

## Results (before)

| Item | Cost/portion | Price | Net | Food % | Margin | At target | Class |
| --- | --- | --- | --- | --- | --- | --- | --- |

## Formula check
<one item worked out line by line>

## What needs attention
1. **<item>** - <finding>. Options: <price / portion / ingredient / accept>. Recommendation: <one>.

## Proposed changes and results (after)
<changes, then the new table or the changed rows>

## Menu engineering actions
- Stars: <items and action>
- Plowhorses: <items and action>
- Puzzles: <items and action>
- Dogs: <items and action>

## Next steps
- <weigh real portions, update supplier prices, track actual food cost monthly>
FILE:examples/example-cafe-menu.md
# Example: a five-item cafe menu

**User:** "We are a small brunch cafe. Prices include 10 percent VAT and I want about 30 percent food cost. Here are my supplier prices and recipes. Why is my margin so thin?"

The sheet has 16 ingredients and 5 items with weekly sales (avocado yield 90 percent because about 1 in 10 is unusable; salmon 85 percent after trimming).

**Command:**
```bash
python3 scripts/cost_menu.py cafe-menu.json
```

**Output (before):**
```
ITEM                      COST   PRICE     NET  FOOD%  MARGIN AT TARGET  CLASS
Avocado Toast             3.13    9.50    8.64   36.2    5.51     11.50  Star
Salmon Spinach Bowl       8.02   14.50   13.18   60.8    5.16     29.50  Puzzle
Flat White                0.72    3.80    3.45   21.0    2.73      2.70  Plowhorse
Oat Flat White            0.91    4.20    3.82   23.9    2.91      3.40  Plowhorse
Blueberry Muffin          0.79    3.20    2.91   27.2    2.12      3.00  Dog

Findings (8):
  [HIGH] Salmon Spinach Bowl: food cost 60.8% is far above the 30% target; price EUR 29.50 or cut cost 4.06 per portion
  [WARN] Avocado Toast: food cost 36.2% is above the 30% target; price at target would be EUR 11.50
  [INFO] Salmon Spinach Bowl: salmon fillet is 76% of the cost; its price or portion matters most
  [INFO] menu engineering: weighted average margin EUR 3.22, popularity line 14.0% of items sold
  [INFO] ingredient 'truffle oil' is not used in any recipe
```

---

# Menu costing report: brunch cafe - October

**Target food cost:** 30%  **Prices include tax:** 10% VAT  **Currency:** EUR
**Assumptions:** avocado yield 90%, salmon 85%, spinach 90%; extras 0.10 per dish, 0.12 per coffee (cup and lid), 0.06 per muffin.

## Formula check (Salmon Spinach Bowl, before)
- Salmon 160 g x (32.00 / 1000 / 0.85) = 6.02
- Spinach 70 g x (14.00 / 1000 / 0.90) = 1.09; egg 0.30; tomatoes 0.36; olive oil 0.15; extras 0.10
- Cost per portion = 8.02; net price = 14.50 / 1.10 = 13.18; food cost = 8.02 / 13.18 x 100 = 60.8%

## What needs attention
1. **Salmon Spinach Bowl (HIGH, Puzzle)** - 60.8% food cost; salmon is 76% of the cost. Pricing it at target (29.50) is unrealistic for a cafe. Recommendation: reduce salmon to 120 g (still a generous portion for a bowl) and raise the price to 17.50; accept about 40% food cost because the margin becomes the highest on the menu.
2. **Avocado Toast (WARN, Star)** - 36.2%. It is the best-selling dish, so a 1.00 increase to 10.50 is low risk.
3. **Flat White and Oat Flat White (Plowhorses)** - healthy percentages (21 to 24%) but small margins; do not discount. Keep the oat surcharge at 0.40: the oat drink costs 0.19 more per cup than milk.
4. **Blueberry Muffin (Dog)** - fine percentage, low margin and low sales. Try a bundle with coffee before removing it.
5. **Truffle oil** is on the sheet but in no recipe: remove it from orders or the sheet.

## Proposed changes and results (after)
Avocado Toast 10.50; Salmon Spinach Bowl 120 g salmon at 17.50. Rerun: `python3 scripts/cost_menu.py cafe-menu-revised.json`

```
ITEM                      COST   PRICE     NET  FOOD%  MARGIN AT TARGET  CLASS
Avocado Toast             3.13   10.50    9.55   32.8    6.42     11.50  Star
Salmon Spinach Bowl       6.51   17.50   15.91   40.9    9.40     23.90  Puzzle
Flat White                0.72    3.80    3.45   21.0    2.73      2.70  Plowhorse
Oat Flat White            0.91    4.20    3.82   23.9    2.91      3.40  Plowhorse
Blueberry Muffin          0.79    3.20    2.91   27.2    2.12      3.00  Dog

Findings (6):
  [WARN] Salmon Spinach Bowl: food cost 40.9% is above the 30% target; price at target would be EUR 23.90
  [INFO] menu engineering: weighted average margin EUR 3.56, popularity line 14.0% of items sold
```
Exit code 0. The remaining WARN is accepted on purpose: 9.40 margin per bowl versus 5.16 before.

## Menu engineering actions
- Stars: Avocado Toast - keep the recipe consistent, top of the brunch section.
- Plowhorses: Flat White, Oat Flat White - no discounts; suggest a pastry with every coffee.
- Puzzles: Salmon Spinach Bowl - give it a short description and staff recommendation; check sales after 4 weeks at the new price.
- Dogs: Blueberry Muffin - test a coffee + muffin bundle for 4 weeks, then decide.

## Next steps
- Weigh five real salmon portions this week to confirm the 120 g spec is followed.
- Update supplier prices monthly and rerun the sheet.
- Compare with actual food cost from inventory at month end.
FILE:scripts/cost_menu.py
#!/usr/bin/env python3
"""Cost menu items from recipes and purchase prices, and suggest menu prices.

Usage:
  python3 cost_menu.py menu.json [--target 30] [--json]
  cat menu.json | python3 cost_menu.py -

Input JSON (see templates/recipe-costing-sheet.md):
  {
    "currency": "EUR",
    "target_food_cost_pct": 30,          # optional, default 30 (or --target)
    "menu_price_includes_tax_pct": 10,   # optional; VAT/sales tax included in menu prices
    "price_rounding": 0.10,              # optional; suggested prices round UP to this step
    "ingredients": [
      {"name": "butter", "price": 9.80, "per": "1 kg", "yield_pct": 100}
    ],
    "recipes": [
      {"name": "Croissant", "portions": 12, "menu_price": 3.20, "sold_per_week": 180,
       "extras_per_portion": 0.05,       # optional: packaging, napkin, garnish
       "items": [["butter", "600 g"], ["flour", "1 kg"]]}
    ]
  }
Units: g, kg, mg, ml, cl, dl, l, oz, lb, each (also pc, pcs, piece, unit, egg).
Recipe quantities are the prepared (usable) amounts. yield_pct is the usable
share of what you buy after trimming, peeling, cooking loss or spoilage.

Per recipe: cost per portion, food cost percent of the net (tax-free) menu
price, contribution margin, suggested price at the target, and the three
biggest cost drivers. With sold_per_week on every recipe, adds a menu
engineering class (Star, Plowhorse, Puzzle, Dog).
Exit code: 0 ok, 1 errors in the data or HIGH findings, 2 usage or input error.
Standard library only.
"""
import json
import math
import re
import sys

UNITS = {  # unit -> (dimension, factor to base unit g / ml / each)
    "mg": ("mass", 0.001), "g": ("mass", 1.0), "kg": ("mass", 1000.0),
    "oz": ("mass", 28.3495), "lb": ("mass", 453.592),
    "ml": ("volume", 1.0), "cl": ("volume", 10.0), "dl": ("volume", 100.0), "l": ("volume", 1000.0),
    "each": ("count", 1.0), "pc": ("count", 1.0), "pcs": ("count", 1.0), "piece": ("count", 1.0),
    "pieces": ("count", 1.0), "unit": ("count", 1.0), "units": ("count", 1.0), "egg": ("count", 1.0), "eggs": ("count", 1.0),
}
BASE = {"mass": "g", "volume": "ml", "count": "each"}


def usage(msg):
    print(f"error: {msg}\n", file=sys.stderr)
    print(__doc__.strip().split("\n\n")[1], file=sys.stderr)
    sys.exit(2)


def parse_qty(text):
    """'600 g' -> (600.0, 'mass', 600.0 in base units)."""
    m = re.fullmatch(r"\s*(\d+(?:[.,]\d+)?)\s*([a-zA-Z]+)?\s*", str(text))
    if not m:
        raise ValueError(f"cannot read quantity {text!r}")
    qty = float(m.group(1).replace(",", "."))
    unit = (m.group(2) or "each").lower()
    if unit not in UNITS:
        raise ValueError(f"unknown unit {unit!r} in {text!r}")
    dim, factor = UNITS[unit]
    return qty, dim, qty * factor


def round_up(value, step):
    return math.ceil(round(value / step, 6)) * step


def analyze(data, target_override=None):
    errors, findings = [], []
    cur = data.get("currency", "")
    target = float(target_override or data.get("target_food_cost_pct", 30))
    tax = float(data.get("menu_price_includes_tax_pct", 0))
    step = float(data.get("price_rounding", 0.10))
    ingredients = {}
    for ing in data.get("ingredients", []):
        name = str(ing.get("name", "")).strip().lower()
        try:
            _, dim, base_qty = parse_qty(ing["per"])
            price = float(ing["price"])
        except (KeyError, ValueError, TypeError) as e:
            errors.append(f"ingredient {name or '?'}: {e}")
            continue
        y = float(ing.get("yield_pct", 100))
        if not 0 < y <= 100:
            errors.append(f"ingredient {name}: yield_pct must be between 1 and 100")
            continue
        ingredients[name] = {"dim": dim, "cost_per_base": price / base_qty / (y / 100), "yield": y, "used": False}

    results = []
    for rec in data.get("recipes", []):
        rname = rec.get("name", "?")
        portions = float(rec.get("portions", 1) or 1)
        lines, bad = [], False
        for item in rec.get("items", []):
            iname, qtext = str(item[0]).strip().lower(), item[1]
            ing = ingredients.get(iname)
            if not ing:
                errors.append(f"{rname}: unknown ingredient {iname!r} (add it to ingredients)")
                bad = True
                continue
            ing["used"] = True
            try:
                _, dim, base_qty = parse_qty(qtext)
            except ValueError as e:
                errors.append(f"{rname}: {e}")
                bad = True
                continue
            if dim != ing["dim"]:
                errors.append(f"{rname}: {iname} is bought by {BASE[ing['dim']]} but used by {BASE[dim]} ({qtext}); "
                              f"convert it (for example weigh one piece)")
                bad = True
                continue
            lines.append((iname, base_qty * ing["cost_per_base"]))
        if bad:
            continue
        batch = sum(c for _, c in lines)
        extras = float(rec.get("extras_per_portion", 0))
        cost = batch / portions + extras
        price = float(rec.get("menu_price", 0))
        net = price / (1 + tax / 100) if price else 0.0
        pct = 100 * cost / net if net else None
        suggested = round_up(cost / (target / 100) * (1 + tax / 100), step)
        drivers = sorted(lines, key=lambda x: -x[1])[:3]
        r = {"name": rname, "portions": portions, "cost_per_portion": round(cost, 3), "menu_price": price,
             "net_price": round(net, 2), "food_cost_pct": None if pct is None else round(pct, 1),
             "contribution_margin": round(net - cost, 2) if net else None,
             "suggested_price_at_target": round(suggested, 2), "sold_per_week": rec.get("sold_per_week"),
             "drivers": [{"ingredient": n, "share_pct": round(100 * c / batch, 1) if batch else 0} for n, c in drivers]}
        results.append(r)
        if pct is None:
            findings.append(("WARN", rname, f"no menu_price; suggested {cur} {suggested:.2f} at {target:g}% food cost"))
        elif pct > target + 15:
            findings.append(("HIGH", rname, f"food cost {pct:.1f}% is far above the {target:g}% target; "
                                            f"price {cur} {suggested:.2f} or cut cost {cost - net * target / 100:.2f} per portion"))
        elif pct > target + 5:
            findings.append(("WARN", rname, f"food cost {pct:.1f}% is above the {target:g}% target; "
                                            f"price at target would be {cur} {suggested:.2f}"))
        elif pct < target - 15:
            findings.append(("INFO", rname, f"food cost only {pct:.1f}%; check the recipe lists every ingredient and portion size"))
        if drivers and batch and drivers[0][1] / batch > 0.5:
            findings.append(("INFO", rname, f"{drivers[0][0]} is {100 * drivers[0][1] / batch:.0f}% of the cost; "
                                            f"its price or portion matters most"))

    sold = [r for r in results if isinstance(r["sold_per_week"], (int, float)) and r["contribution_margin"] is not None]
    if sold and len(sold) == len(results) and len(sold) >= 3:
        total = sum(r["sold_per_week"] for r in sold)
        pop_line = 0.7 / len(sold)
        avg_cm = sum(r["contribution_margin"] * r["sold_per_week"] for r in sold) / total if total else 0
        for r in sold:
            high_pop = total and r["sold_per_week"] / total >= pop_line
            high_cm = r["contribution_margin"] >= avg_cm
            r["menu_class"] = {(True, True): "Star", (True, False): "Plowhorse",
                               (False, True): "Puzzle", (False, False): "Dog"}[(bool(high_pop), high_cm)]
        findings.append(("INFO", None, f"menu engineering: weighted average margin {cur} {avg_cm:.2f}, "
                                       f"popularity line {100 * pop_line:.1f}% of items sold"))
    for name, ing in ingredients.items():
        if not ing["used"]:
            findings.append(("INFO", None, f"ingredient {name!r} is not used in any recipe"))
    return {"currency": cur, "target_pct": target, "tax_pct": tax, "recipes": results,
            "errors": errors, "findings": [{"severity": s, "recipe": n, "message": m} for s, n, m in findings]}


def main(argv):
    target, as_json, paths = None, False, []
    it = iter(argv)
    for a in it:
        if a == "--target":
            try:
                target = float(next(it, ""))
            except ValueError:
                usage("--target needs a number, for example 30")
            if not 5 <= target <= 80:
                usage("--target should be a food cost percent between 5 and 80")
        elif a == "--json":
            as_json = True
        elif a.startswith("--"):
            usage(f"unknown option {a}")
        else:
            paths.append(a)
    if len(paths) != 1:
        usage("give exactly one menu JSON file, or - for stdin")
    try:
        raw = sys.stdin.read() if paths[0] == "-" else open(paths[0], encoding="utf-8").read()
        data = json.loads(raw)
    except (OSError, ValueError) as e:
        print(f"error: cannot read menu JSON: {e}", file=sys.stderr)
        return 2
    if not data.get("recipes"):
        print("error: no recipes in the input", file=sys.stderr)
        return 2
    rep = analyze(data, target)
    if as_json:
        print(json.dumps(rep, indent=2))
    else:
        cur = rep["currency"]
        print(f"Target food cost {rep['target_pct']:g}% | prices include {rep['tax_pct']:g}% tax | currency {cur}\n")
        print(f"{'ITEM':<22} {'COST':>7} {'PRICE':>7} {'NET':>7} {'FOOD%':>6} {'MARGIN':>7} {'AT TARGET':>9}  CLASS")
        for r in rep["recipes"]:
            pct = "-" if r["food_cost_pct"] is None else f"{r['food_cost_pct']:.1f}"
            cm = "-" if r["contribution_margin"] is None else f"{r['contribution_margin']:.2f}"
            print(f"{r['name'][:22]:<22} {r['cost_per_portion']:>7.2f} {r['menu_price']:>7.2f} {r['net_price']:>7.2f} "
                  f"{pct:>6} {cm:>7} {r['suggested_price_at_target']:>9.2f}  {r.get('menu_class', '-')}")
        print("\nTop cost drivers:")
        for r in rep["recipes"]:
            print(f"  {r['name']}: " + ", ".join(f"{d['ingredient']} {d['share_pct']:g}%" for d in r["drivers"]))
        if rep["errors"]:
            print(f"\nErrors ({len(rep['errors'])}):")
            for e in rep["errors"]:
                print(f"  [ERROR] {e}")
        print(f"\nFindings ({len(rep['findings'])}):")
        order = {"HIGH": 0, "WARN": 1, "INFO": 2}
        for f in sorted(rep["findings"], key=lambda f: order[f["severity"]]):
            print(f"  [{f['severity']}] {f['recipe'] + ': ' if f['recipe'] else ''}{f['message']}")
    bad = rep["errors"] or any(f["severity"] == "HIGH" for f in rep["findings"])
    return 1 if bad else 0


if __name__ == "__main__":
    sys.exit(main(sys.argv[1:]))
BusinessPricingAnalysis+2
F@f
0
Android AI App Security Specialist Task
Text

Act as an Android AI App Security Specialist. Implement secure configurations to protect API keys, prevent misuse, and establish a sustainable pricing model for your application.

Act as an Android AI App Security Specialist. You are responsible for implementing secure configurations to protect API keys, prevent misuse, and establish a sustainable pricing model for your application.

Your tasks include:

1. **Backend Proxy Configuration:**
   - Set up a minimal, secure proxy backend using services like Railway.app, Render.com, Vercel, or Firebase Cloud Functions.
   - Create a single endpoint to receive user messages and relay them to the AI API: POST/chat.
   - Ensure the API key is securely stored on the backend and never exposed in the client application.

2. **Android App Updates:**
   - Remove all API keys from the Android app codebase.
   - Use Retrofit or Ktor to connect directly to the backend proxy endpoint (e.g., https://albaroka.com/chat).
   - Ensure no hard-coded keys exist in BuildConfig or code.

3. **Pricing Model Implementation:**
   - Prefer a subscription model via Google Play over one-time payments for sustainability.
   - Integrate with Google Play Billing Library (com.android.billingclient:billing:7.0.0).
   - Manage user quotas and premium memberships from the backend.

4. **Security and Play Compliance:**
   - Apply strict Proguard rules to obfuscate API calls, keys, and sensitive information.
   - Ensure compliance with Play Store data policies and testing phases (Internal Testing, Beta).

5. **Configuration Files and Code:**
   - Abstract API calls within a network package.
   - Align configurations with MainActivity or ViewModel structures.
   - Optimize Gradle and Proguard rule files for enhanced security and performance.

This setup ensures the privacy of your API key, prevents misuse, supports a subscription-based revenue model, and adheres to Google Play's highest standards. Ensure your backend proxy is scalable and reliable.
SecurityAndroidAPI+3
B@bariskarakaya5534
0
SaaS Payment Plan Options
Text

Generate distinct payment plan cards for a SaaS application with a highlighted selected card and the most expensive option in the center.

Act as a website designer. You are tasked with creating payment plan options at the bottom of the homepage for a SaaS application. There will be three cards displayed horizontally:

- The most expensive card will be placed in the center to draw attention.
- Each card should have a distinct color scheme, with the selected card having a highlighted border to show it's currently selected.
- Ensure the design is responsive and visually appealing across all devices.

Variables you can use:
- selectedCardColor for the border color of the selected card.
- centerCard to indicate which plan is the most expensive.

Your task is to visually convey the pricing tiers effectively and attractively to users.
MarketingPricing
A@ahmettzorlutuna
1
Student Tier
Text

Unlocking New Pricing Tiers

Create a special $1-2 student sponsorship tier with meaningful benefits that acknowledges their support while respecting their budget.
PricingStudentsAccessibility
F@f
0
Enterprise Sponsorship
Text

Unlocking New Pricing Tiers

Design enterprise-level sponsorship tiers ($500, $1000, $5000) with benefits like priority support, custom features, and brand visibility for my [project].
PricingEnterpriseTiers
F@f
0
Write Tier Descriptions
Text

Unlocking New Pricing Tiers

Write descriptions for three GitHub Sponsors tiers ($5, $25, $100) that offer increasing value and recognition to supporters.
PricingTiersDescriptions
F@f
0
Suggest Pricing Tiers
Text

Unlocking New Pricing Tiers

Suggest ideas for pricing tiers on GitHub Sponsors, including unique benefits at each level for individuals and companies.
PricingTiersBenefits
F@f
0