feat(market-research): add play.py count (saturation density)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
cd4edf2ad8
commit
36f64a4419
|
|
@ -94,6 +94,17 @@ def cmd_resolve(args):
|
||||||
res.update(parse_details(details, package))
|
res.update(parse_details(details, package))
|
||||||
print(json.dumps(res, indent=2))
|
print(json.dumps(res, indent=2))
|
||||||
|
|
||||||
|
def cmd_count(args):
|
||||||
|
html = _search_html(args.query, args.search_file)
|
||||||
|
packages = []
|
||||||
|
for pkg in ID_RE.findall(html):
|
||||||
|
if pkg not in packages:
|
||||||
|
packages.append(pkg)
|
||||||
|
ratings = [float(x) for x in STAR_RE.findall(html)]
|
||||||
|
avg = round(sum(ratings) / len(ratings), 2) if ratings else None
|
||||||
|
print(json.dumps({"query": args.query, "app_count": len(packages),
|
||||||
|
"avg_rating": avg, "top_packages": packages}, indent=2))
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
ap = argparse.ArgumentParser()
|
ap = argparse.ArgumentParser()
|
||||||
sub = ap.add_subparsers(dest="cmd", required=True)
|
sub = ap.add_subparsers(dest="cmd", required=True)
|
||||||
|
|
@ -101,13 +112,15 @@ def main():
|
||||||
pr.add_argument("query")
|
pr.add_argument("query")
|
||||||
pr.add_argument("--search-file")
|
pr.add_argument("--search-file")
|
||||||
pr.add_argument("--details-file")
|
pr.add_argument("--details-file")
|
||||||
|
pc = sub.add_parser("count")
|
||||||
|
pc.add_argument("query")
|
||||||
|
pc.add_argument("--search-file")
|
||||||
args = ap.parse_args()
|
args = ap.parse_args()
|
||||||
if args.cmd == "resolve":
|
try:
|
||||||
try:
|
{"resolve": cmd_resolve, "count": cmd_count}[args.cmd](args)
|
||||||
cmd_resolve(args)
|
except Exception as e:
|
||||||
except Exception as e:
|
print(f"ERROR: play {args.cmd} failed: {e}", file=sys.stderr)
|
||||||
print(f"ERROR: play resolve failed: {e}", file=sys.stderr)
|
sys.exit(1)
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,12 @@ def main():
|
||||||
check("last_updated", r["last_updated"] == "Jun 1, 2026")
|
check("last_updated", r["last_updated"] == "Jun 1, 2026")
|
||||||
check("developer", r["developer"] == "Focus Labs")
|
check("developer", r["developer"] == "Focus Labs")
|
||||||
|
|
||||||
|
c = run("count", "habit tracker", "--search-file", SEARCH)
|
||||||
|
check("app_count", c["app_count"] == 3)
|
||||||
|
check("avg_rating", c["avg_rating"] == 4.2) # mean(4.6,4.1,3.9)=4.2
|
||||||
|
check("top_packages has habit", "com.example.habit" in c["top_packages"])
|
||||||
|
check("top_packages distinct", len(c["top_packages"]) == len(set(c["top_packages"])))
|
||||||
|
|
||||||
sys.exit(1 if fails else 0)
|
sys.exit(1 if fails else 0)
|
||||||
|
|
||||||
main()
|
main()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue