6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

MATLABで競艇の解析を始めよう(選手データを見てみよう)

Posted at

MATLABでボートレースを解析する8番目くらいの記事です。

 時間が空いたら、去年に何のプログラムを作ったのかすっかり忘れてしまった。。
とりあえず 2019 年のデータも揃ったし、ボートの選手データでも見る方法をやってみましょう。

みんな大好きモーターボートファン手帳を読み込もう。

 蒲郡のタオル売り場とか、児島のガァーコの部屋とかに置いてありますよね。

DSC_0016.JPG

 ウェブサイトにデータもあるので、ダウンロードしてみましょう。
 https://www.boatrace.jp/owpc/pc/extra/data/download.html

 今やほとんど見かけない LZH ですが、ついでに展開しておきましょう。

MATLABで読み込んでみよう。

 たまには Text Analytics Toolbox を使わないで、System コマンドで読んでみよう。
DOS の FIND コマンドを MATLAB から呼べばテキストで取れます。

fname = 'fan1910.txt';
[~,cmdout] = system(['find /c /v "" < ', fname]);
n = str2double(cmdout);

Person = table('Size',[n,44],...
    'VariableTypes',{'double','string','string','string','string',...
                     'string','double','double','double','double',...
                     'double','string','double','double','double',...
                     'double','double','double','double','double',...
                     'double','double','double','double',...
                     'double','double','double','double',...
                     'double','double','double','double',...
                     'double','double','double','double',...
                     'double','double','double','double',...
                     'double','double','double','double'},...
    'VariableNames',{'NameNo','Name','NameKana','Area','Class',...
                     'Era','Born','MF','Age','Height',...
                     'Weight','Blood','WinRate','DoubleWinRate','Win',...
                     'DoubleWin','NumRun','NumFinal','NumFinalWin','StartTiming',...
                     'NumEntry1','DWR1','ST1','SR1',...
                     'NumEntry2','DWR2','ST2','SR2',...
                     'NumEntry3','DWR3','ST3','SR3',...
                     'NumEntry4','DWR4','ST4','SR4',...
                     'NumEntry5','DWR5','ST5','SR5',...
                     'NumEntry6','DWR6','ST6','SR6'});
                 
fid = fopen(fname);
for x = 1:n
    txt = fgetl(fid);
    Person{x,1} = str2double(txt(1:4));
    Person{x,2} = erase(string(txt(5:12)),' ');
    Person{x,3} = erase(string(txt(13:27)),' ');
    Person{x,4} = string(txt(28:29));
    Person{x,5} = string(txt(30:31));
    Person{x,6} = string(txt(32));
    Person{x,7} = str2double(txt(33:38));
    Person{x,8} = str2double(txt(39));
    Person{x,9} = str2double(txt(40:41));
    Person{x,10} = str2double(txt(42:44));
    Person{x,11} = str2double(txt(45:46));
    Person{x,12} = string(txt(47:48));
    Person{x,13} = str2double(txt(49:52))/100;
    Person{x,14} = str2double(txt(53:56))/10;
    Person{x,15} = str2double(txt(57:59));
    Person{x,16} = str2double(txt(60:62));
    Person{x,17} = str2double(txt(63:65));
    Person{x,18} = str2double(txt(66:67));
    Person{x,19} = str2double(txt(68:69));
    Person{x,20} = str2double(txt(70:72))/100;    
    Person{x,21} = str2double(txt(73:75));    
    Person{x,22} = str2double(txt(76:79))/10;    
    Person{x,23} = str2double(txt(80:82))/100;    
    Person{x,24} = str2double(txt(83:85))/100;    
    Person{x,25} = str2double(txt(86:88));    
    Person{x,26} = str2double(txt(89:92))/10;    
    Person{x,27} = str2double(txt(93:95))/100;    
    Person{x,28} = str2double(txt(96:98))/100;    
    Person{x,29} = str2double(txt(99:101));    
    Person{x,30} = str2double(txt(102:105))/10;    
    Person{x,31} = str2double(txt(106:108))/100;    
    Person{x,32} = str2double(txt(109:111))/100;    
    Person{x,33} = str2double(txt(112:114));    
    Person{x,34} = str2double(txt(115:118))/10;    
    Person{x,35} = str2double(txt(119:121))/100;    
    Person{x,36} = str2double(txt(122:124))/100;    
    Person{x,37} = str2double(txt(125:127));    
    Person{x,38} = str2double(txt(128:131))/10;    
    Person{x,39} = str2double(txt(132:134))/100;    
    Person{x,40} = str2double(txt(135:137))/100;    
    Person{x,41} = str2double(txt(138:140));    
    Person{x,42} = str2double(txt(141:144))/10;    
    Person{x,43} = str2double(txt(145:147))/100;    
    Person{x,44} = str2double(txt(148:150))/100;    
end
fid = fclose(fid);

・・・面倒なので44項目でやめた。。

多分143項目あったので、あと99項目も同じようにすれば読めます(省略)。

[項目一覧]
https://www.boatrace.jp/owpc/pc/extra/data/layout.html

試しに何か表示して確認してみよう。

血液型

figure(1)
histogram(categorical(Person.Blood))

blood.png

選手にはA型が多い。(要らない情報)

身長

figure(1)
histogram(categorical(Person.Height))

height.png

165cm くらいが多い。(要らない情報・・・)

ファン手帳で勝てたら苦労しないので、別データで解析しよう。

 ということで、、
 選手データはレース結果から取れそう。あと、ファン手帳は 5月から10月のデータを元に計算してるけど、MATLAB ならその辺は自在ですね。とりあえず 2019年全部でやってみましょう。

 ここから下準備3連発。

ダウンロードしよう。

何個か前の記事で実施したダウンロードプログラムなんですが、どこでやったか忘れたので再掲しますね。
スクリプトを実行しておきましょう。

boat_save.m
% 自動でごっそりダウンロードシステム
%% こんな感じの URL 先を保存しよう。
% http://www1.mbrace.or.jp/od2/K/201904/k190404.lzh
% http://www1.mbrace.or.jp/od2/B/201904/b190404.lzh

since = "20190101";
to = "20191231";
for ix = datenum(since,'yyyymmdd'):datenum(to,'yyyymmdd')
    if exist(['K',datestr(ix,'yymmdd'),'.TXT'],'file') ~= 2
        url = "http://www1.mbrace.or.jp/od2/K/"+datestr(ix,'yyyymm')+"/k"+datestr(ix,'yymmdd')+".lzh";
        web(url,'-browser')
    end
    if exist(['B',datestr(ix,'yymmdd'),'.TXT'],'file') ~= 2
        url = "http://www1.mbrace.or.jp/od2/B/"+datestr(ix,'yyyymm')+"/b"+datestr(ix,'yymmdd')+".lzh";
        web(url,'-browser')
    end
end

%% ダウンロードしたもの(lzh)を C:\work\boat に展開
dl = [getenv('USERPROFILE'),'\Downloads\'];
for ix = datenum(since,'yyyymmdd'):datenum(to,'yyyymmdd')
    if exist(['K',datestr(ix,'yymmdd'),'.TXT'],'file') ~= 2
        zipname = ['k',datestr(ix,'yymmdd'),'.lzh'];
        dos(['"C:\Program Files (x86)\Lhaplus\Lhaplus.exe" /o:C:\work\boat ',dl,zipname,' &']);
    end
    if exist(['B',datestr(ix,'yymmdd'),'.TXT'],'file') ~= 2
        zipname = ['b',datestr(ix,'yymmdd'),'.lzh'];
        dos(['"C:\Program Files (x86)\Lhaplus\Lhaplus.exe" /o:C:\work\boat ',dl,zipname,' &']);
    end
end

Lhaplus が入ってて、ネットワークに繋がってれば自動ダウンロードが動くはず!

ダウンロードしたファイルをMATLABで読み込もう。

 これもどっかでやったけど再掲。こんな関数を作って保存しておきましょう。

boat_allresult_scan.m
function T_Result =  boat_allresult_scan(since,to)
addpath('C:\work\boat')
tic
%% テーブルを作ろう
T_Result = table;
for n = datenum(since,'YYYYmmDD'):datenum(to,'YYYYmmDD')
    
    %% レース結果の読み込み
    fname = ['K',datestr(n,'YYmmDD'),'.TXT'];
    fid = fopen(fname);
    S = textscan(fid,'%s','delimiter','\n');
    C = S{1};
    fclose(fid);
    
    %% BGN/ENDを探す
    KBGN = find(contains(C,'BGN'));
    KEND = find(contains(C,'END'));
    
    %% BGN-END Loop
    for BEloop = 1:length(KBGN)
        
        %% BGN-ENDで切り取る
        res = C(KBGN(BEloop)+1:KEND(BEloop)-1);
        res(cellfun(@isempty,res)) = [];
        
        % 場所
        place = res{1}(1:3);
        place(place == 12288) = [];
        
        % 開催日
        ymd = datestr(n,'YYYYmmDD');
        start_idx = startsWith(res,'着');
        x = find(start_idx)-1;
        end_x = [x(2:end)-1;length(res)];
        
        % ここからレースのループ
        for Rloop = 1:length(x)
            % レース番号
            race = res(x(Rloop):end_x(Rloop));
            R = regexp(race{1},'\d+R','match');
            R = str2double(R{1}(1:end-1));
            
            for fn = 1:6
                fin{fn} = race{fn+3}(1:2);
                fin_boatnum{fn} = str2double(race{fn+3}(5));
                fin_name{fn} = str2double(race{fn+3}(7:10));
                fin_motor{fn} = str2double(race{fn+3}(20:22));
                fin_boat{fn} = str2double(race{fn+3}(25:27));                
                fin_extime{fn} = str2double(race{fn+3}(30:33));
                fin_entry{fn} = str2double(race{fn+3}(37));
                fin_timing{fn} = str2double(race{fn+3}(42:45));
                if isnan(race{fn+3}(51))
                    fin_time{fn} = NaN;
                else
                    fin_time{fn} = str2double(race{fn+3}(51))*60+str2double(race{fn+3}(53:54))+str2double(race{fn+3}(56))*0.1;
                end
            end            
            
            ix = contains(race,'単勝');
            if any(ix)
                z = regexp(race(ix),'\d+','match');
                if length(z{1}) == 1   % 誰も買ってない場合の特払い70円 (2019/01/02 の 620行目の若松2Rとか)
                    win = NaN;
                    win_d = str2double(z{1}{1});
                elseif isempty(z{1})  % 2013/01/14 の 児島7R に単勝が書いてない
                    win = NaN;
                    win_d = NaN;
                else
                    win = str2double(z{1}{1});
                    win_d = str2double(z{1}{2});
                end
            end
            
            ix = contains(race,'複勝');
            if any(ix)
                z = regexp(race(ix),'\d+','match');
                if length(z{1}) == 1    % 特払い70円
                    show = [NaN NaN];
                    show_d = [70 70];
                elseif length(z{1}) < 4    % 2019/8/1 の 383行目みたいに、複勝なのに1個しか書いてないのが結構ある。
                    show = [NaN NaN];
                    show_d = [NaN NaN];
                else
                    show = [str2double(z{1}{1}),str2double(z{1}{3})];
                    show_d = [str2double(z{1}{2}),str2double(z{1}{4})];
                end
            end
            
            ix = contains(race,'2連単');
            if any(ix)
                z = regexp(race(ix),'\d+','match');
                if length(z{1}) <= 1   % 不成立
                    exacta = NaN;
                    exacta_d = NaN;
                elseif length(z{1}) == 2   % 特払い70円
                    exacta = NaN;
                    exacta_d = str2double(z{1}{2});
                else
                    exacta = str2double([z{1}{2},z{1}{3}]);
                    exacta_d = str2double(z{1}{4});
                end
            end
            
            ix = contains(race,'2連複');
            if any(ix)
                z = regexp(race(ix),'\d+','match');
                if length(z{1}) <= 1   % 不成立
                    quinella = NaN;
                    quinella_d = NaN;
                elseif length(z{1}) == 2   % 特払い70円
                    quinella = NaN;
                    quinella_d = str2double(z{1}{2});
                else
                    quinella = str2double([z{1}{2},z{1}{3}]);
                    quinella_d = str2double(z{1}{4});
                end
            end
            
            ix = contains(race,'拡連複');
            ix = ix | circshift(ix,1) | circshift(ix,2);
            rx = race(ix);
            if any(ix)
                z = regexp(rx,'\d+','match');
                if length(z{1}) <= 1   % 不成立
                    wide = [NaN NaN NaN];
                    wide_d = [NaN NaN NaN];
                elseif ~all(ismember(rx{2}(1:3),'123456-'))  % フォーマットがおかしい (2013/04/04 三国9Rとか)
                    wide = [NaN NaN NaN];
                    wide_d = [NaN NaN NaN];
                else
                    wide = [str2double([z{1}{1},z{1}{2}]) str2double([z{2}{1},z{2}{2}]) str2double([z{3}{1},z{3}{2}])];
                    wide_d = [str2double(z{1}{3}) str2double(z{2}{3}) str2double(z{3}{3})];
                end
            end
            
            ix = contains(race,'3連単');
            if any(ix)
                z = regexp(race(ix),'\d+','match');
                if length(z{1}) <= 1   % 不成立
                    trifecta = NaN;
                    trifecta_d = NaN;
                elseif length(z{1}) == 2   % 特払い70円
                    trifecta = NaN;
                    trifecta_d = str2double(z{1}{2});
                else
                    trifecta = str2double([z{1}{2},z{1}{3},z{1}{4}]);
                    trifecta_d = str2double(z{1}{5});
                end
            end
            
            ix = contains(race,'3連複');
            if any(ix)
                z = regexp(race(ix),'\d+','match');
                if length(z{1}) <= 1   % 不成立
                    trio = NaN;
                    trio_d = NaN;
                elseif length(z{1}) == 2   % 特払い70円
                    trio = NaN;
                    trio_d = str2double(z{1}{2});
                else
                    trio = str2double([z{1}{2},z{1}{3},z{1}{4}]);
                    trio_d = str2double(z{1}{5});
                end
            end
            T_Result(end+1,:) = {place,ymd,R,...
                fin,cell2mat(fin_boatnum),cell2mat(fin_name),cell2mat(fin_motor),cell2mat(fin_boat),cell2mat(fin_extime),cell2mat(fin_entry),cell2mat(fin_timing),...
                win,win_d,show,show_d,exacta,exacta_d,quinella,quinella_d,wide,wide_d,trifecta,trifecta_d,trio,trio_d};
        end
    end
    stc = toc;
    disp([datestr(n,'yyyymmdd'),':  ',num2str(stc),'秒経過'])
end

T_Result.Properties.VariableNames = {'Place','YYYYMMDD','R',...
    'fin','fin_boatnum','fin_name','fin_motor','fin_boat','fin_extime','fin_entry','fin_timing',...
    'win','win_d','show','show_d','exacta','exacta_d','quinella','quinella_d','wide','wide_d','trifecta','trifecta_d','trio','trio_d'};

% 数種類に分類できる項目はカテゴリカル。
T_Result.win = categorical(T_Result.win);
T_Result.show = categorical(T_Result.show);
T_Result.quinella = categorical(T_Result.quinella);
T_Result.wide = categorical(T_Result.wide);
T_Result.exacta = categorical(T_Result.exacta);
T_Result.trifecta = categorical(T_Result.trifecta);
T_Result.trio = categorical(T_Result.trio);
toc

関数を実行しよう。

 とりあえず 2019 年全部でやってみよう。

TR_2019 = boat_allresult_scan("20190101","20191231");

下準備ができたら、解析しよう。

 変数は Person と TR_2019 があればいいね。

人が多すぎるので、A1 に絞ろう。

簡単簡単。

A1 = Person(Person.Class == "A1",:)

↓↓↓

A1 =

  325×44 table

    NameNo       Name           NameKana        Area     Class    Era       Born       MF    Age    Height    Weight    Blood    WinRate    DoubleWinRate    Win    DoubleWin    NumRun    NumFinal    NumFinalWin    StartTiming    NumEntry1    DWR1    ST1     SR1    NumEntry2    DWR2    ST2     SR2    NumEntry3    DWR3    ST3     SR3    NumEntry4    DWR4    ST4     SR4    NumEntry5    DWR5    ST5     SR5    NumEntry6    DWR6    ST6     SR6
    ______    ___________    ______________    ______    _____    ___    __________    __    ___    ______    ______    _____    _______    _____________    ___    _________    ______    ________    ___________    ___________    _________    ____    ____    ___    _________    ____    ____    ___    _________    ____    ____    ___    _________    ____    ____    ___    _________    ____    ____    ___    _________    ____    ____    ___

     2876     "鈴木幸夫"      "スズキユキオ"         "愛知"     "A1"     "S"    3.2081e+05    1     62      163        51      "AB"      6.45          51.4         37        18         107          4            1            0.16           48        66.7    0.14    2.1       57        36.8    0.17    3.4        3        66.7    0.24    3.3        0           0       0      0        0           0       0      0        0           0       0      0
     2992     "今村豊"        "イマムラユタカ"         "山口"    "A1"     "S"    3.6062e+05    1     58      162        50      "A "      6.67          39.2         20        24         112          2            0            0.14           25          68    0.14    3.4       23        52.2    0.13    3.1       15        33.3    0.14    2.9       22        31.8    0.13    2.5       14        14.3    0.14    3.3       13         7.7    0.12    2.1
     3022     "西山昇一"      "ニシヤマシヨウイチ"       "愛知"     "A1"     "S"    3.5101e+05    1     59      168        54      "B "      6.53          49.6         37        29         133          5            1            0.16           32        90.6    0.15    3.1       21        61.9    0.16    3.2       20          40    0.15    2.3       27        29.6    0.18    3.6       23        26.1    0.18    3.6       10          20    0.13    3.6
     3024     "西島義則"      "ニシジマヨシノリ"       "広島"     "A1"     "S"    3.6103e+05    1     58      166        58      "AB"      6.63          50.3         33        39         143          2            0            0.15           52        65.4    0.16    3.2       78        46.2    0.15    3.1        9        22.2    0.18    3.9        1           0    0.21      4        1           0    0.35      5        2           0     0.1    3.5
     3070     "山室展弘"      "ヤマムロノブヒロ"       "岡山"     "A1"     "S"    3.6061e+05    1     58      168        51      "A "      7.21          58.8         38        25         107          3            1            0.14           26        80.8    0.13    2.2       32        59.4    0.14      3       26        46.2    0.18    2.5       23        43.5    0.13    2.7        2           0    0.12      3        1         100    0.01      1
     3159     "江口晃生"      "エグチアキオ"         "群馬"     "A1"     "S"    4.0021e+05    1     54      164        54      "AB"      7.48            64         52        37         139          8            3            0.14           49        83.7    0.14    2.8       86        53.5    0.14    2.9        4          50    0.13    2.8        0           0       0      0        0           0       0      0        0           0       0      0
...
...
...

この人が出るだけで配当が荒れたA1選手ランキング2019

 この人が出たら、その人が勝っても勝たなくても配当が荒れる人を探してみよう。こんな感じのスクリプトですね。

A1 = Person(Person.Class == "A1",:);   % 325人いるよ。
m = zeros(height(A1),1);
d = m;
for n = 1:height(A1)
    idx = any(ismember(TR_2019.fin_name,A1.NameNo(n)),2);
    m(n) = nanmean(TR_2019.trifecta_d(idx));
    d(n) = nanstd(TR_2019.trifecta_d(idx));
end
figure(1)
bar(A1.NameNo,m)

tri2019.png

横軸が選手番号で縦軸が3連単の平均配当ですけど見にくい。。
配当が高い順に並び替えて、横軸を名前にしよう。

[ms,idx] = sort(m);
disp([A1.NameNo(idx), ms])
figure(1)
barh(ms);
yticks(1:325);
yticklabels(A1.Name(idx))

tri2019h.png

300人もいると、どうしても見にくい。。。TOP20 くらいにしよう。

figure(1)
barh(ms(end-19:end));
yticks(1:20);
yticklabels(A1.Name(idx(end-19:end)))

tri2019_top20.png

石川選手が出るレースの平均配当が10000円超え!
なんか分かる気がしますね。

低い方はどうだろう。安い方から20件を見てみよう。

figure(1)
barh(ms(1:20));
yticks(1:20);
yticklabels(A1.Name(idx(1:20)))

tri2019_worst20.png

特に中谷選手の出るレースは荒れない!順当!ということですね。

石川選手 3473 を追ってみよう(プログラムで)

 ベテランのイン屋で、特殊な石川ペラでスーパーピット離れ!の選手なので、スタートから荒れそうっていうのはなんとなくわかりますね。(先入観?)

2019年の着順

idx = any(ismember(TR_2019.fin_name,3473),2) ;
P_3473 = TR_2019(idx,:);
figure(1)
histogram(categorical(P_3473.fin(P_3473.fin_name == 3473)));  % 着順

fin3473.png

1着多め。F はフライング、K1 は選手責任の事前欠場、S1 は選手責任の失格です。

12000円以上ついたレースのどこに3473がいたか。

12000円は全通り買っても浮く金額で。

idx = P_3473.trifecta_d > 12000;
sum(P_3473(idx,:).fin_name == 3473)

↓こんな結果。(左から順に1,2,3,4,5,6着の回数)

ans =
    10    10    11    13     9    11

まんべんなくいる。

3473 がインを取りに行った割合 (枠番 > 進入)

idx = P_3473.frame(P_3473.fin_name == 3473) > P_3473.fin_entry(P_3473.fin_name == 3473);
innum = nnz(idx) 
inper = nnz(idx)/numel(idx)

↓↓↓

innum =
   160

inper =
    0.5735

57% くらいインに行ってますね。

3473 がインを取りに行ったレースの平均配当と、取らなかった時の平均配当

インに行ったとき

idx = P_3473.frame(P_3473.fin_name == 3473) > P_3473.fin_entry(P_3473.fin_name == 3473);
mean(P_3473(idx,:).trifecta_d)

↓↓↓

ans =
      12477.63

125倍くらい。

インに行かなかったり行けなかったりしたとき

idx = [P_3473.frame(P_3473.fin_name == 3473) <= P_3473.fin_entry(P_3473.fin_name == 3473)];
mean(P_3473(idx,:).trifecta_d)

↓↓↓

ans =
       7565.59

75倍。

3473 が、いくつインを取ったら配当が高いのか。

pidx = P_3473.fin_name' == 3473;
frame = P_3473.frame';
entry = P_3473.fin_entry';

mn = [];
for n = 1:5
    idx = frame(pidx) == (entry(pidx) + n);   % 枠 == 進入+(1|2|3|4|5) のケース
    mn(n) = mean(P_3473(idx,:).trifecta_d);
end
figure(1)
bar(1:5,mn)

in12345_trif_3473.png

1つか4つ。

3473 がインを4つ取ったときの順位。

1つだけインを取ったときは配当が高いけど、あんまり特徴がなかったので省略して4つ前に行ったときを見てみましょう。

P_3473_in4 = P_3473(frame(pidx) == entry(pidx)+4,:);
sum(P_3473_in4.fin_name == 3473)

↓↓↓(左から順に1,2,3,4,5,6着の回数)

ans =
         11          5          4          2          0          2

3着以内には入ることがほとんど。

インを4つ取った場合の、各着順の配当を個別に見てみる。

5着はなかったので省略。

pidx = P_3473_in4.fin_name' == 3473;
fin = P_3473_in4.fin';

X1 = P_3473_in4.trifecta_d(fin(pidx) == "01")
X2 = P_3473_in4.trifecta_d(fin(pidx) == "02")
X3 = P_3473_in4.trifecta_d(fin(pidx) == "03")
X4 = P_3473_in4.trifecta_d(fin(pidx) == "04")
X6 = P_3473_in4.trifecta_d(fin(pidx) == "06")

↓↓↓

X1 =
       5300.00
      11650.00
        950.00
       2540.00
       3760.00
       1750.00
       9540.00
      13140.00
       1370.00
       2680.00
      53210.00
X2 =
       2290.00
       2320.00
      72440.00
       7060.00
       2020.00
X3 =
       8020.00
      47370.00
        750.00
       1570.00
X4 =
      25990.00
       1200.00
X6 =
      14300.00
      32150.00

4, 6着が意外に高いのと、1,2,3着でも時々とんでもない倍率が出てる。

ページが縦に超長くなったので、とりあえずここまで。。

 選手データをMATLABで見る方法がわかりました!スタ展で石川選手が4つ前に行きそうだったらチャンスと見ていいのかな。
 とりあえず今回は選手をベースに簡単な解析をするやり方をやってみましたが、MATLAB は自分のアイデアを数行で書けるので、みなさんもやってみてくださいね。

 次は何にしようかな。

6
4
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
6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?