From d252b66e9774496e40d7988e8ae059e67c85a3d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=91=90=ED=9B=88?= Date: Tue, 21 Jul 2026 18:44:57 +0900 Subject: [PATCH 1/2] analysis #/115 --- algorithm/scripts/comparison_test.py | 217 ++++++++++++++++++++ algorithm/scripts/diff_features.py | 108 ++++++++++ algorithm/scripts/generate_dashboard.py | 258 ++++++++++++++++++++++++ algorithm/simulator/simulator.py | 16 +- results/comparison_1784200693.json | 21 ++ results/comparison_1784620325.json | 42 ++++ results/comparison_1784624717.json | 42 ++++ results/comparison_1784624767.json | 42 ++++ results/comparison_1784625720.json | 42 ++++ results/comparison_1784625748.json | 42 ++++ results/comparison_1784626593.json | 45 +++++ results/comparison_1784626625.json | 45 +++++ results/comparison_1784626746.json | 45 +++++ results/comparison_latest.json | 45 +++++ results/dashboard_latest.html | 207 +++++++++++++++++++ 15 files changed, 1214 insertions(+), 3 deletions(-) create mode 100644 algorithm/scripts/comparison_test.py create mode 100644 algorithm/scripts/diff_features.py create mode 100644 algorithm/scripts/generate_dashboard.py create mode 100644 results/comparison_1784200693.json create mode 100644 results/comparison_1784620325.json create mode 100644 results/comparison_1784624717.json create mode 100644 results/comparison_1784624767.json create mode 100644 results/comparison_1784625720.json create mode 100644 results/comparison_1784625748.json create mode 100644 results/comparison_1784626593.json create mode 100644 results/comparison_1784626625.json create mode 100644 results/comparison_1784626746.json create mode 100644 results/comparison_latest.json create mode 100644 results/dashboard_latest.html diff --git a/algorithm/scripts/comparison_test.py b/algorithm/scripts/comparison_test.py new file mode 100644 index 0000000..1689989 --- /dev/null +++ b/algorithm/scripts/comparison_test.py @@ -0,0 +1,217 @@ + +""" +여러 feature weight 설정(버전)에 대해 시뮬레이션을 N번씩 돌리고, +결과(EvaluateSummary)를 하나의 JSON 파일로 저장한다. + +run 하나가 끝날 때마다 (전체 루프가 끝나길 기다리지 않고) 그 시점까지의 누적 결과를 +JSON + 대시보드 HTML로 즉시 로컬에 저장한다 -> 중간에 실패해도 이미 끝난 run들은 안전하게 남음. +--output 경로를 구글 드라이브 동기화 폴더 안으로 잡으면, 저장하는 순간 자동으로 클라우드에도 올라감. + +이 JSON은 apple-game-dashboard 스킬(generate_dashboard.py)의 입력으로 쓰인다. + +사용법: + python .claude/scripts/comparison_test.py + python .claude/scripts/comparison_test.py --n-games 200 + python .claude/scripts/comparison_test.py --config my_runs.json + python .claude/scripts/comparison_test.py --seed -1 # 시드 고정 없이 실행 + python .claude/scripts/comparison_test.py --output "G:\\내 드라이브\\DoSay_results\\comparison.json" +""" +import argparse +import json +import sys +import time +from pathlib import Path +import hashlib +import inspect +import subprocess +import diff_features + +sys.path.insert(0, str(Path(__file__).resolve().parent)) +from generate_dashboard import build_html # noqa: E402 + +def find_project_root(start: Path) -> Path: #simulator.simulator import Simulator의 경로를 올바르게 잡아줌 + for p in [start, *start.parents]: + if (p / "game").is_dir(): + return p + raise RuntimeError("프로젝트 루트를 찾을 수 없음 (game/ 폴더 기준)") + + +# 프로젝트 루트를 sys.path에 추가 +PROJECT_ROOT = find_project_root(Path(__file__).resolve()) +sys.path.insert(0, str(PROJECT_ROOT)) + +from algorithm.simulator.simulator import run_single # noqa: E402 +from algorithm.feature_assistance.feature_spec import FEATURES # noqa: E402 +from algorithm.simulator.simulator import DEFAULT_WEIGHTS +def _git_commit_info() -> dict: + """현재 git 커밋 해시와 '커밋 안 된 변경사항 있는지'를 확인한다. + git이 없거나 레포가 아니어도 죽지 않고 None으로 채움.""" + def run(cmd): + try: + return subprocess.check_output( + cmd, cwd=PROJECT_ROOT, stderr=subprocess.DEVNULL, text=True + ).strip() + except Exception: # noqa: BLE001 + return None + + commit = run(["git", "rev-parse", "HEAD"]) + status = run(["git", "status", "--porcelain", "feature/features.py"]) + return { + "commit": commit, + "dirty": bool(status) if status is not None else None, # features.py에 커밋 안 된 수정 있는지 + } + +def capture_feature_snapshot() -> dict: + """지금 이 순간 실제로 쓰이고 있는 feature 함수들의 소스코드를 그대로 캡처한다.""" + snapshot = {} + for spec in FEATURES: + try: + source = inspect.getsource(spec.func) + except (OSError, TypeError): + source = None # 소스를 못 읽는 경우(예: C 확장 함수)는 건너뜀 + snapshot[spec.name] = { + "default_weight": spec.weight, + "source": source, + "source_hash": hashlib.sha256(source.encode("utf-8")).hexdigest()[:12] if source else None, + } + return snapshot +# --------------------------------------------------------------------------- +# 비교하고 싶은 weight 설정(버전)을 여기에 정의한다. +# 새 feature 버전을 실험할 때마다 이 리스트에 추가하면 됨. +# weights에 없는 feature는 feature_spec.py의 기본 weight(1.0)가 적용된다. +# --------------------------------------------------------------------------- +DEFAULT_RUNS = [ + {"name": "from_simulator_default", "weights": DEFAULT_WEIGHTS}, +] + +def save_snapshot(output_data: dict, output_dir: Path, live_dashboard: bool = True) -> None: + """지금까지 끝난 run들의 누적 결과를 즉시 로컬에 저장한다 (JSON + 대시보드 HTML). + + 매 run 직후 호출되므로, 루프 중간에 어떤 run이 실패해도 그 전까지 끝난 run들은 + 이미 디스크에 안전하게 남아있다. output_dir이 구글 드라이브 동기화 폴더 안이면 + 이 write 자체가 곧 업로드 트리거가 됨 (별도 API 호출 필요 없음). + """ + output_dir.mkdir(parents=True, exist_ok=True) + + json_path = output_dir / "comparison_latest.json" + json_path.write_text(json.dumps(output_data, ensure_ascii=False, indent=2), encoding="utf-8") + + if live_dashboard: + html_path = output_dir / "dashboard_latest.html" + html_path.write_text(build_html(output_data), encoding="utf-8") + print(f" → 로컬 저장: {json_path.name}, {html_path.name}") + else: + print(f" → 로컬 저장: {json_path.name}") + + +def run_comparison( + runs: list[dict], + n_games: int, + seed: int | None = None, + output_dir: Path | None = None, + live_dashboard: bool = True, +) -> dict: #runs -> 우리가 돌릴 main algorithm, n_games (횟수) + output_dir = output_dir or (PROJECT_ROOT / "results") + results = [] + output_data = None + code_snapshot = capture_feature_snapshot() + git_info = _git_commit_info() + prev_path = output_dir / "comparison_latest.json" + if prev_path.exists(): + try: + prev_data = json.loads(prev_path.read_text(encoding="utf-8")) + fake_new = {"feature_snapshot": code_snapshot} + print("\n[저번 실행 대비 feature 코드 변경사항]") + diff_features.diff_features(prev_data, fake_new) + print() + except Exception as e: + print(f"(이전 결과와 비교 실패, 무시하고 진행: {e})") + + for i, run in enumerate(runs, 1): + print(f"[{i}/{len(runs)}] '{run['name']}' 실행 중... ({n_games} games)") + t0 = time.time() + + # 버전(run)마다 같은 시드로 리셋 -> 모든 weight 설정이 동일한 게임 보드 시퀀스를 + # 마주치게 되어 재현 가능하고 공정한 A/B 비교가 된다. + summary = run_single(run["weights"], n_games, seed=seed) + + elapsed = time.time() - t0 + print(f" 완료 ({elapsed:.1f}s) | avg_score={summary.avg_score:.2f} " + f"std={summary.std_score:.2f} clear_rate={summary.clear_rate:.2%}") + + results.append({ + "name": run["name"], + "weights": run["weights"], + "summary": { + "n_games": summary.n_games, + "max_score": summary.max_score, + "min_score": summary.min_score, + "avg_score": float(summary.avg_score), + "std_score": float(summary.std_score), + "avg_turn": float(summary.avg_turn), + "avg_time": float(summary.avg_time), + "avg_max_score_ratio": float(summary.avg_max_score_ratio), + "clear_rate": float(summary.clear_rate), + }, + }) + + # run 하나 끝날 때마다 지금까지의 누적 결과를 즉시 저장 (전체 루프 안 기다림) + output_data = { + "generated_at": time.strftime("%Y-%m-%dT%H:%M:%S"), + "n_games": n_games, + "git": git_info, + "feature_snapshot": code_snapshot, + "runs": results, + } + save_snapshot(output_data, output_dir, live_dashboard=live_dashboard) + + return output_data + + +def main(): + parser = argparse.ArgumentParser(description="Apple Game feature weight 버전 비교") + parser.add_argument("--n-games", type=int, default=20, + help="버전당 시뮬레이션 게임 수 (기본 20, 현재 성능 이슈로 크게 잡으면 오래 걸림)") + parser.add_argument("--config", type=str, default=None, + help="RUNS 리스트를 담은 JSON 파일 경로. 지정 안 하면 DEFAULT_RUNS 사용") + parser.add_argument("--output", type=str, default=None, + help="결과 저장 디렉토리 아래 최종 파일 경로. 지정 안 하면 " + "results/comparison_.json (구글 드라이브 동기화 폴더 경로도 가능)") + parser.add_argument("--seed", type=int, default=42, + help="재현성을 위한 랜덤 시드. 모든 버전이 동일 시드로 리셋되어 공정하게 비교됨 " + "(고정하고 싶지 않으면 --seed -1)") + parser.add_argument("--no-live-dashboard", action="store_true", + help="run이 끝날 때마다 대시보드 HTML을 재생성하지 않음 (기본은 매 run마다 재생성)") + args = parser.parse_args() + + if args.config: + runs = json.loads(Path(args.config).read_text(encoding="utf-8")) + else: + runs = DEFAULT_RUNS + + seed = None if args.seed < 0 else args.seed + + if args.output: + out_path = Path(args.output) + output_dir = out_path.parent + else: + output_dir = PROJECT_ROOT / "results" + out_path = output_dir / f"comparison_{int(time.time())}.json" + + output_data = run_comparison( + runs, args.n_games, seed=seed, + output_dir=output_dir, live_dashboard=not args.no_live_dashboard, + ) + + # 최종 결과를 타임스탬프 붙은 별도 파일로도 저장 + # (comparison_latest.json / dashboard_latest.html은 run마다 이미 갱신되어 있음) + out_path.parent.mkdir(parents=True, exist_ok=True) + out_path.write_text(json.dumps(output_data, ensure_ascii=False, indent=2), encoding="utf-8") + print(f"\n최종 저장 완료: {out_path}") + print(f"(중간 저장본: {output_dir / 'comparison_latest.json'}, " + f"{output_dir / 'dashboard_latest.html'})") + return out_path + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/algorithm/scripts/diff_features.py b/algorithm/scripts/diff_features.py new file mode 100644 index 0000000..0c37e7d --- /dev/null +++ b/algorithm/scripts/diff_features.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python3 +""" +comparison_test.py가 만든 두 결과 JSON을 비교해서, 그 사이에 +feature 함수 코드/weight가 정확히 뭐가 바뀌었는지 보여준다. + +git log를 뒤질 필요 없이 "예전 결과 vs 지금 결과"만 있으면 바로 확인 가능 +(각 JSON 안에 그 시점의 feature 함수 소스코드가 그대로 박혀있기 때문). + +사용법: + python diff_features.py old_comparison.json new_comparison.json +""" +import difflib +import json +import sys +from pathlib import Path + + +def load(path: str) -> dict: + return json.loads(Path(path).read_text(encoding="utf-8")) + + +def print_header(text: str): + print(f"\n{'=' * 60}\n{text}\n{'=' * 60}") + + +def diff_git(old: dict, new: dict): + old_git, new_git = old.get("git") or {}, new.get("git") or {} + if old_git.get("commit") != new_git.get("commit"): + print(f"git 커밋: {old_git.get('commit', '?')[:8]} → {new_git.get('commit', '?')[:8]}") + if old_git.get("dirty") or new_git.get("dirty"): + print("⚠️ 커밋 안 된 변경사항이 있는 상태에서 실행됨 (feature/features.py 기준) " + "— 결과가 실제 git 히스토리와 정확히 안 맞을 수 있음") + + +def diff_features(old: dict, new: dict): + old_snap = old.get("feature_snapshot", {}) + new_snap = new.get("feature_snapshot", {}) + all_names = sorted(set(old_snap) | set(new_snap)) + + added = [n for n in all_names if n not in old_snap] + removed = [n for n in all_names if n not in new_snap] + common = [n for n in all_names if n in old_snap and n in new_snap] + changed = [n for n in common if old_snap[n].get("source_hash") != new_snap[n].get("source_hash")] + unchanged = [n for n in common if n not in changed] + + if added: + print_header(f"새로 추가된 feature ({len(added)}개)") + for n in added: + print(f" + {n} (weight={new_snap[n].get('default_weight')})") + + if removed: + print_header(f"삭제된 feature ({len(removed)}개)") + for n in removed: + print(f" - {n}") + + if changed: + print_header(f"코드가 바뀐 feature ({len(changed)}개)") + for n in changed: + old_src = (old_snap[n].get("source") or "").splitlines(keepends=True) + new_src = (new_snap[n].get("source") or "").splitlines(keepends=True) + print(f"\n--- {n} ---") + diff_lines = list(difflib.unified_diff( + old_src, new_src, fromfile=f"old/{n}", tofile=f"new/{n}" + )) + if diff_lines: + print("".join(diff_lines)) + else: + print(" (소스 텍스트는 같은데 hash가 다름 — 인코딩/공백 문제일 수 있음, 확인 필요)") + + if unchanged: + print_header(f"변경 없음 ({len(unchanged)}개)") + print(" " + ", ".join(unchanged)) + + +def diff_performance(old: dict, new: dict): + old_runs = {r["name"]: r["summary"] for r in old.get("runs", [])} + new_runs = {r["name"]: r["summary"] for r in new.get("runs", [])} + common = sorted(set(old_runs) & set(new_runs)) + + if not common: + return + + print_header("성능 비교 (같은 run 이름 기준)") + print(f"{'run':<28}{'avg_score':>12}{'std_score':>12}{'clear_rate':>12}") + for name in common: + o, n = old_runs[name], new_runs[name] + d_avg = n["avg_score"] - o["avg_score"] + print(f"{name:<28}{n['avg_score']:>8.2f}({d_avg:+.2f}) " + f"{n['std_score']:>8.2f} {n['clear_rate']:>8.2%}") + + +def main(): + if len(sys.argv) != 3: + print("사용법: python diff_features.py ") + sys.exit(1) + + old, new = load(sys.argv[1]), load(sys.argv[2]) + + print(f"비교 대상: {sys.argv[1]} ({old.get('generated_at', '?')})" + f" vs {sys.argv[2]} ({new.get('generated_at', '?')})") + + diff_git(old, new) + diff_features(old, new) + diff_performance(old, new) + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/algorithm/scripts/generate_dashboard.py b/algorithm/scripts/generate_dashboard.py new file mode 100644 index 0000000..76dfde9 --- /dev/null +++ b/algorithm/scripts/generate_dashboard.py @@ -0,0 +1,258 @@ +#!/usr/bin/env python3 +""" +run_comparison.py가 만든 비교 JSON을 읽어서 +버전별(avg_score, std_score, clear_rate, avg_turn 등) 통계 대시보드 HTML을 생성한다. + +사용법: + python generate_dashboard.py [output.html] + +출력: + 단일 HTML 파일 (외부 서버 불필요, 브라우저로 바로 열면 됨) +""" +import json +import sys +from pathlib import Path + +HTML_TEMPLATE = """ + + + +Apple Game 알고리즘 비교 대시보드 + + + + +

🍎 Apple Game 알고리즘 비교 대시보드

+
+ +
+
+

평균 점수 (avg_score)

+ +
+
+

안정성: 평균 vs 표준편차

+ +
+
+

올클리어 비율 (clear_rate)

+ +
+
+

평균 턴 수 (avg_turn)

+ +
+
+ +
+

상세 수치

+
+
+ + + + +""" + + +def build_html(data: dict) -> str: + """비교 데이터(dict)를 받아 완성된 대시보드 HTML 문자열을 반환한다. + 다른 스크립트(comparison_test.py)에서 매 run 직후 즉시 재생성할 때 재사용.""" + return HTML_TEMPLATE.replace("__DATA__", json.dumps(data, ensure_ascii=False)) + + +def generate_dashboard_file(json_path: Path, out_path: Path | None = None) -> Path: + """JSON 파일 경로를 받아 대시보드 HTML 파일을 생성하고 그 경로를 반환한다.""" + if out_path is None: + out_path = json_path.with_suffix(".html") + data = json.loads(json_path.read_text(encoding="utf-8")) + out_path.write_text(build_html(data), encoding="utf-8") + return out_path + + +def main(): + if len(sys.argv) < 2: + print("사용법: python generate_dashboard.py [output.html]") + sys.exit(1) + + json_path = Path(sys.argv[1]) + if not json_path.exists(): + print(f"파일을 찾을 수 없음: {json_path}") + sys.exit(1) + + out_path = Path(sys.argv[2]) if len(sys.argv) > 2 else None + result_path = generate_dashboard_file(json_path, out_path) + + print(f"대시보드 생성 완료: {result_path}") + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/algorithm/simulator/simulator.py b/algorithm/simulator/simulator.py index 83d533b..1ee71ab 100644 --- a/algorithm/simulator/simulator.py +++ b/algorithm/simulator/simulator.py @@ -1,6 +1,9 @@ import time + +import random +import time import numpy as np from algorithm.evaluator.evaluate_result import EvaluateSummary, GameResult from algorithm.evaluator.evaluator import pick_best_action @@ -86,9 +89,16 @@ def _evaluate_summary(self, scores, turns, times, ratios, all_clear_count, n_gam clear_rate=clear_rate, weights=self.weights ) - +def run_single(weights: dict[str, float], n_games: int, seed: int | None = None) -> EvaluateSummary: + if seed is not None: + random.seed(seed) + np.random.seed(seed) + simulator = Simulator(weights=weights) + return simulator.simulate(n_games=n_games) + +DEFAULT_WEIGHTS: dict[str, float] = {"remove_nine": 9.0, "remove_the_most_grouping": 3.0} #comaprison용 변수 + if __name__ == "__main__": - simulator = Simulator(weights={"feature1": 1.0, "feature2": 0.5}) # 예시 가중치 - summary = simulator.simulate(n_games=100) + summary = run_single(weights={"feature1": 1.0, "feature2": 3.0}, n_games=100, seed=42) #feature 가중치 설저 , game 판 수 설정 , seed 설정 print(summary) \ No newline at end of file diff --git a/results/comparison_1784200693.json b/results/comparison_1784200693.json new file mode 100644 index 0000000..615768c --- /dev/null +++ b/results/comparison_1784200693.json @@ -0,0 +1,21 @@ +{ + "generated_at": "2026-07-16T20:18:16", + "n_games": 3, + "runs": [ + { + "name": "baseline_equal_weight", + "weights": {}, + "summary": { + "n_games": 3, + "max_score": 101, + "min_score": 92, + "avg_score": 97.0, + "std_score": 3.7416573867739413, + "avg_turn": 41.0, + "avg_time": 0.34664473333274753, + "avg_max_score_ratio": 0.5987654320987654, + "clear_rate": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/results/comparison_1784620325.json b/results/comparison_1784620325.json new file mode 100644 index 0000000..3975df5 --- /dev/null +++ b/results/comparison_1784620325.json @@ -0,0 +1,42 @@ +{ + "generated_at": "2026-07-21T16:52:06", + "n_games": 3, + "git": { + "commit": "f3d7bf2cea0971f4c203331cb49f578a22dedcca", + "dirty": false + }, + "feature_snapshot": { + "remove_nine": { + "default_weight": 1.0, + "source": "def feature_remove_nine(ctx: FeatureContext) -> float:\n area = ctx.board_array\n if not(area == 9).any(): #격자 안에 9가 없을시 0을 return한다\n return 0.0\n nine_count = int((area==9).sum()) #area안에 9가 있는 수의 개수\n if not _has_nine_one_pair(ctx): #9와 짝 지어지는 경우의 수가 판 내에 존재하는지\n return 0.0\n return sigmoid(nine_count, k = 0.5, x0 = 3.0) #추후 이 값을 조정하면서 k 값과 x0 값을 찾아도 됨\n", + "source_hash": "733bcbe50910" + }, + "remove_eight": { + "default_weight": 1.0, + "source": "def feature_remove_eight(ctx: FeatureContext) -> float:\n area = ctx.board_array\n if not(area == 8).any():\n return 0.0\n eight_count = int((area==8).sum()) \n if not _has_eight_pair(ctx):\n return 0.0\n return sigmoid(eight_count, k = 0.5, x0 = 3.0)\n", + "source_hash": "5cf66e82ee82" + }, + "grouping": { + "default_weight": 1.0, + "source": "def feature_remove_the_most_grouping(ctx: FeatureContext) -> float:\n \n return float((ctx.area != 0).sum()) / ctx.area.size\n", + "source_hash": "267e7f89adf9" + } + }, + "runs": [ + { + "name": "baseline_equal_weight", + "weights": {}, + "summary": { + "n_games": 3, + "max_score": 121, + "min_score": 91, + "avg_score": 101.66666666666667, + "std_score": 13.695092389449425, + "avg_turn": 43.0, + "avg_time": 0.24298810000012358, + "avg_max_score_ratio": 0.6275720164609054, + "clear_rate": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/results/comparison_1784624717.json b/results/comparison_1784624717.json new file mode 100644 index 0000000..740bf55 --- /dev/null +++ b/results/comparison_1784624717.json @@ -0,0 +1,42 @@ +{ + "generated_at": "2026-07-21T18:05:18", + "n_games": 3, + "git": { + "commit": "f3d7bf2cea0971f4c203331cb49f578a22dedcca", + "dirty": false + }, + "feature_snapshot": { + "remove_nine": { + "default_weight": 1.0, + "source": "def feature_remove_nine(ctx: FeatureContext) -> float:\n area = ctx.board_array\n if not(area == 9).any(): #격자 안에 9가 없을시 0을 return한다\n return 0.0\n nine_count = int((area==9).sum()) #area안에 9가 있는 수의 개수\n if not _has_nine_one_pair(ctx): #9와 짝 지어지는 경우의 수가 판 내에 존재하는지\n return 0.0\n return sigmoid(nine_count, k = 0.5, x0 = 3.0) #추후 이 값을 조정하면서 k 값과 x0 값을 찾아도 됨\n", + "source_hash": "733bcbe50910" + }, + "remove_eight": { + "default_weight": 1.0, + "source": "def feature_remove_eight(ctx: FeatureContext) -> float:\n area = ctx.board_array\n if not(area == 8).any():\n return 0.0\n eight_count = int((area==8).sum()) \n if not _has_eight_pair(ctx):\n return 0.0\n return sigmoid(eight_count, k = 0.5, x0 = 3.0)\n", + "source_hash": "5cf66e82ee82" + }, + "grouping": { + "default_weight": 1.0, + "source": "def feature_remove_the_most_grouping(ctx: FeatureContext) -> float:\n \n return float((ctx.area != 0).sum()) / ctx.area.size\n", + "source_hash": "267e7f89adf9" + } + }, + "runs": [ + { + "name": "baseline_equal_weight", + "weights": {}, + "summary": { + "n_games": 3, + "max_score": 121, + "min_score": 98, + "avg_score": 109.33333333333333, + "std_score": 9.392668535736913, + "avg_turn": 44.666666666666664, + "avg_time": 0.30774080000082904, + "avg_max_score_ratio": 0.6748971193415638, + "clear_rate": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/results/comparison_1784624767.json b/results/comparison_1784624767.json new file mode 100644 index 0000000..11bd60a --- /dev/null +++ b/results/comparison_1784624767.json @@ -0,0 +1,42 @@ +{ + "generated_at": "2026-07-21T18:06:07", + "n_games": 3, + "git": { + "commit": "f3d7bf2cea0971f4c203331cb49f578a22dedcca", + "dirty": false + }, + "feature_snapshot": { + "remove_nine": { + "default_weight": 1.0, + "source": "def feature_remove_nine(ctx: FeatureContext) -> float:\n area = ctx.board_array\n if not(area == 9).any(): #격자 안에 9가 없을시 0을 return한다\n return 0.0\n nine_count = int((area==9).sum()) #area안에 9가 있는 수의 개수\n if not _has_nine_one_pair(ctx): #9와 짝 지어지는 경우의 수가 판 내에 존재하는지\n return 0.0\n return sigmoid(nine_count, k = 0.5, x0 = 3.0) #추후 이 값을 조정하면서 k 값과 x0 값을 찾아도 됨\n", + "source_hash": "733bcbe50910" + }, + "remove_eight": { + "default_weight": 1.0, + "source": "def feature_remove_eight(ctx: FeatureContext) -> float:\n area = ctx.board_array\n if not(area == 8).any():\n return 0.0\n eight_count = int((area==8).sum()) \n if not _has_eight_pair(ctx):\n return 0.0\n return sigmoid(eight_count, k = 0.5, x0 = 3.0)\n", + "source_hash": "5cf66e82ee82" + }, + "grouping": { + "default_weight": 1.0, + "source": "def feature_remove_the_most_grouping(ctx: FeatureContext) -> float:\n \n return float((ctx.area != 0).sum()) / ctx.area.size\n", + "source_hash": "267e7f89adf9" + } + }, + "runs": [ + { + "name": "baseline_equal_weight", + "weights": {}, + "summary": { + "n_games": 3, + "max_score": 116, + "min_score": 97, + "avg_score": 105.66666666666667, + "std_score": 7.845734863959881, + "avg_turn": 43.0, + "avg_time": 0.1971430333336078, + "avg_max_score_ratio": 0.6522633744855967, + "clear_rate": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/results/comparison_1784625720.json b/results/comparison_1784625720.json new file mode 100644 index 0000000..eccaa67 --- /dev/null +++ b/results/comparison_1784625720.json @@ -0,0 +1,42 @@ +{ + "generated_at": "2026-07-21T18:22:01", + "n_games": 3, + "git": { + "commit": "f3d7bf2cea0971f4c203331cb49f578a22dedcca", + "dirty": false + }, + "feature_snapshot": { + "remove_nine": { + "default_weight": 1.0, + "source": "def feature_remove_nine(ctx: FeatureContext) -> float:\n area = ctx.board_array\n if not(area == 9).any(): #격자 안에 9가 없을시 0을 return한다\n return 0.0\n nine_count = int((area==9).sum()) #area안에 9가 있는 수의 개수\n if not _has_nine_one_pair(ctx): #9와 짝 지어지는 경우의 수가 판 내에 존재하는지\n return 0.0\n return sigmoid(nine_count, k = 0.5, x0 = 3.0) #추후 이 값을 조정하면서 k 값과 x0 값을 찾아도 됨\n", + "source_hash": "733bcbe50910" + }, + "remove_eight": { + "default_weight": 1.0, + "source": "def feature_remove_eight(ctx: FeatureContext) -> float:\n area = ctx.board_array\n if not(area == 8).any():\n return 0.0\n eight_count = int((area==8).sum()) \n if not _has_eight_pair(ctx):\n return 0.0\n return sigmoid(eight_count, k = 0.5, x0 = 3.0)\n", + "source_hash": "5cf66e82ee82" + }, + "grouping": { + "default_weight": 1.0, + "source": "def feature_remove_the_most_grouping(ctx: FeatureContext) -> float:\n \n return float((ctx.area != 0).sum()) / ctx.area.size\n", + "source_hash": "267e7f89adf9" + } + }, + "runs": [ + { + "name": "baseline_equal_weight", + "weights": {}, + "summary": { + "n_games": 3, + "max_score": 102, + "min_score": 87, + "avg_score": 96.33333333333333, + "std_score": 6.649979114420002, + "avg_turn": 41.333333333333336, + "avg_time": 0.2337479333327792, + "avg_max_score_ratio": 0.5946502057613169, + "clear_rate": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/results/comparison_1784625748.json b/results/comparison_1784625748.json new file mode 100644 index 0000000..b8c0ac0 --- /dev/null +++ b/results/comparison_1784625748.json @@ -0,0 +1,42 @@ +{ + "generated_at": "2026-07-21T18:22:29", + "n_games": 3, + "git": { + "commit": "f3d7bf2cea0971f4c203331cb49f578a22dedcca", + "dirty": false + }, + "feature_snapshot": { + "remove_nine": { + "default_weight": 1.0, + "source": "def feature_remove_nine(ctx: FeatureContext) -> float:\n area = ctx.board_array\n if not(area == 9).any(): #격자 안에 9가 없을시 0을 return한다\n return 0.0\n nine_count = int((area==9).sum()) #area안에 9가 있는 수의 개수\n if not _has_nine_one_pair(ctx): #9와 짝 지어지는 경우의 수가 판 내에 존재하는지\n return 0.0\n return sigmoid(nine_count, k = 0.5, x0 = 3.0) #추후 이 값을 조정하면서 k 값과 x0 값을 찾아도 됨\n", + "source_hash": "733bcbe50910" + }, + "remove_eight": { + "default_weight": 1.0, + "source": "def feature_remove_eight(ctx: FeatureContext) -> float:\n area = ctx.board_array\n if not(area == 8).any():\n return 0.0\n eight_count = int((area==8).sum()) \n if not _has_eight_pair(ctx):\n return 0.0\n return sigmoid(eight_count, k = 0.5, x0 = 3.0)\n", + "source_hash": "5cf66e82ee82" + }, + "grouping": { + "default_weight": 1.0, + "source": "def feature_remove_the_most_grouping(ctx: FeatureContext) -> float:\n \n return float((ctx.area != 0).sum()) / ctx.area.size\n", + "source_hash": "267e7f89adf9" + } + }, + "runs": [ + { + "name": "baseline_equal_weight", + "weights": {}, + "summary": { + "n_games": 3, + "max_score": 122, + "min_score": 82, + "avg_score": 104.33333333333333, + "std_score": 16.659998666133067, + "avg_turn": 43.333333333333336, + "avg_time": 0.22396220000033887, + "avg_max_score_ratio": 0.6440329218106996, + "clear_rate": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/results/comparison_1784626593.json b/results/comparison_1784626593.json new file mode 100644 index 0000000..0f4b8c9 --- /dev/null +++ b/results/comparison_1784626593.json @@ -0,0 +1,45 @@ +{ + "generated_at": "2026-07-21T18:36:34", + "n_games": 3, + "git": { + "commit": "f3d7bf2cea0971f4c203331cb49f578a22dedcca", + "dirty": false + }, + "feature_snapshot": { + "remove_nine": { + "default_weight": 1.0, + "source": "def feature_remove_nine(ctx: FeatureContext) -> float:\n area = ctx.board_array\n if not(area == 9).any(): #격자 안에 9가 없을시 0을 return한다\n return 0.0\n nine_count = int((area==9).sum()) #area안에 9가 있는 수의 개수\n if not _has_nine_one_pair(ctx): #9와 짝 지어지는 경우의 수가 판 내에 존재하는지\n return 0.0\n return sigmoid(nine_count, k = 0.5, x0 = 3.0) #추후 이 값을 조정하면서 k 값과 x0 값을 찾아도 됨\n", + "source_hash": "733bcbe50910" + }, + "remove_eight": { + "default_weight": 1.0, + "source": "def feature_remove_eight(ctx: FeatureContext) -> float:\n area = ctx.board_array\n if not(area == 8).any():\n return 0.0\n eight_count = int((area==8).sum()) \n if not _has_eight_pair(ctx):\n return 0.0\n return sigmoid(eight_count, k = 0.5, x0 = 3.0)\n", + "source_hash": "5cf66e82ee82" + }, + "grouping": { + "default_weight": 1.0, + "source": "def feature_remove_the_most_grouping(ctx: FeatureContext) -> float:\n \n return float((ctx.area != 0).sum()) / ctx.area.size\n", + "source_hash": "267e7f89adf9" + } + }, + "runs": [ + { + "name": "from_simulator_default", + "weights": { + "remove_nine": 3.0, + "remove_the_most_grouping": 3.0 + }, + "summary": { + "n_games": 3, + "max_score": 126, + "min_score": 84, + "avg_score": 102.66666666666667, + "std_score": 17.46106780494506, + "avg_turn": 42.0, + "avg_time": 0.22505826666626186, + "avg_max_score_ratio": 0.6337448559670782, + "clear_rate": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/results/comparison_1784626625.json b/results/comparison_1784626625.json new file mode 100644 index 0000000..e106697 --- /dev/null +++ b/results/comparison_1784626625.json @@ -0,0 +1,45 @@ +{ + "generated_at": "2026-07-21T18:37:06", + "n_games": 3, + "git": { + "commit": "f3d7bf2cea0971f4c203331cb49f578a22dedcca", + "dirty": false + }, + "feature_snapshot": { + "remove_nine": { + "default_weight": 1.0, + "source": "def feature_remove_nine(ctx: FeatureContext) -> float:\n area = ctx.board_array\n if not(area == 9).any(): #격자 안에 9가 없을시 0을 return한다\n return 0.0\n nine_count = int((area==9).sum()) #area안에 9가 있는 수의 개수\n if not _has_nine_one_pair(ctx): #9와 짝 지어지는 경우의 수가 판 내에 존재하는지\n return 0.0\n return sigmoid(nine_count, k = 0.5, x0 = 3.0) #추후 이 값을 조정하면서 k 값과 x0 값을 찾아도 됨\n", + "source_hash": "733bcbe50910" + }, + "remove_eight": { + "default_weight": 1.0, + "source": "def feature_remove_eight(ctx: FeatureContext) -> float:\n area = ctx.board_array\n if not(area == 8).any():\n return 0.0\n eight_count = int((area==8).sum()) \n if not _has_eight_pair(ctx):\n return 0.0\n return sigmoid(eight_count, k = 0.5, x0 = 3.0)\n", + "source_hash": "5cf66e82ee82" + }, + "grouping": { + "default_weight": 1.0, + "source": "def feature_remove_the_most_grouping(ctx: FeatureContext) -> float:\n \n return float((ctx.area != 0).sum()) / ctx.area.size\n", + "source_hash": "267e7f89adf9" + } + }, + "runs": [ + { + "name": "from_simulator_default", + "weights": { + "remove_nine": 9.0, + "remove_the_most_grouping": 3.0 + }, + "summary": { + "n_games": 3, + "max_score": 103, + "min_score": 92, + "avg_score": 96.33333333333333, + "std_score": 4.784233364802441, + "avg_turn": 40.666666666666664, + "avg_time": 0.2282038666671724, + "avg_max_score_ratio": 0.5946502057613169, + "clear_rate": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/results/comparison_1784626746.json b/results/comparison_1784626746.json new file mode 100644 index 0000000..b7b82f9 --- /dev/null +++ b/results/comparison_1784626746.json @@ -0,0 +1,45 @@ +{ + "generated_at": "2026-07-21T18:39:07", + "n_games": 3, + "git": { + "commit": "f3d7bf2cea0971f4c203331cb49f578a22dedcca", + "dirty": false + }, + "feature_snapshot": { + "remove_nine": { + "default_weight": 1.0, + "source": "def feature_remove_nine(ctx: FeatureContext) -> float:\n area = ctx.board_array\n if not(area == 7).any(): #격자 안에 9가 없을시 0을 return한다\n return 0.0\n nine_count = int((area==9).sum()) #area안에 9가 있는 수의 개수\n if not _has_nine_one_pair(ctx): #9와 짝 지어지는 경우의 수가 판 내에 존재하는지\n return 0.0\n return sigmoid(nine_count, k = 0.5, x0 = 3.0) #추후 이 값을 조정하면서 k 값과 x0 값을 찾아도 됨\n", + "source_hash": "ebcd207c4a1f" + }, + "remove_eight": { + "default_weight": 1.0, + "source": "def feature_remove_eight(ctx: FeatureContext) -> float:\n area = ctx.board_array\n if not(area == 8).any():\n return 0.0\n eight_count = int((area==8).sum()) \n if not _has_eight_pair(ctx):\n return 0.0\n return sigmoid(eight_count, k = 0.5, x0 = 3.0)\n", + "source_hash": "5cf66e82ee82" + }, + "grouping": { + "default_weight": 1.0, + "source": "def feature_remove_the_most_grouping(ctx: FeatureContext) -> float:\n \n return float((ctx.area != 0).sum()) / ctx.area.size\n", + "source_hash": "267e7f89adf9" + } + }, + "runs": [ + { + "name": "from_simulator_default", + "weights": { + "remove_nine": 9.0, + "remove_the_most_grouping": 3.0 + }, + "summary": { + "n_games": 3, + "max_score": 118, + "min_score": 89, + "avg_score": 99.66666666666667, + "std_score": 13.021349989749739, + "avg_turn": 42.0, + "avg_time": 0.2482827333321135, + "avg_max_score_ratio": 0.6152263374485597, + "clear_rate": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/results/comparison_latest.json b/results/comparison_latest.json new file mode 100644 index 0000000..b7b82f9 --- /dev/null +++ b/results/comparison_latest.json @@ -0,0 +1,45 @@ +{ + "generated_at": "2026-07-21T18:39:07", + "n_games": 3, + "git": { + "commit": "f3d7bf2cea0971f4c203331cb49f578a22dedcca", + "dirty": false + }, + "feature_snapshot": { + "remove_nine": { + "default_weight": 1.0, + "source": "def feature_remove_nine(ctx: FeatureContext) -> float:\n area = ctx.board_array\n if not(area == 7).any(): #격자 안에 9가 없을시 0을 return한다\n return 0.0\n nine_count = int((area==9).sum()) #area안에 9가 있는 수의 개수\n if not _has_nine_one_pair(ctx): #9와 짝 지어지는 경우의 수가 판 내에 존재하는지\n return 0.0\n return sigmoid(nine_count, k = 0.5, x0 = 3.0) #추후 이 값을 조정하면서 k 값과 x0 값을 찾아도 됨\n", + "source_hash": "ebcd207c4a1f" + }, + "remove_eight": { + "default_weight": 1.0, + "source": "def feature_remove_eight(ctx: FeatureContext) -> float:\n area = ctx.board_array\n if not(area == 8).any():\n return 0.0\n eight_count = int((area==8).sum()) \n if not _has_eight_pair(ctx):\n return 0.0\n return sigmoid(eight_count, k = 0.5, x0 = 3.0)\n", + "source_hash": "5cf66e82ee82" + }, + "grouping": { + "default_weight": 1.0, + "source": "def feature_remove_the_most_grouping(ctx: FeatureContext) -> float:\n \n return float((ctx.area != 0).sum()) / ctx.area.size\n", + "source_hash": "267e7f89adf9" + } + }, + "runs": [ + { + "name": "from_simulator_default", + "weights": { + "remove_nine": 9.0, + "remove_the_most_grouping": 3.0 + }, + "summary": { + "n_games": 3, + "max_score": 118, + "min_score": 89, + "avg_score": 99.66666666666667, + "std_score": 13.021349989749739, + "avg_turn": 42.0, + "avg_time": 0.2482827333321135, + "avg_max_score_ratio": 0.6152263374485597, + "clear_rate": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/results/dashboard_latest.html b/results/dashboard_latest.html new file mode 100644 index 0000000..2113dae --- /dev/null +++ b/results/dashboard_latest.html @@ -0,0 +1,207 @@ + + + + +Apple Game 알고리즘 비교 대시보드 + + + + +

🍎 Apple Game 알고리즘 비교 대시보드

+
+ +
+
+

평균 점수 (avg_score)

+ +
+
+

안정성: 평균 vs 표준편차

+ +
+
+

올클리어 비율 (clear_rate)

+ +
+
+

평균 턴 수 (avg_turn)

+ +
+
+ +
+

상세 수치

+
+
+ + + + From 04316c9a011ef0b76bb4d3cb1e0e4e1d38433f87 Mon Sep 17 00:00:00 2001 From: flowba104 Date: Wed, 22 Jul 2026 17:41:42 +0900 Subject: [PATCH 2/2] analysis #/118 --- algorithm/feature/features.py | 2 +- algorithm/scripts/check_changes.py | 0 results/check.json | 45 ++++++++++++++++++++++++++++++ results/comparison_1784709248.json | 45 ++++++++++++++++++++++++++++++ results/comparison_latest.json | 22 +++++++-------- results/dashboard_latest.html | 2 +- results/snap_A.json | 45 ++++++++++++++++++++++++++++++ 7 files changed, 148 insertions(+), 13 deletions(-) create mode 100644 algorithm/scripts/check_changes.py create mode 100644 results/check.json create mode 100644 results/comparison_1784709248.json create mode 100644 results/snap_A.json diff --git a/algorithm/feature/features.py b/algorithm/feature/features.py index 42475cf..8f5b578 100644 --- a/algorithm/feature/features.py +++ b/algorithm/feature/features.py @@ -9,7 +9,7 @@ def feature_remove_nine(ctx: FeatureContext) -> float: nine_count = int((area==9).sum()) #area안에 9가 있는 수의 개수 if not _has_nine_one_pair(ctx): #9와 짝 지어지는 경우의 수가 판 내에 존재하는지 return 0.0 - return sigmoid(nine_count, k = 0.5, x0 = 3.0) #추후 이 값을 조정하면서 k 값과 x0 값을 찾아도 됨 + return sigmoid(nine_count, k = 1.2, x0 = 3.0) #추후 이 값을 조정하면서 k 값과 x0 값을 찾아도 됨 def feature_remove_eight(ctx: FeatureContext) -> float: area = ctx.board_array diff --git a/algorithm/scripts/check_changes.py b/algorithm/scripts/check_changes.py new file mode 100644 index 0000000..e69de29 diff --git a/results/check.json b/results/check.json new file mode 100644 index 0000000..bd003a5 --- /dev/null +++ b/results/check.json @@ -0,0 +1,45 @@ +{ + "generated_at": "2026-07-22T16:55:00", + "n_games": 3, + "git": { + "commit": "d252b66e9774496e40d7988e8ae059e67c85a3d5", + "dirty": false + }, + "feature_snapshot": { + "remove_nine": { + "default_weight": 1.0, + "source": "def feature_remove_nine(ctx: FeatureContext) -> float:\n area = ctx.board_array\n if not(area == 9).any(): #격자 안에 9가 없을시 0을 return한다\n return 0.0\n nine_count = int((area==9).sum()) #area안에 9가 있는 수의 개수\n if not _has_nine_one_pair(ctx): #9와 짝 지어지는 경우의 수가 판 내에 존재하는지\n return 0.0\n return sigmoid(nine_count, k = 0.9, x0 = 3.0) #추후 이 값을 조정하면서 k 값과 x0 값을 찾아도 됨\n", + "source_hash": "5a322efdd644" + }, + "remove_eight": { + "default_weight": 1.0, + "source": "def feature_remove_eight(ctx: FeatureContext) -> float:\n area = ctx.board_array\n if not(area == 8).any():\n return 0.0\n eight_count = int((area==8).sum()) \n if not _has_eight_pair(ctx):\n return 0.0\n return sigmoid(eight_count, k = 0.5, x0 = 3.0)\n", + "source_hash": "5cf66e82ee82" + }, + "grouping": { + "default_weight": 1.0, + "source": "def feature_remove_the_most_grouping(ctx: FeatureContext) -> float:\n \n return float((ctx.area != 0).sum()) / ctx.area.size\n", + "source_hash": "267e7f89adf9" + } + }, + "runs": [ + { + "name": "from_simulator_default", + "weights": { + "remove_nine": 9.0, + "remove_the_most_grouping": 3.0 + }, + "summary": { + "n_games": 3, + "max_score": 111, + "min_score": 99, + "avg_score": 103.0, + "std_score": 5.656854249492381, + "avg_turn": 42.333333333333336, + "avg_time": 0.2432788333389908, + "avg_max_score_ratio": 0.6358024691358025, + "clear_rate": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/results/comparison_1784709248.json b/results/comparison_1784709248.json new file mode 100644 index 0000000..eab6161 --- /dev/null +++ b/results/comparison_1784709248.json @@ -0,0 +1,45 @@ +{ + "generated_at": "2026-07-22T17:34:10", + "n_games": 3, + "git": { + "commit": "d252b66e9774496e40d7988e8ae059e67c85a3d5", + "dirty": false + }, + "feature_snapshot": { + "remove_nine": { + "default_weight": 1.0, + "source": "def feature_remove_nine(ctx: FeatureContext) -> float:\n area = ctx.board_array\n if not(area == 9).any(): #격자 안에 9가 없을시 0을 return한다\n return 0.0\n nine_count = int((area==9).sum()) #area안에 9가 있는 수의 개수\n if not _has_nine_one_pair(ctx): #9와 짝 지어지는 경우의 수가 판 내에 존재하는지\n return 0.0\n return sigmoid(nine_count, k = 1.2, x0 = 3.0) #추후 이 값을 조정하면서 k 값과 x0 값을 찾아도 됨\n", + "source_hash": "01f1b7084066" + }, + "remove_eight": { + "default_weight": 1.0, + "source": "def feature_remove_eight(ctx: FeatureContext) -> float:\n area = ctx.board_array\n if not(area == 8).any():\n return 0.0\n eight_count = int((area==8).sum()) \n if not _has_eight_pair(ctx):\n return 0.0\n return sigmoid(eight_count, k = 0.5, x0 = 3.0)\n", + "source_hash": "5cf66e82ee82" + }, + "grouping": { + "default_weight": 1.0, + "source": "def feature_remove_the_most_grouping(ctx: FeatureContext) -> float:\n \n return float((ctx.area != 0).sum()) / ctx.area.size\n", + "source_hash": "267e7f89adf9" + } + }, + "runs": [ + { + "name": "from_simulator_default", + "weights": { + "remove_nine": 9.0, + "remove_the_most_grouping": 3.0 + }, + "summary": { + "n_games": 3, + "max_score": 112, + "min_score": 107, + "avg_score": 109.66666666666667, + "std_score": 2.0548046676563256, + "avg_turn": 47.0, + "avg_time": 0.4688831667105357, + "avg_max_score_ratio": 0.6769547325102879, + "clear_rate": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/results/comparison_latest.json b/results/comparison_latest.json index b7b82f9..eab6161 100644 --- a/results/comparison_latest.json +++ b/results/comparison_latest.json @@ -1,15 +1,15 @@ { - "generated_at": "2026-07-21T18:39:07", + "generated_at": "2026-07-22T17:34:10", "n_games": 3, "git": { - "commit": "f3d7bf2cea0971f4c203331cb49f578a22dedcca", + "commit": "d252b66e9774496e40d7988e8ae059e67c85a3d5", "dirty": false }, "feature_snapshot": { "remove_nine": { "default_weight": 1.0, - "source": "def feature_remove_nine(ctx: FeatureContext) -> float:\n area = ctx.board_array\n if not(area == 7).any(): #격자 안에 9가 없을시 0을 return한다\n return 0.0\n nine_count = int((area==9).sum()) #area안에 9가 있는 수의 개수\n if not _has_nine_one_pair(ctx): #9와 짝 지어지는 경우의 수가 판 내에 존재하는지\n return 0.0\n return sigmoid(nine_count, k = 0.5, x0 = 3.0) #추후 이 값을 조정하면서 k 값과 x0 값을 찾아도 됨\n", - "source_hash": "ebcd207c4a1f" + "source": "def feature_remove_nine(ctx: FeatureContext) -> float:\n area = ctx.board_array\n if not(area == 9).any(): #격자 안에 9가 없을시 0을 return한다\n return 0.0\n nine_count = int((area==9).sum()) #area안에 9가 있는 수의 개수\n if not _has_nine_one_pair(ctx): #9와 짝 지어지는 경우의 수가 판 내에 존재하는지\n return 0.0\n return sigmoid(nine_count, k = 1.2, x0 = 3.0) #추후 이 값을 조정하면서 k 값과 x0 값을 찾아도 됨\n", + "source_hash": "01f1b7084066" }, "remove_eight": { "default_weight": 1.0, @@ -31,13 +31,13 @@ }, "summary": { "n_games": 3, - "max_score": 118, - "min_score": 89, - "avg_score": 99.66666666666667, - "std_score": 13.021349989749739, - "avg_turn": 42.0, - "avg_time": 0.2482827333321135, - "avg_max_score_ratio": 0.6152263374485597, + "max_score": 112, + "min_score": 107, + "avg_score": 109.66666666666667, + "std_score": 2.0548046676563256, + "avg_turn": 47.0, + "avg_time": 0.4688831667105357, + "avg_max_score_ratio": 0.6769547325102879, "clear_rate": 0.0 } } diff --git a/results/dashboard_latest.html b/results/dashboard_latest.html index 2113dae..ffa0500 100644 --- a/results/dashboard_latest.html +++ b/results/dashboard_latest.html @@ -75,7 +75,7 @@

상세 수치