OmniAICreator/Qiita-1.07M huggingface dataset:
MAMPでローカル作業環境をつくる方法

###1. MAMPをダウンロードする
###2. MAMPWebサイトページ上部のtoolsをクリック
###3. phpMyadminをクリック
###4.任意のデータベースを作成する（この時データベース名など記録しておく）
###5. wordpressを公式HPからダウンロード
###6. アプリケーション＞MAMP＞htdocsの中に解凍したファイルを入れ込む
###7. MAMPの小さいWindowの右上の電源ボタン（スタート）を押す
###8.localhost/wp-adminとアドレスバーに入力し、指示に従って情報を入れる
（この時、データベース名は自分で作成した任意の名前にすること）
###9. アドレスバーにルートを入力すると表示されるようになる
linux における名前解決 ( /etc/hosts 関連)


linux の名前解決に関して調べたので備忘録として

## 結論
ここに全て書いてある

https://debian-handbook.info/browse/ja-JP/stable/sect.hostname-name-service.html

## 簡単に書くと

`/etc/nsswitch.conf` という設定ファイルがあり、その中に `hosts` を設定する部分がある。
以下該当の行のみ抜粋。

```conf
# ホストの名前解決の為にまずはファイルを参照し、失敗したら DNS に問い合わせをする。
hosts: files dns
```

### ファイル
ファイルは `/etc/hosts` ファイル

```conf
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting.  Do not change this entry.
##
127.0.0.1       localhost
```
上記の記述で、 localhost という名前は、 127.0.0.1 というIPアドレスに変換される。

ファイル内に記述がない場合は、DNS に問い合わせする。

### DNS

DNSとは？
>IPアドレスとドメイン名の紐付けをしまっせシステムのこと

https://wa3.i-3-i.info/word1287.html

権威DNSサーバーとか、キャッシュサーバーとかあるので気になる人は調べてみてください。

どのDNSサーバーに問い合わせをするか決めるのが、`/etc/resolv.conf`ファイル

```conf
#
# macOS Notice
#
# This file is not consulted for DNS hostname resolution, address
# resolution, or the DNS query routing mechanism used by most
# processes on this system.
#
# To view the DNS configuration used by this system, use:
#   scutil --dns
#
# SEE ALSO
#   dns-sd(1), scutil(8)
#
# This file is automatically generated.
#
nameserver 8.8.8.8 # GoogleのパブリックDNS
nameserver 8.8.4.4 # GoogleのパブリックDNS
nameserver 1.1.1.1 # Cloudflare(クラウドフレア)がAPNICと提携して維持・運営を行っている
nameserver 1.0.0.1 # Cloudflare(クラウドフレア)がAPNICと提携して維持・運営を行っている
```

https://ja.wikipedia.org/wiki/1.1.1.1


`nsswitch`は多分 `name server switch` で、名前解決するネームサーバーを切り替える(switch)設定ファイルみたいな位置付けかと思います。（多分）

## ちなみに
windows でも同じように設定ができるようです。

https://nekowara.info/archives/14344586.html

mac は `hosts` ファイルや `resolv.conf` はあるが、　`nsswitch.conf` の役割をしているものはなさそう、、、（調べたけど見つからない）

## まとめ
どうやって名前解決しているかわかってよかった！
Googleの検索エンジンにサイトが引っかかるようにする

##○○.xmlのサイトマップをWebサイトを利用して作成
1. https://www.xml-sitemaps.com/
1. 上記サイトの一番上のバーにhttps://から正しいサイトURLを入れる
1. サイトマップを作成し、xml形式のファイルをダウンロードする
1. GoogleSerchConsole＞インデックス＞サイトマップ　より、sitemap.xmlのURLの場所を記述し、サイトの登録を行う
1. FTPを用いてルートの直下に〇〇.xmlのファイルを入れて終了
【C#】WindowsフォームアプリケーションでWordと画面分割するときに手こずった話 - Microsoft.Office.Interop.Word

とあるアプリケーションを開発しているときに2つのウィンドウを同じ大きさでスクリーンに並べようとしたときにハマった時の話です。
もしかしたらプログラミング経験の浅い人だけでなく、ベテランの方でもハマる可能性があるので参考になれば幸いです。

##画面分割イメージ（理想）
メインフォームの大きさと同等の大きさのWordをスクリーン内に並べる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2425930/2283b03b-07a7-2eae-8917-89d0d5a2f8b0.png)

##画面分割イメージ（現実）
Wordの大きさがメインフォームよりも大きくなり、起動位置が大きく右にズレて画面からはみ出る。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2425930/b7fffb2d-6ebc-637e-98c2-2bc9c0d86d1d.png)

##原因
下記のプロパティがpx単位ではなくpoint単位のため。
- objWord.ActiveWindow.Top
- objWord.ActiveWindow.Left
- objWord.ActiveWindow.Width
- objWord.ActiveWindow.Height

point単位のところをpx単位で指定すれば、当然意図したサイズよりも大きくなる。
よってobjWordComs.ActiveWindow.Leftでセットした値以上に右へ配置されて起動され画面からはみ出る。
言わずもがなobjWordComs.ActiveWindow.Heightもまた意図したサイズよりも大きくなる。
###ソースコード
```c#
Rectangle rectangle = Screen.GetWorkingArea(this.FindForm());
this.FindForm().SetBounds(0, 0, this.FindForm().Width, rectangle.Height, BoundsSpecified.All);

Microsoft.Office.Interop.Word.Application objWordComs = new Microsoft.Office.Interop.Word.Application();
objWord.Documents.Open(filePath);
objWord.ActiveWindow.WindowState = Microsoft.Office.Interop.Word.WdWindowState.wdWindowStateNormal;
objWord.ActiveWindow.Top = 0;
objWord.ActiveWindow.Left = Convert.ToInt32(this.FindForm().Width);
objWord.ActiveWindow.Width = Convert.ToInt32((rect.Width - this.FindForm().Width) / 2);
objWord.ActiveWindow.Height = Convert.ToInt32(rect.Height);
```

##解決策
下記のプロパティに値をセットする際にPixelsToPointsメソッドをかませてからセットする。
- objWord.ActiveWindow.Top
- objWord.ActiveWindow.Left
- objWord.ActiveWindow.Width
- objWord.ActiveWindow.Height
###ソースコード

```c#
Rectangle rectangle = Screen.GetWorkingArea(this.FindForm());
this.FindForm().SetBounds(0, 0, this.FindForm().Width, rectangle.Height, BoundsSpecified.All);

Microsoft.Office.Interop.Word.Application objWord = new Microsoft.Office.Interop.Word.Application();
objWord.Documents.Open(filePath);
objWord.ActiveWindow.WindowState = Microsoft.Office.Interop.Word.WdWindowState.wdWindowStateNormal;
objWord.ActiveWindow.Top = 0;
objWord.ActiveWindow.Left = Convert.ToInt32(objWord.PixelsToPoints(this.FindForm().Width));
objWord.ActiveWindow.Width = Convert.ToInt32(objWord.PixelsToPoints((rect.Width - this.FindForm().Width) / 2));
objWord.ActiveWindow.Height = Convert.ToInt32(objWord.PixelsToPoints(rect.Height));
```
Tkinterでクリックした部分をわかるようにしてみた

##はじめに

https://qiita.com/dem_kk/items/dec0cb04169d3b19f99f


前回Tkinterを使ってみて、もう少し何かやりたいなと。
せっかくGUIを使うなら、クリックした部分が直感的にわかるとうれしいと思って作ってみました。

:::note warn
物自体は何とかできましたが、結構ごり押しのコードです。
(きれいなコードではないので注意)
:::

##環境
* windows10
* python3.8.10
* pillow8.3.1
* tkinter8.6

##内容
大まかな流れは、
画像を読みこむ⇒クリックする⇒クリックした場所が色で塗られる⇒リセットボタンを押すと最初の状態に戻る

クリックした場所が色で塗られる部分の作成が結構苦戦。。。
本来はスマートにしてみたかったのですが、自分の実力ではどうにもできず。仕方ないので下記のように手数をかけて作成しています。

①元画像に画像を貼り付けて保存
②保存した画像を読み込む
③読み込んだ画像を表示する
④リセット時は読み込んだ画像をフォルダから削除

書いただけでもごり押し感が半端ない~~とりあえずできたらこっちの勝ちだと思っている~~

```python
import tkinter
import tkinter.ttk
from PIL import Image, ImageTk, ImageDraw
import os

class Application(tkinter.Frame):
    def __init__(self, master=None):
        super().__init__(master)
        self.master = master
        self.master.title('画面')
        self.pack()
        self.create_widgets()

    def create_widgets(self):
        # ボタン
        self.original_button = tkinter.ttk.Button(self, text='リセット')
        self.original_button.grid(row=0, column=1)
        self.original_button.bind('<Button-1>', make_original)
        
        # canvas
        self.test_canvas = tkinter.Canvas(self, width=original_image.width, height=original_image.height)
        self.test_canvas.grid(row=0, column=0, rowspan=3)

        # canvasに初期画像を表示
        self.test_canvas.photo = ImageTk.PhotoImage(original_image)
        self.image_on_canvas = self.test_canvas.create_image(0, 0, anchor='nw', image=self.test_canvas.photo)
        
        #クリックで座標取得
        self.test_canvas.bind("<ButtonPress-1>", ButtonPress)
    
                
def make_original(event):
    os.remove('draw.png')
    set_image(event, original_image)

def ButtonPress(event):        
    a = event.x
    b = event.y
    a_m = a-5
    b_p = b+5
    a_p = a+5
    b_m = b-5
    draw = original_image.copy()
    draw2 = ImageDraw.Draw(draw)
    draw2.rectangle(((a_m, b_p), (a_p, b_m)), fill=(0, 0, 255), outline='white',  width=2)
    draw.save('draw.png')
    draw_image = Image.open('draw.png')
    set_image(event, draw_image)
    print("clicked at ", event.x, event.y) 

def set_image(event, img):
    # canvasの書き換え
    app.test_canvas.photo = ImageTk.PhotoImage(img)
    app.test_canvas.itemconfig(app.image_on_canvas, image=app.test_canvas.photo)

# 画像ファイル読み込み
original_image = Image.open('kikagaku.png')

# アプリケーション起動
root = tkinter.Tk()
app = Application(master=root)
app.mainloop()
```
![画面-2021-12-27-14-18-18.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1259951/1abcbb4a-6bd8-43c0-4f27-6e6bf0a17043.gif)

一応やりたいことは何とかできました(ここには出ていないですが、コンソール画面で座標自体も出ています)。

##まとめ
ごり押しだけど目標達成。
これを応用してまた何か作りたいです。

##参照
https://water2litter.net/rum/post/python_tkinter_canvas_exchange_image/
https://ti-nspire.hatenablog.com/entry/2018/01/18/130346
【Scala, Java】LocalDateから月の第何週かを取得する

`java.time.temporal.WeekFields#weekOfMonth` を使うことで、指定日が月の第何週にあたるかを取得できる。
週の始まりを日曜日とするか月曜日とするかも指定できる。

このカレンダーを例とする。

```
𝙳𝙴𝙲𝙴𝙼𝙱𝙴𝚁 – 𝟸𝟶𝟸𝟷
𝚂𝚞|𝙼𝚘|𝚃𝚞|𝚆𝚎|𝚃𝚑|𝙵𝚛|𝚂𝚊
𝚡𝚡|𝚡𝚡|𝚡𝚡|𝟶𝟷|𝟶𝟸|𝟶𝟹|𝟶𝟺
𝟶𝟻|𝟶𝟼|𝟶𝟽|𝟶𝟾|𝟶𝟿|𝟷𝟶|𝟷𝟷
𝟷𝟸|𝟷𝟹|𝟷𝟺|𝟷𝟻|𝟷𝟼|𝟷𝟽|𝟷𝟾
𝟷𝟿|𝟸𝟶|𝟸𝟷|𝟸𝟸|𝟸𝟹|𝟸𝟺|𝟸𝟻
𝟸𝟼|𝟸𝟽|𝟸𝟾|𝟸𝟿|𝟹𝟶|𝟹𝟷|𝚡𝚡
```

カレンダーはこちらを使わせていただきました。
https://qwerty.dev/calendar-generator/

## 実装

### 週の始まりを日曜日とするなら

```scala
val date = LocalDate.of(2021, 12, 26) 
val weekField = WeekFields.SUNDAY_START.weekOfMonth()

println(date.get(weekField)) // -> 5
```

### 週の始まりを月曜日とするなら

```scala
val date = LocalDate.of(2021, 12, 26)
val weekFieldMondayStart = WeekFields.of(DayOfWeek.MONDAY, 1).weekOfMonth()

println(date.get(weekFieldMondayStart)) // -> 4
```

## 解説

ここで使っている `WeekFields.of()` は第1引数に「週の始まりとする曜日」、第2引数に「何日以上あれば最初の週とみなすか」を指定する。
`WeekFields.of(DayOfWeek.MONDAY, 1)` なら週の始まりは月曜日、1日以上あれば最初の週とする。
`WeekFields.SUNDAY_START` は `WeekFields` に定義されている定数で、内部的には `WeekFields.of(DayOfWeek.SUNDAY, 1)` 。

### 「何日以上あれば最初の週とみなすか」ってどういうこと？

「何日以上あれば最初の週とみなすか」が指定できるのは、ISO-8601のような定義に対応するためらしい。

日時のフォーマットを定義しているISO-8601では、**4日以上ある週じゃないと最初の週と見なされない**。(ちなみにISO-8601では週の始まりは月曜日)

例を挙げる。
2021年12月1日は水曜日なので、日曜日までに5日ある。よって2021年12月1日は第1週である。
2022年1月1日は土曜日なので、日曜日までに2日しかない。この場合、**2022年1月3日(月)からが第1週となる**。

実際にISO-8601の定義に従った `WeekFields` で確認してみる。

```scala
val date = LocalDate.of(2022, 1, 1)
val weekField = WeekFields.of(DayOfWeek.MONDAY, 4).weekOfMonth() // ISO-8601の定義

println(date.get(weekField)) // -> 0
```

このように、最初の週以前の日付は第0週として扱われる。
(なお、`WeekFields` にはISO-8601に合わせた定数である `ISO` が用意されているので、自分でコーディングする必要はない)
Windows環境にbazelを導入してみた

##はじめに
bazelが必要になったが日本語でのインストール方法の紹介が自分が調べた範囲ではLinax環境での記事のみでした。
そのため、Windows環境でのインストール方法について備忘録も兼ねてまとめてみました。

##そもそもbazelって何
bazelはmakeコマンドと似たようなことを行えるオープンソースのビルドツールです。対応言語はJava、C ++、Android、iOS、Go、およびその他のさまざまな言語プラットフォームです。
公式サイトによると、「高度なローカルおよび分散キャッシング、最適化された依存関係分析、および並列実行により、高速でインクリメンタルなビルドが可能になる」と記載されています。

[bazel公式サイト](https://bazel.build/)

##環境
64bit windows10 バージョン21H1 

##インストール
まずはvisualstudioをインストールします。インストールしてない方は以下のリンクからインストールしてください。
https://visualstudio.microsoft.com/ja/

visualstudioのインストールが終わったらbazelのインストールをします。

https://github.com/bazelbuild/bazel/releases

上記のリンクからインストールしたいバージョンのbazelを選択しましょう。

例 ver6.0.0をインストールする場合
![choise.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2423332/3a79ec07-b6c8-f732-7e26-cc7a23531792.png)
インストールが終わったらコマンドプロンプトやPowerShellから簡単にアクセスできるように一工夫します。
##一工夫
インストールしたbazel-（選択したbazelのバージョン）-windows-x86_64.exeファイルをC:\Program Firesにbazel(名前は何でも良いが今回はbazelにする)フォルダを作り、入れてあげましょう。
bazelフォルダのパス 
```C:\Program Files\bazel```
bazelフォルダに入れて上げたbazel-（選択したbazelのバージョン）-windows-x86_64.exeファイルをbazel.exeファイルに変更してあげましょう。
このbazel.exeファイルに対してパスを通してあげます。公式サイトではコマンドでパスを通してあげていますが、通してあげたパスを永続化したいのでシステム環境変数をシステムのプロパティから変更しましょう。

まずはシステムのプロパティからシステム環境変数を開きます。
![cange1step.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2423332/89b25490-3ed2-7c01-ff28-4e0da0f97532.png)

Pathを選択して編集をクリックすると以下の画面に移動します。

![change2step.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2423332/a9147f68-1b82-b82f-a569-af4887c45eee.png)
この画面で新規をクリックし、bazel.exeのあるフォルダのパスを追加します。

以上の作業が終了したら、コマンドプロンプトで
```bazel version```
を入力して選択したbazelのバージョンが表示されればbazelのインストールは終了です。お疲れ様でした。

##終わりに
はじめての記事です。間違いがあればコメントでこっそりと教えてください。
この記事が誰かのお役に立てれば幸いです。
数字を大切にしてあげてますか？

<h1>はじめに</h1>
数字と聞いてアレルギー反応を示した方、ご安心ください。難しい分析の話等はいたしません。今回は考え方の話のみですので、肩の力を抜いてお読みいただければと思います。

<h1>"数字"を大切にしてますか？</h1>
お仕事をする上で誰しも一度位は<b>数字</b>の大事さを耳にすることがあると思います。そんなお仕事には切っても切り離せないこの<b>数字</b>。皆様は本当にこの<b>数字</b>を大切に扱っていますか…？

<h1>数字を使う意味</h1>
皆様は<b>数字</b>をどのように利用してますか？お仕事の数だけ使いみちはあると思いますが、一般的には以下のような使い方なのではないかな？と考えてます。

<b>「解決したい問題に対して数字を根拠に仮説をたてたり、数字をつかって目標と現状の差を理解したりすること。」</b>
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2174644/ef9220b3-1d9c-5311-4a15-0a8602c91275.png" alt="image" width="50%" height="50%">
いや…そんな当たり前のことドヤられても…。なんて思った方が多数かと思います。それはそうですね。ごめんなさい。
しかし改めてよく考えて見てください。本当にきちんと数字を元に<b>予測や原因の究明</b>を行えていますか？意外と<b>数字を眺めるだけ</b>、あるいは<b>数字を羅列するだけ</b>で満足してはいませんか？

<h1>身近過ぎて忘れがちな大切な存在</h1>
上のテキストを読んでドキッとした方もいるのではないでしょうか？数字をきれいに並べる。数字を抽出する。筆者の経験ですが意外とこれで満足する人が少なくありません。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2174644/d56290be-ad12-bbd3-29e4-2bd3c58f3ab6.png" alt="image" width="20%" height="20%"><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2174644/ef12f308-b17f-6b9d-537a-8e05998cfc15.jpeg" alt="image" width="30%" height="30%">
かくいう私も過去に日々の様々なデータを集計していく中で、数字を集計してまとめるという作業が目的になってしまい、いざ上長に問題点や改善点の提案を要求された時、きちんと答えられなかった苦い経験がありました。
お仕事の忙しさにかまけて手段と目的が入れ替わってしまった典型ってやつですね…。

そんな私のような失敗をしないためにも、身近にあるこの数字の大切さをしっかり理解し、いつまでも大切に扱ってあげてください。

<h1>私の数字との付き合い方</h1>
あくまで一例になりますが私の数字の使い方を紹介します。まだ仲良くなれていない人はよろしければ参考にしてみてください。

<b>1. 効果測定をする</b>
自分が立てた数値化した目標と現実結果として出た数字を比較しその差を確認します。目標値との乖離を見えるようにすることで、今自分が持つ問題点に気がつけるかもしれません。
ちなみにこれを意識すると事前に目標を建てることができ、成長意欲や達成意欲を持ってお仕事ができるのでオススメです。

<b>2. 浮かび上がった問題の原因を究明する</b>
仮に「1」で問題が出た場合、数字を使うことで問題の原因となる部分を見つけられるかもしれません。
今回は例として目標の売上に到達しなかった問題を解決したいとしましょう。
当たり前ですが売上の数字を見るだけでは問題の原因となる部分を見つけることはできません。この場合、売上を支える数字、例えば購入者数や購入された商品の数などに改善できる部分が無いかを確認することで原因解決の為の仮説を立てることが可能になります。
なおこの考え方に慣れてくることで自分がどんな数字に興味・関心事があるかもわかってきます。

<b>3. 仮説検証をする</b>
最後は数字を直接使うわけではないですが、数字を元に導き出した仮説から問題解決の為の施策を考えます。もちろんこの施策に効果があるかを調査することも必要になるため、「3」が終わったらまた「1」に戻って効果測定をしてみましょう。

絵にすると以下のような感じでしょうか。よろしければ参考にしてみてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2174644/a1060c18-1e1d-d9c6-59e5-d329338a7da4.png)

<h1>まとめ</h1>
数字はお仕事をする上で非常に大事なものです。しかし、数字は出力するだけ、並べるだけでは意味を成しません。今回のお話に心当たりのある人は、数字を使う意味を今一度見直してみてはいかがでしょうか。
良いDockerfileの書き方まとめ

## はじめに
Dockerを使う時にイメージビルド時間がかかることに気づき、作成されたコンテイナーが本当に良いかみたいな疑問がありますか。
この度、セキュリティーの攻撃を防ぎ、Dockerのイメージビルドプロセスを最適化する方法を調べてみます。

## 良いDockerfileを書くためのベストプラクティス
### 1. /.dockerignoreファイルを使う
最善の方法は、Dockerfileを空のディレクトリ内に配置し、Dockerイメージの構築に必要なアプリケーションファイルと構成ファイルのみを追加することです。
ビルドのパフォーマンスを向上させるために、.dockerignoreファイルをそのディレクトリに追加することで、ファイルとディレクトリを除外することもできます。
### 2. 不要なパッケージをインストールしないように
Dockerイメージはできれば、無駄が無い状態を維持する必要です。移植性、ビルド時間が減ったり、複雑にならなくなったり、コンテイナーのサイズを小さくすることが出来ます。 たとえば、ほとんどの場合、コンテナにテキストエディタをインストールする必要はありません。 必須ではないアプリケーションやサービスをインストールしないでください。
### 3. レイヤー数を最小化する
Dockerfileの各コマンドは、Dockerイメージに該当のレイヤーを追加します。 コマンドとレイヤーの数は、ビルドのパフォーマンスと時間に最終的に影響するため、最小限に抑える必要があります。
### 4. イメージのバージョンを指定する。

Dockerイメージを使用する際にタグを指定しなかった場合には`latest`タグが自動的に利用されます。ただ、`latest`タグに関して、問題があります。基本的には`latest`タグを指定したら、Docker のイメージリポジトリからの最新イメージバージョンに使用されますが、ローカルでキャッシュされるため、タグの更新を忘れていると差異が発生する可能性があります。
また、latestタグを指定する時にイメージのバージョンが変わる可能性があるため、イメージをリビルドすると不具合が生じる可能性があります。latestタグを利用して、イメージバージョンなどの指定的なタグを利用した方が良いです。


### 5. コマンドの結合：
イメージをビルドするとき、Dockerfileの各コマンドでイメージに1つのレイヤーを追加されます。
コマンドを組み合わせると、レイヤー数が減り、イメージのサイズが小さくなります。 コマンド組み合わせの一般的な例はRUNコマンドです。 複数のRUNコマンドを使用する代わりに、各コマンドを「&&」で組み合わせたほうが良いです。

```docker
RUN apt-get update
RUN apt-get install -y python3-pip
RUN cd ~
# Can be converted to
RUN apt-get update && apt-get install -y python3-pip && cd ~
```

### 6. マルチステージビルドを使用する。
マルチステージを使用することは、アプリケーションをデプロイするための推奨される方法です。

これにより、実行中のコンテナーでビルドの依存関係を使用する必要がなくなります。

依存関係を持つ一意のビルドイメージを使用してアプリケーションをビルドし、コンパイルされたバイナリを別のコンテナイメージに移動して実行できます。
マルチステージビルドには、最終的なイメージに必要な最小限のバイナリと依存関係のみが含まれ、中間コンテイナーやファイルなどをビルドする必要がありませんです。

```docker
# Stage 0, "build-stage", based on Node.js, to build and compile the frontend
FROM node:13.12.0 as build-stage
WORKDIR /app
COPY package*.json /app/
RUN npm install
COPY ./ /app/
RUN npm run build
# Stage 1, based on Nginx, to have only the compiled app, ready for production with Nginx
FROM nginx:1.15
COPY --from=build-stage /app/build/ /usr/share/nginx/html
```

上記では、Dockerfileには2つの別々の段階があります。
一つ目のステージは、Nodeイメージからノードアプリケーションをビルドするために使用されます。
二つ目のステージは、`build-stage`をビルドイメージから最終的にアプリケーションにサービスを提供するWebサーバー（Nginx）イメージにコピーするために使用されます。
###参考した内容
- https://medium.com/@BeNitinAgarwal/best-practices-for-working-with-dockerfiles-fb2d22b78186
- https://medium.com/swlh/dockerfile-best-practices-for-building-an-image-6120e512b1fa
- https://matsuand.github.io/docs.docker.jp.onthefly/develop/develop-images/multistage-build/
- https://sysdig.com/blog/dockerfile-best-practices/
PopupMenu の要素を動的に追加する

わざわざ記事にすることでもないかもしれないですが、 PopupMenu を使った際に menu リソース以外からも要素を作成する方法の備忘録を自分ように残します。

## やり方
以下のコードの `popupMenu.menu.add("文字列")` を行うことで好きな数だけ要素を増やすことができます。

```
val popupMenu = PopupMenu(this, target)
popupMenu.menu.add("テスト1")
popupMenu.menu.add("テスト2")
popupMenu.menu.add("テスト3")
popupMenu.show()
```
DaVinci Resolve 17.4.3 無料版 入れてみた！

# DaVinci Resolve(ダビンチリゾルブ) って？
DaVinci Resolveは、動画編集用ソフトのことです。
私最近、動画編集をしたい！と思ったんですが、たくさん種類がありすぎて本当に迷っています。
ただまぁ、迷う時間よりとりあえず手を動かしてみよう、ということで
無料版で使える！というこちらのソフトを入れて使ってみたいと思います。

## 入れてみる！
https://www.blackmagicdesign.com/jp/products/davinciresolve/
上記の公式サイトから無料版を選択してダウンロードを行います。
最初に個人情報の入力を求められてから、ダウンロード画面が表示されます。

ダウンロードが終わり、exeを実行すると下図の画面が出てきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397779/bb90158b-e1d8-ffb3-c9ef-5989b233cb68.png)

今回私は、初期のチェックのままインストールを開始しました。
そのあとも初期のままカチカチと進めていきます。

インストールが完了するとソフトが起動して、初期セットアップ画面がでてきます。
こちらは、画質など聞かれたのでベターなものを選びました。


初期セットアップが終わるとはい、ドン！！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397779/5fc2dea9-e6f5-5e59-289b-ad4c4119e46d.png)

動画編集ソフトを全く使ったことのない自分のイメージしてたかっこいい画面が出てきました。


## 日本語設定にする！
英語設定だったので、とりあえず日本語設定に切り替えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397779/a3646cba-a632-f3a3-f032-d884a6110366.png)

Davinci Resolve ＞ Preferencesを選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397779/5082ce2d-0a1a-cd5b-f683-538c0ccf54cb.png)

User ＞ UI settings ＞ Language ＞ 日本語　を選択
このあと、いったんソフトだけ再起動すると日本語表示になりました。


## プロジェクトを作る！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397779/84c53224-2184-3a1a-abdb-9ffd0539404e.png)

ソフトを立ち上げると上記のような表示になるので
Untitled Project をクリックすると下図のようになります編集画面が出ます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397779/516efbc4-752c-a516-a05e-f245ed8ac36c.png)

ファイル から 新規プロジェクト　を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397779/ba7c7a38-556d-60bd-65bd-c430a0f755e4.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397779/cfb95ff1-31c8-c546-b50f-c46f9cd08aa2.png)

プロジェクト名を入力し、作成をした画面が上図です。
今回はProject１としました。


## 動画取り込みしてみる！

ファイル ＞ 読み込み ＞ メディア から読み込みたい動画を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397779/a4a5bbb1-fb01-69c2-a56f-c5ace58a354e.png)

取り込みを行うと、ファイル形式が一致していません･･･的な表示が出ますので
変更しないを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397779/03eb2ea2-4db9-685d-dde7-fd15f4308935.png)

するとメディアプールに動画が入ります。
（試し撮りした動画なのでグレーで塗りつぶしてます）


各機能については、別途投稿しようか検討中です。
なにせ、文字に起こせるような作業量ではなさそうなので･･･

今回は、ソフトを入れてみてプロジェクトを立ち上げるところまでで終わります！
【Android】 Flipperで簡単にAPIモック環境を作成する

## はじめに
Facebookが作ってる[Flipper](https://fbflipper.com/)というデバッグツールで、簡単にAPIモック環境を作成することができたのでまとめておきます

Flipper導入は公式サイトを参考にNetwork Pluginを設定するとネットワークのトラフィックが参照できるようになります。

- Flipper
 - https://fbflipper.com/docs/getting-started/android-native/
- Network Plugin
   - https://fbflipper.com/docs/setup/plugins/network/

## モックサポートを有効にする
FlipperのNetwork PluginにはOkhttp統合用のFlipperOkhttpInterceptorが用意されています。
そのFlipperOkhttpInterceptorには、isMockResponseSupportedというパラメータがあり、デフォルトだと無効(false)なのですが、こちらを有効（true）に設定することでサーバーレスポンスをモックすることが可能になります。

```
  fun createOkHttpClient(networkFlipperPlugin: NetworkFlipperPlugin): OkHttpClient = OkHttpClient.Builder()
    .addInterceptor(FlipperOkhttpInterceptor(networkFlipperPlugin, true))
    .build()
```
このとき、ネットワークインターセプター（addNetworkInterceptor）ではなくアプリケーションインターセプター（addInterceptor）に登録する必要があります

これで、APIをモックすることができるようになりました。

Flipperアプリを起動するとNetworkにMockボタンが有効になっていると思います（表示されない場合、Flipperアプリを再起動で確認してください）
![flipper_network_mock_showing.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10675/7ae37b54-8246-10a2-141e-4299a2ef74cf.png)

## APIモックを設定する
MockボタンからAPIを指定してレスポンスデータなどを設定することが可能です。
① Add Routeより新規の条件を設定します
※ 前画面で任意のAPIを選択した状態で、Copy Selected CallsするとレスポンスデータなどをCopyした状態でモック用のレスポンスを作成することができます
②  httpリクエストメソッドを設定します
③ URLを設定します
④ レスポンスデータを設定します
※ [httpステータスコード](https://ja.wikipedia.org/wiki/HTTP%E3%82%B9%E3%83%86%E3%83%BC%E3%82%BF%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%89)も変更できる（下記画像の200の部分）のでエラーパターンなどをテストしたい場合には変更することも可能です

![flipper_network_mock_responses.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10675/35c6d41e-7595-53bf-170d-da15391f246a.png)

## APIモックを確認する
リクエストがモックされている場合、オレンジ色になっていれば成功です。

![flipper_network_mocked_response.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10675/3160bb76-2ff1-f66a-c6a2-9d48b2c6e6a3.png)

## さいごに
APIがまだ完成してなかったりレスポンスを変更したい場合、Charlesなどでも同じことはできますが、いつも使っているデバッグツールでできると便利ですよね

## 参考
https://medium.com/mateedevs/android-simple-network-mocking-with-flipper-8e7304ec7be6
Expo SDK44で新しいJSX Transformが使えるようになった

[Expo SDK44のアナウンスブログ](https://blog.expo.dev/expo-sdk-44-4c4b8306584a)に以下のように書いてあります。

> **React 17 JSX transform now enabled by default**: this means that you don’t need to write `import React from 'react';` at the top of every source file that uses JSX. [Learn more about the transform](https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html) and [how you can disable it](https://github.com/expo/expo/blob/master/packages/babel-preset-expo/README.md#jsxruntime), if you prefer.

これで、React 17のWeb開発でできていたimport文の省略がExpo開発でもできるようになりました。一般的には特に大したメリットはないかもしれませんが、とある[自分のプロジェクト](https://github.com/dai-shi/katachidraw)では、WebのコードとExpoのコードが共通であるため、同じように書けることはメリットでした。

仕事のExpoプロジェクトでもSDK44にアップグレードして、`import React`の撲滅を推進しようと思います。すっきりする以外のメリットはないと思いますが。

余談ですが、`react/jsx-runtime`を個別のパッケージで提供してくれないかなと思ったことがあります。[jotai-jsx](https://github.com/dai-shi/jotai-jsx)という実験プロジェクトがありまして、reactは不要でjsx-runtimeだけを使いたいのですが、今だとreactが依存パッケージに入ってしまいます。ただ、バンドル時には不要なコードは消えると思うので、気持ちの問題だけかもしれません。
laravel8 vue3 scss を読み込めない

vue3をやっていたら scss を読み込めない。
laravel を使って vue3 をやる場合は少し特殊なのか？


```/resources/css/app.scss

body {
    background-color: pink !important;
}

```




```vue.blade.php

<link href="{{ mix('css/app.css') }}" rel="stylesheet">

```

```webpack.min.js

const mix = require('laravel-mix');

/*
 |--------------------------------------------------------------------------
 | Mix Asset Management
 |--------------------------------------------------------------------------
 |
 | Mix provides a clean, fluent API for defining some Webpack build steps
 | for your Laravel applications. By default, we are compiling the CSS
 | file for the application as well as bundling up all the JS files.
 |
 */

//ここのsass ってのが重要
mix.js('resources/js/app.js', 'public/js').vue().version()
    .sass('resources/css/app.scss', 'public/css', [
]);


```


ちなみに

npm run prod をするとcssもjsも自動で圧縮される。

以上
Railsのインスタンスメソッドとクラスメソッドの違い

## 概要
Ruby on Railsにおいて__インスタンスメソッド__と__クラスメソッド__についての知識が曖昧だったため
備忘録としてアウトプットします。

## インスタンスメソッドとは
####結論
インスタンスメソッドとは、あるクラスから生成されたインスタンスに対して呼び出すことのできるメソッドです。
#### 使用用途例
例えば、Userクラスにおいて生成されたuserが成年か未成年かを判定したい場合など。
#### コード例

```ruby
class User
  def adult  # インスタンスメソッド
    self.age >= 20 ? '成人' : '未成年'  # ２０歳以上なら'adult', 20歳未満なら'child'を返す処理
  end
end

user = User.new(name: '田中', age: 23)
user.adult #=> '成人' 
```

## クラスメソッドとは
#### 結論
クラスメソッドとは、クラス全体に対して何か処理を行う場合に使用するメソッドです。
#### 使用用途例
例えば、Userクラスの中から20歳以上のuserを取得する場合など
#### コード例

```ruby
class User
  def self.adult #クラスメソッドの定義は'self'をつける   *クラス名（ここではUser）でも可
    user = where('age >= 20')
  end
end

users = User.adult #=> userに20歳以上のuserが格納される
```

## 参考文献
[【Rails】クラスメソッドとインスタンスメソッドの違いと、使い分けについて](https://toarurecipes.com/class-or-instance-method/)
非エンジニアでも3分でChrome拡張を作ってQOLを上げる

# 背景
楽天市場、便利ですよね。みなさんもよく使われると思います。
我が家でも良く使われています。

https://www.rakuten.co.jp/


### PCで商品を探し、スマホで決済したい
楽天市場には、スマホアプリで決済すると獲得ポイントが+0.5倍になるというキャンペーンがあります。

こちらのキャンペーン、商品が見やすいからとPCでショッピングをしていると、ついつい決済までそのまま行ってしまい、
購入完了後の画面を見てから「スマホアプリで購入すればよかった〜〜！！！」となりがちです。

# それ、拡張機能でどうにかなるのでは？
以前からChrome拡張機能を作ってみたいと思っていたため、ぱぱっと作ってみることにしました。

要件は以下です。

- 楽天市場でカートを表示した際、「スマホアプリで購入するように！！」と促すメッセージを表示する
- なるべく気付きやすい形が良い
  - メッセージ表示中は注文確定ボタンなどが押せない


# 拡張機能を作っていく

Chrome拡張機能を作るにあたり、必要なファイル構成は以下です。

- content.js   (機能自体のスクリプトを書く）
- manifest.json(拡張機能の設定ファイル)

以下を参考にしました。
https://qiita.com/RyBB/items/32b2a7b879f21b3edefc

それでは作っていきましょう！

### `manifest.json`

```json 
{
  "name": "alertRakuten",
  "version": "1.0.0",
  "manifest_version": 2,
  "description": "楽天市場にて、スマホアプリで決済することを促す機能",
  "content_scripts": [
    {
      "matches": ["https://basket.step.rakuten.co.jp/rms/mall/bs/cartall/*"],
      "js": ["content.js"]
    }
  ]
}
```

上記、適宜書くべきことを書きます。


今回注意すべきは`content_scripts`の部分。
`matches`に、**どのWebページで動作させたいか**を書きます。

`https://basket.step.rakuten.co.jp/rms/mall/bs/cartall/*`  
上記であれば、「`cartall/` まで完全一致のURLであり、それ以降の文字列はなんでも良い」という意味になります。

これで楽天市場のカート画面で動作させることができそうです。

### `content.js`

```javascript
alert('スマホアプリから購入するんですよ〜〜');
```

上記manifest.jsonで記述したURLで発火するスクリプトを記述します。

> 「スマホアプリで購入するように！！」と促すメッセージを表示する
> なるべく気付きやすい形が良い
> メッセージ表示中は注文確定ボタンなどが押せない

今回の用件であれば、js標準のalertで問題なさそうです。

# 実際に動かしてみる

用意するものが揃ったので、実際に動かしてみましょう。

1) 作成したcontent.jsとmanifest.jsonを同じフォルダにまとめる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431852/275ffa7b-0ed3-47b8-d2de-9534da655b3d.png)

2) chrome://extensions/にアクセス
3) デベロッパーモード > ON
4) パッケージ化されていない拡張機能を読み込むを押下し、1で作成したフォルダをアップロード



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431852/255fa4df-0688-c930-0d67-b99ab3755e3a.png)

上記のように、自分のChromeに自作の拡張が読み込まれれば成功です！

### 外部へ公開する場合
今回の拡張機能は個人利用目的のため、Chrome拡張機能ストアに公開しませんが、公開したい方は別途手続きが必要です。


# 動作例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431852/09f64bee-3b0d-fa55-df65-2c2d9399feb7.png)

無事、楽天市場の買い物かごを開いたタイミングでAlertを出すことに成功しました！
これで毎月何かを購入するたびに「スマホで買えばよかった！！」と後悔することがなくなりそうです。

# 編集後記
今回は初めて拡張機能を作ってみました。Chrome上で動作させるまでの手順が全く難しくなく、
特別なドメイン知識も必要としないため、開発に全リソース割くことができて素敵ですね。
また何か作ってみようと思います！

# 参考文献
https://qiita.com/RyBB/items/32b2a7b879f21b3edefc
【Ruby】自己代入演算子「||=」

```ruby
hoge ||= 5
```

「||」演算子の自己代入演算子。**hogeが偽か未定義ならhogeに5を代入する。**
わかりやすく書き直すと↓

```ruby
hoge = hoge || 5
```


hogeが**false,nil以外** → 5を返す
hogeが**false** → hogeに5を代入する
hogeが**nil(未定義)** → hogeに5を代入する

##参考

https://docs.ruby-lang.org/ja/latest/doc/spec=2foperator.html#selfassign
Visual Studio の Git で rebase する

# 前置き

Visual Studio の Git 機能は非常に便利なのですが、rebase がちょっとわかりづらかった（コマンドに対して結果がどうなるのかイメージしづらかった）ので、簡単にやり方をまとめてみました。

# 環境

Microsoft Visual Studio Professional 2019
Version 16.11.7
日本語版

# やり方

- develop
- feature

とブランチがあって、feature に対して develop を rebase します。

【feature】
![スクリーンショット 2021-12-27 094104.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23789/0753aae8-0219-a693-74bb-cbe724e2ebc7.jpeg)

【develop】
![スクリーンショット 2021-12-27 094126.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23789/ddee6bdf-f14a-a0f8-7e77-3eb1d802d7cf.jpeg)

まずは feature をチェックアウトします。
で、ここがわかりずらい！と感じたポイントです。
「Git リポジトリ」ウィンドウで develop を右クリックし「**'feature'を'develop'にリベースにする**」を選択します。
「feature に対して develop を rebase したい」から、
「feature **に** develop **を** rebase する」とかの方がわかりやすいのでは…と感じました。
だって Git コマンドなら`git rebase develop`じゃないですか…。

![スクリーンショット 2021-12-27 094149.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23789/15fd4476-6dae-346d-0a4a-dd43cc04a8fa.jpeg)

結果としては以下のようになります。

![スクリーンショット 2021-12-27 094237.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23789/6194b92a-f1bf-bf8e-b7e4-250900aa9d06.jpeg)

※ ちなみに英語版だと「Rebase 'feature' onto 'develop'」

![スクリーンショット 2021-12-27 104327.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23789/33d953c1-c3f5-1103-b53e-2f7cf89aed00.jpeg)

# Appendix

rebase した場合、force push が必要になるケースが多いと思いますが、Visual Studio はデフォルトだと force push は禁止されています。
「ツール > オプション > ソース管理 > Gitグローバル設定 > プッシュを有効にする --force-with-lease」を ON にすることで force push が行えるようになります。

![スクリーンショット 2021-12-27 134118.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23789/21e7d119-9539-c8d9-ce12-838938782a00.jpeg)

プッシュの失敗時、以下のような確認ウィンドウが表示されます。

![スクリーンショット 2021-12-27 134220.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23789/7d5049fb-2555-f0a3-d988-af9c69c3c177.jpeg)
rails7で`to_s`の引数にシンボルでフォーマットを指定するとDEPRECATION WARNINGが発生する(`DEPRECATION WARNING: Integer#to_s(:currency) is deprecated. Please use Integer#to_formatted_s(:currency) instead.`)理由と対応

# 概要

rails7で`1000.to_s(:currency)`の様に、`to_s`の引数にシンボルでフォーマットを指定するとDEPRECATION WARNINGが発生するようになりました。

```ruby
DEPRECATION WARNING: Integer#to_s(:currency) is deprecated. Please use Integer#to_formatted_s(:currency) instead.
```

この変更はこちらのPRで追加されています。

https://github.com/rails/rails/pull/43772

# 理由
ruby3.1で`symbol`, `true`, `false`, `nil`, `0-9`への`to_s`メソッド使用時のパフォーマンスチューニングが行われました。

https://github.com/ruby/ruby/commit/b08dacfea39ad8da3f1fd7fdd0e4538cc892ec44

railsではactivesuportで複数クラスの`to_s`メソッドをオーバーライドしているためこの恩恵が受けられなくなってしまった様です。
これまでの実装である、引数に`:currency`などのシンボルを受け取り、そのシンボルをもとにフォーマットを動的に変更する処理は`to_formatted_s`でも実装されたため、そちらを使うようにそのためwarnignのメッセージで促されています。
`to_s`は`DEPRECATION WARNING`を出力するかruby実装の`to_s`を呼び出すかを判断する処理に変更されました。

# 解決方法
warnignのメッセージで書かれているより呼び出すメソッドが変更するだけです。


```diff
- 1000.to_s(:currency)
+ 1000.to_formatted_s(:currency)
```


`to_formatted_s` は`to_fs`と言うメソッド名でも呼び出せるようにaliasが指定されています。
【bokeh】ColumnDataSourceインスタンス生成時に、`ValueError: cannot insert ~, already exists`が発生

# 環境
* Python 3.9
* bokeh 2.4.2
* pandas 1.3.3

# やりたいこと
Pythonの可視化ライブラリ[bokeh](https://docs.bokeh.org/en/latest/)を使って、グラフを生成したいです。

# 発生したエラー
`bokeh.models.ColumnDataSource`のインスタンス生成時に、`ValueError: cannot insert x, already exists`というエラーが発生しました。


```python:foo.py
from bokeh.plotting import figure, output_file, save
from bokeh.models import ColumnDataSource
import pandas

index = pandas.Series([0, 1, 2, 3, 4], name="x")
data = {"x": [1, 2, 3, 4, 5], "y": [6, 7, 2, 3, 6]}
df = pandas.DataFrame(data=data, index=index)

source = ColumnDataSource(data=df)

p = figure()
p.circle(x="x", y="y", source=source)

output_file("foo.html")
save(p)
```


```
$ python foo.py
Traceback (most recent call last):
  File "foo.py", line 9, in <module>
    source = ColumnDataSource(data=df)
  File "/home/vagrant/.pyenv/versions/3.8.6/lib/python3.8/site-packages/bokeh/models/sources.py", line 227, in __init__
    raw_data = self._data_from_df(raw_data)
  File "/home/vagrant/.pyenv/versions/3.8.6/lib/python3.8/site-packages/bokeh/models/sources.py", line 272, in _data_from_df
    _df.reset_index(inplace=True)
  File "/home/vagrant/.pyenv/versions/3.8.6/lib/python3.8/site-packages/pandas/util/_decorators.py", line 311, in wrapper
    return func(*args, **kwargs)
  File "/home/vagrant/.pyenv/versions/3.8.6/lib/python3.8/site-packages/pandas/core/frame.py", line 5799, in reset_index
    new_obj.insert(0, name, level_values)
  File "/home/vagrant/.pyenv/versions/3.8.6/lib/python3.8/site-packages/pandas/core/frame.py", line 4414, in insert
    raise ValueError(f"cannot insert {column}, already exists")
ValueError: cannot insert x, already exists
```


# 原因

ColumDataSourceコンストラクタの処理で、[pandas.DataFrame.reset_index](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.reset_index.html)を実行しています。
https://github.com/bokeh/bokeh/blob/d8ac28b6997b969fbb5f808927a09a1a57e659b9/bokeh/models/sources.py#L271
このとき、indexのname`x`とcolumnのname`x`が重複していたため、上記のエラーが発生しました。

ColumnDataSourceはDataFrameに名前付きのindexがあれば、その名前を持つ列を作ろうとします。そのため、`reset_index`を使っているのだと思います。

> * If the DataFrame has a named index column, the ColumnDataSource will also have a column with this name.
> * If the index name is None, the ColumnDataSource will have a generic name: either index (if that name is available) or level_0.

https://docs.bokeh.org/en/latest/docs/user_guide/data.html#using-a-pandas-dataframe 引用
Python: PDFファイル内の全ページを任意のサイズに変換する

```python
from enum import Enum
from io import BytesIO
import PyPDF2


class PDFSizeParam(tuple, Enum):
    PX_72DPI_A4 = (595, 847)
    PX_300DPI_A4 = (2480, 3508)
    PX_350DPI_A4 = (2894, 4093)


def scale_pdf_to(pdf_bytes: bytes, scale_to: PDFSizeParam = PDFSizeParam.PX_72DPI_A4) -> bytes:
    reader = PyPDF2.PdfFileReader(BytesIO(pdf_bytes))
    num_pages = reader.getNumPages()
    pages = [reader.getPage(i) for i in range(num_pages)]
    [page.scaleTo(scale_to.value[0], scale_to.value[1]) for page in pages]
    writer: PyPDF2.PdfFileWriter = PyPDF2.PdfFileWriter()
    [writer.addPage(page) for page in pages]
    temp_pdf: BytesIO = BytesIO()
    writer.write(temp_pdf)
    temp_pdf.seek(0)
    return temp_pdf.read()
```
bytes <-> File読み書きは割愛。
【Ruby】クラスとモジュールの違いと使い分け

##クラスとモジュールの違い

- クラスはインスタンスが生成でき、モジュールはインスタンスが生成できない
- クラスは継承でき、モジュールは継承できない


##クラスとモジュールの使い分け

moduleをclassにincludeをして使用できるようにする、ミックスインでの例。
モジュールはクラス間でメソッドを共有することができる。
モジュールをクラスに組み込むことで、クラス定義にメソッドをコピー＆ペーストしたのと同じようにモジュールのメソッドをクラスで利用できるようになる。
これは、特定のクラスで再利用したいメソッドがあり、かつ、それを一カ所に集めておきたい場合に便利。

```ruby
module Cream
  def cream?
    true
  end
end

class Cookie
  include Cream
end

cookie = Cookie.new
p cookie.cream?
#=> true
```


##参考

http://ruby-for-beginners.rubymonstas.org/advanced/modules.html
Python: 複数PDFを結合して１つのPDFに変換する

```python
from io import BytesIO
from typing import List
import PyPDF2

def merge_pdfs(pdf_bytes: List[bytes]) -> bytes:
    merger: PyPDF2.PdfFileMerger = PyPDF2.PdfFileMerger()
    try:
        for b in pdf_bytes:
            merger.append(PyPDF2.PdfFileReader(BytesIO(b))) if b else None
        ret: BytesIO = BytesIO()
        merger.write(ret)
        ret.seek(0)
        return ret.read()
    finally:
        merger.close()
```

bytes <-> File読み書きは割愛。
シェル学習(No.1)

#シェル学習(No.1)

####ファイルのパーミッション
aの内容をよめるようにするにはどの様にすればよいでしょう？
?に解答が入ります。

```shell
chmod -r a
??????????
cat a
cat:a:許可がありません
```
解答

```
chmod +r a
```
-r +r マイナス・プラス記号がそれぞれ不許可許可に対応する。



#####***自分のユーザーの確認方法


```shell
whoami
```

####rootユーザーとsudo

パーミッションを超えた操作が必要なときは、sudoというコマンドを使用する。
sudoは、rootという特別なユーザーでコマンドを実行する。
UCHIMEでキメラ配列除去

シーケンスデータにはキメラ配列が入り込むことがあります。特に複数の生物種が含まれるメタゲノムデータではキメラ配列除去が必須です。メタゲノム解析ではOTUクラスタリングに含まれていることも多く、意識せずキメラ配列除去を行っていることもありますが、キメラ配列除去のみを行う機会がありましたので、調べた内容をまとめてみようと思います。



#UCHIME
NCBI にて 16S rRNA シーケンスデータからのキメラ配列除去についての記事を見つけ、Uchime2_ref を使っていたので採用しました。Uchime2_ref はデータベース配列に対してアライメントを行い、キメラ配列を見つけるモードになります。

https://www.ncbi.nlm.nih.gov/genbank/rrnachimera/

#UCHIME アルゴリズムが使えるツール

複数手段があったので特徴を記載します。

###UCHIME

ページは USEARCH の中にありますが、UCHIME のみ単体でダウンロードできました。USEARCH、VSEARCH と違い、出力形式の種類が少ないようです。キメラ配列を決定した後は、キメラ配列ではなかった配列を元ファイルから ID で取り出します。

https://www.drive5.com/usearch/manual/uchime_algo.html

###USEARCH

USEARCH は解析の他、ファイルの加工などもできて大変便利です。UCHIME にはない出力形式が選べ、キメラ配列判定にならなかった配列の出力が可能です。データベース配列のデータ量が大きいと使えないなど 32bit 版には制限があります。なお 64bit 版は有償になります。

https://drive5.com/usearch/

###VSEARCH

USEARCH の代替えソフトです。USEARCH 32bit 版では計算しきれないデータ量も解決してくれることがあります。必須オプションにデフォルト値を設定してくれていたり、コマンド操作がより簡易になっている気がします。

https://github.com/torognes/vsearch

#UCHIME で気を付けたい点

###OTU クラスタリングをする際は推奨されない

クラスタリングをせずに解析するときに使いました。
クラスタリングしてキメラ除去も行いたいときは、USEARCH であれば、cluster_otus コマンドに組み込まれているキメラ除去を用いたほうが上手くいきます。

>http://www.drive5.com/usearch/manual/cmd_uchime2_ref.html

###-strand plus

プラス（センス鎖）方向のみのアライメントしか行わないので、データベースの配列に reverse complement も追加する必要があります。USEARCH の-strandオプションはプラスしか設定できないのに必須オプションなので、付けないと動きません。

###max length

データベース配列、入力配列ともにツールに設定された最大サイズを超える配列は処理しません。オプション値で設定できますが USEARCH にはありません。ログに出力されるので、そこで確認ができます。（バージョンによって異なる可能性があるので、試した際に確認した数値は割愛します）
PUT・PATCH・DELETEメソッド

#PUT・PATCH・DELETEメソッドについて
※とある未熟者エンジニアの備忘録です。(laravel6)

ルーティングのリストを見るとMethod欄がPUT・PATCH・DELETEに設定されていた場合について、調べた事をまとめていきます。

HTMLのformタグでは、
これら３つのメソッドをサポートしていないそうです。

その為、LaravelのbladeでPUT・PATCH・DELETEメソッドを使用する場合は、
formタグではmethod属性をPOSTのままにしつつ、
@methodでPUT・PATCH・DELETEメソッドを指定する必要があるとの事です。

PUTで簡潔な例を載せておきます。

```
<form method="POST" action="{{ route('●●●') }}">
@method('PUT')
・・・
</form>
```
下記のMethodフィールド参照

https://readouble.com/laravel/6.x/ja/blade.html
UiAutomatorで表示しているブラウザのURLを取得する

## 結論

```kotlin
uiDevice.findObject(UiSelector().resourceId("com.android.chrome:id/url_bar")).text
```

## 概要
UiAutomatorを利用した検証で遷移したブラウザページのリンクを取得したい
結論項にある方法で取得が可能

## 参考
https://stackoverflow.com/questions/48112983/how-to-verify-a-chrome-tab-url-by-using-ui-automator
[Python] Requests パラメータ allow_redirects

# allow_redirects

`Request`は（`HEAD`以外）デフォルトリダイレクトする

`history`のプロパティでリダイレクトされたかの歴史を追跡できる

## 例

GitHub は`HTTP`を`HTTPS`にリダイレクトする

```python:default
>>> r = requests.get('http://github.com/')

>>> r.url
'https://github.com/'

>>> r.status_code
200

>>> r.history
[<Response [301]>]
```

`allow_redirects=False`を設定すると、リダイレクトをしない

```python:allow_directs=False
>>> r = requests.get('http://github.com/', allow_redirects=False)

>>> r.status_code
301

>>> r.history
[]
```

`HEAD`の場合、デフォルトはリダイレクトしない

リダイレクトをしたい場合、`allow_redirects=True`を設定すれば

```python:allow_directs=True
>>> r = requests.head('http://github.com/', allow_redirects=True)

>>> r.url
'https://github.com/'

>>> r.history
[<Response [301]>]
```

# 参考

https://docs.python-requests.org/en/latest/user/quickstart/#redirection-and-history
新規登録機能

#新規登録機能について
※とある未熟者エンジニアの備忘録です。(laravel6)

Laravelでは簡単に新規登録機能を実装する事ができます。
ルートは仮で設定したルートを用意し説明していきます。

php artisan route:list
上記コマンドにてログイン機能のルートが確認できます。
App\Http\Controllers\Auth\RegisterController.phpのshowRegistrationFormアクションメソッドを使うという設定を行い、そしてregisterという名前付きでルートを用意したとします。

次にviewを書く作業の説明です。
resources\viewsの中にauthフォルダを作成します。
ここに簡潔なregister.blade.phpを作る事にします。

```
<h1>新規ユーザー登録画面</h1>
<form action="{{ route('register') }}" method="post">
  @csrf
  <label>name</label>
  <input type="text" name="name" placeholder="店名を入力してください">
  <label>email</label>
  <input type="email" name="email" placeholder="emailを入力してください">
  <label>password</label>
  <input type="password" name="password" placeholder="パスワードを入力してください">
  <label>confirm_password</label>
  <input type="password" name="password_confirmation" placeholder="パスワードを入力してください">
  <input type="submit" value="登録">
</form>
```

これで新規登録機能は完了です。

これだけ？という疑問が生まれると思いますので、
どこで新規登録機能の処理がされているのか見ていきましょう。

実は冒頭で説明したRegisterController.phpの中にshowRegistrationFormアクションメソッドは書かれていません。
showRegistrationFormアクションメソッドの代わりに
use RegistersUsers;
が途中で書かれています。
一番上にはuse Illuminate\Foundation\Auth\RegistersUsers;と記載がありますので、
このRegistersUsers;の場所は
vendor\laravel\framework\src\illuminate\Foundation\Auth\RegistersUsers;
ここに書かれています。

このRegistersUsers;の中を見てみると
showLoginFormアクションメソッドが書かれています。

```
public function showRegistrationForm()
    {
        return view('auth.register');
    }
```

viewを作成するディレクトリも指定がされている為、
resources/viewsの中にauthフォルダを作成します。
authフォルダの中に次は冒頭で出てきましたregister.blade.phpを作成します。

バリデーションも機能している為、パスワードを入力する際は最低でも8文字を満たすようにしましょう。エラーメッセージは設定されていないので、8文字未満でパスワードを設定してしまうとDBに反映されませんのでご注意下さい。
Dialogflowでリンクボタンを表示したい

# はじめに
Dialogflowとは、Googleが提供しているチャットボットサービスです。
あらかじめ管理画面から質問とそれに対する回答を登録しておいて、Google側が出力してくれたコードを貼り付けるだけで、webサイトに簡単にチャット機能が追加できます！
すばらしい！！！

ですが、返事でwebサイトのURLを表示するにはどうしたらいいの？というところにつまずいたので、書いておきます。

# リンクボタンを回答で表示しよう
画面左にある「Intents」から「CREATE INTENT」ボタンをクリックします。
![CREATE_INTENT.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392006/7c8b295c-d09e-250b-f39e-6317b2cf77de.png)


「Training phrases」に質問を入力してください。
![Training phrases.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392006/4a48d129-6264-4bf3-6a49-04e575891e1c.png)


「Responses」で回答を登録していきます。
もとからある「Text Response」は削除してください。
「ADD RESPONSES」をクリックして、「Custom Payload」をクリックしてください。
![Responses.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392006/d11e391d-a57b-22e3-b07c-965e51285d25.png)


以下、リンクボタンの例になります。

```
{
  "richContent": [
    [
      {
        "type": "button",
        "icon": {
          "type": "chevron_right",
          "color": "#FF9800"
        },
        "text": "こちらを参照してください",
        "link": "https://www.google.com/"
      }
    ]
  ]
}
```

# 実際に動作を確認してみよう
画面左にある「Integrations」のWeb Demoからできた気がする...
けど、記憶を失いました。。

![スクリーンショット 2021-12-27 10.53.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392006/faf2e6bd-0d93-8bf3-4108-afaaf9c22b78.png)



# 余談
Dialogflowの導入としては、この記事がわかりやすくておすすめです。

https://100webdesign.jp/services/web_knowhow/ai-chat-bot/web_knowhow-20255/
[Rails]Webアプリケーションしか作った事ない僕が、ネイティブアプリケーションを作りたい

#はじめに
初学者の私が、２ヶ月でRailsを学びWebアプリケーションを作れるようになりました。
IOSでリリースをするに至って
まずどのような知識が必要かをまとめる記事になっています。



##React Native

React Nativeは、iPhoneとAndroidどちらでも動かすことができる開発用フレームワークです。
JavaScriptで開発することができるため、JavaやSwiftが書けないエンジニアでも、React Nativeを使えばアプリ開発ができます。
React Nativeの開発言語は、JavaScriptです。そのため、JavaScriptのコードを書ければAndroidとiOSの両方で開発が可能になるフレームワーク

```
Reactに慣れている人にとっては学習コストの低いReact Native
ネイティブエンジニアには、逆に学習コストが高くなると考えられます。
```
##Flutter

FlutterはGoogleが作ったモバイルアプリ用のフレームワーク。
「Dart」という言語を使って開発をしていきます。

```
モバイルアプリ開発をこれから本格的に始めたいWebアプリ開発者
React Nativeがなじめないと思っている人
```

#実際どのようにしてリリースしていくか
**簡単に言うとReactに慣れているか慣れていないか**
私は、javascriptを使ってコードを書いたことはあるが慣れているわけではないので
**現状Flutterを使って作ろうと考えている。**
だがjavascriptは需要があると思うので将来的に使う可能性がある場合Reactを使おうと思う。

##終わりに
この記事についてはこれからもアップデートしていきます。
RPAの開発者が持っておきたい、たったひとつのマインド - はじめてのAA

#はじめに

これからRPAの開発を始めるみなさん、今の気持ちはいかがですか？

「RPAを使えば、業務がどんどん効率化できる！」と楽しみな気持ちもある一方、
「本当にできるのかな？」という不安もあるのではないでしょうか。

もちろん、同じようにRPAの開発を勉強していても、すぐに習得できる人もいれば、習得に時間がかかる人もいます。

その差を分ける大きなポイントが、実はマインドにあるとしたらどうでしょう？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/71a8f6d2-c1d6-fce8-2d3e-6efdbb65c594.png)

要領の良さやIT知識は、一朝一夕には身に着けられませんが、マインドはすぐに変えられます。

みなさんもこの記事を読んで、今日から「開発が得意な人（得意になる人）のマインド」を手に（心に）入れましょう！

# 開発が得意な人・苦手な人の分かれ目：「エラーに対するマインド」

RPAの開発をしていると、Botが思い通りに動かない場面にはしょっちゅう遭遇します。

実はこうした状況に対するマインドこそが、Bot開発が得意な人と苦手な人の大きな分かれ目になります。

「エラー」という言葉は、正確には、Botから何らかのエラーメッセージが返ってくるような状況を言うのですが、ここでは

- Botが途中で止まってしまう
- Botが思っていたのと違う動きをする　（データが更新できていない、想定外の更新をしているなど）

といった状況も広義の「エラー」に含めて解説したいと思います。

## 開発が苦手な人は、エラーを怖がる

開発がなかなか習得できない人は、作る前からエラーを怖がります。

「エラーが出たらどうしよう」と恐れるあまり、Botを作る手も自然と遅くなります。

そうして時間をかけ、ようやく出来上がったBotを動かし、エラーが出ると、そこで絶望してしまいます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/d308c1ae-f064-a310-88c1-c1a68078ddc5.png)

## 開発が得意な人は、「エラーは出て当たり前」と思っている

一方、開発が得意な人は、「エラーは出るのが当たり前」と思っています。

エラーかどうかは動かさないとわからないので、とにかく作ってみて、動かして、エラーを出そうとします。

エラーは出るのが当たり前なので、絶望することはなく、ただそのエラーを修正しようとします。

そのプロセスを何度も繰り返し、最終的にエラーのないBotを完成させます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/b41e1de8-015e-ddaa-126f-df219adb4316.png)

## エラーを出している回数は、開発が苦手な人より得意な人の方が多い

上記の図を見比べてみるとわかりますが、実はエラーを出している**回数**は、開発が苦手な人より得意な人の方が多い傾向にあります。

**エラーは「出してはいけないもの」ではなく、「出して直すもの」**と知っているからですね。

開発中にたくさんのエラーを出して直すプロセスを繰り返すことで、結果的には様々な状況に対応できる、安定したBotを作れるというメリットもあります。

# 結論

これからBot開発を勉強していく中で、作ったBotが思い通りに動かない状況に、みなさんは何度も遭遇すると思います。

それは決して悪いことではなく、開発者がダメだから起こるわけでもなく、Bot開発のために必ず必要なプロセスです。

エラーが出て、「もういやだ！」「自分には才能がない」と絶望しそうになったら、どうかこの話を思い出してください。

**「エラーや間違いは、出たら直せばいい[^1]。怖がらず、どんどん作って動かしてみよう！」**


#最後に

この記事は、「はじめてのAA」シリーズからリンクされています。

Automation Anywhere を初めて使っている方は、ぜひ以下のリンクもチェックしてみてください。

https://qiita.com/IQ_Bocchi/items/8d28f12256037b5f9058


[^1]: 細かいことを言えば、実際には起こしちゃいけない性質の間違いもあります。機密情報を"うっかり"全メールリストに一斉送信しちゃうとかですね。こういう本当にやばい間違いには、気をつけるというか、そういうやばい間違いが起きにくい仕組みを作っておくという考え方は必要です。やばい間違いのもうひとつの例として、会社にひとつしかない秘伝のエクセルデータを"うっかり"全消ししちゃうとかもありますね。この場合、"うっかり"を起こさないように注意するというよりは、"うっかり"はあり得るという認識に基づき、更新前に必ずバックアップをとるといった対策が必要になってきます。
【React】複数のrefを扱う方法 ver.2【createRef不要】

Reactの関数コンポーネントにおいて、refを複数扱う方法は、以下のような書き方がよく知られていると思います。

```typescript
const ref = useRef<RefObject<HTMLDivElement>[]>([]);
data.forEach((_, index) => {
	ref.current[index] = React.createRef<HTMLDivElement>();
});
```

これとは異なる方法で複数のrefを扱う方法を発見したので、ここに残しておきます。

# 再帰コンポーネント

再帰コンポーネントを利用すると、createRefを使わずとも複数の要素を扱うことができます。
useRefとforwardRefを組み合わせて使う方法については、私の以前の記事を御覧ください。

* [【React】useRefとforwardRefを両立する方法【関数コンポーネント】](https://qiita.com/costeka/items/a2722350c5d1b995f3c3)

```typescript
const NewMultiRefSample = React.forwardRef<HTMLDivElement[], { data: string[] }>(({ data }, ref) => {
	// 今回表示する要素のref
	const divRef = useRef<HTMLDivElement>(null);
	// 次以降表示する要素のref
	const nextRef = useRef<HTMLDivElement[]>(null);
	// 今回表示する要素と、次以降表示する要素を合わせてフォワーディングする
	useImperativeHandle(ref, () => {
		const divDom = divRef.current;
		const nextDoms = nextRef.current;
		if (divDom != null && nextDoms != null) {
			return [divDom, ...nextDoms];
		} else {
			return [];
		}
	});

	const copiedData = data.concat();
	if (copiedData.length <= 0) {
		return null;
	}
	const headData = copiedData.shift();

	return (
		<>
			<div ref={divRef}>{headData}</div>
			<NewMultiRefSample ref={nextRef} data={copiedData} />
		</>
	);
});
```

このコンポーネントにrefを渡すと、DOMノードを配列を得られます。

```typescript
const App = () => {
	const data = ["red", "blue", "yellow"];
	const refs = useRef<HTMLDivElement[]>(null);
	useEffect(() => {
		console.log(refs.current);
	});
	return <NewMultiRefSample ref={refs} data={data} />;
};
```

# この手法の長所

この手法の長所は、親コンポーネント（サンプルのApp）と子コンポーネント（サンプルのNewMultiRefSample）の再レンダリングを切り離すことができることです。

冒頭に紹介した方法では、子コンポーネントをメモ化していたとしても、親コンポーネントが再レンダリングされるたびに、createRefで作り直されたrefが子コンポーネントに渡されてしまうため、子コンポーネントは必ず再レンダリングされてしまいました。

それに対して、この手法はuseRefしか利用しないため、親コンポーネントが再レンダリングされても子コンポーネントには同じrefが渡される、つまり子コンポーネントは再レンダリングされません。

親コンポーネントが頻繁に再レンダリングされる、または子コンポーネントのレンダリングのコストが重い場合、この手法を使うのが良いと思います。

# この手法の短所

この手法の短所は、なんといっても読みにくい・理解されにくいことです。

チーム開発の場合は、むやみに利用するのは避けたほうがいいでしょう。
【Mac】 Gstremerでエレメントを確認する方法

本記事ではGstremerのコマンドの一つをご紹介します。
今回のコマンドを使用することで、Gstremerのエレメントを検索できます。

##環境
macOS Monterlay 12.0.1
GStreamer Core Library version 1.18.4


## 下記のコマンドを実行する。 ※ 今回は「264」で検索しています。
```
gst-inspect-1.0 | grep 264
```

## 結果は以下のとおりです。
```
rtp:  rtph264depay: RTP H264 depayloader
rtp:  rtph264pay: RTP H264 payloader
videoparsersbad:  h264parse: H.264 parser
applemedia:  vtenc_h264_hw: H.264 (HW only) encoder
applemedia:  vtenc_h264: H.264 encoder
typefindfunctions: video/x-h264: h264, x264, 264
libav:  avenc_h264_videotoolbox: libav VideoToolbox H.264 Encoder encoder
libav:  avdec_h264: libav H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 decoder
libav:  avmux_ipod: libav iPod H.264 MP4 (MPEG-4 Part 14) muxer
x264:  x264enc: x264enc
```



以上で終わりです。
エレメントエラーになった場合は、このコマンドで代替パイプラインを探すこともできます。また特定のパイプラインが確認できなかった場合、パッケージを追加することで確認できるようになる場合もございます。
Laravel + Amazon S3で動画をストリーミング再生したい

# はじめに
小規模な会員制の動画配信のシステムを作ったときに、動画をストリーミング再生したくなったので、その方法を書いておきます。
というか、もともとすばらしい記事があったのですが、それの初心者向けの補足をします。
（私がつまづいたところを書いておきます。。）

# とりあえず、この記事すばらしい!!

[Laravelで動画のストリーミング再生を実装する【Safariでも再生可能】](https://code-pocket.info/20200624304/)

とりあえず、この記事を読んで、この記事のコードをコピペしてください。
ヘルパーの方は何書いてあるか、私にはさっぱりわかりません!!

# Amazon S3につないでおいて

[Laravel 公式](https://readouble.com/laravel/8.x/ja/filesystem.html)

# 補足します1

「ヘルパーにS3の接続とファイルパスを渡す」という箇所がありまして、"s3上の動画ファイルのパス"とだけ書いてあるんですが、なにを指定したらいいのか、だいぶ悩みました...

S3のバケットの中にファイルアップロードすると思うのですが、バケット名までは、.envで指定してあるのでバケット名以降のパスを書きます。

例えば、バケット名「aaa」の中に、「bbb > ccc.txt」が保存してあったら、
`bbb/ccc.txt`と書けばいいのです!!

なんか、アップロードしたあとのURLとか書いたりして、取れないよーとかなってました...


# 補足します2

参考にした記事の最後に、
「作成したメソッドにルーティングを設定し、ブラウザからアクセスすると動画が再生できます！」
と書いてあるんですが、ここも補足します。

記事内にある、`streamVideoFile`メソッドへのルーティング（URL）を例えば、
http://localhost:8888/streamVideoFile
にしたとします。

そしたら、それとは別にviewファイルを表示するルーティングを用意して、そのviewファイルにvideoタグを書きます。
videoタグのsrcを、先ほど作成したルーティングに設定します。

```html

<video controls preload="auto">
    <source src="http://localhost:8888/streamVideoFile" type="video/mp4">
</video>

```

こうやって書いておくと、videoタグでストリーミング再生が実現できます！！

実際は、同じ動画を再生するとかはあまりないと思うので、違う動画を再生できるように、引数なりなんなり渡して、動画切り替えたりしてください。


# まとめ
ぶっちゃけ、このストリーミング再生の記事書いてくれている人がいなかったら、私は実装できていなかった...
ありがとうございます。。
【Mac】Gstremerで動画を保存する方法


本記事ではGstremerのコマンドの一つをご紹介します。
今回のコマンドを使用することで、Macに接続されているカメラデバイスで撮影した映像を動画にして保存することができます。

## 環境
macOS Monterlay 12.0.1
GStreamer Core Library version 1.18.4


## 下記のコマンドを実行する
```
$ gst-launch-1.0 -e avfvideosrc device-index=1 ! vtenc_h264 ! qtmux ! filesink location=file-test1.mp4
```

## 撮影が開始されると下記の画面になります。


```
パイプラインを一時停止 (PAUSED) にしています...
Pipeline is live and does not need PREROLL ...
Pipeline is PREROLLED ...
パイプラインを再生中 (PLAYING) にしています...
New clock: GstSystemClock
Redistribute latency...
Redistribute latency...
0:00:10.9 / 99:99:99.
```
## 動画の撮影をCtl+Cで強制終了させます。これで実行したディレクトリに動画が保存されます。
```
パイプラインを一時停止 (PAUSED) にしています...
Pipeline is live and does not need PREROLL ...
Pipeline is PREROLLED ...
パイプラインを再生中 (PLAYING) にしています...
New clock: GstSystemClock
Redistribute latency...
Redistribute latency...
^Chandling interrupt.
割り込み: パイプラインを停止しています...
EOS on shutdown enabled -- Forcing EOS on the pipeline
Waiting for EOS...
Got EOS from element "pipeline0".
EOS received - stopping pipeline...
Execution ended after 0:00:16.649098000
Setting pipeline to NULL ...
Freeing pipeline ...
```

## パイプラインの簡単な解説
* -e 
    * 撮影を強制終了しても、動画が破損しないようにするオプション。
* avfvideosrc device-index=1 !
    * デバイス番号の指定。※ 今回接続したWebカメラの番号は1番。
* vtenc_h264 !
    * 特定のエンコード。
* qtmux !
    * コンテナ化。※ 今回はquick time形式でコンテナ化。
* filesink location=file-test1.mp4
    * 名前を指定してファイルを保存。
    
以上で終わりです。
パイプライン作成にあたり、利用できるオプションはたくさんあります。またエンコードやコンテナ化の種類もたくさんあります。Webカメラの種類や使用するPCの仕様で組み合わせが変わるので、都度ご確認ください。
本のおすすめ　ディープフェイク

# 本　ディープフェイク
https://www.kinokuniya.co.jp/f/dsg-08-EK-1058331

# 記載内容で気になる用語とか

- インフォカリプス Information + Apocalypse
    - 偽の情報によって情報の信頼性が落ち、情報の終末が迫ってるって考え方。まぁ危機を煽って焚き付ける手法でもあるね。

- AI によって偽物を作る技術が進化したいま、偽物を見破るaiとのいたちごっこがある
    - その為に・・
        - ファクトチェック
        - ディープフェイク
        - medifor
        - ディープフェイク発見チャレンジ
        - google ジグソーのアセンブラー
        - ディープ トレイス
        - リアリティー ディフェンダー
    - ブロックチェーンでこの辺盛り上がりそう
    - エストニアでの成功例
        - サイバー攻撃にたいしてボランティアのIT対策から始まって今ではデジタル大国らしい