OmniAICreator/Qiita-1.07M huggingface dataset:
【python】@propertyと@x.setter でデコレータ

「きれいなpythonコードを書きたいな」と思いつつ、デコレータ(decorator)を使ってみることにしました。decorator が関数のラッパとしてどう働くかは数多の解説があります。

ここでは、getter/setterの関数の実装として使ってみます。単純に参照や代入をするとき、そこに自分独自の処理を含めた関数として実装したいときに使えます。

# デコレータを使った変数の取得と設定の実装

単純に、整数値という制約をつけて書いてみました。

```python:test.py
class Something(object):

    def __init__(self):
        self._param:int = 10
    
    @property
    def param(self) -> int:
        if isinstance(self._param,int):
                return self._param
        else:
            raise ValueError("not integer. {}".format(self._param.__class__.__name__))

    @param.setter
    def param(self, p_):
        if isinstance(p_, int):
            self._param = p_
        else:
            raise ValueError("not a integer. {}".format(p_.__class__.__name__))


try:
    obj = Something()
    print("[1]", obj.param)
    obj.param = 200
    print("[2]", obj.param)
    obj.param = 1.23
    print("[3]", obj.param)
except Exception as e:
    print(e)
```

実行してみると、

```
$ python test.py
[1] 10
[2] 200
not a integer. float
```

エラーの使い方、これで良いのかな。入出力の型については、型を定義することで対応できるのかもしれないと思う。もっと他の場面で使えるのだと思う。典型例は何だろうか？

### 参考

下記のサイトを参考にしました。

https://www.freecodecamp.org/news/python-property-decorator/

本家本元の解説、どこかにあるのかな。

# まとめ

とりあえず使ってきたいと思う。「ここでこそ」という典型的な使用例を知りたい。
(2021/05/24)
aplayでは、ボリューム調整できない罠

そんなこと知ってるって？
いや、備忘録なんで許して。

例えば、wavを再生したいとき、コマンドはみなさんaplayを使うと思うんでよ。

```shell
aplay -D plughw:0 test.wav
```

こんな感じで使用しますよね？

で、再生できるとなるとこんなこと思ったりしませんか？

ボリューム調整の引数が見当たらないなー。

はっきりいうとaplayにはそんな機能見当たりません。 （私調べ）

マニュアルでも見当たらなかったから確かなはず、違ったら教えてください。

で結局どうするかというと、

amixerを使うにたどり着きました。

```shell
amixer -c0 sset Headphone 100% &&\
aplay -D plughw:0 test.wav
```


この「Headphone」という部分は、私のraspberry pi4bがこれじゃないとイヤイヤと聞かなかったものでこのように設定しております。
確認方法は、以下のコマンドでみてね。

```shell
amixer scontrols
```

###で！

実際のところは、複数の音声を流すとかあるよね。
例えば、①の音声を流した後に、②の音声を再生したいとかとか。
この場合、①の音声が以上に音量が大きく録音されてたりすると、②との音量の格差に音が聞き取れないとかあるよね。
そういうときに、さっきのamixerを分けてコマンドするといい感じに調整できるというわけだ。

```shell
amixer -c0 sset Headphone 50% &&\
aplay -D plughw:0 test1.wav

amixer -c0 sset Headphone 100% &&\
aplay -D plughw:0 test2.wav
```

とまあ、それだけの話。
RealtimeDatabase（JSON）に時刻を保存するときのメモ

RealtimeDatabaseに限らずJSON形式で保存する場合も同様

## JSON形式のデータベースへの保存
ミリ秒単位の文字列で現在時刻の取得

```typescript:typescript
      createdAt: new Date().getTime(),
```

## JSON形式のデータベースからの取り出し
dayjsを使用して復元

```typescript:typescript
      import dayjs from "dayjs";
      dayjs(createdAt).fromNow();
```


## フォーマット指定例

```typescript:typescript
登録日時：{`${dayjs(post.createdAt).format("YYYY/M/D hh:mm")} `}
```
【PHP】世界1わかりやすいPHPの$_GETメソッド

$_GETメソッドとは、linkや送信ボタンからデータを受け取って、URLに付与できる。

つまりページ替えができるってことだ


```PHP
<?php
if (isset($_GET["page"])) {
    $page = $_GET["page"];
} else {
    $page = 1;
}

?>
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>サンプル</title>
</head>
<body>
    <p>現在 <?php echo $page; ?> ページ目です。</p>

    <p>
        <?php if ($page > 1) : ?>
            <a href="?page=<?php echo ($page - 1); ?>">前のページへ</a>
        <?php endif; ?>
        <?php if ($page < 2) : ?>
            <a href="?page=<?php echo ($page + 1); ?>">次のページへ</a>
        <?php endif; ?>
    </p>
</body>
</html>
```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954863/5a88e2a2-d0fb-0077-df23-040ee2786b0d.png)



実行後↓



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954863/7f62c8c3-dea3-509f-14c0-1d6c5891a951.png)
外部のデータ保管サービスについて

# Amazon Web Services（略称：AWS）
インターネット通販で有名な米Amazonが提供している、サーバーに関するサービスの総称です。
サーバーを作成するサービス、データを保存するサービスなど、100種類以上の様々なサービスを提供しています。

# 「Amazon S3」
画像などが保存できるストレージサービスのこと AWS・S3を利用する際は、セキュリティー対策が必要であること


# 導入までの流れ
1,AWSアカウント作成
2,S3で保存先を作成
3,S3に保存する処理を記述　（ローカル環境）
4,S3に保存する処理を記述　（本番環境）

# 必要なセキュリティー対策
ログインを二段階に設定（二段階認証）
利用制限付きのユーザーを使用（IAMユーザー）
保存機能にアクセス制限を設定（バケットポリシー ）
秘密情報を変数に代入して使用（環境変数）
秘密情報を誤操作でコミットしないよう防止する機能（git-secrets）

# 実装にあたり…
S３の導入にあたり、Herokuにおけるデータベースがdownになっており、いくら更新してもHerokuに反映されないということがありました。
一つの機能を実装したら必ず本番環境でテストすることを心がけたいです。
M1 Macbookでdocker loginが失敗する

# 環境
macOS Big Sur 11.3.1
Docker Desktop 3.3.3(64133)

# エラー内容
```
➜  ~ docker login
Authenticating with existing credentials...
Login did not succeed, error: Error response from daemon: Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username (******):
Password:
Error response from daemon: Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
```
# 解決策
Docker Desktop -> Troubleshoot -> Reset to factory defaults -> Reset to factory defaults

ほぼ下記の内容
https://forums.docker.com/t/not-work-docker-pull-apple-m1/108612/4
[備忘録]redmine-centos-ansibleでインストールに失敗したときの対処法（create locale ja_JP.UTF-8でこけた編）

# はじめに
マビノギで現在所属しているギルドの情報交換用に、Redmineのサーバーを構築しようとしていました。
が、案の定と言うべきか構築中にエラーが発生して解決に手間取りました（２時間くらい）。
「コマンド５個実行するだけでインストール完了」と言う割には、ずいぶん手がかかった。。

あまりに解決しないストレスで禿げそうだったので、同様のエラーにぶつかった人が困らないよう
そして自分自身の備忘のため、ここに対応内容を記す。

#発生したエラー
今回Redmineのインストールに使ったのはこれ。

https://github.com/farend/redmine-centos-ansible

当然、これだけだとやり方がさっぱりだったので、下記webサイトで紹介された手順を実行した。

https://masalib.hatenablog.com/entry/2019/03/02/000000

で、後半の
`ansible-playbook -i hosts site.yml`
を実行したところ、エラーが発生。

エラーが出たのはplaybookのうち

```
TASK [pg : set locale ja_JP.UTF-8]
```
にあたる部分。

```bash:
localedef -i ja_JP -c -f UTF-8 -A /usr/share/locale/locale.alias ja_JP.UTF-8
```

のコマンドを実行したときにエラーが発生したようで、出てきたエラーが

```:エラー内容
[error] ????????? `UTF-8' ????????: ??????????????????????
[error] ?????????????? `ANSI_X3.4-1968' ?????????: ??????????????????????
```

・・・なにこれ。

# 対処法
?だらけでまともなエラー文も吐いてくれなかったので、辛うじて読み取れた単語
localedef
UTF-8
ANSI_X3.4-1968

localedefでのエラーということで、エラーの原因として考えられるのは下記か。
・ja_JP、UTF-8のデータが収められたファイルがない？
・locale.aliasがない？　→　ファイルは存在していたので、今回は関係なしか。

あと、今回導入していた
redmine-centos-ansible

を手掛かりに、ひたすらググること２時間・・・
ストレスのあまり禿げそうになったところで、見た目それっぽいエラー文とその対処法が
紹介されたwebサイトを見つけたのです。

https://zatoima.github.io/postgresql-create-database-locale-error.html

```:エラー文（引用）
[postgres@pgsql ~]$ sudo localedef -i ja_JP -c -f UTF-8 -A /usr/share/locale/locale.alias ja_JP.UTF-8
[error] character map file `UTF-8' not found: No such file or directory
[error] default character map file `ANSI_X3.4-1968' not found: No such file or directory
```

・・・うん。見た目それっぽいエラー文。
このエラー文に従うと、どうやらUTF-8のcharacter mapファイルが無かった模様。
（なぜANSI_X3.4-1968も無いと怒られているのかは謎）

このサイトでは、対処法として`glibc-locale-source`と`glibc-langpack-en` 
のインストールが挙げられていたので、それに倣ってインストールを実行。
その後playbookをリトライ。

```
TASK [pg : create locale ja_JP.UTF-8] ****************************************************************************
changed: [localhost]

（中略）

ok: [localhost] => {
    "msg": "インストールが完了しました。 http://ipアドレス/redmine/ にアクセスしてください。"
}
```

・・・どうやら無事実行できたようです。

# おわりに

つかれた。
吐きそう。
頭痛い。

ぶたさんは事務員なので、本職でエンジニアの皆様ほどソフトウェアの知識も無ければ
論理的な思考や情報収集の訓練を受けてるわけでもありませんが
猿真似（豚真似？）の如く、こんな感じでどっこい頑張っています。
ぶひぶひ。
いきなりスプレッドシートが開けなくなったが、待っていたら復活した話

# スプレッドシートが消えた？
私の勤めている会社では、アルバイトのシフトを1つのスプレッドシートで管理しています。
このシートに記載されたシフトは、GASを活用してカレンダーや他のスプレッドシートと連携していました。そして、カレンダーでシフトを共有したり、入力されたシフトの情報を基に業務を割り振ったりしています。
いわばこのシートがハブとしての役割を持っていたわけです。

そのシートが、朝突然「消え」ました。

業務の割り振りを担当している方から「シフト管理シートが開けなくなっています！」と連絡を受けた時、私は軽くパニックになりました。というのも、そこに書かれたGASのスクリプトを復元できる自信が全くなかったからです。
私は「消え」たスプレッドシートに、各人のシフトを整形してGoogleカレンダーに登録するスクリプトや、毎月新しいシフト入力表を発行スクリプトなどを含め、数百行のスクリプトを書いていました。
さらに、このスプレッドシートに対し、他のシートから情報取得のためのアクセスがあります。それらとの親和性を考えると、再度ゼロからスクリプトを書き直すのは現実的ではありません。正直「終わった…」と思いました。
# 状況を整理すると…
* スプレッドシートにアクセスできない。「 現在、ファイルを開くことができません。アドレスを確認して、もう一度試してください。」というメッセージが出る
* Google Driveから検索するとヒットするので、完全に消えたわけではないのかも。
* ファイルサイズが「0バイト」になっている。謎
* 最終更新日時が「0:00」になっている
* ゴミ箱には入っていないので、誤って削除したわけではなさそう

ファイルサイズが「0バイト」になっているなどGoogle Driveも怪しく、ファイル破損も頭によぎりました。
#「終わった…」と思いながらも調べてみる。
結論から書くと、この問題を解決してくれたのはこのフォーラムのスレッドです。

https://support.google.com/drive/thread/99463070/i-cannot-open-one-of-my-google-docs-sorry-unable-to-open-the-file-at-this-time?hl=en

要約すると、「スプレッドシートが急に開けなくなった！でも1日待ってたら元に戻った！謎！」ということです。
「スプレッドシート　開けなくなった」とか、上記のエラーメッセージで調べても有用な情報が出てこず（上記エラーメッセージはスクリプトエディタへのアクセス権限がない時などにも出るもので、その情報が多く出てきました）、やむなく英語で調べていたところこのスレッドにたどり着きました。

会社の重要なファイルが消失しているなかで「とりあえず1日待ってみる」のはストレスでしたが、他に対処法もなさそうだったのでとりあえず放置してみました。
すると、何の前触れもなく、夕方突然ファイルが開けるようになったのです。終始謎です。1日待ったら戻った！って。一番モヤモヤします…

# おわりに
恐らくGoogle側の問題だとは思うのですが、突然ファイルが開けなくなったので（しかも開けなくなったファイルがそこそこ重要だったので）面喰らいました…今後同じような事象が発生した方の参考になれば幸いです。
【Flutter】Google fontsを使ってみる

Flutterでは何もしなければデフォルトのゴシック系のfontが表示されますが、Fontを変えたい、もう少し日本語のfontにしたい場合`Google fonts`を使うと便利です。

ここでは`Google fonts`のインストールのやり方と具体的な使い方について紹介します。

# Google fontsをインストールする

[puv.dev](https://pub.dev/)から`google_fonts`を検索してください

https://pub.dev/packages/google_fonts

`google_fonts`のページが表示されるので`Install`をクリックします。
![スクリーンショット 0003-05-24 21.55.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163786/8e6683d0-0d6e-f678-3d5b-f9381901ae21.png)

次のページにインストールするために必要なソースがのっています。

![スクリーンショット 0003-05-24 21.57.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163786/43b6612e-abbd-9a37-8e5f-4dc30cfdc02d.png)

`google_fonts: ^2.1.0`の部分を`pubspec.yaml`の`dependencies`に貼り付けてください。


```yaml
dependencies:
  google_fonts: ^2.1.0
```
vscodeならそのまま保存で自動インストールされます。
自動インストールされなかったら下記のcmdを叩いてみてください。

```terminal
flutter pub add google_fonts
```

# Google fontsを使って見る
まず、使いたいdartのファイル上でインポートしてください。

```dart
import 'package:google_fonts/google_fonts.dart';
```

## ページ全体に読み込ませる
ページ全体でGoogleのFontを使いたい場合は`MaterialApp`の`theme`内に記入してください。

```dart
MaterialApp(
  theme: ThemeData(
    textTheme: GoogleFonts.sawarabiMinchoTextTheme(
      Theme.of(context).textTheme,
    ),
  ),
);
```

## 個別で使用する

個別で使用する場合は`Text`の`style: GoogleFonts.使いたいフォント`で囲い、その中に色やfontSizeを設定していきます。

```dart
Text(
  'はじめる',
  style: GoogleFonts.sawarabiMincho(
    textStyle: Theme.of(context).textTheme.headline4
    color: Color(0xFF000000),
    fontSize: 20.0,
  ),
),
```
GoogleFonts内にある`Sawarabi Mincho`を使うとこのように表示されます。

![スクリーンショット 0003-05-24 22.13.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163786/1107870a-8e7e-56f9-8141-467486128e11.png)

## Fontの探し方
使いたいFontの探し方ですが
まずはGoogle Fontsのページを開いてください。

https://fonts.google.com/

Langageの選択があるのでここで`Japanese`を選択してください。
※探している書体が日本語の場合です。

![スクリーンショット 0003-05-24 22.15.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163786/20dc2a1e-d9db-8086-e4cc-94477634fdad.png)

ここでは`Sawarabi Mincho`を使いたいと思います。

![スクリーンショット 0003-05-24 22.20.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163786/4060c7de-270a-314a-b7ac-2f620637e1e4.png)

### Flutterでの探し方
GoogleFontsと記入した後、command keyを押しながらクリックします。

![スクリーンショット 0003-05-24 22.22.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163786/8335c176-e486-c313-341c-d113a781652c.png)

すると`google_font.dart`が表示されます。

![スクリーンショット 0003-05-24 22.24.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163786/27454ca1-a23a-e287-fc7e-4d790fe30e50.png)

こちらをしたにスクロールしていくとfontの名前が乗っているので検索するなりして探します。
![スクリーンショット 0003-05-24 22.25.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163786/e3cd4253-27a1-f02c-f75f-80be0a49e585.png)

`Sawarabi Mincho`を発見したので右側にある`GoogleFonts.sawarabiMincho`を使用したいところで貼り付ければOKです。

```dart
'Sawarabi Mincho': GoogleFonts.sawarabiMincho,
```
![スクリーンショット 0003-05-24 22.26.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163786/b1abc465-943f-49f1-605a-a56ed3ea4143.png)

以上がFlutterで`Google fonts`を使う簡単な説明でした。
CCNA試験学習(忘備録)〜ネットワーク基礎〜

#はじめに

私は4月からインフラエンジニアとしてSES企業に6月から就職が決まっています。
ネットワークの入門書を3冊読破し、資格試験の勉強を始める準備が整ったかと思ったので内定先でも推奨されているCCNAの受験を決めました。それでもやはり分からない単語も多いので、ここに書き留めていきたいと思います。
Ping-tの問題を解きながら忘備録として投稿させて頂きたいと思います。

####輻輳(ふくそう)

>様々なものが1ヶ所に集中して混雑している状態。

####ISP

>Internet Service Providerの略。「プロバイダ」と略称されることが多い。
公衆通信回線などを経由して契約者にインターネットへの接続を提供する事業者。
TCP/IPという技術で接続を可能にしている。

####イントラネット

>限定されたユーザー間でのネットワーク。社内ネットワークなど。

####ハイパーバイザー

>コンピュータを仮想化し、複数の異なるオペレーティングシステム（OS）を互いに干渉させずに並行して動作させられるようにするソフトウェア。
ただしホストOSを必要としないタイプのソフトを指す場合が多い。

####vSwitch

>virtual switchの略。(仮想スイッチ)
ソフトウェアを使ってコンピュータ内に擬似的に再現したスイッチのこと

####全二重通信方式（FULL DUPLEX）

>送りながら受け取れる。
電話の通話をイメージ。インターネットもフルデュプレックス。

####半二重通信方式(HALF DUPLEX)

>トランシーバーのように、いちいち送信と受信の切り換えを行い、聞いている間はしゃべれず、しゃべっている間は相手の話を聞くことができないような通信方式。送ると受け取りを同時にできない。
半二重通信方式が発生する可能性がある。コリジョンを検知した場合は、バックオフアルゴリズムを実行し、ランダムに計算された時間待機し、その後送信を再開する。

####２進数

>0,1を使って表す数値。コンピュータはどんな情報も2進数に変換する。
２進数データは**「バイナリデータ」**ともいう。

####10進数

>0,1,2,3,4,5,6,7,8,9を使って表す数値。
IPv4アドレスで登場。

####16進数

>0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,Fを使って表す数値。
IPv6アドレスで登場。

####符号化(エンコード)

>ある情報をバイナリデータに変換すること。

####複合化(デコード)

>バイナリデータを逆に戻すこと。

####帯域幅

>1秒間に送れる情報量。単位は**bps**

####ユニキャスト

>ネットワーク内でのデータの通信方法。1対１の通信。

####ブロードキャスト

>ネットワーク内でのデータの通信方法。１対全員の通信。

####マルチキャスト

>複数の通信相手に同じパケットを届けるために使われる1対多の通信方式で、特定のグループ宛に送られる。
アドレスは「224.0.0.0〜239.255.255.255」の中から使用される。

####IP(Internet Protocol)

>ネットワーク層、インターネット層のプロトコル。
IPアドレスを使用してエンドツーエンドの通信を可能にする。
・送りっぱなしの**コネクションレス型**
・保証はしないが最善を尽くす**ベストエフォート型**
・データを破棄したら破棄しっぱなし
というような特徴がある。
必要があれば他のプロトコルで補うスタンス。

####ARP(Address Resolution Protocol)

>IPアドレスからMACアドレスを調べる仕組み。
ブロードキャストでMACアドレスを尋ねる。**ARPリクエスト**
該当したMACアドレスはユニキャストで**ARPリプライ**で応える
**ARPテーブル**が存在するおかげで、何度もARPリクエストを送らなくても良い仕組みになっている。

####ICMP(Internet Control Message Protocol)

>エラー通知や問い合わせ情報を転送するためのプロトコル。
IPとセットで用いられ、IPの補助を行う。

####デフォルトゲートウェイ

>ゲートウェイとは、異なるネットワーク同士を接続するネットワーク機器の事。
ゲートウェイは、通信プロトコルを変換し、異なるプロトコルを用いたネットワークを繋げることができる。



#参考

デフォルトゲートウェイ　https://livra.geolocation.co.jp/iplearning/654/
NIC https://ja.wikipedia.org/wiki/%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E3%82%AB%E3%83%BC%E3%83%89
ハイパーバイザー　https://e-words.jp/w/%E3%83%8F%E3%82%A4%E3%83%91%E3%83%BC%E3%83%90%E3%82%A4%E3%82%B6%E3%83%BC.html
[Rails]link_toメソッドからcreateを実行する

# 記事の概要
　link_toでのcreateを実装したのでメモ。
　いつもcreate実行するときはform_withのフォームからユーザーが入力したものを送信してサーバー側で受け取りcreateすることが多い。しかし、ユーザーが何も情報を入力する必要がないとき(開発者が予め決めている時など)、リンクボタン押すだけでcreateアクションを実行することを想定します。


# コード
　ビューファイルの記述例。　hogesコントローラーのcreateアクションへのパスを指定し、その後ろに送りたいパラメータを記述する。そして、link_toの後ろにHTTPメソッドのPOSTを指定する!!　


```views/hoges/new.html

<%= link_to "fuga", hoges_path(user_id: current_user.id, hoge_name: current_user.name), method: :post %>
```

　受け取る側の記述。

```ruby:hoges_controller
class HogesController < ApplicationController

  def create 
    Hoge.create(user_id: params[:user_id], hoge_name: "#{params[:hoge_name]}")
  end
  
end
```
React入門 - Tips9 - null,undefined,空文字

# 目次


# nullとundefinedと空文字の違いについて


[こちら](https://qiita.com/katu_/items/a7a0087e615264d609b4)を参考にさせていただきました。
というか、こちらに全て書いてあります。

纏めます。

- nullは、意図して変数にnullを代入して値がないことを示す。
- undefinedは、
  変数を定義（初期化していない）した状態
  又は
  オブジェクトなどでキーが存在しない場合
  （キー自体に？がついて必須項目で無い場合などに、キーが存在しないなど）
- 空文字は、nullと似ているが、空文字が変数に入っている状態である。


# null、undefined、空文字判定

以下試してみました。

```typescript
const test1: string | null | undefined = '';
// const test2: string | null | undefined;  // これはtypescript的にエラー
const test3: string | null | undefined = undefined;
const test4: string | null | undefined = null;

console.log('test1-1:' +  (test1 === '' ? '=' : '≠' ))
console.log('test1-2:' +  (test1 === null ? '=' : '≠' ))
console.log('test1-3:' +  (test1 === undefined ? '=' : '≠' ))
if (test1) {
  console.log('test1-4:OK')
} else {
  console.log('test1-4:NG')
}

console.log('test3-1:' +  (test3 === '' ? '=' : '≠' ))
console.log('test3-2:' +  (test3 === null ? '=' : '≠' ))
console.log('test3-3:' +  (test3 === undefined ? '=' : '≠' ))
if (test3) {
  console.log('test3-4:OK')
} else {
  console.log('test3-4:NG')
}

console.log('test4-1:' +  (test3 === '' ? '=' : '≠' ))
console.log('test4-2:' +  (test3 === null ? '=' : '≠' ))
console.log('test4-3:' +  (test3 === undefined ? '=' : '≠' ))
if (test4) {
  console.log('test4-4:OK')
} else {
  console.log('test4-4:NG')
}
```


「null、undefined、空文字」を一度に判定したい場合、
つまり、値が入っていないことを確認したい場合、

```typescript
if (変数名)
```

でいけますね。

**<font color="red">==と===も違いがあるようですのでご注意を</font>**
React入門 - Tips8 - reactstrap

<!-- https://www.aizulab.com/blog/react-bootstrap/ -->

# 目次

# bootstrapとは

HTML／CSS／JavaScriptから構成される最も有名なWEBフレームワークです。
らしいです。
Javascriptも含むんですね。
よく知らんかったです。

Qiita投稿にあたって、CSSフレームワークの選定に少し迷いましたが、一番有名なものを
選べば実務で出会う可能性が高いかもしれないということで選びました。
（変わったやつをやってみたかったってのはあるんですが）

# bootstrapとreact-bootstrap

Reactアプリ用に再設計されたUIフレームワーク。
jQueryなど不要な依存関係を除いて、純粋なUIフレームワークとしている。
Reactコンポーネント化している。

なんと！
実装しながら躓きながら**<font color="red">reactstrap</font>**なるものを見つけました。
react-bootstrapとの比較はググるなり[ここ](https://npmcompare.com/compare/bootstrap,react-bootstrap,reactstrap)見るなりで。

今回は、**<font color="red">reactstrap</font>**を採用することとします。
なぜなら、躓きながらもそれでうまくいったため。。

# インストール

```
$ yarn add react-bootstrap bootstrap
```

# コーディング

Part9のコードをbootstrap化してみます。

```typescript
import React, {useState, useLayoutEffect} from 'react';
import { useFormik } from 'formik';
import * as Yup from "yup";
// import {Form, Button, InputGroup} from 'react-bootstrap';   // ★☆★☆react-bootstrapをimport
import 'bootstrap/dist/css/bootstrap.min.css';  // ★☆★☆bootstrapのcssをimport
import {Form, FormGroup, Button, Input, Label} from 'reactstrap'; // ★☆★☆reactstrapをimport

export const FormikTest: React.FC = () => {

  // 入力チェックスキーマ
  const validationSchema = 
    Yup.object({
      id: Yup.string()
        .required("idは必須項目です"),
      pwd: Yup.string().required("パスワードは必須項目です")
    });

  // formik定義
  const formik = useFormik({
      // 初期値の定義
      initialValues: {
        id: 'yokowake',
        pwd: '',
      },
      // バリデーション定義
      validationSchema,
      // サブミット時の処理を記述
      onSubmit: (values) => {
        alert('form data : ' + JSON.stringify(values))
      },
    });

    /** レンダー部分 */
    return (
        <Form onSubmit={formik.handleSubmit}>
          <div>
            <Label htmlFor="id">Id</Label>
            <Input
              type="text"
              id="id"
              name="id"
              onChange={formik.handleChange}
              value={formik.values.id}
            />
            {/* エラー表示 */}
            {formik.touched.id && formik.errors.id ? (
              <div className="error">
                <span style={{color: 'red'}}>{formik.errors.id}</span>
              </div>
            ) : null}
          </div>
          <div>
            <Label htmlFor="pwd">Pwd</Label>
            <Input
              type="text"
              id="pwd"
              name="pwd"
              onChange={formik.handleChange}
              value={formik.values.pwd}
            />
            {/* エラー表示 */}
            {formik.touched.pwd && formik.errors.pwd ? (
              <div className="error">
                <span style={{color: 'red'}}>{formik.errors.pwd}</span>
              </div>
            ) : null}
          </div>
          {/* サブミットボタン */}
          <Button onClick={() => formik.handleSubmit()}>Submit</Button>
        </Form>
    );
};

export default FormikTest;
```

見た目の確認と動作の確認を行ってみてください。

以上
tkinterのテキストボックスを入力選択状態にする方法:ショートカットキーでテキストボックスの選択する方法

#概要
tkinterでアプリのようなものを作っていて、ショートカットキーで入力ボックスを選択する方法がなかなか見つからなかったため、記事にします。

#結論

```python
txtBox_name.focus_set()
```
でできます。

#例
Shift + G  :2個めのテキストボックスを選択
Shift + F  :1個目のテキストボックスの内容を2個目に移動
ボタン　　　:1個目のテキストボックスの内容を2個目に移動

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/5a33cf4e-2e4f-e3f4-b7ef-14995004c7f6.png)



```python
import tkinter as tk

def next_box(event):
    editbox2.delete(0,tk.END)
    editbox2.insert(tk.END,editbox.get()) 
    
    editbox.delete(0,tk.END)

def select_box(event):
    editbox2.focus_set()

root = tk.Tk()
root.title(u"テスト画面")
root.geometry("400x200")

editbox = tk.Entry()
editbox.pack()

editbox2 = tk.Entry()
editbox2.pack()

button = tk.Button(text = '次ページ',width = 30)
button.pack()
button.bind('<Button-1>',next_box)


root.bind('<Shift-Key-F>',next_box)
root.bind('<Shift-Key-G>',select_box)
#root.bind('<Enter>',next_page)  #挙動がおかしい気がする

root.mainloop()

root.mainloop()
```
はじめてのシェルスクリプトでジャンケンゲーム

#はじめに
シェルスクリプトを初めて触った駆け出しエンジニアがジャンケンゲームを作成しました。


##ゲームの概要
* ジャンケンを始めるかどうかプレイヤーの入力を待つ
* y (yes)のときゲーム実行。 n (no)やその他の入力があった場合は、ゲームは始まらない
* プレイヤーは対話型の入力値で何を出すか決める
* コンピューターはランダムで、何を出すか決める
* 勝つまでゲームは続く。（負けor引き分けで終わらない）
* コンピューターに勝った時、それまでのゲーム数を表示させる

##ゲームのイメージ
![game1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969534/a4d03529-0ff3-a7b4-8d1a-6485d34e1713.png)

##コード
```.bash
#!/bin/bash

echo " >>> ジャンケンゲームを始めますか？"
echo ">>> y or n"
echo -n ">>>"
read val

### 定義
count_game=0

play_game() {
arr=( "グー" "チョキ" "パー" )

###　player入力
echo ">>>　選択して下さい"
echo ">>>　0:グー 1:チョキ 2:パー"
echo -n ">>>"
read val

### 入力チェック
if [[ ${#val} == 1 && $(echo $val | grep [0-2]) ]]
then
 ### 配列から要素を取得
 play_act=${arr[$val]}
else
 echo " 0 から 1 から 2 を入力してください！"
 exit 1
fi

### 0〜2の乱数を取得
while true
do
 num=$((RANDOM % 3))
 if (( 0 <= num && num <= 2))
 then
  break
 fi
done

### 配列から要素を取得
comp_act=${arr[$num]}

### 判定
if [[ "$play_act" == "$comp_act" ]]
then
 result="draw"
elif [[ "$play_act" == "グー" && "$comp_act" == "チョキ" ]]
then
 result="play"
elif [[ "$play_act" == "チョキ" && "$comp_act" == "パー" ]]
then
 result="play"
elif [[ "$play_act" == "パー" && "$comp_act" == "グー" ]]
then
 result="play"
elif [[ "$comp_act" == "グー" && "$play_act" == "チョキ" ]]
then
 result="comp"
elif [[ "$comp_act" == "チョキ" && "$play_act" == "パー" ]]
then
 result="comp"
elif [[ "$comp_act" == "パー" && "$play_act" == "グー" ]]
then
 result="comp"
fi


### 表示
echo "--- 自分 => [$play_act]"
echo "--- 相手 => [$comp_act]"
count_game=`expr $count_game + 1 `

### 判定
case "$result" in
 "play")
   echo "勝ちです"
   onemore=0
   ;;
 "comp")
   echo "負けです"
   onemore=1
   ;;
 "draw")
   echo "引き分けです"
   onemore=1
   ;;

### 負けた場合、再度呼び出し
if [ "$onemore" == 1 ]
then
 echo "勝つまで続けましょう!"
 play_game
else
 echo "おつかれさま！${count_game}戦目での勝利です！"
fi
}

if [[ ${#val} == 1 && ${val} == y ]]
then
 play_game
else
 echo "やらないんですね。はい。。"
fi
```

#おわりに
プログラミングにまだまだ不慣れなのと、初めてシェルスクリプトを書いたこともあり至らない点もあるかと思います。
多目に見ていただけると幸いです。。
React入門 - Tips7 - immer。オブジェクト配列のクローン

# 目次

# この記事を書くに至った理由

formikを使用し、繰り返し項目を使用する場面でよく分からないエラーが出て、少しはまりましたが解決しました。
結論は、formikの繰り返し項目と紐づけている定義のオブジェクト配列のクローンの仕方に問題があったようです。
（入力画面でその繰り返し項目を使用しました。確認画面へ遷移し戻るボタンで戻って来た場合に、遷移前の入力状態を復元させる部分でオブジェクト配列をクローンしているつもりが参照になっていました。それが原因で項目値をコードで変更させようとするとreadonly property的なエラーが出ていました。）

# オブジェクト配列のクローン

javascriptでのオブジェクト配列のクローンは簡単には出来ないみたいですね。
ディープコピーとかシャローコピーとかそんな言葉もありますね。
ディープコピーとかクローンについては、ググってください。

# 試したコード

```typescript
// 配列にするオブジェクト
type Test = {
    itm1: string;
    itm2: string;
}
// オブジェクト配列を含むオブジェクト（これを試します。）
type Tp = {
    tp1: string;
    tp2: string;
    test: Test[];
}

// 元ネタを初期化（値を入れておきます。）
const motoNeta: Tp = {tp1: '123', tp2: '456', test: [{itm1: '789',
itm2: '012'}, {itm1: '111', itm2: '222'}]}

// クローンできるか試すパターン
const {test, ...test2} = motoNeta; //１）元ネタをオブジェクト配列とそれ以外に分離
const slice = test.slice();  // ２）１）で分離したオブジェクト配列をslice
const spread: Test[] = [...test];  // ３）１）で分離したオブジェクト配列をスプレッド構文で展開
const assign = Object.assign([{}], test); // ４）１）で分離したオブジェクト配列にOBject.assignを使ってみる
const create = Object.create(test); // ５）１）で分離したオブジェクト配列にOBject.createを使ってみる
const jsonp: Test[] = JSON.parse(JSON.stringify(test))  // ６）１）で分離したオブジェクト配列にJSON.parse(JSON.stringify

// クローン出来ているか確認するため、test配列の一部を変更します。
test[0].itm1 = 'xxx'

// 全パターンを出力して確認します。
console.log(motoNeta)
console.log(test2)
console.log(test) //ＮＧ
console.log(slice) //ＮＧ
console.log(spread) //ＮＧ
console.log(assign) //ＮＧ
console.log(create) // ＮＧ
console.log(jsonp) //OK
```

出来るパターンは上記だと一つしかありませんね。
[こんなサイト](https://www.typescriptlang.org/play?#code/Q)で試してみてください。

JSON.stringifyで展開してJSON.parseする。
しかし**<font color="red">このやり方は、オブジェクトの中身がstringなどに限るようです。date型などの場合、おかしくなるとどっかのサイトに書いてありました。</font>**

# immer

現場にいる、他社さんに教えてもらいました。
immer。こんなのがあるんですね。
先の方法よりも簡単にクローンを作成することが出来る感じです。

[ここによると](https://qiita.com/wateru_09/items/8b7938719a87df62c887)

`yarn add immer`
でインストールし使用できるみたいです。

試したソースは以下。
こちらの場合は、
自分PCで試してもよりですが、[こんなとこだと](https://codesandbox.io/)すぐ試せます。

```typescript
import produce from "immer"

export default function App() {
  const baseState = [
      {
          todo: "Learn typescript",
          done: true
      },
      {
          todo: "Try immer",
          done: false
      }
  ]

  // クローン作成し、doneの値を変えてみる。
  const nextState = produce(baseState, draftState => {
      // draftState.push({todo: "Tweet about it"})  // 新しいクローンに要素追加を試す場合、コメントアウト解除してください。
      draftState[1].done = true
  })

  console.log('baseState');
  console.log(baseState);
  console.log('nextState');
  console.log(nextState);

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}
```

immer便利かもしれない。。
【Flutter】パッケージをGitでフォークしてカスタマイズする

pub.dev のパッケージをカスタマイズする時に便利な方法を見つけたので紹介します！

パッケージを使っていて、自分用の独自機能を追加したくなったり、バグを見つけて直したくなったりすることがあるかと思います。
そんな時に使えるのが、 今回の「**Git でフォークしてカスタマイズ**」です。

このやり方だと pub.devに公開されたパッケージからの入れ替えも簡単で flutter コード上は同じような扱いになります。さらにメンテナンス性も上がるのでかなりオススメです。

# やり方
pub.dev さからカスタマイズしたパッケージのページにアクセスします。
![スクリーンショット 2021-05-24 21.40.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535406/9d15f42e-a367-3ce5-1cda-28c61c56b849.png)

右サイドバーの Repository(GitHub) から GitHub のページに行きます。

![スクリーンショット 2021-05-24 21.41.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535406/a0c7ab91-72fa-c3e3-d6eb-d74e7d20119c.png)

GitHubにログインして、右上の Fork ボタンを押して、フォークします。

![スクリーンショット 2021-05-24 21.46.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535406/b0f43095-cab8-4c3a-3bc6-8d4288595515.png)

フォークしてできたリポジトリのURLをコピーします。

pubspec.yaml を開き、先ほどのURLで置き換えます。

```pubspec.yaml
dependencies:
  flutter:
    sdk: flutter
  Flutter-Sign-in-Button:
    git: https://github.com/fuku02/Flutter-Sign-in-Button # ←フォークしてできたリポジトリ
```

``` git: repository url ```と記述することでパッケージの参照元を変更できます。


これで、フォークしたリポジトリが Flutter で使えるようになりました。
あとは、リポジトリをクローンしてカスタマイズしていくだけです。

# おわりに
pubspec.yaml で GitのURLを指定できることを、今回初めて知りました。
チーム内での共有も楽になるので、パッケージのカスタマイズをしやすくなりますね。

Twitter でも Flutter や Unity の情報をつぶやいてるので、
よろしければフォローお願いします。
Step FunctionsからLambda経由せずにSlackへ通知する

# はじめに

AWS Step Functionsで処理結果をSlackに通知したいなぁ…でもそのためにLambdaを一つ作るのも面倒くさいなぁ…と思っていたのですが、ちょっと工夫したらLambdaを作らずにSlackのIncoming Webhookを呼び出せることに気づいたので、ちょっと実装してみました。

# さっそく実装

で、こんな感じで実装してみました。

![StepFunctionsSlack.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83499/285d6f9a-dd43-2ac2-5e58-c538fd51d2d8.png)

- API GatewayはAWSサービスだけでなくて、外部のWebAPIのラップにも使うことができる
- Step FunctionsのタスクとしてAPI Gateway呼び出しを行うことができる

この2点を組み合わせた形です。

なお、今回はCDKを使ってサンプル実装をしています。
CDKプロジェクトは[github](https://github.com/masaminh/stepfunctions_slack)の方に置いてあります。

## API Gatewayの実装

![apigateway.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83499/2515e281-2811-d18c-61b9-119d4846c4e3.png)

単純にAPI GatewayでのPOSTをSlackのIncoming WebhookのPOSTに繋げてあげているだけです。
~~本当はプライベートAPIにする方がいいのかな、とも思ったのですが、Step FunctionsからはプライベートAPIは呼び出せない旨がAWSのドキュメントに記載されていたので、リージョンAPIにした上でIAM認証にすることで、無関係の他者から呼び出せないようにしています。~~

2021/05/24 修正
プライベートAPIにしてもAWS内からだったら他者から呼び出されてしまうことを忘れて記載してました。リージョンAPIだろうがプライベートAPIだろうが、何らかの制限をかける必要はありますね。
今回はIAM認証を使うことで、期待外から使用されることを避けています。

## Step Functionsの実装

```json
{
  "StartAt": "Initialize",
  "States": {
    "Initialize": {
      "Type": "Pass",
      "Result": {
        "text": "Hello, World!"
      },
      "ResultPath": "$.message",
      "Next": "PostMessage"
    },
    "PostMessage": {
      "End": true,
      "Type": "Task",
      "Resource": "arn:aws:states:::apigateway:invoke",
      "Parameters": {
        "ApiEndpoint": "XXXXX.execute-api.ap-northeast-1.amazonaws.com",
        "Method": "POST",
        "Stage": "prod",
        "Path": "/messages",
        "RequestBody.$": "$.message",
        "AuthType": "IAM_ROLE"
      }
    }
  }
}
```

サンプルなので、InitializeステートでSlackのIncoming WebhookへPOSTするデータを作成していますが、実際の処理の際には通知内容を作成するLambdaなどを呼び出す形になると思います。

API Gatewayに送る箇所は見ればわかるレベルの内容だと思います。

# 実行結果

こんな感じでSlackの方に通知されました。

![slack.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83499/51f7987a-f537-5e36-a08d-642500888f4c.png)

# おわりに

これを作った後に「SNSからChatbot経由でSlackへ通知する方が自然じゃない?」と思ったりもしましたが、手段が多いに越したことはないということで。

それはさておき。
今までStep FunctionsってLambdaでの処理を繋げていくもの、というイメージが強かったのですが、Lambda以外のAWSサービスへ接続がいろいろできるということで、処理の分離をしやすくなっているのかな、という印象をもちました。

私の個人開発ではLambdaの実行結果の通知にLine NotifyやSlackのIncoming Webhookを使うことが多く、それぞれのLambdaの中でaxiosなど使ってこれらのWebAPIを呼び出す、ということをしていたのですが、今回のサンプル実装のように通知部分はStep Functionsから直接呼び出せるようになると、Lambdaは処理に専念でき、面倒なI/O系の記述を減らすことができる、というメリットがあるのかな…と感じています。

# 参考リンク
[Step Functions を使用した API Gateway の呼び出し](https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/connect-api-gateway.html)
Amazon ECS の「タスクのスケジューリング」の設定について

## ■Cron形式で設定する場合

:::note alert
NGの設定
:::

```
cron(*/1 * * * * *)
```

結果 → <font color=red>**Parameter ScheduleExpression is not valid**</font>

下記URLの「Wildcards」に記載があります。

https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/ScheduledEvents.html

`The * (asterisk) wildcard includes all values in the field. In the Hours field, * would include every hour. You cannot use * in both the Day-of-month and Day-of-week fields. If you use it in one, you must use ? in the other.`

曜日の項目が二つあり、両方に<font color=blue>**「*」**</font>は使用できないようです。

:::note info
OKの設定
:::

```
cron(*/1 * * * ? *)
```

片方を<font color=blue>**「?」**</font>にします。

## ■ECRのCMDを「タスクのスケジューリング」で上書きする場合

「タスクのスケジューリング」設定の「コンテナの上書き」にある「コマンドの上書き」に記載をします。
「docker-compose.yml」と異なり、「カンマ区切り」で入力を行います。

```docker-compose.yml
command: ping 127.0.0.1
```

下記は「タスクのスケジューリング」での記述

```
ping,127.0.0.1
```

※カンマ区切りでダブルクォーテーションで区切られます。

カンマを入力したい場合は少し特殊になるようです。
※エスケープ文字が無いようです（見当たりませんでした）

下記のような形にすると「カンマ」を入力することができます。

```
TEST=$(printf "\x2c") && echo "te${TEST}st"
```

<font color=blue>**\x2c**</font> は「カンマ」になりますので、一度変数にいれて利用します。
[Vue.js] vueインスタンスを作る方法

## 概要
Vueインスタンスを作る方法をここに記述します。

## 環境
Vue.jsのHPから開発バージョンのscriptをコピペしている
Vue.js：https://jp.vuejs.org/v2/guide/

## ｈｔｍｌにdivを設け,idを記述する

```html:html
  <div id="app">
　　　　//idには任意の名前を入れる。今回は初期値としてappを設定
　</div>
```

## main.jsに新たに設けるvueインスタンスを記述する。
Vurインスタンスは下記のように記述し、生成する。また、複数のインスタンスを生成することも可能。

```js:main.js
new Vue({
	el: '#app',
       //#appはhtmlの定義した<div id="app"></div>のID名
  data: {
  }
})
```
以上
AWS 認定ソリューションアーキテクト プロフェッショナル に合格しました

AWS認定ソリューションアーキテクト – プロフェッショナル（SAP-C01）試験に合格しました。
他の人もたくさん書いてるので、目新しさも面白みもないですが、学習に利用した本やコンテンツなどを紹介します。

# 公式のガイド
AWS公式の認定試験に関するページから試験ガイドとサンプル問題を入手できるので、まずは求められるスキル・知識レベルと、自分の到達度を確認しました。

https://aws.amazon.com/jp/certification/certified-solutions-architect-professional/

上記ページの`試験の準備`から進んだページに試験ガイドとサンプル問題へのリンクがあります。
また、同じ箇所の`試験対策トレーニングを受講する`の`無料のデジタルトレーニングを受ける`から、試験準備のEラーニングが受けられます（日本語コンテンツもあり）。
（2021/5時点）

# 対策問題集
アソシエイトの本は複数あるのですが、プロフェッショナルはこれしかないようです。
（2021/5時点）

https://www.amazon.co.jp/dp/4865942483

アソシエイトレベルのスキル・知識がある前提となっているため、AWSサービスそのものの解説は薄いです。
なので、各サービスの詳細については別途学習する必要があります。

試験ガイドにもある５つの分野に合わせたケース問題と詳細な解説、その後の模擬試験について、１回通してやってみて、出来なかったところと理解が怪しいと思ったところを再度やりました。

# Udemy
セールの時にコース買って取り組んでみましたが、若干内容が古い気がするのと、問題の意味が分からないものがあったりして、ストレスでした。

同じように思った人がいたようで、コメント入ってたのですが、それに対するコンテンツ提供者の回答が「AWSの試験でも日本語が怪しいやつがある」とのこと。確かにそうだけど、本試験では英語に切り替えることで乗り切れます。
「ご指摘ありがとうございます。修正します」じゃなくて、そういう対応なんか、と思って・・・分かりますよね。
そもそも、結構頻繁にメモリ不足のエラーが表示されるし（iPad mini 2019）、たまにコンテンツが更新されるけど変更点を確認しても「しゅうせい」としか書いてないし。

# AWS Black Belt Online Seminar

自分の理解の怪しいサービスについては、Black Beltオンラインセミナーのアーカイブ資料で学習しました。

https://aws.amazon.com/jp/aws-jp-introduction/aws-jp-webinar-service-cut/

# IAMまわり
IAMまわりが特に理解が怪しかったので、こちらで紹介されていた本を熟読しました。

https://dev.classmethod.jp/articles/review-aws-iam-book/

# 模擬試験
公式の模擬試験です。
アソシエイト合格時（だったか、AWSのセミナー受講のご褒美）に、無料クーポンをもらっていたので、これで受けました。
いい感じにボロボロだったので、全体的に足りてないことを思い知りました。
実は、模試の受験の後に対策問題集を購入したことを思い出しました。

本番受験の前日にも（今度は正規料金で）受験して、期待の結果にならず、慌てて対策問題集を見直しました。

# まとめ
アソシエイト受験から時間が開いたこともあり、S3だけでも色々と進化（Intelligent TieringとかDeep Archiveとか）していて、マジで持続的に学習が必要だなと、改めて思いました。
やはり、使ったことのないサービスは分かってないですね。当たり前だけど。

受験当日も自信はなく、最後に提出（残り時間8分）した後、「おめでとうございます」が表示された時は思わずガッツポーズ（小さく）でした。
いやぁ、疲れた。

ちなみにスコアレポートを確認してみたら、ギリギリだと思ってたのに、思いのほか高得点でした。（自慢か）

しばらく受験勉強のない日々を堪能します。
PHPのwhile文

#前提
PHPは未経験
PHPの学習を始めたため、アウトプットとして投稿
開発環境はXAMPP

#while文の書き方
PHPのwhile文は以下のように書く

```
while(条件式){
    処理
}
```
解説すると指定した条件を満たしている場合に処理を行うという
ただそれだけ・・・

#実際に書いてみた
```
<?php 
$i = 0;
while($i<10){
  echo $i."<br>";
  $i ++;
}
 ?>
```

#実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1031387/35747549-790c-06d5-8ab5-a8031f39c6e3.png)

#解説
カウンターの初期値を0としてその値が10より小さい場合にwhile文の中の処理を実行する。
処理の最後にカウンターの値を1増やす。
処理の内容は、
カウンターの値を出力する。その際に改行も行う。
出力内容は$iの値と改行になるため、
連結演算子「.」を使用して$iと改行タグを繋いだ。
【Oracle Cloud】コンパートメント単位でリソース制限を設定してみた

##はじめに
Oracle Cloud Infrastructure（以下OCI）ではアカウント（テナンシ）単位でサービスリミットが設定されています。
※サービスリミット：OCIのアカウント毎に設定されている各種サービスのリソース制限

サービスリミットはOracleによって設定されていますが、コンパートメント単位のリソース制限はテナンシ及びコンパートメントの管理者が設定することが可能です。

この機能により、各コンパートメントのサービス利用量の上限を管理者がコントロールすることができます。
今回はコンピュートインスタンスのリソース制限を設定してみようと思います。

##前提条件
コンパートメント割当てに必要な権限をユーザに付与します。
quota_adminグループを作成し、ユーザを追加した後に、下記のポリシーを設定します。
`allow group quota_admin to { QUOTA_READ, QUOTA_CREATE, QUOTA_DELETE, QUOTA_UPDATE, QUOTA_INSPECT } in tenancy
`

##コンパートメント割当ての設定
OCIコンソール画面のナビゲーション・メニューを開きます。
「ガバナンスと管理」→「ガバナンス」→「割当てポリシー」に移動し、
「割当て制限の作成」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226871/2664e691-f9f1-cca5-2448-a34ac1841d7a.png)

ポリシーの作成画面で各項目を入力していきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226871/735fbc06-21ac-56a2-31d6-4b251fd37916.png)




名前：ポリシー名
説明：ポリシーの説明
割当て制限ポリシー：ポリシー本文

割当て制限ポリシーについて、サービスに割当て制限を設定する基本的な構文は下記になります。
`set {サービスファミリ名} quota {サービス名} to {数量} in compartment {対象コンパートメント}`

今回はtest_compartmentのCompute E3 Shapeのコア数上限を1に設定したいので、
`set compute-core quota standard-e3-core-ad-count to 1 in compartment test_compartment`というポリシーを設定しました。

ポリシー構文やルールの詳細はドキュメントに記載されていますので、併せてご確認ください。
https://docs.oracle.com/ja-jp/iaas/Content/General/Concepts/resourcequotas.htm

##割当て設定の確認

割当てポリシーが正しく適用されているか確認します。
test_compartmentにE3 Computeインスタンスを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226871/d3c1e74c-fbc3-d505-03f2-fb82411bb1a8.png)

2つ目のE3 Computeインスタンスの作成を試みたところ、`The following compartment quotas were exceeded`とエラーが表示されてインスタンスの作成に失敗しました。
設定した割当てポリシーが正しく機能していることを確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226871/8853b133-4951-7a89-deb3-bb8f437a0d7d.png)


##参考資料
https://docs.oracle.com/ja-jp/iaas/Content/General/Concepts/resourcequotas.htm
【Python3/Python-dotenv】.envのファイルの中身を上書きする方法

[1]:[https://github.com/theskumar/python-dotenv]

Pythonで.envファイルをいじる時、「[Python-dotenv][1]」を使用されている方は
多いのではないでしょうか。
今回は、その[Python-dotenv][1]を利用して、直接envの値を上書きする方法です。

## 前提条件
Python-dotenvのインストールについては、[公式のGithub][1]を参考にしてください。

.envファイルに以下の値が存在していると仮定します。

```terminal:.env
GREETING_KEY="HELLO"
```

今回は、この`HELLO`を`HEY`に変更します。

## 上書きできない例

最初に思いついたのは、下記のようなコードです。

```python:failed.py
import os
from dotenv import load_dotenv

class OverrideEnv:

  def __init__(self):
     load_dotenv()

  def changeGreetingKey(self):
     str = "HEY"
     os.environ["GREETING_KEY"] = str
```

一見良さそうです。
しかし、このコードを走らせた後に、`.env`のファイルの中身を確認しても、
`GREETING_KEY="HELLO"`のままです。

## 上書きできる例

上書きするためには、`dotenv.set_key`を用います。
下記のコードだとうまくいきます。

```python:success.py
from dotenv import load_dotenv
import dotenv

class OverrideEnv:

  def __init__(self):
     load_dotenv()

  def changeGreetingKey(self):
     str = "HEY"
     
     dotenv_file = dotenv.find_dotenv()
     dotenv.set_key(dotenv_file, "GREETING_KEY", str)
```

このコードを走らせた後に、`.env`ファイルの中身を確認すると、
`GREETING_KEY`の値が`HELLO`から`HEY`に変わっているはずです。

もし、envの値が変わらない、コードが動かないなどありましたら、
教えてください。
最後までお読みいただきありがとうございました🙇‍♂️
undefined method `map' for nil:NilClassエラー

![20210524-205440.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/960935/477989e9-e0ef-39df-0c5b-dccb07b5858b.png)


map, map! メソッドとは
-

map は、配列の要素の数だけブロック内の処理を繰り返し、結果として作成された配列を返します。mapは元の値に対して影響を与えないのに対し、map!は元の値を書き換えます。また、Rubyには **collectメソッド**がありますが、これは**mapメソッドの別名**です。

```rb:【誤】
  def index
    @products = Product.all
  end
  
  def search
    @results = @p.result.includes(:category)
    set_product_column
  end

  private

  def search_product
    @p = Product.ransack(params[:q])
  end

  def set_product_column
    @product_name = Product.select("name").distinct
  end 
```

```rb:【正】
  def index
    @products = Product.all
    set_product_column
  end
  
  def search
    @results = @p.result.includes(:category)
  end

  private

  def search_product
    @p = Product.ransack(params[:q])
  end

  def set_product_column
    @product_name = Product.select("name").distinct
  end 
```

indexにあるべきset_product_columnがsearchアクションにあったため
[C++/Windows] 現在の電源プランのGUIDを取得する

# もくじ

https://tera1707.com/entry/2022/02/06/144447

# やりたいこと

C++で、Windowsの電源オプションの画面で設定している「電源プラン」が何かを取得したい。
どうも、電源プランそれぞれに**GUID**が振られていて、それを取得するのがいいっぽい。

電源オプションの画面は、下記のような感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/7850368b-ca99-9e7d-22ac-e6168941bedc.png)

`powercfg -l`コマンドで、現在設定している電源プランの一覧が取得できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/fa763453-7e2f-fa64-008d-6cc7554227eb.png)

コマンドで取った一覧のうちの**「現在選択している電源プラン」**のGUIDを取得したい。

# やり方

**[PowerGetActiveScheme()](https://docs.microsoft.com/ja-jp/windows/win32/api/powersetting/nf-powersetting-powergetactivescheme)**関数を使用する。

# サンプル

```cpp
#pragma comment(lib, "PowrProf.lib")

#include <Windows.h>
#include <powersetting.h>

int main()
{
    GUID* pPwrGUID;

    PowerGetActiveScheme(NULL , &pPwrGUID);

    system("pause");
}
```

# 参考

PowerGetActiveScheme 関数

https://docs.microsoft.com/ja-jp/windows/win32/api/powersetting/nf-powersetting-powergetactivescheme
エンジニアにも、英語学習が必須になってくるのでは？という話。

「いやいや、プログラミングスキルやITの知識などがあれば、英語学習なんてそんなに必要じゃないでしょ」という反論が返ってきそうだが。

でも例えば、楽天グループでは全社員にTOEICの点数目標があって、英語力が必要。

楽天グループのIT・プログラミングの担当者たちからは、最初は不平不満の声が大きかったそうだ。

それでも三木谷社長はその目標を下げなかった。いつかは必ず必要な日がくるから、と。

自分も、少しそう思うのだ。今は、日本語でもプログラミングやITスキルを勉強する書籍・ツールはたくさんある。

でもますます少子高齢化が進む日本では、日本の中のパイはどんどん減っていく。当然日本語の情報も減っていく中で、最新の技術を学ぶには、英語で文献や参考書を読むぐらいはできるようにならないといけないのではないかと。

そして、海外のエンジニアと常時繋がりながら開発する場面も増えるだろう。

そんな日は、そう遠くない将来やってくる。

そんな焦りから、自分も少しずつだが英語学習を始めている。ツールは、オンライン英会話を使って。

レアジョブ英会話というサービスがある。これがとても良いサービスで、フィリピン人講師と会話しながら、楽しみながら英語力を向上させることができる。

レアジョブ英会話の情報は、以下のサイトが詳しい。

https://rarejob-review.com/

なかなか急速には英語力は向上しないが、一歩ずつ英語力も高めていき、多方面で活躍できるエンジニアになっていきたいと考えている。
AWS S3 クイズ  ～バケットが空ではない？～

# Question
ここに何の変哲もないバケットがあります。ご覧の通り、オブジェクトはありません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/9621a2d4-ddec-9183-713c-7ac5bc8a8dbe.png)

S3 スペシャリストのあなたは、リソース整理のために空のバケットは削除するように依頼されました。

そこでバケット名を確認し、「削除」をクリックしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/776d59f0-9b5b-3f5d-fe55-fb8df68e2c5a.png)

しかし、なぜかバケットは空ではないというメッセージが表示されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/cb142ab3-a2b9-2042-f89e-c626be2ee943.png)

この理由は以下のどれでしょうか？

1. バグ
2. キャッシュが残っている
3. バージョニングを有効化している
4. SSE-KMS により暗号化したオブジェクトを削除した直後である
5. SSE-S3 により暗号化したオブジェクトを削除した直後である
6. バケットが削除されたくないと懇願している

※何かの試験みたいですが、パクっていません。自分自身の経験談です。

# Answer

答えは「3」です。（Twitter みたいに正答率出せたらいいのに、と思います。運営さんよろしくお願いします。）

「バージョンの表示」をクリックしてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/9d294891-d7fe-6f4c-346e-29a3f4a13ac5.png)

オブジェクトが姿を現しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/69da0255-7962-2375-7660-0899fb68e0fb.png)

削除マーカーを削除してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/0b54c199-bca0-ab1d-a523-bef9139427d2.png)

オブジェクトが復元しました。あら不思議！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/54fc8f23-0931-7b0b-c2a7-2ee6f88c97a6.png)

# 完全に削除

「バージョンの表示」を切り替えてから削除してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/c619447f-d10f-4886-6b94-751360e985f2.png)


元に戻すことができないというメッセージが表示されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/06a54a09-0460-0976-a1ac-99d2e6a1abbf.png)

この状態で削除すると、**オブジェクトのバージョンもろとも削除**されます。（復元不可能）
その後、バケットが空になり、冒頭のような空でないという警告は表示されずにバケットが削除できるようになります。

一方で「バージョンの表示」を切り替えずに削除しようとした場合は、削除マーカーが追加されるというメッセージが表示されます。一見削除されたように見えますが、削除マーカーが追加されただけでオブジェクトは復元可能です。(バージョン ID が蓄積していく)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/357b735f-387b-1caa-e884-a30fb053061f.png)

# 参考記事

https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/versioning-workflows.html
PHPのfor文

#前提
PHPは未経験
PHPの学習を始めたため、アウトプットとして投稿
開発環境はXAMPP

#for文の書き方
PHPのfor文は以下のように書く

```
for(式1; 式2; 式3){
処理
}
```

・式1 － カウンターの初期値
・式2 － for文が実行される条件
・式3 － 処理一回ごとのカウンターの増減幅

#実際に書いてみた

```
<?php 
for($i = 0; $i < 5; $i++){
echo $i;
}
 ?>
```
上記のコードはカウンターの初期値を0として、
その値が5よりも小さい場合にfor文の中の処理を行い
処理を一回実行する度に1カウントアップをするという内容である。

実行結果はこうなる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1031387/d965b69c-c600-aa6c-74a0-995b998f4cd4.png)

カウンターが0から4の時
echo $i;
が実行された。
[Admob] 起動時にアプリがクラッシュする


（この記事は、私が[自己解決したTeratailの質問](https://teratail.com/questions/319848)を要約したものになります。)

Admobでバナー広告を実装していたところ、クラッシュしたのでそのことについて書こうと思います。

----
## 開発環境
Xcode 12.4
Google Mobile Ads SDK 7.69.0
Firebase 7.5.0
## エラー内容
>Thread 2: "The Google Mobile Ads SDK was initialized without AppMeasurement. Google AdMob publishers, follow instructions here: https://googlemobileadssdk.page.link/admob-ios-update-plist to include the AppMeasurement framework and set the -ObjC linker flag. Google Ad Manager publishers, follow instructions here: https://googlemobileadssdk.page.link/ad-manager-ios-update-plist"

## 心当たりがあったこと
・App Tracking Transparencyで許可をリクエストの実装をしていない。

・Admob管理画面でアプリの追加、広告ユニットIDの作成、を行ったのが24時間以内。（アカウントは半年前に作成済み）

・Firebaseにアプリをリンクさせたのも24時間以内。

## 原因
`Info.plist`内に以下のキーを追加していないのが原因でした。

```XML
<key>GADIsAdManagerApp</key>
<true/>
```
参考：[Xcode Error When Added AdMob Plugin To Ionic Project　(stackoverflow)](https://stackoverflow.com/questions/55577811/xcode-error-when-added-admob-plugin-to-ionic-project)


---
"WARNING: `pyenv init -` no longer sets PATH."のFish shellでの解決

pyenvのアップデートで`pyenv init -`の仕様が代わり、自動でパスが設定されなくなったそうな。
その為、以前のセットアップのままの人向けに警告文が出力されるようになり、シェル起動時に件の文が出る。

`python init` で必要な変更に関する情報を得ろって言われるので見てみる。

```
# (The below instructions are intended for common
# shell setups. See the README for more guidance
# if they don't apply and/or don't work for you.)

# Add pyenv executable to PATH by running
# the following interactively:

set -Ux PYENV_ROOT $HOME/.pyenv
set -U fish_user_paths $PYENV_ROOT/bin $fish_user_paths

# Load pyenv automatically by appending
# the following to ~/.config/fish/config.fish:

status is-login; and pyenv init --path | source
pyenv init - | source

# If fish is not your login shell,
# add the following to ~/.profile:

export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init --path)"
```

読むと必要なのが次のものだと分かるので`~/.config/fish/config.fish`にあるpyenvのコードと置き換える。

```
set -Ux PYENV_ROOT $HOME/.pyenv
set -U fish_user_paths $PYENV_ROOT/bin $fish_user_paths
status is-login; and pyenv init --path | source
pyenv init - | source
```

## 実際の設定

`pyenv-virtualenv`と`tmux`にも対応したものがこれ。

```
set -Ux PYENV_ROOT $HOME/.pyenv
set -U fish_user_paths $PYENV_ROOT/bin $fish_user_paths
if command -v pyenv 1>/dev/null 2>&1
    if status is-login && test -z "$TMUX"
        pyenv init --path fish | source
    end
    pyenv init - fish | source
    pyenv virtualenv-init - fish | source
end
```

## GUIのターミナルの設定

GUIのターミナルではログインシェルとして実行するかどうかの設定があるものもある。
その場合は設定によっては`pyenv init --path`が実行されなくなってしまうので注意。
JavaScript上での実用的な操作

#JavaScript上での操作

```index.html
<!DOCTYPE html>
<html>
  <head>
    <title><ToDo-js></ToDo-js></title>
    <meta charset="UTF-8" />
    <script src="src/index.js"></script>
  </head>

  <body>
    <div class="input-area">
      <input id="add-text" placeholder="ToDoを入力" />
      <button id="add-button">追加</button>
    </div>
    <div class="incomplete-area">
      <p class="title">未完了のToDo</p>
      <ul>
        <li>
          <div class="list-row">
            <p class="todo-name">ToDoです</p>
            <button>完了</button>
            <button>削除</button>
          </div>
        </li>
        <li>
          <div class="list-row">
            <p class="todo-name">ToDoです</p>
            <button>完了</button>
            <button>削除</button>
          </div>
        </li>
      </ul>
    </div>
    <div class="complete-area">
      <p class="title">完了したToDo</p>
      <ul>
        <li>
          <div class="list-row">
            <p class="todo-name">ToDoでした</p>
            <button>戻す</button>
          </div>
        </li>
      </ul>
    </div>
  </body>
</html>
 ```

#####createElement
#####className
↓document.createElement("div"); でdivを生成する。
↓div.classNameでクラス名を付与する。

```index.js
  const div = document.createElement("div");
  div.className = "list-row";
  console.log(div);
```
[![Image from Gyazo](https://i.gyazo.com/4866f1b39fdbc14f30eda859d29433e2.png)](https://gyazo.com/4866f1b39fdbc14f30eda859d29433e2)

#####innerText
↓p.innerText で、要素内のレンダリングされたテキストを取得

```index.js
  const p = document.createElement("p");
  p.className = "todo-name";
  p.innerText = inputText;
  console.log(p);
```
[![Image from Gyazo](https://i.gyazo.com/c5f519e52c46199b3e75fc323e3a9452.png)](https://gyazo.com/c5f519e52c46199b3e75fc323e3a9452)

#####appendChild
↓div.appendChild(p); で、divの子要素にpを設定。

```index.js
  div.appendChild(p);
  console.log(div);
```
[![Image from Gyazo](https://i.gyazo.com/29c478e183cf759af82b8819b69a01da.png)](https://gyazo.com/29c478e183cf759af82b8819b69a01da)

#####parentNode
#####removeChild
↓parentNode で、親要素・親ノードを取得する。
↓removeChild で、特定の子要素（子ノード）を削除する。

```index.js
const deleteButton = document.createElement("button");
  deleteButton.innerText = "削除";
  deleteButton.addEventListener("click", () => {
    //押された削除ボタンの親（div）を未完了リストから削除
    const deleteTarget = deleteButton.parentNode;
    document.getElementById("incomplete-list").removeChild(deleteTarget);
  });
```

#####firstElementChild

↓const addTarget = completeButton.parentNode; で、完了ボタンの親要素（div）を取得。
↓const text = addTarget.firstElementChild.innerText; で、divの最初の子要素を取得。

```index.js
  const completeButton = document.createElement("button");
  completeButton.innerText = "完了";
  completeButton.addEventListener("click", () => {
    //完了リストに追加する要素
    const addTarget = completeButton.parentNode;
    const text = addTarget.firstElementChild.innerText;
    console.log(text);
  }
```
[![Image from Gyazo](https://i.gyazo.com/2399650de067492af4fb0ab2c9ce2660.png)](https://gyazo.com/2399650de067492af4fb0ab2c9ce2660)
CUDAを入れたときのSteamが起動しない問題の解決法


# 問題
Cudaでnvidia-driverを入れるとSteamに必要な32bit版のライブラリが入らないためSteamが起動しない

# 解決法
手動で32bit版のライブラリを手動で入れる

NVIDIAのDLページから目的のバージョンのドライバを入手する
（当記事ではversion495.29.05として記載）

https://www.nvidia.co.jp/Download/driverResults.aspx/181164/jp

ダウンロードフォルダにて以下を実行

```shell:目的のライブラリを抜き出して配置
chmod u+x NVIDIA-Linux-x86_64-495.29.05.run
./NVIDIA-Linux-x86_64-495.29.05.run -x
cd NVIDIA-Linux-x86_64-495.29.05/32
sudo cp libEGL* libGLESv* libGLX* libnvidia-egl* libnvidia-gl* libnvidia-tls* /usr/lib32
```

```shell:シンボリックリンク作成、ロード
cd /usr/lib32
sudo ln -s libEGL_nvidia.so.495.29.05 libEGL_nvidia.so.0
sudo ln -s libGLESv1_CM_nvidia.so.495.29.05 libGLESv1_CM_nvidia.so.1
sudo ln -s libGLESv2_nvidia.so.495.29.05 libGLESv2_nvidia.so.2
sudo ln -s libGLX_nvidia.so.495.29.05 libGLX_indirect.so.0
sudo ln -s libGLX_nvidia.so.495.29.05 libGLX_nvidia.so.0
sudo ldconfig

```

```shell:シンボリックリンク削除（update時に掃除するとき）
cd /usr/lib32
sudo unlink libEGL_nvidia.so.0
sudo unlink libGLESv1_CM_nvidia.so.1
sudo unlink libGLESv2_nvidia.so.2
sudo unlink libGLX_indirect.so.0
sudo unlink libGLX_nvidia.so.0
sudo ldconfig

```





# 参考
https://askubuntu.com/questions/1271975/steam-20-04-not-working-while-i-have-cuda#