OmniAICreator/Qiita-1.07M huggingface dataset:
[C#] null許容参照時代のTry-Parseパターン

# Question

以下のメソッドは、trueを返す場合は`value`に非nullの値を格納し、falseを返す場合はnullを格納する。

```csharp
bool TryGetValue(string key, out string value) { ... }
```

では、このメソッドは、null許容参照型の導入時にどう変化させなければならないか。

```csharp
bool TryGetValue(string key, out string? value) { ... }
```

と書いてしまうと、呼び出し側で面倒なことになる。

```csharp
if (TryGetValue("hoge", out string? value)
{
    // nullを許容しない引数のメソッドに渡す際、!演算子が必要になる
    DisallowNullMethod(value!);
}
```

# Answer

`NotNullWhen`属性、あるいは、` MaybeNullWhen`属性をout引数に付ける。

```csharp
bool TryGetValue(string key, [NotNullWhen(true)] out string? value) { ... }
```

```csharp
bool TryGetValue(string key, [MaybeNullWhen(false)] out string value) { ... }
```

下の場合、引数の型がnullを許容しない型になるが、メソッド内ではout引数にnullを代入できる。

こう書いておくと、このメソッドがtrueを返したコンテキストに限り、`value`の値をnull非許容としてあつかえる。

```csharp
// メソッドを呼び出す際は、null許容型な必要がある
if (TryGetValue("hoge", out string? value)
{
    // ここではvalueをnull非許容として扱える
    DisallowNullMethod(value);
}
```

# 参考にした情報

https://stackoverflow.com/questions/55526064/trygetvalue-pattern-with-c-sharp-8-nullable-reference-types
https://www.misuzilla.org/Blog/2019/09/25/NullableReferenceTypes
AWS Glueのジョブで自動生成したコードをAthenaのパーティションに対応させたい

# はじめに
AWS Glueのジョブは自動的に変換スクリプトを作ってくれますが、Athenaのパーティションに対応していません。
ネットを色々見ましたが、全然上手くいかず困りましたがなんとかなったので、対応方法についてまとめました。

# 事前準備
事前にテーブルを作成します。
テーブルについてへGlueのGUI上からぽちぽちっと作成しています。
今回は同じテーブルでpartitionがないテーブルからparitionがあるテーブルに移行するとして記事を書いています。
b_tableはjsonで作成しています。
a_tableはなんでも良いです。（自分はCSVファイルをクローラーで読み込ませて作りました）
b_tableをjsonにした理由としては、CSVだとヘッダー行も生成されるせいかAthena上からクエリ発行できなかったからです。
Parquetで作りたかったのですが、上手くパーティションを認識してくれなかったので諦めました。
databaseは適当な場所でOKです。

```
a_table
id: bigint
name: string
date: string
```

```
b_table
id: bigint
name: string
date: string(partition)
```

ジョブの作成も必要ですが、ぽちぽちするだけなので割愛します。
スクリプトは自動生成しているものとします。

# スクリプトの編集
2箇所変更が必要です。
変更後のソースのみ記述しますが、自動生成したコードを検索するとすぐに分かるかと思います。

一つ目は`SelectFields.apply`を変更します。
自動生成では、パーティションについての記述がありませんが、`paths`に記述を追加してあげる必要があります。
今回は`date`を追加しています。

```
selectfields2 = SelectFields.apply(frame = applymapping1, paths = ["id", "name", "date"], transformation_ctx = "selectfields2")
```

次に`glueContext.write_dynamic_frame.from_catalog`を編集します。
これには`additional_options`を設定することができるので、ここにパーティション情報を設定していきます。
`partitionKeys`は`List`になっているため、複数設定することが可能となっています。
複数設定する場合はテーブルに設定したパーティションの順番と合わせて記載してください。

```
additionalOptions = { "enableUpdateCatalog": True "partitionKeys" : ["date"]}
datasink5 = glueContext.write_dynamic_frame.from_catalog(frame = resolvechoice4, database = "default", table_name = "b_table", additional_options = additionalOptions, transformation_ctx = "datasink5")
```

# 実行と確認
実行はGUI上から可能なので、しばらく待ちます。
終わったらGlueのテーブルからパーティションが出来ていることを確認したり、Athena上からクエリ投げたりして確認してみてください。

# 参考URL
https://dev.classmethod.jp/articles/aws-glue-now-supports-the-ability-to-update-partitions-from-glue-spark-etl-jobs/
SolitonNKの次期バージョンはどんな風になるだろうか？

SolitonNKの内部エンジンである Gravwell が近々大きなバージョンアップを予定しています。SolitonNKも、この新バージョンの Gravwell をそう遠くない時期に採用するはずですので、SolitonNKの新バージョンがどのように発展しそうなのかをご紹介したいと思います。今回の紹介内容は、既に公開されている情報をまとめていますが、Gravwell 新バージョン自体が未リリースですので、次期SolitonNKが必ずそうなると確約するものではありません。

# Big Bang

Gravwell について、次期バージョンについてこんなことが言われています。

「これこそが。スタート、時間の始まり...Gravwell宇宙は拡大している」

大袈裟に見えますが、SolitonNKの心臓部Gravwellは、そう表現したくなるぐらい、これまでになく大きく拡張・発展します。そして、その新バージョンには「Big Bang」（ビッグバン）と名付けられています。良く知られた、宇宙の最初に起こった急速な大膨張のことです。

「ビッグバン」と言わしめるほどの拡張機能には何があるでしょうか？新しい機能には大きく次の７つがあり、データ分析をより簡単に、より生産的に行うことができるようになります。

1. キット：これまでユーザが一つ一つ作って組み上げなければいけなかった、検索文、ダッシュボード、リソースなどが、予めパッケージ化されたものがキットです。キットは典型的な利用シーンに対応できるよう豊富に数多く用意され、迅速かつ適切なリアルタイムなデータ分析・可視化が簡便にできるようになります。
2. 検索文ライブラリ： よく使われる検索文を保存し、グループの他のメンバーと共有することができます。また、ラベルに基づいてフィルタリングしたり、基本的なテキスト検索を使用して検索することもできます。
3. プレイブック： ステップバイステップの手順、ドキュメント、設定済みの検索文を使って知識を共有できます。
4. SOARスクリプト： 新機能ではありませんが、デバッグ機能を拡張し、SOARスクリプトの開発と管理のUXが強化されます。
5. アクショナブル：Gravwellのテキスト表示において、登録された語と一致するテキストを「クリック可能」にするトリガーを設定し、クリックしてIPアドレスをクリックして詳細な調査できるようにしたり、AWSコンソールでAWSセキュリティグループを開くようにしたりすることができます。
6. マクロ：検索クエリ内での使用が可能になり、一般的なアクティビティを1つのマクロに縮小することが可能になりました（例：DNSエントリの結果一覧からMicrosoftドメイン削除する作業を頻繁にしている場合、それをマクロ化して作業を高速化することができます）。
7. テンプレート： 検索テンプレートはクエリライブラリに似ていますが、検索時に入力される変数を定義する機能が含まれています。これらは調査を行ったり、プレイブックの一部として利用するのに最適です。

# キット

“Big Bang”によって目覚ましい変貌を遂げるだろう次期SolitonNKの新しい機能の中でも、キットはその最も大きな機能拡張で、ユーザのデータ分析を極めて簡便にする効用があります。

キットについては、既にGravwellの[「コミュニティエディション」](https://www.gravwell.io/download)でそのいくつかが試用できるようになっています。

## Netflow キット

Netflow v5 キットは、Netflow インジェスターを活用するツールで、netflow 検索モジュールを多用しています。このキットには、Netflowデータ分析のため、すぐに使えるダッシュボード、クエリ、テンプレート、プレイブック、およびアクショナブルが用意されています。

## IPFIX キット
IPFIX キットは、Netflow インジェスターを活用するツールで、ipfix 検索モジュールを多用しています。このキットには、IPFIXデータ分析のため、すぐに使えるダッシュボード、クエリ、テンプレート、プレイブック、およびアクショナブルが用意されています。

## Grokキット
Grokキットには、インデクサーに蓄積されたデータの抽出にGrokパターンを使用できるようにするためのドキュメントと、パターンリソースファイルが含まれています。これにより、これまで多くの正規表現を組み合わせて作成しなければならなかった抽出パターンが大幅に簡素化されて活用できます。

## Network Data Fusionキット
このキットにより、より詳細ネットワークデータを得るために利用可能なリソースが得られるようになります。

## CoreDNS キット
CoreDNSキットは、Gravwell CoreDNSプラグインを活用するツールです。このキットには、CoreDNSデータ分析のため、すぐに使えるダッシュボード、クエリ、テンプレート、プレイブック、およびアクショナブルが用意されています。

## 天気 キット
現在の気象条件を[Open Weather](https://openweathermap.org/)から収集して場所を一覧で表示する学習キットで、付属のダッシュボードを使って確認できます。本体がリリースされてないのに、このキットは既にv2になってます。

# 待ち遠しい

Gravwellの新バージョン「Big Bang」は8月初旬に発表されて、リリースが間もなく出ると幾度となく伝えられているのですが、まだ本記事公開時点（2020.9.9）では正式リリースのアナウンスはありません。SolitonNKにもこれら新機能が取り入れられるものと期待しているのですが、待ち遠しいですね。

Soliton NK について、今後も記事を追加していく予定です。
【RubyMine】{} → do..endのブロック自動変換を無効にする

こういうやつ

![debug.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63597/eaa4de15-a3b3-92b0-e792-a2005b72d69c.gif)

blockのなかのロジックが複雑な時に改行して整えようとする時とかに煩わしいやつ


## 解決方法
Preferencesの`Convert {} blocks to do..end by Enter` のチェックを外せば良い
![スクリーンショット 2020-09-02 18.26.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63597/ac003770-5018-4c56-7c49-156695a53f46.png)
RubyMine2020.2時点
WordPressのバージョンを非表示にする方法【セキュリティ対策】

##はじめに

WordPressでホームページや作成すると、HTMLソース内にメタ情報としてWordPressのバージョンが記載されています。

例えば、WordPress 5.5を使用している場合は、次の通りです。

`<meta name="generator" content="WordPress 5.5"/>`

`<link rel='stylesheet' id='dashicons-css'  href='https://example.com/wp-includes/css/dashicons.min.css?ver=5.5' type='text/css' media='all' />`

攻撃者はWordPressに対して不正アクセスを試みる際に、ターゲットの情報収集から始めます。もし、脆弱性があるWordPressのバージョンを使用していることがわかれば、そこを狙った攻撃を行います。

逆に言えば、WordPressのバージョン情報を非表示にして、攻撃者に有用な情報を与えないことは、有効なセキュリティ対策の1つとなります。

この記事では、簡単なカスタマイズにより、HTMLソース内に出力されるWordPressのバージョンを非表示にする方法を紹介します。

##WordPressのバージョンを非表示にする方法

WordPressのfunction.phpに以下のコードを設置してください。
管理画面から、外観→テーマエディター→テーマファイルで編集できます。

```function.php
remove_action('wp_head','wp_generator');

function remove_wp_version( $src ) {
    if ( strpos( $src, 'ver=' . get_bloginfo( 'version' ) ) )
        $src = remove_query_arg( 'ver', $src );
    return $src;
}
add_filter( 'style_loader_src', 'remove_wp_version', 9999 );
add_filter( 'script_loader_src', 'remove_wp_version', 9999 );
```

上記コードは、head内のメタ情報を非表示にすると共に、CSSやJavaScriptにパラメータとして含まれるバージョン情報も非表示にしています。

WordPressのテーマによっては最初からバージョンを非表示に削除してくれるものもありますが、きちんと確認して、セキュリティ対策をしておきましょう。
HTTPSで通信する時のSNIを書き換える

# SNIの書き換え

サードパーティ製のhttpsクライアントを使っている時にSNIに対応していない為nginxなどでルーティングできない、実際とは違うSNIを試したい時があるかもしれない。

mitmproxyというproxyを使うことでSNIの書き換えができる場合がある。
今回は CONNECTメソッドが使えるクライアントを前提にしている。

ただしおそらく以下のURLのTransparent HTTPSの方式ならプロキシに対応していなくても書き換えられそうである。
https://docs.mitmproxy.org/stable/concepts-howmitmproxyworks

mitmproxyをpipなどでインストールする。
https://docs.mitmproxy.org/stable/overview-installation/

以下のプログラムをcustom_sni.pyとして保存する。

```python
from mitmproxy import ctx, http
import mitmproxy

def next_layer(layer: mitmproxy.proxy.protocol.Layer):
    if isinstance(layer,mitmproxy.proxy.protocol.TlsLayer):
        layer._custom_server_sni="<解決したいSNI>"
        
    return layer
```

前準備としてmitmproxyの証明書(~/.mitmproxy/mitmproxy-ca-cert.cer)を許可しておく。
その後以下を実行することで、8080ポートでプロキシを開始する。

```bash
mitmproxy -s custom_sni.py
```

あとは使いたいクライアントでプロキシ設定をすれば良い
DjangoでProgrammingError: (1146, "Table '<テーブル名>' doesn't exist")が発生したら

## はじめに
作成したDjangoアプリをAWS EC2にデプロイする過程でタイトルのエラーが発生しました。

原因がわからず苦労したので、解決方法を書き残しておきます。

## 環境
+ Amazon Linux 2(64bit)
+ Apache2.4.43
+ MySQL8.0.21
+ Python3.7.8
+ Django3.1

## エラー内容
ApacheやMySQLの設定を終え、Djangoの`migraioｎ`を実行した後、ブラウザからEC2のパブリックIPアドレスにアクセスすると次のようなエラーが表示されました。

`Django.db.utils.ProgrammingError: (1146, "Table '<テーブル名>' doesn't exist")`

文字通りテーブルが存在しないよーというエラーです。

ローカルでSQLite３を使っていたときはうまくいっていたので、サーバ内のMySQLの設定がおかしいのかと思い色々いじってみたがうまく行かず…

そこでDjangoのアプリ構成をもう一度よく見返してみると、作成されているはずのmigrationファイルが存在しないことに気づきました。migrationがうまく行われていないようです。

## 原因と解決法
今回デプロイしたDjangoプロジェクトは１プロジェクトの下に２つアプリという構成でした。

その場合はどうやら`python3 manage.py makemigraions <アプリ名>`のようにアプリ名を指定しないと、正しくmigrationが実行されないことがあるようです。

そこで今度は

`python3 manage.py makemigraions <アプリ名>`
`python3 manage.py migrate`

と実行したところ、テーブルが作成され、上記のエラーが解消しました。

同じような事象に悩まされている方はぜひ試してみてください。

## 参考
[django model を作成したが、makemigrations で No changes detected になる| Monotalk]
(https://www.monotalk.xyz/blog/django-model-%E3%82%92%E4%BD%9C%E6%88%90%E3%81%97%E3%81%9F%E3%81%8Cmakemigrations-%E3%81%A7-no-changes-detected-%E3%81%AB%E3%81%AA%E3%82%8B/)
npm run dev で起動したサーバーに外部からアクセスする(webpack-dev-server)

# はじめに
はじめてvueでSPA作ろうと思い `npm run dev` してみたはいいものの外部からのアクセスができず躓いてしまったので備忘録。

# プロジェクト作成から起動まで
※vue-cliがインストールされていない方はつぎのコマンドで。

```
$ npm i -g @vue/cli
```

### 1. プロジェクト作成
```
$ vue init webpack-simple <プロジェクト名>
```

### 2. モジュールインストール
```
$ cd <プロジェクト名>
$ npm i
```

### 3. 起動
```
$ npm run dev
> vue_test_app@1.0.0 dev /home/treskot-test/vue_test_app/vue_test_app
> cross-env NODE_ENV=development webpack-dev-server --open --hot

Project is running at http://localhost:8080/
webpack output is served from /dist/
404s will fallback to /index.html
Unable to open browser. If you are running in a headless environment, please do not use the open flag.
{ parser: "babylon" } is deprecated; we now treat it as { parser: "babel" }.
```

# 外部からアクセスできない :frowning2:
※後日追記予定
<input type="number">のスピンボタン（上下の矢印ボタン）をCSSで非表示にする


![screen_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94442/9be60808-ea6e-8e0c-be6a-bfa1fb10e712.png)
この矢印のやつを消す方法です。

### Chrome, Safari
```css:CSS
input[type="number"]::-webkit-outer-spin-button, 
input[type="number"]::-webkit-inner-spin-button { 
  -webkit-appearance: none; 
  margin: 0; 
} 
```
### FireFox， IE
```css:CSS
input[type="number"] { 
  -moz-appearance:textfield; 
} 
```

### CSSのクラスを指定して、Chrome, Safari, FireFox， IE まとめて書く
```css:CSS
.no-spin::-webkit-inner-spin-button,
.no-spin::-webkit-outer-spin-button {
    -webkit-appearance: none;
    margin: 0;
    -moz-appearance:textfield;
}
```
```html:HTML
 <input type="number" class="no-spin">
```

### CSSのクラスを指定して、!importantで最優先にしてまとめて書く
```css:CSS
.no-spin::-webkit-inner-spin-button,
.no-spin::-webkit-outer-spin-button {
    -webkit-appearance: none !important;
    margin: 0 !important;
    -moz-appearance:textfield !important;
}
```

![screen_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94442/48c126a8-73b4-1d41-e076-7d07a2d6633f.png)
消えました！

##### 参考URL：
[数字のみを入力できるフォーム(テキストボックス)を作成する](https://qiita.com/Avocado/items/2148d3af400823f91ea5)
[HTML5入力タイプの数値矢印をCSSクラスで非表示にしますか？](https://www.it-swarm.dev/ja/css/html5%E5%85%A5%E5%8A%9B%E3%82%BF%E3%82%A4%E3%83%97%E3%81%AE%E6%95%B0%E5%80%A4%E7%9F%A2%E5%8D%B0%E3%82%92css%E3%82%AF%E3%83%A9%E3%82%B9%E3%81%A7%E9%9D%9E%E8%A1%A8%E7%A4%BA%E3%81%AB%E3%81%97%E3%81%BE%E3%81%99%E3%81%8B%EF%BC%9F/1056353956/)
[INPUTタグ type numberの時に表示される矢印ボタン(スピンボタン)を消す方法](https://hirooooo-lab.com/development/html5-input-type-number-customize/)
[とほほのWWW入門 > CSS - !important](http://www.tohoho-web.com/css/rule/important.htm)
Dockerを理解する

#プログラミング勉強日記
2020年9月2日
コンテナ仮想化技術であるDocker(ドッカー)についてまとめる。

#Dockerとは
　Dockerはコンテナ型仮想化と呼ばれる技術の1つである。
　サーバー仮想化は、物理サーバーの上に仮想的なサーバーである仮想サーバーを複数作り貸すことができ、この仮想サーバーは本物のサーバーと同じようなふるまいをする。
　コンテナ型仮想化はOSの上にコンテナと呼ばれる仮想的なユーザがアプリケーションを実行するためのリソースが提供されるユーザ空間を提供する。通常は1つのOSの上に1つのユーザ空間があるが、コンテナ型仮想化では1つのOSの上で仮想的なユーザ空間であるコンテナを複数提供することができる。

#良いところ
　Dockerはあらかじめ設定した環境をどんなマシン上でも瞬時に立ち上げることや、瞬時に削除することができる。つまり、<font color=blue>すぐに使える</font>ということが大きな利点である。
　冪等性(べきとうせい)と呼ばれる何回実行しても結果が変わらない性質があるので、何度立ち上げても同じ開発環境が立ち上がる。

#参考文献
[注目を浴びる「Dockerコンテナ」、従来の仮想化と何が違うのか？](https://cn.teldevice.co.jp/column/10509/)
Scalaで定数を宣言するときは final val を付けると良さそう

コードレビューしてたら、その昔強い人に教えてもらったこと思い出したのでメモ。

`val Count = 1000` みたいな定数を宣言するときに `final val` にするとコンパイルしたときにインライン展開されて定数を読みに行く必要がなくなるので良さそうという話。

実際に中身を確認してみると...

```scala
$ cat Example.scala
class Example {

  val CountVal            = 100
  final val CountFinalVal = 100
  lazy val CountLayVal    = 100

  def myPrint(c: Int): Unit = print(c)

  myPrint(CountVal)
  myPrint(CountFinalVal)
  myPrint(CountLayVal)

}

$ scala -Xprint:jvm Example.scala
[[syntax trees at end of                       jvm]] // Example.scala
package <empty> {
  class Example extends Object {
    final <synthetic> lazy private[this] var CountLayVal: Int = _;
    @volatile private[this] var bitmap$0: Boolean = _;
    private[this] val CountVal: Int = _;
    <stable> <accessor> def CountVal(): Int = Example.this.CountVal;
    final <stable> <accessor> def CountFinalVal(): Int(100) = 100;
    private def CountLayVal$lzycompute(): Int = {
      Example.this.synchronized(if (Example.this.bitmap$0.unary_!())
        {
          Example.this.CountLayVal = (100: Int);
          Example.this.bitmap$0 = true
        });
      Example.this.CountLayVal
    };
    <stable> <accessor> lazy def CountLayVal(): Int = (if (Example.this.bitmap$0.unary_!())
      Example.this.CountLayVal$lzycompute()
    else
      Example.this.CountLayVal: Int);
    def myPrint(c: Int): Unit = scala.Predef.print(scala.Int.box(c));
    def <init>(): Example = {
      Example.super.<init>();
      Example.this.CountVal = 100;
      Example.this.myPrint(Example.this.CountVal());
      Example.this.myPrint(100);
      Example.this.myPrint(Example.this.CountLayVal());
      ()
    }
  }
}
```

> Example.this.myPrint(100);

確かに、インライン展開されてることが確認できます。良さそう!!!
getStaticPropsはJSONで返さない方が良い

## はじめに
Next.jsの勉強をしていて、すこしハマったことがあったので備忘録として共有しておきます。

## 結論
結論から言うと、getStaticPropsはJSONで返さない方が良いです。
なぜなら動的ルーティングで```fallback: true```にしてプリレンダリングする時、プリレンダリングされてないURLが叩かれた時、新たにページにレンダリングが走るのだが、もしもそのページの情報が無い場合、```undefined```がpropsで渡され、JSON.parseによってオブジェクトに変換する際に```undefined```のためエラーが吐き出されるから。

## 環境

- Next.js v9.4.0

## 動的ルーティングをプリレンダリングする時

それは動的ルーティングをプリレンダリングする際に発生しました。
getStaticPathsでプリレンダリングするパスを生成し、getStaticPropsでそのパスに対応したページの情報を取得し、コンポーネントで吐き出しをするのですが、

```react
function Post({ post }) {
  const postData = JSON.parse(post)// ここでエラー発生！！！！！！！！！！！
  // getStaticPropsで取得された情報(post)を吐き出す
}
export default Post

export async function getStaticPaths() {
  const res = await fetch('https://*************/***')
  const datas = await res.json()
  const paths = datas.map((data) => ({
    params: { id: post.id ),
  }))
   return { paths, fallback: true }
}

export async function getStaticProps({ params }) {
  const res = await fetch(`https://*******/*****/posts/${params.id}`)
  // この時JSONに変換してpropsに渡していた
  return { props: { res } }
}
```

このようにgetStaticPropsで取得した情報をJSONにしてpropsに返していた。

### その結果
ビルド時に上の2行目でエラーが吐き出された。
理由はもしも叩かれたURLが無い場合、```undefined```がpropsで渡され、JSON.parseによってオブジェクトに変換する際に```undefined```のためオブジェクトに変換できず、エラーが吐き出されてしまうから。

## 解決策
getStaticPropsはJSONでreturnせずにオブジェクトに変換して返しましょう！

## 訂正
ある日、
> これ、getStaticPathsで fallback: true にしなくてもデータとってこれない時あるくない？

と指摘があり、考えてみると確かにgetStaticPath関係なしにプリレンダリング時にデータとってこれない時あるな、と思ったので結論にて訂正します！

## 結論

getStaticPropsはJSONでreturnせずにオブジェクトに変換して返しましょう！

（P.S. getStaticPropsでデータとってこれなかったときは例外処理をしてビルドが通らないようにしましょう！)
Imagemagickで画像を縦横に連結する方法

いつも忘れるので、自分用メモ。

#結合

```bash
montage -tile (横)x(縦) -geometry 100% *.png output.png
```

```-geometry``` の値はお好みで。元画像たちをこのサイズにしてから連結する。
記述しないと自動でリサイズされてしまい、なんだかなぁな出来栄えになる。

※追記：元の画像が小さいと、100%指定するだけでは余白が生まれてしまう。余白が必要ない場合は```100%+0+0```とする。

一列につなげたい場合は単にappendでもよい。結果は同じ。

```bash
convert -append *.png output.png #縦につなげる
convert +append *.png output.png #横につなげる
```

#連番・ワイルドカード指定

ファイル指定にはワイルドカードが使える。 ```*``` は任意の文字列、 ```?``` は任意の一文字を表し、マッチするファイルすべてを選択することができる。

```bash
icon-?.png
#icon-a.png, icon-b.png...などとマッチ

icon-*.png 
#icon-a, icon-b, icon-facebook, icon-twitter...などとマッチ
```

連番を指定することもできる。

```bash
montage -tile 5x4 icon-%d.png[1-20] output.png
#icon-1.png, icon-2.png, ..., icon-20.pngを並べる
```

この指定方法では、icon-01.pngのようにゼロ埋めしてあるとエラーになってしまう。その場合は桁数を指定すればよい。

```bash
montage -tile 5x4 icon-%03d.png[1-20] output.png
#icon-001.png, icon-002.png, ... , icon-020.pngを並べる
```

### 参考
[コマンドラインのドキュメント(公式)](https://imagemagick.org/script/command-line-tools.php)
[入力ファイルの指定方法(公式)](https://imagemagick.org/script/command-line-processing.php#input)

かなりいろんなことができるソフトだけど、英語読めないマンには学習がつらい。
日本語教材なんかないかな？
Herokuの無料プランでDynoがSleepするのを防ぐ

Herokuの無料プランは30分アクセスがないとスリープしてしまいます。(スリープしたアプリにアクセスすると応答に10秒くらいかかります)
スリープを防ぐため、`Heroku Scheduler`を使って10分おきにcurlでリクエストを送るように設定します。

## 設定方法
- Herokuのダッシュボードから、アドオン`Heroku Scheduler`を追加
    - コマンドで追加する場合は`$ heroku addons:create scheduler:standard`

- ダッシュボードのアドオン一覧から`Heroku Scheduler`をクリックし、設定画面に移動

- `Create job`をクリック
![ 2020-09-02 17.44.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244893/9b8eafdb-b6f2-fc6f-4e86-5c83844d1dd0.png)

- `every 10 minutes`、`curl yourdomain.com`をセットし、`SaveJob`で設定を保存
![ 2020-09-02 17.52.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244893/2a9bcb25-6ba1-91af-8dd1-60c3daceb313.png)

## 注意点
- `Heroku Scheduler`は確実に動作を保証するものではないらしいです。動作しなかったり、2回実行されちゃったりする場合があるとのこと。今回の場合は30分に1回でもアクセスがあれば良いので、特に問題はないですが、念のため。
- Herokuの無料プランは、**全ての無料アプリ**合計で月1000時間までです。1ヶ月は約720時間なので、複数アプリを無料で運営することはできません。
- Heroku Schedulerが動いている間、Scheduler動作分も月1000時間の無料枠から時間が消費されていきます。

## 参考
- [【Heroku】無料プランの Sleep を回避する - 山崎屋の技術メモ](https://www.shookuro.com/entry/2018/05/05/112133)
EBSの自動削除オフに気をつけよう

## EBS料金が増えていた…
EBSの料金が高くなっている事に気づいてボリューム一覧を確認したところ不要なボリュームがたくさんあることがわかりました。

## 対処
対処としては不要なボリュームをただコンソールから削除しただけです。特に意図的にボリュームをデタッチしたりなどはしていないため、現在利用していないものは基本不要と考えてOKでした。

## 不要なボリュームが増えていた原因
ではなぜ不要なボリュームが増えていたんでしょうか。
おそらくはEC2の`終了時に削除`というものにチェックが入っていなかったことが原因です。デフォルト状態だとEC2インスタンスを削除するとボリュームも同時に削除されるのですが、ボリュームだけ残しておくことが設定で可能です。`DeleteOnTermination 属性`とも呼ばれるものです。
参考:[インスタンスの削除で Amazon EBS ボリュームを保持する](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/terminating-instances.html#delete-on-termination-console)
この設定のおかげで、オートスケーリンググループでインスタンスが削除されるとボリュームが残ってしまい、どんどん不要なボリュームが増えていっていた…ということでした。
podman play kubeで永続化ストレージを使用する

# はじめに
CentOS８を動かしてみたらdockerが未サポートで代替として用意されているPodmanを使用してdocker-compose的なことをしたかったのだが、podman-composeは問題が多く開発も止まっている。podman公式でサポートされているkubernetesの設定ファイルを使用してPodを作成する方法があるのだが、いかんせんドキュメントも貧弱で情報が少なすぎた、、、。
ストレージの永続化に結構手間取ったのでその方法をまとめてみました。

何か問題があれば指摘してください。

# 環境
```bash
$ podman -v
podman version 2.0.5

$ cat /etc/redhat-release
CentOS Linux release 8.2.2004 (Core)
```

# 今回動かすもの
`podman play kube`コマンドでWordpress+MariaDBを動かし、MariaDBのファイルを永続化してコンテナ再起動後も同じデータが使用できるようなPodの作成を目指します。


## 結論
kubernetesのvolumeのhostPathを使用する。
Referenceは[こちら](https://kubernetes.io/docs/concepts/storage/volumes/#hostpath)
`$ podman play kube wp-pod.yml` 

```yaml:wp-pod.yml
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: "2020-07-01T20:17:42Z"
  labels:
    app: wp-pod
  name: wp-pod
spec:
  containers:
  - name: wptest-web
    env:
    - name: WORDPRESS_DB_NAME
      value: wp
    - name: WORDPRESS_DB_HOST
      value: 127.0.0.1
    - name: WORDPRESS_DB_USER
      value: wordpress
    - name: WORDPRESS_DB_PASSWORD
      value: w0rdpr3ss
    image: docker.io/library/wordpress:latest
    ports:
    - containerPort: 80
      hostPort: 8080
      protocol: TCP
    resources: {}
    securityContext:
      allowPrivilegeEscalation: true
      capabilities: {}
      privileged: false
      readOnlyRootFilesystem: false
      seLinuxOptions: {}
    workingDir: /var/www/html
  - name: wptest-db
    env:
    - name: MYSQL_ROOT_PASSWORD
      value: myrootpass
    - name: MYSQL_USER
      value: wordpress
    - name: MYSQL_PASSWORD
      value: w0rdpr3ss
    - name: MYSQL_DATABASE
      value: wp
    image: docker.io/library/mariadb:latest
    resources: {}
    volumeMounts:
    - mountPath: /var/lib/mysql
      name: db-volume
    securityContext:
      allowPrivilegeEscalation: true
      capabilities: {}
      privileged: false
      readOnlyRootFilesystem: false
      seLinuxOptions: {}
    workingDir: /
  volumes:
  - name: db-volume
    hostPath:
      path: /tmp/mariadb_data
      type: Directory
status: {}
```

- 注意点  
  フォルダを予め作成しておく必要がある  
  今回ならば/tmp/mariadb_data

## 説明
肝となる設定が以下の２つです

```yml
  volumes:
  - name: db-volume
    hostPath:
      path: /tmp/mariadb_data
      type: Directory
```
こちらのvolumesでVolume名と、パスを設定し、


```yaml
    volumeMounts:
    - mountPath: /var/lib/mysql
      name: db-volume
```
コンテナの設定のvolumeMountのところで先ほど作成したVolume名と、コンテナ内の永続化を行いたいパスの指定を行います。


## 確かめてみよう
http://localhost:8080  
でWordpressの初期設定画面が出てくるので初期設定を済ませ、記事を1本適当に作ってみましょう
その後、

```bash
$ podman pod stop wp-pod
$ podman pod rm wp-pod
```
を行ってpodの削除を行いましょう。
その後、

```bash
$ podman play kube wp-pod.yml
```
でもう一度Podの作成を行い
http://localhost:8080
にアクセスして前と同じ記事が出てくるか確認してみましょう

# 最後に
一度わかるとDocker-composeとそこまで差がなくて大したことがないんですけど、この情報にたどり着くのが現状すごい大変でした。
まだまだバグも多い感じでpodmanのアップデート推奨です
raw文字列

#raw文字列

Windows環境で利用されるファイルのパスの区切り文字など、バックスラッシュ自体を文字列として定義したい場合があります。
文字列リテラル内のバックスラッシュはエスケープシーケンスとして扱われるため、「¥¥」のようにして2つ重ねる必要があり
面倒だし、文字列リテラルが見づらくなってしまいます。
バックスラッシュを含め、文字をそのままリテラルとして扱いたい時には、raw文字列を使うと便利です。
「raw」とは「未加工の」といった意味の形容詞です。raw文字列を使うと、入力した文字そのままの文字列を定義します。
エスケープシーケンスはコントロールコードなどに変換されず、そのまま文字列として扱われます。
raw文字列を定義するには、引用符の前に「r」を添えます。例えば、Windowsのパスをraw文字列として定義するためには
「r”C:¥path¥to¥file”」のようにします。

【raw文字列を利用する】
raw = r”C:¥path¥to¥file”
raw
↓
‘C:¥¥path¥¥to¥¥file’


文字列で利用できるメソッド
以下では「S」は文字列オブジェクト、[ ]内の引数はオプションとします。※省略可

【find()メソッド：文字列を検索する】
S.find(検索したい文字列)[, 開始インデックス [, 終了インデックス]])

文字列Sの先頭から「検索したい文字列」を探し、最初に見つかった位置を0から始まるインデックスをして返します。
見つからなかった場合は「-1」を返します。
オプションの引数を与えて、検索をする範囲を指定することができます。
find()は文字列の先頭から検索を行いますが、rfind()というメソッドを使うと、文字列の末尾（右）から検索します。


【index()メソッド：文字列を検索する】
S.index(検索したい文字列[, 開始インデックス][,  終了インデックス])

find()と同じように動作しますが、「検索したい文字列」が見つからなかった場合は「ValueError」という例外を発生します。
rfind()に相当するrindex()というメソッドを使うと、文字列を末尾（右）から検索できます。


【endswith()メソッド：最後の文字列を調べる】
S.endswith(検索したい文字列[, 開始インデックス][,  終了インデックス])

文字列Sが「検索したい文字列」で終わっているときにTrue（真）を、そうでないときはfalse（偽）を返します。
オプションで与える引数によって、検索をする範囲を指定できます。


【startswith()メソッド：最初の文字列を調べる】
S.startswith(検索したい文字列[, 開始インデックス][,  終了インデックス])

文字列Sが「検索したい文字列」で始まっているいるときにTrue（真）を、そうでないときはfalse（偽）を返します。
オプションで与える引数によって、検索をする範囲を指定できます。


【split()メソッド：文字列を分割する】
S.split([区切り文字列[, 分割数]])

文字列Sを、「区切り文字列」で区切り、文字列のリストを作って返します。リストの文字列からは区切り文字列を除去します。
オプションの分割数を指定しないと、文字列の末尾まで分割を行います。
指定すると、分割を行う数を制限できます。
split()の分割数は文字列の先頭から数えますが、rsplit()というメソッドを使うと、末尾（右）からの分割数を指定することができます。


【join()メソッド：文字列を連結する】
S.join(シーケンス)

シーケンス中の要素（文字列）を、文字列Sを使って連結します。
結果として連結した文字列（コピー）を返します。


【strip()メソッド：文字列を削除する】
S.strip([削除する文字列])

文字列の先頭及び末尾から文字列を削除します。結果として、削除を行った文字列（コピー）を返します。
引数を指定しないと、スペース、タブなどを含む空白文字を削除します。引数を指定すると「削除する文字列」を
対象に削除を行います。文字列の先頭（左）のみを対象に同様の処理を行うlstrip()メソッドや、末尾のみを対象とする
rstrip()メソッドもあります。


【upper()メソッド：アルファベットを大文字に変換する】
S.upper()

文字列Sの英字小文字を大文字に変換し、コピーを返します。


【lower()メソッド：アルファベットを小文字に変換する】
S.lower()

文字列Sの英字大文字を小文字に変換し、コピーを返します。


【ljust()メソッド：文字の幅を合わせる】
S.ljust(幅[, 埋め草文字])

文字列Sを、幅（数値）を考慮して「左寄せ」します。文字列を表示する際、幅を合わせるために利用します。
文字列の長さが幅に満たない場合はスペースで埋め、結果の文字列をコピーして返します。オプジョンの引数では
幅を合わせるときに利用する埋め草となる文字列を指定できます。
同様に、右寄せを行うrjust()や中央寄せ（センタリング）を行うcenter()メソッドもあります。
【Unity】コルーチン（Collections）の基礎的な使い方（自分用）



#はじめに

ここでは技術的な部分で初心者の方向けになんとなくわかっていただけるように書いています。



#コルーチンとは


コルーチンって何？
っていう方向けに言葉の意味をなんとなく理解してもらえるようこちらで説明しています。

[【Unity】コルーチン（Coroutine）](https://chan-ryu.hatenablog.com/)




主にポイントは↓のこの3つになります。

```
①IEnumerator 
②yield
③StartCoroutine 
```


まずこの下にあるスクリプトを見てください。
これからこのスクリプトを元に順番に説明していきます。


```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Tesycoltin : MonoBehaviour
{
    void Start()
    {
        StartCoroutine("Coroutine1");
    }

    IEnumerator Coroutine1()
    {
        Debug.Log("開始");
        yield return new WaitForSeconds(3);
        Debug.Log("3秒経過");
        yield return new WaitForSeconds(5);
        Debug.Log("5秒経過");
    }

    void Update()
    {
        
    }
}
```



ちなみにこのスクリプトの実行結果はコンソールに実行した瞬間に「開始」と表示され、3秒たったら「3秒経過」、5秒たったら「5秒経過」と表示された。


![“shot” 2020-09-02 17.23.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/688851/843536ac-0036-fb65-a85c-9ee3cdca1b99.png)


###①IEnumerator


```
    IEnumerator 「関数の名前」()
    {

　　　　「処理の内容」

    }
```

はじめにIEnumerator型の関数を作成する。
「IEnumerator」と書いた後、次に自分で好きな名前の関数を書く。
私が用意したスクリプトでは「Coroutine1」としてある。
そして関数の中にコルーチンの処理の内容を書いていく。


###②yield


①で関数を作成したら次ははその中の処理の内容を書いていく。
書き方として始めに「yield」を付けその次にどういう処理の仕方しにするか書いていく。

私の用意したスクリプトは

```
        Debug.Log("開始");
        yield return new WaitForSeconds(3);
        Debug.Log("3秒経過");
        yield return new WaitForSeconds(5);
        Debug.Log("5秒経過");
```



上から順番に実行されていくので、言葉で説明すると
始めにコンソールに「開始」と表示。
次に
「yield return new WaitForSeconds(3);」
これは3秒待って再会という事なので文字通り3秒たって次は下にある「3秒経過」をコンソールに表示する。
下にあるやつも5秒後にコンソールに「5秒経過」と表示されるようになってる。


ここで注意したいのが
「yield return new WaitForSeconds(3);」
の後に
「yield return new WaitForSeconds(5);」
が書いてありますが、
3秒待って再開したその後にまた5秒待つわけではなく、最初に実行してから3秒後、最初に実行してから5秒後だという事。

そして他にも

・1フレーム待機させる　「yield return null;」
・コルーチンを停止・破棄する「yield break;」

などもあるがここではなんとなく使い方を感じてくれればいいと思ってるので深くは書かないです。


###③StartCoroutine


最後にこのようにStartメソッドの中に「StartCoroutine」とカッコの中に先ほど作った関数の名前を入れれば無事実行されます。

```
    void Start()
    {
        StartCoroutine("関数名");
    }

```

終わり。
LANとWAN、プロトコルとパケット

#LANとWAN
事業所など局地的な狭い範囲のネットワークを**LAN**
LAN動詞をつなぐ広域ネットワークを**WAN**と呼ぶ

#データを運ぶ通信路の方式とWAN通信技術
　コンピュータがデータをやりとりするためには互いを結ぶ通信路が必要で
　もっともシンプルな形は互いを直接1本の回線で結んでしまうこれを**専用回線方式**という
　正しこれでは1対１の通信しか行えないので交換機が回線の選択を行って、必要に応じた通信路
　が確立される方式がありこれを**交換方式**と言う

#交換方式
　交換方式には2種類の方式がある

　**・回線交換方式**
　送信元から送信先にまで至る経路を交換機がつなぎ、通信路として固定する。
　
　**・パケット交換方式**
　**パケット**という単位に分割された通信データを交換機が適切な回線へと送りだすことで通信路を形成する
　WANの構築で拠点間を接続する場合などを除いて、現在のコンピュータネットワークで用いられるのは基本的に**パケット交換式**になる
　

#LANの接続形式(トポロジー)
 　LANを構築するときに、各コンピュータをどのようにつなぐか。その接続形態のことをトポロジーと呼ぶ
　　以下の３つが代表的なトポロジー
　
　**・スター型**
　![図100.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686519/10e348a1-1514-3753-0f8f-1783c5c2b806.png)


　**・バス型**
　![図101.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686519/3b7aad28-0d51-d934-255d-95a8f796f8c9.png)


　**・リング型**
　![図102.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686519/ca99bf3e-9920-e045-dbf5-1ab0b7fcc127.png)


#現在のLANはイーサネットがスタンダード
　LANの企画として、現在もっとも普及しているのが**イーサネット(Ethernet)**です。IEEEによって標準化されており
　接続形態や伝達速度ごとに、以下の企画に分かれている
　![図103.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686519/7798568d-90c9-6564-fef2-0f906aafc474.png)

　　

#イーサネットはCSMA/CD方式でネットワークを監視
　イーサネットはアクセス制御方式として**CSMA/CD方式**を採用している
　CSMA/CD方式では、ネットワーク上の通信状況を監視して、他に送信を行っている者がいない場合に限って
　データの送信を開始する。
　それでも同時に送信してしまい、通信パケットの**衝突(コリジョン)**が発生した場合は各々ランダムに
　求めた時間分待機してから、再度送信を行う。

#トークンリングとトークンパッシング方式
　リング型LANの代表核である**トークンリング**では、Access制御方式にトークンパッシング方式を用います。
　

#無線LAN
　ケーブルを必要とせず電波などを使って無線で通信を行うLANが**無線LAN**という
　IEEE802.11シリーズとして規格化している
　電波の届く範囲であれば自由に移動することができるが、電波を盗聴されてしまう恐れもあるため
　通信を暗号化するなど、しっかりとしたセキュリティ対策が必要になる
　

#クライアントサーバとサーバ
　ネットワークにより、複数のコンピュータが組み合わさって働く処理の携帯にはいくつか種類がある
　代表的なのが以下の通り
　
　**・集中処理**
　ホストコンピュータが集中的に処理をして、他のコンピュータはそれにぶら下がる構成です。
　![図104.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686519/0fcbeb03-5168-841c-dc69-3dba068ba12c.png)


　**・分散処理**
　複数のコンピュータに負荷を分散させて、それぞれで処理を行うようにした構成
　![図105.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686519/3c7c4eb3-a40e-9b92-ad9b-7c63497f407e.png)


　**・クライアントサーバシステム**
　集中的に管理したほうが良い資源(プリンタやハードディスク領域など）やサービス
　を提供する**サーバ**や必要に応じてリクエストを投げる**クライアント**という
　２種類のコンピュータで処理を行う構成で現在の主流となっている

#プロトコルとパケット
　コンピュータは異論な約束ことにのっとってネットワークを介したデータのやり取りを行う
　
#プロトコルとOSI基本参照モデル
　プロトコルには様々な種類があり「どんなケーブルを使用して」「どんなデータ形式で」といったことが、事細かに決まっている
　それらを７階層に分けたのが**OSI基本参照モデル**
　![図106.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686519/4889b7a2-dd25-b474-3fa6-2d396d5f6cc9.png)


#なんで「パケット」に分けるのか
　TCP/IPというプロトコルを使うネットワークでは、通信データをパケットに分割して通信路へ流す。
　なぜ分割して流すかというと通信路上を流せるデータ量は有限だから。


#以上
【bat】xcopyのD:MM/DD/YYYYオプションを付けるだけではDオプションの効果がない

1日に何度も実行する「その日更新されたファイルをコピーする」batを作成した時に、少しだけハマったので備忘録として残します。


# xcopyコマンド
ディレクトリ構造毎、ファイルをコピーするコマンド


# Dオプション、D:MM/DD/YYYYオプション

#### Dオプション
コピー先に同名ファイルがある場合、更新日が新しい場合のみコピーする。

#### D:MM/DD/YYYYオプション
指定された日付以降に更新されたファイルだけをコピーする。


# ハマった点
「D:MM/DD/YYYYオプション」のみだと「Dオプション」の効果はないので、指定された日付以降に更新されたファイルが毎回コピーされます。

未コピーの指定された日以降に更新されたファイルをコピーしたい場合は、「D:MM/DD/YYYYオプション」と「Dオプション」の両方を指定する必要がある。

```bat
rem D:MM/DD/YYYYオプションのみ
rem 実行する毎に更新日がMM/DD/YYYY以降のファイルがコピーされる
xcopy D:MM/DD/YYYY コピー元 コピー先

rem DとD:MM/DD/YYYYオプションを指定
rem 更新日がMM/DD/YYYY以降のファイルがコピーされる
xcopy /D /D:MM/DD/YYYY コピー元 コピー先
```


# 感想
参考に記載しているMicrosoft Docsだと分かりやすいので、しっかり公式リファレンスを確認するべきでした。


# 参考
xcopy
https://docs.microsoft.com/ja-jp/windows-server/administration/windows-commands/xcopy
WindowsServer2016　DNS編

##今回やること
前回はADの構築をしましたが、今回はDNSサーバーの設定確認をしていこうと思います。
前回のAD構築の記事はこちら
⇒[AD構築の記事](https://qiita.com/nishi-infr/items/47ca1204428f402edf9f)

##使用ツール
VMware Workstation 15 Player

##DNSサーバー設定
前回はADの構築をしていきました。
今回、構築後にやるべきDNSサーバーの機能の正常性確認を行っていきたいと思います。

DNSサーバーの設定がそもそも入っていないと、ADで検索機能を使おうとすると名前解決できないので
一切機能しません。
ただADインストールするとDNS機能も追加でインストールされるらしいです。
便利ですね。

![win.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686507/9e04c102-5c57-643c-c7b9-77c4344b8443.jpeg)
ADだけインストールしましたがDNSの項目も増えていますね。

では早速見ていきたいと思います。
まずツールをクリックするとたくさん出てくるので、その中のDNSをクリックします。
![win1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686507/02711368-d92c-34dd-ba84-6c5fcb683d6c.jpeg)

そして対象サーバーのプロパティを開いて、監視タブをクリックします。
![win2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686507/ebcf10c0-d1ef-f8d4-777a-dfa08f5ab711.jpeg)
そしてテスト実行をクリックして単純クエリのところが可になれば、DNSサーバーは正常であるという確認が
取れます。

ちなみにコマンドプロンプトからも実行できますので、楽なほうでやるのがいいかもですね。
コマンドは
⇒ **dcdiag /test:dns**
これで流して合格しました。が出ればOKです。

DNSマネージャーを開いて、対象サーバーをクリックするとこんなのがでてきます。
![win3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686507/54e5c05b-954a-782f-69f8-7dfe17dcc97e.jpeg)
ここの前方参照ゾーンの対象ドメインを見てみると、サーバーが登録されています。
ここにでていればDNSサーバーに登録されているという確認が取れます。

ちなみにDNSサーバーを停止したり、再起動したりするのは、
１、DNSマネージャー開く
２、対象サーバー右クリック
３、すべてのタスク
４、その中から項目選ぶ
でできます。
![win4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686507/3a9ba595-7c7b-c98e-96f1-adaabf302912.jpeg)

これでDNSのもろもろの設定確認は完了したので終了です。

##まとめ
今回DNSサーバーに触れてみました。
どこに何があるか中々覚えるのが大変です。
仮想環境なので、いじりまわしてますが、結構迷子になります。
説明文読んでも何をする機能なのか理解できない部分が多いので、まだまだ勉強不足ですね。

次回はファイアウォールを構築していこうと思います。
軽く勉強しましたが、これまた難しそうな気配がでてます。
規則の作成を色々やっていくわけですが、項目が多すぎてきちんと理解するには時間がかかりそうです。
現場では定義書通りに項目を作成していくのかなー？なんて勝手に予想してます。

以上となります。
GPUサーバ（リモートサーバ）上でjupyter notebookを起動する

<h2>概要</h2>
AWSのGPUインスタンスを用いてjupyter notebookを起動するまでを記載する。

<h2>環境</h2>
・mac OS Catalina 10.15.6
・AWS Deep Learning AMI (Ubuntu 18.04)

<h2>手順</h2>
<h3>インスタンス作成</h3>
○EC2インスタンスを作成する
**AMI**:AWS Deep Learning AMI (Ubuntu 18.04)
**インスタンスタイプ**:GPU インスタンス p2.xlarge
**ストレージサイズ (GiB)**:200
あとはデフォルト

**→**インスタンスの作成に失敗 下記エラーが
>You have requested more vCPU capacity than your current vCPU limit of 4 allows for the instance bucket that the specified instance type belongs to. Please visit http://aws.amazon.com/contact-us/ec2-request to request an adjustment to this limit.

どうやらインスタンス制限がかかっている模様。キャパシティをあげる申請を行う。

○下記サイトを利用すると引き上げ容量を計算し、申請画面へと遷移することができる。
https://ap-northeast-1.console.aws.amazon.com/ec2/home?region=ap-northeast-1#LimitsCalculator
※外国は24時間対応しているそうなので、英語設定を行い、英語で申請を出すと早く申請が降りる

改めてインスタンス作成を行う。

<h3>ssh接続</h3>
ターミナルにssh接続コマンドを入力する
```ssh -i <pemファイルのアドレス> ubuntu@パブリック DNS（ec2-○○○.com）```

pytorchの環境に入る
```source activate pytorch_p36```


<h3>jupyter notebook設定</h3>
jupyter notebookにパスワードを設定する
```jupyter notebook password```

パスワードは下記jsonファイルに保存されているのでコピーする
```less ./.jupyter/jupyter_notebook_config.json```

各種設定を※pyファイルに記載する
```vi ./.jupyter/jupyter_notebook_config.py```

```./.jupyter/jupyter_notebook_config.py
c = get_config()
c.NotebookApp.ip = '0.0.0.0'
c.NotebookApp.open_browser = False
# 先ほどコピーしたhash関数で生成したパスワード(sha1:###)は以下に記載する
c.NotebookApp.password = 'コピーしたパスワード' 
c.NotebookApp.port=8888
```

いざ、jupyter notebookを開く
```jupyter notebook```
http:<アドレス>:8888で起動

起動しない

理由はインスタンス作成時にセキュリティーグループの設定でルールの追加を行っていないからだった

EC2のページの左からセキュリティーグループを選択
→設定しているセキュリティーグループを選択
→アクションを選択し、インバウンドルールを編集する

○カスタムTCP TCP 8888
を追加する（今回はSHH,カスタムTCPともにソースはマイIPを選択した）

そして、もう一度
```jupyter notebook```

http:<アドレス>:8888で起動

開かない...


原因は、アドレスにプライベートIPを記載していたからだった
パブリックIPを記載し、もう一度


成功



パスワードを入力し、問題なくjupyter notebookを起動することが出来た。





以上

<追記>
確認していないが、下記でローカルに繋げると思う。
ssh -L 8888:localhost:8888 ~
こうすると、サーバーのパブリックIPで接続していたところが、localで接続できるようになる
http://<サーバーアドレス>:8888 → http://localhost:8888
@PostConstruct

# @PostConstructとは
- 初期化メソッド
- オブジェクトの初期化部分
- オブジェクト生成後、別途初期化作業を行うために実行するメソッドに宣言する。
- PostConstructアノテーション付きのinitメソッドはWASが上がるときに実行される。

# メリット

1. コンストラクタが呼び出された時、beanはまだ初期化されないです。（挿入された依存性がない。）
でも、＠PostConstructを使うとこで、beanが初期帰化されるときの同時に依存性を確認できます。

2. bean lifecycleで一回だけ実行されることを保証できます。（**WASが上がるときにbeanが生成されるときの1回だけ初期化**されるため。）なので、**PostConstructアノテーションを使うことでbeanが何回も初期化されることを防ぐことができます。**

# 適用ソース
自分がWebSocketの勉強をしていた時に作成したコードの一部です。

```java

@Slf4j
@RequiredArgsConstructor
@Service
public class ChatService {

    private final ObjectMapper objectMapper;
    private Map<String, ChatRoom> chatRooms;

    @PostConstruct
    private void init() {
        chatRooms = new LinkedHashMap<>();
    }

    public List<ChatRoom> findAllRoom() {
        return new ArrayList<>(chatRooms.values());
    }

    public ChatRoom findRoomById(String roomId) {
        return chatRooms.get(roomId);
    }

    public ChatRoom createRoom(String name) {
        String randomId = UUID.randomUUID().toString();
        ChatRoom chatRoom = ChatRoom.builder()
                .roomId(randomId)
                .name(name)
                .build();
        chatRooms.put(randomId, chatRoom);
        return chatRoom;
    }

    public <T> void sendMessage(WebSocketSession session, T message) {
        try {
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(message)));
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
    }
}
```

# 終わりに
サンプルコードや資料を調べていたら、Serviceアノテーションがついているクラス内で使用している場合が多かったのですが、それについては調べないとなりませんね。。
C++における構造体(struct) とクラス(class)の違いについての備忘録

UnionFindの実装をしている時に知ったのだが、C++では構造体にメンバ関数をもったりコンストラクタを持ったりできるらしい。
調べてみたところ、C++における構造体とクラスの違いはメンバ変数のデフォルト(何も指定しない時)でのアクセスレベルの違いのみであるということだ。

構造体の場合デフォルトではpublic:、逆にクラスの場合はデフォルトではprivateなのだそうだ。

自分はC++超初心者かつ競プロしかしてないのであまりクラスや構造体を使ったコードを書くことはないのだが、たまたまライブラリを作る時に書かなければいけないときに、他の人が構造体の中でコンストラクタや関数を持っていたのでびっくり仰天した。
Burpでlocalhostへの通信が受け取れなくてハマった

Burp Suiteの基本設定や利用方法は良記事が一杯あるので割愛します。
タイトルの事象でハマってる人向けの記事です。
お忙しい人はオチのみ閲覧してください。
<font color='red'>リクエスト改ざんは不正アクセス禁止法に引っかかるので自サイト以外では実施しないでくださいね</font>

####環境
Burp Suite Community Edition v2020.8.1

####経緯
新しいPCを買ってdjangoの勉強を始める。
↓
djangoのバリデーションの動作を確認したい！
ブラウザ側はエラーになって表示されるのでわかりやすい。
サーバー側はどうなの？
テストしようにもブラウザ側でエラーになって狙った値を送れない！
↓
Burp Suite（ローカルプロキシツール）使ってPOST改ざんしたりしてテストしよう！
↓
久しぶりのBurp利用、バージョン上がってるやん！ナニコレDashboardとかあるぞ！
Burpの初期設定を実施。ブラウザのプロキシ設定も実施。
↓
インターネットへの接続は受け取れるのにローカルホストへの接続だけは受け取れない([Proxy]→[HTTP history]にlocalhost:8000への接続のログが表示されない)！
なぜ！？

####オチ①
<b>java入ってなかった＼(^o^)／</b>

同じ人いないかもですが、一応リンク貼っておきますね。
[javaダウンロード](https://java.com/ja/download/?_fsi=OGoDWCTs)

なんか普通に使えているように見えたので気づくまでにかなり時間かかりました。。。

####オチ②
<b><-loopback>が必要！！</b>

PCのプロキシ設定で赤枠（下記画像）の部分に<-loopback>という記述が必要でした。
（Chromeやedgeの場合はPCのプロキシ設定画面でブラウザのプロキシ設定を実施する）
![プロキシ設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/702253/e43c3938-9549-416d-d4a7-d0fb2e551528.png)

後、赤枠下のチェックボックスこれにチェックついてるからダメっていう人もいるかと（昔ハマった）

####まとめ
javaはちゃんとインストールしよう！
ブラウザのプロキシ設定はハマるポイントがあるぞ！
私だけかもしれませんが。。。
UnionFindの実装を†完全に理解した†ので備忘録として書く

競プロとC++を初めて約１ヶ月が経過した頃、[AtCoder Beginner Contest 177のD](https://atcoder.jp/contests/abc177/tasks/abc177_d)でUnionFindを使う問題が出された。
今まで実装もしたことがなく、たまたまコンテストの数日前にUnionFindの概念を知った直後だったので「UnionFindが使える！！」　と気づいたものの実装はさっぱりだったので、そのコンテストの時は誰かのUnionFindを借りてきて、貼って無事ACした。
このコンテストの後に、この機会に実装を理解しようと思い無事、†完全に理解した†(ごめんなさいごめんなさい)ので共有しようと思う。

この記事では「UnionFindの'基本的な実装方針'」(木を使って、、等々)みたいなことはあまり説明しないので、概念を理解していて主な実装部分が気になる方が対象だ。
とはいうものの軽くUnionFindがどういうものか触れておくと、集合をグループ分けするものである。
例えば{  {1},{2},{3},{4},{5}  }という集合があったとして、
・1と２を同じグループに統合しろ :

```cpp 
union(1,2)
 ```

・２と５を同じグループに統合しろ:

```cpp 
union(2,5)
 ```
というような命令ががあったとして、この２つの命令がなされた後には
{1,2,5} {3},{4}　のようなグループ分けがなされる。
このような「要素を統合する命令」がUnionである。

次にFindについてだが、「要素Aはどのグループに属しているか」というのを調べる命令である。
上記の例でいうと、今、{1,2,5} {3},{4}　のようなグループがなされているが、{1,2,5} をグループAとし{3},{4}をグループB,Cとする。
そして 、

```c++
find(2) //A
find(4) //C
```
といった具合にしたい。
ここでAとかBとか行ったグループの名前をどのように決めるのかだが、それはそのグループに属している代表の要素をグループの名前にする。 
おそらくコードを見てもらったほうがいい気がするので以下が実装である。

```cpp
struct UnionFind {
	vector<int> d; //iが子ならd[i]は親のidでiが親ならd[i]は -サイズ
	UnionFind(int n): d(n, -1) {}
	int find(int x) {
		if (d.at(x) < 0)return x;//親なら自分自身の番号を返す
		else return d.at(x) = find(d.at(x)); //経路圧縮　メモ化
	}
	bool unite(int x, int y) { //voidでもいいが、くっつけられるか判定できた方が嬉しいときもある
		x = find(x); y = find(y); //根同士をくっつけるため
		if (x == y) return false;//統合できない(しない)
		if (-d.at(x) < -d.at(y)) swap(x, y);
		d.at(x)+= d.at(y); //親のサイズの更新 サイズが大きい方に小さい方を統合
		d.at(y) = x;//yは親ではなくなったのでyの親をｘに設定
		return true;//統合できた
	}
	int size(int x) {return -d.at(find(x));}
	bool same(int x, int y) {return find(x) == find(y);}//これはおまけ
};
```


この実装方針は過去にSunkeさんがUnionFindを実装するときに動画内で話していたものである。
この方法が非常に上手いので参考になった。
そのグループのサイズを返すsize()関数があると思うが、それがあるので実装がやや複雑になっている。
size()を作らなければもっとシンプルに実装することが可能だ。
というのも、size()の実装のために、配列のグループの代表(親)の部分にはそのグループの"-サイズ"が格納されている。
そしてその要素が親かどうかは配列の中身が負かどうかで判定をしているのだ。
配列の子の中身は自身の親が格納されている。
ここでポイントなのだが、木構造が深くなってしまっているときにfind()を行うと、毎回再帰でたどっていかなければならないのだが、たどる過程でそのグループの代表に直接つなぎ替えることで計算量を大幅に削減している。

```cpp
else return d.at(x) = find(d.at(x)); //経路圧縮
else return find(d.at(x)); //経路圧縮してない TLEになる時もある。
```
以上が大まかなUnionFindの実装である。
こまかい実装部分については各自コードを解読するように(コメントをつけているので)

ここで補足なのだが、なぜunion()でなくunite()なのかは'union'はC++では予約語だからである。
公開済のiOSアプリのアプリ名を変えたときにハマったこと

[こんなアプリ](https://apps.apple.com/jp/app/like-a-paper/id1511690088#?platform=ipad)をつくって、公開して、
本業でいっぱいっぱいだったので、アップデートはかけられていなかったのですが、
それでも海外を中心にじわじわダウンロードされていて、うれしかったです。

そんな中、一通の英文メールが来ました。
最初スパムかと思った（英語でメールなんてまず来ない）のですが、よく読んでみるとアプリを誉めてくれている内容でした。
そして後半に入ると、なんか英語についてダメ出しをされています。

元々アプリ名は、

Like a Paper

という名前で、僕的には全く違和感なかったです。
（皆さんはどうですか？）
「a paper」で、「（なんでもないただの）紙」を表せている……と思っていたのですが、メールくれた方は英語ネイティブで、
「アプリ自体は素晴らしいし、気に入ってるけど、アプリ名はちょっと変だよ笑」
みたいなことを言っています。

その後よく調べてみると、"paper"は通常不可算名詞で、「一枚の紙」と言いたければ、"a piace of paper"などの表現になるようです。
"a paper"だと、一枚（一日分？）の新聞というニュアンスで、意図したかった「ただの紙」という表現にはならない、と気づきました。

というわけで、公開済みのアプリ名を変更することにしました。

# そもそも公開済みのアプリ名は変更できる？
これは結論、できます。というかできました。

# 公開済みじゃなかったら？
もしstore公開前に、アプリ名を変更しなきゃいけなくなったら、プロジェクトファイルごと作りなおすのをオススメします。
新プロジェクトで、つくったコードをコピペで移すのがいいと思います。
アプリ名の変更はかなりめんどくさいです。

# やったこと
まずXcode上でプロジェクトファイルを選択して、Display Nameを変更。
（たぶんここはほとんど何も影響しない）
それからプロジェクトファイル名を変更しました（`.xcodeproj`の名前を変える）。

経験上、Finderからディレクトリ名・ファイル名操作すると悲惨なことになることはわかっていたので、基本Xcodeから操作しました。

プロジェクト名を変えると、ワーニングが出て、「付随して色々変わるけど大丈夫？」みたいな確認が出るので、OKにして進みます。
その後クラスの入っているディレクトリ名/テストの入っているディレクトリ名もXcode上から変更しました。(app/appTests/appUITests)

ここまでで一旦ビルドしてみると、ビルドがコケました。エラーを見ると、plistのパスが通らなくなってました。
Built Settingのところで、旧アプリ名でFindかけると、plistのパスが古い形式で指定されていたので、そこのパス名を書き換えました。

その後、Finder上で親ディレクトリも名前を変更しました。
別にやらなくてもいいんでしょうけど、気になってしまって……
Xcodeを開いたまま親ディレクトリをおもむろに改名すると、Xcodeがエラーになりますが、普通にFinderからもう一度開くと、いい感じにパス名が引き継がれていました。

が、ビルドすると問題が起きました。

```shell
<unknown>:0: error: PCH was compiled with module cache path
```

最初キャッシュが残ってるだけなので、クリーンビルドでイケるだろうと思ったら、ダメでした。
Altつきの強いクリーンビルドやってもダメ。
ググるとXcodeの環境設定のLocationをDerivedDatadからDerivedDatad2にすればビルドできるよ、みたいなこと書いてあって、
確かにそれでもできるんですが、ちょっと気持ち悪いので、

https://developer.apple.com/forums/thread/64345

こちらを見て、DerivedDatadの中の「LikeAPaper」（旧アプリ名）と「ModuleCache.noindex」のディレクトリをワイルドに全削除しました。
すると無事ビルドできるようになりました。

# 変更できないところ
さてApp Store申請しようと思ったら、完全に別アプリ扱いになっていることに気づきました。
iOSアプリはBundle Identifierを変えると別アプリ扱いになり、
思いっきりその中に旧アプリ名を入れてしまっていたので、残念ながらここは恥ずかしい英語ミスが残ることになりました。

またアプリ内でファイルWriteしてるんですが、そのファイル名も旧アプリ名を入れたファイル名にしていたので、ここにも残ることになりました。
アプリ名やディレクトリ名変えたことが影響して、ファイルパスが通らなくなるんじゃないかな？　バージョンアップ前のデータをちゃんと読めるかな？　という不安があったんですけど、
パス名をよく確認したら、アプリに対して環境内で一意に定まるようなパスになっていて、
Bundle IDさえ同じだったら、そこは上手いことやってくれてました。

まあユーザーからは見えないから別にいいかなとは思います。

あとSKUも変更できません。

逆に言えば、SKUとBundle ID以外は、たとえ公開済みであっても変更可能でした。

# App Storeのアプリ名はApp Store Connectから変える
ここまでやって審査出して、通ってから、App Storeの名前が変わってないことに気づきました。
アプリ名が変われば自動でStoreの名前も変わるかと思ってましたが、別モノでした。

App Store Connectの一般→App情報からアプリ名が変更できるので、変えました。
ちなみにレビュー済になってしまうと、この項目が編集できなくなるので、僕はわざわざStore上の名前変更のためだけにバージョンアップ出すハメになりました。
Try Catch文がとらえるのは"例外"である

###要約
try-catchを使うときは、それが本当に必要か、適切にCatchできているか考えて使おう。

###ひどいコードを見た
この間、Visual studioを用いてデバッグしていたら、例外が頻繁に発生していちいち止まるので、なんだこれと思ったら下記のようなコードがあった

```cs
    try
    {
        // a,b共に、nullになる可能性がある
        var a = GetA();
        var b = GetB();
        // 変数bのnullチェックはしていない
        if(a != null)
        {
            var aHoge = a.GetHoge();
            var bHoge = b.GetHoge();
            // なんらかの処理が続く
        }
    }
    catch
    {}

```

このコード何がやばいかっていうと変数bがnullになるケースがあったということです。
デバッグしているとbがnullになるのでexceptionを出すんですね。
普通にbがnullかどうかチェックするだけで例外は防げるのに...


で、なにが言いたいかというと、
**なんも考えずtry-catchを使うんじゃねー！！**
ってことです。

例に上げたコードで言えば変数bがnullであるかどうかチェックしていればtry-catchは必要ないわけです。
むしろtry-catchを使うことで自分のミスを見逃しています。


try-catchは便利です。
どんなエラーが起こっても一気に捉えて対応してくれるのだから。
ただ一つはっきり宣言しておくけども、

**try-catchが捉えるのは例外だからな！！！**

これを一つ肝に命じてコーディングを行っていきたいと思います。

とりあえず、コーディングに自信のない方はtry-catchを使わないことから初めてみてはどうでしょうか？
初版ではtry-catch使わずにしっかりと発生するエラーを確認し、本当にとらえようのないエラーの場合のみtry-catchを使うようにすればいいと思います。


**ただしtry-finallyなら使ってもいい！**
expressを使ってnuxtjsにapiを作る

nuxtjsではapiも作れるらしい。（ちょっとした通信を試したいときには便利そう。）

# expressをインストールする

[expressのインストール](http://expressjs.com/ja/starter/installing.html)

```sh
$ npm install express --save
```

# 設定

nuxt.config.jsに`serverMiddleware`を追加する。

```javascript:nuxt.config.js
export default {
  // 省略
  ...

  serverMiddleware: ['~/api']
}
```

プロジェクトフォルダの直下に`api`フォルダを作成してindex.jsを配置する。

```javascript:api/index.js
const express = require('express')
const app = express()
app.get('/', (req, res) => {
  res.json({ message: 'hello, api' })
})
module.exports = {
  path: '/api',
  handler: app
}
```

ブラウザで`localhost:3000/api`にアクセスしてjsonで`message: 'hello, api'`が表示できたらapiは完成

# 使い方

pageからaxiosを使ってapiにアクセスしてみる。

```vuejs:pages/index.vue
<template>
  <div>
    {{ message }}
  </div>
</template>

<script>
export default {
  async asyncData(context) {
    const response = await context.$axios.get('http://localhost:3000/api')
    return {
      message: response.data.message
    }
  }
}
</script>
```
[機械学習] グラボ等PCパーツを海外輸入する手引き

# はじめに

国内で販売していないPCパーツを買いたい、商品を送ってもらえない(日本への配送不可)、安くかいたい、人向けの記事となります。

# 米Amazonからの輸入方法

欲しいものがあるのに日本への発送ができない場合に`Planet Express`というサービスを利用して、仮の米国住所(Planet Express社のもの)を手に入れます。その住所を経由して自宅へと送られてくる仕組みとなっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282788/48dd11b9-8c41-f99f-a09a-ba8f1b886739.png)
引用: https://chasuke.com/planetexpress/

## 手順

1. [PlanetExpress](https://planetexpress.com/ja/%E3%83%9B%E3%83%BC%E3%83%A0%E3%83%9A%E3%83%BC%E3%82%B8/)で住所を取得
2. 米Amazonで注文(住所は上で説明したとおり)
3. 到着を待つ

# ツール
・[PlanetExpressを登録](https://planetexpress.com/ja/%E3%83%9B%E3%83%BC%E3%83%A0%E3%83%9A%E3%83%BC%E3%82%B8/)
・[日本語の住所を英語表記にするサービス(無料)](http://judress.tsukuenoue.com/)

# クーポン
非課税になるプレミアムプランのトライアルクーポンコード：　`30days`

# 参考サイト
https://chasuke.com/planetexpress/
https://androplus.org/Entry/12215/
gorp利用環境下でバルクインサートしてみた

## この記事が解決する問題
gorpを利用している環境で、どうしてもバルクインサートしたいケース
ORMとしての利点を享受できないため、その部分許容できる場合にこの記事を参考いただければと思います。
gorpについては書いていないので下記を参照ください。
https://github.com/go-gorp/gorp

## コード
```go
// ユーザ情報をバルクインサートする例
func bulkInsertUsers(tx *gorp.Transaction, users []User) error {
  sql := `INSERT INTO users(name, age, email) VALUES`
  args := map[string]interface{}{}
  for i, user := range users {
    nameKey := fmt.Sprintf("name_%d", i)
    ageKey := fmt.Sprintf("age_%d", i)
    emailKey := fmt.Sprintf("email_%d", i)
    args[nameKey] = user.Name
    args[ageKey] = user.Age
    args[emailKey] = plan.Email
    // プリペアドステートメントを利用
    sql += fmt.Sprintf("(:%s, :%s, :%s)," nameKey, ageKey, emailKey)
  }
  // 末尾の,を除去
  sql = sql[0 : len(sql)-1]
  _, err := tx.Exec(sql, args)
  return err
}
```

データ量によりますが、ある程度の件数のデータをインサートする場合、普通にインサートするより数倍〜数十倍高速です。


## まとめ
- gorp利用環境下でもバルクインサート自体はできる
- ORM必要ないならgorp使わなくていい
プログラミングで数学と英語を学ぶ（その２）

# 問題

https://projecteuler.net/problem=2

# 使用する英単語

https://progeigo.org/learning/essential-words-600-plus/
のBから始まる単語

# プログラム

```

#!/usr/bin/python3
# -*- coding: utf-8 -*-

# このプログラムはバグとビットバイト計算がない（そらそうだ）
# This program doesn't have bug and bit byte calc.
# ブラウザでは試してないよ
# I dindn't try this on browser.

# ベースの数
based_numgber = 1
# 分岐の数（フィボナッチは二つ目の数字で分岐するんだよ多分）
branch_number = 2
# 空白の数（途中のってことで）
blank_number = 0
# 合計をバックアップしておく
backup_numgber = branch_number

# 計算をブロックする数
block_numger = 4000000

# ブーリアンのフラグ（意味が分からん）
boolean_flag = True

while boolean_flag :
    blank_number = based_numgber + branch_number
    based_numgber = branch_number
    branch_number = blank_number

    if blank_number >= block_numger :
        break

    if blank_number % 2 == 0 :
        backup_numgber += blank_number

print(backup_numgber)

```

# 実行結果

```

# python3 test.py
4613732

```


# 結論

こんな変数名書かれたら怒るわ
Laravel(5.5)でSQLite3がNo such file or directoryが出続ける際の解決策

# 結論

```config/database.php
    'connections' => [

        'sqlite' => [
            'driver' => 'sqlite',
            'database' => database_path('database.sqlite'),
            'prefix' => '',
        ],
```

databaseをenvを経由せずに指定する。

## 事象

Laravel5.5でsqliteを使用した時に、
`sqlstate hy000 error 2002 no such file or directory`
がDB接続時に出続けた。マイグレーションは通っているのに・・・。

パーミッションの問題かと思われたが、何をどういじっても、同じログが出る。

config/database.phpを確認したら、

```config/database.php
    'connections' => [

        'sqlite' => [
            'driver' => 'sqlite',
            'database' => env('DB_DATABASE', database_path('database.sqlite')),
            'prefix' => '',
        ],
```

で

`env('DB_DATABASE', database_path('database.sqlite'))` が `""`(空白)になっていた。

.envでDB_DATABASEをコメントアウトしたり

```.env
#DB_DATABASE=
```

そもそも削除したり、

```.env

```

```console
$ php artisan config:clear
```

しても、`env('DB_DATABASE', database_path('database.sqlite'))` が`""`(空白)。

## 対処法

config/database.phpでenvを経由せずに、直接指定する。

```config/database.php
    'connections' => [

        'sqlite' => [
            'driver' => 'sqlite',
            'database' => database_path('database.sqlite'),
            'prefix' => '',
        ],
```


~~ローカル環境構築もDocker使って、統一するんじゃダメなですかね。。。~~
KivyでSFライクなボタンを作る

# 完成したもの
Kivyで画像などを使わずにSFっぽいボタン作れないかなと思って作った。
結果こんな感じのボタンができました。
![SFButton.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483769/0460ada4-b99b-5e4b-df88-bde033214df3.jpeg)

# というわけで作ってみた
方針は単純で、ボタンのキャンバスに枠を二つ作ることで実現します。
main.pyとtest.kvを同階層において実行すれば最初の画像のようになります。

``` main.py
from kivy.app import App
from kivy.factory import Factory

class TestApp(App):
    def __init__(self, **kwargs):
        super(TestApp, self).__init__(**kwargs)
        
    def build(self):
        self.root = root = Factory.FloatLayout()

        btn = Factory.SFButton(
            text="This is SF !",
            size_hint=(0.5, 0.2),
            pos_hint={'x':0.25, 'y':0.4},
            on_release=self.btn_pushed
        )
        root.add_widget(btn)
        
        return root
    
    def btn_pushed(self, instance, *args):
        print(f"{instance.text} pushed !")


def main():
    TestApp().run()

if __name__ == '__main__':
    main()
```

``` test.kv
#: import hex kivy.utils.get_color_from_hex

<SFButton@Button>:
    background_color: hex('#44acac')
    canvas.before:
        Color:
            rgba: hex('#26c7e5')
        Line:
            width: 2
            rectangle: self.x, self.y, self.width, self.height

        Color:
            rgba: hex('#26c7e5')
        Line:
            width: 1
            rectangle: self.x-4, self.y-4, self.width+8, self.height+8
```

## ポイント
canvas.beforeでは色を指定→図を指定を連続すると絵が描けるそうですね。
それを利用して内側→外側の順に四角形を描画しています。
ここで外側の線を引くとき、内側と同じように

```
rectangle: self.x, self.y, self.width, self.height
```

としてしまうと・・・
![failed.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483769/b5f7fdc9-5083-4702-2dc2-78912f551ad9.jpeg)
とこのように内側の線しか見えなくなります。(なんで外側の線で上書きされないの？？)
その為外側の線では

```
rectangle: self.x-4, self.y-4, self.width+8, self.height+8
```

と少し大きな四角形になるように調整しました。この辺は外側の線のwidthをでまた変わると思います。ちなみに

```
rectangle: self.x-3, self.y-3, self.width+6, self.height+6
```

の場合は
![ex2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483769/6ea80528-1af8-1229-2485-58904a2f3df9.jpeg)
となりました。その他いろいろ試しましたが個人的には冒頭の画像になるtest.kvの調整が好きです。

色の指定は16進数の方が見やすいかと思い、kivy.utils.get_color_from_hex関数を利用しています。

# 最後に
画像なしでもまぁっぽい感じが出せたとは思います。
最終的には押されたときもSFライクなデザインで動作させたいなぁ、、