OmniAICreator/Qiita-1.07M huggingface dataset:
Occipital社のCanvasについて調べてみた

ほぼ公式の翻訳と関連記事の引用になります。
CanvasのすごさやLidarの可能性は感じ取ってもらえるかなと思います。

## Canvasとは 

[公式サイト](https://canvas.io/)や[動画](https://www.youtube.com/watch?v=XA7FMoNAK9M)がわかりやすいのでそちらを見てください。あとは実際に建築デザイナーの方が使われたそうなのでその方の声を引用。

https://ameblo.jp/chicago-japan-architect/entry-12623747855.html

> この作業を自分でやると約4時間はかかります。そして現場に行く時間も加えると、丸１日では終わらない仕事内容が3分程度で完了しています。

## 出力形式について

| 出力オプション | 説明 |
| ---- | ---- |
| On-Device Scan | 即時出力/無料/3Dメッシュ/.OBJファイル/距離の測定が可能 |
| Reprocessed Scan | アップロード15~30分/スキャンごとに3ドル/.OBJファイル/CanvasBusinessメンバーシップに無料 |
| About Scan To CAD |  TD  |

### Scan To CADの対応アプリ

| アプリケーション | 拡張子 |
| ---- | ---- |
| SketchUp | .skp, .dwg, .dae |
| Revit | .rvt, .dwg, .ifc  |
| Chief Architect | .plan, .dwg, .dae |
| 2020 Design Live | .kit, .dwg, .dae |

## Auto Scan To CAD

Scan To CADは、お客様の3Dスキャンデータを約2営業日以内に、編集可能でデザインに適したプロ仕様のCADファイルに加工する半自動サービスです。

家具やその他の移動可能なアイテムは含まれません。Scan To CADでは、お客様に空間の真っ白なキャンバスを提供することを目的としています。

100sqft ≒ 9.29㎡ ≒ 15$ ≒ 1500円
10平米の場合、最低20$からなので2,000円
20平米の場合、3,000円くらいかと思われます。

## Canvas 3D Web Viewer

Canvas アプリでクラウドにアップロードすると、注文の種類にかかわらず、Web Viewerでスキャン画像を見ることができます。

任意の角度から空間を眺めたり 任意の角度から見たり、任意の2点を測定したりすることができます。実際には 実際には、ビューワを使ってポイントを計測する方が、アプリ内で計測するよりも簡単で正確だと感じるかもしれません。
マウスを使って測定できるので、アプリ内よりもビューワを使って測定した方が マウスを使うことができるからです。

https://canvas.io/viewer/7qMDyJmv

## FAQ

### 人が手作業してるの？

Scan To CADは、自動化されたコンピュータ・ビジョン技術と人間のオペレーターの両方を含む半自動のパイプラインです。ほとんどの作業はソフトウェアによって行われ、空間を再現してCADジオメトリを生成します。そして、高度な訓練を受けた人間のオペレーターが、専用のツールを使ってプロセスを監督し、お客様が選択した出力フォーマットに合わせて、デザインに適したプロ仕様のファイルを返します。すべてのScan To CADの注文は、当社の専門チームによって処理されます。専門チームは、厳重に管理された状態で、注文処理の期間と目的のためだけにデータにアクセスすることができます。

## VR Roomを作成するその他の方法

### Blenderで作成する

架空の部屋やモデルルームを作るのであればネットでも情報の多いBlenderが良さそうです。実際の部屋をわざわざBlenderで作る必要はCanvasの登場によってなくなったのではないでしょうか。

https://www.pentacreation.com/blog/2020/02/200201.html

### Matterportを使う

不動産VRといえば[Matterport](https://matterport.com/ja)。C向けの製品だと他に競合が見当たらない。

#### MatterportのViewer
Webで見るとかなりのクオリティなんですが、推奨されいてるOculus Questで見るとすごく酔いました。まだまだ現地で得られる情報との差は大きいなと感じましたが、全然イメージと違った・・っていうようなこ体験はなくなると思います。

https://www.homes.co.jp/iezukuri/contents/3dmodelhouse/1/#anchor_showcase

### NavVisを使う

大きめの室内であれば[NavVis](https://www.navvis.kke.co.jp/)がいいのではないかと思います。Canvasを使ってみて思ったのがちゃんとスキャンできたかがよく分からないんですよね。結果同じところを二度塗りするようなことがあり、意外と大変です。（おそくらMatterportの製品もそんな感じだと思う）

NavVisなら背負って歩くだけなので、撮影者の負担はかなり少なそうです。
WPA2-PSKって何者？

#WPA2-PSKとは？
WPA(Wi-Fi Protected Access)は、無線LANのデータ暗号化方式のひとつ。

安全に配慮が必要な無線LANに対して、セキュリティの高い
暗号化方式を使おうと辿り着いたのがこの方法らしい。。

##そもそもなんで無線LANはリスクがあるの？
このご時世、喫茶店やホテル・駅などあらゆるとこに存在する無線LAN。
何が危険なのか見ていきましょう。

・不正アクセス
⇨たまに耳に入るやつですね。
　　情報が盗まれてしまうなど。企業の無線LANに被害があった日には。。

・通信内容の不正取得
⇨通信の内容が見られてしまうケースですね。
　　有線LANにはないリスク。。

##WPA2-PSKだと何がいいの？
無線LANのリスクは分かりましたが、中でもWPA２-PSKが推奨されるのは何故でしょうか？
現時点では最も安全な方式と言われているそうです。

詳しく見てみましょう。。

###①PSK
PSKとはPre-Shared Keyの略称
PSKは8文字以上63文字以下の複雑な構造

どうやらこれは事前に共有するキーのようですね。
8~63文字となんとも強そうな構造。

このPSKを使ってより安全に接続してるんですね！

###②AES
さらにWPA2-PSKでは、AESという強力な暗号化技術も採用されているとか。
AESはAdvanced Encryption Standardの略称で、
Wi-Fiも認定しているほどの強力な暗号化を行うのが特徴とのこと。

したがって、WPA2-PSKは総合的に見ても非常に安全性が高いといえるのでは。。

## WPA2-PSKは無線LANの暗号化方式！
情報処理試験でこの単語を見かけたら、
・暗号化方式
・セキュリティが強い
・AESを使用

されてるんだな、と覚えていただければ
解くことができるかと思います。

初めての投稿なので少し文章が安直かもしれませんが、
お役に立てたら幸いです。
SQLのキーにはどのデータタイプが良いのか

# プライマリーキーのデータタイプはDBにどう影響するのか
ここで考えるべきことは大きくわけ二つ
1. ___サーチコスト___
2. ___データタイプのサイズ___


## サーチコスト
サーチコストとは文字通りサーチする際にかかるコストのことです．
例えばこのようなランダムにジェネレイトされたアレーがあるとします．

~~~java
int[] a = int[10]
for(int i = 0; i < a.length; i++){
    a[i] = rand();
}
~~~

ここでaの中から最大の値をサーチする時，ここでのサーチコストは全ての値を一つ一つ調べなくてはいけないのでO(n)となります．
*nはアレーの長さ

ただ実際のDBはB+treeやHashMapまたそれにHash-based indexes 併用しているのでサーチ自体にかかるコストはO(1)つまりコンスタントな時間で処理することが可能です．本当はこのデータストラクチャーを作るコストも考えるべきなのですが今回は単純にサーチコストに絞って話していきましょう．

ではキーを探すコストがコンスタントであるのになぜキーのデータタイプがサーチコストに影響するのでしょうか．

ここは2つの点にフォーカスしてみましょう．

#### 1. タイムコンプレキシティ
これは簡単にいうとどれだけの時間がかかるかということです．

int と Stringはどちらの方がキーとして適しているのか．単純に時間だけで比べてみましょう．

~~~java
int a = 1;
int b = 2;
~~~

ここで `a==b`　とコールしたとしましょう．aとbはまずデータタイプが一致しています．これをリターンする際のオペレーションは全てのビットをXORゲートに通したのちNOTゲートに通し全てのビットから出たワイヤーをANDゲートで処理するという形になるので，intは4byte(32bit)と決まったサイズなのでここでのタイムコンプレキシティはO(1)となります．

ではこれがStringだった場合はどうでしょうか．

~~~java
String a = "1";
String b = "2";
~~~
ここで `a.equals(b)`　をコールしたとしましょう．aとbはまずデータタイプが両方Stringで一致しています．ストリングはオブジェクトでありcharのアレーなので，一文字一文字先程のゲート処理を行なったのち全てが一致するかを調べることになるため，ここでのタイムコンプレキシティはO(n)となります．

つまり単純にタイムコンプレキシティで比較した場合intの方が優れているといえます．

#### 2. スペースコンプレキシティ
これはどれだけのスペースを使うかということです．ここでのスペースはメモリー内のスペースと思っていただいて結構です．

ではintとbig int(他の言語ではlongという名の方が多い）を比べてみましょう．

intとbig intではタイムコンプレキシティは同じです．この二つの大きな違いはサイズです．

intは4byte(32bit)に対しbig intは8byte(64bit)あります．一見2倍だけの違いのように見えますが，実際は莫大な違いがあります．intのmaxは2ˆ32 ˜= 40億なのに対しbig intのmaxは2ˆ64 ˜= 2000京となります．

もちろんbig intを選べばオバーフローする可能性は減らせますが，その分倍のスペースを使うのでどれくらいの数のデータが保存させるのかをあらかじめ予想し選ぶことが必要です．

## データタイプのサイズ

先述した通り，それぞれのデータタイプには与えられたサイズがあり，DBの使い方によって適したサイズのキーを選ぶことが大切になってきます．

いくつか例をあげておきます．
-char: 1 byte
-int: 4 byte
-big int: 8 byte
-varchar(max): 65,535 byte

他にも色々ありますし，もちろんvarcharのサイズを自分で指定することも可能です．

一番ここで恐るべきことはオバーフローなので，実際に予想されるサイズより少し大きいものを選ぶことが安全策かと思います．

## まとめ
どのデータタイプがキーに適しているかというのは一概にはいえません．多くの場合intかbig intが使われることが多いですが，実際に自身のDBに適しているのはなんなのか考えてみると良いかと思います．

またこれはSQLのDBに限った話ではなく，どの言語においてもどのデータタイプが適しているのかタイム/スペースコンプレキシティをベースに考える癖をつけることは大切なことです．
UITableViewCellがdeinitされるタイミング


## 検証

以下のようなコードでUITableViewCellのカスタムセルを作成し、
UITableViewのインスタンスメソッドである
・[register(_:forCellReuseIdentifier:)](https://developer.apple.com/documentation/uikit/uitableview/1614937-register)
・[dequeueReusableCell(withIdentifier:)](https://developer.apple.com/documentation/uikit/uitableview/1614891-dequeuereusablecell/)
の2つを使用してカスタムセルを表示させ、インスタンスが解放されるタイミングを検証してみた。


```SampleTableViewCell.swift
final class SampleTableViewCell: UITableViewCell {
    
    @IBOutlet private weak var titleLabel: UILabel!
    @IBOutlet private weak var urlLabel: UILabel!
    
    func configure(model: Model) {
        self.titleLabel.text = model.fullName
        self.urlLabel.text = model.urlString
    }

　　deinit {
        print("deinit")
   }
}
```

```SampleViewController.swift
final class SampleViewController: UIViewController {
    var models = [Model]()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        tableView.register(UINib.init(nibName: "SampleTableViewCell", bundle: nil), forCellReuseIdentifier: "SampleTableViewCell")
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let cell = tableView.dequeueReusableCell(withIdentifier: SampleTableViewCell.className) as? SampleTableViewCell else {
            fatalError()
        }
        let model = models[indexPath.row]
        cell.configure(model: model)
        return cell
    }
}

```

※SampleViewControllerは一部のコードを抜粋

## 結果
　親のUITableViewが解放されるタイミング(画面遷移など)でカスタムセルも解放された。

　tableViewの[register(_:forCellReuseIdentifier:)](https://developer.apple.com/documentation/uikit/uitableview/1614937-register)を行うと、
　カスタムセルは初期化された後、その親であるUITableViewが存在する限りは解放されない。
　なぜかというと、[dequeueReusableCell(withIdentifier:)](https://developer.apple.com/documentation/uikit/uitableview/1614891-dequeuereusablecell/)等で
　既にインスタンス化されているカスタムセルを再利用できるようになっており、
　必要に応じて利用するためにインスタンスを保持し続けるから。


## 参考
https://stackoverflow.com/questions/33210583/uitableviewcell-object-deinit-never-called
cv2やmatplotlibのマウスイベントのコールバック関数でグローバル変数を使わないで引数argと返り値returnを使う

# 要約
cv2かmatplotlibで画像を表示して、2点クリックするごとに線を引いて、その結果の線分のリストを得たかった。
グローバル変数を使いたくなかったので苦労した.
今回はcv2で書いたがmatplotlibでCallBack関数を使用する際もおそらく同じ
画像はQを押すと閉じれます。


関数名にバリバリ日本語を使っているが後で自分が見やすいようにこうしています。
英語で書いてもわかりやすい関数名などつけられないので許して

# 環境
jupyter notebook
Python 3.6.0 on win32

# コード
```python
#画像をQで閉じる
import numpy as np
import cv2
import matplotlib as plt

class mouse_event_handler:
    def __init__(self):
        self.points = []

    def mouse_event(self, event, x, y, flags, param, img):
        if event == cv2.EVENT_LBUTTONUP:
            self.points += [[x,y]]
            line_number, buf = divmod(len(self.points),2)
            is_even = (buf == 0)
            if is_even:
                p1 = self.points[(line_number-1)*2]
                p2 = self.points[(line_number-1)*2+1]
                cv2.line(img,p1,p2,(255,0,0),3)

        
def 画像を表示してクリックで線を引いた結果のリストを受け取る関数(img):
    m = mouse_event_handler()

    cv2.imshow('img',img)
    cv2.namedWindow("img", cv2.WINDOW_NORMAL)
    cv2.setMouseCallback ("img", \
                          lambda event, x, y, flags, param: \
                          m.mouse_event(event, x, y, flags, param, img))
    #event, x, y, flags, paramはcv2で定義されているもの
    #クリックされた際にコールバック関数としてm.mouse_evnetが呼び出されるがその際に渡される5つの引数
    #(正確にはm.mouse_eventではなくlambda関数)

    #引数imgは参考サイト通りに設定した

    while (True):
        cv2.imshow("img", dummy_img)
        if cv2.waitKey(1) & 0xFF == ord("q"):
            break

    cv2.destroyAllWindows()
    return m.points

dummy_img = 255*np.ones((1000,1000,3))
print(画像を表示してクリックで線を引いた結果のリストを受け取る関数(dummy_img))
```

# 参考
[PythonとOpenCVで画像処理④【マウスイベント】](https://rasp.hateblo.jp/entry/2016/01/24/204539)
[(stack over flow) Returning values from callback(s) in Python](https://stackoverflow.com/questions/19585935/returning-values-from-callbacks-in-python)
[Pythonでcallbackに引数を使う方法と注意点](https://rcmdnk.com/blog/2015/11/25/computer-python/)
GitHubでやること


##記事を読む前に気をつけること
本記事はアウトプットのためにまとめているものです。
違っているところや違和感があることについては悪しからず、、、


Gitの導入
---
念のため確認

```terminal:terminal
$ git --version
x.xx.x.windows.x
```
上記コマンドでバージョンが出力されなければ以下の手順を踏んでgitをインストールします
バージョンが出力されれば②の設定から作業を進めてください。
Gitのインストール
---
1. [Git](https://git-scm.com/downloads)のwebサイトからgit for windowsをダウンロードする
2. ダウンロードしたファイルのインストールを進める
3. 上記のコマンドでgitのバージョンが表示されたらインストール完了です

Gitの設定
---
まず下記urlからGitHubアカウントを作成します
[GitHubサインアップページ](https://github.com/join)

作成したらアカウントのユーザー名とメールアドレスを設定します

```terminal:terminal
$ git config --local user.name "ユーザー名"
$ git config --local user.email "メールアドレス"
```
コミットなどのGitコマンドを使用する際にはこの情報を使用するため忘れずに設定しましょう。


設定が反映されているか確かめるには次のコマンドを実行してください。
設定した情報が出力されます。

```terminal:terminal
$ git config user.name
> ユーザー名
$ git config user.email
> メールアドレス
```
これは初期設定で、今作業した配下のディレクトリでは上で設定した内容が反映されています。

１つのPCでそんな複数もアカウントつかわねぇよ！って人は下のコマンドを実行してください

```terminal:terminal
$ git config --global user.name "ユーザー名"
$ git config --global user.email "メールアドレス"
```
> --global

でPC全体に設定を行います

これでだけでGitの基本設定は終わりです。
もちろん、さらに詳細な設定をすることも可能です。
気になる方は調べてみてください。

GitHubからリポジトリをcloneする（コードをlocalに持ってくる）
---
試しにruby公式のリポジトリをcloneします

```terminal:terminal
$ git clone https://github.com/ruby/ruby.git
```
これでコードを実行したディレクトリにrubyのコードを持ってきました

作業ブランチを切り替える
---
作業ブランチを切り替えましょう
まだ、ブランチが他にないので新規にブランチを作成します

```terminal:terminal
$ git checkout -b "任意のブランチ名"
* 任意のブランチ名
  master
```
入力したブランチに切り替わっていたら成功です


修正したコードをGitHubに上げる場合
---
GitHubにコードをあげる際はコードの最終確認を行いましょう

```terminal:terminal
$ git status
> 現在のファイル状況を確認

$ git add {ファイル名}
> 変更をコミットしたい（反映させたい）ファイルをindexに登録

$ git diff --cached
> indexに登録したファイルの変更内容を全て確認

$ git commit -m "コミットメッセージ"
> indexに登録した変更内容を記録する

$ git push {リモートリポジトリ} {現在のブランチ名}
> localのcommit履歴（変更履歴）をremoteに上げる
```

以上が大まかなGitHubの使用方法になります。
どこか違う点やこんな便利なコードもあるよ！って場合は優しくコメントいただければと思いますmm
DNSフォワーダ とは

## 勉強前イメージ

DNSサーバに送るって感じで
キャッシュとちょっとややこしくなってしまった

## 調査

### DNSフォワーダとは？

DNSのクライアント(PC等)からDNSサーバへ問い合わせを行う際、
クライアントとDNSサーバが違いネットワークに存在する時に使用するもので、
DNSの問い合わせのパケットをDNSサーバに転送する機能です。

よくこの機能が使われているのが家庭用のルーターです。
クライアント(PC)のDNSサーバはルーターに向いてますが、
基本的にはルーターにはDNSリゾルバの設定はないので(アップデートなど必要)
その際の中継の機能として `DNSフォワーダ` があります。

他にもDNSプロキシやDNSリレーなど呼ばれています。

![12021-07-12 # DNSフォワーダ と キャッシュ の違い - diagrams.net -.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/361a0316-c750-0369-28b6-2028bdffd9fb.png)

### キャッシュとの違い

最初、フォワーダとキャッシュの違いがあやふやでした。
キャッシュは問い合わせした際の結果を一定期間保持し、再度同様の問い合わせがあれば前の問い合わせ結果から返答する機能です。
↑で例として書いてる家庭用のルーターにキャッシュ機能があれば、
PCから何度も問い合わせを行っても、一定期間はインターネットプロバイダのDNSサーバへ接続せずに
保持しているIPアドレスをPCに返します。

### フォワーダ と キャッシュの違い まとめ

- フォワーダ → DNSパケットの中継
- キャッシュ → DNSの答えを一定期間保持し、再度問い合わせがあればキャッシュから返答

## 勉強後イメージ

なんでフォワーダが必要なのかなって思ったけど、
DNSの応答をネットワークが異なる箇所に存在するDNSサーバに投げる ということをしたいから、ってことかな？

## 参考

- [7.12　DNSリレー機能](https://www.alaxala.com/jp/techinfo/archive/manual/AX7700R/HTML/10_10_/APGUIDE/0115.HTM)
- [【図解】DNSプロキシ(DNSフォワーディング、DNSリレー)の中継機能の仕組み、ciscoでの設定例](https://milestone-of-se.nesuke.com/l7protocol/dns/dns-proxy/)
予測符号化モデルについて調査中

### 予測符号化モデルについて調査する動機(追記)
画像認識は、画像の取得から推論結果を得るまでの遅延がどうしても大きくなってしまいがちである。
リアルタイムに動作するシステムの一部として画像認識技術を用いるとその遅延時間が問題になってしまうことがある。
潤沢なハードウェア資源を使って推論に要する時間を短縮するアプローチもあるだろう。
しかし、リアルタイムであって組み込み系の画像認識の場合には、潤沢なハードウェア資源を使うというアプローチは許されないことが多い。

また、リアルタイムに動作するシステムの場合には、その遅延がシステムの動作の本質にかかわってくる場合も多い。明日の天気予報が、明日になって得られるのでは、実用上は意味がない。
　走行中の車両からの物体検出ならば、その結果を事故の回避に結び付けられる必要がある。通常の画像認識の結果は、機械学習によるものであれ、ルールベースのものであれ、常に、画像をキャプチャした時点という過去の時点の情報である。情報を手にした時点では、既に遅延時間分だけ過去の情報にすぎない。
　
　そのため、今を知るためには、遅延時間分に相当する時間差だけ「未来予測」した結果が、おそらく「今」の状況である。
　人の脳の中ではそのような処理をしているので、網膜に結像してから知覚するまでの時間差があるようには自覚されない。

深層学習の分野でも、微小な時間差分だけ、「未来予測」をする試みがなされている。

---
Wikipedia [Predictive coding](https://en.wikipedia.org/wiki/Predictive_coding)


[予測符号化 (predictive coding) とは何か]
(https://omedstu.jimdofree.com/2018/08/17/%E4%BA%88%E6%B8%AC%E7%AC%A6%E5%8F%B7%E5%8C%96-predictive-coding-%E3%81%A8%E3%81%AF%E4%BD%95%E3%81%8B/)


[Predictive coding (Rao & Ballard, 1999) モデルの実装](https://salad-bowl-of-knowledge.github.io/hp/neuroscience/2020/04/25/predictive-coding.html)

[Deep Predictive Coding Networks for Video Prediction and Unsupervised Learning](https://arxiv.org/abs/1605.08104)

qiita [「予測する脳」Predictictive codingの実装モデル「PredNet」を動画に適用して、一時点先の画像予測を行ってみた](https://qiita.com/Afo_guard_enthusiast/items/00e4abf7cdef30d30c81)

github [prednet](https://github.com/coxlab/prednet)

----

github [Deep Predictive Coding for Multimodal Representation Learning](https://github.com/thefonseca/predictive-coding)


上記のgithub の内容は興味深かったので、そのREDAME.mdの内容を一部和訳する。
動画での次のフレームの画像の予測を行っている。

---

### 概要
機械学習の用語では、常識的な推論は、時空間感覚データの背後にある隠れた要因を解きほぐす表現を学習する能力に関連しています。 この作業では、知覚と神経科学の文献からの学習の予測符号化理論が、そのような常識的な誘導バイアスを実装するための良い候補である可能性があると仮定します。 Lotterらによる予測符号化（2016）の先行する深層学習の実装に基づいています。 そして、料理やダイビングなどの抽象的な日常の人間の行動を推測するという挑戦的なタスクにその用途を拡張します。 さらに、聴覚データを処理するための同じアーキテクチャの新しい用途を提案し、単純な感覚置換トリックを使用して、予測符号化モデルが有用な表現を学習できることを発見しました。 私たちの転移学習実験は、UCF-101アクション分類データセットで学習された表現の優れた一般化も示しています。

### 研究上の質問
世界を観察することで常識を身につける機械の設計を調べるために、Lotterらによって公開された予測符号化モデル（2016）の深層学習の実装を利用します。 彼らの深層予測符号化ネットワーク(deep predictive coding network)は、合成画像と自然画像のオブジェクトの動きに相関する潜在変数を解きほぐす表現を学習することが示されました。 私たちは彼らの研究を拡張して、以下の質問に対処します。

- 教師なし予測符号化モデルは、より高いレベルの時空間概念、つまり運転や運動などの日々起こる活動を学習できますか？

- 予測符号化の誘導バイアスは、これらのモデルが聴覚情報からも学習できるほど十分に一般的ですか？ 
- Friston and Kiebel（2009）およびRao and Ballard（1999）によって提案された元の神経科学理論に関して、深い予測符号化の実装の制限は何ですか？

## 寄与
私達の主要な寄与は以下に要約される。

![](https://github.com/thefonseca/predictive-coding/raw/master/images/next-frame.png)
麗しのXMODEM

#事件の始まり
令和3年。
XMODEMという技術を使う事になるなんて10年以上前エンジニアになりたての頃の私は想像することが出来ただろうか。

ことの経緯は某案件のため、社内にある「Cisco3550」を10台をラックマウントする事となった。
発売が2003年。EoLが2007年の代物である。
![C3550.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1314094/4e22a20e-e52b-4e26-af47-50819bd432e1.png)

ちなみに、この名器は2021年現在、某オークションサイトでは500円ほどで売買されている。
https://aucfan.com/intro/q-cisco.203550/

#XMODEMを実施する背景
そもそも、なぜXMODEMを利用することになったかというと、Ciscoスイッチを動作させるIOSが削除されたためである。
**削除理由はAnsibleを使ったIOSのアップグレードテストの失敗です:fist:**

IOSを削除されてしまうと、見た目はランプがオレンジランプ点灯で機器障害に見えて、コンソールでログインするとROMONモードになり、```Switch：```と表示される。

ここからはCisco3550を捨てるか、XMODEMを使って復旧させるかの葛藤が始まるわけだが、こんなネタどこの誰も需要が無いと思いつつも、個人的には成仏出来ないと思い記事にしたいと思う。

ぶっちゃけ言うと、某有名サイトに記載あるわけで参照したら出来るって話ではあるが、
一部コマンドが間違っていたり、注意点があったので補完の意味で投稿したいと思う。
https://www.infraexpert.com/study/ciscoios14.html

#復旧手順
①PCとコンソール接続
コンソール接続を行う。ターミナルソフト ( Tera Term ) も起動させておく。

②スイッチの電源のオフとオン
物理的にケーブルの抜き差しを行う。地味に再起動に10分ぐらいかかる。

③MODEボタンを押し続ける
あまり馴染みが無いかもしれないが、スイッチのフロント側に「Mode」ボタンがあり30秒ぐらい押していると初期化される。
![Modeボタン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1314094/49c3b288-1c5a-f994-3c1d-121e40ece215.png)

④フラッシュファイルシステムの初期化
スイッチのフラッシュファイルシステムを初期化する。
```switch： flash_init```

⑤フラッシュメモリの内容確認
フラッシュメモリにどのようなファイルがあるのか表示させる。
``switch： dir flash：``
![dir.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1314094/7951a319-9458-6255-4a6d-97dca2ff7a3d.png)

⑥xmodem回復の高速化
xmodemを使用しIOSをダウンロードするという事は、LANケーブルではなくコンソールケーブルを経由してダウンロードすることになる。その場合、デフォルトでは9600bpsのスピードで超低速なので、この値をBAUDレートの最大値である115200に変更する
```switch： set BAUD 115200```

注意：TeraTarm側もBAUDレートを変更しないと文字化けしてしまう...:girl_tone1:
![文字化け.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1314094/96ddccd4-a309-7aa6-c295-c5a33dbc2f93.png)

※TeraTarm側のレートも変更必要となる。
　・　Tera Termメニュー「設定（S）」⇒「シリアルポート」⇒ ボー・レートで115200
![teratarm.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1314094/9f219e48-75ce-76a2-34e3-deaecbd9bea6.png)

⑦xmodemのファイル受信
xmodemプロトコルを使用してファイル転送を開始する。以下コマンドで受信準備が完了。
```switch：copy xmodem: flash:c3550-i5q3l2-mz.121-12c.EA1.bin```
　※　地味にスペースが必要で、スペースが無かったらエラーで弾かれる...:girl_tone1:

⑧xmodemのファイル送信
Tera Termでxmodemによるファイル転送を開始する。以下の手順で転送を開始できる。
　・　Tera Termメニュー「ファイル（F）」⇒「転送（E)」⇒「XMODEM」⇒ 送信(S)
　※　送信するIOSを格納している場所を選択していき、IOSを選択する。
　※　転送が始まらない場合、一度Tera Termを閉じて起動して、再度ボーレートを設定。
　**※　個人的ベストハマりポイント。問題がいまいち分からんけど⑦⑧を何度も繰り返した**:girl_tone1:

~~~
　あとは、シリアルからIOSをスイッチに送るのを待つのみ。
　わたしの場合、金曜日の夜にXMODEMを仕掛けて帰宅した。
　余談だが10年ほど前の記憶では転送完了まで数時間かかっていた。
　とにかく明るい安村でいないと、プレッシャーでメンタル崩壊する(´;ω;`)
~~~
![成功.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1314094/ec94f3e6-954f-256d-3a8c-31a3aac09940.png)
　「成功したね！」:girl_tone2:

⑨xmodemのボーレートをデフォルト値へ
ダウンロードが完了するとBAUDレートをデフォルト値に戻す。
```switch： set BAUD 9600```

⑩tera termの設定変更
CatalystでBAUDレートをデフォルト値 9600 に戻したので、Tera Termでも9600に戻す。

⑪新規にダウンロードしたIOSで起動させる。
```switch： boot flash：c3550-i5q3l2-mz.121-12c.EA1.bin```
![log.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1314094/24d4817f-b075-444c-08b6-7a4a96b2e0eb.png)

~~~
ここまで来たら終了！
通常どおり起動して、初期設定して完了(´;ω;`)
お疲れ様でした！
~~~


#イベント告知
https://www.ap-com.co.jp/blog/archives/7770
ウォータフォールモデルのプロジェクト管理

##はじめに
システム開発は一般的にプロジェクト形式をとることが多い。
ポイントをまとめておきたいと思う。

## プロジェクトの定義
目的を達成するために計画と実行する業務。
計画とは、一定期間で人・物・金を投入して目標を達成すること。
期間と目標が重要で、目標を達成する期限が決まっていなければプロジェクトではない。
※期限が無ければ、ただの通常業務である。

## プロジェクトの開始と終了
プロジェクトでは開始と終了を明確にすることが重要である。

・キックオフ
　開始時はキックオフミーティングを実施し、プロジェクトのスタートを宣言する。
・プロジェクト終了ミーティング
　無事にシステムがリリースされ問題が無ければ、終了を宣言する。
　プロジェクトを振り返り反省会をするのもよい。

※備考
・プロジェクトの規模が大きければ、対顧客向け、社内向け等、関係者の種類別に実施する。


##ウォータフォールモデル
ウォータフォールモデルでは以下の工程がある。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1308027/eb962ec0-e216-089e-c118-499db0f09ec3.png)

要件定義と総合テスト
外部設計と結合テスト
内部設計と単体テスト
というふうに、各工程で成果物をまとめ
各フェイズの設計とテストを行うことで品質を担保する

###各フェイズについて

|NO|名称|略称|主担当|レビュアー|
|:-:|:-|:-|:-|:-|
|1|要件定義|RD【requirements definition】|開発SE|顧客|
|2|外部設計（基本設計書）|SD【system design】|開発SE|顧客、PG|
|3|内部設計（詳細設計書）|PD【process design】|開発SE|PG|
|4|製造/単体テスト|PG/UT【programming/test】|PG|PG|
|5|結合テスト|JT【joint test】|PG|開発SE|
|6|総合テスト|ST【scenario test】|開発SE|顧客|

それぞれ主担当が作業を担当しレビュアーに承認してもらうとよい


1.要件定義：
　業務システムの要件を定義する。
2.外部設計：
　要件定義に沿ってシステム要件を定義する。
　特に、顧客が利用することになる画面や帳票レイアウトは重要。
3.内部設計
　システムが処理する内部処理を定義する。
4.製造
　実際の開発、プログラミング。
5.単体テスト
　プログラムが想定通りが単体でテストする
6.結合テスト
　プログラムを繋げてテストする。
　結合が意味する範囲は、プロジェクトの規模で変化する。
　規模が大きければ、内部結合、外部結合等と分割する。
7.総合テスト
　システムが要件定義通りが、実業務に沿ってテストする。
　顧客にも参加してもらうのが良い。
2020年度　広島大学　数学【１】（平面図形）

# 問題文

$a$と$b$を正の定数とする。$0<\theta<\pi$を満たす実数$\theta$に対し,平面上で,次の３つの条件1,2,3を満たす三角形$PAB$,およびこの三角形と辺$AB$を共有する長方形$ABCD$を考える。

1. $PA=a,\ PB=b,\ \angle APB=\theta$である。
1. 2点$C,D$はともに直線$AB$に関して点$P$と反対側にある。
1. $AB=3AD$である。

三角形$PAB$の面積と長方形$ABCD$の面積の和を$S$とする。次の問に答えよ。

(1)辺$AB$の長さを$a, b, \theta$を用いて表せ。
(2)$S$を$a, b, \theta$を用いて表せ。
(3)$\theta$が$0<\theta<\pi$の範囲を動くときの$S$の最大を$M$とし,$S$が最大値$M$をとるときの$\theta$の値を$\beta$とする。$M$を$a, b$を用いて表せ。また$\sin\theta$および$\cos\theta$の値をそれぞれ求めよ。
(4)$a=16$,$b=25$とする。また$\beta$を(3)で定めた値とする。$\theta=\beta$のときの、点$P$と直線$AB$の距離を求めよ。


# 読んで思ったこと

- (1)と(2)は図を描いて素直にやればいいかな
- (3)で、$\beta$の値を求めないということは、$S$が$\sin\theta$と$\cos\theta$の関数になるんだろうな（三角形PABの面積は$\frac{ab}{2}\sin\theta$、ABの長さは余弦定理で出すと$\cos\theta$が含まれるから）
- $\sin\theta$と$\cos\theta$が混ざってる状態（$\cos^2\theta + \sin^e\theta = 1$でどちらかに揃えることができない状態）で最大が求まるってことは....？
- どうでもいいけど$\alpha$をとばして$\beta$をいきなり使ったのはなんでだろうw
- (4)は$\theta=\beta$のときの三角形PABの面積が表せたらチョロそうだけど、まだわからんなぁ
- $16$とか$25$っていう数字がなんだかわざとらしいけど、なんかあるんか.....？


# 実際に解いてみた

(1)
$\triangle PAB$に余弦定理を当てて、$AB>0$より

```math
AB=\sqrt{a^2 + b^2 - 2ab\cos\theta}
```

(2)(3)

```math
\begin{align}
S &= \frac12ab\sin\theta + AB\cdot \frac13AC\\
&= \frac12ab\sin\theta + \frac13(a^2 + b^2 - 2ab\cos\theta)\\
&= \frac16ab(3\sin\theta - 4\cos\theta) + \frac13ab\\
&= \frac56ab\sin(\theta - \alpha) + \frac13(a^2 + b^2)
\end{align}
```

ただし$\alpha$は$\cos\alpha = \frac35,\ \sin\alpha = \frac45$を満たす実数で、$0<\cos\alpha<1,\ 0<\sin\alpha<1$であるため、$0<\alpha<\frac{\pi}{2}$である。
よって$-\frac{\pi}{2} < \theta - \alpha < \pi$なので$-1 < \sin(\theta - \alpha) \le 1$となる。
ゆえに$S$は$\theta = \alpha + \frac{\pi}{2}$のとき最大値$M = \frac56ab + \frac13(a^2 + b^2)$をとる。
また$\sin\beta = \sin(\alpha + \frac{\pi}{2}) = \cos\alpha = \frac35$、$\cos\beta = \cos(\alpha + \frac12) = -\sin\alpha = -\frac45$

(4)

```math
\triangle PAB = \frac12 \cdot 16 \cdot 25 \cdot \frac35 = 120\\
AB = \sqrt{16^2 + 25^2 - 2 \cdot 16 \cdot 25 \cdot \left( -\frac45 \right)} = \sqrt{1521} = 39
```

点$P$と直線$AB$の距離を$L$とおくと、

```math
\triangle PAB = \frac{39}{2} L = 120\ \  \Leftrightarrow\ \ L=\frac{80}{13}
```


# 最初に思ったことの答え合わせ

> (3)で、$\beta$の値を求めないということは、$S$が$\sin\theta$と$\cos\theta$の関数になるんだろうな
> $\sin\theta$と$\cos\theta$が混ざってる状態で最大が求まるってことは....？

混ざってたけど合成できる形になってたからラッキーだった

> どうでもいいけど$\alpha$をとばして$\beta$をいきなり使ったのはなんでだろうw

教科書で三角関数の合成に$\alpha$が使ってあるから、それになれてる人用に$\alpha$を空けてくれてたんだねwそういうとこ好きだぞ！！！

> (4)は$\theta=\beta$のときの三角形PABの面積が表せたらチョロそうだけど、まだわからんなぁ

チョロでした

> $16$とか$25$っていう数字がなんだかわざとらしいけど、なんかあるんか.....？

約分しやすいだけでした（~~はいNをやくぶうううぅぅぅぅぅん！！！~~）
初学者が「Git をはじめからていねいに」でつまづいたところをまとめてみた

Git について学習したのでアウトプットします。
ちなみに私はMac触り始めて半年の者です。（ガチガチの初心者です）
初学者のアウトプット記事ですので、間違っている点など多々あるかと思いますが、暖かい目で見守っていただけますと幸いです。

こちらが今回の学習で参考にさせていただいた「Git をはじめからていねいに」のURLです。
[Git をはじめからていねいに](https://github.com/yamataku29/introduction-to-git)

#Gitってどうやって入れるの？（インストールすんの？）
まず、Gitをインストールする方法がわかりませんでしたので、まとめました。

まず、ターミナルを開き、

```qiita.git
'git --version'
```

と入力してEnter

```qiita.git
'git version バージョン数字'
```

と出れば、ひとまずGitはインストールされているので、最新版GitをインストールするためにHomeｂrewを使用します。
（Macは標準でインストールされているみたいです。）

こちらの記事の”Homebrewを使ってGitをインストールする”を参考にしてインストールしました。
[Homebrew参考URL](https://tracpath.com/bootcamp/git-install-to-mac.html)
Homebrewをインストールするメリットも書かれているのでとても参考になりました:relaxed:

#txtファイルってどう保存するの？
はじめてのコミットの章で、「nyan書かれた nyan.txt というファイルを作業ディレクトリ内に作ってください。」と書いてあり、早速混乱しましたので、解決法をまとめました。

1．テキストエディットを起動して「nyan]を入力
2．フォーマットを標準テキストにする。
３．ファイル→保存→標準テキストのエンコーディングを日本語（Shift JIS）にする。
４．保存場所をmy_first_workspaceにする（デスクトップ上でmy_first_workspaceを検索）

注意点としては、テキストファイルをそのまま保存してしまうと、txtファイルにはなりません。
必ず、2と3の行程が必要です。

#エディタについて
エディタはviが嫌な人は、Mac標準のエディタの使用もひとつの手ですと紹介されてますが、viとMac標準のエディタでは使用感が若干異なるので、Gitに出力された表示やhelpをよく読んで、進めましょう。（viエディタの方が参考記事が多い気がします。初学者はviの方がいいのかな？）

viとMac標準エディタの差異をご紹介します。

viではコミットの際

```qiita.git
'git commit'
```
と入力するとエディタが立ち上がり、コミットメッセージを入力して:wqと入力すればOKですが、
Mac標準エディタでは

```qiita.git
'git commit -m "コミットメッセージ"'
```
と入力しないとコミットできません。
ちなみに設定でエディタをviしていてもこの書き方でちゃんとコミットできます。
メッセージはちゃんと”で囲まないとだめです。

また、マージの際は
viの場合

```qiita.git
'git merge my_first_branch'
```

でエディタが立ち上がり、メッセージにMerge branch 'my_first_branch'と書かれているので、そのまま:wqで保存して終了できますが、

Mac標準エディタの場合、
マージした後に、コミットしてくださいみたいな文言が出てきます。
その場合は、コミットと同じようにコミットメッセージを書いてコミットすることで、マージすることができます。

マージコミットする時のメッセージ例

```qiita.git
`git commit -m "my_first_branchをマージ"
```

#終わりに
今回初めてMacでGitを学習しましたが、Macの機能とGitの機能のふたつを勉強できました。
「Git をはじめからていねいに」はとても勉強になる記事でしたが、私のようなズブズブの初学者には少し手強いものになるのではないかと感じました。
もし、私のような初学者の方が「Git をはじめからていねいに」でつまづいた時に、この記事を見て参考にしていただければ、幸いです。
有料Slackでシングルチャンネルゲストを招待する方法

Slackは会社同士のコラボレーションに便利なツールです。
会社間の連絡にメールでなくSlackを使う機会が増えています。

無料ユーザーは、Slackコネクトが使えません。
招待する場合は「シングルチャンネルゲスト」として招待を送りましょう。
ゲスト招待のUI操作が解りづらかったので、メモしておきます。

##やりたいこと

Slack無料ユーザーをゲストとして招待する。
1つのチャンネルが使える、シングルチャンネルゲストとして招待する。

##2種類のゲストの違いを理解する

ゲストには、有料の「マルチチャンネルゲスト」と無料の「シングルチャンネルゲスト」があります。
間違った方法で招待すると、自分の会社でゲストの課金をすることになったり、
相手の会社が課金しないとコネクトできなかったりします。

###マルチチャンネルゲスト
あなたが指定するチャンネル (複数可) のみにアクセスできます。
マルチチャンネルゲストは通常のメンバー料金が請求されます。
そのため、参加できるチャンネル数に制限はありません。

###シングルチャンネルゲスト

無料で、アクセスできるのは 1 チャンネルのみとなっています。
ワークスペースの有料アクティブメンバー 1 人につき 5 人まで、
シングルチャンネルゲストを招待できます。
例えば、ワークスペースのメンバー数が 10 人の場合、招待できるシングルチャンネルゲストは最大 50 人です。

[Slack でのゲストのメンバー種別を理解する](https://slack.com/intl/ja-jp/help/articles/202518103-Slack-%E3%81%A7%E3%81%AE%E3%82%B2%E3%82%B9%E3%83%88%E3%81%AE%E3%83%A1%E3%83%B3%E3%83%90%E3%83%BC%E7%A8%AE%E5%88%A5%E3%82%92%E7%90%86%E8%A7%A3%E3%81%99%E3%82%8B) | Slack

ご紹介する方法で招待を送ると、無料のゲストで招待が可能です。

##メンバーを招待

サイドバー上部の矢印メニューをクリックします。
![](https://i.gyazo.com/5db0ef7b73ebfe378198db2eeb8f253f.png)

##ゲストを招待する
メールアドレスと招待の種類を指定します。

![Alt text](https://i.gyazo.com/56064266dca2ef727642d46fd8c3f9ee.png)

ゲストを招待するチャンネル名を指定します。

![Alt text](https://i.gyazo.com/9013de55b500e01a24517cad33203259.png)

これで無料Slackの方をゲスト招待できます。
無料ゲストの方も多いので、上手に活用したいですね。
残プロ　第-41回　~flaskのredirectを使う~

# redirectとは

pythonの関数からhtmlを指定するにはrender_templateを使用しましたが，外部サイトへの遷移はできませんでした．
そこで活躍するのがredirectメソッドです．以下のように返り値として利用できます．


~~~ python:
@app.route('/redirect')
def google():
    return redirect('https://www.google.com/?hl=ja')
~~~
PHP 定義済み定数 DIRECTORY_SEPARATOR 個人メモ

# 目的

- 定義済み定数である`DIRECTORY_SEPARATOR`の存在を初めて知ったのでメモ的にまとめておく

# DIRECTORY_SEPARATORは名前通りディレクトリの区切り文字が格納されている定数

- 下記のように記載して実行してみる。

    ```php
    echo DIRECTORY_SEPARATOR;
    ```

- ~~`\`が出力された。~~
- `/`が出力された。
- ~~この定義済み定数はOSによって`¥`を返したり`\`を返したりするらしい。~~
- この定義済み定数はOSによって`/`を返したり`\`を返したりするらしい。
- linux系環境だと`/`を、windows環境だと`\`を返すようだ。
【TypeScript】ユーザー定義型ガードと配列

## （前提）[ユーザー定義型ガード](https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards)

次のような型を定義した場合、

```typescript
interface Named {
    name: string;
}
```

次のような関数を定義すると、

```typescript
function isNamed(obj: any): obj is Named {
    return typeof obj.name === "string";
}
```

次のように、あるオブジェクトが `Named` 型であるかどうか `isNamed` 関数を用いて判定し、`true` であれば型アサーションなしで `Named` 型として扱うことができる。

```typescript
const obj = JSON.parse('{ "name": "Alice" }');
if (isNamed(obj)) {
    // ここでは obj が Named 型であるとみなされる。
    console.log(`obj.name: ${obj.name}`);
} else {
    console.log("`obj` is NOT Named.")
} // > "obj.name: Alice"
```

## オブジェクトがユーザー定義型の配列であるかどうかを判定する

あるオブジェクトがユーザー定義型の配列であるかどうかを判定するには次のようにする。

```typescript
const obj = JSON.parse('[{ "name": "Alice" }, { "name": "Bob" }, { "name": "Charlie" }]');
if (Array.isArray(obj) && obj.every(isNamed)) {
    // ここでは obj が Named[] 型であるとみなされる。
    console.log(obj.map(named => named.name));
} else {
    console.log("`obj` is NOT array of Named.");
} // > ["Alice", "Bob", "Charlie"]
```

／以上
Progateで作ったWebアプリをDjangoで作ってみる！ Part1 -初期設定編-

ProgateのNode.jsコースではお買い物リストアプリを作るのですが、これと全く同じものをDjangoで作ってみます。

Djangoでのアプリ開発の一連の流れを整理するために記していきます。

**目標物**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/471633/f75ec259-afa7-615a-2e96-01db943e50f9.png)

HTMLとCSS、PNG形式画像は使い回しで、一部をDjango用のタグに変えます。

# はじめに

まずは初期設定を進めていきます。

プロジェクト名を<font color="RoyalBlue">**listapp**</font>、アプリ名を<font color="Tomato">**list**</font>とします。

# プロジェクトの作成

Djangoのプロジェクト作成は``django-admin``というコマンドを使います。

今回のプロジェクト名は<font color="RoyalBlue">**listapp**</font>なので以下のコードを実行します。


```console
django-admin startproject listapp
```

# アプリの作成

``cd``コマンドでプロジェクトの中に移動します。

```console
cd listapp
```

これで<font color="RoyalBlue">**listapp**</font>プロジェクトの中に移動しました。

続いて、アプリ作成のコマンドを実行します。アプリを作成するには``manage.py``コマンドを使います。

``manage.py``コマンドはDjangoに備わる便利機能を使うためのファイルです。

アプリ名は<font color="Tomato">**list**</font>です。

```console
python manage.py startapp list
```

これで<font color="RoyalBlue">**listapp**</font>プロジェクトの中に<font color="Tomato">**list**</font>アプリが作成されました！

# アプリの登録

アプリ作成後は、プロジェクトに対して作成したアプリを認識させる必要があります。

アプリを追加する場所は、**setting.py**ファイルの中の``INSTALLED_APPS``という変数の中です。

<font color="Tomato">**list**</font>アプリなので、ここの末尾に``list``というコードを記入します。

```python:listapp/listapp/setting.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'list', # ☆
]
```

これでアプリをプロジェクトに認識させることができました。

# urls.py

アプリの中に**urls.py**ファイルを作成します。Visual Studio Codeのエクスプローラーの「新しいファイル」アイコンか以下のコマンドで作成します。


```console
touch list/urls.py
```

**urls.py**ファイルはブラウザからのrequestをもとに、**views.py**ファイルに対して指示を出します。

``urlpatterns``に書かれていることは、ブラウザからのrequestと**path()**関数の第一引数のURLが合致した場合に、**views.py**にかかれている**path()**関数の第二引数の中身（classやfunction）を実行するように指示する、という意味です。

プロジェクト（<font color="RoyalBlue">**listapp**</font>）の**urls.py**ファイルからアプリ（<font color="Tomato">**list**</font>）の**urls.py**を呼び出すためのコードを、プロジェクト（<font color="RoyalBlue">**listapp**</font>）の**urls.py**ファイルに書いていきます。

**include()**関数は他のurls.pyを呼び出すために使います。

<font color="Tomato">**list**</font>アプリの``urlpatterns``は一旦、空にしておきます。

```python:listapp/listapp/urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    # リクエストされたパス部分がadmin/に合致した場合、admin.site.urlsを呼び出す
    path('admin/', admin.site.urls), 

    # listアプリのurls.pyを呼び出す
    path('', include('list.urls')),
]
```

```python:listapp/list/urls.py
from django.urls import path

urlpatterns = [
    
]
```

イメージはこんな感じ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/471633/5b2fde8c-7f1b-3df2-1f9e-4ac9d16b31be.png)



これでとりあえず初期設定は完了です！

Part2に続きます！

[Part2](https://qiita.com/insilicomab/items/bab360f4d1503034ddf5)
【JavaScript】str.matchAll(re)はre.exec(str), re.test(str)の最後のマッチ位置を引き継ぐので注意

正規表現が間違えてるのかと3時間ぐらい格闘して10キロ痩せた

# re.exec(str)

普通に使ったら何回実行しても結果は同じ。

```js
const re = /\d/;
const str = "abc123def";

re.exec(str)[0] // 1;
re.exec(str)[0] // 1;
re.exec(str)[0] // 1;
```

正規表現にgフラグをつけると実行するたびに次のマッチの結果が返ってくる。

```js
const re = /\d/g;
const str = "abc123def";

re.exec(str)[0] // 1;
re.exec(str)[0] // 2;
re.exec(str)[0] // 3;
```

マッチするものがなくなったら一旦nullを返してまた最初から始まる。

```js
const re = /\d/g;
const str = "abc123def";

re.exec(str)?.[0]; // 1
re.exec(str)?.[0]; // 2
re.exec(str)?.[0]; // 3
re.exec(str)?.[0]; // undefined
re.exec(str)?.[0]; // 1
re.exec(str)?.[0]; // 2
```

# re.test(str)

こっちも同じ。
`true/false`しか返ってこないので前回の位置を引き継いでるのが分かりにくい。

```js
const re = /\d/g;
const str = "abc123def";

re.test(str); // true
re.test(str); // true
re.test(str); // true
re.test(str); // false
re.test(str); // true
re.test(str); // true
```

`exec`と夢のコラボも実現

```js
const re = /\d/g;
const str = "abc123def";

re.exec(str)[0]; // 1
re.test(str); // true
re.exec(str)[0]; // 3
re.test(str); // false
```


# str.matchAll(re)

で、`str.matchAll(re)`もそれを引き継ぐ。
ちなみに`str.matchAll(re)`に渡す正規表現はgフラグがついてないとエラーになる。

```js
const re = /./g;
const str = "abcdef";

re.exec(str)[0]; // a
re.exec(str)[0]; // b

[...str.matchAll(re)].map(m=>m[0]);
// c, d, e, f
```

でも`str.match`には影響ないよ。
だから`str.matchAll`にも影響ないんだと思ってた。

```js
const re = /./g;
const str = "abcdef";

re.exec(str)[0]; // a
re.exec(str)[0]; // b

[...str.match(re)]
// a, b, c, d, e, f
```

「そうはならんやろ」って人、こんなんやりそうな感じしませんか。(やった)

```js
const re = /\d/g;
const str = "abc123def";

// なんとなく負荷下がりそうだしそもそもマッチしないなら実行せんとこ
let matches;
if (re.test(str)) { //ここで「1」が消費される
  matches = [...str.matchAll(re)], // 2, 3
} else {
  matches = []
}
```

なっとる！！！！！！やろがい！！！！！！！！
iOSクラッシュログ(.ipsファイル)のシンボル化チュートリアル

# 環境
- Xcode 12.5.1
- iOS 14.6
- iPhone 8

# 事前準備
- ipsファイルを取得するための実機を用意
- エラー発生用testアプリを作成
  - 今回は画面にUIButtonを配置し、押すと`fatalError()`を実行するようにした

```swift:ViewController.swift
import UIKit

class ViewController: UIViewController {
    @IBAction func didTapErrorButton(_ sender: UIButton) {
        fatalError("an error occurs")
    }
}
```

- testアプリをアーカイブ、AdHoc配信のipaを作成し、実機にインストール
  - 今回は[Apple Configurator 2](https://apps.apple.com/jp/app/apple-configurator-2/id1037126344?mt=12)を使用し、インストールした 

# 手順

１. testアプリでエラーを発生させる

２. `設定アプリ`>`プライバシー`>`解析および改善`>`解析データ`から対象の`ipsファイル`を取得

- ips一覧の画面を上にスライドすると検索ボックスが出てくるので、testアプリのプロジェクト名を入力すると対象のipsを見つけやすい
    - 対象ipsのテーブルセルを選択し、右上に共有アイコンからAirDropなどでipsファイルを取得できる

３. Xcodeのアプリケーションメニュー`Window`>`Organizer`から対象のアーカイブを右クリック。 `Show in finder`し`xcarchive`ファイルを確認する

４. 対象の`xcarive`ファイルを右クリック、`パッケージの内容を表示`を選択する

５. 以下のファイルを取得

- dSYMsフォルダの`dSYM`ファイル
    - シンボル化対象のipsファイルと同一のビルドUUIDを持つdSYMファイルを取得する必要がある。ipsファイル内に記載された`slice_uuid`の値と以下のコマンドから出力したdSYMファイルのUUIDが一致することを確認する。

```
xcrun dwarfdump --uuid {対象のdSYMファイル}/Contents/Resources/DWARF/{testアプリのproject名}
```
- `BCSymbolMaps`フォルダの`bcsymbolmap`ファイル
    - このファイルはiOSアプリのビットコードを有効にしている場合に必要。今回はビットコード有効の前提で進める

６.  以下のコマンドを実行し、dSYMファイルの難読化を解除する

```
dsymutil --symbol-map bcsymbolmapファイルへのパス dSYMファイルへのパス
```
７. 以下のコマンドを実行し、シンボル化に必要な環境変数を設定

```
export DEVELOPER_DIR="/Applications/Xcode.app/Contents/Developer"
```

８. 以下のコマンドを実行し、ipsファイルをシンボル化する

```
/Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/symbolicatecrash {対象のipsファイルのパス} {対象のdSYMのパス}
```

# 結果

ipsファイルのスタックトレースにエラーが発生したclass名/fucn名が表示される

```text:シンボル化後のipsファイルスタックトレース抜粋
Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   libswiftCore.dylib                  0x00000001b02cc398 _assertionFailure+ 201624 (_:_:file:line:flags:) + 1504
1   libswiftCore.dylib                  0x00000001b02cc398 _assertionFailure+ 201624 (_:_:file:line:flags:) + 1504
2   test                                0x0000000104b3996c @objc ViewController.didTapErrorButton(_:) + 22892 (<compiler-generated>:14)
3   UIKitCore                           0x00000001af1e5ca4 -[UIApplication sendAction:to:from:forEvent:] + 96
```
AWSでAIサービスを使ってみる〜第2回translate編〜

##はじめに
前回AWSでAIサービスを利用するにあたっての導入をさせて頂きました。
今回はAWSのAIサービスのひとつであるTranslateを使用していきます。

##Amazon Translateとは
Translateを使うとテキスト(文字列)を別の言語に翻訳することができます。

##テキストを翻訳してみる
それでは早速テキストを翻訳してみましょう。


```trans_text_ja.py
#boto3をインポート
import boto3
translate = boto3.client('translate')
text = '昨日のご飯は美味しかった。'

#翻訳
result = translate.translate_text(
    Text=text, SourceLanguageCode='ja', TargetLanguageCode='en')
print(result['TranslatedText'])
```

ターミナル上でtrans_text_ja.pyを実行



```
python trans_text_ja.py
```

実行すると次のような翻訳されたテキストが表示される。


```
Yesterday's dinner was delicious
```

##翻訳先の言語を指定する
```trans_text_en.py
#boto3をインポート
import boto3
translate = boto3.client('translate')
text = "Today's sky was blue and so beautiful" 

#翻訳
result = translate.translate_text(
    Text=text, SourceLanguageCode='en', TargetLanguageCode='ja')
print(result['TranslatedText'])
```

ターミナル上でtrans_text_en.pyを実行

```
python trans_text_en.py
```

実行すると次のような翻訳されたテキストが表示される。


```
今日の空は青くてとても綺麗でした。
```

##CSVファイルを翻訳してみる
pythonの実行ファイル


```trans_csv.py
import boto3
import csv
translate = boto3.client('translate', 'us-east-2')
with open('trans_csv_in.csv', 'r', encoding='utf-8') as file_in:
  with open('trans_csv_out.csv', 'w', encoding='utf-8', newline='') as file_out:
    writer = csv.writer(file_out)
    for row in csv.reader(file_in):
      result = translate.translate_text(
        Text=row[2],
        SourceLanguageCode='auto', TargetLanguageCode='ja')
      row[2] = result['TranslatedText']
      writer.writerow(row)
```


```trans_csv_in.csv
20210701,"Nosuke","Hello Nosuke! What happened yesterday? "
20210702,"Nöskey","Eigentlich habe ich Shuzo Matsuoka gestern gesehen"
20210703,"Nosuk","Pour de vrai? C'est pour ça qu'il faisait chaud hier! "
20210704,"Noskki","Su pasión cambia la temperatura!"
```

```trans_csv_out.csv
20210701,Nosuke,こんにちは之助！昨日何が起きたの？ 
20210702,Nöskey,実は昨日松岡修三を見て
20210703,Nosuk,本当に？だから昨日は暑かった！ 
20210704,Noskki,彼の情熱は温度を変える
```


##まとめ
やはり松岡修造は熱かった。

いかがでしたか、pythonでのAIプログラミングの実装で翻訳のプログラムをpythonでやってみました。
AWS内でboto3を用いて、こんなに手軽に翻訳プログラミングができるなんて素晴らしいですね。
次回は別の機能を紹介させて頂きます。

##引用元
[AWSでつくるAIプログラミング入門](https://www.amazon.co.jp/AWS%E3%81%A7%E3%81%A4%E3%81%8F%E3%82%8B-AI%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E5%85%A5%E9%96%80-%E6%9D%BE%E6%B5%A6-%E5%81%A5%E4%B8%80%E9%83%8E/dp/4798059056)
pythonプログラムをdaemon化してサーバーで定期実行

# pythonプログラムをdaemon化して定期実行

crontabでやりたかったのですが、躓いてしまったので、ググってみるとなんと
pythonプログラムをdaemon化⇒定期実行できる！ということで。
自分メモ

## pip install 
以下のコマンドでpython-daemonモジュールをインストールします。

```
pip install python-daemon
```

## 最終的なソース

```
import pymsteams
import time
import schedule
import daemon
import sys


def good_morning():
 myTeamsMessage = pymsteams.connectorcard("{Teams Incoming Webhook URL}")
 myTeamsMessage.title("hogehoge")
 myTeamsMessage.text("fugafuga")
 myTeamsMessage.send()

//　毎日朝9時に"good_morning()"メソッドを実行する、の意
schedule.every().day.at("09:00").do(good_morning)
dc = daemon.DaemonContext(stdout=sys.stdout)

with dc:
 while True:
  schedule.run_pending()
  time.sleep(1)
```

## PGの止め方

```
$ ps -aux | grep {動かしたpythonファイル名}
$ kill {process番号}
```

## まとめ

馴染みのあるプログラミングで、サーバーで定期実行できるのは 　
いいですね！
PowerAutomateでオブジェクト配列のプロパティの値をjoinする

#概要
Power Automateで以下のようなオブジェクト配列があったとき、指定のプロパティの値をカンマ区切りなどで結合する方法です(join)


例えば以下のようなもの。
SharePointのユーザー型のフィールドで複数値可としていると、以下のような値が格納されています。
フィールドの値の中身を確認するには「作成」アクションを使って確認します。
※参考

https://qiita.com/yamad365/items/8922474d5aae94937018

```JSON:
[
    {
      "@odata.type": "#Microsoft.Azure.Connectors.SharePoint.SPListExpandedUser",
      "Claims": "i:0#.f|membership|user1@tenant.onmicrosoft.com",
      "DisplayName": "Tomioka",
      "Email": "user1@tenant.onmicrosoft.com",
      "以下":"略"
    },
    {
      "@odata.type": "#Microsoft.Azure.Connectors.SharePoint.SPListExpandedUser",
      "Claims": "i:0#.f|membership|user2@tenant.onmicrosoft.com",
      "DisplayName": "Takanashi",
      "Email": "user2@tenant.onmicrosoft.com",
      "以下":"略"
    }
]
```


そこからEmailプロパティの値であるメールアドレスを抜き出し、
以下のように;区切りで文字列を結合します。

```
user1@tenant.onmicrosoft.com;user2@tenant.onmicrosoft.com
```

使いどころの例です。
承認アクション(Approvals)で、承認者が複数ある場合はメールアドレスを;区切りで入力する必要があります。
担当者には先ほどの;区切りのメールアドレスが入ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293667/5b66687e-8b9b-48ed-e0a1-266d07c6c9c3.png)


#方法1 データ操作を使った方法

以下のような2アクションを使います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293667/c771bef4-fac0-f258-85e7-1cc6af0e5b12.png)

**①選択アクション**

まず選択アクションで「開始」部分にオブジェクト配列が入ったフィールドを設定。
今回の場合はSharePointで用意したユーザー列です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293667/af515fda-ecd3-8d7f-3f71-66e5eaf9306b.png)

次に、以下アイコンの「マップをテキストモードに切り替え」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293667/e7ea4f61-fe42-2fde-1e44-5991b3faa74b.png)

「マップ」にプロパティを設定します。
今回の場合はSharePointのユーザー列 Emailです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293667/fe54d25d-c587-d899-8f22-1220b106fcd3.png)

これで以下のような文字列の配列になります。
オブジェクト配列から任意のプロパティの値をセレクトして新しい配列/又はオブジェクト配列にするアクションですね。

```JSON
[
    "user1@tenant.onmicrosoft.com",
    "user2@tenant.onmicrosoft.com"
]
```
<br>

**②結合アクション**
あとは配列をカンマ区切りで結合するだけです。

結合アクションで「結合する配列」に先ほどの出力を。
「次を使用して結合」には区切り文字、今回の場合;を入力します。
表示は「結合」ですがアクション一覧画面では「参加」となっているこいつです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293667/f664e8e4-1e42-5e5a-9fb3-eac16f374b31.png)
※join関数でも可


#方法2 変数とApply to eachを使った方法

そのまんまです。
まず文字列変数を初期化。
次に文字列変数への追加で、取得したいプロパティを設定。今回の場合はSharePointユーザー列のEmailです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293667/529991ef-7753-ded0-52b3-3e72e72aff3e.png)


Emailは上記のJSONの通り、配列内の要素であるため参照を設定すると勝手にApply to eachが付きます。
配列の要素を一要素ずつループで参照し、メールアドレス + ; を変数に追加していく流れです。
方法1よりは直感的かもしれません。

デメリットとしては「変数の初期化」アクションがスコープの中に入らないこと、
Apply to eachが若干遅いことでしょうか・・
【Laravelクエリビルダ】曜日別にグループ化して集計する方法

Laravelのクエリビルダで曜日別にグループ化して集計する方法を解説します。

バージョンは6系です。

ブログでLaravel初学者に向けた以下のような記事も以下のような記事も書いています。

https://www.kamome-susume.com/enginner-job-change-site/

##　ゴール

| 曜日 | 合計 |
|:-:|:-:|
| 月  |  200 |
|   火|   300|
|   水|   500|

## 準備

postsテーブルに以下のデータを用意。

| post_id| amount | created_at |
|:-:|:-:|:-:|
|  1 | 100 |2021-06-01 12:23:07 |  
|   2|  200|2021-06-15 15:23:23 |   
|   3| 300 |2021-06-30 16:21:12 |   
|   4| 400|2021-07-21 19:23:32  |   
|   5|  200|2021-07-27 15:04:56 | 

ここから、created_atの曜日をグループ化させて、amountの合計値を算出する。

ちなみに 5つの日付は火曜か水曜になっています。
なので完成は、以下となります。

| 曜日 | 合計 |
|:-:|:-:|
|   火| 合計値  |
|   水|  合計値 |

## 考え方
曜日でグループ化させるために、WEEKDAY関数を使う。
ビューで表示する際に、曜日の配列を用意する。
foreachと曜日の配列をもとに曜日を表示させる。

WEEKDAY関数の他にDAYOFWEEKがあります。違いは、WEEKDAYは月曜始まりで、DAYOFWEEKは日曜始まりな点です。

簡単に言えば、WEEKDAY関数は日付を月曜なら0,火曜なら1を返します。
DAYOFWEEKなら日曜なら0,月曜なら1を返します。

http://bashalog.c-brains.jp/14/03/11-103012.php

## サンプルコード

モデル(Post.php)

```
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;←忘れずに記載する

class Post extends Model
{
    public function getAmountByHour()
    {
      return DB::table('posts')
              ->selectRaw('WEEKDAY(created_at) AS week')
              ->selectRaw('SUM(amount) AS total_amt')
              ->groupBy('week')
              ->get();
    }
}
```
`selectRawはselect(DB::raw)`の省略形。
WEEKDAY関数を使って曜日をグループ化させます。

`WEEKDAY(created_at)`で日付が対応する曜日となって返します。

例えば、2021-06-01は火曜日なので、`->selectRaw('WEEKDAY(created_at) AS week')`は1を返します。

WEEKDAY関数やSUM,COUNT関数などを使う場合は、DB::rawが必要です。

`SUM(amount)`でamountの合計値を出しています。

最後に`groupBy('week')`でグループ化しています。
※`AS week`で`WEEKDAY(created_at)`に別名をつけています。


コントローラー(PostController.php)

```
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Post;←バージョン8系なら use App\Models\Post;

class PostController extends Controller
{
    public function index()
    {
        $this->posts = new Post();

        $results = $this->posts->getAmountByHour();

        return view('posts.index', compact(
            'results',
        ));
    }
}

```

ビュー(index.blade.php)

```
<table>
    <thead>
      <tr>
        <th>曜日</th>
        <th>合計</th>
      </tr>
    </thead>
    <tbody>
    @foreach ($results as $result)
      @php
        $week = [
                '月', //0
                '火', //1
                '水', //2
                '木', //3
                '金', //4
                '土', //5
                '日', //6
                ];
        @endphp
      <tr>
        <td>{{ $week[$result->week] }}</td>
        <td>{{ $result->total_amt }}</td>
      </tr>
    @endforeach
    </tbody>
</table>
```

ビューで曜日の配列を作ります。WEEKDAY関数を使っているので、
0は月曜、1は火曜...となります。配列で対応させるように書いていきましょう。

`$result->week`には、1とか2とか数字が戻り値となります。
なので、`$week[0]`は月曜、`$week[1]`は火曜になるってわけですね。

ブログでLaravel初学者に向けた以下のような記事も以下のような記事も書いています。

https://www.kamome-susume.com/enginner-job-change-site/
型キャスト（Swift)

型キャストとは
---
スーパークラスにたいするサブクラスかどうかの判定やクラスの変換をすることを型キャストという

is
--
スーパークラスとサブクラスの関係をbool型で返してくれる。違っていたらfalseで返してくれる。エラーにはならない。


ダウンキャスト
---
名前の通りでキャスト（型）をダウンさせる。クラスやプロトコルにおいて下位変換するもの

as?
```as?``` は生成されるインスタンスが、スーパークラスに対する対象のサブクラスのインスタンスか分からない時に使う
返り値はオプショナル型になり、ダウンキャストに失敗するとnilを返します。
as!
```as!```はダウンキャストが失敗したときにエラーを吐く。確実にダウンキャストが成功する時に使用したほうが良い。
【MacOS】BigSurに変えたらBluetoothイヤホンからクソデカノイズ飛んできて鼓膜吹き飛んだのでなんとかする👂💥💥💥

## 現象

BigSurのiMacを最近導入して、Bluetoothイヤホンで曲を聴いていたが、曲が変わるたびにノイズが乗るようになった。小さなラップノイズだったのでその時はあまり気にしていなかったが、YouTubeで動画見てたら動画の終わりにクソデカノイズが飛んできて耳が壊れたのでさすがに対策することにした。



## 原因

結論から言うとBluetoothのコーデックがAACになっていて、これがmacとあまり相性が良くないらしい。Mojaveの時はこんなことなかったのにアプデして劣化するのやめてくれや。。。



## 対処法

AACより音質や遅延が悪いようだが今回はSBCに変更する。

ちなみにコーデックはざっくり三種類に分かれており、デフォルトの設定でAACが適用されているみたい。

| コーデックの特徴一覧 |         |         |               |
| -------------------- | ------- | ------- | ------------- |
| **コーデック名**     | **SBC** | **AAC** | **AptX**      |
| 音質                 | 悪い    | 良い    | 良い          |
| 遅延                 | 大きい  | 低遅延  | AACより低遅延 |



Catalinaではoptionを押したままBluetoothのアイコンから詳細を確認できたようだが、BigSurではそれができなくなっているため。Bluetooth Explorerを導入して設定を行う。



Bluetooth ExplorerはAppleの[Developerサイト](https://developer.apple.com/download/more/)からダウンロードできる。Apple IDでログイン後、検索欄に`Bluetooth`と打ち込むと`Addition Tools for Xcode 11.4`がヒットした。

![スクリーンショット 2021-07-12 21.47.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1583578/992386a8-917f-502f-cfae-9da3d259924e.png)




View Detailsから該当のアプリが入っていることを確認できるので、これをダウンロード。

![スクリーンショット 2021-07-12 21.52.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1583578/5d76eff0-5e77-15f6-3781-5ccac18bc6f3.png)




dmgファイルを開き`Hadware`フォルダ内の`Bluetooth Explorer.app`をアプリケーションフォルダに移す。

これでMisson Controlにも表示されるようになったので、これを開く。
![スクリーンショット 2021-07-12 22.00.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1583578/c2b033f5-18bb-8d76-b350-5a992153c715.png)



開くとメニューバーが表示されるので`Tools`→`Audio Options`を選択。`Codecs`の`Enable AAC`からチェックを外し、`Disable AAC`にチェックを入れる。この時接続中のBluetoothイヤホンは接続を一旦解除する。
![スクリーンショット 2021-07-12 22.02.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1583578/7abc2b28-407f-1284-090b-34217937c339.png)


設定した後もう一度イヤホンを接続し、なんでもいいので音を再生する。再生しながら、今度は、`Tools`→`Audio Graphs`を選択。`Active Audio Codec`が`SBC`に変わっていれば設定の変更が反映されていることがわかる。
![スクリーンショット 2021-07-12 22.06.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1583578/cd376512-da2c-b268-d71b-945925461375.png)
やっとノイズが無くなった！😂



## 参考元
- [価格.com - 『MacからのBluetooth接続は注意が必要』 DENON PMA-600NE のクチコミ掲示板](https://bbs.kakaku.com/bbs/K0001182074/SortID=23902187/)
- [【macOS BigSur】AptXは使えない?コーデックの確認と解説を紹介します](https://irilyuu.com/mac-ios/mac/aptx/)
RevertをRevertした時に起きたエラー(備忘録)

git revertとは
=
<b>「既存のコミットを取り消す」</b>コマンドです。
Revertは「コミットを打ち消した」というコミットをpushし、状況を戻すもの。

似たコマンドでは、git resetがあります。
git resetの場合は、そのまま過去に戻しているものです。

本題
=

アプリを作製中、取り組んでいた機能がうまくいかず1つ前の記述を戻そうとしたところ
そのコミットがすでにrevertされていためrevertされたコミットをrevertする必要が出てきました。

なのでまず

```
#ログの確認
$ git log 


#最新のコミットに戻す
$ git reset --hard HEAD
```
で git IDを確認し、その後最新のコミットに戻し



```
$ git revert "コミットID"
```
これで呼び戻し完了！
と思いきや、rails sでアプリを起動しようとしたところ

```
=> Booting Puma
=> Rails 6.0.3.7 application starting in development 
=> Run `rails server --help` for more startup options
warning Integrity check: Top level patterns don't match                        
error Integrity check failed                                                   
error Found 1 errors.                                                          

=====================================================
  Your Yarn packages are out of date!
  Please run `yarn install --check-files` to update.
=====================================================

To disable this check, please change `check_yarn_integrity`
to `false` in your webpacker config file (config/webpacker.yml).


yarn check v1.22.10
info Visit https://yarnpkg.com/en/docs/cli/check for documentation about this command.


Exiting
```
とエラーが出て起動できない笑

なので、エラー文からここだけ読み

```
＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝
Your Yarn packages are out of date!
Please run `yarn install --check-files` to update.
＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝========
```
Please runなので、`yarn install --check-files`を読み込んでね！って言われてます笑

```
$ yarn install --check-files
```
ターミナルに打ち込んでインストールして無事完了:relaxed:
最後に
=
Please run って書いてあったらとりあえず読み込みます笑
.envを使って環境変数を設定できるのね。

### Reactアプリの環境変数はどこで保持したらいいんだ？
ReactでAPIサーバーにアクセスするときに、APIサーバーのオリジンをソースに直書きしてはいけないな、と思って、環境変数として持つにはどうすればいいのだろう？という疑問があって調べてみました。以下が直す前。

```js:sample.js
try {
      const { data } = await axios(
        `http://localhost:3000/path/to/src`,　// ← 直書きしてる
      )
      const hoge = data.hoge
      this.setState({ hoge })
    } catch (err) {
      console.log(err)
    }
```

### 結論
`.env`ファイルをプロジェクトのルートディレクトリ直下に作るだけでOK。

Reactで環境変数を定義するときのお作法として`REACT_APP_`という接頭辞を付ける必要があるみたいです。

```.env:.env
REACT_APP_ORIGIN=http://localhost:3000
```
`process.env.REACT_APP_ORIGIN`でカスタム環境変数にアクセスできる！

```js:sample.js
try {
      const { data } = await axios(
        `${process.env.REACT_APP_ORIGIN}/path/to/src`, // ← 置き換えた
      )
      const hoge = data.hoge
      this.setState({ hoge })
    } catch (err) {
      console.log(err)
    }
```

環境ごとに`.env`ファイルを使い分けることもできるみたいです。開発環境用に`.env.development`、本番環境用に`.env.production`というふうにファイルを分ければ良いようです。npmスクリプトコマンド（`npm start`とか）によって適用される優先順位が変化するようです。詳しくは以下のリンクを参考にしてください。


### 参考リンク
- https://create-react-app.dev/docs/adding-custom-environment-variables/