OmniAICreator/Qiita-1.07M huggingface dataset:
【シェル芸本】テキスト処理に使うLinuxコマンドをまとめる。

# はじめに

私は普段大学でlinuxを使います。ディレクトリ作成やファイル移動など簡単なことだけですが、コマンドを入力して処理が行われるというのが非常に気に入り、もっとCUIで何かがしたいと考え、衝動的にシェル芸の本を3冊買ってしまいました。痛い出費ですが、買ったからには少しでも早く習得したいと考え、アウトプット代わりに問題を解くために使ったコマンドをまとめることにします。

私が買った本のうちの一冊は「1日1問、半年以内に習得 シェル・ワンライナー160本ノック」というもので、さしあたり1章を終わらせてから本記事を執筆しているので、これからまとめるコマンドはおそらくは基本的なコマンドだと思われます。

https://amzn.asia/d/5TQVKCP


# 目次
[はじめに](#はじめに)
[1.cat](#1-cat)
[2.sed](#2-sed)
[3.grep](#3-grep)
[4.awk](#4-awk)
[5.sort](#5-sort)
[6.uniq](#6-uniq)
[7.xargs](#7-xargs)
[8.tr](#8-tr)
[おわりに](#おわりに)


# 1. cat
catコマンドはファイルの中身をそのまま出力してくれるコマンド。
```
cat hogehoge.txt
```
このまま実行してやればファイルの中身が出力される。
オプションとして、`-b 空白行を飛ばして行番号を表示`や`-n 行番号を表示`などがあります。
似たようなコマンドに`tac`というものがあり、こちらはファイルの中身をすべて逆さまにして出力します。

# 2. sed
sedコマンドは入力されたテキストを置換とかしてくれます。
結構色々使い方があるみたいです。
```
sed 's/hoge/fuga/' #最初のhogeのみfugaに置換
sed 's/hoge/fuga/g' #すべてのhogeに対してfugaに置換
```
というように、置換ができたり,
```
sed -n '/hoge/p' #hogeにマッチした行のみ出力
sed -n '/hoge/,/fuga/p' #hogeにマッチした行からfugaにマッチした行までを出力
```
という抽出？もできたりします。
`-n 自動出力しない(マッチしたり置換したやつ以外出力しない)`
検索には正規表現が使えますが、`-E 拡張正規表現を認める`を使うと、拡張正規表現も使えるようです。私は拡張正規表現はほとんど知りませんが、それでもカッコで囲んだ部分を\1,\2\,...,\nのように変数として扱える**後方参照**という機能が開放され、それだけでも結構便利な使い方ができます。

# 3. grep
```
grep (文字列) #文字列を検索して、マッチした行を出力する。
```
もちろん正規表現は使えるし、オプション`-E 拡張正規表現を認める`もある。`-l ファイル名を大量に入れて実行したとき、マッチしたもののファイル名のみを出力。`、`-n ファイルを入れて実行したとき、マッチした行を出力する。`というものもある。
`-l`については`|`パイプラインで入れると(標準入力)としてファイル名が出るので、ファイル名を出したいときはxargsでファイル名を与えて実行してやるといいと思います。
それ以外にも`-v マッチしない行を出力。` `-o 検索と一致したものを出力する。` `-r ディレクトリ以下の位置にあるファイルを全て検索する。`など、便利なオプションが多数ある。


# 4. awk
コマンドライン上の入力行ごとにを引数に渡し、awkというプログラミング言語を活用することができます。読み込んだ引数は一番左の列を一列目として\$1(第1フィールド),\$2(第2フィールド),...,\$n(第nフィールド)というように変数として呼び出しが可能です。なお、\$0は行全体を指します。
```
awk '条件{処理}' #基本はこの形で使う。条件をパターン、処理をアクション、パターンとアクションの組をルールという。
```
ルールは2つ以上並べることができます。特殊なパターンとして`BEGINパターン`と`ENDパターン`が存在しています。
```
BEGIN{処理} #一行目の処理前に処理が実行されます。
END{処理} #最終行の処理を終えた後、処理が実行されます。
```
なお、自分で適当な名前の変数を宣言することもできます。特に型はないようで、文字列か数字かを自分で判断してくれるみたいです。連想配列や、for文とかif文とかもかけます。
他にもawkの内部で独自の変数(組み込み変数というらしい)が使えるようで、`NF Number of Fields、各行の列数`というものがある。
オプションとして、`-F(文字) デフォルトで空白が設定されている区切り文字を(文字)に変更する。-F:で区切り文字を:にできます。

# 5. sort
テキストをソートしてくれます。`-k (数字) (数字)列目を基準にソートしてくれる`、`-n 数字としてソート`、`-t (なんか文字) 区切り文字をデフォルトの空白から(なんか文字)に変えてソートする`というオプションがあります。

# 6. uniq
連続行の出力や削除をしてくれます。`-c 出現回数を行の前に出力してくれます。`というオプションがあります。sort+uniqで文字列カウントに使えるみたいです。

# 7. xargs
入力から文字列を読み込み、それをコマンドに引数として渡した後に実行させます。
```
cat hoge.txt | xargs　#xargsは何も指定しないとechoコマンドが実行される。
seq 10 | xargs -I@ mkdir #(数字)というディレクトリが作成される。
```
個人的に相当便利だな？と思いました。`-n(数字) 引数が入る上限を決める。(数字)個が上限になる。``-I@ @をプレースホルダとして指定する。`
プレースホルダは要はこれから入れる値を予め変数として呼び出せる文字、みたいな認識でいいと思います。

# 8. tr
```
tr hoge fuga #hogeをfugaに置換する。
tr -d hoge #hogeを削除する。
tr -s hoge #hogeの繰り返しを一つにまとめる
```
sedみたいに置換や削除ができるみたいです。`-c hoge以外をfugaで置換`など、便利な機能がありますが、sedと結構機能が被ってるな、とも思いました。trとsedで違うところがあればぜひコメント欄で教えてください。

# おわりに
以上、シェル芸本を解く際に使った、基本的な(と思われる)コマンドをまとめました。何かしら間違いや問題等ありましたら、ぜひ教えてください。

# 参考文献
上田隆一,山田泰宏,田代勝也,中村壮一,今泉光之,上杉尚史.「1日1問、半年以内に習得 シェル・ワンライナー160本ノック」.技術評論社.2021
沓名亮典.「Linuxコマンドポケットリファレンス」.技術評論社.2015
ITmedia.「Linux基本コマンドTips」.[https://atmarkit.itmedia.co.jp/ait/series/3065/].(参照　2024-01-02)
『卒業式』というふりかえり

# はじめに
チームメンバーは極力固定化したいというのは、多くのスクラムマスターが願うことではありますが、いろいろな事情でメンバーが増減することは多々あります。
チームメンバーの増減ってそこそこ頻繁にありそうなのですが、「どうしてる？」って情報あまり多くないんですよね。。。

そんなときどんなアクティビティを行えばチームの混乱をなるべく減らすことができるでしょうか？

私は最近、メンバーが減るときは「卒業式」というアクティビティを行うようにしています。
もし、メンバーが減るとき「どんなアクティビティをしようかな？」と悩んでいる方がいらっしゃれば参考になれば幸いです。

やり方はすごーく簡単です。

# アクティビティの進め方
## 事前準備
* 卒業式の雰囲気を出せるような背景画像

私は、以下のイラストをMiroに貼り付けています。（どこから引っ張ってきたかは失念...確か[いらすとや](https://www.irasutoya.com/)だと思ったんですが探しても見つからなかったw）
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107292/5f6569f1-87c4-70a1-588d-4d1db4c2cc8e.png" width="256"/>

## Step 1.
これまでの、仕事をふりかえって、卒業メンバーに対しての感謝したいことを一杯書いてもらいましょう。
注意深くファシリテーションする必要も無いので、ファシリテーターも思い出して一杯感謝の言葉を書きましょう。
卒業メンバーが、その場にいるなら別のエリアに在校生（？）向けのメッセージを書いてもらっても良いかもしれません。

## Step 2.
在校生メンバーから卒業生へ向けて書いた言葉を読み上げてもらいます。
折角なのでファシリテーターが読み上げるのでは無く、メンバーに声を出してもらうようにしましょう。
卒業生メンバーからの在校生向けのメッセージがあれば、最後にそれも声をだしてもらいましょう。

## Step 3.
感謝の言葉とは、大なり小なり卒業メンバーに助けられたと言う事です。
裏を返せば、卒業メンバーがいなくなればその助けがなくなるかも知れないと言う事です。
書かれたものの中で今後困りそうなことや不安な事は無いかをメンバーで話し合ってみましょう。
卒業メンバーの言葉の中にも申し送りとして顕在化してない何かが潜んでいるかも知れませんので、その記載にも目も向けて見てください。

## Step 4.
最後に、みんなで「おめでとうございます！！」って言って、書いた紙のスクリーンショットを撮って、卒業生メンバーに送りましょう。

# この手法のねらい
メンバーが減ると言う事は、少なからずチームのパフォーマンスが一時的に劣化します。
この手法は、メンバーが減ることでどのようなリスクや不安があるかを「感謝」というポジティブな形で可視化することを目的としています。

# その他の手法
## 卒業メンバーに遊んでてもらう
許されるなら、卒業メンバーに何も作業をしてもらわないことで、何が起こるかを観察してみるのも良いかもしれません。

## 象・死んだ魚・嘔吐
メンバーがいなくなることをテーマとして、[象・死んだ魚・嘔吐](https://qiita.com/piyonakajima/items/ad3c44d1dc377e41d394)を行っても良いかも知れません。
ただ、こちらはネガティブな事をネガティブなこととして表明していくのでどちらがあなたのチームに向いているかは一考された方が良いかもしれません。
【令和5年秋期】応用情報技術者試験：合格体験記

## はじめに
10月8日(日)に実施された、応用情報技術者試験に無事合格した。
備忘録と振り返りも兼ねて投稿。

## 前提条件
### 経験
- エンジニア歴1年ほど。
- インフラ案件をいくつか担当

### 主な保有資格
- 基本情報技術者試験
- Java Silver
- Azure AZ-104
- AWS SAA

## 受験情報
- 2023年10月28日(日)

## 学習時間

- 期間: 1年間（2022年11月 ~ 2023年10月）
- 勉強時間: 220時間（）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513223/8e9ec1c4-05f8-a598-e72c-a94d17d50071.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513223/7cf1494f-fb25-91f5-b5cb-d093ee9c47d0.png)


今回はそれなりに記録をつけていたので、わりと正確です。
最初は4月に受験するつもりでしたが申込を忘れてしまいパス。
4月にAZ-104、6月にJava Silver を受験したので、その期間はほとんどしていません。

## 勉強方法と教材
### キタミ式イラストIT塾 応用情報技術者 令和05年
https://gihyo.jp/book/2022/978-4-297-13188-3

いろんなサイトでおすすめされていたので利用しましたが、私にはあまりあわなかったです。
（イラストとか吹き出しが多くて逆に見づらかったり...）

### 2023　応用情報技術者　午後問題の重点対策
https://www.itec.co.jp/store/products/detail.php?product_id=3811

これもいろんなサイトおすすめされていたので購入。
海雪が丁寧なので、午後の勉強を始める際の一冊目としてとても良いと思いました。

### 過去問道場
https://www.ap-siken.com/apkakomon.php

これは皆さん利用していると思います。
午前・午後ともに演習はここで仕上げました。
午後は本番の問題が難しかった場合の時のために、2問多く勉強していました。
- 情報セキュリティ
- 経営戦略
- プログラミング
- システムアーキテクチャ
- ネットワーク
- 組込みシステム開発
- 情報システム開発

## 所感
午前は、過去問道場10年分を周回していましたが、結構初見の問題もありました。
午後は、下記を選択。
- 情報セキュリティ
- システムアーキテクチャ
- ネットワーク
- 組込みシステム開発
- 情報システム開発 

経営戦略、プログラミングを選択する予定でしたが、組み込みシステム開発、情報システム開発に変更しました。
模擬試験として午後を通して解いていたなかったので、時間配分が不安でしたがなんとかなりました。
感触としては、60点ギリギリかなーっといった感覚でした。

## 試験結果
以下の通り、無事合格しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513223/6efbbe74-dcd5-f46b-b07f-53c8d00755f0.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513223/324c79b9-fc93-f93d-2ffb-ef3331e5e00b.png)

午後は自己採点で60点ギリギリだったので、少し上振れたようです。
合格できてよかったです。

## さいごに
最後まで見ていただき、ありがとうございました。
参考になれば幸いです。
ELB (Elastic Load Balancing)

## はじめに
この記事はAWS SAA試験勉強のための、ELBに関する知識のまとめです。

## ELBとは

ELBとは、Elastic Load Balancingの略称で、AWSが提供しているロードバランシングサービスです。EC2インスタンス間のトラフィック分散を実施します。

スティッキー(固定する)セッションはセッション中に、同じユーザから来たリクエストを全て、常に同じEC2インスタンスに送信する機能。

Amazon EC2インスタンスとELBの間の通信を暗号化することで、EC2インスタンスを利用したトラフィックのセキュリティを向上させることができます。SSL/TSL証明書をELBまたはEC2インスタンスに設定することで、SSL通信を実行することが可能。

ELBの発動には数分かかるため、スパイク(急激な負荷増)には対応できません。

ELBロードバランサーを指すようにZone Apexを登録するために、Route53ではエイリアスレコードを登録する必要があります。

ELBのリスナー設定でHTTPSプロトコルを利用するように変更できます。

### ターミネーションポリシー

NewestInstanceは新しく設置されたインスタンスから削除されるポリシー設定。

## rsync
「rsync」は、リモート環境とファイルやディレクトリを「同期（sync）する」というコマンドです。
ELBを使って負荷分散した際、複数のEC2インスタンスの特定ディレクトリを同期したいときには、rsyncを使うのが一般的。

```css:
/* ディレクトリを同期する（内容のみをコピー）*/
rsync -avh --progress /path/to/source/ /path/to/destination/
```

## [ALB(Application Load Balancer)](https://qiita.com/naoya_ok/items/a9e58cd092d1770a5f91)




## CLB(Classic Load Balancer)

L4/L7で負荷分散。


## NLB(Network Load Balancer)

L4(トランスポート層)で負荷分散。

HTTP/HTTPSトラフィックやアプリケーション層のルーティングが必要な場合はALBを選択し、TCP/UDPレベルの負荷分散や高スループットが必要な場合はNLBを選択します。
NLBに対してAWS Global Acceleratorを追加して、正しいリスナーポートを使用するようにGlobal Acceleratorの標準アクセルレーターエンドポイントを設定することで、グローバルなエンドポイントを介して、より高速なアプリケーションアクセスを可能にします。

バックエンドのEC2インスタンスの代わりに、NLBでTLS接続をTerminationすることができます。この際の証明管理書はAWS Certificate Manager(ACM)が推奨されます。


ELBのうち固定IPアドレスを割り当てることができるのはNLBのみです。


## GLB(Gateway Load Balancer)

サードパーティネットワークアプライアンス製品向け。

## Connection Draining

**既存の接続を開いたまま**、登録解除または異常なインスタンスへのELBのリクエスト送信を停止する機能。

## ELBではない方法でトラフィック分散による高可用性とフォールトトレランスを構成する方法

仮想のElastic IPアドレスを使用してEC2インスタンスに付与します。

## ヘルスチェック
ELBのヘルスチェックがターゲットのインスタンスの異常を検知した場合、そのターゲットへのトラフィック送信を停止します。

## SNI（Server Name Indication）

SNIは、暗号化通信で使用するサーバー証明書をパブリックIPアドレスではなくドメイン名によって判断する技術です。SNIに対応したELBに複数のサーバー証明書を導入すると、ELBが宛先ドメイン名から適切なサーバー証明書を判断してサーバーへ通信を転送します。SNIはALBとNLBが対応しています。
aria-practicesのdatepicker-dialogのユースケースについて整理する

# 背景
input[type=date]のdatepickerでは以下のようにclear（削除）ボタンがあります。
clear（削除）ボタンを表示させないようにするには簡単な実装では難しいです。

aria-practicesでdatepickerのサンプルがありました。これはclear（削除）ボタンがないです。

https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/examples/datepicker-dialog/

しかし本番環境向けではないそうです。
それについて調査し、どのようなケースで使用可能なのかについて整理します。



# 前提知識

## ARIAとは

https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA

- Accessible Rich Internet Application の略
- ウェブ・コンテンツやウェブ・アプリケーション（特にJavaScriptで開発されたもの）を障害者にとってよりアクセシブルにする方法を定義する役割と属性のセット

## アクセシビリティとは

https://developer.mozilla.org/ja/docs/Learn/Accessibility/What_is_accessibility

- 自分のウェブサイトを可能な限り多くの人に利用してもらうようにすること
- かつてはハンディキャップを持つ人々のためのものだった
- 現在はモバイルデバイスや遅いネットワークを利用している人々のためのものでもあると考えられている
- 能力や環境にかかわらず全員を同一に扱い、同じ機会を与えることと考えることもある

# 本番環境向けではないという記述について
https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/examples/datepicker-dialog/#support-notice-header:~:text=Picker%20Dialog%20Example-,Read%20This%20First,-The%20code%20in
>There may be support gaps in some browser and assistive technology combinations, especially for mobile/touch devices. Testing code based on this example with assistive technologies is essential before considering use in production systems.
>Robust accessibility can be further optimized by choosing implementation patterns that maximize use of semantic HTML and heeding the warning that No ARIA is better than Bad ARIA.

- モバイル/タッチ・デバイスに対するサポート・ギャップがあるそうです。
- セマンティックHTMLを最大限に利用することを推奨されています。

# 最後に
- PCでの使用であれば問題ないのかなと個人的には思いました。
- ```<dialog>```を使ってサンプルコードを書き直す等、セマンティックなHTMLで実装し直そうと思います。
- サンプルコードではキーボードサポートが充実していましたが以下が気になりました。
    - 実際ユーザが常識の範囲でどこまでキーボード操作で使うのか
    - 取扱説明書のようなものを別途用意するか、キーボードガイドを要素の近くに表示させるべきなのか
- MDNのアクセシビリティのチュートリアルを読んで勉強してみます。

https://developer.mozilla.org/ja/docs/Learn/Accessibility
Amazon API Gateway

AWS上でAPI を作成、公開、モニタリング を **簡単に行う** ためのAPI管理サービス。

受信したAPI コールと転送データ量に応じて課金される従量課金制サービスです。

Amazon API GatewayはAPIへのアクセスを IAM のアクセス権限によって制御することができます。そのためには、API の呼び出し等を API コール元にアクセスを許可する **IAM ポリシー**を作成して設定することが必要です。



```json:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "execute-api:Invoke"
      ],
      "Resource": [
        "arn:aws:execute-api:リージョン:アカウントID:APIID/ステージ/HTTPメソッド/リソースパス"
      ]
    }
  ]
}

```



## API Gatewayの利用例

- **HTTP経由の呼び出しリクエスト**という要件は、API Gatewayを利用する典型的なユースケースとなります。
- Amazon Kinesis Data StreamsとAmazon API Gatewayを統合して、<font color="red">**REST APIからデータポイントにアクセス**</font> できるように構成することが可能です。

- Amazon API Gatewayでは、簡単にWebsocketで接続するAPIが作成できます。マネージドサービスなので、冗長化構成も勝手にやってくれているので、とても簡単にWebsocketAPIを作成することができます。

- API Gateway自体はサーバを管理する必要がないため、Lambdaと組み合わせることでサーバレスアプリケーションを構成することができます。


## APIキャッシュ
Amazon API Gatewayでは、APIキャッシュを有効にすることで、エンドポイントのレスポンスがキャッシュされるようにできます。キャッシュを有効にすると、エンドポイントへの呼び出しの数を減らすことができ、<font color="red">**APIリクエストのレイテンシー短縮**</font>に効果的です。
キャッシュを有効にすると、API Gatewayは秒単位で指定できるTTLが切れるまで、エンドポイントからのレスポンスをキャッシュします。その後、API Gatewayは、エンドポイントへのリクエストを行う代わりに、キャッシュからのエンドポイントレスポンスを確認してリクエストに応答します。
APIキャッシュのデフォルトのTTL値は300秒です。最大のTTL値は3600秒です。TTL=0にするとキャッシュは無効になります。

## スロットリング制限設定

APIリクエストに対する一時的な高負荷発生に備えて、Amazon API Gatewayの処理性能を向上させるためには、API Gatewayのスロットリング制限設定とキャッシュを有効化することが必要である。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359600/9ada4a10-33c2-a2d5-bc93-f24c38c0692a.png)


## WebSocket

WebSocketは、リアルタイムな双方向通信を提供するプロトコルで、AWS上での使用は様々なケースで見られます。以下は、AWSでWebSocketを利用する主なケースの例です。

リアルタイムアプリケーション:
WebSocketは、リアルタイムなデータ更新が必要なアプリケーションに適しています。例えば、オンラインゲーム、チャットアプリケーション、リアルタイムな協力作業ツールなどがこれに該当します。

IoTデバイスとの通信:
IoTデバイスとの通信において、WebSocketはデバイスからのデータをリアルタイムでクラウドに送信し、逆にクラウドからデバイスに指示を送るのに利用されることがあります。

モバイルアプリケーション:
モバイルアプリケーションがサーバーとリアルタイムに通信する必要がある場合、WebSocketが有用です。例えば、リアルタイムな通知、更新、チャットなどが挙げられます。

サーバーレスアーキテクチャ:
AWS LambdaやAmazon API Gatewayと組み合わせて、WebSocketをサーバーレスアーキテクチャに統合することができます。Lambdaを使用すると、サーバーレス関数がWebSocketイベントを処理できます。

リアルタイムデータ分析:
データのリアルタイム分析が必要な場合、WebSocketを使用してクライアントがリアルタイムでデータを受信できるようにすることが考えられます。

API Gatewayを使用したWebSocket:
Amazon API Gatewayを使用して、WebSocket APIを簡単に構築できる。これにより、サーバーレスアーキテクチャや既存のバックエンドサービスとの統合が容易になります。

チャットアプリケーション:
チャットアプリケーションは、WebSocketを使用してリアルタイムなメッセージングを提供する典型的な例です。WebSocketは、クライアントとサーバー間の低レイテンシ通信を実現します。

上記のケース以外にも、要件やアプリケーションの性質によってはWebSocketが有用であることがあります。AWSでは、Amazon API GatewayやAWS App Runnerなど、WebSocketをサポートするさまざまなサービスが提供されています。


## VPCリンク

API Gatewayからプライベートサブネット内のAWSリソースへアクセスさせたい場合はVPCリンクを作成します。これにより、APIとプライベートサブネット内のリソースとの間で、インターネットを経由しないセキュアな通信が可能になります。

## オーソライザー

API Gatewayのオーソライザーを使用すると、APIへのアクセス制御を実装することができます。オーソライザーには、Amazon Cognitoのユーザープールを使用する方法と、Lambda関数を使用する方法があります。
Amazon Cognitoのユーザープールを使用する方法は、Amazon Cognitoが提供するマネージド型の認証機能を使用するため、開発者は認証プロセスについて自身で管理する必要がありません。

## ステージ

API Gatewayでは、ステージという概念を使用して、APIの異なるバージョンや開発段階を管理します。これにより、開発、テスト、本番などの異なる環境でAPIを個別に管理できます。

### [Canaryリリース](https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/canary-release.html)
Canaryリリースは、新しいバージョンのAPIを段階的にリリースする方法です。まず、既存の本番ステージに新しいAPIバージョンをデプロイし、一部のトラフィックを新しいバージョンに向けます。
JQuery の ready の実装


**コメント欄から情報頂きましたのでコメント欄を参照ください**



# JQuery の ready の実装

DIV でもなんでも ready が実行できて追加要素の描画完了時に実行してくれるのでどういう実装してるのかと思ってソース読んだら setTimeout してた

[JQuery 3.7.1 のソース](https://code.jquery.com/jquery-3.7.1.js)

## 一部抜粋
``` javascript
if ( document.readyState === "complete" ||
	( document.readyState !== "loading" && !document.documentElement.doScroll ) ) {

	// Handle it asynchronously to allow scripts the opportunity to delay ready
	window.setTimeout( jQuery.ready );

}
```

## 動作を推測
* setTimeout を呼び出す
* 描画含む他のタスクに処理が一旦切り替わる
* 描画処理が終わったら処理に戻ってくる
* 結果として描画終了後に処理を続行することになる
という一連の流れのおかげで動的に DIV 等を追加した後に ready すると描画後に実行される
ということっぽい

## ready を意識する状況
* 動的にDIV等の要素追加をした後にすぐにサイズを測ると 0 を返してくる時、ready後だと想定通りのサイズが返ってくる
* 動的にDIV等の要素追加をした後にスクロールポジションが想定していない値になっている時、ready後だと想定通りのサイズが返ってくる
Vue3でBuildするとwatchEffect()が動作しなくなる

## はじめに
### 概要
Vue3で``` yarn run dev ```を使用して動作確認したのち、```yarn run build```を実行して```yarn run preview```を動作確認をするとwatchEffect()が動作しなくなったので、調査した時の個人的な備忘です

### 環境
- Vue3
- Typescript
- Vite
- Docker

## 調査
### 検証①
[GithubのIssue](https://github.com/vuejs/core/issues/5707)に同じような問題が挙がっていたので確認
どうやらVueのバージョンが古いよう
```diff_json: package.json
  "dependencies": {
    "pinia": "^2.0.30",
-    "vue": "^3.2.45",
+    "vue": "^3.4.3",
    "vue-router": "^4.1.6"
  }
```

#### 結果
変化なし...
どうやら違うよう

### 検証②
確認していたらどうやらwatchEffect()内で監視しているデータが正しく変更されていないよう
データを追っていくとselectタグ内でv-modelしている値をscriptタグ内でrefし忘れていた

```vue: hoge.vue(template)
<template>
    <select v-model="month" @change="changeMonth(month)" >
        <option v-for="monthFor in monthList" :key="monthFor" :value="monthFor">{{ monthFor }}月</option>
    </select>
</template>
```

```diff_vue: hoge.vue(script)
<script setup lang="ts">
import { date } from '@/stores/date'
import { ref } from 'vue'

const dateStore = date()

const nowDate = new Date()
const thisMonth = nowDate.getMonth() + 1

- const month = dateStore.month
+ const month = ref(dateStore.month)

const monthList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

const changeMonth = (selectedMonth: number): void => {
    dateStore.setMonth(selectedMonth)
}

</script>
```

#### 結果
buildしても動いた！

## まとめ
単純な凡ミスでした笑
ただ``` yarn run dev ```で動いてbuildして動かなくなるのは謎ですね...
Amazon Route53(フィフティースリー)

## はじめに
この記事はAWS SAA試験勉強のための、Amazon Route53に関する知識のまとめです。

## Amazon Route53とは


エッジロケーションで使用されるDNSサービス。

アプリケーションとWebサーバーおよびその他のリソースの状態とパフォーマンスを監視するヘルスチェック機能を提供します。

## ヘルスチェック

Route53のヘルスチェックはインターネット経由でアクセスできるエンドポイントに使用可能あるため、オンプレミスにも使用できます。


## エイリアス(ALIAS)
- S3バケットにドメイン名でアクセスするためには、Route53のエイリアス機能を使って、S3バケットにエイリアスを設定します
- ELBとAutoScalingを使用してEC2上にWebサイトを構築し、Route53のエイリアスとしてELBのエンドポイントを紐づけることが出来ます
- Route53ホストゾーンにおいてAliasレコードを利用して、API Gatewayエンドポイントを設定することができる。Route53ホストゾーンのAliasレコードを利用して、ALBやCloudFrontなどのAWSサービスをドメインに関連付けて、URLを公開することができます
- エイリアスレコードを作成してCloudFrontを構成することで、Route53のDNSレコードにCloudFrontを設定してドメインを関連付けることができます

### DNSレコード設定の一般論(AWSでも同様)
IPv4に基づいたドメイン設定をする場合は、**Aレコードタイプ**にすることが必要。IPv6 アドレスの場合は**AAAA レコード**。

## ルーティングポリシー

### 加重ルーティング
ABテストのために新サービスをリリースしたサーバーに一定割合のユーザーを誘導したい場合は、**加重ルーティングポリシー**。
サーバーごとに性能の偏りがある場合などに、それぞれのサーバーに加重をかけてトラフィックを分散させるには、加重ルーティングを構成します

 ### 位置情報ルーティング
 **位置情報ルーティング**を使用すると、ユーザーの地理的位置に基づいてトラフィックを処理するリソースが選択されます。この機能によって、ユーザーの位置に応じて言語表示やトラフィック処理方法を変更することが可能となります。

### フェイルオーバールーティング
メインに障害が発生した場合に自動でサブにルーティングするポリシー。
Amazon Route 53の DNS **フェイルオーバー**機能では、複数のEC2インスタンスの正常性をチェックし正常なリソースのみを使用して DNS クエリに応答するように、DNSレベルでルーティングすることができます。




(Route53に限らず一般論として)フェールオーバーには以下の種類があります。

- フェールオーバー(アクティブ/パッシブ)
プライマリリソースをアクティブなリソースとしてルーティングする。
障害が発生したらセカンダリにルーティングする。

- フェールオーバー(アクティブ/アクティブ)
複数のリソースをプライマリとしてルーティングする。
障害が発生した場合、正常なリソースにフェールバックする。

この仕組みを利用して、Route53でDR環境の構築もできます。

ラウンドロビンはリソースを順番に利用すること。


### 複数値回答ルーティングポリシー
複数のリソースに対してヘルスチェックを行い、正常なリソースの中から最大8個のIPアドレスを回答します。

## シャッフルシャーディングと エニーキャスト ルーティング

DDoS 攻撃中にも適切なエンドユーザーがアプリケーションの利用を継続することができるように支援する機能。

## DR環境構成

本番環境に加えて、遠隔地向けのDR環境を別リージョンに設置して、２つの構成をRoute53で連携することで災害発生時の切り替えを自動化することができます。

## トラフィックフロー

Route53において複雑なルーティングを設定するにはトラフィックフローを用いてルーティングの順序を詳細に設定します。

## Route 53 Resolver


Route 53 Resolverは、VPCにデフォルトで提供されるDNSサーバーで、インターネット上に公開されたリソースの名前解決と、VPC内のリソースの名前解決ができます。
Google ColabのKaggle用データが消えてしまったのでGoogleドライブと連携させた

# 何が起こった？
昨日、Kaggle APIとGoogle Colabを連携させ、快適な開発環境が構築できて満足していました。ところが、朝起きてみると、昨日せっせと作ったはずの分析結果や予測結果、提出用ファイル一式が全部なくなっていました。ちーん。。。

どうやら、Google Colabを一定時間利用していないと、セッションが切れてカーネルがデタッチされ、ファイルやインストール済みのライブラリが消えてしまうようです。Kaggleに投稿した結果ファイルだけはKaggle側に保存されているのだけれど、いろいろ試行錯誤して「次はこれを投稿してみよう」と思っていたファイルはもう残っていない。。。あー、なるほど。そういう仕様でしたか。

調べてみると、「一定時間以上操作がない（90分ルール）」と「連続で長時間利用している（12時間ルール）」の2つの原因でセッションが切れるようでした。90分ルールはまあ分かる。開発よりも別のことを優先していたわけだから。しかし12時間ぶっ通しで集中して作業していたら、突然セッションが切れてファイルが消えてしまうのは、考えるだけでも恐ろしい。おじさん想像しただけで泣いちゃう。

<img width=200 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3666147/750873d5-adfe-fe11-a119-196f33d7b5d6.png">


# 対策：Google ColabとGoogleドライブとの連携
幸い、Google ColabとGoogleドライブは簡単に連携できます。下記のコードを実行することで、Google Colabの/content/driveディレクトリの下に、GoogleドライブのMyDriveディレクトリをマウントさせることができます。
~~~.py
from google.colab import drive
drive.mount('/content/drive')
~~~
これで、Google ColabからGoogleドライブ上のファイルを直接読み書きできるようになりました。

あとは、Google Colabの最初のセルに、環境構築用のコマンド一式をまとめておけば、朝起きてポチっと実行するだけで、Kaggle用に必要なライブラリやファイル一式が準備できるようになります。

私のノートブックでは、一番最初のセルに下記のような感じで設定しています。Googleドライブとの連携ついでに、GoogleドライブのKaggle用ディレクトリにkaggle.jsonファイルを置いて、Kaggle API用の認証を自動で済ませられるようにしています。

~~~.py
# ライブラリのインストールとデータの入手
! pip install -q pycaret
! pip install -q kaggle

# GoogleドライブをGoogle Colabにマウント
from google.colab import drive
drive.mount('/content/drive')

# 環境変数にプロジェクト用のフォルダを登録
%env KAGGLE_HOME=/content/drive/MyDrive/kaggle
%env KAGGLE_PJ=titanic                      # Googleドライブ上のフォルダ名
%env KAGGLE_COMPETITION=titanic             # コンペの名前（ダウンロード時に使用）

# Kaggle APIキーをGoogleドライブからGoogle Colabにコピー
! mkdir ~/.kaggle
! cp $KAGGLE_HOME/kaggle.json ~/.kaggle/
! chmod 600 ~/.kaggle/kaggle.json

# Dataの取得
! kaggle competitions download -c $KAGGLE_COMPETITION
! unzip -n ./$KAGGLE_COMPETITION.zip -d $KAGGLE_HOME/$KAGGLE_PJ
~~~

こうしておけば、titanicから別のコンペに参加する場合でも、最初のセルの
~~~.py
%env KAGGLE_PJ=titanic                           # Googleドライブ上のフォルダ名
%env KAGGLE_COMPETITION=titanic             # コンペの名前（ダウンロード時に使用）
~~~
を変えてやるだけで、ファイル置き場を簡単に切り替えることができます。
コンペの名前は、各コンペのDataタブの下の方にコマンドラインに書かれているので、「-c」オプションの横にある名前をコピペします。Titanicの場合は下記のような感じです。
![Kaggleコマンド.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3666147/55dd5976-619d-681c-8a61-43fecdf23ae2.png)



ちなみに、Google Colabでの環境変数の指定方法は、上にあるように「%env」で行います。私は「!export KAGGLE_PJ=titanic」とやろうとして、うまくいかず、ちょっとハマりました。

# 参考にしたページ
https://kenko-keep.com/12hour-90minit/

https://teratail.com/questions/336887

https://blog.kikagaku.co.jp/google-colab-drive-mount/

https://qiita.com/sakaia/items/c8367e75d9c8fd38e7bf

https://hiyokoyarou.com/
Go によるsessionの処理

## はじめに
Goでのsessionの扱いについてわかりやすく説明することを目標に記事を書きました。

## そもそもsessionとは？
・DBではなくサーバーに保存される情報で、容量はサーバーの容量に依存する。
・key,valueを設定して好きな値を保存できる。
・sessionに保存されるid でクライアントのcookieと結びつく。
・ログイン後はログアウトするまで基本的に消さないデータ。有効期限を設定しているなら、それを超えたら消える。

## Goでのsessionの扱い
sessionを保存するのに便利なパッケージのgorilla sessionを使用してsessionの扱いを紹介します。
https://github.com/gorilla/sessions

まずsessionを保存するためのstoreを作成します。
```
var cs *sessions.CookieStore = sessions.NewCookieStore([]byte("secret-key-xxxxx”))
```
ここの引数の[]byte("secret-key-xxxxx”) は秘密鍵になります。
```
ses, _ := cs.Get(rq,”session_name”)
```
そして作成したsessionに値を詰めていきます。
```
ses.Values[“name”] = rq.PostFormValue(“name”)
ses.Values[“pass”] = rq.PostFormValue(“pass”)
```
注意しないといけないのは、ses.Valuesは空のインターフェースなので、型アサーションをして型を変換しなければならない点です。
詰め終わったらsessionを保存しておきましょう。saveしないとsessionの値は消えてしまいます。
```
ses.Save(request,writer)
```
こうして、sessionから値を取り出すことが可能となります。
```
ses[key] = value
```
ちなみにSession IDは元から構造体Sessionに用意されています。
```
type Session struct {
	// The ID of the session, generated by stores. It should not be used for
	// user data.
	ID string
	// Values contains the user-data for the session.
	Values  map[interface{}]interface{}
	Options *Options
	IsNew   bool
	// contains filtered or unexported fields
}
```
Rails APIとReactを使用したウェブサイトのXSSとCSPの対策について

### はじめに
Ruby on Rails APIとReactを使用したウェブアプリケーションのセキュリティ設計について、
特にXSS(クロスサイトスクリプティング)とCSP(コンテンツセキュリティポリシー)に焦点を当ててまとめました。

## XSS（クロスサイトスクリプティング）
XSSは、ウェブページに不正なスクリプトが注入され、エンドユーザーのブラウザ上で実行されるセキュリティ攻撃です。
これにより、ユーザーのセッション情報の盗用やマルウェアの配布などが発生するリスクがあります。

### Railsにおける対策
**JSONレスポンスのサニタイズ** : 
- JSON形式でデータを返す場合は、適切にエスケープ処理を行います。

**パラメータの検証** : 
- 入力されたデータを適切に検証し、不正な入力を防ぎます。
**Strong Parameters** の使用: 不要なパラメータをフィルタリングします。

### Reactでの対策
**データバインディング**: 
- ReactはデフォルトでHTMLをエスケープしますが、dangerouslySetInnerHTMLの使用は避けるべき
**ユーザー入力のサニタイズ**: 
- ユーザー入力を扱う場合は、DOMPurifyなどのライブラリを使用してサニタイズします。

## CSP（コンテンツセキュリティポリシー）
CSPは、ウェブページがどのリソースを読み込めるかをブラウザに指示するセキュリティ標準です。
外部のスクリプトやスタイルの読み込みを制限することで、XSS攻撃のリスクを低減します。

### Rails APIでの実装
**CSPヘッダーの設定**: secure_headersなどのgemを使用してCSPヘッダーを設定します。
**ポリシーの調整**: 必要に応じてスクリプトやスタイルのソースを調整します。

### Reactでの対応
インラインスタイルとスクリプトの避ける: CSPを厳格にすると、インラインスタイルやスクリプトがブロックされる可能性があります。これを回避するためには、外部ファイルの使用が推奨されます。

## まとめ
XSSとCSPは、Rails APIとReactを使用したウェブアプリケーションのセキュリティにおいて重要な役割を果たします。適切なサニタイズとデータバインディングを行い、セキュリティ対策を施すことで、攻撃リスクを効果的に低減できます。

## 単語まとめ
- **サニタイズ**とは
  - サニタイズは、アプリケーションに渡される不正な入力を「清浄化」するプロセスです。これにより、スクリプトの注入やSQLインジェクションなどの攻撃を防ぎます。
  入力データを適切にエスケープし、不正なコードが実行されないようにします。

Rails APIでのサニタイズ例
``` Ruby
# Rails API - サニタイズされたパラメータの例
def create
  sanitized_params = sanitize_user_input(user_params)
  @user = User.new(sanitized_params)
  # ...
end

private
def user_params
  params.require(:user).permit(:name, :email)
end

def sanitize_user_input(params)
  params.each do |key, value|
    params[key] = ActionController::Base.helpers.sanitize(value)
  end
end
```

- **データバインディング**とは
  - ユーザーインターフェイス要素（例えば、フォームの入力）とアプリケーションのデータソース（例えば、データベースのレコード）を連携させるプロセスです。
  - セキュリティの観点: Reactでは、データバインディングを通じて不正なスクリプトを注入されるリスクがあります。これを防ぐために、ReactはデフォルトでHTMLのエスケープ処理を行います。

Reactでのデータバインディング例
``` jsx
// React - 安全なデータバインディングの例
class UserForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = { name: '' };
  }

  handleChange = (event) => {
    this.setState({ name: event.target.value });
  }

  render() {
    return (
      <form>
        <label>
          Name:
          <input type="text" value={this.state.name} onChange={this.handleChange} />
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}
```

この例では、ReactのsetStateを使用してフォームの入力値を安全にデータバインディングしています。Reactは自動的にHTMLをエスケープしています。
この点に関しては追加で記事をまとめる予定です。
ベイズ統計モデリング 写経4

### 3.4.4 リストとデータフレーム

リストは異なるタイプの要素で構成されるベクトル

``` r
mylist = list(a=1:3, b=matrix(1:6,nrow=2), c="hello world")
mylist
```

    ## $a
    ## [1] 1 2 3
    ## 
    ## $b
    ##      [,1] [,2] [,3]
    ## [1,]    1    3    5
    ## [2,]    2    4    6
    ## 
    ## $c
    ## [1] "hello world"

リストの要素aにアクセスする

``` r
mylist$a
```

    ## [1] 1 2 3

aの２番目の要素にアクセス

``` r
mylist$a[2]
```

    ## [1] 2

最初の要素にアクセス

``` r
mylist[[1]]
```

    ## [1] 1 2 3

最初の要素の2番目にアクセス

``` r
mylist[[1]][2]
```

    ## [1] 2

\[\]が１つだと、最初の要素の名前とその項目のlistが返される

``` r
firstlis = mylist[1]
firstlis
```

    ## $a
    ## [1] 1 2 3

``` r
class(firstlis)
```

    ## [1] "list"

データフレーム型はlistの行列版

``` r
d=data.frame(Integers = 1:3, NumberNames = c("one","two","three"))
d
```

    ##   Integers NumberNames
    ## 1        1         one
    ## 2        2         two
    ## 3        3       three

データフレームの各要素にアクセス

``` r
d$NumberNames
```

    ## [1] "one"   "two"   "three"

2列目の要素にアクセス

``` r
d[[2]]
```

    ## [1] "one"   "two"   "three"

2列目を抽出したdataframeを返す

``` r
d[2]
```

    ##   NumberNames
    ## 1         one
    ## 2         two
    ## 3       three

2列目にアクセス

``` r
d[,2]
```

    ## [1] "one"   "two"   "three"

2行目にアクセス

``` r
d[2,]
```

    ##   Integers NumberNames
    ## 2        2         two
【Ansible備忘録】Ansibleで対話型のコマンドに対応する（expectモジュール）

# 本記事のターゲット
- Ansible初学者
- 実務でAnsibleを使用しているエンジニア
- 対話型、対話形式のコマンドやインストールの自動化に困っている方

# 前書き
ソフトウェアの中には、dnfモジュールではなく「install.sh」のようなシェルスクリプトを実行してインストールするものがあります。
その際、実行するだけでインストールを完了してくれるものもあれば、インストール途中に質問を投げかけ「**yes/no**」を入力させる**対話型**のものもあります。

もし対話型のソフトウェアのインストールをAnsibleで自動化する場合、Shellモジュール等でそのまま実行しても質問のタイミングでこけてしまいます。
自動化を実現する為には「**expectモジュール**」を活用する必要があるので、以下にその方法を記載します。

尚、今回はapacheのインストールを例に紹介します。
> 「ん？apacheならdnfモジュールを使えば良いのでは？:thinking:」

とかいう野暮なことは聞かないでください。
（対話型インストールのソフトウェアを探すのは流石にシンドイ…:expressionless:）

<br>

※参考にする場合は自己責任でお願いします。
※expectモジュールを使用する場合、**pexpect**を対象ノード側にインストールしておく必要があります。


# expectモジュールの記載例

```ruby:main.yml
- name: apacheのインストール（dnfモジュール未使用） #任意の名称
  expect:
    command: dnf install httpd
    responses:
      "Is this ok \\[y/N\\]": y
```
### command
shellモジュールやcommandモジュールのように**実行したいコマンド**を記載します。

### responses
```
"<質問内容>":<回答内容>
```
上記のように記載します。
「:」より左側の**質問内容**部分はインストール途中で確認を求められる際の文章になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3339646/4479b3b2-cc13-518b-63b0-6ac4d2c21dc8.png)




#### responses記載時の注意点
「:」よりも左側の**質問内容**の文中に`[]`、`()`、`?`、`.`などの正規表現として用いられる記号が含まれている場合、**`\\`** を使用してエスケープする必要があります。

# 裏ワザ（自己責任）
> []、()、?、.などの正規表現として用いられる記号が含まれている場合、「\\\」を使用してエスケープする必要があります。

と上述しましたが、複数の正規表現が使われている場合、上手くエスケープできないことがあります。

そこで`[]`、`()`、`?`、`.`などの正規表現が含まれていない部分のみを`responses`に記載してみたところ、コケることなく正常終了しました。:sweat_smile:

質問文の全文ではなく、一部が記載されていれば問題ないと判断されるみたいですね。
ただ、詳細設計書に質問内容自体も記載されている現場の場合、この方法はNGを喰らうかもしれませんね…

```ruby:記載例
- name: apacheのインストール（dnfモジュール未使用） #任意の名称
  expect:
    command: dnf install httpd
    responses:
      "Is this ok": y
```

# 終わりに
主要なミドルウェアはdnfモジュールでインストール可能ですが、場合によっては"**PJ特有**"のミドルウェアを使用することもしばしばあります。（大人の事情的な。。）
rpmが配布されているミドルウェアであれば良いのですが、必ずしもそうとは限りません。
もしAnsibleで自動化する必要がある上、インストールするミドルウェアが対話型インストールだった場合、今回紹介した「expectモジュール」を活用して頂ければと思います。
他の人の設定を気軽に試す方法(Neovim)

## はじめに

Neovimで他の人の設定を試したいこと、ありませんか？
本記事では自分の `~/.local/share/nvim/` や `~/.local/state/nvim/` を汚さずに、他の人の設定を試す方法を紹介します。

## 環境

- OS：macOS Sonoma 14.0
- Neovim：v0.10.0-dev-2021+gee2127363

## 他の人の設定を試す方法

### 他の人の設定ファイルを取得する

まずは他の人の設定ファイルを取得します。

私の設定ファイルは以下にあります。

https://github.com/uhooi/dotfiles/tree/06ffa25e51ea5348f29a96346af6f44c3c502a06/.config/nvim

`git clone` （または `ghq get` ）で取得するのが手っ取り早いです。

```shell-session
$ git clone https://github.com/uhooi/dotfiles.git
```

### 設定ファイルを配置する

`~/.config/` に適当な名前（例: `uhooi` ）のフォルダを作成し、そこに設定ファイルを配置します。

私は以下のようにして設定ファイルをコピーしました。

```shell-session
$ mkdir ~/.config/uhooi
$ cp -r ~/ghq/github.com/uhooi/dotfiles/.config/nvim/* ~/.config/uhooi/
```

### Neovimを起動する

あとは `NVIM_APPNAME={.configに作成したフォルダ名} nvim` を実行して起動するだけです。

私の場合は以下です。

```shell-session
$ NVIM_APPNAME=uhooi nvim
```

通常は `~/.config/nvim/` に設定ファイルがあり、 `~/.local/share/nvim/` や `~/.local/state/nvim/` を汚します。
しかし `NVIM_APPNAME` を指定することで `~/.config/{NVIM_APPNAME}/` の設定ファイルが使われ、 `~/.local/share/{NVIM_APPNAME}/` や `~/.local/state/{NVIM_APPNAME}/` を汚します。

### 設定ファイルとキャッシュを削除する

試し終わったら、設定ファイルとキャッシュを削除します。

私の場合は以下です。

```shell-session
$ rm -r ~/ghq/github.com/uhooi/dotfiles/
$ rm -r ~/.config/uhooi/
$ rm -r ~/.local/share/uhooi/
$ rm -r ~/.local/state/uhooi/
$ rm -r ~/.cache/uhooi/
```

## おわりに

たったこれだけで他の人の設定を試せました。
自分のキャッシュも汚さないので、気軽に試せると思います :relaxed:
【個人開発】近くの図書館に読みたい本が入荷されたときに通知するLINE Botを作りました。

## はじめに
こんにちは！都内文系大学生の@StStuです。
私はプログラミングにまだまだ通じていないのですが、勉強も兼ねて、「<b>近くの図書館に読みたい本が入荷されたときに通知するLINE Bot</b>」を作りました。

名称はそのままですが、「<b>新着図書通知Bot</b>」です…

LPはこちらから！

https://stock-stu.com/library_notify/

## 新着図書通知Botについて
今回作成した新着図書通知Botについて簡単にご紹介させてください。


:::note warn
記事内に誤記や勘違い等ありましたら、ご指摘いただければ幸いです…
:::



### 新着図書通知Botのたった一つの機能
今まで自分でいくつかアプリを作ってきたのですが、毎回機能を増やそうと躍起になって、本来の目的を見失うことが多々ありました。
今回は、その反省を活かし、一つのことだけができるように特化しました。
それは、「家の近くの図書館に、読みたい新刊が入荷されたときに通知する」という機能です。

現在、いわゆるMPVの状態で、細かい課金機能などは、これから拡充していこうと考えています。

### 作った動機
本当はこういったアプリ・Botを作成するときは、マーケットイン（顧客ありきの考え方）の考え方が大事なのだろうと思います。
しかし今回のBotは、完全に自分本位で作成しました。
一義的な動機としては、LINE BotをPythonのライブラリを通じて自分で作り上げてみたいというものでしたが、せっかくならば自分のニーズ（新刊図書を早く読みたい！）を満たすものが良いと考え、このBotの作成に至りました。
人気の新刊図書は入荷から少し経つと、すぐに行列ができて、借りられるのが数カ月先といったことがよく起こります（本当は全ての新刊を購入することができたらよかったのですが…）。

もし、同じニーズをお持ちの方がいらっしゃったら、ぜひご利用いただければなと存じます。

### 使っている技術
- Python
- Flask
- LINE Bot
- Docker

が主なものです。
Flaskを用いてVPS上にサーバーを作成し、Webhookとして利用しています。
VPS上に環境を作成するに当たって、Dockerを利用しています。

#### Python・Flask
DockerのPythonイメージを利用して、Webhookサーバーを作成しています。
またユーザー情報や、読みたい本を保存するために、sqlite 3データベースを使用しています。
sqlalchemyを使用しているため、SQL文をわざわざ勉強する必要がなく非常に簡便です。

#### カーリル様のAPI
図書館の蔵書検索のために、[カーリル様のAPI](https://calil.jp/doc/api_ref.html)を利用しています。
カーリル様のAPIなしには、今回のアプリを作ることはできませんでした。この場を借りて感謝申し上げます。
カーリル様が開発している[OpenBD](https://openbd.jp/)を使用して、ISBNという書籍コードから書籍名を取得しています。

#### 郵便番号検索API
[zipcloud](https://zipcloud.ibsnet.co.jp/doc/api)様のAPIを利用して、郵便番号から住所を取得しています。

#### LINE Bot
![Screenshot_20240102-223443-portrait.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609788/bd770e81-cf99-c888-0d87-a0a478274e2c.png)
最近、[LIFF](https://developers.line.biz/ja/docs/liff/overview/)も流行っているようなのですが、ユーザーに対するプッシュ通知が必要だった上、作成コストも比較的低そうなので、LINE Botを作成するのが最も適していると考えました。

#### Docker

Dockerについての知識が浅く、環境構築には大変時間がかかりました…
外部サイトにはなりますが、環境構築に際してこちらのサイトの情報は非常に参考になりました。

https://vps-one.site/docker-flask-deployment-sakura-vps/

### ChatGPTとの関係
私のような初学者にとって、ChatGPTは本当に欠かせない存在です。
先行文献を読まずとも、6割くらいの作業は完璧にこなしてくれます。

その一方で、ChatGPTの誤りの数は決して少なくありません。
そのため、初学者にとってはこのようなやり方が効率が良いように感じています。
1. 自分の知らない分野について、ChatGPTに概観を説明してもらう
2. 自分なりにその分野について簡単に反芻する
3. 自分なりにコードを書くor解釈したものをChatGPTにぶつける
4. ChatGPTのフィードバックを受け、新しく質問をしたり、ある程度見識を得た状態で、ChatGPTにコード作成を依頼する

これの1のステップをおろそかにして、ChatGPTに丸投げしてしまうと、結局ChatGPTの誤りに全く気づけず、遠回りをしてしまうようなことが非常に多かったです。

LPはこちらから！

https://stock-stu.com/library_notify/lp/top/
[WatchOS] CMBatchedSensorManagerが使えるApple Watchのモデルについて

# はじめに
watchOS 10では`High Frequency Motion API`が使えるようになりましたが、どのAppleWatchを購入すれば使えるのか分からず困っていました。

どの端末を購入すれば`watchOS 10.0+`で使える`CMBatchedSensorManager`で正常に値が取れるかどうか、技術仕様を確認することに。

https://developer.apple.com/documentation/coremotion/cmbatchedsensormanager

ちなみに、Appleのサイトには以下のように記載がありました。

> ジャイロスコープと加速度センサーがさらに改善されたApple Watch Series 8とUltraでは、高周波データにアクセスして方向や加速度の急な変化を検出できます。

<img width="300" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631585/abe84488-7c1b-ae01-dc40-5a029f6c047b.png">

https://developer.apple.com/jp/watchos/

少なくとも`Apple Watch Series 8`と`Ultra`では使えそうです。

WWDC23の`What’s new in Core Motion` でも一部触れられていましたが、どのモデルが対応するのかまでは分からずです。

https://developer.apple.com/videos/play/wwdc2023/10179/

# 調べた結果
技術仕様を確認したところ`高重力加速度センサー`と書かれていれば使えそうです。
現在購入できるApple Watchでは使えそうですが、`Apple Watch Series 7`では`加速度センサー`となっていて使えないのではないかと思います。

以下、技術仕様のリンクを載せておきます。

#### Apple Watch Series 9 - 技術仕様
https://support.apple.com/kb/SP905?viewlocale=ja_JP&locale=ja_JP

> センサー: 
常時計測の高度計
高重力加速度センサー
ハイダイナミックレンジジャイロスコープ

#### Apple Watch Ultra 2 - 技術仕様
https://support.apple.com/kb/SP906?viewlocale=ja_JP&locale=ja_JP

> センサー:
常時計測の高度計
高重力加速度センサー
ハイダイナミックレンジジャイロスコープ

#### Apple Watch SE (第2世代) - 技術仕様
https://support.apple.com/kb/SP877?viewlocale=ja_JP&locale=ja_JP

> 特徴:
高重力加速度センサー
最大256G（転倒検出と衝突事故検出対応）
ハイダイナミックレンジジャイロスコープ


#### 過去のモデルの仕様を確認する
https://support.apple.com/kb/SP860?viewlocale=ja_JP&locale=ja_JP

> 特長:
加速度センサー
最大32G（転倒検出対応）
ジャイロスコープ

https://support.apple.com/kb/SP878?viewlocale=ja_JP&locale=ja_JP

> 特徴:
高重力加速度センサー
最大256G（転倒検出と衝突事故検出対応）
ハイダイナミックレンジジャイロスコープ

https://support.apple.com/kb/SP879?viewlocale=ja_JP&locale=ja_JP

> 特徴:
高重力加速度センサー
最大256G（転倒検出と衝突事故検出対応）
ハイダイナミックレンジジャイロスコープ

# 実際に購入した端末での動作確認
`Apple Watch SE (第2世代)`を購入して動かしてみました

サポート自体は問題なくしていそうです

```swift
CMBatchedSensorManager.authorizationStatus // authorized
CMBatchedSensorManager.isDeviceMotionSupported // true
CMBatchedSensorManager.isAccelerometerSupported //true

let sensor = CMBatchedSensorManager()
sensor.deviceMotionDataFrequency // 200
sensor.accelerometerDataFrequency // 800

```

しかし、フォーラムのコメントでもあるように

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

`sensor.startDeviceMotionUpdates`
`sensor.startAccelerometerUpdates`
で`Error Domain=CMErrorDomain Code=109`となりデータが取得できませんでした。

##### 試した環境
`Xcode 15.0 Beta7(15A5229h)`
`Xcode 15.1 Beta(15C5028h)`
`Xcode 15.1(15C65)`

Xcodeのバグのようでもありますが、私の手元では今でも発生しているようでした。

今後使えるようになったら(問題の解消方法が分かったら)この記事も更新するようにします🙏

# おわりに

`MBatchedSensorManager`をサポートしているモデルはわかりましたが、ドキュメントもまだ整備されていないようなので様子を見ながら引き続き調べていこうと思います

https://developer.apple.com/documentation/coremotion/cmbatchedsensormanager


# 参考
https://www.tomsguide.com/features/watchos-10-exclusive-these-are-the-biggest-apple-watch-upgrades-powered-by-new-developer-apis

https://developer.apple.com/forums/thread/733858
YDLIDAR T-Mini Pro &大阪工業大学 事例

大阪工業大学の宮脇健三郎さんのYDLIDAR T-Mini Proを使ったロボット事例を紹介します！

小さなT-Mini Proが逆さまに設置され、かろうじて床をナビゲートしています！ビデオを入手：https://twitter.com/i/status/1723255091703193823

---------------------------------------------------------------------
Check this robot case sharing with YDLIDAR T-Mini Pro of 宮脇健三郎 San from Osaka Institute of Technology! 

Little T-Mini Pro installed upside down which barely on the floor for navigation, and it's working well! Get Video at: https://twitter.com/i/status/1723255091703193823

![F-FrvB3boAAOlz-.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3491551/fbffe7e0-5a6d-cd92-0314-66deda5eaa9b.jpeg)

![F-FrwVkbEAAOW8I.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3491551/78eeebbd-32a7-b3e4-17b3-d00d59b3c0d9.jpeg)

![FvunItNagAAVh0O.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3491551/100ca449-380d-d3a9-0943-d677c1552830.png)
三項演算子で条件分岐させる

## はじめに
「依頼を探す」ページが表示される時は依頼の検索機能が、

そして「提案を探す」ページが表示される時には提案の検索機能が・・・

といったように、表示されるビューによって処理の内容を変えたい時は「三項演算子」を使うのが良いそうです。

https://www.php.net/manual/ja/language.operators.comparison.php#language.operators.comparison.ternary

> 『(expr1) ? (expr2) : (expr3) という式は、式1 が true の場合に 式2 を、 式1 が false の場合に 式3 を値とします。』（PHP公式ドキュメントより）

## 環境
PHP 8.2.7
Laravel 9.52.16

## 問題
* 検索フォームを実装しようとしている
* 提案・依頼の両方を検索できるようにしたい
* つまり、表示するビュー次第でルートを分岐させたい

```php: commons.search_form.blade.php
{{-- 今はまだ依頼の検索しかできないが、将来的に提案の検索もできるようにしたい --}}
<div>
    <form action="{{ route('sales-search') }}" method="GET" class="flex">
        <input type="text" name="keyword" placeholder="キーワードで依頼を検索…" class="shadow appearance-none border rounded w-full py-1 px-2 text-gray-700 leading-tight focus:outline-none focus:shadow-outline mr-2">    
        <button type="submit" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-1 px-2 rounded focus:outline-none focus:shadow-outline">検索</button>
    </form>
</div>
```

## 解決策
* 三項演算子を使う

https://www.php.net/manual/ja/language.operators.comparison.php#language.operators.comparison.ternary

```php: commons.search_form.blade.php
{{-- これでアクセスするルートを分岐できる --}}
<div>
    <form action="{{ $isSalesPage ? route('sales-search') : route('purchases-search') }}" method="GET" class="flex">
        <input type="text" name="keyword" placeholder="キーワードで依頼を検索…" class="shadow appearance-none border rounded w-full py-1 px-2 text-gray-700 leading-tight focus:outline-none focus:shadow-outline mr-2">    
        <button type="submit" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-1 px-2 rounded focus:outline-none focus:shadow-outline">検索</button>
    </form>
</div>
```

関係するコントローラ内で、論理値を持たせる$isSalesPageを定義することにより、

現在表示しているページが「依頼」ページか「提案」ページかを判断します。

もし依頼ページが表示されていたら依頼を検索するロジックを持つコントローラに、

逆に提案ページが表示されていたら提案を検索するロジックを持つコントローラにルーティングされるようになります。

参考に、依頼に関するコントローラはつぎのようになっています

```php: SalesOrdersController.php（一部）
// 最初に表示される「依頼」のページ
    public function othersSales()
    {
        $isSalesPage = true;

        $user = Auth::user();

        $othersSales = SalesOrder::where('user_id', '!=', Auth::id())->orderBy('created_at', 'desc')->paginate(10);

        return view('sales.others_sales', [ // この先にsearch_form.blade.phpが@includeされている
            'user' => $user,
            'othersSales' => $othersSales,
            'isSalesPage' => $isSalesPage, 
        ]);
    }
    
// $isSalesPageがtrueの時にルーティングされる
    public function search(Request $request)
    {
        $isSalesPage = true;

        $user = Auth::user();

        $keyword = request('keyword');

        $othersSales = SalesOrder::where('user_id', '!=', Auth::id())->where('title', 'like', "%{$keyword}%")->orderBy('created_at', 'desc')->paginate(10);

        return view('sales.others_sales', [
            'user' => $user,
            'othersSales' => $othersSales,
            'isSalesPage' => $isSalesPage,
        ]);
    }
```


## おわりに
分岐処理ができるところを、別のファイルを作ることで対応していた節もあるので、

これを機により効率的なコーディングを意識したいと思います。
大文字判定 Python3編

https://paiza.jp/works/mondai/conditions_branch/conditions_branch__bool_step2

これは解法が２つある
ひとつはそれぞれの言語で大文字判定メソッドがあればそれが使える
pythonの場合は`isupper()`（小文字は`islower()`)

```py
if str(input()).isupper() == True:
    print('YES')
else:
    print('NO')

```
<b>（2024.01.04修正）
上記のような==TRUEというような書き方はPythonの書き方ではだめだそうです。
私もオリジナルのガイドを読んで初めて知りました。。。
なので修正しておきます。</b>

```py
if str(input()).isupper():
    print('YES')
else:
    print('NO')

```


もう１つはUnicordの番号を調べる方法
これは`ord()`を使う
つまり、大文字の”A"と”Z"の間になければOKってことですね
UnicordはVBA屋時代のときにもお世話になってましたね

```py
c = input()

if ord(c) >= ord("A") and ord(c) <= ord("Z"):
    print("YES")
else:
    print("NO")
```

<b>（2024.01.04修正）
コメントを頂いたのですが、コメントのご提案が私のよりもっと直感的なので、こちらも
書き直しておきます</b>

```py
c = input()

if ord("A")　<= ord(c) <= ord("Z"):
    print("YES")
else:
    print("NO")
```
文系出身からシステムエンジニアに就職してつらかったこと

## はじめに
今回の記事は私が文系でかじった程度の技術でシステムエンジニアに就職したときにつらかったことを備忘録として記事にしていきます！  
## 現在の状況
初めに簡単に現在の状況について書いていきます  
* 社会人歴2年目
* 設計～テスト実施まで担当として対応
* 使用言語:Nodejs
* フレームワーク:React
* その他:AWS
自分でいうのもなんですが去年からでは考えられないような活躍ができています（笑）
特にミーティングに参加して疑問点の聞き出し、技術面から回答できるようになった点はとても成長を感じます。  
プログラミングに関してもまだわからないことは多いですがTypescriptを用いて１人で実装できるようになりました。
## つらかったこと  
初年度はほんとにつらかったです。  
とにかく何もわからない！
入社前はProgateを用いて独学をやっていたのですがいざ実践となるとほぼ役に立たない！  
どんなことがつらかったのか項目ごとに書いていきます！
### 専門用語がわからない
IT業界の基礎的な知識がないため会話の内容がまずわからない！  
UT(ユニットテスト)ってなに？とか
「ブランチ切って実装してね！」のブランチがまずわからない！
こんな状態でした。
周りからしたらなんでこんな奴が就職できたんだと思っていたと思います。
働いてみると自分でもなんで就職できたのかわからない状態でした。
### Git難しすぎ
題目通りです。
Git操作のコマンドが何が何だかわからない状態でした。
初心者過ぎてブランチ名日本語にして注意されていました。  
今ではほとんど起きないってわかりますがPushやCloneでもぶっ壊してしまうのではと思ってしまい作業の速度が全然上がりませんでした。

理解できて来た方法としてはとりあえずコマンドを打ちまくって意味を理解していきました。
結局やらないと身につかなかったです
もしもGitについてわからない！勉強したい場合こちらのサイトから学習してみてください！
基礎的なことはこちらで理解しました。
[サル先生のGit入門【プロジェクト管理ツールBacklog】](https://backlog.com/ja/git-tutorial/)
### システムの動きがわからない
実際に配属して説明を受けますがコードを見ても全然理解できない
小さい修正でも何もわからないといったことが多く、最初の1か月は仕事ができたと思った瞬間が1つもなかったです。  
これは正直コードを書いていくことで自然と理解することができました。
またシステムを設計していくと必然的に理解できるようになります。
### インフラ関連で苦労
私はシステム開発でAWSを用いた開発をしていますが設定がすることに一苦労といった感じでした。
今では資格取得のために勉強しよう！と思えるほど好きになりましたが最初は似た名前なのに全然違う出会ったりS3ってなに？何がしたいの？といった感じでした。
これも公式を見ながら１つずつ勉強していくことで今では教えられるほどに成長できました。  
## 最後に
この記事を読まれている方の多くは未経験や経験の浅い方ばかりでしょう。
最初はわからないことばっかりだと思うのでわからないということを上司であったり周りに伝えるようにしましょう！
私の場合は優しく教えてくれる先輩ばっかりだったので何とかなりました！
今では後輩を持ち教えながら自分の作業を行っています。
精神論ですが自分はできる！と強い気持ちを持ってとにかく学習していくことが重要です！
1つ1つ悩みを解決させていきましょう！
AWS Certified Data Analytics対策まとめ

Exam Readiness: AWS Certified Data Analytics - Specialty
https://www.aws.training/Details/eLearning?id=46612

上記公式のデジタルトレーニングを元に自分が大事だと思ったことをまとめたものになります。

-試験の概要

・この試験で検証される能力

AWS データ分析サービスを定義し、相互に統合する方法を理解する
AWS のデータ分析サービスを収集、ストレージ、処理、可視化というデータライフサイクルに適合させる方法を説明する

この試験で出題される技術的な内容の 5 つの分野

1,収集 (18%)
    1.1 収集システムの運用特性を決定する
    1.2 データの頻度、ボリューム、ソースを処理する収集システムを選択する
    1.3 順序、形式、圧縮など、データの主な属性に対応する収集システムを選択する
2,ストレージとデータ管理 (22%)
    2.1 分析用のストレージソリューションの運用特性を決定する
    2.2 データアクセスと取得パターンを決定する
    2.3 適切なデータレイアウト、スキーマ、構造、形式を選択する
    2.4 使用パターンとビジネス要件に基づいてデータライフサイクルを定義する
    2.5 データのカタログ作成とメタデータの管理に適切なシステムを決定する
3,処理 (24%)
    3.1 適切なデータ処理ソリューションの要件を決定する
    3.2 分析用データの変換と準備のソリューションを設計する
    3.3 データ処理ソリューションを自動化および運用化する
4,分析と可視化 (18%)
    4.1 分析と可視化ソリューションの運用特性を決定する
    4.2 対象のシナリオに適したデータ分析ソリューションを選択する
    4.3 対象のシナリオに適したデータ可視化ソリューションを選択する
5,セキュリティ (18%)
    5.1 適切な認証および認可メカニズムを選択する
    5.2 データ保護と暗号化技術を適用する
    5.3 データガバナンスとコンプライアンス管理を適用する

-出題される問題について

シナリオ: この部分から、問題の基本的な状況を把握できます。正しい解答を見つけるのに役立つサービス、問題、要件が記載されています。正しい解答を特定するために必要な情報が不足していることはありません。シナリオの情報を追加または除外して考えようとしないでください。

問題: 問題では、解答で必ず満たすべき具体的な条件が指定されます。複数の解答が必要な場合、問題には必要な解答の数が必ず明記されています。何も指定されていない場合、正しい解答はただ 1 つのみです。

-以下のアプローチに従って問題を分析する
問題分析のこのアプローチには、以下の 4 つのステップがあります。

1,AWS のサービスと状況特性を特定する。
2,問題点と懸念点を特定する。
3,要件を特定する。
4,答えとして求められているものを特定する。
ベイズ統計モデリング 写経3

### 3.4.3 行列と配列

列数を指定

``` r
matrix(1:6, ncol=3)
```

    ##      [,1] [,2] [,3]
    ## [1,]    1    3    5
    ## [2,]    2    4    6

行数を指定

``` r
matrix(1:6,nrow=2)
```

    ##      [,1] [,2] [,3]
    ## [1,]    1    3    5
    ## [2,]    2    4    6

行と列に名前を付ける

``` r
matrix(1:6,nrow=2, dimnames = list(TheRowDimName=c("Row1Name","Row2Name"), TheColDimName=c("Col1Name","Col2Name","Col3Name")))
```

    ##              TheColDimName
    ## TheRowDimName Col1Name Col2Name Col3Name
    ##      Row1Name        1        3        5
    ##      Row2Name        2        4        6

行列の要素を指定.　名前を指定

``` r
x = matrix(1:6,nrow=2, dimnames = list(TheRowDimName=c("Row1Name","Row2Name"), TheColDimName=c("Col1Name","Col2Name","Col3Name")))
x["Row2Name","Col3Name"]
```

    ## [1] 6

要素のindexで指定

``` r
x[2,3]
```

    ## [1] 6

列の長さを指定

``` r
x[2,1:3]
```

    ## Col1Name Col2Name Col3Name 
    ##        2        4        6

列の要素を省略

``` r
x[2,]
```

    ## Col1Name Col2Name Col3Name 
    ##        2        4        6

行の要素を省略

``` r
x[,3]
```

    ## Row1Name Row2Name 
    ##        5        6

2番目を表示

``` r
x[2]
```

    ## [1] 2

array型

``` r
a = array(1:24, dim=c(3,4,2),
          dimnames = list(
            RowDimName = c("r1", "r2","r3"),
            ColDimName = c("c1", "c2","c3","c4"),
            LayDimName = c("l1", "l2")
          ))
a
```

    ## , , LayDimName = l1
    ## 
    ##           ColDimName
    ## RowDimName c1 c2 c3 c4
    ##         r1  1  4  7 10
    ##         r2  2  5  8 11
    ##         r3  3  6  9 12
    ## 
    ## , , LayDimName = l2
    ## 
    ##           ColDimName
    ## RowDimName c1 c2 c3 c4
    ##         r1 13 16 19 22
    ##         r2 14 17 20 23
    ##         r3 15 18 21 24

3行2層目の要素を返す

``` r
a["r3",,"l2"]
```

    ## c1 c2 c3 c4 
    ## 15 18 21 24

3行2層目の要素を返す

``` r
a["r3","c4",]
```

    ## l1 l2 
    ## 12 24
Qiita CLI をセットアップしてみた【非IT従事者向け手順書】

# はじめに
Qiita CLI のインストールができている前提でセットアップを行う記事です。
インストールがまだの場合は以下の記事を参照してください。
- Node.js のインストール
https://qiita.com/yurimiyasakura/items/d4fe132fc9bc8189eff4
- Qiita CLI をインストールしてみた
https://qiita.com/yurimiyasakura/items/e9ccede805f2b700aba8


非IT向けのStep by Step ですので、回りくどく感じるかもしれませんが、ご容赦ください。

# 事前準備
1. コマンドプロンプトを開きます。
2. 以下のコマンドでQiita を保存するディレクトリに移動します。
    ~~~
    cd [フォルダパス]
    ~~~

# init コマンドを実行する
このコマンドを実行する事で、以下の項目が生成されます。
- .gitignore
- GitHub Actions のワークフローファイル
- ユーザー設定ファイル（qiita.config.json）

以下のコマンドを入力して、Enterキーを押します。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/b8edd2b0-7f25-2d4c-a356-d19cef0ba686.png)

Success と出ればOKです。

# Qiita のトークンを発行する
Qiita CLI にログインする為にトークンを発行します。

1. Qiita にログインします。
2. 以下にアクセスします。
    https://qiita.com/settings/tokens/new 

3. 「read_qiita」と「write_qiita」にチェックが入っているのを確認します。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/76e63ff4-7031-8fb2-066c-35bad1fb4687.png)

4. 「発行する」をクリックします。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/230204be-d479-3f4b-03ed-cf1d74d1de48.png)

5. 発行されたトークンをコピーします。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/3430ee41-b694-c48a-1746-42fecb33f4d2.png)

# Qiita CLI のログイン
1. 以下のコマンドを入力し、Enterキーを押します。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/0ee9e1de-098c-a4e0-0d44-cab129dd50c7.png)

2. 発行したトークンを貼り付け、Enterキーを押します。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/5604c80f-6937-41b4-3e24-11b73b702ec7.png)
    ログインが完了しましたと出れば完了です。

# Qiita Preview の起動
以下のコマンドを入力し、Enterキーを押します。
~~~
npx qiita preview
~~~
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/db7e2ccc-351d-fb47-0066-7f4ccb4eaeea.png)


※コマンド実行時に Qiita に投稿している記事がダウンロードされます。

## 【補足】既存記事のダウンロード場所について
Qiita の記事を保存するディレクトリ（フォルダ）を開くと、「public」というフォルダが生成されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/6608edc0-39e5-c538-58d8-6dd88889b68e.png)

この「public」フォルダ内に Qiita に投稿している記事が入っています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/3c06e8db-eec5-437f-1866-bcd78186b6c4.png)

記事の名前はURL末尾のユニーク番号です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/55ef91b6-afbf-1034-724c-07a2c4dae2c5.png)

以上でセットアップは完了です。
お疲れ様でした！
PID 制御シミュレータ 動作確認

## はじめに

python で作った PID 制御の関数がどの程度の精度で動作するのか、理論的な計算値と比較してみました。

## 前提条件

PID 制御器の伝達関数 $C(s)$ は以下とする。

$$C(s) = K_p + K_i/s + K_ds$$

制御対象の伝達関数 $G(s)$ は以下とする。

$$G(s) = 1/s$$

これは 測定値 $y(t)$ の変化率が 操作量 $u(t)$ に比例するというモデルに相当する。

$$\dot{y}(t) = u(t)$$

以上から、システム全体としての伝達関数 $K(s)$ は以下となる。

$$K(s) = \frac{C(s)G(s)}{C(s)G(s) + 1}$$

これに ステップ関数 $R(s) = 1/s$ を入力した時の応答 $Y(s)$ は以下となる。

$$Y(s) = K(s)R(s) = \frac{C(s)G(s)}{C(s)G(s) + 1}\cdot\frac{1}{s} = \frac{K_ds^2 + K_ps +Ki}{(K_d + 1)s^2 + K_ps +K_i}\cdot\frac{1}{s}$$

## 計算方法

以下に示す 3 通りの方法で計算して、結果を比較する。

### 方法 1: 数学的に解く方法

$Y(s)$ を逆ラプラス変換して $y(t)$ を求められるが、上記の条件であれば数式の形で比較的簡単に解くことができる。

そこで、まずこの方法で $y(t)$ を求めた結果を $Y_1$ としてプロットする。

### 方法 2: Python-Control を使う方法

python のパッケージで Python-Control という便利な機能があるので、これを使って計算してみることにする。

これは上記で定義した 伝達関数 $C(s)$, $G(s)$ を引数として関数を呼び出すと $y(t)$ が (数値計算結果として) 求められるというもので、
この結果を $Y_2$ とする。

### 方法 3: 近似的な数値計算

$\Delta{t}$ を十分微小な時間変化と仮定して、微分・積分を近似値として求める。

以下では、制御対象の測定量 $y(t)$ を離散的な数列 $y_i$ として表現する。

同様に、偏差量 $e(t)$ および 操作量 $u(t)$ を各々 $e_i$, $u_i$ と表現する。

また、目標値 $r(t)$ は $r(t) = 1$ とする。

経過時間 $t$ は $t = i\Delta{t}$ であるため、

$$y_i = y(i\Delta{t})$$

と相互変換できる。

初期条件として $i = 0$ のとき

$$y_0 = 0$$

$$e_0 = 0$$

とする。

$i \geqq 1$ のときは以下の手順で $y_i$ を計算する。

まず、フィードバックされた測定量 $y_{i-1}$ から偏差量 $e_i$ を求める。

$$e_i = 1 - y_{i-1}$$

次に、操作量 $u_i$ を以下の近似式によって求める。

$$u_i = K_p + K_i\bigg(\sum_{k=1}^{i} e_k\bigg)\Delta{t} + K_d\frac{e_i - e_{i-1}}{\Delta{t}}$$

すると、 $\dot{y}(t) = u(t)$ という条件から $y_i$ は以下の式で近似できる。

$$y_i = y_{i-1} + u_i\Delta{t}$$

以上の手順を繰り返すことで、逐次的に $y_i$ を求めることができる。

この方法によって求めた結果を $Y_3$ とする。

## 実行結果

実際に行ってみると、思ったより合っていることが確認できました。

$Y_1$, $Y_2$ は厳密な解なので、ある意味、合ってないと逆におかしいです。

$Y_3$ はあくまで近似計算なので多少誤差があることを予想しておりましたが、以外と正確なことがわかります。

## 実行方法について

pidctest.py を Jupyter Lab のセルに読み込んで実行します。

また、Python-Control を使うため、以下の通りパッケージをインストールの必要があります。

```bash
conda install -c conda-forge control slycot
```

または

```bash
pip install control slycot
```

以下にJupyter Labで実行するpid-control-test.ipynbのリンクを記載します。

https://github.com/ATSU3/pid-control-test/blob/main/pid-control-test.ipynb
ラズパイでgithubの追加認証できた話

# ラズパイのOSでまさか２要素認証通るとは？

奇跡的じゃないですか。

## 手順はそんなにむずかしくない

認証が通っているパソコンでブラウザを立ち上げ、githubの設定のところで
`add passkey device`実行。

スマホをパスキーデバイスとして追加します。何度か失敗したけど、（その理由も謎だけど）最終的にはうまくいきました。

## 次にラズパイでブラウザ起動します

ブラウザに自分のプライベートリポジトリのURLをせっせと入力します。

そうすると、パスキーがスマホ端末におくられます。

それを`raspbian OS browser`にも入力します。

これで大丈夫。

ブラウザからgithub できるので、`github discussion`もできます。