OmniAICreator/Qiita-1.07M huggingface dataset:
VBAで共有メモリを使用するサンプル

健忘録

```vb
Private Const PAGE_READONLY = 2&
Private Const PAGE_READWRITE = 4&
Private Const FILE_MAP_WRITE = 2&
Private Const FILE_MAP_READ = 4&

Private Declare PtrSafe Function CreateFileMapping Lib "kernel32" Alias "CreateFileMappingW" (ByVal hFile As LongPtr, lpFileMappingAttributes As Any, ByVal flProtect As Long, ByVal dwMaximumSizeHigh As Long, ByVal dwMaximumSizeLow As Long, ByVal lpName As String) As LongPtr
Private Declare PtrSafe Function OpenFileMapping Lib "kernel32" Alias "OpenFileMappingW" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal ptrToNameString As String) As LongPtr
Private Declare PtrSafe Function CloseHandle Lib "kernel32" (ByVal hObject As LongPtr) As Long
Private Declare PtrSafe Function MapViewOfFile Lib "kernel32" (ByVal hFileMappingObject As LongPtr, ByVal dwDesiredAccess As Long, ByVal dwFileOffsetHigh As Long, ByVal dwFileOffsetLow As Long, ByVal dwNumberOfBytesToMap As Long) As LongPtr
Private Declare PtrSafe Function UnmapViewOfFile Lib "kernel32" (ByVal lpBaseAddress As LongPtr) As Long
Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)

'*****************************************************************************
'[概要] Objectのアドレスを共有メモリに保存する
'[引数] Object
'[戻値] なし
'*****************************************************************************
Private Sub SetCommon(ByRef Ribbon As Object)
    Dim hFileMap As LongPtr
    Dim pMap     As LongPtr
    Dim Pointer  As LongPtr
    
    'ハンドルをCloseすることはあきらめる(ただしExcelをすべて閉じればハンドルは解放される)
    hFileMap = CreateFileMapping(-1, ByVal 0&, PAGE_READWRITE, 0, Len(Pointer), ThisWorkbook.FullName)
'    hFileMap = OpenFileMapping(FILE_MAP_WRITE, False, ThisWorkbook.FullName)
    If hFileMap <> 0 Then
        pMap = MapViewOfFile(hFileMap, FILE_MAP_WRITE, 0, 0, 0)
        If pMap <> 0 Then
            Pointer = ObjPtr(Ribbon)
            Call CopyMemory(ByVal pMap, Pointer, Len(Pointer))
            Call UnmapViewOfFile(pMap)
        End If
    End If
End Sub

'*****************************************************************************
'[概要] Objectを共有メモリから取得する
'[引数] なし
'[戻値] Object
'*****************************************************************************
Private Function GetCommon() As Object
    Dim hFileMap As LongPtr
    Dim pMap     As LongPtr
    Dim Pointer  As LongPtr
    
    hFileMap = OpenFileMapping(FILE_MAP_READ, False, ThisWorkbook.FullName)
    If hFileMap <> 0 Then
        pMap = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0)
        If pMap <> 0 Then
            Call CopyMemory(Pointer, ByVal pMap, Len(Pointer))
            Call UnmapViewOfFile(pMap)
            
            Dim obj As Object
            Call CopyMemory(obj, Pointer, Len(Pointer))
            Set GetCommon = obj
        End If
        Call CloseHandle(hFileMap)
    End If
End Function
```
MySQLでパーティショニングする

一定のルールでテーブルに格納されるデータを分割して保存するようなイメージの機能です。
巨大テーブルで走らせるDELETEはとても負荷の大きい処理ですが、パーティションごと削除することでとても高速に不要データの切り離し処理を行うことができるようになります。
ほかにも、上手にパーティションを設定してクエリをチューニングすると、インデックスを張ったときのようなパフォーマンス向上にもつながります。

特定のパーティションを対象に検索をするクエリの例です。
スキャン対象がパーティション内に限られるのでクエリの高速化が見込めます。

    SELECT * FROM logs PARTITION (p2017, p2018) WHERE productid = 3;

##パーティショニングの種類
いろいろなパーティショニングの種類がありますが、おおむね以下の３種類で大概のことは足るように思います。

####RANGEパーティショニング
パーティショニングに使用するカラムの値の範囲を指定してパーティショニングします。
ログテーブルでデータを期間別に管理したり、データをパージすることを見込んでいる場合などに使います。

####LISTパーティショニング
パーティショニングに使用するカラムの値のバリエーションでパーティショニングします。
性別、地域などのある程度とりうるバリエーションが決まっているデータを分割したい場合に使います。

####HASHパーティショニング
パーティショニングに使用するカラムの数字をパーティション数で割り算したときの剰余（余り）の数字でグルーピングしてパーティショニングします。

##パーティショニングの定義
以下のテーブルにパーティショニングを設定する例を考えます。
MySQL系のパーティション機能で対象にできるカラムは主キー（Primary Key）となっているものに限られるのでテーブル設計から練っていく必要があります。

    CREATE TABLE logs (
        id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
        userid BIGINT UNSIGNED NOT NULL,
        productid BIGINT UNSIGNED NOT NULL,
        created DATETIME NOT NULL,
        amount INT UNSIGNED NOT NULL,
        PRIMARY KEY (id, userid, productid, created)
    ) ENGINE=InnoDB;

####RANGEパーティショニング
createdを使って年ごとに分割します。

    ALTER TABLE logs PARTITION BY RANGE (YEAR(created)) (
        PARTITION p2017 VALUES LESS THAN (2017) ENGINE = InnoDB,
        PARTITION p2018 VALUES LESS THAN (2018) ENGINE = InnoDB,
        PARTITION p2019 VALUES LESS THAN (2019) ENGINE = InnoDB,
        PARTITION p2020 VALUES LESS THAN (2020) ENGINE = InnoDB,
        PARTITION pmax VALUES LESS THAN MAXVALUE
    );

※MAXVALUEを使ったパーティションを設定すると新しいパーティションを追加することができなくなるので注意です。

####LISTパーティショニング
productidを使って分割します。

    ALTER TABLE logs PARTITION BY LIST (productid) (
        PARTITION p1 VALUES IN (1),
        PARTITION p2 VALUES IN (2),
        PARTITION p3 VALUES IN (3),
        PARTITION p4 VALUES IN (4),
        PARTITION p5 VALUES IN (5)
    );

####HASHパーティショニング
idを使って20パーティションに分割します。

    ALTER TABLE logs PARTITION BY HASH (id) PARTITIONS 20;

##パーティションの追加と削除
新しく登録しようとするデータが入ることができるパーティションが存在しないとエラーになりますので、MAXVALUEのないRANGEパーティションは定期実行バッチなどでパーティションを増やしていく必要があります。
また、LISTパーティションでデータのバリエーションが増えるときも同様にパーティションを増やす必要があります。

####パーティションの追加
パーティションの追加はただ器を用意するだけでデータの分類を伴わないため一瞬で完了します。

    ALTER TABLE logs ADD PARTITION ( PARTITION p2021 VALUES LESS THAN (2021) ENGINE = InnoDB );

####パーティションの削除
パーティションを削除すると、そのパーティションに所属するデータも一緒に削除されます。

    ALTER TABLE logs DROP PARTITION p2017;

####パーティションの再構成
再構成といっても、既存のパーティショニングを土台から組み替えるようなことではなく、あるパーティションに入っているデータを細分化させる処理となります。

※MAXVALUEを何とかしたい場合の例

    ALTER TABLE logs REORGANIZE PARTITION pmax INTO (
        PARTITION p2021 VALUES LESS THAN (2021) ENGINE=InnoDB,
        PARTITION pmax VALUES LESS THAN MAXVALUE ENGINE=InnoDB
    );

※古いデータを細分化したい場合の例
p2017が一番手前のパーティションとした場合。

    ALTER TABLE logs REORGANIZE PARTITION p2017 INTO (
        PARTITION p2011 VALUES LESS THAN (2015),
        PARTITION p2012 VALUES LESS THAN (2016),
        PARTITION p2013 VALUES LESS THAN (2017)
    );
Docker opengl error

dockerでGUIは使えるようになったけどopenGL errorが出る...

```
libGL error:
```

環境：
ubuntu18
nvidia-docker2
nvidia-driver430.50

<h1>ubuntu18の場合

DockerFileを作る

```
FROM ubuntu:18.04
RUN apt -y update &&\
    apt install -y --no-install-recommends mesa-utils x11-apps
   
ENV NVIDIA_VISIBLE_DEVICES ${NVIDIA_VISIBLE_DEVICES:-all}
ENV NVIDIA_DRIVER_CAPABILITIES ${NVIDIA_DRIVER_CAPABILITIES:+$NVIDIA_DRIVER_CAPABILITIES,}graphics
```

アクセス権限を付与する

```
xhost local:
```

イメージの作成

```
sudo nvidia-docker build --tag opengl-ubuntu18:test .
```

コンテナーを走らせる

```
docker run --runtime=nvidia -it --name="opengl-ubuntu18" --env="DISPLAY" --volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" --privileged opengl-ubuntu18:test
```

確認

```
glxgears
```
成功！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/b5b86d82-bf21-bc6c-f1bd-6f9380a82432.png)



<h1>ubuntu16の場合<h1>

```
FROM ubuntu:16.04
RUN apt -y update &&\
apt install -y --no-install-recommends mesa-utils x11-apps \
    pkg-config \
    libxau-dev \
    libxdmcp-dev \
    libxcb1-dev \
    libxext-dev \
    libx11-dev && \
    rm -rf /var/lib/apt/lists/*
COPY --from=nvidia/opengl:1.0-glvnd-runtime-ubuntu16.04 \
  /usr/local/lib/x86_64-linux-gnu \
  /usr/local/lib/x86_64-linux-gnu

COPY --from=nvidia/opengl:1.0-glvnd-runtime-ubuntu16.04 \
  /usr/local/share/glvnd/egl_vendor.d/10_nvidia.json \
  /usr/local/share/glvnd/egl_vendor.d/10_nvidia.json

RUN echo '/usr/local/lib/x86_64-linux-gnu' >> /etc/ld.so.conf.d/glvnd.conf && \
    ldconfig && \
    echo '/usr/local/$LIB/libGL.so.1' >> /etc/ld.so.preload && \
    echo '/usr/local/$LIB/libEGL.so.1' >> /etc/ld.so.preload

ENV NVIDIA_VISIBLE_DEVICES ${NVIDIA_VISIBLE_DEVICES:-all}
ENV NVIDIA_DRIVER_CAPABILITIES ${NVIDIA_DRIVER_CAPABILITIES:+$NVIDIA_DRIVER_CAPABILITIES,}graphics
```


imageを変えたらros:melodic ros:kineticでも出来た!
これが最小限かな？もっと簡単な方法あったら教えてください
Ruby と Perl と Java と Python で解く AtCoder ABC 165 D 床関数

# はじめに
AtCoder Beginner Contest 165 が開催されました。
その D問題でちょっとだけ嵌りましたので、~~復讐~~復習したいと思います。
# 今回のお題
*[AtCoder Beginner Contest 165 D - Floor Function](https://atcoder.jp/contests/abc165/tasks/abc165_d)*
<font color="brown">Difficulty: 505</font>

今回のテーマ、床関数
# Ruby
入力例１をエクセル先生で確認します。
<img width="668" alt="20200503.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538241/64074e10-fd32-0630-a9fb-ad3b5dbbeefb.png">
丁度 **7** で周期していることが分かります。
よくよく考えれば、**7** で割っているのでそうなりますので、n が b - 1 以上の場合は関数 f の取り得る最大値、未満の場合は（単純増加ですので）n を関数 f に代入した値が答えとなります。

```ruby.rb
a, b, n = gets.split.map(&:to_f)
if n >= b - 1
  puts (a - a / b).floor
else
  puts ((a * n / b).floor - a * (n / b).floor).floor
end
```
```f.rb
a, b, n = gets.split.map(&:to_f)
```
いつもの癖で`gets.split.map(&:to_i)`とコーディングしましたので、計算が合わず焦りました。
*Ruby* は型の変換が必要です。
# Python
```python.py
a, b, n = map(int, input().split())
if n >= b - 1:
    print(int(a - a / b))
else:
    print(int(a * n / b) - a * int(n / b))
```
*Python* は整数と整数の割り算により自動的に実数に変換するようです。
# Perl
```perl.pl
chomp (my ($a, $b, $n) = split / /, <STDIN>);
if ($n >= $b - 1) {
  print int($a - $a / $b), "\n";
} else {
  print (int($a * $n / $b) - $a * int($n / $b)), "\n";
}
```
*Perl* は整数と整数の割り算により自動的に実数に変換するようです。
# Java
```java.java
import java.util.*;

class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int a = Integer.parseInt(sc.next());
        Double b = Double.parseDouble(sc.next());
        Double n = Double.parseDouble(sc.next());
        sc.close();
        if (n >= b - 1) {
            System.out.println((int) (a - a / b));
        } else {
            System.out.println((int) (a * n / b) - a * (int) (n / b));
        }
    }
}
```
*Java* は型の変換が必要です。

||Ruby|Python|Perl|Java|
|:--:|:--:|:--:|:--:|:--:|
|コード長|138 Byte|129 Byte|169 Byte|517 Byte|
|実行時間|53 ms|23 ms|2 ms|102 ms|
|メモリ|14204 KB|9016 KB|4788 KB|35648 KB|
# まとめ
+ ABC 165 D を解いた
+ Ruby に詳しくなった
+ Python に詳しくなった
+ Perl に詳しくなった
+ Java に詳しくなった
DDDのエンティティと値オブジェクト【僕の備忘録】

##エンティティとは
ライフサイクルを管理する必要がある=状態が変化していくオブジェクト
IDを持ちそれによって同一性を識別できるオブジェクト
例)
社員
 -社員ID
 -名前
 -所属
 -役職

##値オブジェクトとは
ライフサイクルを管理する必要がない=不変なオブジェクト
プロパティを複数持ち、相互に関係して初めて意味を成す
例)
通貨
 -金額(100)
 -単位(円)

##参考にさせて頂いたサイト
https://codezine.jp/article/detail/10038
https://codezine.jp/article/detail/10184
今更HDDについて詳しく調べてみた件

どうも初めまして！　

最近基本情報技術者の資格取得に向けて勉強中な駆け出しエンジニアのワカです。

#■この記事を書こうと思ったきっかけ
最近書籍を購入して勉強しているのですが、暗記ばかりでなかなか身にならないと思いました。

そこで基本情報に書かれている内容を自分なりに解釈したものをここに備忘録として書き残すことにしました。
そうすれば手も動かせるし人にみられると思うとその分責任感出ますしね！

あと個人的に今自作PCを作りたいとも考えているのでこの機会に詳しくなっとこうと思ったのも理由の一つです笑

もしかすると間違っている点などあるかもしれませんので、その時は指摘していただけると嬉しいです。

#■HDD

##ハードディスクの構造と記録方法
HDD（ハードディスクドライブの略）はどのようにしてデータを保管しているのかというと
中にある**プラッタ**と呼ばれるディスクに**アクセスアーム**と言われる針で読み書きをしています。

例えると古いレコードを聞くような形を思ってもらえればいいかと…。

ただ、ハードディスクを最初使う際には初期化（フォーマット）が必要です。
フォーマットを行うことで読み書きを行うための準備が整うわけです。

フォーマットされたディスクには実は区画で細かく分けられています。
この区画のひと区画、最小の範囲を**セクタ**と呼んでおり、そのセクタが連なり、一周したものを**トラック**と呼びます。

またハードディスク内のディスクは１枚ではなく複数枚あり、同心円上のトラックをまとめると**シリンダ**と呼びます。

つまりセクタの集まりがトラック、トラックの集まりがシリンダというようにそれぞれが単位のような役割を果たしていると思ってもらえればOKです。
**セクタ　＜　トラック　＜　シリンダ**

ただOSが読み書きするとき複数セクタを一つのブロックとして扱います。これを**クラスタ**と呼びます。

ちなみに…もし読み書きしたデータが１ブロックみたない場合に余分な空き容量（セクタ）が発生することがありますが、これは全て無駄な領域として見なされてしまいます。

##データへのアクセスにかかる時間
データへアクセスして任意のデータを読み出すために必要なステップは以下の通りです。

①シーク（位置決め）
↓
②サーチ（回転待ち）
↓
③データ転送

これら①〜③にかかる時間を全て合わせたものが**アクセス時間**となるわけです。

##フラグメンデーション
ハードディスクに書き込みや消去を行っていくとファイルが断片化してきます。
そうなると読み書きに必要な時間が多くかかってきてしまいます。

どういうことかというと…
十分に容量があれば一度のアクセスで全てのデータ転送が完了するはずが、空きがなく分散していると分散しているところにアクセスしなおす必要があるので必要アクセス分時間がかかることになるわけです。

このファイルがあちこちに分散してしまうことを**フラグメンデーション**と呼びます。

ではその場合どのようにすると良いかというとあちこちに散らばったデータを連続したデータ領域に並べ替えてしまうことで解消します。これを**デフラグ（デフラグメンデーション）**と言います。

##RAID（レイド）

ハードディスクの速度や信頼性を向上させるためにRAID（レイド）呼ばれる技術があります。

これは複数のハードディスクを組み合わせて仮想的なハードディスクを構築、運用することを指します。RAIDの種類は以下の通りです。

| 種類 | 説明 | メリット＆デメリット |
|:-:|:--|:--|
| RAID0（ストライピング）  |　一つのデータを２台以上のディスクに分散させて書き込みする   | 高速化が図れる<br>いずれかの１台が故障すると全データがなくなる（信頼性が低い）  |
| RAID1(ミラーリング）  |２台以上のディスクに対して同じデータを書き込む   |常時バックアップがある状態（信頼度高）<br>使えるディスク領域は半分に…   |
| RAID５  |３台以上のディスクを使ってデータと同時にパリティ情報（※１）を使って書き込む   |複数のディスクに分散させて書き込む。<br>いずれかの１台が故障してもパリティ情報を使って復元できる   |

※１パリティ情報・・・誤り訂正符号。送られてきた情報が正しいかどうかを確かめる情報。

#■最後に
ここまで長々と読んでくださりありがとうございました！
少し説明がわかりにくかった部分があるかと思いますが、もしわからないところがあればコメントしていただけると嬉しいです。

では！次の記事にて！
Laravelでエラーハンドリング(エラー時の制御)を行う

# 目次
Laravelの記事一覧は下記
[PHPフレームワークLaravelの使い方](https://qiita.com/toontoon/items/c4d0371e504c37f6576e)

# Laravelバージョン
動作確認はLaravel Framework 7.19.1で行っています

# Laravelのエラーハンドリング
Laravelでエラーが起こった場合に表示する画面を制御します


# 前提条件
[eclipseでLaravel開発環境を構築する。デバッグでブレークポイントをつけて止める。(WindowsもVagrantもdockerも)](https://qiita.com/toontoon/items/76fa7f8845b20776077c)
本記事は上記が完了している前提で書かれています
プロジェクトの作成もapacheの設定も上記で行っています


# HTTPステータスコードのエラー画面

## viewの作成
(1) /sample/resources/views/errorsフォルダ作成
(2) /sample/resources/views/errors/404.blade.phpファイル作成

```404.blade.php
<html>
    <head>
        <title>sample</title>
    </head>
    <body>
        存在しないURLです
    </body>
</html>
```

/resources/views/errors/HTTPステータスコード.blade.php
というファイルを作成しておけば、そのファイルが描画されます

## 動作確認
`http://localhost/laravelSample/sample/notfound`

実行結果

```
存在しないURLです
```

# PHPのエラー画面

## Controllerにメソッド追加
(1) /sample/app/Http/Controllers/SampleController.phpにpostメソッドを追記
`public function post()
    {
        return view('sample.post');
    }
`

(2) /sample/routes/web.phpに下記を追記
`Route::post('sample/post', 'SampleController@post');`

## viewの作成
(1) /sample/resources/views/layout/post.blade.phpファイル作成

```post.blade.php
<html>
    <head>
        <title>sample</title>
    </head>
    <body>
        post送信画面
    </body>
</html>
```

(2) /sample/resources/views/layout/error.blade.phpファイル作成

```error.blade.php
<html>
    <head>
        <title>sample</title>
    </head>
    <body>
        {{ $msg }}
    </body>
</html>
```

## Handler修正
(1) /sample/app/Exceptions/Handler.phpのrenderメソッドを修正

```
public function render($request, Throwable $exception)
    {
        if ($exception instanceof \Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException) {
            return response()->view('sample.error', ['msg' => "サポート外メソッドです"]);
        }

        return parent::render($request, $exception);
    }
```

## 動作確認
`http://localhost/laravelSample/sample/post`

実行結果

```
サポート外メソッドです
```

post送信しか/sample/routes/web.phpに書かなかったのにgetアクセスしようとしたため
MethodNotAllowedHttpExceptionが発生しました
Handler.phpのrenderでその例外を判定してsample.errorを描画しました
[Oracle Cloud] Load Balancer に Windows Server をぶら下げて、リモートデスクトップする

# はじめに

OCI Load Balancer 配下に、2台 Windows Server をぶら下げて、冗長化・負荷分散構成が出来ます。設定にちょっとしたコツが必要だったので、備忘録的に残しておきます。



# 前提

- Windows Server 2019 を2台構成済み



# Load Balancer 作成

1ページ目の指定内容です。以下のパラメータがポイントです

- Public を指定
- Network Security Group を、ロードバランサーにぶら下げる Windows Server と通信出来るものを指定

![1588457219268.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/573db774-1451-dffc-5b8c-c85fff8032f7.png)



2ページ目の指定内容です。

- ロードバランシングポリシーを IP Hash に指定
- バックエンドサーバーの Port は3389を指定

ロードバランシングポリシーは、この手順では IP Hash にしています。接続元のIPアドレスのハッシュ値によって、接続するWindows Server を指定する方式です。リモートデスクトップを使う時には、基本的には前回アクセスした Windows Server に接続したいため、この方式を選びました。環境によっては、うまく負荷分散が出来なく偏りが発生するのでご注意ください。

![1588457253715.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/3270e8af-0497-7004-748b-bd8e67a18cfe.png)



3ページ目の指定内容です。リスナーを TCP の 3389 を指定します。

![1588457336929.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/fea576ae-9afd-13f4-ac4c-005309fd780f.png)



上記パラメータを指定して作成します。

**注意点 : ロードバランサー作成後の詳細画面で、入力したパラメータが正しく作られているか確認したほうが良いです。自分の環境では、正しく入力されないことがありました**



# LBへRDP

ロードバランサーの Public IP 宛に、リモートデスクトップでアクセスします。

![1588457749327.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/6a39a62a-c2ab-24c8-635d-6f8ef8e974db.png)



正常に接続が出来ました。今回は、1台目の Windows Server に接続されています。バランシングポリシーが IP Hash のため、1台目に障害が発生しない限りは、2回目以降のアクセスでも同じサーバーに接続されます。

![1588457725782.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/d920e3c5-a8c9-acdc-ed5c-50c75b01bc8e.png)



# 仮想マシンの強制停止してみる

Stop で強制停止

![1588457903543.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/1f8d63e6-a3e1-1613-f6f7-4edcd85d4b2a.png)



1台目に障害が発生されて、ロードバランサーのヘルスチェックに失敗します。なので、 2台目の Windows Server に接続されます。

![1588458089845.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/bf52129a-8ec7-08ad-e233-ad23fa4dca1b.png)



# 復旧すると

元々つかっていた win01 に接続されます。
「Flutterについての下調べ」 ~私文男子の格闘第1話~

#はじめに
(2020/5/3 投稿)
Qiitaはじめて2日ですが、他のブログ媒体よりもView数がびっくりするほど伸びるので、ビビっている日々を過ごしております。どうも私文男子です。
本日は、**Flutterについて調べたこと**を書いておきたいと思います。

#Flutterとは？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629658/a21bcb48-778c-0c96-30ae-2a637577c52a.png)
(画像:Flutter公式より)

Flutterは、Googleによって開発されたモバイルアプリケーションSDK (Software Development Kit)です。
以下はFlutter公式からの引用です。

>Flutter is Google’s UI toolkit for building beautiful, natively compiled applications for mobile, web, and desktop from a single codebase.
>(日本語訳)
>Flutterは、単一のコードベースからモバイル、ウェブ、デスクトップ向けのネイティブにコンパイルされた美しいアプリケーションを構築するためのGoogleのUIツールキットです。

今までiOSやAndroidでリリースしたい時に、別々のSDK(iOSならXcode/AndroidならAndroid Studio)でUIのためのコードを書かなければいけなかったのをGoogleさんがえええい！と統合したSDKを作ったわけなんですね。ふえええ、すごい。

#なぜFlutterから入ったのか?
私はもともとデザイナーでして、アプリのモックアップをよく作っています。
モックを作るためには、**Adobe XD**を使っているわけなのですが、あるデザイン案件をフリーランスで請け負っている時にこんなことを言われました。

**「開発言語はFlutterを使う予定なので、FlutterのプラグインをXDにインストールしてやってみてください」**

デザイナーとしてもまだまだわからないことだらけで、プラグインすら怪しい中でのこの注文は難しかったので、蹴られてしまいました...
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629658/9e5d21a7-d878-9649-bbae-16fa33e117ad.png)


後になって調べてみると、どうやら
**「Flutterを使えば、XDで作ったUIのコードが自動生成されるらしい」**
ということがわかりました。エンジニアとしては知識経験ともに0の私にとったらこんなありがたいことはありません。
モバイルアプリ作りはFlutterとXDのコンボで始めてみようと思いました。

もちろん他にもFlutterを使うメリットとして、

・iOS/Androidが両方開発できるようになる
・速いコンパイル
・高い堅牢性を誇るDart言語

という点があるようなので、エンジニアとしての初陣はFlutterでいきたいと思います。

次回、環境構築行ってみたいと思います！お楽しみに！
ドメイン駆動設計【僕の備忘録】

##前書き
ドメイン駆動開発について勉強したので自分用にメモ

##ドメインとは
・単語の意味：ドメイン=領域
・ここでいう領域→プログラムを適用する対象となる領域
・例：物流システムのドメイン=荷物、輸送手段、輸送者、顧客、倉庫、経路などなどなど

→**業務知識**って言い換えてもいいのかも

##ドメイン駆動設計とは
**顧客と開発者が直面している課題の解決のためにドメインの知識を正しく用いて(取捨選択して)設計する**こと。
つまり**システム作るとき業務知識ちゃんと理解して設計**しろよってことかな
当たり前じゃんって思ったけど、しっかり抜け漏れなく設計するのは意外と細かいとこまで注意してドメインモデルを作成する必要がありそうです。


##ドメインモデル
大枠は**オブジェクト指向のクラスみたいなイメージ**かな
ただこの時にドメインの知識をいれる必要がある。
必要なメンバだけでなく、それが動的に変化していい値なのか、不変にしなきゃいけない値だとか、そのドメイン特有のルールだとかをサービスロジック側で意識しなくても不整合が生じないようにする。
**いろんな人がそのクラスを扱うこととなってもドメインルールを強制できるような設計**を心がけるのがドメインモデル。

例：クラスを用意する。nameプロパティを持つ。nameはインスタンス作成後は変更不可。というドメイン
×メンバ全てにgetter setterをつける。setterがあるのでサービスロジックから自由にnameの変更が可能となり、ドメインルールを守れていない。新たにプロジェクトに加わった人が間違えてしまう可能性が生じる。
〇nameはsetterを用意せず、コンストラクタやファクトリなどでのインスタンス生成時のみ設定できるようにする。新規にプロジェクトに参加した人もnameは上書きできないというルールを守ることになる。

##まとめ
**業務知識を取捨選択して設計に落とし込むこと**
**それを誰もがルールを守らざるを得ないようにドメインモデルを作成すること**


##参考にさせて頂いたサイト
https://codezine.jp/article/detail/11968
https://little-hands.hatenablog.com/entry/2017/10/04/201201
Pythonの文字列が標準でf文字列になる（かも）

## はじめに

Python言語サミット2020が4月の15日、16日の2日間で開かれました。これはPython実装の開発者（本家のCPythonに加えてPyPyなども）が集まる会議で、単にプレゼンし合う場というよりは言語本体や標準ライブラリの現状や今後に関する議論をして合意を目指すという会議とのこと。

今年はコロナウイルス蔓延の影響で、ご多分に漏れずオンライン開催となったそうですが、2日間の議題を見るとなかなか興味深いものが並んでいます。

* 全ての文字列をf文字列にする
* CPythonのパーサーをPEGベースの物にする
* (C)Pythonの仮想マシンの形式仕様記述
* 実装非依存のC言語拡張API
* CPythonのドキュメンテーション保守の変革
* ライトニングトーク
  * pip, PyPI そしてパッケージングに今後何を求める？
  * 「マルチコアPython」プロジェクトの失敗を振り返る
* Pythonの型導入の今後の方向性
* CPythonのコア開発のワークフロー改善活動アップデート
* モバイルプラットフォーム上のCPython

このなかで、1つ目の「全ての文字列をf文字列にする」というのを取り上げて、[このブログ投稿](https://pyfound.blogspot.com/2020/04/all-strings-become-f-strings-python.html)を元にどんな議論がされたのかを軽くまとめてみたいと思います。



## f文字列とは

まず議論に入る前にf文字列とは何かをおさらいしておきましょう。f文字列はPython 3.6で導入された機能で、文字列の一部に変数や式をいれておき、それを実行時に置き換えるというものです。

例えば

```python
>>> x = 1
>>> print(f"xの値は{x}です")
xの値は1です
```

となります。f文字列が導入される前までは似たようなことをしようとすると

```python
print("xの値は%dです" % x)
```

としたり、

```python
print("xの値は{}です".format(x))
```

としたりしていました。どちらにしても、変数で置き換える場所と変数を指定する場所が分かれていてわかりにくく、バグが起こりやすい部分でした。これがf文字列の導入で一気に楽になりました。

他の言語でも、例えばJavaScriptだと、

```javascript
let x = 1
console.log(`xの値は${x}です`)
```

と書けたりしますし、Ruby, Scala, C#などでも同様の機能があるので時代の潮流に乗ったということですかね。

なお、f文字列の機能はPython 3.8で少し拡張されていて、例えば

```python
>>> x = 1
>>> y = 2
>>> print(f"{x=}, {y=}, {x+y=}")
x=1, y=2, x+y=3
```

とできます。つまり、`{}`の最後に`=`をつけることで変数や式の値だけでなく、変数や式そのものを出力に含めてくれます。ちょっとしたデバッグする時に便利なので覚えておいて損はないかと思います。

## Python言語サミット2020での議論

上記のようにとても便利なf文字列。これがあるのでPython2からPython3に上がって来た、という人もいるらしいのですが、多く使われるに連れて不満も出てきています。それを解決するための議論がPython言語サミット2020の1つ目の議題となっています。議題を提出したのは元々f文字列導入のためのPEPを2015年に書いた Eric Smithさん。

ここで取り上げている問題というのは、これ。

```python
>>> x = 1
>>> print("xの値は{x}です")
xの値は{x}です
```

わかりますでしょうか。「あ、文字列の前の`f`を付け忘れた (^^;」というやつです。

この間違いを避けるために、変数置換があろうがなかろうが全ての文字列の前に `f`を付ける、というプログラマーを彼は見たことがあるそうです。そこで彼の提案は

「文字列をデフォルトでf文字列にする」

というものです。実際、f文字列を3.6で導入する時には最初はそういう提案だったらしいのですが、大きすぎる破壊的な変更ということで却下され、今の`f`を頭につける形に落ち着きました。

今回の提案は、`f`がついてもつかなくてもf文字列とする、そして追加で 「p文字列」というのを導入し、文字列の前に`p`がついていたらこれまでの文字列として扱う、というものでした。それによる性能面での低下もありません。

一方で発案者のSmithさんも幾つか問題があることわかっていて、例えば`p`という新しい文字列接頭詞を導入しないといけない。あと、結構大きな変更になるので

```python
from __future__ import all_fstrings
```

という import文がある時のみこれを有効にするようにしたりしたくなる。まあでもそうするとなかなかこれを外すことができなくなるのでこの案は却下かなということになりました。

この提案に対して参加者から幾つかコメントが出ました。

Yarko Tymciurakさんからは「初心者に `p`って何でどうやって説明するの 」という質問がでました。Smithさんは「`p`って言語仕様をちょっと複雑にしちゃうよね」と認めながらも「実際には`p`ってそれほど使われないだろうし、説明もまあ自明じゃないですかね」と答えました。

何人かの参加者はこの変更に前向きで、Brett Cannonさんは「`f`接頭詞を無くすことは初心者にとってPythonを学ぶのが簡単になるだろう」とコメントしました。

Larry Hastingsさんは「PHPの文字列もこういう仕様だし、スクリプト小僧たちはとっても気にいると思う」と言いながらも、「でもこれって、『おっと、`f`つけるの忘れっちゃった』というのを避けるためで、それって別にすぐに気がつく間違いだと思うけど、それだけのために言語仕様の変更する？」と疑問を呈しました。

多くの参加者は、f文字列が最初からデフォルトだったら良かったということに同意しながらも、Paul Mooreさん、Guido van Rossumさん（Pythonの創始者ですね）などは益よりも害の方が大きくなってしまうことを懸念しました。そして、続きはMLで議論しましょうということでこの議題は終了となりました。

## まとめ

個人的には f文字列をデフォルトにするのに賛成ですが、それほど簡単に行かないんだなと思いました。短いブログ記事でしたが、参加者の皆さんが様々な側面を考えながら慎重に言語仕様の変更を議論している様が垣間見れて良かったと思います。
[Swift] Unit/UI Test 　メモ #2



# XCTest
[前回のメモ＃１はここへ](https://qiita.com/mario7/items/7e41de8aa7a7ca00ccef)

## 基本

| メソッド | 意味 |
|:--|:--|
| setUp | 各テストが始まる前に実行|
| tearDown| 各テストが終わった後に実行 |
| setUpWithError | 各テストが始まる前に実行、　throws付き|
| tearDownWithError| 各テストが終わった後に実行、throws付き |
| testExample|各テスト実施|
| testPerformanceExample|性能テスト|


## テンプレート(Xcode 11.4 )
`throws付き`両方のサンプルテストメソッドをマークします。
ただし、setup()、tearDown()、非スローテストメソッドを使用できます。
__（非推奨ではありません。）__ 

```
override func setUpWithError() throws {}
override func tearDownWithError() throws {}
func testExample() throws {}
func testPerformanceExample() throws {}
```

※参照：[XCTest Error Handling Improvements](https://useyourloaf.com/blog/xctest-error-handling-improvements/)

## Realm
Realmアプリを使用してテストする最も簡単な方法
・デフォルトのレルムをテストごとに新しいファイルに設定します。
理由：アプリケーションデータを上書きしたり、テスト間で状態を漏らしたりしないようにするため、

```realmTests.swift
class TestCaseBase: XCTestCase {
    override func setUp() {
        super.setUp()
        Realm.Configuration.defaultConfiguration.inMemoryIdentifier = self.name
    }
}
```
参照：　[Realm](https://realm.io/docs/swift/3.20.0/#testing-and-debugging)

## UI Test
```sampleUITests.swift
 func testExample() {
    let app = XCUIApplication()
    app.buttons["Test"].tap()
    app.staticTexts["touched Test Button: "].tap()
}
```

## コードカバレッジ(Code Coverage )
実際にテストによって実行されているアプリコードを通知するので、アプリコードのどの部分が（まだ）テストされていないかがわかります。

<img width="893" alt="coverage-xcode.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101832/cc952859-caf0-cbf3-d1d7-2484e06d08ff.png">

※参照：[raywenderlich test tutorial](https://www.raywenderlich.com/960290-ios-unit-testing-and-ui-testing-tutorial#toc-anchor-001)
WSL2(Ubuntu18.04)上でDockerを起動する

どーも、ふぎとです。
今回は「**手元のSurface Goで練習用にDockerを
動かす**」話。

★★★★★★★★★★★★★★★★★★★★★★★★
具体的な環境構築については、[こちらの方の記事](https://dev.to/birdsea/windows-subsystem-for-linux-2-docker-for-wsl2-3dpm)が
わかりやすかったのでオススメ。
★★★★★★★★★★★★★★★★★★★★★★★★

##やっと環境構築できたけど…

（文系エンジニアのふぎとくん。きょうは苦心して
Dockerを動かす環境を用意したみたい。）

「ふう、WSL→WSL2の切り替え、Dockerのインストール
確認までなんとかできたで」
「あとは起動するだけや！」

~~~
$sudo service start docker
start: unrecognized service
~~~

「おっしゃ、これで起動できたな？」
「ほなネットワークの確認や」

~~~
$docker network ls
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
~~~

「ほえ？」
「キャノット・コネクト・トゥ・ザ・ドッカー・デーモン？」
「Docker起動できてへんのかいな」
「なんでや？」

##颯爽と先輩登場

「おお、ふぎとやないか」
「そんな頭かかえてどないした？」
「あ、先輩ええところに」
「Dockerが起動せえへんのです」
「起動せえへん？環境構築ちゃんとしたんか？」
「した…はずなんですど、コマンド打っても起動せんくって…」
「どれどれ、ちょっと見してみい」
「……あー、わかったわ」

##あっさり解決

「ふぎとお前な、単語の順番間違えとるわ」
「え、順番ですか？」
「そうや。さっき起動しようとしたとき
　"sudo service start docker"って
　打ち込んどったやろ」
「はい」
「その順番が違うねん」
「正しくはこうや」

~~~
$sudo service docker start
 * Starting Docker: docker
~~~

「おお⁉」
「明らかにちゃんと起動してますやん」
「せやろ」
「ネットワークの確認もちゃんとできる」

~~~
$docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
8ff1f4a3af31        bridge              bridge              local
7a0808d7b4d1        host                host                local
95ce0a993fb8        none                null                local
~~~

「ほんまですやん…」
「こんな単純なことやとは……」
「まあでも間違えてまう気持ちはわかる」
「お前が最近さわってたAmazonLinux2の
　**[systemctlコマンド](https://qiita.com/shimajiri/items/ae8fe481bea3e9660a0c)とはちょっと順番が
　違う**からな」
「ほんまですね…勉強なりました」
「ありがとうございます(*´ω｀)」

##おしまい

ではでは今回はこの辺で。ふぎとでした。
ゼロから始めるLeetCode Day10 「1431. Kids With the Greatest Number of Candies」

#概要
海外ではエンジニアの面接においてコーディングテストというものが行われるらしく、多くの場合、特定の関数やクラスをお題に沿って実装するという物がメインである。

その対策としてLeetCodeなるサイトで対策を行うようだ。

早い話が本場でも行われているようなコーディングテストに耐えうるようなアルゴリズム力を鍛えるサイト。

せっかくだし人並みのアルゴリズム力くらいは持っておいた方がいいだろうということで不定期に問題を解いてその時に考えたやり方をメモ的に書いていこうかと思います。

[Leetcode](https://leetcode.com/)

基本的にeasyのacceptanceが高い順から解いていこうかと思います。

前回
[ゼロから始めるLeetCode Day9「701. Insert into a Binary Search Tree」](https://qiita.com/KueharX/items/5cc45adb826cf66ca8ab)

10日も続きました、すごい。

# 問題
[1431. Kids With the Greatest Number of Candies](https://leetcode.com/problems/kids-with-the-greatest-number-of-candies/)

配列`candies`と数値の`extraCandies`が与えられます。`candies[i]`はi番目の子供が持っているキャンディの数です。
それぞれの子供に子供たちの中で最大数のキャンディーを持つことができるように子供たちにextraCandyを配布する方法があるかどうかを確認します。

問題だけだと少しわかりにくいですね・・・
実際の例を見た方が良さそうです。

```
Input: candies = [2,3,5,1,3], extraCandies = 3
Output: [true,true,true,false,true] 
```

一番最初の子の場合は元から持っているキャンディー2個に`extraCandies`の3個を与えた場合、2+3で5になり、`candies`の中で最大値である5に並ぶため、trueとなります。
二番目、三番目、五番目の子についても同様のことがいえます。

唯一`False`なのは仮に3個の`extraCandies`を与えられても4個にしかならず、配列の中の最大値である5に届かない四番目の子です。

それぞれの配列の数字に`extraCandies`の値を足した後に配列の中の最大値と比較し、最大値以上であれば`True`を、未満であれば`False`を`candies`に代入し、その流れを一通り回した後にcandiesを返すような関数であれば条件を満たしそうです。

まずは再帰と分岐だけで書いてみた例

```Python
class Solution:
    def kidsWithCandies(self, candies: List[int], extraCandies: int) -> List[bool]:
        num = max(candies)
        for i in range(len(candies)):
            if candies[i] + extraCandies >= num:
                candies[i] = True
            else:
                candies[i] = False
        return candies
# Runtime: 64 ms, faster than 33.33% of Python3 online submissions for Kids With the Greatest Number of Candies.
# Memory Usage: 13.6 MB, less than 100.00% of Python3 online submissions for Kids With the Greatest Number of Candies.
```

超シンプルです。ただこれだとあまり速くないですし、もっと簡略化したいですね。
ここでの省略できる部分を考えてみると、for文以降のif分岐が少し冗長かなと思います。


```Python
class Solution:
    def kidsWithCandies(self, candies: List[int], extraCandies: int) -> List[bool]:
        num = max(candies)
        return [candy + extraCandies >= num for candy in candies]
# Runtime: 48 ms, faster than 33.33% of Python3 online submissions for Kids With the Greatest Number of Candies.
# Memory Usage: 14 MB, less than 100.00% of Python3 online submissions for Kids With the Greatest Number of Candies.
```

こう書き換えてみます。少し速くなりましたね。
returnの後に続いているのはリスト内包表記というもので、
`[ 式 for 変数 in オブジェクト ]`
という書き方をすることができるというものです。

内包表記には他にも、
`セット { 式 for 変数 in オブジェクト }`
`辞書 { キー式: 値式 for k,v in オブジェクト }`
`ジェネレーター　( 式 for 変数 in オブジェクト )`
といった物もあるので、興味がある場合は以下のドキュメントを参考にすると良いです。

[6. 式 (expression)](https://docs.python.org/ja/3/reference/expressions.html)

なお、内包表記の速度に関する興味深い記事として以下のような物がありました。
時間があるときにチェックするといいかもしれません。

[Pythonのリスト内包表記の速度](https://qiita.com/intermezzo-fr/items/43f90e07e4cebe63aeb6)
Vue.js 初心者は Vue Masteryの動画学習がベストプラクティス

#はじめに
Vue.js公式がゴリ押ししているVue Masteryの動画学習が、初心者の学習に最も効率的であると感じましたので、プログラミング歴3ヶ月(独学) 超ど素人の小職が、その概要をお伝えしていきます!:blush:

目と耳から情報を叩き込んで、それと同時にコードを書いてイメージを掴むことができるため、動画学習は最強ですよね！:thumbsup:

#Vue Masteryとは
Vue.js公式による動画学習サービスです。 Vue.js専門のUdemy的な存在です。
[Vue Mastery](https://www.vuemastery.com/)
<img width="1431" alt="mastery.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629856/59c4e3d9-fb32-6ef7-9845-500fdb793ea0.png">
コースは、初級　中級　上級 の3つに分かれており、それぞれのコースで細かく学習パートが設定されています。

#Vue Masteryのメリット
1. 図やアニメーションを多く使用した説明で、めちゃくちゃイメージしやすい。
2. 簡単なアプリを作りながら学んでいくスタイルのため、実践力が身に付く。
3. 各セクションごとでコードや画像をダウンロードできるため、ハンズオンで学習可能。
4. 毎回ちょっとした課題が出るため、すぐにアウトプットできる。
5. 動画1本につき平均10分程度なので、隙間時間の学習が可能。
6. 公式が運営しているため、学ぶことの全てがベストプラクティスで間違いない。

#Vue Masteryのデメリット
1. 英語　(英語字幕があるし、速度もスローにできるので全然問題無し)
2. 定期講読料金 Monthly 19ドル (2000円くらい) (初級パートはほぼ無料なので問題無し)

#Intro to Vue.js 
初級コース(Beginner path)のIntro to Vue.jsではECサイトの詳細ページを作りながら学習していきます。
<img width="1430" alt="Intro to Vue.js 1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629856/c6eb998a-ecb8-8be6-2695-96c843ac249f.png">
実際にアプリを作りながらの学習のため、力がメキメキつくこと間違い無しです!!

<img width="1432" alt="Intro to Vue.js 2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629856/47203d5c-60ad-2632-7bd9-5aff977f3042.png">

このようにアニメーションを使って分かりやすく説明してくれるので、理解度が爆上がりします。
英語が分からなくても、ほとんど理解できると思いますので安心してください。

<img width="1440" alt="Intro to Vue.js 3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629856/05ecf3cc-dbd8-d379-42df-1ba9d45797b9.png">
v-ifディレクティブはこんな感じのイメージです。
やっぱり文章で説明されるより、分かりやすいですよね?

#Vue Mastery　オススメ学習法
動画を見ながら、実際にコードを書いて学習する。
→ 見るだけではダメです。書いて自分で動かしてみます。

英語字幕をつけて、速度0.75倍にしてなんとか食らいついてみる。
→ 英語学習もできて一石二鳥です。

定期購読して、レベルの高い学習をする。
→ クオリティ高すぎて、2000円くらい安いと思います。1ヶ月だけでも課金するべきです。

JavaScriptの基礎知識が無ければ理解することが困難ですので、まずはそちらからという方は、我らが[ドットインストール](https://dotinstall.com/)さんでJavaScriptのDOM編までやんわりと理解できれば大丈夫だと思います。

#おわりに
私もまだまだ学習中ですが、Vue Masteryはマジで初心者にとって最強の学習法だと思いますので、英語アレルギーの方も騙されたと思って是非1度ご覧になってみてください!

また、皆さんのオススメの学習法やチュートリアルがございましたらご教示いただけますと幸いです。

引き続きどうぞよろしくお願い申し上げます。

Mahalo
takunosuke
OpenSSL CSR生成スクリプト

```
#!/bin/sh


if [ $# -lt 2 ]; then
  echo "usage: $0 <fqdn> <passphrase> [<city>] [<pref>]"
  echo "pref : default => KANAGAWA"
  echo "city : default => YOKOHAMA"
  exit 1;
fi


echo "-------------------------------------------------------"
CN=$1
PP=$2
CITY=$3
PREF=$4

# default
CITY=${CITY:=YOKOHAMA}
PREF=${PREF:=KANAGAWA}

echo CN=$CN
echo PP=$PP
echo CITY=$CITY
echo PREF=$PREF

echo "-------------------------------------------------------"
echo 対話式で入力するdistinguished nameを一度に指定。コモンネームは第1引数
SJ="/C=JP/ST=$PREF/L=$CITY/O=$CN/OU=$CN/CN=$CN"
echo $SJ
 
echo 秘密鍵を作成
openssl genrsa -des3 -passout pass:$PP -out $CN.key 2048
 
echo "-------------------------------------------------------"
echo パスフレーズなしの秘密鍵にする
openssl rsa -passin pass:$PP -in $CN.key -out $CN.key
 
echo "-------------------------------------------------------"
echo CSR出力
openssl req -new -sha256 -key $CN.key -out $CN.csr -subj "$SJ"
 
echo "-------------------------------------------------------"
echo 確認のためにCSR内容を表示
openssl req -noout -text -in $CN.csr

echo "-------------------------------------------------------"
echo server.csrとserver.keyを指定して server.crtを作成する
openssl x509 -req -in $CN.csr -signkey $CN.key -sha256 -days 36500 -out $CN.crt

echo "-------------------------------------------------------"
echo 証明書ファイルの内容を表示
openssl x509 -text -noout -in $CN.crt

echo "-------------------------------------------------------"
echo 証明書ファイルのfingerprintを表示
openssl x509 -fingerprint -noout -in $CN.crt

echo "-------------------------------------------------------"
echo 秘密鍵から公開鍵を作成する
openssl rsa -pubout -in $CN.key -out $CN.pub

echo "-------------------------------------------------------"
echo 公開鍵を確認する
openssl rsa -text -pubin  < $CN.pub

echo "-------------------------------------------------------"
echo PKCS#12作成
openssl pkcs12 -export -in $CN.crt -inkey $CN.key -out $CN.p12 -password pass:$PP

echo "-------------------------------------------------------"
echo "PKCS#12確認"
openssl pkcs12 -in $CN.p12  -info -noout -password pass:$PP

```

# 参考
* [https://www.dondari.com/OpenSSL CSR生成スクリプト](https://www.dondari.com/OpenSSL_CSR%E7%94%9F%E6%88%90%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88)
laravel pluckメソッドの挙動について

pluckメソッドでkeyとvalueを取得して、toArrayでコレクションを配列にする。
ちなみにコレクションとは配列を拡張したLaravel独自の型のこと
Laravel側からデータベースを取得したときは、コレクション型になっている。

```php

public function index()
 {
  $tags = Tag::pluck('title', 'id')->toArray();
  dd($tags);
 }
```

結果

```
array:10 [▼
  1 => "タグ1"
  2 => "タグ2"
  3 => "タグ3"
  4 => "タグ4"
  5 => "タグ5"
  6 => "タグ6"
  7 => "タグ7"
  8 => "タグ8"
  9 => "タグ9"
  10 => "タグ10"
]
```

注意点としては、pluckメソッドの第1引数がvalueで、第2引数がkeyとなる。
試しにpluckメソッドの引数を逆にしてみる。

```php

public function index()
 {
  $tags = Tag::pluck('id', 'title')->toArray();
  dd($tags);
 }
```

出力結果

```
array:10 [▼
  "タグ1" => 1
  "タグ2" => 2
  "タグ3" => 3
  "タグ4" => 4
  "タグ5" => 5
  "タグ6" => 6
  "タグ7" => 7
  "タグ8" => 8
  "タグ9" => 9
  "タグ10" => 10
]
```

titleがkeyになり、idがvalueとなりました。

何か間違っている点があればアドバイスお願いします。ありがとうございました。
特定のポート番号を使用しているプロセスを見つけ、終了する方法

ローカル開発時に、プロセスの占有により、アプリケーションが起動不可になることがよくあるので、対処方法の覚え書きを残しておきます。

## 環境
- OS：WIndows10
- 使用ツール：コマンドプロンプト

## 手順
### 1. 特定のポート番号を使用しているプロセスの確認
以下のコマンドを実行する

```
> netstat -ano | find "<ポート番号>"
```

|コマンド（オプション）|用途|
|---|---|
|netstat|ホストのネットワーク接続状態やソケット／インターフェイスごとのネットワーク統計の確認など|
|（-a）|現在のすべての接続を表示|
|（-n）|出力をIPアドレスなど数値のみに抑制|
|（-o）|プロセスIDを表示|
|find|テキストの検索|

【例】ポート番号が8080の場合は、以下の通り

```
> netstat -ano | find "8080"
```

### 2. プロセスを終了させる

```
> taskkill /f /pid <プロセスID>
```

|コマンド（オプション）|用途|
|---|---|
|taskkill|タスクを終了させる|
|/f|強制終了|
|/pid|プロセスIDの指定|


【例】1の実行結果が

```
> netstat -ano | find "8080"
  TCP         0.0.0.0:8080           0.0.0.0:0              LISTENING       31712
  TCP         [::]:8080              [::]:0                 LISTENING       31712
```
だった場合は以下の通り

```
taskkill /f /pid 31712
```

## 参考
- [Windows で実行中のプロセス（タスク）を終了 (kill) する (taskkill) | まくまくWindowsノート](https://maku77.github.io/windows/admin/taskkill.html)
- [netstat ～ホストのネットワーク統計や状態を確認する | @IT](https://www.atmarkit.co.jp/fnetwork/netcom/netstat/netstat.html)
- [find テキストの検索 | Windowsコマンド集](https://xtech.nikkei.com/it/free/NT/WinKeyWord/20040805/1/find.shtml)
- [特定のポート番号を使用しているプロセスの見つけ方 | Qiita](https://qiita.com/riekure/items/39eba9b4857372bea766)
CloudFunctionsで文字列をハッシュ化したいならcrypto

複雑な家庭の事情でどうしてもfirebase上のアプリで任意の値をMD5にしなければならなかったのでメモ。

nuxt上でなんか処理しようかとおもったがいいライブラリがなく、CloudFunctionsならNode.jsなのでcryptoモジュールが使えることに気づいた。

```/functions/index.js
const crypto = require('crypto');
const hash_ni_shitai_value = "ハッシュ化したい値";
const hash_ni_natta_value = crypto.createHash('md5').update(hash_ni_shitai_value).digest('hex');
return hash_ni_natta_value;
```

phpの`md5($str)`ほど短くはないけどこれが最短なのでは。
FirebaseHosting + CloudFunctionsでクライアントのIPを取得する方法

複雑な家庭の事情でどうしてもfirebaseを使いつつクライアントのIPアドレスを取得しなくてはならなかったのでメモ。

前提として、フロントはNUXTでつくってます。

#### バックエンド（CloudFunctions側）

```/functions/index.js
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp(functions.config().firebase);

exports.getIp = functions.https.onCall((data, context) => {
  const clientIp = context.rawRequest.headers['x-appengine-user-ip'];
  return clientIp;
});
```
- firebase内でのリクエストなのでfunctions.https.onCall()を使用
- onCall((data, context)
    - dataにはリクエスト時に投げた値が入りますが、今回は何も投げません
    - contextにはリクエストする側の認証情報が入ります
    - 詳しくは[公式説明で](https://firebase.google.com/docs/functions/callable?hl=ja)
- context.rawRequest.headers['x-appengine-user-ip']でIPが取得できます
- リクエストヘッダーの値についての詳しい情報も[公式説明で](https://cloud.google.com/appengine/docs/standard/go/reference/request-response-headers?hl=ja)

#### フロントエンド（NUXT側）

```/pages/index.vue
  created() {
    const getIp = firebase.functions().httpsCallable("getIp");
    getIp().then((response) => {
      console.log(response)
    });
   },
```

- httpsCallableで関数を指定
- ページ読み込んだらすぐに確認できるようcreatedに書いてます
GPUサーバにSSH接続して、Docker上で起動したJupyter notebookをブラウザで開きたい

#はじめに
研究室のGPUサーバ(DGX-1)上でjupyter notebookを使って解析を行っているのですが、手順を忘れそうなので備忘録として書きました。dockerやSSHなどについては詳しくないで実行するコマンドのみを記しています。
#1. jupyter notebookが入ったDockerイメージを作成
私の作成したdocker fileです。
https://github.com/henyo245/docker_note_gpu/blob/master/dockerfile
#2. gunzipに圧縮

```
$ docker save image_name | gzip > [イメージ名].tar.gz
```

#3. SCPでguznipをサーバに転送

```
$ scp ~/Desktop/[イメージ名].tar.gz henyo245@[サーバのアドレス]:/home/henyo245/
```
#4. gunzipを解凍

```
$ docker load < [イメージ名].tar.gz
```

#5. Dockerコンテナを作成
-pオプションでポートを指定する。
`-p <分析サーバーのport番号>:<コンテナのport番号>`なので
　コンテナのport番号:8888
　分析サーバーのport番号:9000
とすると次のようになる。


```
$ nvidia-docker run -it -p 9000:8888 [イメージ名] /bin/bash 
```

これでコンテナに入れる。
#6. jupyter notebookを起動

```
# jupyter notebook --allow-root
```
tokenなしでjupyter notebook起動したい場合は、オプションで`--NotebookApp.token=''`をつける。
#7. ポートフォワード
`-L <localのport番号>:localhost:<分析サーバーのport番号>`なので、
　localのport番号: 8888
とすると次のようになる。

```
$ ssh -L 8888:localhost:9000 henyo245@[サーバのアドレス]
```


#8. ブラウザでJupyter notebookを開く
URLに`http://localhost:<分析サーバーのport番号>`を入力。今回の場合は、
`http://localhost:9000`となる。
paiza スキルチェック過去問題集 「Cランク相当 検索履歴」について


（問題）
https://paiza.jp/works/mondai/skillcheck_archive/search_history?language_uid=python3

（Javaで解いた動画）
https://paiza.jp/works/skillcheck/primer/skillcheck4　

この問題の回答がなかったので、自分の復習もかねて回答コードを掲載します。
問題文は以下の通りです。

>あなたが利用しているブラウザでは検索ワードの履歴を見ることができません。あなたは検索ワードの履歴を見られないのは不便だと思ったので、検索ワードの履歴を見る機能を自分でつくることにしました。

>検索ワードの履歴とは次のようにつくられます。

>検索ワード W が以前に入力されたことがある場合：
履歴中の W を削除する。
履歴の先頭に W を追加する。
検索ワード W が以前に入力されたことがない場合：
履歴の先頭に W を追加する。

>検索ワード W が N 個与えられるので、N 個の検索ワードが与えられた後の履歴を表示するプログラムを書いてください。

問題文だけでは少しわかりにくいという方は、リンク先を見ていただくと、具体例が載っているので理解できると思います。


#回答の指針
標準入力１行目に、検索ワード数をあらわす整数Nが与えられます。続く２行目以降で、１行に１単語ずつ検索したワードが与えられます。
予め空のリストを作成しておき、１行ずつワードを見て、リスト内にそのワードがない場合はリストに格納し、リスト内にそのワードがあった場合はリスト内の該当ワードを削除したうえでリストに付け加えると、与えられた条件にマッチしそうです。

```python

#整数Nの取得
n = int(input())
#空のリスト
words=[]

#1行ずつワードを取得する
for i in range(n):
    W = str(input())
#リスト格納前にif文で取得したワードがリストに含まれているかを確認する
    if W in words :
        words.remove(W) #リストにある場合はリスト内のワードを削除する
    words.append(W) #リスト内の有無にかかわらず追加するのでappend()メソッドはこの位置
```

結果を表示する際に、一行ずつ、リストに新しく追加された順番という条件があるので、それにあった答えを出力します。

```python

#結果を表示する
for i in range(int(len(words))):
    print(words[-i-1])
```
これで完成です。
macOS Catalina で sudo 実行時、AppleWatchで認証する。

端末から `sudo` を実行した際に Touch ID で認証を行う方法がありますが、これを Apple Watch で行う方法です。
確認した環境は以下の通りで、他の環境では試せていませんが、APIの都合で Catalina 以降でしか使えないようです。

- Mac mini 2018 (macOS Catalina 10.15.4)
- Apple Watch Series 5 (watchOS 6.2.1)

## PAM WatchID

https://github.com/biscuitehh/pam-watchid

### インストール

上記からソースをクローンしてインストールします。（事前にコマンドライン開発環境は必要ですが割愛）

```
$ git clone https://github.com/biscuitehh/pam-watchid.git
$ cd pam-watchid
$ sudo make install
```

### pam編集

次に `/etc/pam.d/sudo`を編集し、コメントを除いた最初の行にインストールした `pam_watchid.so` を記述します。引数に `reason=` 以降を加えるとそれが認証ダイアログで表示されるようなので、入れてみます。

```diff
--- sudo	2020-05-03 03:52:15.000000000 +0900
+++ sudo	2020-05-03 03:50:51.000000000 +0900
@@ -1,4 +1,5 @@
 # sudo: auth account password session
+auth       sufficient     pam_watchid.so "reason=管理ユーザとして認証"
 auth       sufficient     pam_smartcard.so
 auth       required       pam_opendirectory.so
 account    required       pam_permit.so
```

`sudo vi /etc/pam.d/sudo` などとした場合には `:w!` などで強制的に保存してください。

### 動作内容

これで次回以降 `sudo` 実行時に次のような画面が現れ
![スクリーンショット](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1095/02290d08-cead-cd52-c853-289cb0a7579d.png)


Apple Watch 側で認証を求める次のような画面が表示されます。

![AppleWatch](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1095/ea5ef915-ee55-ce0b-ba76-0a9a084ccc11.png)
node.jsでLINE Notifyを使ってみた

# 概要
webサービスやバッチ処理を作っていると、何かアクションがあった事をすぐに気づきたいと思うことがあるかと思います。
この通知がよく使うアプリに送られて来たら気づきやすいですよね！？

よく使うアプリは人それぞれかと思いますが、LINEは多くの人が利用しているかと思います。
そして、LINEでは個人で簡単に通知を投げられる機能 [LINE Notify](https://notify-bot.line.me/ja/) を提供しています。

ここでは、LINE Notifyのパーソナルアクセストークンでの通知をnode.jsを用いて行うまでの軌跡をまとめています。

# ざっと全体の流れ
手順はざっと以下な感じ。

1. LINE) パーソナルアクセストークンを取得
2. 開発) アクセストークンを使ってrequestを投げる
3. LINE) 通知が届いた事を確認

とても簡単！

# 手順
## 1. パーソナルアクセストークンを取得
LINEアカウントを持っていれば簡単に作れます。

### 1-1. LINE Notifyページへ遷移
以下URLよりLINE Notifyのページへ遷移しましょう。
https://notify-bot.line.me/ja/

### 1-2. LINE ログイン
LINEにログインします。
メアドやパスワード登録がされている必要があります。
また、LINEアプリでPCでのログインを許可していないと弾かれるので、事前に外しておきましょう。

### 1-3. マイページに遷移
右上のアカウントメニューよりマイページに遷移。

### 1-4. アクセストークンの発行
マイページにある「アクセストークンの発行(開発者向け)」より、「トークンを発行」をクリックし、
トークン名や通知したい先を選択して発行！

### 1-5. アクセストークンをメモ
発行するとアクセストークンが表示されます。
このトークンは再発行されないので、確実にメモリましょう。
また、このトークンが流出すると、第三者が投稿し放題なので取り扱い要注意。

---
![LINE_Notify.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630783/ea5c6805-b268-31c6-8dfa-35714a356fdc.png)
---

ここまででLINE Notifyの準備は完了です！

# 2. アクセストークンを使ってrequestを投げる
取得したTokenを利用して通知してみます。
ざっくり言うと、POSTでトークンをheaderに添えてメッセージ投げれば投げれます。簡単！

詳しいリクエスト方法は公式ドキュメントをみていただけたらと思います。
[LINE Notify API Document](https://notify-bot.line.me/doc/ja/)
（"通知系"項目が本記事で利用しているパーソナルアクセストークンでの通知です）

node.jsだとこんな感じで投げられるかと思います。
(requestモジュールがinstallされている前提)

```javascript:app.js
const request = require('request');

const message = `これは
テスト
ですよ`;

sendRequest(message);

/**
 * LINE Notifyへ送信依頼
 * @param {Object} message - 送信メッセージ
 */
function sendRequest (message) {
  const options = {
    uri: 'https://notify-api.line.me/api/notify',
    headers: {
      // TOKENを誤ってgitに上げてしまわないように、環境変数から取得するようにした
      'Authorization': `Bearer ${process.env.LINE_TOKEN}`
    },
    form: {
      message
    }
  };
  
  request.post(options, (error, response, body) => {
    if (error) {
      console.error(error);
      return;
    }
  
    console.log(body);
  });
}
```

実行

```
$ LINE_TOKEN=<取得したTOKEN> node app.js
{"status":200,"message":"ok"}
```

LINEの通知先にLINE Notifyさんが通知してきたら成功です。
(どのTOKENから通知されたかは、メッセージの先頭にテキストでTOKEN名が書かれています)

# 終わりに
利用準備も簡単で、実装もシンプルなのですぐに通知を実装したい時とか便利なのではないでしょうか？
ただし、1時間に叩けるAPIの上限はトークンごとに1000回までらしいのでご注意ください。
（1000回/時 LINE API叩く仕様見直したほうが良さそうですががが）
ubuntu18.04以降でウィンドウを４画面にする方法 (chromeで)

以下の図のように「画面を４分割して作業したいなぁ」と思っていたが，検索しても18.04より前版だったり，出てこなかったりしました．

ウィンドウ分割の操作はWindows10と同じコマンドでできました．
また，ユーザレビューには「Ubuntu20.04でもできたよ」とコメントがありました．
![snapping_4windows.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128943/21c13771-5344-56dd-5393-593a5348b5aa.png)
リンクしか貼ってませんが，この手順を踏めばできます．

# 今回の環境
- Ubuntu18.04
- Gnome Shell 3.28.4
- Google Chrome
- chrome-gnome-shell

firefoxなどの他のブラウザでは検証していません．

# 結論
ブラウザ操作が多く，画像を貼るのが大変だったので，参考元を見るのが早い．
1から順番に実行してみてください．
1. [WebブラウザからGNOME Shell拡張機能をインストールできるようにする](https://linuxfan.info/setup-gnome-shell-extensions)
2. [４画面にする拡張機能をインストール](https://www.linuxuprising.com/2020/02/wintile-for-gnome-shell-windows-10-like.html)

# どんなことをしているか
1. GNOME Shellとブラウザのコネクタ(chrome-gnome-shell)をインストール
2. ChromeなどのブラウザにGNOME Shell integrationをインストール
3. 簡単に拡張機能を切り替えできる拡張機能であるExtensionsをインストールする
4. ウィンドウを４分割する拡張機能であるWinTileをインストールする

# 参考資料
- [GNOME Shellのカスタマイズに必須！拡張機能をインストールする方法](https://linuxfan.info/setup-gnome-shell-extensions)
- [WinTile For GNOME Shell: Windows 10 Like Quarter Tiling (Snapping) With Super/Win + Arrow Keys Or Mouse](https://www.linuxuprising.com/2020/02/wintile-for-gnome-shell-windows-10-like.html)
- [wintile のGithubホームページ](https://github.com/fmstrat/wintile)
OkHttp の Intercepter で出るエラー( java.lang.NoSuchMethodError: No static method metafactory )

# 背景

MVVM の復習のために久しぶりに github API を Retrofit2 でたたくサンプルアプリを作成していた。

参考サイト　https://tech.mti.co.jp/entry/2020/03/31/163321

# エラーの内容
こんな感じのエラーが出てくる

```
java.lang.NoSuchMethodError: No static method metafactory(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; in class Ljava/lang/invoke/LambdaMetafactory; or its super classes (declaration of 'java.lang.invoke.LambdaMetafactory' appears in /apex/com.android.runtime/javalib/core-oj.jar)
        at okhttp3.internal.Util.<clinit>(Util.java:87)
        at okhttp3.internal.Util.skipLeadingAsciiWhitespace(Util.java:321)
```

# 解決策

これを Gradle　(Module:app) に追加したら行ける

``` build.dradle
android {

    ...
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    kotlinOptions {
        jvmTarget = "1.8"
    }
}
```
MVCモデルをもう一度振り返ろう！

#MVCモデルをもう一度振り返ろう！
MVCモデルとはモデル(M)、ビュー(V)、コントローラー(C)の3つに役割を分けて開発を行う設計パターンです。
railsなどもMVCモデルに基づいて作られています。

##MVCモデルのそれぞれの役割

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629620/068ffd73-21b4-e199-7b2d-187a0e72aa86.png)

MVCモデル参考イメージ出典：https://www.katonobo.com/entry/what_is_MVC

・モデル(model)：表示や入力に関連しない処理
・ビュー(view)：表示や入力に関する処理
・コントローラー(controller)：ビューとモデルの橋渡し役

という役割とされています。
役割を聞いただけですとよくわからなかったのですが、私のイメージですと、、、
・モデルはデータをコントローラーに引き渡す役
・ビューは見た目の役
・コントローラーは上記の理解

といった解釈をしています。
もっと分かりやすい解釈がありましたらご教授お願いします！

##twitterを例にMVCモデルの働きを見てみよう！
MVCモデルの働きをtwitterにツイートを投稿した時を仮定して流れを考えてみます。

ユーザーがツイートを投稿したとします。

ビューでツイートを取得します。
　　　　　↓
ツイートデータはコントローラーへ行きます。
　　　　　↓
ツイートデータはコントローラーからモデルへ引き渡されます。
　　　　　↓
モデルにきたツイートデータはデータベース(テーブル)に保存されます。
　　　　　↓
データベースに保存されたツイートデータは、またモデル、コントローラーを通りビューへいきます。
　　　　　↓
ここでビューにツイート内容が表示され、私たちの目に見える状態になります。

以上でMVCモデルの説明を終わります。
間違いなどがありましたらご指摘いただければ幸いです。
最後までご覧いただきありがとうございました！
PHP 関数について

#関数とは
処理をまとめて名前をつけたもので、関数を呼び出す事で必要な値などを簡単に得る事ができます。

###関数の種類
組み込み関数とユーザー定義関数がある。

####組み込み関数
元々PHPに定義されている関数で、関数を呼び出すだけで簡単に使用出来る。
使い方はPHPマニュアルの関数リファレンスに載っている。（https://www.php.net/manual/ja/funcref.php）

####ユーザー定義関数
自身で定義が出来る関数

##基本的な書き方
関数を定義する場合は、`function`を最初に記述する。

```php

function 関数名(引数){
  処理
}

//関数の呼び出し
関数名();
```

###例文

```php
//関数の定義
function getWord($word){
  echo $word;
}

//関数の呼び出し
getWord('こんにちは');
```

解説をすると、`function getWord`でユーザー定義関数（getWord)を定義しています。そのあとの`($word)`は引数にあたります。例文では`$word`という変数が引数になっています。
処理は`echo`で`$word`という引数を表示させるというふうになっています。
次に関数の呼び出しですが、`getWord`の後に`('こんにちは')`とあると思いますが、この'こんにちは'が引数にあたります。従って、呼び出した関数`getWord`の引数`こんにちは`が、定義した`getWord`の引数にそのまま代入されます。よって`echo`で出される値は`こんにちは`になります。
以上、簡単ではありますが、関数の基本について書いてみました。
ご意見、ご指摘等ありましたらどんどんお願いします！！
備忘録　render partialで部分テンプレートを表示しよう

# 共通のビューを部分テンプレートを使って表示

renderメソッドのパーシャルオプションを使って共通部分を表示しましょう。

部分テンプレートとしてビューファイルを作成する時は　\_hogehoge.html.erbのようにファイル名の前に_（アンダースコア）をつける必要があります。
次のように書くと部分テンプレートをビューに表示できます。

```ruby
render partial: 'hogehoge'
```

別ディレクトリに部分テンプレートのデータがある場合は

```ruby
render partial: 'ディレクトリ名/hogehoge'
```

で呼び出せます。

### localsオプション

localsオプションを使うと部分テンプレート内で使う変数の定義をすることができます。

```ruby
render partial: 'ファイル名',locals:{ '部分テンプレート内で使う変数': '変数に入れる値' }
```

変数は複数指定することも可能です。

```ruby
render partial: 'ファイル名', locals:{ dog: "ぽち", cat: "たま", pig: "ぶー" }
```

```html
<p>この子たちの名前は<%= dog %>,<%= cat %>,<%= pig %> です<p>
<!-- この子たちの名前はぽち、たま、ぶーです -->
```

### 部分テンプレート内ではインスタンス変数を使わないようにしよう

部分テンプレートに直接インスタンス変数を書いてしますと、
インスタンス変数の定義に依存した書き方になってしまい、再利用性が低下してしまうため。

```ruby
render partial: 'ファイル名', locals:{ hoge: @hoge }
```
このようにlocalsオプションでローカル変数に代入してあげましょう。
tax_free、茶色になったってよ。

### 茶色になりました
わーい。
<img width="637" alt="スクリーンショット 2020-05-02 23.25.00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273421/c3d5fc3b-efd6-dc7f-8d6d-9b3f6d9a4833.png">

凡人の私が茶色になるためにしたことを、書いていきます。

### スペック

- 数弱(偏差値60くらい)
- Pythonは一年くらい触ってた
- 始めたのは高校一年
- 普通の高校で、某つよつよ高校みたいに校内につよい先輩はいない
- 三日坊主

### やったこと
<img width="1285" alt="スクリーンショット 2020-05-03 2.05.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273421/78c3dfcf-f21b-75f9-6b0f-f1651818121b.png">
精進グラフ

見てわかるとおり、最初の数ヶ月はほとんど精進していませんでした。
コンテストに出て、「解けなかったー」→復習しないで寝るレベルでした。先に書いたように私は数学への理解が深いわけでもなく、理解が早いほうではありませんので、精進無しでレートが上がるはずがありません。精進するようになったのは最近になってからで、正直気付くのが遅すぎました。

ABC-Aのpieを埋めたくて解いていましたが、途中で止めました。理由はA解くならCとか解いて、競プロの思考力をつけたほうがよさそうと考えたからです。実際Aは作業感が強く、頭をほとんど使っていませんでした。これは人によると思いますが、ある程度慣れてきたら、ABC-C,Dを解いたほうがいいと思います。もちろん、Aを埋めるのはいいことですが、モチベが最優先です。
おすすめの問題とかはもっとつよい人の記事を読んでください

あとはTwitterでつよい人、同年代の人をフォローして情報共有するのがいいと思います。
**フォロワー、絡んでくれた方々にとても感謝してます。ありがとうございます**

### まとめ
私は努力が必要なフェーズになると、堕落してしまう人ですが諦めずに緑を目指していきます。サボってたら、twitterでツンツンしてください
ではまた、おやすみなさい。