0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

函館ダークマターが揺れた1週間  —— bashita_tool誕生・補正値スナップショット・venue_correction整理・YouTube完全リニューアル —— シリーズ第8弾

0
Posted at

競馬予想システム 変革履歴レポート V6.8|bashita_tool新設・YouTube動画リニューアル・函館ダークマター検証

はじめに

71歳・独学Python・競馬予想システムを自作しています。

2018年ごろからPythonを独学で学び始め、現在はnetkeibaのスクレイピング・機械学習的な補正係数チューニング・Excel可視化・YouTubeでの予想動画配信まで一人でこなしています。本記事はその開発ログ「変革履歴レポート」のV6.8版です。

対象期間:2026年6月22日 〜 6月29日


V6.8期間 プロジェクト概要

カテゴリ 内容
py ブラッシュアップ venue_correction.csv 構造整理・save_venue_csv() 修正(No.64)
py 新規作成 bashita_tool.py 新設(09_bashita/ 配下、No.01〜12)netkeiba shutuba_past スクレイピング → Excel蓄積 + HTML馬柱出力
YouTube リニューアル 1次案(緑楕円)→ 2次案(HTML表・紺地再構築)→ 最終案(Excel生シート貼込)の3段階で確定
スナップショット機能 yosou_hikaku_v3.py No.51:[2]実行時に補正値スナップショット自動記録・バックアップ保存

🗂️ venue_correction.csv 構造整理(No.64)

▼ 背景・課題

V6.6期間のhosei_history.csv整理(239→87件)と並行して、venue_correction.csvの備考列が問題として顕在化した。函館ダークマター行の備考欄に「※MM/DD手動修正→値」が最大9回分連続で羅列されており、CSVとしての可読性・保守性が著しく低下していた。

変更履歴の正はhosei_history.csvに一元化されているにもかかわらず、venue_correction.csvが非公式の二重管理状態になっていた。

▼ 変更内容(No.64)

対象 変更前 変更後
備考列 ※MM/DD手動修正→値 の履歴を最大9件羅列 統計情報のみ残し、履歴羅列を全削除
最終更新日列 (列なし) 新設:hosei_history.csvの変更日時から自動復元・設定
save_venue_csv() 保存時に全行の最終更新日を更新していた 変更があった行のみ最終更新日を更新するよう修正
履歴管理 venue_correction.csv備考列とhosei_history.csvの二重管理 hosei_history.csvを唯一の変更履歴ストアとして確立

▼ save_venue_csv() — 変更行のみ最終更新日を更新

save_venue_csv() のポイントは「変更があった行だけ update_date を今日の日付にセットしてから保存する」設計です。呼び出し元で変更行に日付をセット済みのため、関数自体はシンプルに書き込むだけです。

def save_venue_csv(data: dict):
    """venue_correction.csv に書き込む"""
    rows = []
    for venue in VENUES:
        # ダークマター(全馬共通)
        dm = data.get((venue, 'ダークマター'),
                      {'factor': 1.0, 'sample': 0, 'tentative': '',
                       'note': '', 'update_date': ''})
        rows.append({
            '会場': venue, '属性': 'ダークマター',
            '係数': round(dm['factor'], 3),
            'サンプル数': dm['sample'],
            '暫定': dm['tentative'],
            '備考': dm['note'],
            '最終更新日': dm.get('update_date', '')  # [No.64] 変更行のみ呼び出し前にセット済み
        })
        # 騎手ランク(S/A/B/C)
        for rank in RANKS:
            key = (venue, f'ランク{rank}')
            val = data.get(key, {'factor': 1.0, 'sample': 0,
                                  'tentative': '✅暫定(N=0)',
                                  'note': 'デフォルト値', 'update_date': ''})
            rows.append({
                '会場': venue, '属性': f'ランク{rank}',
                '係数': round(val['factor'], 3),
                'サンプル数': val['sample'],
                '暫定': val['tentative'],
                '備考': val['note'],
                '最終更新日': val.get('update_date', '')  # [No.64] 変更行のみ呼び出し前にセット済み
            })
    pd.DataFrame(rows,
                 columns=['会場','属性','係数','サンプル数','暫定','備考','最終更新日']
                 ).to_csv(VENUE_CSV, index=False, encoding='utf-8-sig')

変更行への日付セットは呼び出し元で行います:

# 係数を変更した行のみ今日の日付をセット(変更なし行は既存日付を保持)
merged[(v, attr)]['update_date'] = today_str  # [No.64]
save_venue_csv(merged)

これにより「いつ・どの会場の係数を変えたか」がCSVで一目瞭然になりました。


🐴 bashita_tool.py 新設(No.01〜12)

▼ 開発背景

YouTube動画でnetkeiba馬柱ページのスクリーンショットをそのまま使用することは著作権上グレーゾーンであり、代替素材の必要性があった。V5py・V58pyがnetkeiba shutuba_pastページから5走データをスクレイピングしている実績を活かし、独自馬柱ビジュアルを生成する専用ツールとして09_bashita/配下に新設した。

またV58pyへの組み込みは「単一責務・スクリプト分離」の設計方針に反するとして、独立ツールを採用。

▼ 配置・構成

項目 内容
ファイルパス /home/yuji/競馬予想システム/09_bashita/bashita_tool.py
バージョン v1.00 No.12(V6.8期間完成版)
入力 netkeiba shutuba_past URL(URLを直接貼り付け)
出力① bashita_data.xlsx(累積型・レース単位でシート追加)
出力② {race_id}.html(レースごと・動画素材用馬柱HTML)
デスクトップランチャー 作成済み(補正値mixer.desktopを参考に同方式で作成)

▼ No.10:URLバリデーション追加

誤URL(result.html等)を貼り付けると従来は無言で終了していた。extract_race_id() に shutuba_past.html チェックを追加し、明示的なエラーメッセージを表示するよう修正:

def extract_race_id(url):
    # [No.10] shutuba_past.html 以外のURLは弾く
    # [No.11] sys.exit → None返却に変更(ループでリトライするため)
    if "shutuba_past.html" not in url:
        print("[ERROR] URLが違います")
        print("[ERROR] 正しいURL形式: https://race.netkeiba.com/race/shutuba_past.html"
              "?race_id=XXXXXXXXXXXXXX&rf=shutuba_submenu")
        return None
    m = re.search(r"race_id=(\d+)", url)
    if not m:
        print("[ERROR] URLからrace_idが取得できません")
        return None
    return m.group(1)

▼ No.11:URL入力ループ化(リトライ対応)+ No.12:バージョンバナー

従来はコマンドライン引数方式だったため、誤URLを渡すとツールを開き直す必要があった。main() をループ構造に変更し、エラー時はそのまま再入力できるようにした。あわせてNo.12で起動時バージョンバナーを追加:

VERSION = "v1.00 No.12"

def main():
    # [No.12] 起動時バージョンバナー表示
    print("=" * 50)
    print(f"  bashita_tool.py  {VERSION}")
    print("=" * 50)
    print("URLを貼り付けてEnterを押してください")
    print("終了するには 'q' を入力してください")
    print()

    # [No.11] URL入力ループ(誤URL時にリトライできる)
    while True:
        try:
            url = input("URL: ").strip()
        except (EOFError, KeyboardInterrupt):
            print("\n[INFO] 終了します")
            sys.exit(0)

        if url.lower() in ("q", "quit", "exit", ""):
            print("[INFO] 終了します")
            sys.exit(0)

        race_id = extract_race_id(url)
        if race_id is None:
            print()
            continue   # URLが不正 → 再入力へ

        soup   = fetch(url)
        horses = parse_all(soup)

        if not horses:
            print("[WARN] 馬データが取得できませんでした")
            print()
            continue   # データなし → 再入力へ

        save_excel(horses, meta, race_id)
        save_html(horses, meta, race_id)
        print("[INFO] 完了!")
        print()

sys.exit()return None に変えてループ側で制御する設計がポイントです。

▼ No.09(前No.08):休養行・走間隔バッジ表示

従来の parse_past()run_date が空(=休養)のセルを continue でスキップしていた。休養明け(鉄砲)を考察要素として可視化するため、is_restフラグを立てて保持するよう変更:

# [No.09] run_dateが空でも is_rest=True で保持(休養行として表示するため)
is_rest = not bool(run_date)

return {
    "run_date": run_date,
    ...
    "is_rest": is_rest,  # ← 追加
}

走間隔の計算と色分けバッジは _interval_badge() で実装:

def _interval_badge(days):
    """日数を受け取り間隔バッジHTMLを返す。Noneなら空文字。"""
    if days is None:
        return ""
    if days >= 90:
        return f'<span class="badge badge-teppou">鉄砲 {days}日</span>'
    if days >= 30:
        return f'<span class="badge badge-tataki">叩き {days}日</span>'
    return f'<span class="badge badge-ok">{days}日</span>'

CSSは3色で定義:

.badge-teppou { background: #e65c00; color: #fff; }  /* 鉄砲: 90日以上 */
.badge-tataki { background: #d4a017; color: #fff; }  /* 叩き: 30〜89日 */
.badge-ok     { background: #4a9;    color: #fff; }  /* 間隔良好: ~29日 */

走間隔の計算ロジックは「今回レース日 − 1走前の出走日」で算出し、休養行は is_rest=True でスキップしながら前後の実走日を遡って計算します:

for i, p in enumerate(past):
    if p.get("is_rest"):
        intervals.append(None)
        continue
    cur_dt = _to_dt(p["run_date"])
    if i == 0:
        # 1走前 → 今回レースまでの間隔
        diff_days = (today_dt - cur_dt).days
    else:
        # i走前 → (i-1)走前まで(休養行を飛ばして遡る)
        prev_dt = None
        for j in range(i - 1, -1, -1):
            if not past[j].get("is_rest"):
                prev_dt = _to_dt(past[j]["run_date"])
                break
        diff_days = (prev_dt - cur_dt).days
    intervals.append(max(diff_days, 0))

▼ No.01〜12 開発経緯まとめ

No. 分類 内容
No.01 新規 基本スクレイピング実装・shutuba_pastからの5走データ取得
No.02 改善 Excel(bashita_data.xlsx)への累積書き出し実装
No.03 改善 netkeiba DOM構造を解析し正確なパーサーに書き直し
No.04 BUGfix race_date誤取得修正(HTMLページタイトルから正確な開催日を取得)
No.05 改善 馬名取得追加・全15頭整合確認・HTML白背景化
No.06 改善 デスクトップランチャー作成(URL入力式)
No.07 BUGfix 出走情報(騎手・体重・人気・オッズ)全頭欠損修正・完成版
No.09 改善 休養行・走間隔バッジ表示(鉄砲/叩き/間隔良好の3色)
No.10 改善 URLバリデーション追加(shutuba_past.html以外はエラー表示)
No.11 改善 URL入力ループ化(リトライ対応・sys.exit→None返却)
No.12 改善 起動時バージョンバナー表示(VERSION定数・枠付き表示)

📸 yosou_hikaku_v3.py 補正値スナップショット機能(No.51)

6月22日に実装。tekichuritu_master.xlsxの的中率検証結果が、どの補正値状態のもとで行われたかを後から追跡できないという課題を解決。[2]「レース後複数一括buildモード」1実行=1補正値状態と1対1で結びつける機能。

変更 内容
変更① hosei_mixer_v1.pyをimportし、load_v58_values()/load_v5_values()/load_venue_csv()を再利用
変更② get_hosei_snapshot() / calc_hosei_hash():現在の補正値一式を取得・比較用ハッシュ計算
変更③ check_batch_hosei_state():.batch_hosei_state.jsonで[2]実行間の補正値変化を検知
バックアップ 04_hikaku/的中率推移/ にタイムスタンプ付きバックアップを自動保存

📺 YouTube動画リニューアル(6月22〜24日)

▼ 1次案→2次案→最終案 比較

1次案 2次案 最終案(確定)
フレーム 緑の楕円(四隅欠け) 紺地・四角(楕円問題解消) 紺地・四角(継承)
本文表示 HTML表(整いすぎて淡白) HTML表で順位表等を再現 Excel生シート画像を貼込
説得力 インパクトに欠ける まずまず 「本物感」が最大
評価 不採用 外枠のみ採用 ✅ 採用確定

「いいねぇ〜 これで決まり その他のExcel表もこれに準じて貼り付けていく」

▼ 技術対応:Excel行列見出しの印刷出力

LibreOfficeのCLI変換(--convert-to pdf)は sheet_view.showRowColHeaders(画面表示設定)を反映しない仕様だった。print_options.headings = True(印刷用設定)で解決:

from openpyxl import load_workbook

wb = load_workbook("yosou.xlsx")
ws = wb.active

# NG: 画面表示設定(CLI変換では反映されない)
# ws.sheet_view.showRowColHeaders = True

# OK: 印刷用設定(PDF/PNG変換時に行列見出しが出力される)
ws.print_options.headings = True

wb.save("yosou_with_headers.xlsx")

その後 LibreOffice CLI で PNG 変換:

libreoffice --headless --convert-to png yosou_with_headers.xlsx

▼ 動画制作フロー(リニューアル確定版)

Step 作業 ツール
レース資料・xlsx予想結果を用意 Yuji
xlsx生シートをPDF→PNG変換(行列見出し付き) openpyxl + LibreOffice
台本(ナレーション原稿)生成 Claude
VOICEVOXで段落ごとにwav書き出し VOICEVOX(玄野武宏 Normal)
初期スライド雛形HTMLに生シート画像を差込 Claude(HTML/CSS)
wav長さ計測→ffmpegで画像同期→mp4合成 ffmpeg
YouTube投稿 Yuji

💾 make_hikaku_batch.py 全レース完了時バックアップ(No.09)

▼ 設計上の根本的欠陥と修正

従来の設計欠陥は「バックアップ取得タイミングが更新前(プリスナップショット)」だったこと。1レースごとにバックアップしても「全36レース完了後の最終状態」は保存できない。

正しい設計:全レース完了フラグ(ng_listが空)をトリガーに1回だけバックアップ

生成バッチスクリプト内に以下のコードを埋め込む形で実装:

# [No.09] 全レース完了時(失敗なし)のみtekichuritu_masterをバックアップ
if not ng_list:
    _master = '/home/yuji/競馬予想システム/04_hikaku/的中率推移/tekichuritu_master.xlsx'
    _ts     = datetime.now().strftime('%Y%m%d_%H%M%S')
    _backup = (f'/home/yuji/競馬予想システム/04_hikaku/的中率推移/'
               f'tekichuritu_master_backup_{_ts}.xlsx')
    try:
        shutil.copy2(_master, _backup)
        print(f" 💾 tekichuritu_masterバックアップ完了: {os.path.basename(_backup)}")
    except Exception as _e:
        print(f" ⚠️  tekichuritu_masterバックアップ失敗: {_e}")

ng_list は実行中に失敗したレースを追記するリスト。if not ng_list: で全レース成功を確認してからバックアップするため「1回の[2]実行=1バックアップ」が保証される。

6/28に全36Rの一括比較検証を完了。tekichuritu_master_backup_20260628_224929.xlsx が正常に生成されたことを確認。


📺 YouTube第2回動画 制作・投稿(6月27〜28日)

▼ 6/27:一括レンダリングの構造的欠陥

複数スライドを1つのHTMLで一括レンダリングして1080px単位で機械的に切り出す手法を採用したところ、後のスライドほど切り出し位置がズレる構造的欠陥が発覚。修正サイクルを複数回繰り返し容量制限に到達、投稿未完了。

確立した作業ルール:

ルール 内容
スライドは1枚ずつ個別レンダリング 1ページ=1HTMLで個別レンダリング。1枚確認してから次へ進む
余分な資料は送らない yosou xlsx+台本txtのみ。mp4や旧サンプルの再送を省略し容量節約
先に進める前に必ず確認 バグ修正・エンコードなど重い処理の前に必ず確認を取る

▼ 6/28:確定フォーマットで完走・投稿成功

作業ルールを徹底した結果、YouTube Studio投稿に成功。


🎯 osushi_seiki_v5.py 新アルゴリズム(No.13)と出力改善(No.15)

▼ 新アルゴリズム概要(No.13 / v3.0)

旧アルゴリズムの「tekichu_scoreによる単勝/複勝/馬連の振り分け」を廃止し、「指数差×騎手ランク複合条件による複勝特化」に全面変更:

BUY : 指数差5〜10 かつ 騎手ランクS/B → 複勝購入推奨(実績71.6%)
SHOW: 指数差5〜10 かつ ランクA、または 指数差3〜5 かつ ランクS/B → 参考
SKIP: 指数差10超 / ランクC / 指数差3未満 / 少頭数 / G1見送り対象

判定ロジックは osushi_config.pycalc_osushi_scores() に分離。チューニング時は config のみ変更すればよい設計:

# osushi_seiki_v5.py(メイン)
from osushi_config import (
    SEIKI_CSV, MAX_OUTPUT_COUNT, BUDGET,
    G1_SKIP_BUDGET, calc_osushi_scores
)

# ③ スコア計算(osushi_config共通エンジン)
df_result = calc_osushi_scores(df_target)

コンソール出力では zone ごとに絵文字で視覚的に分類:

for i, r in df_result.iterrows():
    zone = r['zone']
    if zone == 'BUY':
        zone_str = '🟢BUY'
    elif zone == 'SHOW':
        zone_str = '🟡SHOW'
    else:
        zone_str = '🚫SKIP'

    print(f" {i+1:>2}{r['place_r']:<12} {r['course']:<10} "
          f"[{r['score_diff']:>5.1f}pt]  {zone_str}  {r['name_1']}")
    print(f"{r['meiken_reason']}  ({r['head_count']}頭・騎手{r['rank_1']})")

▼ xlsx出力改善(No.15)

6/27〜6/28のBUY判定5件全ハズレ(0/5)を受けて調査したところ、以下の問題が確認された:

問題 内容
騎手ランクがxlsxに出力されていない ターミナルのコンソール表示のみ・xlsxのSheet1に列なし
race_idがxlsxに出力されていない df_hikaku内に存在するのにwrite_xlsx()のheadersに未記載
的中率計算式の不一致(バグ) コンソール:h/(h+m) vs xlsx:h/n(不明含む)

修正後のSheet1列構成:

順位 / 開催場・R / コース / 馬券種 / 推奨馬 / 根拠 / 区分 / 指数差 / 頭数 / 騎手ランク

的中率計算を h/(h+m) に統一(「不明」を分母から除外):

# BUGfix: h/n(不明含む)→ h/(h+m) に統一
hit_rate = h / (h + m) if (h + m) > 0 else 0

▼ 71.6%根拠の検証

docstringに「複勝的中率71.6%(1014レース分析・116件)」と記載されていたが根拠データが見当たらなかった。calc_osushi_scores() を実際に動かして「指数差5〜10 かつ 騎手ランクS/B」に該当する116件の複勝的中率を計算した結果、約71.6%が正しいことを確認。数字は正しかった。


📊 函館ダークマター係数変更(1.000→0.636)の検証と今後の方針

▼ 検証結果(6/28時点・72R蓄積後)

期間 DM係数 複勝的中率 ◎平均誤差
〜6/22 DM=1.000期(48R) 1.000 37.5% 4.04
6/28 DM=0.636期(24R) 0.636 33.3% 4.52(悪化)
函館72R全体 36.1% 4.20

◎平均誤差とは「本命馬の予測着順(1位想定)と実際の着順のズレの平均値」。成績の良い会場では3.5以下に収まる傾向がある。
DM=1.000期の48Rも週ごとに25.0%〜41.7%と大きく波があり、24Rのサンプルでは統計的判断は困難。現時点では判断保留が妥当。

▼ 全体評価(V5 vs V58 会場別◎平均誤差)

会場 V5誤差 V58誤差 コメント
阪神 2.93 2.90 V58がV5を上回る
中山 3.49 3.46 V58がV5を上回る
東京 3.86 3.47 V58が大きく改善
京都 3.89 3.71 V58が改善
小倉 3.16 3.33 V5優位
中京 3.55 3.73 V5優位
福島 3.87 3.91 ほぼ同等
函館 3.50 4.20 V58が大幅悪化(V58固有の問題)
新潟 4.52 4.81 V5・V58ともに苦手会場

函館・新潟を除いた7会場のV58誤差平均は約3.43で、既に目標ライン3.5をクリアしている。

▼ V5 DIST_FACTORとの比較から得た知見

V5は距離(DIST_FACTOR)と馬場状態(BABA_FACTOR)しか補正していないにもかかわらず、7会場でV58と同等以上の精度を出している。

# V5py の DIST_FACTOR(距離スケーリング)
DIST_FACTOR = {
    '1200m': 0.500,
    '1400m': 0.650,
    '1600m': 0.800,
    '1800m': 0.900,
    '2000m': 1.000,  # 基準
    '2200m': 1.050,
    '2400m': 1.100,
}

この「距離スケーリング」が馬の能力を距離適性込みで正規化する根本的な効果を持つ。V58の horse_dist_correction は「馬×距離の個別補正」であり、設計思想が異なる。この差が函館・新潟での誤差拡大の一因と分析された。

▼ 今後の方針(確定)

方針 タイミング 内容
venue_correctionへ距離スケール列を追加(案A) 函館シーズン終了後 V5のDIST_FACTORに相当する距離スケーリング係数をvenue_correction.csvに追加
mixer [3] を会場別総合コントロールパネル化 同上 ダークマター・騎手ランク・距離スケールを横並びで操作できる設計に拡張
V7〜V9ロードマップ更新 設計中 距離スケール係数をvenue_correctionの列として追加する設計が確定

venue_correction.csvが「会場別の係数バンク」として育っていく構造を確立。将来のV7〜V9係数(上がり性能・コースリピーター・覚醒鮮度)も同枠組みで追加していく:

会場 | ダークマター | 騎手ランクS | 距離スケール | 上がり性能(V7) | リピーター(V8) | 鮮度(V9)
函館 |   0.636     |    ...     |    ...      |     ...       |     ...       |  ...
新潟 |   1.000     |    ...     |    ...      |     ...       |     ...       |  ...

📋 V6.8期間 改修一覧

● py系改修

No. 対象ファイル 分類 内容
No.51 yosou_hikaku_v3.py 新機能 補正値スナップショット自動記録・バックアップ保存
No.64 hosei_mixer_v1.py / venue_correction.csv 改善 備考列整理・最終更新日列新設・save_venue_csv()修正
No.09 make_hikaku_batch.py / yosou_hikaku_v3.py 新機能 全36レース完了後にtekichuritu_masterをタイムスタンプ付きバックアップ
No.13 osushi_seiki_v5.py 改善 新アルゴリズム適用(指数差×騎手ランク複合条件・複勝特化)
No.15 osushi_seiki_v5.py / osushi_kekka_hikaku_v1.py 改善・BUGfix xlsx出力改善(race_id・騎手ランク列追加)・的中率計算バグ修正

● bashita_tool.py 新設(No.01〜12)

No. 分類 内容
No.01 新規 shutuba_pastスクレイピング基本実装
No.02 改善 Excel累積書き出し実装
No.03 改善 netkeiba DOM構造解析・パーサー書き直し(15頭正常取得)
No.04 BUGfix race_date誤取得修正(HTMLページから正確な開催日を取得)
No.05 改善 馬名取得追加・全頭整合確認・HTML白背景化
No.06 改善 デスクトップランチャー作成(URL入力式)
No.07 BUGfix 出走情報(騎手・体重・人気・オッズ)全頭欠損修正・完成版
No.09 改善 休養行・走間隔バッジ(鉄砲/叩き/間隔良好の3色)
No.10 改善 URLバリデーション追加(shutuba_past.html以外はエラー表示)
No.11 改善 URL入力ループ化(リトライ対応・sys.exit→None返却)
No.12 改善 起動時バージョンバナー表示

🗺️ 次期作業予定

優先度 内容
YouTube第3回以降:制作ルール確立済み・継続
函館ダークマター係数再検証(N数蓄積後・DM=0.636の効果確認)
tekichuritu_master スナップショット機能の継続検証
venue_correctionへ距離スケール係数追加(函館シーズン終了後)

おわりに

V6.8は「bashita_tool.py」という新しい武器を手に入れた期間でした。著作権上の制約から始まったこのツールが、YouTube動画の独自素材として活きる設計になっています。

また函館・新潟問題の分析を通じて、「V5の距離スケーリングが本質的に効いている」という新たな知見が得られました。これがvenue_correctionへの距離スケール列追加という次の設計方針に直結しています。

データを積み上げながら設計を磨いていく、このサイクルが続いています。


チャンネル名:71才隠居ジジィの競馬新聞
ハッシュタグ:#競馬予想 #複勝 #函館競馬 #福島競馬 #小倉競馬

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?