OmniAICreator/Qiita-1.07M huggingface dataset:
[Kotlin] コルーチンでCPUコアを全て使って並列処理

# はじめに
Kotlinのコルーチン、私はスレッドに対する明確なメリットを知らず、あまり使ってませんでした。
しかし今回、大量のレコードをなるべく速く処理したいという状況で、コルーチンがとても役に立ったので紹介します。

# マルチコアを使い切る

最近のCPUはたいてい複数のコアを持っていますが、シングルスレッドのプログラムでは１つのコアしか使うことができません。
しかし、並列で処理できるタスクなら全てのCPUコアを使って並列処理するのが一番速いです。

全てのCPUコアを使って並列処理するには、コアの数だけスレッドを作り、それらのスレッドを上手く管理して並列に処理をする必要がありますが、マルチスレッドプログラミングは落とし穴が多く、自分で実装すると意外と時間がかかるものです。
しかし、Kotlinのコルーチンを使えばそれを簡単に実現することができます。


# コードサンプル

コードから入ります。
以下の数行のコードでCPUコアを全て使って並列処理ができます。

```kotlin:コルーチン並列処理の例
import kotlinx.coroutines.*

fun <T> operateItems(items: Collection<T>, operate: (T) -> Unit) = runBlocking(Dispatchers.Default) {
    items.map {
        async { operate(it) }
    }.awaitAll()
}

```

簡単にコードの解説をすると、例えば、10万件のレコードを並列処理したい場合、引数`items`に10万件のレコードを渡し、引数`operate`に各レコードの処理をする関数を渡します。

各レコードについて、`async`関数で作られたコルーチンで並列処理が行われ、`awaitAll`で全ての処理が終わるまで待機します。

# コルーチンのスレッド管理

コルーチンは**Dispather**というもので、スレッドの使い方を決めます。
コルーチンは必ずしもマルチスレッドで動くとは限らず、Dispather次第でシングルスレッドで動かすこともできます。

コードサンプルではDispatcherに`Dispatchers.Default`を使用していますが、このDispatcherはCPUコアの数だけスレッドを作ってプールし、コルーチンの処理をそれらのスレッドで分散して実行します。
これにより全てのCPUコアを使って並列処理ができます。

[Dispatcher.Defaultの説明](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-dispatchers/-default.html)

コードサンプルの例では、async内に書いた`operate(it)`は、CPUコアが空き次第順番に実行されていきます。
例えば、４コアのCPUならoperateがまず４回実行され、いずれかの実行が終わり次第次のoperateが実行され、常に４つのoperateが並行実行されている状態になります。

# 速度計測


６コアCPUのマシンで上記のコルーチンのコードを実行し、シングルスレッドの処理と速度を比較してみました。
６コアなので上手くいけばコルーチンはシングルスレッドの６倍速になるはずです。

100ミリ秒くらいかかる処理を1000回実行するパターンと、10ミリ秒くらいかかる処理を10000回実行するパターンの2パターンで速度計測しています。

```kotlin:100ミリ秒くらいの処理を1000回実行するコード例
operateItems((1..1000).toList()) {
    processTakes100ms() // Math.pow()を大量実行して100msくらいかかるよう調整した関数
}
```

|                      |  シングルスレッド  | コルーチン   |
| ---------------------| ------------- | ---------- |
| 100msの処理 × 1000回  |  99.4s         |17.4s|
| 10msの処理 × 10000回  |  100.4s        |17.5s|

シングルスレッドで１００秒ほどかかる処理がコルーチンでは１７.５秒程度で、**シングルスレッドの５.７倍**ほどの速度になっています。
６倍には少し届きませんでしたが、十分許容できるオーバーヘッドです。

特に後者はコルーチンを１万個も生成していますが、それでも速度があまり落ちず、軽量であるというコルーチンの強み実感することができました。


# まとめ

- コルーチンのDispathcers.DefaultはCPUコアを全部使ってくれる
- コルーチンは軽いから大量生産しても大丈夫
windowsでdockerのvolume指定するときに環境変数使ったら;Cついてくる問題

対処ができればとりあえず良いと思うんで事象と対処について説明
### 環境
windows
vscodeでgitbash使用
docker desktop使用
### 事象
イメージ作って以下コマンド実行
```
docker container run -it -p 4567:4567 --name sinatra -v "${PWD}/srcs":/var/www sample/sinatra:latest
```
↓file sharing エラー発生（これは大したことないが）
```
docker: Error response from daemon: user declined directory sharing C:\Users\S724\Downloads\github\docker_ruby_yamaura\docker\src;C.
↑なんかパスの末尾に;Cついてるうう
```
心配になりつつfile sharingの設定をdocker desktopで設定
すると。。。
src;Cファイルが実際に作成されてしまっていたのです。
さらにファイル作ったりしてもdocker内の指定ディレクトリに同期されない・・・

### 対処
```
docker container run -it -p 4567:4567 --name sinatra2 -v "C:\Users\S724\Downloads\github\docker_ruby_yamaura\docker\srcs":/var/www sample/sinatra:latest
```

普通にパス指定したら治った

### 状況整理
・環境変数が介入すると末尾に;Cがついている
・git bash上ではC:\Users\S724\Downloads\github\docker_ruby_yamaura\docker\src;Cは想定したファイル.\srcを指している模様
・src;Cにファイルを作ったりしても同期されない
・対処のコマンドだと正しく機能する

# 追記（重要）
コンバータが悪さをしているみたいなので以下のように環境変数を設定した上で実行するとpwdでもいけました
```
MSYS_NO_PATHCONV=1 docker container run ...
```

上の参考：https://github.com/docker-archive/toolbox/issues/673
アプリの通知許可部分の小ネタ

# 現場で知った小ネタの共有
## あの許可モーダルってこんなことやっていたんですね
アプリのインストールして使い始めると「通知の許可」を確認してくるモーダルが出てきたことがあると思います。
あの質問は聞かれた瞬間にアプリの設定に項目を追加しているようです。

こんなやつです。↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2657595/7368eabf-d8cd-944d-f72f-7292ca0c12c2.png)

### 確認モーダルが表示される前のiPhoneの設定画面

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2657595/85700240-ecfc-d550-dc3b-fa3b4d2277e0.png)

### 確認モーダル表示後の設定画面

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2657595/bf5c58da-62d6-95d5-4e51-afdee04ac888.png)

### Flutterとfirebaseを使う場合
以下の感じの部分でモーダルが表示されます。
自分の環境で動作検証したところ
初回のみ確認モーダルが表示され、次回以降は通ってもモーダル表示はされないっぽいです。
```
FirebaseMessaging.instance.requestPermission(
　announcement: true,
　carPlay: true,
　criticalAlert: true,
);
```

### まとめ
これで困るケースがあるとは現時点では考えられませんが、特定のボタンを押して初めて確認モーダルが表示されるような実装をしていると、ユーザーによって設定項目の項目が変わってしまいます。
何かしらのバグの温床にはなりそうなので、必要な確認は必ずユーザーが通るように実装しておいたほうがよさそうです。
Androidは今度検証します。
リストの中のリスト？？めっちゃリスト？？

この記事は、岩手県八幡平市のプログラミング教室「アクセルキャンプ」の公開教材です。
[アクセルキャンプ(フリースペースプラウド)のリンク](https://freespaceproud.com)
教材の作成依頼等も承っております。ご意見等は、リンク先の問い合わせ欄からお願いします。
教材の転用・利用等は自由です。

# 「リストの中のリストってのはよ、俺見たいなリストを言うんだぜ」  
とかって意味ではないです。意味わかんないですよね。まあ、リッキー先生はイケメンの中のイケメンってよく言われますが、それってただイケメンってだけだよね、といつも心のなかで思っています。  
  
# リストの復習  
リストは複数のデータをひとまとめにして、変数名をつけたものでしたね。こんな感じのやつです。  
```python3
ricky = ["イケメン", "天才", "やさしい"]
```
  
リッキー先生の１００くらいあるいいところを３つの項目に絞って書いたわけですが、ちょっとシンプルすぎるので、それぞれの要素を深掘りしたいです。単純に
```python3
ricky = ["かっこいい", "スタイル抜群", "マッチョ", "IQ300","20ヵ国語喋れる"...]
```
とかって、ずーっと要素を書き足していってもイイんですが、なんせいいところが１０００くらいあるので、超絶見にくくなります。そこで便利なのが、**リストの中のリスト＝多次元配列**ってやつです。リストの中のデータの一つとして、小さいリストを入れることができます。実際に書いてみましょう。
```python3
ricky = [
    ["かっこいい", "スタイル抜群", "マッチョ"],
    [ "IQ300","20ヵ国語喋れる", "天才プログラマー"],
    ["みんなに好かれてる", "性格もイケメン", "いつも他人のことを考えてる"],
    ["メッチャモテる"]
]
```
書いてて蕁麻疹（じんましん）が出た人は、きっと疲れてるんですね。今すぐお医者さんに行きましょう。「あれ？項目一つ増えてね？」と思った人、気のせいです。  
  
***
という冗談はさておき、この多次元配列、プログラミングをやってるとめちゃくちゃ使います。  
例えばですが、皆さんのお家の電話番号や住所を、リストとして使うことをかんがえてみてください。電話番号と住所を登録するとして、  
Aさん：電話番号１１１ー１１１１－１１１１　住所A件B市C－１  
Bさん：電話番号２２２ー２２２２－２２２２　住所D件E市F－１
Cさん：電話番号３３３ー３３３３－３３３３　住所G件H市I－１  
て感じだったとしましょう。　　
これを全部横並びにすると、何がなんだかわからなくなります。
```python
information = ["Aさん", "１１１ー１１１１－１１１１","A県B市C－１", "Bさん", "２２２ー２２２２－２２２２", "D県E市F－１", "Cさん", "３３３ー３３３３－３３３３", "G県H市I－１"]
```

これを、Aさんだけの情報、Bさんだけの情報　Cさんだけの情報に分けた２次元配列にしてみましょう。  
```python
information = [
    ["Aさん", "１１１ー１１１１－１１１１","A県B市C－１"],
    ["Bさん", "２２２ー２２２２－２２２２", "D県E市F－１"],
    ["Cさん", "３３３ー３３３３－３３３３", "G県H市I－１"]
]
```

これで、だいぶ見やすくなりました。
# 二次元配列からのデータの持ってきかた  
上のプログラムから、Bさんの住所の情報を持ってきて表示したいとき、どうしたらいいでしょう？リストでは最初はゼロから始まることは覚えてますね。informationリストの中で、Bさんの情報は２番目＝１番目なので、まずはこれを表示してみましょう。  
```python
#リストは省略
print(information)
```  
>実行結果：['Bさん', '２２２ー２２２２－２２２２', 'D県E市F－１']

こんな感じで、Bさん関連の情報がまるっと出てきました。  
その中の一つだけ、住所だけ抜き出したいんでしたね。住所はこの小さいリストの３番目＝２番め名ので、このようにすると持ってこれます。
```python
#リストは省略
print(information[1][2])
```
このようにして、大きいリストから順番にインデックス番号（要素の番号）を指定していきます。「infromationリストの中の◯番目のリストの中の△番目の要素」といった感じで指定したい場合は、
```python
infromation[◯][△]
```
といった形になります。　

# これって一体何に使うの？  
例えばインベーダーゲームのようなゲームを作っていて、敵の場所を格納しておくリストを作成するとします。 
こういう場合、X座標とY座標があり、「この敵のｘ座標を知りたい」「この敵をY方向に動かしたい」みたいな状況がよくあります。そんなときは、ｘ座標とY座標のみの小さなリストを、大きなリストにいくつも入れることで、全ての敵の座標が管理できます。
```python
enemy = [
    [10, 200],
    [150, 327],
    [49, 68],
    ...
]
```
こんな感じで、データをいい感じに管理するのに超便利なので、覚えといてください。  
  
# 宿題！
自分の家族の家族の名前、誕生日をまとめたinformationリストを作りましょう。
そして、その中から自分の誕生日だけを出力してみてください。  
余裕があれば、更にメンバーを追加したり、身長など他のデータもリストに入れて管理してみましょう。（体重とかは書く前に本人に聞こうね！！念のため！！）  
  
今回は以上ですが、授業でやったblenderの使い方も[ここ](https://qiita.com/ricky-sensei/private/21bc0b6e08db876559bd)にまとめたので、よかったら見てみてください！  
ではまた来週！！
Reactで画像をグラフに導入

## 前提
以前作成した下記記事の環境からスタート

https://qiita.com/sh19982580/items/5f71856c7949c494d769

## コマンド
下記コマンドでライブラリを入れる
`yarn add chart.js react-chartjs-2`

## コード

    import React from "react";
    import { Chart, registerables } from "chart.js";
    import { Bubble } from "react-chartjs-2";

    Chart.register(...registerables);

    const img = new Image();
    img.src = "URL";
    img.width = 100;
    img.height = 100;

    const img2 = new Image();
    img2.src = "URL";
    img2.width = 100;
    img2.height = 100;

    const data = {
      datasets: [
        {
          data: [
            {
              x: 10,
              y: 25,
              r: 1,
            },
          ],
          pointStyle: img,
        },
        {
          data: [
            {
              x: 20,
              y: 10,
              r: 1,
            },
          ],
          pointStyle: img2,
        },
      ],
    };

    const App = () => {
      return (
        <>
          <h1>マッピング</h1>
          <Bubble data={data} width={10} height={10} />;
        </>
      );
    };
    export default App;

## 確認
ターミナルで`yarn start`
ブラウザで`http://localhost:8111`にアクセス
グラフが表示されていたらOK！

## 最後に

グラフのドット部分を画像にするところが非常に時間がかかりました。
色んなライブラリをいじってみて、`react-chartjs-2`ならできそうだったので、作成しました。
まだ、コードが固定値、グラフも見栄えが良くないですが改良すれば良さげなものが完成しそうです！

## 参考文献

https://www.chartjs.org/docs/latest/configuration/elements.html#types

https://react-chartjs-2.js.org/components/bubble
STM32G031とMCP9701で温度をシリアルに出力 (UnbufferedSerial)(テーブル方式)

x MCP9701-E/TO 販売コード 103199

x 超超重要 なぜか秋月STM32G031J6M6がうり切れていた。注意!!(2022/8/27現在)


x 過去ログを見よ
x PA_2をOBでGPIOに出来る人むけ
x STM32G031は、秋月で売っているSTM32G031J6M6の事

目的
秋月で売っている安価なMCP9701(約25円)を使って温度を出力する。
なぜこうなったかは、MCP9701のログをみて
センター400mV,ステップ19.5mV/1℃


![o_con692.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/d8403f0c-d50a-be20-d31c-ecbbd422595d.jpeg)


![o_con693.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/b2abc366-2f97-3bbf-1a2f-9cd278a90c0d.jpeg)


![o_con694.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/b53cdbca-9957-aaae-75da-d4e8e0659a7c.jpeg)



```c++



//SER_MCP9701_table_031_1


//温度

static const char tmp_t[]= {
    0*2+0,0*2+1,0*2+1,
    1*2+0,1*2+1,1*2+1,
    2*2+0,2*2+1,2*2+1,
    3*2+0,3*2+1,3*2+1,
    4*2+0,4*2+1,4*2+1,
    5*2+0,5*2+1,5*2+1,
    6*2+0,6*2+1,6*2+1,
    7*2+0,7*2+1,7*2+1,
    8*2+0,8*2+1,8*2+1,
    9*2+0,9*2+1,9*2+1,
    10*2+0,10*2+1,10*2+1,
    11*2+0,11*2+1,11*2+1,
    12*2+0,12*2+1,12*2+1,
    13*2+0,13*2+1,13*2+1,
    14*2+0,14*2+1,14*2+1,
    15*2+0,15*2+1,15*2+1,
    16*2+0,16*2+1,16*2+1,
    17*2+0,17*2+0,17*2+1,
    18*2+0,18*2+0,18*2+1,
    19*2+0,19*2+0,19*2+1,
    20*2+0,20*2+0,20*2+1,
    21*2+0,21*2+0,21*2+1,
    22*2+0,22*2+0,22*2+1,
    23*2+0,23*2+0,23*2+1,
    24*2+0,24*2+0,24*2+1,
    25*2+0,25*2+0,25*2+1,
    26*2+0,26*2+0,26*2+1,
    27*2+0,27*2+0,27*2+1,
    28*2+0,28*2+0,28*2+1,
    29*2+0,29*2+0,29*2+1,
    30*2+0,30*2+0,30*2+1,
    31*2+0,31*2+0,31*2+1,
    32*2+0,32*2+0,32*2+1,
    33*2+0,33*2+0,33*2+1,
    34*2+0,34*2+0,34*2+1,
    35*2+0,35*2+0,35*2+1,
    36*2+0,36*2+0,36*2+1,36*2+1,
    37*2+0,37*2+1,37*2+1,
    38*2+0,38*2+1,38*2+1,
    39*2+0,39*2+1,39*2+1
};


static const char data[][5]= {
    "00.0","00.5","01.0","01.5","02.0","02.5","03.0","03.5","04.0","04.5","05.0","05.5","06.0","06.5","07.0","07.5","08.0","08.5","09.0","09.5",
    "10.0","10.5","11.0","11.5","12.0","12.5","13.0","13.5","14.0","14.5","15.0","15.5","16.0","16.5","17.0","17.5","18.0","18.5","19.0","19.5",
    "20.0","20.5","21.0","21.5","22.0","22.5","23.0","23.5","24.0","24.5","25.0","25.5","26.0","26.5","27.0","27.5","28.0","28.5","29.0","29.5",
    "30.0","30.5","31.0","31.5","32.0","32.5","33.0","33.5","34.0","34.5","35.0","35.5","36.0","66.5","37.0","37.5","38.0","38.5","39.0","39.5"
};


#include "mbed.h"

//シリアルの定義
UnbufferedSerial serial_port(PA_2, PA_3); //031

//アナログ入力の設定
AnalogIn adc_vbat(PB_7); //PB_7 ADC1/11


//メイン関数
int main()
{

    //シリアルの初期化
    serial_port.baud(9600);
    serial_port.format(
        /* bits */ 8,
        /* parity */ SerialBase::None,
        /* stop bit */ 1
    );

    //無限ループ
    while(1) {

        //センサーのADC値を0から512に変換
        int s = (int)(adc_vbat.read() * 512.0);
 
        //温度の表示
        //s = (s >> 3);
        if(s >= 184) {
            serial_port.write("40.0", 4);
        } else if(s <= 62) {
            serial_port.write("-0.0", 4);
        } else {
            serial_port.write(data[tmp_t[s-63]], 4);
        }
        serial_port.write("\r\n", 2);

        //1秒待つ
        wait_us(1000*1000);

    } //while

} //main




```
"||"はどんな時に使うのか？

はじめに
--
ポートフォリオを作成していく中で、「これ何してるの、、？」というコードに出会うことがしばしばあります。
やはり何をするにも土台が大切だろうと言うことでわからないことを一つ一つ調べて備忘録として残していこうと思います。
千里の道も一歩から！

or演算子
--
左辺を最初に評価し（真偽値かどうか調べる）、偽だった場合に右辺を評価する。
~~~rb
# trueを返す
false || true 

#3は真なので左辺で3を返す
3 || 5 

# trueを返す
false || nil || true 

#trueを返す(trueの箇所で評価は終了。nilの箇所は評価すらしていない）
false || true || nil 
~~~

自己代入演算子
--
aが偽か未定義だった場合、aに左辺(今回はhoge)を代入する。

~~~rb
#hogeが返ってくる
a ||= hoge
puts a #=>hoge

#hogeが返ってくる(既にaにはhogeが代入されているので、pogeは代入されない）
a ||= poge
puts a #=>hoge
~~~

自己代入演算子が原因で実際に起きたエラー
--
余談ですが、下記のように自己代入演算子が記述されていたことでRSpecが失敗してしまったことがありました。

~~~.spec/rails_helper.rb
ENV['RAILS_ENV'] ||= 'test'
~~~

DockerfileでRAILS_ENVに"development"を代入してしまっていたため、test環境でRSpecを実行できなかったのです。

~~~yml
RAILS_ENV: development
~~~

"||"を削除して、testを代入するとエラーは解消しました。
これも詳しい仕組みを理解できていないので、今後調べてみようと思います。
~~~.spec/rails_helper.rb
ENV['RAILS_ENV'] = 'test'
~~~


終わりに
--
演算子はとても多いですが、意味がわかるととても便利なものだなと感じました。
コツコツと一つずつ学んで、土台を固めていきたいと思います。

参考
--
https://docs.ruby-lang.org/ja/latest/doc/symref.html
DANE とは

## 勉強前イメージ

見たことないかも？？

## 調査

### DANE とは

DNS-Based Authentication of Named Entities の略で、デーンと読みます。
DANEはDNSを用いて通信するための仕組みになります。
[DNSSEC](https://qiita.com/miyuki_samitani/items/0f26423cf54d7bd20c07) を利用してDANE自体はドメインの証明書を発行する認証局、または証明書の紐づけを行い
証明書を不正に発行するようなことを防ぎます。

悪意を持った第三者はドメインの所有者ではなく認証局を狙って証明書を不正に発行したりします。
それを防ぐのがDANEです。

### DANEが格納する情報について

DANEはTLSAレコードというものに証明書の情報を定義します。
以下は定義されている4種類になります。

- CA証明書の情報

SSL証明書の発行元CAの証明書情報または公開鍵のハッシュ値になります。
ハンドシェイクで取得した証明書の階層検証を行ってCA証明書があることを確認します。

- エンドエンティティ証明書の情報

SSL証明書の情報。
ハンドシェイクで取得した証明書がTLSAレコードと一緒であることを確認します。

- トラストアンカーの証明書の情報

SSL証明書の階層の最上位にいるCA、 [トラストアンカー](https://qiita.com/miyuki_samitani/items/1b96627516687c865b18) の情報になります。
ハンドシェイクで取得した証明書の階層検証を行ってトラストアンカーがTLSAレコードに設定された証明書と一致することを確認します。

- 自己署名証明書の情報

いわゆるオレオレ証明書の情報になります。
取得した証明書がTLSAレコードに設定された証明書と一致することを確認する必要があります。

## 勉強後イメージ

DNSって結構セキュリティ的にも狙われてるんじゃない？って感じしてる・・・
最近DNSを調べててめっちゃいろいろあるなぁと。

## 参考

- [DANEとは](https://www.nic.ad.jp/ja/basics/terms/dane.html)
- [DNS-based Authentication of Named Entities（DANE)(https://college.globalsign.com/blog/dane/)
【#54 エンジニア転職学習】GORMでテーブルリセット/goqueryをループ処理

# はじめに
富山県に住んでいるChikaといいます。
毎日投稿を目標に、バックエンドエンジニア転職に向けた学習内容をアウトプットします。

 引き続きスクレイピングのプロジェクトをつくっていきます。

バックエンドエンジニアになるまでの学習内容は以前投稿した以下の記事を基にしています。


https://qiita.com/Chika110/items/ef54dddd565a0193ef44

# 本日の学習内容
本日はMySQLのテーブルリセットとスクレイピングのループを追加しました。
* **DBテーブルのリセットとスクレイピングのループ処理追加　←Topics!!**


# DBテーブルのリセットとスクレイピングのループ処理追加
URL一覧のスクレイピングコードを調整しました。
**①スクレイピングの開始時に毎回DBテーブルをリセットする機能
②複数ページをスクレイピングできるようにループ処理**
の2点を追加しました。
ついでに`main.go`にまとめて書いていたスクレピング実行文を`scrape`パッケージに移動しました。

①については、毎回リセットでいいので`gorm.Migrator().DropTable()`を使用してテーブル毎削除　→　直後にマイグレーションの流れにしました。

②は通常の`for`文を使用しているだけですが、アクセスの間隔をあけるためのtime.Sleepを入れてます。
また、ページをすべてスクレピングしたあとにまとめてINSERTしてほしいので、`gorm.Create()`はループの外に出してあります。

```main.go
package main

import (
	"job_offer_scraping/db"
	"job_offer_scraping/scrape"
)

func main() {
	dbconn := db.DbConnect()
	scrape.SaveURLs(dbconn)
}
```
```dbmodels.go
package db

import "gorm.io/gorm"

type Mynavi_url struct {
	gorm.Model
	URL string
}
```
```base.go
package db

import (
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

func DbConnect() *gorm.DB {
	var dsn = "USER:PASS/job_offer_scraping?charset=utf8mb4&parseTime=True&loc=Local"
	db, err := gorm.Open(mysql.Open(dsn))
	if err != nil {
		panic("failed connecting DB")
	}
   	db.Migrator().DropTable(&Mynavi_url{})
	db.AutoMigrate(&Mynavi_url{})
	return db
}
```
```scrape.go
package scrape

import (
	"job_offer_scraping/db"
	"log"
	"net/http"
	"strconv"
	"strings"
	"time"

	"github.com/PuerkitoBio/goquery"
	"gorm.io/gorm"
)

func SaveURLs(dbconn *gorm.DB) {

	var urllist []db.Mynavi_url

	for i := 1; i < 2; i++ {
		url := "https://tenshoku.mynavi.jp/list/pg"
		url += strconv.Itoa(i)
		url += "/"

		res, err := http.Get(url)
		if err != nil {
			log.Fatal(err)
		}
		defer res.Body.Close()
		if res.StatusCode != 200 {
			log.Fatalf("status code error: %d %s", res.StatusCode, res.Status)
		}

		doc, err := goquery.NewDocumentFromReader(res.Body)
		if err != nil {
			log.Fatal(err)
		}

		doc.Find("div.cassetteRecruit").Each(func(i int, s *goquery.Selection) {
			href, _ := s.Find("p.cassetteRecruit__copy > a").Attr("href")
			href = string([]rune(href))
			url := strings.SplitAfterN(href, "/", 3)
			trimurl := strings.Join(url[0:2], "")

			mynaviurl := db.Mynavi_url{URL: trimurl}
			urllist = append(urllist, mynaviurl)
		})
		time.Sleep(30 * time.Second)
	}
	dbconn.Create(&urllist)
}
```

#### 使用している教材はこちら↓

https://www.youtube.com/watch?v=tYbVl6N8oxI&list=PLv6F1QYhG31S-sDkutIQjCnKjFTvjuUus&index=1&t=2049s

# おわりに
最後までお読みいただきありがとうございました。
アドバイス・応援コメント等いただけますと幸いです。
MySQLへレコードを追加するSQL

# INSERT文

データベースへレコードを追加するには
`INSERT文`が必要です

### INSERTの書き方

```
INSERT INTO `テーブル名`( `列名1`, `列名2`, `列名3`, `列名4`, `列名5`, `列名6`) VALUES ('値1','値2','値3','4','5','6')
```

見本のテーブル名は実際に使用するデータベースのテーブル名に置き換えます
見本の列名は実際に使用するデータベースの列名（カラム）に置き換えます。



## 発生するエラーについて

#### 設定している`データ型`（text,intなど）に`間違った値を入れる`とエラーが発生します
    
    - 対策：int型（整数型）の列に対してはint型（整数型）の値を入れる
    - 対策：idなどのAUTO_INCREMENT(自動加算）列は`列名`と`値`を省略する
    - 対策：timestamp型（自動更新日時挿入）の列は`列名`と`値`を省略する
#### INSERT文に記述している、`列名の数`と`値の数`が相違する

    - 対策：INSERT文に記述する列名の数と対応する値の数を等しくする
    - 例：列が5種類に対し、入力しようとしている値の数が4種類だった場合はエラーになる
    - 対策：自動で入力されるIDやタイムスタンプなどは省略する
    - 例：列が5種類に対しIDなどの自動入力列が1列含まれる場合、IDの列を省略し、列と値は計4種類でSQLを記述する
#### テーブルに存在する列は一度のSQL処理で全て埋める必要がある


    - 対策：列が合計2列存在する場合は、2列分の値を一度に入力する必要がある
    - 例：( `列名1`, `列名2`) VALUES ('値1','値2')
    - 例：自動入力分（IDなど）がある場合はその分を省略する

## SQLコマンド入力の短縮とSQLの実行
### MySQLでフォーマットを入力する

![スクリーンショット 2022-08-19 21.26.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2765288/ed530ac5-d77b-afcc-e04a-1f51268a91f7.png)

1. ブラウザのMySQL画面よりSQLタブを開きます
1. INSERTボタンを押すことでテーブル名とカラム名が自動入力されたSQL文が出力されます
1. 値側の [] は文字列なので消去しなければエラーの原因になります
1. SQL文の修正が済んだら実行ボタンを押します
DAO -Web3で注目の技術①-

# はじめに
IT×ビジネスという視点で週1本記事を投稿しています。
もし興味のある方は下のリンクから他の記事も見ていただければ幸いです。
 [@7_inai_](https://qiita.com/7_inai_)

本記事では、Web3で注目の技術①としてDAOについてまとめます。
Web3については[こちらのリンク](https://qiita.com/7_inai_/items/c441008bb0849908fbc6)からご確認ください。


 [Web3でビジネスはどう変わる？]
# DAOとは
DAO（Decentralize Autonomous Organization）とは分散型自立組織のことで、[ブロックチェーン](https://qiita.com/7_inai_/items/2ea53163ae5ec3df9cfe)上で世界中の人々が協力して管理・運営する __組織__ のことです。
つまり、中央集権的な管理者がおらず、参加者全員が平等でありかつ誰でも自由にDAOの活動に参加できることが最大の特徴です。


# DAOについての重要ワード
- ガバナンストークン：組織内で投票を行うために発行される通貨
→ユーザーの投票は、ガバナンストークンの保有量によって重み付けされます。長期的にプロジェクトの健全な運営に関心を持つように、取引手数料の一部をガバナンストークン保有者に分配することもあります。
- スマートコントラクト：ブロックチェーンシステム上に設定されたルールに従って自動的に取引が実行されるプログラム
→例えばガバナンストークンによる投票により過半数を超えた場合は、スマートコントラクトにより実行されます。

# DAOの事例
DAOという言葉を聞き覚えのない方もいるかもしれませんが、世界中では多くのDAOが存在しています。例えば以下のようなDAOがあります。

### 土地を買ったCityDAO
ブロックチェーン都市を作ることを目的として作られたDAOがあります。このDAOの参加者から集めたトークンで実際にアメリカのワイオミング州に土地を買い、市民権をNFT化して発行しています。実在する土地に対してガバナンストークンを使って意見を募り、都市化させていきます。
シムシティ(街を建造するゲーム)を現実世界でしているようなイメージです。

# 終わりに
宇宙旅行を行ったことで話題の前澤友作氏が、先日MZDAOというDAOのコミニティの参加者をLINEや Twitterで募集していました。詳細もわからない部分が多く、これからどう進むのかも所属している全員で検討していくとのことです。前澤さんも注目するDAOがこれからどうなっていくのかが非常に楽しみです。

最後までお付き合いくださりありがとうございました。
PostgreSQL チート・カラムにユニーク制約をつける

- [あるWebサービスの開発メモ・目次ページに戻る](https://qiita.com/ishi32/items/152a1ecf7eeee7a8fb57)
- [あるWebサービスの開発メモ・PostgreSQL チートに戻る](https://qiita.com/ishi32/items/eaa4c1f3a4cf8f3d4170)

### やりたいこと

ユーザプロフィールテーブルのユーザ名はユニーク制約をつけて同一のユーザ名の登録を受け付けないようにしたい

### tl;dr

#### PostgreSQL のカラムにユニーク制約をつける

```
ALTER TABLE "(テーブル名)" add constraint "(制約名)" unique "(カラム名)";
```

### 実際にやってみる

#### ユーザプロフィールテーブルのスキーマ

Supabase の SQL Editor で以下を投入

```
select column_name, ordinal_position, data_type from information_schema.columns where table_schema = 'public' and table_name = 'profiles' order by ordinal_position;
```

以下が返される

| column_name   | ordinal_position | data_type                |
| ------------- | ---------------- | ------------------------ |
| id            | 1                | uuid                     |
| created_at    | 2                | timestamp with time zone |
| updated_at    | 3                | timestamp with time zone |
| username      | 4                | text                     |
| avatar_url    | 5                | text                     |
| plan          | 6                | text                     |
| contact_madd  | 7                | text                     |
| year_of_birth | 8                | text                     |
| zip           | 9                | text                     |
| job           | 10               | text                     |
| facebook      | 11               | text                     |
| twitter       | 12               | text                     |
| homepage      | 13               | text                     |
| blog          | 14               | text                     |
| gender        | 15               | text                     |
| score         | 16               | numeric                  |

#### ユニーク制約をつける

Supabase の SQL Editor で以下を投入

```
ALTER TABLE "profiles" add constraint "profiles_username_constraint" unique ("username");
```

#### 動作確認

Supabase の SQL Editor で以下を投入

```
select id, username from profiles;
```

以下が返される

| id                                   | username   |
| ------------------------------------ | ---------- |
| d35b807f-ab47-4173-a50c-cd16032bbdca | yuta       |
| df971572-8be0-42e2-8246-52b6ab65383f |            |
| 0b0393b1-cdb5-47de-a0ca-b2b15d0751b2 | mike       |
| 1a679275-2447-4a02-9230-b95e850a22c9 | sirokuro公式 |

Supabase の SQL Editor で以下を投入

```
update profiles set username = 'mike' where id = 'df971572-8be0-42e2-8246-52b6ab65383f';
```

以下が返される

```
Failed to run sql query: duplicate key value violates unique constraint "profiles_username_constraint"
```

「duplicate key value violates unique constraint "profiles_username_constraint"」を含む文字列が返却された場合は「指定のユーザ名は既に登録されています」といったメッセージをユーザに通知できればよさそうだ。

念のために初めの select を再度実行

```
select id, username from profiles;
```

問題なさそう

| id                                   | username   |
| ------------------------------------ | ---------- |
| d35b807f-ab47-4173-a50c-cd16032bbdca | yuta       |
| df971572-8be0-42e2-8246-52b6ab65383f |            |
| 0b0393b1-cdb5-47de-a0ca-b2b15d0751b2 | mike       |
| 1a679275-2447-4a02-9230-b95e850a22c9 | sirokuro公式 |
SwiftUIでButtonを実装するときはButtonStyleを使おう

# 概要
SwiftUIでカスタマイズした見た目のButtonを実装するときは、ButtonStyleを使うやり方とそうじゃないやり方があります。
ButtonStyleを使った方が便利で簡単でシンプルなコードを書くことができます。
しかし、SwiftUIのButtonの実装方法について検索するとButtonStyleを使わないやり方が多く見つかります。

この記事では角丸ボタンのコードを例に、SwiftUIでのButtonの作り方を紹介します。


# SwiftUIでのButtonのカスタマイズ方法
SwiftUIでのButtonの作り方は大きく分けて二つ。Labelをカスタマイズする方法と、ButtonStyleを作成する方法です。

## ButtonのLabelをカスタマイズする方法
```swift:RoundedButton.swift
struct ContentView: View {
    var body: some View {
        Button(action: {}) {
            //カスタマイズしたLabel
            Text("Button")
                .padding()
                .foregroundColor(.white)
                .background(.green)
                .cornerRadius(8)
        }
    }
}

```



## ButtonStyleを使ってカスタマイズする方法
```swift:RoundedButtonStyle.swift
struct ContentView: View {
    var body: some View {
        Button(action: {}) {
            Text("ButtonStyle")
        }
        .buttonStyle(RoundedButtonStyle())
    }
}


struct RoundedButtonStyle: ButtonStyle {
    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .padding()
            .foregroundColor(.white)
            .background(.green)
            .cornerRadius(8)
            .opacity(configuration.isPressed ? 0.2 : 1)
    }
}

```

# 二つの方法の比較
一見するとLabelのカスタマイズの方がコード量が少なくてシンプルなコードに見えます。しかし、実際の開発ではButtonのような部品のコードが肥大化することで可読性が下がり、わかりづらいコードになりやすいです。
複数のボタンに同じ見た目を適用するとコードがもっと無意味に複雑になっていきます。


ButtonStyleによるカスタマイズではButtonStyleを作成することで、Buttonを宣言するコードをシンプルに保つことができます。コードを再利用することも簡単になります。 
もう一つのメリットとして、ボタンが押下された時の動作もconfigurationを使って簡単にカスタマイズすることができるようになります。


# まとめ　
SwiftUIでのButtonのカスタマイズはButtonStyleを使った方が便利でわかりやすい、シンプルなコードを書くことができます。
特に理由がなければButtonStyleによるカスタマイズを利用することがお勧めです。
 
今回は紹介しませんでしたが、公式にもいくつか便利なButtonStyleがあるのでぜひ利用してみてください。　

# 参考資料　
https://developer.apple.com/documentation/swiftui/buttonstyle
GASをスプレッドシートから開くときに、「Googleドキュメント内でエラーが発生しました。このページを再読み込みするか...」というエラーを解決した。


### 問題

スプレッドシートからGASを開こうとしたときに以下の画像のようなエラーが出てしまい、ヘルプセンターのリンクに飛んでも解決することができませんでした。


![gaserror.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2788880/179a33a4-74d6-b0e0-f87a-b3cf27335c88.jpeg)

### 解決策

以下の手順で解決しました。
1. Chromeタブの右上にある３つの点みたいなところを押して、「設定」を選択します。
![スクリーンショット 2022-08-19 20.57.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2788880/ffca4723-8c50-0ee6-66d7-edde2e911a00.png)

2. 次の画面の左に出てくるサイドバーの「プライバシーとセキュリティ」を選択します。
![スクリーンショット 2022-08-19 20.58.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2788880/99496801-8d71-1284-8418-b1d5b0827ea1.png)

3. 「閲覧履歴データの削除」を選択します。
![スクリーンショット 2022-08-19 20.58.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2788880/ad070c3f-cad5-3f68-2fe9-64388b1ac51c.png)

4. 以下の画像のような画面になるので、そのまま「データを削除」のボタンを押します。
![スクリーンショット 2022-08-19 20.58.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2788880/38eeda02-6908-e323-afe8-ab0b35fbf66c.png)


### 終わりに

僕はこの手順で解決しました。</br>
同じエラーで悩まれた方のお力になれれば幸いです。
#1 【 Unity の教科書 】 をマスターするまでの記録

**【Unityを学ぶ理由】**
<dl>
    <dt>① 自分が作りたいと思う，アプリケーションを作れるようになる</dt>
    <dd>自分が作れるアプリなんて，他の優秀な人がすぐに作ってしまえるだろうとネガティブモードになるが，自分のできることが増えればそんなことはないと！考える。<br>
良くない方向に考えてしまい，行動に移せないことが自分の良くない部分だと思う。こう考えてしまう原因をなくすようにしたい。<br>
行動と目標を具体的に書き出すことで，現在の行動を肯定化して，日々の成長を加速させたい。
</dd>
<p>
  <br>  
</p>
<dt>② Unity でアプリを作ることで，収入を増やせるようになる</dt>
    <dd>お金をUnityを使うことで稼げるようになって，会社でなく自分でお金を生み出すことを経験する</dd>
</dl>

**【目標】**
<dl>
  <dt>8月中に，Unity の教科書を1周終える事を目指す</dt>
  <dd>Unity の基本操作に慣れる</dd>
<p>
  <br>  
</p>
  <dt>その際の疑問・解決方法・学びをアウトプットする</dt>
  <dd>疑問があった時に，すぐにやる気が無くなる癖がある（過去の経験の影響あり），<br>
良い調べ方を学び，疑問・壁に直面する　→　それを解決する。を楽しめるようになりたい。<br>アウトプットする習慣・癖を付ける
</dd>
</dl> 

**【予定】**
・Unityの教科書(449ページ)，現在164ページ，残り285ページ
・今日の日付 8月19日，8月の残りの日数13日
・余裕を持ち，8月27日までに1周終わらせることを目指す
→ 31ページ / day のペース
・8月19日
→ 195ページまで
 

**【8月19日の成果】**
→ 196ページまで終了
分かりやすい文章を書くには

## 文章は短く
文章は短く書くことが基本です。最初から短く書けない場合は、最初は長い文章で書いても全然大丈夫です。一度文章を書き上げた後に、余分な文をそぎ落としながら、徐々に短い文章に仕立てていければいいのです。

## インプットを多く
名文を沢山読み込むことも有効です。名文はそれだけで文章の型となっています。名文を沢山覚えて、自分の中にストックを作っておくと、文章を書いている途中で、ふと、ストックの中から文章が出てくることがあります。いい文章事例に沢山触れるようにしましょう。

## 分かりやすい言葉を発する
日頃からトレーニングのように、意識して分かりやすい言葉を発し続けていることが大事だと考えます。自分のペンから分かりやすい文章が出てくるには、まず、頭の中で分かりやすい文章が、無声の言葉として出てこなければなりません。ペンは出てきた文章を、紙の上になぞるだけです。日頃から何を考え、どのような言葉を発しているかが、重要になってくると思います。

## 人に教える
人に教えるという行為も、分かりやすい文書を書くためのトレーニングになっていると思います。後輩に仕事の仕方を教える、家族の人にパソコンの操作を教えるなどは、実にいいトレーニングになっていると思います。そして、教えた後の相手の反応を知ることも大事です。文章を書くと、情報の伝達は一方通行になりがちです。直接人の教えると、自分の説明の仕方の良し悪しがダイレクトに返ってくるため、見直す切欠にできます。「この説明の仕方は良くなかったかな」と思ったら、その場で即、修正ができます。そして、事例データベースにストックしておいて、次回に生かすことができます。

## 話し方をカスタマイズする
「自分の説明が伝わらないのは、他人の理解力の無さが原因である」このように決めつけてしまえばそれまでです。その主張は一理あったとしても、どう工夫すれば伝わるのかを、常に考えることが大事です。自分は海外に行って、相手の言っている英語がチンプンカンプンで、困り果てたことがあります。相手は「この人は自分が話している英語が理解できないらしい」と悟ったのか、中学レベルの単語だけを使って、全ての文法を噛み砕いて、丁寧に言い直してくれたのでした。「おー、そのレベルの単語なら流石に理解できるぞ」と、喜んだものです。日本人が日本人に物事を説明をする際、そもそも日本語が分からいということはない。普段の会話で、難しい単語が頻発することも、自信の経験上、そうそうない。自分は分かりやすい説明をしているつもりでも、相手は分かり難いと捉えることがある。相手が分かってくれるかどうかは、相手の事前知識のレベルによって変わってくるものです。「相手は分かっていないな」と思ったら、相手に合わせて、説明の仕方をカスタマイズして説明する必要があります。どのようにカスタマイズすればいいのかは、最初は難しいかも知れない。ひとえに経験値を積むことだと思う。
非デザイナーにこそ見てほしい！デザインに違和感を感じたときに見るべき４つのポイント

## はじめに
非デザイナーの方でフロントを実装していて何かかが違うけど何が違うのかわからなかったり、
見ていて内容が入りづらいと感じたことはないでしょうか？
私は過去にデザインがないのでよしなにやってほしい、いい感じにしてほしいと依頼されたときにデザインの知識が全くなくて苦戦した経験があります。
そのようなときに今からご紹介する４つのポイントを知っていればスムーズに対応できるかもしれません。

## 概要
４つのポイントとはずばりデザインの基本である４原則のことです。
４原則とは「近接・整列・強弱・反復」のことで、情報を整理して見やすくするための考え方です。
デザインで思考を組み立てて表現するときや、仕事で使うような資料づくりにも役立つのでとても便利です。

## 本題
それでは４原則についてそれぞれ解説していきます。

**１.近接**
関係する情報を近づけてグループ化する
![content_A.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249131/aa0b1840-0925-ecf0-6ce8-ab700a76de16.png)

**２.整列**
要素を規則的に配置して一体性をもたせる
![content_B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249131/77581f2e-1b20-0f54-3bd6-0d4f99959b0a.png)

**３.強弱**
要素の優先度を明確にするために色や大きさを使い分ける
![content_C.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249131/61326f99-c591-d444-d02c-82de8e74a843.png)

**４.反復**
同じ要素を規則的にくり返すことで一貫性をもたせる
![content_D.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249131/6d5f4f89-6fb3-be01-ae7e-9079d89417c1.png)

## おわりに
４原則以外にも余白や色に関する法則など他にもいろいろがありますが、今回は必要最低限なところだけをご紹介させていただきました。
少しでもフロント実装のお役にたてれば幸いです。
最後まで読んでいただきありがとうございました！
配列をネストしたブロックに変換する

# やりたいこと

配列をネストしたブロックに変換したい。

たとえば、ブロックを受け取る transaction という共通の名前のクラスメソッドを持ったクラス CuteDB, CoolDB, EpicDB があるとして

```rb
nested_transactions([CuteDB, CoolDB, EpicDB]) do
  hoge
end
```

を

```rb
CuteDB.transaction do
  CoolDB.transaction do
    EpicDB.transaction do
      hoge
    end
  end
end
```

という構造に変換したい。ネストする順番を動的に決定するのが目的。

# 方法

Proc オブジェクトと Enumerable#inject を利用する。

(@kts_h さんのコメントのおかげで nested_transactions メソッドの実装がシンプルになりました :pray::sparkles:)

```rb
module CuteDB
  def self.transaction
    puts('CuteDB start')
    yield
    puts('CuteDB end')
  end
end

module CoolDB
  def self.transaction
    puts('CoolDB start')
    yield
    puts('CoolDB end')
  end
end

module EpicDB
  def self.transaction
    puts('EpicDB start')
    yield
    puts('EpicDB end')
  end
end
    
def nested_transactions(dbs, &block)
  # 配列の最初の要素を一番外側、最後の要素の一番内側にしたいので
  # reverse (reverse_each) する。
  dbs.reverse_each.inject(block) do |nested_blocks, db|
    proc { db.transaction(&nested_blocks) }
  end.call
end

nested_transactions([CuteDB, CoolDB, EpicDB]) do
  puts('I am working on my precious DBs.')
end
# CuteDB start
# CoolDB start
# EpicDB start
# I am working on my precious DBs.
# EpicDB end
# CoolDB end
# CuteDB end

nested_transactions([EpicDB, CuteDB]) do
  puts('I am working on my precious DBs.')
end
# EpicDB start
# CuteDB start
# I am working on my precious DBs.
# CuteDB end
# EpicDB end
```
一般的にダウンロードされているファイルではなく、危害を及ぼす可能性があります。

ウェブサイトで、ファイルをダウンロードできるようにすると、
`Google セーフ ブラウジング`の仕組みを利用しているブラウザで警告がでる場合がある。

- **Chrome**　一般的にダウンロードされているファイルではなく、危害を及ぼす可能性があります。
- **Firefox**　このファイルを開くのは危険です。

その時は、

Google Search Consoleで
`セキュリティの問題`から、**審査をリクエスト**すると、良いらしい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132059/61bfc825-1b6a-8cff-b866-0fd007aa71d4.png)

以前は、こうした問題が発生していたら、サーチコンソールのメッセージに表示されて、分かるようになっていたと思う。しかし、今は、この件に関しては、メッセージに表示されないようだ。だから、最近まで、問題が発生していたことに、気づきませんでした。
非エンジニアのPython忘備録的ブログ


# Pythonメモ

:::note info
pythonの基本的なコード知識
等のメモをここに残します。
:::

## 小文字大文字への変換
```Python:main.py
#各小文字大文字への変換
s = "String"
#全て小文字にする
print(s.lower())
#全て大文字にする
print(s.upper())
```

```:結果
string
SRTING
```

## リストの簡単な考え方のループ例
### 例 以下の入力を番号小さい順に並び替えて出力
※一番最初の入力値は下に出てくる入力値の行数

``` :入力値
3
2 ITO
11 KATO
21 MUTO
```
``` :main.py
#空の配列Aを作成
A = []
#最初の行、すなわちその下にある入力値の行数取得
n = int(input())
#n-1回、以下の処理を繰り返す
for i in range(n):
#配列Aの一番後ろに入力値(行ごと)を追加
    A.append(input().split(" "))

for j in range(n):#n-1回、以下の処理を繰り返す
#もしA配列のj番目の0番目(カウントは0スタート)の要素数が1だったら
    if len(A[j][0]) == 1:
#A配列のj番目の0番目(もしjが0であればここは2)の先頭に0をつける
        A[j][0] = "0" + A[j][0]

#上記を行わずにA.sort()などだけ使うと例えば4,10と並んで欲しくても
#10,4などと左から一桁目の数字を基準に並んでしまうので注意
#A配列の各1番目をキーに昇順に並び替え
A.sort()

#n-1回、以下の処理を繰り返す
for s in range(n):
#もしA配列のs番目の0番目(カウントは0スタート)の0番目の要素が0だったら
    if A[s][0][0] == "0":
#A配列のs番目の0番目(カウントは0スタート)にA配列のs番目の0番目の先頭の0を取り除く
        A[s][0] = A[s][0][1:]

#n-1回、以下の処理を繰り返す
for m in range(n):
#2-1回、以下の処理を繰り返す
    for k in range(2):
#もしA[m][k]のうちのkが1だったら(すなわち文字列の方の値のインデックス番号だったら)
        if k == 1:
#出力して改行
            print(A[m][k])
        else:
#改行せずに空白を入れて横に並べる
            print(A[m][k],end=" ")
```
※勉強していたものが溜まってきてQuittaに
自分で考えた簡単なコードを挙げることにしました。

最後までご閲覧いただきありがとうございます。
【ポートフォリオ作成8日目】ER図の作成

# 概要
7日目の続き。
# ER図の作成
## 1. Draw.io integrationでER図を作成
- VSCodeに拡張機能「Draw.io integration」を導入
- 任意の場所にファイルを作成
- ファイルの拡張子を「.dio」にすると「Draw.io integration」が起動
- ER図を作成

# 参考
- [【VSCode】VSCode上でER図が書ける拡張機能「Draw.io integration」について解説](https://techtechmedia.com/draw-io-integration/?quad_cc)
【Git】初心者が使えると良さげなコマンド集

チームで開発をする上では欠かせないGit。自分自身まだまだ初心者ではありますが、ひとまず最低限は使えるようになってきたので、「これが使えればとりあえずは大丈夫そう」というGitコマンドを紹介します。

# ブランチの一覧表示
```php:ターミナル
    $ git branch
```
*がついているのが今いるブランチです。
```php:ターミナル
    $ git branch
    * develop
      feature
      master
```

# ブランチの切り替え
```php:ターミナル
    $ git checkout
```
「-b ブランチ名」 をつけるとブランチを新規で作成しつつ切り替えができます。
```php:ターミナル
    $ git checkout -b TEST 
      develop
      feature
      master
    * TEST
```

# ブランチの作業を確定させる
```php:ターミナル
    $ git commit
```
-m でコミットメッセージの記述が可能です。
```php:ターミナル
    $ git commit -m '13行目のインデントを修正しました'
```

# ローカルのコミット内容をリモートに反映させる
```php:ターミナル
    $ git push
```
初回push時は、リモートに該当ブランチがないため以下のコマンドが出力されます。
そのまま実行でリモートブランチ作成&pushしてくれます。
```php:ターミナル
    git push --set-upstream origin ブランチ名
```

# リモートにある最新のソースコードを取得する
特に、ブランチを新しく作成するときはやったほうがいいです。
```php:ターミナル
    $ git pull
```

# ブランチにおける編集中のファイルを表示する
コミット済の場合は、nothing to commit, working tree clean等の文言が表示されます。
```php:ターミナル
    $ git status
```

# 変更点を一時退避させる
未コミットの状態でブランチを切り替えると、移動元ブランチの内容が移動先ブランチに自動マージされてしまいます。git stashを使うことで変更点を一旦退避させ、自動マージを防止します。
```php:ターミナル
    $ git stash
```

# 退避した変更点を元に戻す
git stashで退避した変更点を元に戻す(未コミットの状態に戻す)ことができます。
```php:ターミナル
    $ git stash apply
```

# おまけ：エラーメッセージ
git pushしたときに以下のようなメッセージが表示される場合があります。
```php:ターミナル
    Everything up-to-date
```
pushの内容とpush先に差分がない場合、このようなメッセージが出ます。
コミットできているかを確認しましょう。

# おわりに
開発部門で業務をするにあたって最初に？？となったのがGitでした。
Gitだけをゴリゴリ勉強するよりも、「〇〇したい」となったときに調べて学ぶ、くらいの方がいいんじゃないかと思いました。
この記事が参考になると嬉しいです(￣▽￣)
Goでレコードを追加する際にincorrect string value

# はじめに

Goの開発を始めて今回DBでかなり時間を使ってしまったのでまとめます
またGoと書いてありますが根本的な原因はGoにはなかったのに早くに気づいてなかったので無駄に時間を取られました(それは検索してもみつからないわけだ)

# 問題

Go(gorm)でレコードインサートをした際に以下のエラーが発生した

```
incorrect string value
```

名前に日本語を利用していたためエラーが発生していることはわかっていたが`go mysql incorrect string value`としてもそれらしき記事がまったくヒットしなくて困っていた

# 解決方法

これはそもそもGoのエラーではなく`MySQL`のエラーなのでそちらの対応が必要になる

今回はDockerでMySQLのコンテナをたてていたので日本語(utf-8)を使えるようにするため色々調べた

まずイメージをMysql:5.7を利用していたので以下の`my.cnf`を作成

```cnf:my.cnf
[mysqld]
character_set_server=utf8
character_set_filesystem=utf8
collation-server=utf8_general_ci
init-connect='SET NAMES utf8'
init_connect='SET collation_connection = utf8_general_ci'
skip-character-set-client-handshake
```

そしてdocker-compose.ymlで共有する

```yml:docker-compose.yml
  db:
    image: mysql:5.7
    volumes:
      - ./my.cnf:/etc/mysql/conf.d/my.cnf
    env_file:
      - .env
    container_name: db
    ports:
      - 3306:3306
```

これで問題なく日本語のインサートができて、MySQLからの確認もできた

ここでMySQLのイメージが古いことに気づき、MySQL8.0に変更
すると、デフォルトで日本語対応しており、表示の箇所(select * from)などで文字化けする対応をするだけで済みそうだった

最終的には

```yml:docker-compose.yml
  db:
    image: mysql:8.0
    volumes:
      - ./my.cnf:/etc/mysql/conf.d/my.cnf
    env_file:
      - .env
    container_name: db
    ports:
      - 3306:3306
```

```cnf:my.cnf
[client]
default-character-set = utf8
[mysqld]
character-set-server = utf8
```

で落ち着いた

ちなみに私がはまったのが、コンテナの設定を変えても変更が反映されていない(日本語がインサートできない)というので、原因はコンテナのキャッシュが効いていたことだった。コンテナを`docker-compose down -v`で落としてから立てたら動いた

# おわりに

新米Gopherにむけて私の記事がどれも参考になればよいなと思い、これから細かい単位で記事を投稿していきます

# 参考
https://blog.leko.jp/post/how-to-use-redmine-with-docker-in-japanese/
【IT-DIY】GoogleGlassを使って、QRコードをスキャンし、結果をi-Reporter帳票に出力(Part.2)

# 概要

こんにちは。
[前回](https://qiita.com/ohbay/items/102888d9100a90ab1959)は、サンプルPGをインポートして、ちょこっとソースをいじって遊んでみました。
今回は、特定のジェスチャー操作で、撮影している映像をキャプチャし、
QRコード読取後に、"WebAPI"(1)をたたいて、帳票を作成してみます。  
(1) : 厳密には、"ConMas i-Reporter外部連携API"をラップしたWebAPI（社内開発しているものなので、割愛）  

# [Step.1] 特定ジェスチャー操作で、キャプチャする処理を実装

GoogleGlassでは、様々なジェスチャー操作ができるようです。
https://github.com/googlesamples/glass-enterprise-samples/blob/master/GestureLibrarySample/main/src/main/java/com/example/glass/ui/GlassGestureDetector.java

```java
public enum Gesture {
    TAP,
    TAP_AND_HOLD,
    TWO_FINGER_TAP,
    SWIPE_FORWARD,
    TWO_FINGER_SWIPE_FORWARD,
    SWIPE_BACKWARD,
    TWO_FINGER_SWIPE_BACKWARD,
    SWIPE_UP,
    TWO_FINGER_SWIPE_UP,
    SWIPE_DOWN,
    TWO_FINGER_SWIPE_DOWN
}
```

今回は、"SWIPE_FORWARD"(前スワイプ操作) で今映している映像をキャプチャし
base64文字列にして、APIリクエストする処理を追加してみます。  

# [Step.2] QRコードを読み取り後、APIリクエストする処理を記述してみよう！

ここは、前回やったことと同じです（※ JSON形式に差異はありますが）  
今回は、以下のJSON形式をi-Reporter側APIに送信します

```
{
  "qr" : "hogehoge,fugafuga",
  "base64": ["base64データ文字列1", "base64データ文字列2", "base64データ文字列{N}"
}
```

上記JSON形式を、i-ReporterAPIをラップしている社内WebAPIに対し、リクエストし、  
i-Reporterが扱っている帳票を自動作成します。  

# [Step.3] 動作確認

### Google Glassで実際に見ている映像

「i-Reporterで作成した帳票を確認」の画像と若干違うのはご了承ください
※ キャプチャの都合上です(机の上汚い、、、）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2629696/6e3fb94b-28f1-534b-259f-5643a6dba545.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2629696/1e595f76-e93a-b5ad-0eb6-f34373c07086.png)

上記キャプチャで見ている映像中で、"SWIPE_FORWARD(前スワイプ操作）"して、
APIリクエストしてます。  

# [Step.4] i-Reporterで作成した帳票を確認

帳票上の"現場名"は、
以下のQRコード(1)を読み取って、i-Reporterの帳票に埋め込んだものです。
※ "現場名"には、「hello google glass X {パッケージ製品名}」が入っています
※ 社内風景の写真は、プライバシーの観点からぼかし加工済み

(1) : 
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2629696/f7f8d6ee-2eca-64da-77cc-edbd9f2d280e.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2629696/c9a36990-4058-6271-bf19-a58235e3e128.png)

# 今後の予定について

とりあえず、形にすることができました。
あとは、どういう活用できるか、アイディア次第ですね！

こうしたらいいんじゃない？などのアイデアがある方、
こちらの投稿のコメントまで、よろしくお願いします！
◇Windowsのバッチファイルでカレントフォルダ名を取得する

# ◇カレントフォルダ名を取得する

バッチファイルにファイルやフォルダをドラッグアンドドロップして処理する時に、ドロップされたパスの最後のフォルダとなるカレントフォルダを取得します。

バッチファイルではcallで呼び出したルーチンには通常とは別の%1などの特殊変数が使えます。
これを使うことでパスを分解できます。

例えば
`C:\AAA\BBB\CCC\DDD.txt`から`CCC`を取り出します。


```
:: ドロップされたパスからカレントフォルダ名を取得;
:GetCurrenrFolderName
set TargetFolderName=%~dp1
set TargetFolderName=%TargetFolderName:~0,-1%
set TargetPathATTR=%~a1
set TargetPathATTR=%TargetPathATTR:~0,1%
if /i "%TargetPathATTR%" equ "d" if /i "%~n1" neq "" (
  set TargetFolderName=%~dpn1
)
call :GetName "%TargetFolderName%"
goto :EndGetCurrenrFolderName
:GetName
set TargetFolderName=%~n1
exit /b
:EndGetCurrenrFolderName
echo Current FolderName = "%TargetFolderName%"
echo.
```


## ドロップされたパスから種別とカレントフォルダ情報を表示するサンプル

```bat:DropFileIdentification.bat
@echo off


:: 遅延展開 バグの原因になる場合があるので注意;
setlocal enabledelayedexpansion


:: エスケープシーケンスを利用;
for /f "tokens=1,2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do (set ESC=%%b)


echo ◇ドロップされたパスから種別とカレントフォルダ情報を表示します。
echo.


:: ドロップされたパスがドライブかファイルかフォルダか判別する;
set TargetPath=%1
set TargetPathATTR=%~a1
set TargetPathATTR=%TargetPathATTR:~0,1%
if /i "%~n1" equ "" (
  echo "%1" is drive.
)
if /i "%TargetPathATTR%" equ "d" if /i "%~n1" neq "" (
  echo "%1" is folder.
)
if /i "%TargetPathATTR%" neq "d" (
  echo "%1" is file.
)
echo.


:: ドロップされたパスからカレントフォルダ名を取り出す;
:GetCurrenrFolderName
set TargetFolderName=%~dp1
set TargetFolderName=%TargetFolderName:~0,-1%
set TargetPathATTR=%~a1
set TargetPathATTR=%TargetPathATTR:~0,1%
if /i "%TargetPathATTR%" equ "d" if /i "%~n1" neq "" (
  set TargetFolderName=%~dpn1
)
call :GetName "%TargetFolderName%"
goto :EndGetCurrenrFolderName
:GetName
set TargetFolderName=%~n1
exit /b
:EndGetCurrenrFolderName
echo Current FolderName = "%TargetFolderName%"
echo.


:: 終了処理を起動条件により分岐（エクスプローラーから起動されていた場合は選択処理）;
:EndProcess
echo %CMDCMDLINE%|find /i "%~f0">NUL
if "%ERRORLEVEL%" neq "0" (goto :eof)
choice /t 10 /c qa /d q /m "10秒待機します。即閉じる場合はQ、待機はAを押してください。"
if "%ERRORLEVEL%" equ "2" (
  echo %ESC%[1A%ESC%[2K%ESC%[1A
  pause
)
goto :eof
```


# おわりに

他にも「[⧉Windowsのバッチファイルのテクニックをご紹介します][]」にてご紹介させて頂いております。
お時間ありましたら覗いてみてください
お粗末様でした。

https://github.com/Aromatibus/

[⧉Windowsのバッチファイルのテクニックをご紹介します]: https://qiita.com/aromatibus/items/12fa4775f38c9889a686
◇Windowsのバッチファイルでドライブかファイルかフォルダかを判別する

# ◇ドライブかファイルかフォルダかを判別する

バッチファイルにファイルやフォルダをドラッグアンドドロップして処理する時に、ドロップされたものがドライブかフォルダかファイルかを判別します。


```
:: ドロップされたパスがドライブかファイルかフォルダか判別する;
set TargetPath=%1
set TargetPathATTR=%~a1
set TargetPathATTR=%TargetPathATTR:~0,1%
if /i "%~n1" equ "" (
  echo "%1" is drive.
)
if /i "%TargetPathATTR%" equ "d" if /i "%~n1" neq "" (
  echo "%1" is folder.
)
if /i "%TargetPathATTR%" neq "d" (
  echo "%1" is file.
)
echo.
```


## ドロップされたパスから種別とカレントフォルダ情報を表示するサンプル

```bat:DropFileIdentification.bat
@echo off


:: 遅延展開 バグの原因になる場合があるので注意;
setlocal enabledelayedexpansion


:: エスケープシーケンスを利用;
for /f "tokens=1,2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do (set ESC=%%b)


echo ◇ドロップされたパスから種別とカレントフォルダ情報を表示します。
echo.


:: ドロップされたパスがドライブかファイルかフォルダか判別する;
set TargetPath=%1
set TargetPathATTR=%~a1
set TargetPathATTR=%TargetPathATTR:~0,1%
if /i "%~n1" equ "" (
  echo "%1" is drive.
)
if /i "%TargetPathATTR%" equ "d" if /i "%~n1" neq "" (
  echo "%1" is folder.
)
if /i "%TargetPathATTR%" neq "d" (
  echo "%1" is file.
)
echo.


:: ドロップされたパスからカレントフォルダ名を取り出す;
:GetCurrenrFolderName
set TargetFolderName=%~dp1
set TargetFolderName=%TargetFolderName:~0,-1%
set TargetPathATTR=%~a1
set TargetPathATTR=%TargetPathATTR:~0,1%
if /i "%TargetPathATTR%" equ "d" if /i "%~n1" neq "" (
  set TargetFolderName=%~dpn1
)
call :GetName "%TargetFolderName%"
goto :EndGetCurrenrFolderName
:GetName
set TargetFolderName=%~n1
exit /b
:EndGetCurrenrFolderName
echo Current FolderName = "%TargetFolderName%"
echo.


:: 終了処理を起動条件により分岐（エクスプローラーから起動されていた場合は選択処理）;
:EndProcess
echo %CMDCMDLINE%|find /i "%~f0">NUL
if "%ERRORLEVEL%" neq "0" (goto :eof)
choice /t 10 /c qa /d q /m "10秒待機します。即閉じる場合はQ、待機はAを押してください。"
if "%ERRORLEVEL%" equ "2" (
  echo %ESC%[1A%ESC%[2K%ESC%[1A
  pause
)
goto :eof
```


# おわりに

他にも「[⧉Windowsのバッチファイルのテクニックをご紹介します][]」にてご紹介させて頂いております。
お時間ありましたら覗いてみてください
お粗末様でした。

https://github.com/Aromatibus/

[⧉Windowsのバッチファイルのテクニックをご紹介します]: https://qiita.com/aromatibus/items/12fa4775f38c9889a686
Oracle19cをWSLのdockerで動かす(スキーマ作成まで自動化)

# 趣旨

以下参考サイトを参照し、WSL2のdockerでOracle19cのコンテナを起動させたい。
スキーマ・テーブル作成まで自動化したいが、
startup/setupスクリプトがCDBに対して動くので、
PDBに対して動くようにしたい。

# 前提条件
- Windows10
- WSL2
- Ubuntu20.10

# 参考サイト
- https://zenn.dev/msksgm/articles/20211225-oracle-database-19c-docker
- https://github.com/oracle/docker-images/blob/main/OracleDatabase/SingleInstance/README.md
- https://qiita.com/blueskyarea/items/e96ec596819e0530e577

# 事象

- /opt/oracle/scripts/setupに置いたcreate user文が、CDBに対して実行される。（PDBが作られる前に実行される?）
CDBでは、ユーザーを作れない（ORA-65096)
- 以下の通り、startupスクリプトが動くが、エラーになる。（CDBに対してCREATE USERするため [ORA-65096](https://cosol.jp/knowledge/knowledge_post/ora-65096/)発生）

```docker-compose logs -f
myoracledb19     | Executing user defined scripts
myoracledb19     | /opt/oracle/runUserScripts.sh: running /opt/oracle/scripts/setup/01_ot_create_user.sql
myoracledb19     | CREATE USER OT IDENTIFIED BY "oracle"
myoracledb19     |             *
myoracledb19     | ERROR at line 1:
myoracledb19     | ORA-65096: invalid common user or role name
myoracledb19     |
myoracledb19     |
myoracledb19     | GRANT CONNECT, RESOURCE, DBA TO OT
myoracledb19     |                                 *
myoracledb19     | ERROR at line 1:
myoracledb19     | ORA-01917: user or role 'OT' does not exist
myoracledb19     |
myoracledb19     |
myoracledb19     |
myoracledb19     |
myoracledb19     | /opt/oracle/runUserScripts.sh: ignoring /opt/oracle/scripts/setup/02_ot_drop.sql_block
myoracledb19     |
myoracledb19     | /opt/oracle/runUserScripts.sh: ignoring /opt/oracle/scripts/setup/03_ot_schema.sql_block
myoracledb19     |
myoracledb19     | /opt/oracle/runUserScripts.sh: ignoring /opt/oracle/scripts/setup/04_ot_data.sql_block
myoracledb19     |
myoracledb19     | DONE: Executing user defined scripts
myoracledb19     |
myoracledb19     | The Oracle base remains unchanged with value /opt/oracle
myoracledb19     | #########################
myoracledb19     | DATABASE IS READY TO USE!
myoracledb19     | #########################
myoracledb19     | The following output is now a tail of the alert.log:
myoracledb19     | ORCLPDB1(3):ALTER DATABASE DEFAULT TABLESPACE "USERS"
myoracledb19     | ORCLPDB1(3):Completed: ALTER DATABASE DEFAULT TABLESPACE "USERS"
myoracledb19     | 2022-08-19T02:13:23.851527+00:00
myoracledb19     | ALTER SYSTEM SET control_files='/opt/oracle/oradata/ORCLCDB/control01.ctl' SCOPE=SPFILE;
myoracledb19     | 2022-08-19T02:13:23.864042+00:00
myoracledb19     | ALTER SYSTEM SET local_listener='' SCOPE=BOTH;
myoracledb19     |    ALTER PLUGGABLE DATABASE ORCLPDB1 SAVE STATE
myoracledb19     | Completed:    ALTER PLUGGABLE DATABASE ORCLPDB1 SAVE STATE
myoracledb19     |
myoracledb19     | XDB initialized.
```

# docker-compose

```docker-compose.yml
version: '3'
services:
  oracle_server:
    image: oracle/database:19.3.0-ee
    container_name: myoracledb19
    ports:
      - 1521:1521
      - 5500:5500
    volumes:
      - ./oradata:/opt/oracle/oradata
      - ./setup:/opt/oracle/scripts/setup
    environment:
      - ORACLE_PWD=oracle
      - ORACLE_PDB=ORCLPDB1
```

# 解決策
- 実行したいスクリプトの最初に以下を入れる。
```SQL
ALTER SESSION SET CONTAINER=ORCLPDB1;
```
laravel Eloquentモデル作成時にマイグレーションとファクトリーを一緒に作成する

# 概要

- モデル作成時に一回でマイグレーションとファクトリーを作成する方法をまとめる。

# 方法

- 下記コマンドを実行する。

    ```shell
    php artisan make:model -fm モデルクラスの名前
    ```

- オプション`-f`が「モデルと一緒にファクトリーも作成」
- オプション`-m`が「モデルと一緒にマイグレーションも作成」
- その他にもコントローラーやシーダーを作成してくれるオプションもある。

    ```
    $php artisan make:model -h
    Deprecated: PHP Startup: Use of mbstring.internal_encoding is deprecated in Unknown on line 0
    Description:
      Create a new Eloquent model class
    
    Usage:
      make:model [options] [--] <name>
    
    Arguments:
      name                  The name of the class
    
    Options:
      -a, --all             Generate a migration, seeder, factory, policy, and resource controller for the model
      -c, --controller      Create a new controller for the model
      -f, --factory         Create a new factory for the model
          --force           Create the class even if the model already exists
      -m, --migration       Create a new migration file for the model
          --morph-pivot     Indicates if the generated model should be a custom polymorphic intermediate table model
          --policy          Create a new policy for the model
      -s, --seed            Create a new seeder for the model
      -p, --pivot           Indicates if the generated model should be a custom intermediate table model
      -r, --resource        Indicates if the generated controller should be a resource controller
          --api             Indicates if the generated controller should be an API controller
      -R, --requests        Create new form request classes and use them in the resource controller
          --test            Generate an accompanying PHPUnit test for the Model
          --pest            Generate an accompanying Pest test for the Model
      -h, --help            Display help for the given command. When no command is given display help for the list command
      -q, --quiet           Do not output any message
      -V, --version         Display this application version
          --ansi|--no-ansi  Force (or disable --no-ansi) ANSI output
      -n, --no-interaction  Do not ask any interactive question
          --env[=ENV]       The environment the command should run under
      -v|vv|vvv, --verbose  Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
    ```
C# 学習ノート

# クラス
アプリ内の特定の機能を担うかたまり。
ユーザが定義できるデータ型。
文字列や数字すべてのオブジェクトを普遍的に表現、操作できるような雛形のようなもの。
例えば、文字列ならstringというクラスで、数学的機能はMathというクラスで表現する。
あとTaskもクラス。Task型。（タスク型は以下の記事で使用した）
（https://qiita.com/Shi05yu/items/9c2f984f71806bcafa5c）

## 部分クラス（パーシャルクラス）
通常、1つのクラスの中身は同じファイル内で定義しなければならないが、クラスの定義時にpaetialとつけると1つのクラスの内容を別ファイルで定義することができる。

参考サイト：
https://ufcpp.net/study/csharp/oo_class.html#partial

# メソッド
データを操作するための道具。
クラスの動作や処理、振る舞いを表現するもの。（クラスの中にはメソッドが定義されている）
主に、クラスで管理されているデータ(フィールド)の値を操作するためのもの。
Console.WriteLineやConsole.ReadLineはConsoleクラスの静的メソッド(オブジェクトを生成しなくてもクラスから直接呼び出せるメソッドのこと、クラスメソッドとも呼ぶ)である。
クラスとメソッド（手続き）をまとめた考え方をカプセル化という。
関数と似ているが、厳密には異なるものである。(違いについてはまた今度調べる)
フィールド(変数)とメソッドのことを総称してメンバーという。

# 静的メソッド
インスタンス化しなくても使えるメソッド。
static修飾子をつけることで静的メソッドになる。
**Windowsアプリケーションなどのコントロール(UIスレッド？)を操作するメソッドは静的メソッドにすることはできない。
なお、delegate変数は静的メソッドを代入する。(そうでないとエラーとなる)**

# 修飾子
public→すべてのクラスからアクセス可能
private→同じクラス内からのみアクセス可能(既定)
static→静的メンバーを指定

# コンストラクタ
あるインスタンスが生成されたときに（newで生成）実行されるメソッドの種類。
インスタンスが生成されたクラスの名前と同じにしなければいけない。
コンストラクタは暗黙のうちに実行されるため、戻り値は存在しない。
戻り値はつけられないが、引数はつけることができる。

```C#:sample.cs
namespace WpfApp1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        //コンストラクタ
        public MainWindow()
        {
            InitializeComponent();

            //Page1の画面を表示する
            Uri uri = new Uri("/Page1.xaml", UriKind.Relative);
            frame.Source = uri;
        }
    }
}
```

参考サイト：
https://atmarkit.itmedia.co.jp/fdotnet/csharp_abc/csharp_abc_011/csharp_abc01.html


# その他の参考サイト
・クラス、インスタンス、メソッドの関係性についてわかりやすかった
https://www.youtube.com/watch?v=3KtwtbX7P5E

・クラスをオブジェクトとして扱うためにインスタンス化
https://www.fenet.jp/dotnet/column/language/309/#:~:text=%E4%B8%80%E8%88%AC%E7%9A%84%E3%81%A7%E3%81%99%E3%80%82-,C%23%E3%81%A7%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B%E3%81%AB%E3%81%AF%20(%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AE,%E5%AE%9F%E4%BD%93%E5%8C%96%E3%81%95%E3%82%8C%E3%81%BE%E3%81%97%E3%81%9F%E3%80%82