{
  "starter": "# Course template: Copyright (c) 2026 OriginMind. All rights reserved.\nimport math\n\ndef summarize(rows, threshold=1.5):\n    \"\"\"rows: t_s, x_m, y_m, battery_pct 的字典列表。\n    至少两行；所有值有限；时间严格递增；电量在 0..100；\n    threshold 必须是正有限数，否则抛出 ValueError。\n    \"\"\"\n    # TODO 1：检查输入与阈值，错误要说明行号或字段。\n    # TODO 2：遍历相邻点，计算距离、耗时、速度与可疑区间。\n    # TODO 3：返回契约中全部指标，不要把平均分段速度当全程速率。\n    raise NotImplementedError(\"请完成自己的实现\")\n",
  "harness": "import csv, io, json, traceback\nstudent_globals = {\"__name__\": \"__student__\"}\ntry:\n    exec(compile(student_source, \"exercise.py\", \"exec\"), student_globals)\n    data = [{key: float(value) for key, value in row.items()} for row in csv.DictReader(io.StringIO(student_csv))]\n    result = student_globals[\"summarize\"](data)\n    print(json.dumps(result, ensure_ascii=False, indent=2))\nexcept Exception:\n    traceback.print_exc()\nprint(\"===ARTS_TESTS===\")\ntry:\n    import math\n    summarize = student_globals[\"summarize\"]\n    \n    def rows(t, x, y=None, battery=None):\n        y = [0]*len(t) if y is None else y\n        battery = [100]*len(t) if battery is None else battery\n        return [dict(t_s=a,x_m=b,y_m=c,battery_pct=d) for a,b,c,d in zip(t,x,y,battery)]\n    \n    cases = [\n     (\"正常往返\", rows([0,1,2,4], [0,1,1,0], [0,0,1,0], [100,99,98,97]),\n      {\"samples\":4,\"duration_s\":4,\"distance_m\":2+math.sqrt(2),\"mean_speed_mps\":(2+math.sqrt(2))/4,\"max_speed_mps\":1,\"displacement_m\":0,\"battery_drop_pp\":3}),\n     (\"静止\", rows([0,1,2], [0,0,0]), {\"distance_m\":0,\"mean_speed_mps\":0,\"max_speed_mps\":0}),\n     (\"斜线回程\", rows([0,1,2], [0,3,0], [0,4,0]), {\"distance_m\":10,\"displacement_m\":0}),\n     (\"非等间隔\", rows([0,1,3], [0,1,1]), {\"distance_m\":1,\"mean_speed_mps\":1/3}),\n     (\"负坐标\", rows([0,2], [-3,0], [-4,0]), {\"distance_m\":5,\"mean_speed_mps\":2.5}),\n     (\"电量回升\", rows([0,1], [0,1], battery=[90,92]), {\"battery_drop_pp\":-2}),\n    ]\n    count=0\n    for name, data, expected in cases:\n        result = summarize(data)\n        for key, value in expected.items():\n            assert abs(result[key]-value) <= 0.001, (name,key,result)\n        count+=1; print(\"PASS\",name)\n    jump = summarize(rows([0,1,2], [0,0,10]))\n    assert jump[\"suspicious\"] == [{\"start_s\":1,\"end_s\":2,\"speed_mps\":10}]\n    count+=1; print(\"PASS 跳变区间\")\n    assert summarize(rows([0,1],[0,1.5]))[\"suspicious\"] == []\n    count+=1; print(\"PASS 阈值等于不标记\")\n    bad_cases = [\n     (\"空输入\", [], 1.5), (\"单行\", rows([0],[0]),1.5),\n     (\"重复时间\", rows([0,0],[0,1]),1.5), (\"时间倒退\",rows([1,0],[0,1]),1.5),\n     (\"缺字段\",[{\"t_s\":0}, {\"t_s\":1}],1.5),\n     (\"NaN 坐标\",rows([0,1],[0,float(\"nan\")]),1.5),\n     (\"无穷时间\",rows([0,float(\"inf\")],[0,1]),1.5),\n     (\"字符串数值\",rows([0,1],[0,\"1\"]),1.5),\n     (\"布尔值\",rows([0,1],[0,True]),1.5),\n     (\"电量越界\",rows([0,1],[0,1],battery=[101,90]),1.5),\n     (\"零阈值\",rows([0,1],[0,1]),0), (\"负阈值\",rows([0,1],[0,1]),-1),\n     (\"NaN 阈值\",rows([0,1],[0,1]),float(\"nan\")),\n     (\"无穷阈值\",rows([0,1],[0,1]),float(\"inf\")),\n    ]\n    for name,data,threshold in bad_cases:\n        try: summarize(data,threshold)\n        except ValueError: pass\n        else: raise AssertionError(name)\n        count+=1; print(\"PASS\",name)\n    print(f\"{count}/{count} cases passed\")\nexcept Exception:\n    traceback.print_exc()\n    print(\"本次测试未全部通过，请从首个失败用例开始修复。\")\n",
  "datasets": {
    "normal": "t_s,x_m,y_m,battery_pct\n0,0,0,100\n1,1,0,99\n2,1,1,98\n4,0,0,97",
    "unequal": "t_s,x_m,y_m,battery_pct\n0,0,0,100\n1,1,0,100\n3,1,0,99",
    "jump": "t_s,x_m,y_m,battery_pct\n0,0,0,100\n1,0,0,100\n2,10,0,99",
    "stationary": "t_s,x_m,y_m,battery_pct\n0,0,0,100\n1,0,0,100\n2,0,0,99"
  }
}
