OmniAICreator/Qiita-1.07M huggingface dataset:
STM32G031のArduinoでの液晶,AQM0802Aで表示(STM32G031J6M6)(i2c)

AQM0802Aとは、秋月で売っているi2cの液晶である。
なにがすごいのかと言うと信号線2本でマイコンと接続できる。
8文字2行のキャラクター液晶である。

1.SCLとSDAを接続、プルアップも忘れずに
2.電源の接続
3.下記のソースコードを書き込む
4.コンパイル実行で表示されたら終了
5.おわり

おまけ
古いスイッチサイエンスのソースを使っています。

x PA11,PA12は、いつも間違えるので各自確認のこと

STM32G031を使用した。液晶時計ができました。
STM32G031のArduinoでの時計,DS1307で時刻表示( AQM0802A i2c)(STM32G031J6M6)
https://qiita.com/caa45040/items/fee158b4d04a5139bae0

LPC1114のMbedでの時計,DS1307で時刻表示( AQM0802A i2c)(ハードはichigojam)
https://qiita.com/caa45040/items/5f0e7f0f3ebcae613ec2



```c++


#include <Wire.h>
 
#define vddPin 16    // ArduinoA2
#define gndPin 17    // ArduinoA3
//#define sdaPin 18    // ArduinoA4
//#define sclPin 19    // ArduinoA5

#define sdaPin PA12    // ArduinoA4
#define sclPin PA11    // ArduinoA5


#define I2Cadr 0x3e  // 固定
byte contrast = 35;  // コントラスト(0～63)
 
void setup() {
  pinMode(gndPin, OUTPUT);
  digitalWrite(gndPin, LOW);
  pinMode(vddPin, OUTPUT);
  digitalWrite(vddPin, HIGH);
  delay(500);
  //Wire.begin();
  Wire.begin(sdaPin,sclPin);
  lcd_cmd(0b00111000); // function set
  lcd_cmd(0b00111001); // function set
  lcd_cmd(0b00000100); // EntryModeSet
  lcd_cmd(0b00010100); // interval osc
  lcd_cmd(0b01110000 | (contrast & 0xF)); // contrast Low
  lcd_cmd(0b01011100 | ((contrast >> 4) & 0x3)); // contast High/icon/power
  lcd_cmd(0b01101100); // follower control
  delay(200);
  lcd_cmd(0b00111000); // function set
  lcd_cmd(0b00001100); // Display On
  lcd_cmd(0b00000001); // Clear Display
  delay(2);
}
 
void loop() {
  lcd_setCursor(0, 0);
  lcd_printStr("SWITCH");
  lcd_setCursor(0, 1);
  lcd_printStr("SCIENCE");
  delay(100);
}

// コマンド RSを0
void lcd_cmd(byte x) {
  Wire.beginTransmission(I2Cadr);
  Wire.write(0b00000000); // CO = 0,RS = 0
  Wire.write(x);
  Wire.endTransmission();
}

// データ RSを1
void lcd_contdata(byte x) {
  Wire.write(0b11000000); // CO = 1, RS = 1
  Wire.write(x);
}

//ラストのデータは、COは、0
void lcd_lastdata(byte x) {
  Wire.write(0b01000000); // CO = 0, RS = 1
  Wire.write(x);
}
 
// 文字の表示
void lcd_printStr(const char *s) {
  Wire.beginTransmission(I2Cadr);
  while (*s) {
    if (*(s + 1)) {
      lcd_contdata(*s);
    } else {
      lcd_lastdata(*s);
    }
    s++;
  }
  Wire.endTransmission();
}
 
// 表示位置の指定
void lcd_setCursor(byte x, byte y) {
  lcd_cmd(0x80 | (y * 0x40 + x));
}


```

![i2c_8x2_031_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/f4d4332c-bcb7-79c4-8d00-cf3f09ac37ef.jpeg)

![i2c_g031_p_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/50265a38-98e9-4bea-d06c-28a2c115ab56.jpeg)
M5StackシリーズのAtomic GPSで現在位置をAmbentに表示する

##M5StackシリーズのAtomic GPSで現在位置をAmbentに表示する
![スクリーンショット 2021-02-05 10.26.36_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181687/8b6a77d4-a026-5886-c8ad-a87652a5496e.png)
![スクリーンショット 2021-02-05 9.33.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181687/a8e2b5b9-68bb-b116-5714-4bc5824afc45.png)

https://www.switch-science.com/catalog/6474/
##元ネタ
https://ambidata.io/blog/2017/08/04/gps-2/
##必要なライブラリ
M5Stackの開発環境は公式を見てインストールしてください。

・Ambient
![スクリーンショット 2021-02-05 10.15.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181687/c7f2059a-1ac9-af32-9ea4-64ef4982ade8.png)
・M5Atom
![スクリーンショット 2021-02-05 10.22.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181687/65dc61aa-a8e8-574c-9f79-79d21089298f.png)

・TinyGPS++
http://arduiniana.org/libraries/tinygpsplus/

##ソース

<details>
<summary>M5Atomic_GPS</summary>
<div>

```M5AtomicGPS_Ambient.ino

#include "M5Atom.h"
#include <TinyGPS++.h>
#include "Ambient.h"
unsigned long seconds = 1000L; // !!! SEE THE CAPITAL "L" USED!!!
unsigned long minutes = seconds * 60;
unsigned long hours = minutes * 60; 
unsigned long ambient_refresh_rate = 1 * minutes;

// Ambient Settings
unsigned int channelId = 100;
const char* writeKey = "ライトキー";

// WiFi Settings
const char* ssid = "...ssid...";
const char* password = "...password...";

TinyGPSPlus gps;

WiFiClient client;
Ambient ambient;

void setup()
{
    M5.begin(true,false,true); 
    Serial1.begin(9600,SERIAL_8N1,22,-1);
    Serial.begin(115200);

    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
        delay(100);
        Serial.println(WiFi.localIP());
    }
    void sendInfo2Ambient();
    ambient.begin(channelId, writeKey, &client);
}


    
void loop()
{
  while (Serial1.available() > 0) {
    if (gps.encode(Serial1.read())) {
       if (gps.location.isValid()) {
       ambient.clear(1);
       ambient.clear(2);
       ambient.clear(9);
       ambient.clear(10);
       
       char buf[16];
       char buffer_lat[16];
       char buffer_lng[16];
       dtostrf(gps.location.lat(),10,8,buffer_lat);
       ambient.set(9,buffer_lat);
       Serial.print(buffer_lat);
       Serial.print(":");
       dtostrf(gps.location.lng(),10,8,buffer_lng);
       ambient.set(10,buffer_lng);
       Serial.print(buffer_lng);
       Serial.print(":");
       Serial.print(gps.altitude.meters());   
       Serial.print(":");
       Serial.println(gps.hdop.hdop());
       ambient.set(1,gps.altitude.meters());
       ambient.set(2,gps.hdop.hdop());
       }
    }
 }
  sendInfo2Ambient();
  Serial.println("refresh!");
  delay(ambient_refresh_rate);
  Serial.println("Reload");
}


void sendInfo2Ambient()
{
 if (gps.location.isValid()) {
   ambient.send();
  }
}
```

</div>
</details>
コメントスパムを退けるフォームのワンライナーアイデア

フォームを設置すると、アクセスの少ないページでもわりとコメントスパムの餌食になります。

```HTML
<form method="POST" action="https://somewhere.com/form">
  メールアドレス <input type="email" name="email">
  <button type="submit">送信</button>
</form>
```

[reCAPTCHA](https://www.google.com/recaptcha/about/) を使えば手軽で安心ですが、それすらも面倒くさいときの**ネタ半分なアイデア**です。

```HTML
<form method="POST"
    action="https://localhost"
    data-foo="https://somewhere.com/form"
    onsubmit="if(confirm('「キャンセル」を押してください。スパム対策です。')) { return false; } else { this.action = this.getAttribute('data-foo'); return true; }"
>
  メールアドレス <input type="email" name="email">
  <button type="submit">送信</button>
</form>
```

まず、本来の送信先`action`を`data-foo`などに記述し、`action`は`https://localhost`などのダミーにします。

これでDOMレベルでスクレイピングしてくるボットにはほぼ対策できます。

親切に `https://www.cia.gov/` とかに送らせてもいいかもですね！ (冗談ですが)

次に`onsubmit`で、確認ダイアログを表示し、人間殿には敢えて`キャンセル`を選んでもらいます。

キャンセルが選ばれると、`action`に`data-foo`の値(本来の送信先)を移し、`return true`でフォームの内容を送信します。

実は**「フォームの内容を送信します。よろしいですか？」** と、お決まりのワンクッション挟んでいても、それを突破してくるスパムボットがありました。それで逆にする発想に繋がりました。

認知的負荷が高く、コンバージョン率を落としてしまいますが、ブラウザの挙動を再現するタイプのボットにはこれでさらに対策できます。
VScodeで保存時に任意コマンドを走らせるようにしよう！！

# はじめに
とある事情で、コードを書いたらReactの手動Buildをするというフローを繰り返しているのですが。めちゃくそ発狂したのでCtrl Sをした時に任意コマンドを実行できたらええのになーーーと思ったので解決に至った。

# 結論
VScodeの「Run on Save」という拡張機能を使ってええ感じになった。

# Step1
VScodeで「Run on Save」を検索してEnable
![Screenshot from 2021-02-05 10-32-43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298716/958ba5fe-e6ff-d163-bff1-ac2bce7f3f6e.png)

# Step2
Shift + ctrl + Pというショートカットで、コマンドパレットが開くので、検索欄から、「Open Settings(JSON)」を選択する。

# Step3
settings.jsonをカキカキする。

```json:settings.json
    "emeraldwalk.runonsave": {
        "commands": [
            {
                "match": "./*.py",
                "cmd": "echo python"
            },
            {
                "match": "./example_project/*",
                "cmd": "echo Hello World!"
            }
        ]
    }
```
matchで、対応したいファイルの範囲を設定。
cmdで、実行したいコマンドを入力。

出力先は、アウトプットパネルでRun On Saveを選択すれば出力されるー
![Screenshot from 2021-02-05 10-47-52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298716/09bb0100-9fad-2296-cbb6-9cdbab9173c5.png)

# 終わりに
ナイスなアイディアあったら教えてくださいー
UE4 UATHelper: パッケージ化 (iOS):     Code Signing Error: Provisioning profile "..." doesn't match the entitlements file's value for the get-task-allow entitlement.

##よくわからんエラー

```
UATHelper: パッケージ化 (iOS):     === BUILD TARGET DemoCPP OF PROJECT ... WITH CONFIGURATION Shipping ===
UATHelper: パッケージ化 (iOS):   
UATHelper: パッケージ化 (iOS):     Check dependencies
UATHelper: パッケージ化 (iOS):     Code Signing Error: Provisioning profile "... Ditribution" doesn't match the entitlements file's value for the get-task-allow entitlement.
UATHelper: パッケージ化 (iOS):     Code Signing Error: Code signing is required for product type 'Application' in SDK 'iOS 14.4'
UATHelper: パッケージ化 (iOS):   
UATHelper: パッケージ化 (iOS):     ** BUILD FAILED **
UATHelper: パッケージ化 (iOS):   
UATHelper: パッケージ化 (iOS):   
UATHelper: パッケージ化 (iOS):     The following build commands failed:
UATHelper: パッケージ化 (iOS):       Check dependencies
UATHelper: パッケージ化 (iOS):     (1 failure)
UATHelper: パッケージ化 (iOS):     Executing /Users/ten/UE4/Builds/TEN-DESKTOP/C/Users/Chi__/Documents/Unreal_Projects/EOS/DemoCPP_4.26/Intermediate/Build/IOS/.../Shipping/CleanProject.sh
UATHelper: パッケージ化 (iOS):     ERROR: Unhandled exception: System.Exception: ** BUILD FAILED **
```

###パッケージ化設定→配布用にチェック、ビルドコンフィグレーション[Shipping]で再ビルドしてみよう

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500172/1685e913-bec8-4297-7eae-d81246c09ea5.png)

これで直らなかったらプロビジョンの設定を失敗して居る可能性大なので見直してみてね
対称式と漸化式

# はじめに
問題を解いていてふと気になったので考察．果たして使い道はあるのだろうか．．．
# 本題
長くなっても読むの飽きるので簡単に．

ある二次方程式の2解，$\alpha,\beta$に対して$,a_n=\alpha^n+\beta^n$とおく．このとき，以下が成り立つ．

```math
{
a_{n+2}=(\alpha+\beta)a_{n+1}-\alpha\beta a_n
}
```

いや，待てよと．どんな思考回路でこれが見つけられるのか．当方，高校のときこんなの知らなかった．
# 実験的アプローチ
たとえば$n=3$，すなわち，$a_3=\alpha^3+\beta^3$の値を求めたいとしよう．これはみんな知っているあの公式(?)を使えば一発．

```math
{
\alpha^3+\beta^3=(\alpha+\beta)^3-3\alpha\beta(\alpha+\beta)
}
```
これは高校でも習うはず．では$n=4$のとき，$a_4=\alpha^4+\beta^4$を求めたいとしよう．お？まだいけるか．

```math
{
\alpha^4+\beta^4=(\alpha^2+\beta^2)^2-2(\alpha\beta)^2
}
```

おそらく参考書などはここぐらいまでの値しか求めさせなさそう．$n=5$のときも$a_2$と$a_3$を使えばできなくはない．**ただ，やりたくない．**係数とか考えたくないし，2乗，3乗も嫌．

何とか簡単に・・・**1つ前の式まるまる使っちゃえ！**こうして偶然，邪心から生まれたのがこちら．

```math
{
\alpha^5+\beta^5=(\alpha+\beta)(\alpha^4+\beta^4)-\alpha\beta(\alpha^3+\beta^3)
}
```
あれ，これ4乗でも適応できるんじゃね？と．

```math
{
\alpha^4+\beta^4=(\alpha+\beta)(\alpha^3+\beta^3)-\alpha\beta(\alpha^2+\beta^2)
}
```

**おお！！これなら累乗しなくていいし，計算もめっちゃ楽やん！！**

# まとめ
結局，**実験って大切．**最初から型にはめるんじゃなく，一度自分で探してみる．あがいてみる．教えてる中高生にはその「あがき」とか，足りない気がするなぁ．自分で探して見つけたときの感動は，数学に限らず勉強したな！！っていう達成感になるのに・・・
Python学習 基礎編　~条件分岐 if文とは？~

こちらではPython学習の備忘録と、Ruby、JavaScriptとの比較も含め記載していきたいと思います。
プログラミング初心者や他の言語にも興味、関心をお持ちの方の参考になれば幸いです。

###if文とは？

if文を用いると

①「**もし○○ならば●●を行う**」
②「**もし○○ならば●●を行う、そうでなければ■■を行う**」
③「**もし○○だったら●●を行う、そうでなくもし△△であれば▲▲を行う、いずれでもなければ■■を行う**」

などの条件分岐ができる。

#####真偽値とは？
条件式は、成り立つと「true」、成り立たなければ「false」という真偽値に置き換わる。
真偽値には、「true」と「false」という2つの値しか存在しない。

###Python、Ruby、JavaScriptの各々の書き方は？

###Python

```py:script.py

# ①
if 条件式:
  処理  # 条件式が成り立てば実行される

# ②
if 条件式:
  処理  # 条件がtrueのとき実行
else:
  処理  # 条件がfalseのとき実行

# ③
if 条件式 1:
  処理  # 条件式1がtrueのとき実行
elif 条件式 2:
  処理  # 条件式1がfalseで、条件式2がtrueのとき実行
else:
  処理  # 条件式1&2ともfalseのとき実行
```

###JavaScript


```javascript:script.js

// ①
if (条件式) {
  処理  // 条件式が成り立てば実行される
}

// ②
if (条件式) {
  処理  // 条件がtrueのとき実行
} else {
  処理  // 条件がfalseのとき実行
}

// ③
if (条件式 1) {
  処理  // 条件式1がtrueのとき実行
} else if (条件式 2) {
  処理  // 条件式1がfalseで、条件式2がtrueのとき実行
} else {
  処理  // 条件式1&2ともfalseのとき実行
}
```

###Ruby

```ruby:index.rb
# ①
if 条件式
  処理  # 条件式が成り立てば実行される
end

# ②
if 条件式
  処理  # 条件がtrueのとき実行
else
  処理  # 条件がfalseのとき実行
end

# ③
if 条件式 1
  処理  # 条件式1がtrueのとき実行
elsif 条件式 2
  処理  # 条件式1がfalseで、条件式2がtrueのとき実行
else
  処理  # 条件式1&2ともfalseのとき実行
end
```

**※ 注意すべき点**
条件式は、必要なだけ記述することができるが、if 文の条件式は上から順に評価されていくため、もしどこかの条件式で true になった場合はそれ以降の条件式は評価されない。
例えば「条件式2」で true になる場合であっても、すでに「条件式1」で true になっていた場合は「条件式2」の評価は行われない。

* * *
#### おわりに
初歩的な部分ですが、若干、言語によって記述方法が違うので忘れないように投稿しました。
また、みなさんの参考になれば幸いです。
【Swift】ViewController.swift の名前を変更したい

# どういうことか

プロジェクトを作成すると初めから作られている **ViewController.swift** の名前を変更したい。
ナビゲーターエリア（左側のファイルなどが並んでいる場所）で直接名前を変更したら不整合などが出そうな気がする。

## 変更する

**ViewController.swift** を開く

```swift:ViewController.swift
import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
}
```

ここの `ViewController` の部分を右クリック（っていうのか？？）して **Refactor** から **Rename...** を選択する。
するとこういう画面になる。

![62dbf5c7db342b3283e5d4dbdaeaa582.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413699/0527bee1-e1ef-d4fb-af50-61b228144428.png)

付けたい名前に書き換えて右上の **Rename** をクリック。完。
Xcode9以上からできるみたい。
【encoding Error】python （SyntaxError: Non-ASCII character '\xe3' in file python.py on line 1, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details）

#はじめに
python初心者がぐぐりながら、色々やっていたら初歩的なエラーがでたので忘備録として残しておきます。

#今回出たエラー

SyntaxError: Non-ASCII character '\xe3' in file python.py on line 1, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details
![スクリーンショット 2021-02-05 10.31.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631096/4871c122-8183-c4f2-5884-a0064fd6158e.png)


#私のpython version
$ python -V
Python 2.7.17

#対処方法
こちらのコードを行頭に記述。
$ # -*- coding: utf-8 -*-

python3系をつかっていればおこらない？みたいです。

割と楽に対処できるエラーでよかった
プラグイン機構のドキュメント

# プラグイン拡張

- 命名規約
	- https://github.com/EC-CUBE/sample-payment-plugin/issues/6
- ディレクトリ構成
    - https://github.com/EC-CUBE/sample-payment-plugin#%E6%8E%A8%E5%A5%A8%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E6%A7%8B%E6%88%90
- プラグインのジェネレータ
    - https://github.com/EC-CUBE/sample-payment-plugin#%E3%83%97%E3%83%A9%E3%82%B0%E3%82%A4%E3%83%B3%E3%82%B8%E3%82%A7%E3%83%8D%E3%83%AC%E3%83%BC%E3%82%BF
- プラグインの有効化・無効化
    - https://github.com/EC-CUBE/sample-payment-plugin#%E5%88%A9%E7%94%A8%E4%BE%8B
- プラグインインストーラの作成(PluginManager)
    - なし
- 管理画面の簡易設定画面
    - なし
- 管理画面のメニュー追加
    - https://github.com/EC-CUBE/sample-payment-plugin
- ルーティングの追加
    - https://github.com/EC-CUBE/sample-payment-plugin#%E3%83%AB%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%E3%81%AE%E8%BF%BD%E5%8A%A0
- フォームの拡張
    - https://github.com/EC-CUBE/sample-payment-plugin#formtype%E6%8B%A1%E5%BC%B5
- レポジトリ拡張
    - https://doc4.ec-cube.net/customize_repository
- テーブル・カラム追加する
	- https://github.com/EC-CUBE/sample-payment-plugin#entity%E6%8B%A1%E5%BC%B5
- 画面への出力方法
	- https://github.com/EC-CUBE/sample-payment-plugin#%E3%83%95%E3%83%AD%E3%83%B3%E3%83%88%E7%94%BB%E9%9D%A2%E3%81%B8%E3%81%AE%E3%83%91%E3%83%BC%E3%83%84%E5%9F%8B%E3%82%81%E8%BE%BC%E3%81%BF
- テンプレートの配置
	- なし
- プラグインが生成するデータの配置
	- https://github.com/EC-CUBE/ec-cube/pull/3911
- PurchaseFlow
	- https://doc4.ec-cube.net/customize_service
- StateMachine/WorkFlow
	- https://doc4.ec-cube.net/customize_order_state_machine
- 外部ライブラリの利用
	- なし
- 依存関係のあるプラグイン
	- なし

# Symfony拡張
- Event
   - https://symfony.com/doc/current/event_dispatcher.html

# Doctrine拡張
- Event
   - https://www.doctrine-project.org/projects/doctrine-orm/en/2.8/reference/events.html
- SQLFilter
   - https://www.doctrine-project.org/projects/doctrine-orm/en/2.7/reference/filters.html
Python で C++ の const member functions っぽいことをする - ディスクリプタの使用例

C++ では メンバ関数の宣言に `const` を付加して、あるクラスのメンバ関数がメンバ変数を変更しないことをコンパイラに伝えられます。これは、その関数の呼び出しに副作用がないことを明確にして、意図しない副作用を作りこまないための機構です。この関数は *const member function* と呼ばれます。

---
ここでは、Python プログラマが副作用のないバウンドメソッドを明示する方策を考えます。
*const member function* っぽいことを Python のデコレータで表現できないでしょうか。

(実際のところ、実行時のパフォーマンスを犠牲にして、`@constant` であることを明示する実用性はないかもしれません。ディスクリプタを使ってみたいというモチベーションであることにご留意ください。）

```python:person.py
class Person:
    def __init__(self, name, phone=None):
        self.name = name
        self.phone = phone

    def rename(self, name):
        self.name = name

    @constant
    def has_phone(self):
        return self.phone is not None
```

`rename()` は `Person` のメンバ変数である `name` を書き換えます。一方で `has_phone()` は書き換えません。もし、`rename()` に `@constant` が修飾されていれば、`rename()` の実行時に例外が送出されることを期待します。C++ の *const member functions* はコンパイルエラーになりますが、そこは Python なので、あくまで実行時例外です。（っぽいことをします。）

この `@constant` デコレータ は `__get__()` を実装したディスクリプタです。

```python:constant.py
import functools


class constant:
    def __init__(self, func):
        self.func = func

    def __get__(self, instance, klass=None):
        @functools.wraps(self.func)
        def wrapper(*args, **kwargs):
            before = dict(instance.__dict__)
            self.func.__get__(instance)(*args, **kwargs)
            for k, v in instance.__dict__.items():
                if v != before[k]:
                    print("Warning")  # Error を送出してください

        return wrapper
```

`before = dict(instance.__dict__)` はバウンドメソッド実行時のインスタンスの `__dict__` を保持しています。Python では、インスタンスのメンバ変数が `__dict__` に保持されていることを利用します。（つまり、 `__slots__` を実装するクラス内では、このデコレータを使用できないことに注意してください。）

デコレータ ( `@constant` ) 解釈時（ `constant.__init__()` 実行時）には、ディスクリプタの `func` に格納される関数は、アンバウンドです。したがって、バウンドメソッド実行時に `func` にインスタンスをバウンドする必要があります。

バウンドメソッド実行時は、ディスクリプタの `__get__` が呼び出されます。そのタイミングで、`self.func.__get__(instance)` という処理によって `func` にインスタンスをバウンドした上で、関数を呼び出しています。これは Python のバウンドメソッドは、`__get__` を実装したディスクリプタであることを利用しています。

最後に、バウンドメソッド実行後の `instance.__dict__` と `before` を比較します。
Webpack5でLICENSE.txtを出力させない

# Webpackの出力が少し変更になっていた
※覚書です。
2020年9月にwebpack5のプレリリースが来ていた（2022年11月現在は5.74.0）

すると前と違ったことがあった。
ライセンスを別ファイルに出力するようになった。

コンパイル後のjsがすっきりするし、いいことではあったが案件での対応の際、
txtファイルは納品できない…とのことだったので、今までと同じようにvender.jsなどのコンパイル後のjsにライセンスを含める必要が出てきた。

webpack.config.jsを変更する必要がある。

## 公式に乗ってた
```javascript:webpack.config.js
const TerserPlugin = require('terser-webpack-plugin');
.
.
.

  optimization: {
    minimizer: [new TerserPlugin({
      extractComments: false,
    })],
  },
```

これをwebpack.config.jsに追加。
詳しくは公式を確認。
https://webpack.js.org/plugins/terser-webpack-plugin/#extractcomments

なかなか調べても出てこなかったので、覚書程度に残しておきます。


## 2022年11月9日更新
2022年7月15日に 5.74.0 がリリースされました。
LICENSE.txt に関して特に変更なしでした。
Duet Airを使って余っているPCをサブディスプレイとして使用する

# 目的

- Duet Airというサブスクサービスを利用して余っているPCをサブディスプレイとして利用する方法をまとめる

# 条件

- 下記方法でメインPCとメインPCの映像を表示するPCにDuetのアプリがインストールできていること。
    - []()
- メインPCとメインPCの映像を表示するPCが同じネットワーク（LAN内）上にいる必要がある。
- 自分名義のクレジットカードを持っていること。

# 情報

- 筆者はMacBookPro 2020inchの映像をMacBook Air 2012 11inchに表示する。
- メインPCを「ホストPC」と呼び、メインPCの映像を表示するPCを「サブPC」と呼ぶことにする。
- 同じ方法でWindowsPCの活用もできるはずである。
- Duet Airはサブスクリプションで料金が必要になる。最短で1年契約で2021年2月4日現在$19.99とされており、日本円換算すると2098円である。
- 金額とプランの内容は公式が下記リンクでまとめてくれている。
    - [https://ja.duetdisplay.com/help-center/differences-between-duets-base-app-air-and-pro](https://ja.duetdisplay.com/help-center/differences-between-duets-base-app-air-and-pro)

# 公式のリンク

- [https://ja.duetdisplay.com/air](https://ja.duetdisplay.com/air)

# 方法

1. ホストPCでDuetアプリを起動する。
1. 「デスクトップ」をクリックする。

    ![Duetの設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/99a698df-b983-c84f-3dba-156af2705fc6.png)

1. 「サインイン」をクリックする。

    ![Duetの設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/94fc5374-0404-2c43-55a2-2d3f8c3955dc.png)

1. 「サインアップ」をクリックする。

    ![Duetの設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/961da61b-db87-70c0-5e1b-234613232c25.png)

1. 任意の情報を入力し「続ける」をクリックする。

    ![Duetの設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/13da9f81-c521-954e-5126-3bda3b1bfa76.png)

1. 利用許諾規約が表示されるので内容に目を通し同意するなら「ライセンス条項と規約に同意します」にチェックマークをつけて「同意して実行する」をクリックする。

    ![Duetの設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/bb5e0fa5-0d86-d822-5a48-d354aa90854c.png)

1. 下記の画面が表示されたら先程入力したメールアドレスにメールが送信される。

    ![Duetの設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/bd04410d-5614-b0b9-db7c-758363eea70c.png)

1. 下記のようなメールが届くので「Verify Email」をクリックする。

    ![Duet_Email_Confirmation_-_shun_okawa_gmail_com_-_Gmail.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/7068eb63-7af3-5c08-2ba5-ea168e2b221e.png)

1. duetアプリで「サインイン」をクリックして先程サインアップで入力した情報を入力する。

    ![Duetの設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/cac77188-bd28-52e7-5f72-a3cc4b7a1ddb.png)

1. ログインできるとプロフィール画面が開くので「画面共有が有効です」に必ずチェックを入れる。他のチェックボックスはお好みで付ける。

    ![Duetの設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/b96afb2e-ff73-17eb-80ec-84876122ead1.png)

1. サブPCでもDuetを起動してサインインを行う。
1. メインPCのDuetで「デスクトップ」をクリックする。

    ![Duetの設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/e1f5bf5a-0fe9-db00-df54-30c4c42ae4c1.png)

1. 「1週間のトライアルを開始する」をクリックする。

    ![Duetの設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/cfa572c9-360a-1ff0-635e-d318ce20cc93.png)

1. クレジットカードの情報を入力する。

    ![Duetの設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/aa4e18a5-76d3-b071-a0bc-f62d3f85008b.png)

1. サブPCで接続したい端末を選び「画面を拡張する」をクリックする。

    ![Duetの設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/bb564541-3342-2331-40b6-6076a6e4ef79.png)

1. サブPCにメインPCの画面が表示される。
[Ruby]文字列を1文字ずつ配列として取得(備忘録)


入力で文字列があった場合、それを1文字ずつ配列として取得したい場合の方法
例えば以下のような標準入力があった場合、

```

hello
```
次の記述で配列として取得できます

```ruby
p gets.chomp.split("")
 # => ["h", "e", "l", "l", "o"]
```

split("")で空白のない文字を切り分けます。
chompは改行をなくすために採用しています。

ちなみに、以下の方法でもできるようです。

```ruby
p gets.chomp.chars
 # => ["h", "e", "l", "l", "o"]
```

以上です。
[Python]文字列並び替え問題作成スクリプト

「与えられた文字列を並び替えて、意味のある言葉にする」って問題ありますよね

こんな感じの奴です
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1023362/82979242-d5a7-ab9c-2c20-cb8246b5307b.png)
引用 https://noutore.link/474/

この問題を作れるPythonスクリプト作ってみました

```shuffle_text.py
import random

def shuffle_text(text):
    text_list = [word for word in text]
    result = ""
    while len(text_list) > 0:
        pick_index = random.randrange(0,len(text_list))
        result += text_list.pop(pick_index)
    return result

if __name__ == "__main__":
    text = input("文字列を入力:")
    print(shuffle_text(text))
```

`text_list = [word for word in text]`
Pythonの文字列は変更不可(途中の文字を削除とか出来ない)ので、一旦リストにしています  
  
例えば「こんにちは」というtextを渡した場合、
text_listは[こ,ん,に,ち,は]になります

あとは、これからランダムに一個ずつ抽出してresultとして返すだけ
[Swift] as キャストって何？

```swift:全体
var text: String = "Hello"
var i: Int? = Int(text)

var animal: Animal = Poodle()
animal.breathe()
//animal.chokomakaRun() //←これはエラー。animal変数のデータ型がpoodleではなくてAnimalだから

var poodle = animal as? Poodle //animalをpoodle型にキャスト
poodle?.chokomakaRun()
poodle?.breathe()

class Animal {
    func breathe() {
        print("呼吸する")
    }
}

class Dog: Animal {
    func bark() {
        print("吠える")
    }
}
//AnimalでもあるしDogでもある
class Poodle: Dog {
    func chokomakaRun() {
        print("ちょこまか")
    }
}
```

詳しくみていきます。

Animalクラスが存在し、呼吸する関数があります。
そしてDogクラスはそのAnimalクラスを継承し、bark関数とbreathe関数が使えます。
さらにさらに、Poodleクラスがあり、それはDogクラスを継承し、そのDogクラスはAnimalクラスを継承しているため、
PoodleクラスではchokomakaRun関数とbark関数とbreathe関数が使えます。


```swift

var animal: Animal = Poodle()
animal.breathe()
var poodle = animal as? Poodle //animalをpoodle型にキャスト

poodle?.chokomakaRun()
poodle?.breathe()
//animal.chokomakaRun() //エラーになる理由: animal変数のデータ型がpoodleではなくてAnimalだから

class Animal {
    func breathe() {
        print("呼吸する")
    }
}
```
上記で述べたように、PoodleはAnimalを継承しているのでAnimal型の変数にPoodleのインスタンスを作ることが出来ます。
そのため、poodleインスタンスが入ったanimal関数では、Animal クラスが持っていたbreathe関数を使うことが出来るわけです。

一方で、Animalクラスのanimalで、Poodleクラスが持つchokomakaRun関数を使うことは出来るでしょうか？
結論からいうと、出来ません。
animal変数はAnimal型であり、Animalクラスが持つ関数はbreatheのみだからです。


ではどのようにすればAnimal型のanimal変数が、Poodle型が持つchokomakaRun関数を使えるでしょうか。

ここでキャストが必要になります。ようは型を合わせるわけですね。

```swift
var animal: Animal = Poodle()
animal.breathe()

var poodle = animal as? Poodle //animalをpoodle型にキャスト

poodle?.chokomakaRun()
poodle?.breathe()
```

このようにしてAnimal型のanimal変数をPoodle型に変更することができます。(?をつけているので、オプショナルになります。)

型をこのように変換し、poodleという変数にPoodle型に変更されたanimal変数を入れました。
このpoodle変数ではpoodleクラスで使用できた、chokomakaRun関数とbark関数とbreathe関数が使えるようになりました。

継承の大元、一番抽象的なクラスAnimalから一番具体的なPoodleに型を変えたことで、Poodleの関数が使えるようになった感じです。
MySQL の charset について

よく忘れるので。

これはmysqlクライアント（WEBサーバー側）の話です。
mysqlサーバー（DBサーバー側）の話ではないです。

### 単語について
ステートメント：クエリ(DML)やDDLなどの総称

## クライアントのcharset、サーバーのcharset

- `クライアント`:ステートメント送信、DBサーバーに到達したステートメントの解釈、DBサーバーが返す結果
- `サーバー`：データベースやテーブルを作成する際のデフォルト値。webサーバーからDMLを発行する際には関係なく、DDLを発行する際に考慮するもの。


例えば２台のwebサーバーの文字コードが違う場合、`クライアント`はそれぞれのサーバーに合わせてwebサーバー単位（もしくはセッション単位）で設定する。

一方データベースやテーブルのデフォルト値である`サーバー`は、どのwebサーバーからでも同じ値が指定されておくべきもの。

# ステートメントでの設定確認

```
show variables like "chara%";
```

注：
この確認方法は、そのクライアント（もしくはセッション）における設定値の確認。
クライアントAからと、クライアントBからでは、それぞれの設定に従った結果が返る。

## クライアント
- character_set_client
クライアントがステートメントを送信する際の文字セット。

- character_set_connection
サーバーが、クライアントから送信されたステートメントをこの文字セットに変換する。

- character_set_results
サーバーが、クライアントにクエリー結果を返信するときに使用する文字セット。
これには、カラム値などの結果データと、カラム名やエラーメッセージなどの結果メタデータが含まれます。

## サーバー

- character_set_database
デフォルトデータベースで使用される文字セット。デフォルトデータベースが存在しない場合、変数は character_set_server と同じ値になります。

- character_set_server
データベース作成時にデフォルトで使用される文字コード。


# 設定ファイル my.conf
linuxではmy.conf。windowsではmy.ini

## ファイルの場所の確認方法

```
 mysql --help | grep my.cnf
```

## 設定方法
```
[mysql]

# character_set_client
# character_set_connection
# character_set_results
default-character-set=utf-8

# character_set_database
# character_set_server
character-set-server=utf-8
````

# クエリによる動的な指定方法

クエリで指定することで、セッション単位で指定ができる。

[参照](https://dev.mysql.com/doc/refman/5.6/ja/charset-connection.html)

```
SET NAMES utf8
```

- character_set_client
- character_set_connection
- character_set_results

```
SET CHARACTER SET utf8
```

- character_set_client
- character_set_results
"Out of range value for column 'カラム名' at 行番号" に対処した

開発業者が納品したWebアプリケーションがエラーを吐いていた。
致命的な問題で無かったことから発覚が遅れ、瑕疵担保責任を追及できる期間はとうに過ぎていたので、自分で直したという話。

調査ついでにエラーログの見方を簡単に説明しよう。

# 出力されたエラーメッセージ

```python
_mysql_exceptions.DataError: (1264, "Out of range value for column 'カラム名' at row 1")
```

MySQLdbというPythonのモジュールが投げた例外のようだ。
最初の *1264* は4桁なので、MySQL独自のエラーコードだろう。

## ２つのエラー番号
MySQLのエラー番号には、

1. MySQL独自のエラーコード（4桁）
2. ODBCやANSI SQLで定められたSQLSTATE（5桁）

がある。

SQLSTATEは汎化されているので、MySQLに特化した独自コードの方が詳細に特定できる。
[公式サイト](https://dev.mysql.com/doc/refman/5.6/ja/error-messages-server.html)ですべてのエラーメッセージを確認できるが、特に良く見かけるものを以下に抜粋する。

### Row 行番号 doesn't contain data for all columns
- エラーコード：1261
- SQLSTATE：01000
- 意味：すべてのカラムへのデータを含んでいない

### Row 行番号 was truncated; it contained more data than there were input columns
- エラーコード：1262
- SQLSTATE：01000
- 意味：カラムよりも多いデータを含んでいたので、切り捨てたデータがある

### Column set to default value; NULL supplied to NOT NULL column 'カラム名' at row 行番号
- エラーコード：1263
- SQLSTATE：22004
- 意味：NOT NULL のカラムにデフォルト値の NULL を登録した

### Out of range value for column 'カラム名' at row 行番号
- エラーコード：1264
- SQLSTATE：22003
- 意味：範囲外の値だったので、取り敢えず限界の値で登録した

▶ 今回出力されたエラーメッセージである。

### Data truncated for column 'カラム名' at row 行番号
- エラーコード：1265
- SQLSTATE：01000
- 意味：先頭からみて入れられるところまで登録し、残りは切り捨てた

# つまり…
エラーコード *1264* は、データ型の範囲を超えた値をINSERTしたときに発生するWarningである。直前に実行したSQLのWarningは `SHOW WARNINGS` で確認できる。
データ型の範囲を超えると、そのデータ型の最大値または最小値に調整されて登録されるはずだが、PythonがDataError例外を投げたのでrollbackされたと推測。実際にも登録されていなかった。

```python:スタックトレース例
insert into zzzzz_table values(5,1611728121,0,162,58.2,63.9,1,27.5)

Traceback (most recent call last):
  File "/foo/bar/example.py", line 547, in <module>
    fooList()
  File "/foo/bar/example.py", line 164, in barList
    cursor.execute(qstr)
  File "/usr/lib/python2.7/dist-packages/MySQLdb/cursors.py", line 226, in execute
    self.errorhandler(self, exc, value)
  File "/usr/lib/python2.7/dist-packages/MySQLdb/connections.py", line 36, in defaulterrorhandler
    raise errorvalue
_mysql_exceptions.DataError: (1264, "Out of range value for column 'xxxxx' at row 1")
```

## データ型
対象カラムのデータ型を`DESC`で確認すると`TINYINT`であった。
`TINYINT`の取りうる範囲は次の通り。

- **バイト数**： 1バイト
- **デフォルト桁数**： tinyint(4)
- **符号付き（SIGNED）の範囲**：-128 ～ 127

データ型の後に`UNSIGNED`を付けると符号なしとなり、0～255の範囲になる。
ちなみに tinyint(1) はBoolean型と同じだ。

直前のSQLで127を超える値をINSERTしていたが、運用上ありえない値なのでソースコードを修正した。
TypeScriptでValueObjectの表現を考えてみた

# TL;DR

```typescript
abstract class ValueObject<T> {
  protected constructor(protected readonly val: T) {}

  get(): T {
    return this.val;
  }

  eq(vo: ValueObject<T>): boolean {
    if (this.constructor.name !== vo.constructor.name) return false;
    return this.get() === vo.get()
  }
}

abstract class StringValueObject extends ValueObject<string> {}

class UserName extends StringValueObject {
  static of(_val: string): UserName {
    return new this(_val);
  }
}

class AdminName extends StringValueObject {
  static of(_val: string): UserName {
    return new this(_val);
  }
}

const userName1 = UserName.of('rokumura')
const userName2 = UserName.of('rokumura')
const adminName = AdminName.of('rokumura')

console.log(userName1 == userName2)  // false
console.log(userName1.eq(userName2)) // true
console.log(userName1.eq(adminName)) // false
```

# 不変性

`readonly`にすることで、値の変更を防ぐ。

```typescript
protected constructor(protected readonly val: T) {}
```

`Object.freeze`を使っているサンプルも見かけたが、`readonly`だけでも十分なのでは。

# 等価判定

上記の`eq`では、コントラクタの名前を利用して、クラスが同じであることも条件に加えている。
単純に値が等価であるかだけを比較したければ、下記で十分。

```typescript
eq(vo: ValueObject<T>): boolean {
  return this.get() === vo.get()
}
```

# プリミティブの指定

他のプリミティブを指定することももちろん可能。

```typescript
abstract class NumberValueObject extends ValueObject<number> {}
class Price extends NumberValueObject {
  static of(_val: number): Price {
    return new this(_val)
  }
}
```

# バリデーション

バリデーションは、コンストラクタに仕込んでもいいし、抽象クラスに用意してもいいだろうし、`of`の中に設けてもいいだろうし。

## コンストラクタに仕込んだ場合

```typescript
abstract class NumberValueObject extends ValueObject<number> {
  constructor(val: number) {
    if (val < 0) throw new Error('The value must be more than 0.')
    super(val)
  }
}

class Price extends NumberValueObject {
  static of(_val: number): Price {
    return new this(_val)
  }
}

const price1 = Price.of(100)
const price2 = Price.of(-1) // Error: The value must be more than 0.
```

## 抽象クラスに用意した場合

```typescript
abstract class NumberValueObject extends ValueObject<number> {
  protected static validate(_val: number): void {
    if (_val < 0) throw new Error('The value must be more than 0.')
  }
}

class Price extends NumberValueObject {
  static of(_val: number): Price {
    super.validate(_val)
    return new this(_val)
  }
}

const price1 = Price.of(100)
const price2 = Price.of(-1) // Error: The value must be more than 0.
```

## ofの中に設けた場合

```typescript
abstract class NumberValueObject extends ValueObject<number> {}

class Price extends NumberValueObject {
  static of(_val: number): Price {
    if (_val < 0) throw new Error('The value must be more than 0.')
    return new this(_val)
  }
}

const price1 = Price.of(100)
const price2 = Price.of(-1) // Error: The value must be more than 0.
```

# 最後に

お寿司食べたい🍣

# 参考
* [TypeScript DeepDive：クラス](https://typescript-jp.gitbook.io/deep-dive/future-javascript/classes)
* [TypeScript DeepDive：readonly](https://typescript-jp.gitbook.io/deep-dive/type-system/readonly)
* [TypeScript DeepDive：等価演算子の同一性](https://typescript-jp.gitbook.io/deep-dive/recap/equality)
【PHP】PSRについて

#はじめに
[以前の記事](https://qiita.com/strrr/items/973e212114cdb8d4cf3f)でオートロードについて触れたのですが、その際に`psr-4`という単語を初めて目にし、その理解を後回しにしていたので、今回軽く調べて記事にすることにしました。
知識を整理するための個人的な備忘録です。

#PSRとは
`PSR`とは、`PHP-FIG(PHP Framework Interop Group)`が策定している**PHPコーディング規約**の事で、`PHP Standards Recommendations`の略です。

#PHP Standards Recommendations
[PHP Standards Recommendations](https://www.php-fig.org/psr/)

上記のページに規約が一覧で表示されています。

>[PSRワークフロー付属定款](https://www.php-fig.org/bylaws/psr-workflow/)によれば、羅列された各PSRはステータスを保持しています。提案が参加投票に合格すると、**Draft**としてリストされます。 PSRが **Accepted**とマークされていなければ、変更の対象となります。**Draft**中は大幅に変更される可能性がありますが、**Review**にはわずかな変更しかありません。

###PSR一覧(2021年2月時点)
| NUM | TITLE | STATUS |
|:----------:|:-----------:|:------------:|
|  0  |[Autoloading Standard](https://www.php-fig.org/psr/psr-0/)|Deprecated|
|  1  |[Basic Coding Standard](https://www.php-fig.org/psr/psr-1/)|Accepted|
|  2  |[Coding Style Guide](https://www.php-fig.org/psr/psr-2/)|Deprecated|
|  3  |[Logger Interface](https://www.php-fig.org/psr/psr-3/)|Accepted|
|  4  |[Autoloading Standard](https://www.php-fig.org/psr/psr-4/)|Accepted|
|  5  |[PHPDoc Standard](https://github.com/php-fig/fig-standards/blob/master/proposed/phpdoc.md)|Draft|
|  6  |[Caching Interface](https://www.php-fig.org/psr/psr-6/)|Accepted|
|  7  |[HTTP Message Interface](https://www.php-fig.org/psr/psr-7/)|Accepted|
|  8  |[Huggable Interface](https://github.com/php-fig/fig-standards/tree/master/proposed/psr-8-hug)|Abandoned|
|  9  |[Security Advisories](https://github.com/php-fig/fig-standards/blob/master/proposed/security-disclosure-publication.md)|Abandoned|
| 10 |[Security Reporting Process](https://github.com/php-fig/fig-standards/blob/master/proposed/security-reporting-process.md)|Abandoned|
|  11  |[Container Interface](https://www.php-fig.org/psr/psr-11/)|Accepted|
| 12 |[Extended Coding Style Guide](https://www.php-fig.org/psr/psr-12/)|Accepted|
|  13  |[Hypermedia Links](https://www.php-fig.org/psr/psr-13/)|Accepted|
|  14  |[Event Dispatcher](https://www.php-fig.org/psr/psr-14/)|Accepted|
|  15  |[HTTP Handlers](https://www.php-fig.org/psr/psr-15/)|Accepted|
|  16  |[Simple Cache](https://www.php-fig.org/psr/psr-16/)|Accepted|
|  17  |[HTTP Factories](https://www.php-fig.org/psr/psr-17/)|Accepted|
|  18  |[HTTP Client](https://www.php-fig.org/psr/psr-18/)|Accepted|
| 19 |[PHPDoc tags](https://github.com/php-fig/fig-standards/blob/master/proposed/phpdoc-tags.md)|Draft|



###認証フロー
PSRのワークフローには、以下のステータスがあります。
>**1**.`Pre-Draft` — 参加投票に合格すると`Draft`に進む

>**2**.`Draft` — 準備投票に合格すると`Review`に進む

>**3**.`Review` — 承認投票に合格すると`Accepted`に進む

>**4**.`Accepted` — 正式承認され提案(PSR勧告となる)

上記以外に、2つのステータスがあります。

>**・**`Deprecated` — 承認されたが不要になった提案（通常、新バージョンに変わった提案）

>**・**`Abandoned` — 積極的な議論がなく放棄された提案

#参考
[PSR - Ground Sunlight](http://www.y2sunlight.com/ground/doku.php?id=psr:top)
Gatsby.js 【error "window" is not available during server side rendering.】


Gatsby.jsにて、

```terminal
error "window" is not available during server side rendering.
```
上記のエラー時の対処法になります。

## サーバーサイドレンダリング（SSR）でwindowオブジェクトを取得している為のエラー

```jsx

import React from 'react'

export default () => {
  const loc = window.location.pathname //windowオブジェクト
  return (
    <div>
     <p>{loc}</p>
    </div>
  )
}
```
上記のように、windowオブジェクトを使用しているとbuild時にエラーになります。

## useState, useEffectを使うことで解決

```jsx
import React, { useState, useEffect } from 'react'

export default () => {
  const [loc, setLocationName] = useState('')
  useEffect(() => {
    setLocationName(window.location.pathname)
  }, [])

  return (
    <div>
     <p>{loc}</p>
    </div>
  )
}
```
useState, useEffectを使うことで、クライアントサイドで呼び出すことができるので、
`error "window" is not available during server side rendering.`を解消できました。
【Python3】定期券計算を使って「○年○月○日は何カ月前！」ってのを書いてみた

# 1. 概要
Python3でいわゆる定期券計算とdatetimeを使って、何日前、とか何カ月前みたいなのを出してみた。

![20210205083839_a5b294ec43bb5777c5a19f65eb448791.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92447/39363502-0504-4eea-227e-0549e8147a8c.png)
という事が稀に良く起きるので。あ、手書きで漢字を書く時も稀に良くある。
耄碌したかな…。

# 2. 動作サンプル
[https://paiza.io/projects/_YmaBQlwVecdO9JDagJKvA](https://paiza.io/projects/_YmaBQlwVecdO9JDagJKvA)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92447/9ca83c25-3ed0-68ad-76ce-b88db70f7abb.png)

# 3. ソース
```python
from datetime import datetime

def test(old_datetime):
    today_datetime = datetime.today().replace(hour=0,minute=0,second=0,microsecond=0)
    
    # 日数と週の扱い
    date_diff = (today_datetime - old_datetime).days
    week_diff = date_diff // 7
    
    # 月の扱い
    month_diff = (today_datetime.month - old_datetime.month) + (today_datetime.year - old_datetime.year) * 12
    if today_datetime.day - old_datetime.day < 0:
        month_diff -= 1
    
    # 年の扱い
    years_diff = month_diff // 12
    
    print(f'{old_datetime} は、{years_diff} 年前、{month_diff} カ月前、{week_diff} 週間前、{date_diff} 日前')


print(f'今日は {datetime.today()} です。')
test(datetime(2021, 2, 4))
test(datetime(2021, 2, 3))
test(datetime(2021, 2, 1))
test(datetime(2021, 1, 31))
test(datetime(2020, 12, 4))
test(datetime(2020, 2, 6))
test(datetime(2020, 2, 5))
test(datetime(2020, 2, 4))
```

# 4. 解説
## 4.1. 1日前について
**【昨日】って何？**って話。これは、0時を回ったらという判断にした。
厳密には24時間経過したらってなるけど、感覚としては寝て起きたら、寝る前の時間は昨日じゃん？
って事で、datetimeは`00:00:00.000`で丸めてある。

## 4.2. 1ヵ月前、1年前について
定期券計算の肝なんだけど、`2021/02/01`から見て`2021/01/31`は、`1日前`だけど、`1ヵ月前じゃない`。
`先月の同じ日付のプラス1` が1ヵ月経過していない境界になるわけだ。

| 今日       | 調べる日    | 判定                 |
|------------+------------+----------------------+
| 2021/02/05 | 2021/02/05 | 0年前、0ヵ月前、0日前 |
| 〃         | 2021/02/04 | 0年前、0ヵ月前、1日前 |
| 〃         | 2021/01/06 | 0年前、0ヵ月前、30日前 |
| 〃         | 2021/01/05 | 0年前、1ヵ月前、31日前 |
| 〃         | 2020/02/06 | 0年前、11ヵ月前、365日前 |
| 〃         | 2020/02/05 | 1年前、12ヵ月前、366日前 |

## 4.3. 1週間について
これは単純に日数を7で割った商でいい。

# 5. あとがき
ああ、タイムゾーン入ってないなこれ…まあいいや。
コミュニティでの質問と投稿のアクションでトピックを必須にするにはどうすればよいですか？

面白い質問です。

https://trailblazers.salesforce.com/answers?id=9064S000000DWNK

回答としてはトリガーでトッピックの有無をチェックする。
これしかないみたいです。
誰でもできる遅刻しないための自動入室Tips (MacOS版)

オンラインでの授業や仕事が増えてきました。
ギリギリまで寝てていいオンライン。たまにギリギリの時や遅刻する時があると思います。そんなあなたも自動入室のシステムを構築して遅刻のない紳士淑女な人間になりましょう。
__※部屋のURLが固定されている場合のTipsです。__
#まず
今回使用するアプリは以下の通り。コーディングは必要ありません。

- __カレンダー(Macデフォルト)__
- __Automator__

#Automatorでアプリを作成する
Automatorでアプリケーション(カレンダーアラームでもOK)を選択。
![名称未設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1082995/29f223da-0033-2418-fac6-81930b1b7125.png)
次に、①ライブラリの__インターネット__を選択 > ②__指定されたURLを取得__を選択 > ③のアドレスに__入室したいURL__を入力。
![名称未設定（アプリケーション）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1082995/f1d6b9ef-16a6-220e-949a-6d1e61009605.png)
そして、④同じインターネットのライブラリから__Webページを表示__を選択。
これでAutomatorの工程は終わりです。ちゃんと入室できるか右上の実行を押して試してみましょう。

問題なく実行できたら、cmd+sで保存してアプリケーションを作成します。保存場所はどこでも構いません。
![保存.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1082995/b6a9d14c-8751-7d49-941e-2c7e5174869d.png)

#カレンダーで予定を作成する
あとは簡単。好きなところに予定を立てます。
次に、__通知__ > __カスタム__ > __ファイルを開く__ > __その他__ > __Finderで先ほど作ったアプリ__を選択。
その下の項目で、通知したい時間を設定できます。__イベントの開始時刻__や__分前__,__分後__ が作りやすいと思います。お好みで設定してください。
![カレンダー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1082995/34885ef4-5728-6e30-a32c-d04b33930cbb.png)
これで完成です。
#糸冬
さあこれであなたも時間に余裕がある紳士淑女の仲間入りです！お疲れ様でした。
セキュリティの観点からGoogleなどのアカウントに__サインイン__していないと入れない部屋もあります。もしそうであれば、__サインイン済みのクライアントを立ち上げて__おきましょう。
そうでないとせっかくのゆったりした時間が後悔に変わるでしょう...
Data Loader Mac Big Sur インストールエラー（再燃かな）

解決したと思っていましたが、インストールできないみたいです。
https://trailblazers.salesforce.com/answers?id=9064S000000DZDt

回避策
ターミナルファイルとフォルダへのアクセスを許可する必要があります。[システム]-> [セキュリティとプライバシー]-> [プライバシー]タブ-> [ファイルとフォルダーの選択]-> [ターミナル]まで下にスクロール->インストールファイルが配置されているフォルダーを確認します。
ボタンを押すことでページが追加される実装をする

## できるもの
![画面収録-2021-02-04-23.35.31 (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549093/46fee9be-3ac2-bda5-be48-8a86fdc46c20.gif)

画面下部に配置されたボタンを押すとページが追加され、それまでできなかったスクロールができるようになります。動画では追加されたページに遷移するようにしていますが、その処理についてはこの記事では書きません。

## ページとなるViewControllerを作成する

表示されるだけなので、大したことはしていません。

```Swift
import UIKit
import SnapKit
class PageInnerViewController: UIViewController {

    var pageIndex = 0
    let numberLabel = UILabel()
    override func viewDidLoad() {
        super.viewDidLoad()
        setupNumberLabel()
    }
    
    func setupNumberLabel() {
        numberLabel.text = pageIndex.description
        view.addSubview(numberLabel)
        let size = numberLabel.sizeThatFits(CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude))
        numberLabel.snp.makeConstraints {
            $0.center.equalToSuperview()
            $0.size.equalTo(size)
        }
        let backGroundColor: Array<UIColor> = [.red, .blue, .green, .white, .cyan, .purple, .yellow, .gray]
        view.backgroundColor = backGroundColor.randomElement()
    }
}
```
## UIPageViewControllerを貼り付けるVCを作成する
### [表示されるVC型]の配列をつくる

```Swift
var viewControllers: Array<PageInnerViewController> = [PageInnerViewController()]
```

初期値は[]ではなく、一つ入れています。これはUIPageViewControllerのイニシャライザのためにはじめに表示されるVCを用意しておくためです。
### VCを作成し、配列に追加する関数を作成する

インスタンス化したものを先ほど作成した`viewControllers`にappendします。さらにその後DataSourceをリセットします。
この一旦nilを入れselfをいれる処理がない場合、一つ前のページに戻らないと次のページにいけないといったバグが起こってしまいます。

```swift
@objc func makeVC(){
        let vc = PageInnerViewController()
        viewControllers.append(vc)
        if let pageViewController = pageViewController {
            pageViewController.dataSource = nil
            pageViewController.dataSource = self
        }
    }
```
Angularの主要な要素

# Angularの主要な要素

-   NgModule
-   Template
-   Component
-   Service

# NgModule

- Component, Serviceを持つ
- NgModule使用時に遅延ロードされる
  - Root Moduleのみアプリ開始時にロード

- 下記メタデータを持つ
  - declarations: 保有するcomponent
  - exports: 公開するcomponent
  - imports: importするNgModule
  - bootstrap（Root Moduleのみ）: Root Component
    - Root Moduleをbootstrapすることでアプリを起動する


# Component

- プロパティとメソッドを通してViewを制御する
- 下記メタデータを持つ
  - selector: 使用するcss
  - templateUrl: Viewを共に構成するtemplate
  - providers: 使用するservice

# Template

- Componentと共にViewを構成するhtml
- Angular特有のsyntax（attribute directiveと呼ぶ）も使用可能
  - 例：ngForで反復表示
  - [自作も可能](https://angular.jp/guide/attribute-directives#building-an-attribute-directive)

# Service

- データに依存しないLogic部分
- @Injectableデコレータを使用
  - どのコンポでもserviceを使用可能にしたい場合は`providedIn: 'root'`
  - 特定のNgModuleをimportした場合のみserviceを利用可能にしたい場合は、そのNgModuleをimportした上で`providedIn: {NgModule名}`

# Routing

-   画面遷移を扱う
-   @angular/routerの下記を用いる
    -   Routes: linkとcomponentを紐付け
    -   RouterModule: これをimportしたNgModuleにRoutesを紐付け
    -   RouterOutlet: linkと紐づくcomponentを表示
    -   RouterLink: linkを貼る
-   Best Practice：AppModuleにimportするRouterModule（一般にAppRoutingModuleと命名）を作成
    - AppModuleにimportすることで全てのNgModuleでRoutesが使用可能になる
    - AppRoutingModuleで画面遷移を一括管理できる
    - 全てのtemplateにおいてrouter-outletと書くだけで適切な画面が表示されるようになる
[GCP] Professional Cloud Architect資格に合格したときの学習方法

2020年の12月にGCPのProfessional Cloud Architect資格に合格しましたので、少しでも参考になればと勉強方法を共有いたします。
Professional Cloud Architect資格はGCPの上位資格でアーキテクト向けの資格になります。

# 前提知識・条件

- 日常業務でGCPを使っているが、GCE, GCS, IAM, AI Platformあたりをメインで使用。
- それ以外のサービスは必要に応じて触ったことがある程度
- Associate Cloud Engineer資格は合格済み
- Associate Cloud Engineer試験での知識も役立つので、自信ない方はAssociate Cloud Engineerから受験するのがおすすめです。

# 勉強方法

期間としては11/21~12/5の2週間ほど。

- [Professional Cloud Architect](https://cloud.google.com/certification/cloud-architect?hl=ja)の公式ページで試験概要を把握する
- [試験ガイド](https://cloud.google.com/certification/guides/professional-cloud-architect?hl=ja)で試験範囲で要求される知識を確認する
- [公式の模擬試験](https://cloud.google.com/certification/sample-questions/cloud-architect?hl=ja)をやって、どれくらい解くことができるかを最初に確認する
- [ケーススタディのサンプル](https://cloud.google.com/certification/guides/professional-cloud-architect?hl=ja)を読んで求められるシステムの要件を把握しておく。
    - 3つの会社のサンプルがあるが、本番試験では3つともまんべんなく質問が出てきた。
- Coursera
    - [Cloud Architecture with Google Cloud Professional Certificate](https://www.coursera.org/professional-certificates/gcp-cloud-architect)を受講した。
    - 自分は動画を英語字幕で視聴。動画見るのが結構時間かかるので、1.25倍速くらいで視聴。（時間節約したい方はおすすめ）
    - コース終了のため、QwickLabの手を動かす課題があるので、手を動かして理解できる
    - 7つ目のコースの[Preparing for the Google Cloud Professional Cloud Architect Exam](https://www.coursera.org/learn/preparing-cloud-professional-cloud-architect-exam)は実際の試験の問題に近いものが出るので、解答を読んで解き直しておく。
- Udemyの[Google Certified Professional Cloud Architect Practice Tests](https://www.udemy.com/course/gcp-pca-practice-tests-latest/)の講座を受講した。
    - 本番の試験に即した問題が豊富。この講座の問題そのまま・近いものが結構出てきました。
    - 50問x2, 10問x1, 50問（ケーススタディ問題）でかなり問題慣れることができるのでおすすめ。
    - 英語なので、実際の本番試験では日本語文なのでそのあたりは注意。
- 再度、[公式の模擬試験](https://cloud.google.com/certification/practice-exam/cloud-engineer?hl=ja)をやってみてどれくらい解くことができるか確認する
    - 自分は9割りほど解けたので、これで本番試験を受験しようと決めました。

# 本番試験当日

- 試験はオンサイト監視（試験会場に行く）と遠隔監視（リモート受験）の2つが選べたので、私は遠隔監視で自宅から受験しました。
- 遠隔監視では、チャットで試験官の人と英語のやり取りをしながら部屋や机の状況が問題ないかカメラで映して見せる必要があります。
    - 机の上には、紙やペンなどPC以外何もない状態にする必要あり
    - 身分証明書をカメラで試験官に見せる（自分はパスポートを見せた）
- 遠隔監視は、わざわざ会場まで行く必要がなく楽だったのでおすすめです。


本番試験では、感触的に9割以上の問題は解けていたと思います。

以下、本番試験の問題からしっかり勉強していたほうが良いと思われるものです。

- Managed instance group & Load Blancer
    - [マネージド インスタンス グループの作成](https://cloud.google.com/compute/docs/instance-groups/creating-groups-of-managed-instances?hl=ja)
- ストレージの特性の違い、どういった要件の時に使用されるか
- GKE
    - クラスタのデプロイ方法
    - ロールバックの仕方など
- IAM、具体的な権限名とどういった要件の時にどの権限を使用するべきか
- ハイブリットネットワーク接続
    - [ネットワーク接続](https://cloud.google.com/network-connectivity/docs?hl=ja)
- 適切なセキュリティの設計・設定方法
    - 組織、フォルダ、プロジェクトの構成方法
    - GCSのセキュリティ設定など
    - ファイアウォールの設定方法
- オンプレミス環境からのデータ移行の方法
    - gsutil or Transfer Applianceかなど
- ケーススタディ問題のビジネス要件・技術要件を理解しておく
    - 3つのケーススタディごとに、どのGPCのサービスを組み合わせるのが適切なアーキテクチャか試験前に理解しておく

ちなみに、合格かどうかは終わった後にすぐに表示されるのでわかるようになっています。

![pca-image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156927/e6b5f153-d9af-1607-2571-f5a91102e31e.png)
js ランダム部分配列 / 文字列を文字単位でユニーク

## ランダムに部分的に配列を取ってくる

[フィッシャー–イェーツのシャッフル](https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A3%E3%83%83%E3%82%B7%E3%83%A3%E3%83%BC%E2%80%93%E3%82%A4%E3%82%A7%E3%83%BC%E3%83%84%E3%81%AE%E3%82%B7%E3%83%A3%E3%83%83%E3%83%95%E3%83%AB#cite_note-nist-5)

```javascript:配列から無作為に要素を取ってくる_$O(n^2)$　
// fullArrから無作為に重複しないnum個選択したサブセットを返す。
// numをfullArr.lengthにすれば順番をランダムにすることもできる。
// [a,b,c,d] => [c,b]や[d,a]など (num=2のとき)
function randomArray(fullArr, num){
 const seq = [...Array(fullArr.length).keys()] // 0からn-1の連番
 const arr = []
 for(let i=0; i < num; i++){
   const iSeq = Math.floor(Math.random() * seq.length)
   arr.push(fullArr[seq[iSeq]])
   seq.splice(iSeq, 1) // sequenseからは削除
 }
 return arr
}
```

↓追記。@nagtkk様よりご指摘いただいた方法。上記は単純実装であり、改良すると計算量が減るとのこと。

```javascript:配列から無作為に要素を取ってくる_$O(n)$
function randomArray(fullArr, num) {
    const arr = fullArr.slice();

    for (let i = 0; i < num; i++) {
        // i から 最後までの間から 1 つ選び j とする
        const j = i + Math.floor(Math.random() * (arr.length - i));
        const tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }
    arr.length = num; // 切り詰める
    return arr;
};
```

## 文字列をユニークな配列に
`文字列.match(/./g)`は文字列を1文字ずつの配列にする。各一文字にマッチするので。
また、Setは(各要素が各々1つの値を持つ？)集合なので重複は削除される。
文字の種類が多い、日本語などで使えそうな関数。

```javascript:文字列を重複のない1文字ずつの配列にする
// "the str" => [t,h,e, ,s,r]
function uniqueChars(str){
  return [...new Set(str.match(/./g))]
}
```

この関数についても@nagtkk様にご指摘いただき、

>Set は、配列でなくとも Iterable (イテレータが取得可能)なら受け取ることができ、文字列はIterable なのでそのまま突っ込めます。
>文字列にインデックスアクセスした場合と異なり、サロゲートペア等考えなくてよいです。文字列からイテレータを取得した場合は、Unicode コードポイント単位で分かれてくれます。

とのこと。つまり`[...new Set(str)]`で済んでしまうので、関数化しないという選択肢もある。
Gitとは何か？　簡単に全体像理解できる

<h2>今回の内容</h2>

今回は、Gitは何のために使われるかを書きます

<h2>結論：</h2>
Gitは、ファイルのバージョンを管理するためのもの

バージョン管理するを聞いてもピンとこないかもしれません。

簡単に言うと…
ゲームのセーブ機能の様なものです！

しかし、ゲーム機能と違うところがある！
それは、セーブした地点にいつでも戻れると言うことです！

<h2>具体例</h2>
ファイルの新規作成・削除・編集がひと通り終わりセーブがしたくなった際にGitを使いセーブ(バージョン管理)をします。

これにより、いつでもそのセーブ地点に戻ることができます。

<h2>ファイルをバージョン管理するメリット</h2>

<ul>
    <li>どれが最新ファイルかが一目でわかる</li>
    <li>変更したファイルの状態の記録・確認</li>
    <li>以前のファイルの状態に戻すことができる</li>
    <li>複数人での作業の際に変更したものを気づかず他人が変更した場合、その部分に警告を出してくれる</li>
</ul>

<h2>まとめ</h2>
この様なメリットがあるので、個人開発・共同開発の際に使われます！

私も個人開発・共同開発の際は、いつも使っております！
PowerShellの新しいクロスプラットフォームを試してみる

PowerShellを起動してみたらこんな文言が出た。

```
新しいクロスプラットフォームの PowerShell をお試しください https://aka.ms/pscore6
```
ということで、新しいやつというのを落としてみる。

gitHubのリリースページに案内されるのでそこからインストーラーをダウンロード。
[リリースページ](https://github.com/PowerShell/PowerShell/releases)

インストールするとスタートメニューに追加される。

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1026740/4dc973d7-e42f-822f-9b8d-0bdd339ae4f4.png)|
|:--|

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1026740/3fbe0334-0dac-4289-0786-df0dfd1b1f82.png)

見た目はだいぶ黒い。
PowerShellのバージョンを確認する

PowerShellを起動したところ、新しいプラットフォームを確認してみてください。と出たので自分のバージョンがいくつか気になり調べてみました。

```
>$PSVersionTable
```

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1026740/d0b9ed9b-f1d7-1a76-d4b6-f5be65a13146.png)|
|:--|

$PSVersionTable で確認できるようです。最新だとv7ぐらいなのでだいぶ古そうですね。