OmniAICreator/Qiita-1.07M huggingface dataset:
Railsチュートリアルmodule SessionsHelperを例にmoduleとHelperの役割を見てみる

Railsチュートリアルも9章に入ったのですが、Sessionが出てきてからかなり難易度が上がったように感じたので、知識の定着を図ることも兼ねて、理解が曖昧な部分を自分用にまとめておきます。

##module SessionsHelperとは

Sessionコントローラーを生成した時点で、自動的にmodule SessionsHelperも生まれてました。

まず、**module**というのはclassと同様に部品の集まりです。以下の説明がわかりやすいと思います。

>Rubyにはオブジェクト指向で一般的なクラス以外にも、モジュールという概念が存在します。モジュールではクラスと同じように定数やメソッドをまとめたり、クラスに組み込んで多重継承を実現したり、クラスなどをまとめることで名前空間を提供するなど、いろいろな使い方ができます。 https://qiita.com/shiopon01/items/fd6803f792398c5219cd

ちなみにクラスとモジュールの違いに関する説明は[こちら](https://qiita.com/fukumone/items/2dd4d2d1ce6ed05928de)の記事が分かりやすいと思いました。

次に**Helper**とは、動作の処理をメソッド化してまとめたものです。例えば、上のコードでは「渡されたユーザーでログインする」メソッドと「現在ログイン中のユーザーを返す」メソッドをSessionsHelper内でまとめています。

Railsチュートリアルで、module SessionsHelper内で記述されたメソッドはApplicationControllerを継承したclass SessionsControllerで呼び出されていることを確認できます。

SessionsController内でSessionsHelperが使える理由は、このようにApplicationController内でmodule SessionsHelperがincludeされているからです。

```ruby
class ApplicationController < ActionController::Base
    include SessionsHelper   
end
```

まとめると、module SessionHelperとは、Session関連で使うメソッドのまとまりということです。

##まとめ：

本来別のメソッドの記事を書こうとしてたのですが、その記事内でmodule SessionsHelperの説明をセットにしているとくどすぎると感じたので分けることにしました。
Raspberry Pi の OS と Kernel のバージョン確認

# Raspberry Pi の記事を書くときのスペック確認のため
## 1. OSのバージョン確認
Raspbian のバージョンを確認しようとしたところ、
2020年5月に正式名称が Raspbian から **Raspberry Pi OS**へ変更とのこと。
Raspberry Pi OSにはバージョンが存在しないためにリリース日とカーネルバージョンで識別。

リリース日はわからなかったため、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637498/11a83f83-c176-81a0-3e1e-13818d88b10f.png)
Imager から確認。

> Raspberry Pi OS (32-bit)
リリース日：2021-05-07
Raspberry Pi Imager v1.6.2

ただ、普通に Raspbian の確認コマンドも使えました。
##### 1. `cat /etc/debian_version`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637498/ea236d7f-d5e6-a963-b67f-08f0c2a704c3.png)

##### 2. `cat /etc/issue`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637498/b76da7b8-e9f7-8c33-4660-781fe3727cfd.png)

##### 3. lsb_releaseコマンド
まず、`sudo apt-get install lsb-release`
でパッケージインストール
`lsb_release -a`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637498/ef9c1936-723a-e6c3-8998-fef5fef88aa4.png)
> **Raspbian ： 10.10**

## 2. Kernel のバージョン確認
`uname -a`
`cat /proc/version`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637498/c39ca661-e214-b4d7-4b1d-fa33fd02f7f0.png)
> **Kernel ： 5.10**

こちらを参考にしました。

https://www.checksite.jp/raspbian-version-check/
SQLデータベース超入門ノート1

# 前提
今回はSQLの練習としてSQLite3を使います。

以下のコマンドでSQLite3をインストールします。

```
apt -y update
apt -y install sqlite3
```
# データベース作成

データベースを作成します。

```
sqlite3 [ファイル名].sqlite3
```

格納される値のデータ型は以下の通り

- NULL　　　　　NULL値
- INTEGER    　　　符号付整数。1, 2, 3, 4, 6, or 8 バイトで格納
- REAL       　　　　　浮動小数点数。8バイトで格納
- TEXT       　　　　テキスト。UTF-8, UTF-16BE or UTF-16-LEのいずれかで格納
- NUMERIC　　　数値データを格納

テーブルを作成します。

```
create table [テーブル名]( [カラム名][データ型], [カラム名][データ型]);
```
以下のコマンドで利用していない領域を解放します。

```
VACUUM;
```
以下のコマンドでデータを挿入します。
※文字列はシングルクォートで囲みます。

```
insert into [テーブル名] values([データ], [データ]);
```


テーブル名の変更

```
ALTER TABLE [テーブル名] RENAME TO [新しいテーブル名];
```
カラムの追加

```
ALTER TABLE テーブル名 ADD COLUMN [カラム名][データ型];
```
テーブル削除

```
DROP TABLE [テーブル名];
```

PRIMARY KEY 制約

```
CREATE TABLE テーブル名([カラム名] [データ型] PRIMARY KEY, ...);
CREATE TABLE テーブル名([カラム名1], [カラム名2], ... ,PRIMARY KEY([カラム名1], [カラム名2], ...));
```
integerを指定すると自動で連番が割り当てられます。

```
create table user(id integer primary key, name text);
```

# データの確認

情報の確認

```
.tables
.databases
```

データの全件取得

```
select * from [テーブル名];
```
データの型取得

```
select [カラム名], typeof([カラム名]) from [テーブル名];
```
masterでデータ取得

```
select * from sqlite_master;
select * from sqlite_master where type='table' and name='[テーブル名]';
```
以下でスキーマ(履歴)を取得します。

```
.schema
```
radikoのダウンロード方法

# はじめに

radikoのダウンロードはこれまで[こちらの方法](https://github.com/morinokami/radiko-downloader)で行うことができましたが、最近になってswfストリームじゃなくなり、この手法でのダウンロードができなくなったみたいです。

代わりに[streamlink](https://streamlink.github.io/)を用いてダウンロードすることができるようになった(以前からできたかもです)ので、こちらの方法を試すのが良いかなと思われます。

# 環境

MacOS

# 各パッケージインストール

```zsh
brew install streamlink ffmpeg
```

# ダウンロード

```zsh
streamlink 'radikoのURL' best -o output.ts
ffmpeg -i output.ts radiko`date '+%Y%m%d'`.mp3
rm output.ts
```

実行後に、カレントディレクトリに`radiko20210817.mp3`のようなファイルが生成されているかと思います
GitLab-CEのバージョン指定アップグレード

# 概要
自宅ServerでGitLabを動かしているが、久々に「sudo apt-get upgrade」で全体を更新したところGitLabのアップデートで指定バージョンを経由しないとダメだというメッセージが出たため、忘備録として手順を残した。

★GitLab-CEの13.10→14.1へのアップグレード手順

#前提
*　Ubuntu18.04（Bionic）
*　GitLab-CE（13.10）

#apt-get　upgradeで表示されたエラー
要は、apt-get upgradeでGitLab14.1がリストに出てるけど、今は13.10なので「メジャーバージョンアップ」になるよ。と、、、
そして、14.1をインストールする前に14.0にアップグレードしてくれ。と、、、、
最後に、アップグレードする際には、段階があるので、それに従ってくれ。ということです。

```
Preparing to unpack .../gitlab-ce_14.1.2-ce.0_amd64.deb ...
gitlab preinstall: It seems you are upgrading from major version 13 to major version 14.
gitlab preinstall: It is required to upgrade to the latest 14.0.x version first before proceeding.
gitlab preinstall: Please follow the upgrade documentation at https://docs.gitlab.com/ee/update/index.html#upgrade-paths
dpkg: error processing archive /var/cache/apt/archives/gitlab-ce_14.1.2-ce.0_amd64.deb (--unpack):
 new gitlab-ce package pre-installation script subprocess returned error exit status 1
Errors were encountered while processing:
 /var/cache/apt/archives/gitlab-ce_14.1.2-ce.0_amd64.deb
E: Sub-process /usr/bin/dpkg returned an error code (1)
```

#GitLabの段階アップグレード
GitLabが示す情報は下記
https://docs.gitlab.com/ee/update/index.html#upgrade-paths

![gitlab001.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222251/8ce09ec7-3d40-c366-38b2-afb3231e2735.png)

上記の情報によると、14.1にする前には「13.12」と「14.0」を順に入れていく必要がある。


#GitLabの旧パッケージ提供URL
GitLab-CEの旧パッケージは下記にて提供されている
https://packages.gitlab.com/gitlab/gitlab-ce

ここから、自分の使っている環境に適したものをクリックして情報を取得する。
Ubuntu18.04なので、「Ubuntu/bionic」のものを選ぶ
![gitlab002.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222251/dbd28579-d4bc-b430-6bb5-8792df761f7e.png)
![gitlab003.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222251/faa33ab8-8a43-8c22-4d01-658efed10bba.png)

1つずつ見ていく。
まずは、リンクをクリックすると下記のようなページが見れる。
![gitlab004.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222251/b2788ff3-0882-2f64-1b1a-b3a84847a9c8.png)

右側に「install」のコマンドが記載されているので、このようにバージョンを指定すると特定のバージョンをインストールすることが可能である。

#アップグレード
一応、キャッシュの悪影響が出ないように消しておく

```
$ sudo apt-get clean
```

まずは、13.12にアップグレード

```
$ sudo apt-get install gitlab-ce=13.12.9-ce.0
$ sudo gitlab-ctl reconfigure
$ sudo gitlab-rake gitlab:check
```

続いて、14.0へアップグレード

```
$ sudo apt-get install gitlab-ce=14.0.7-ce.0
$ sudo gitlab-ctl reconfigure
$ sudo gitlab-rake gitlab:check
```

最後に、通常のupgradeで14.1にアップグレードする

```
$ sudo apt-get clean
$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo gitlab-ctl reconfigure
$ sudo gitlab-rake gitlab:check
```

#バージョン確認
簡単なのは、GitLabにログインして「ヘルプ」を見ること（右上のメニューから）
![gitlab005.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222251/d655b463-b353-be51-23cf-bddd61c9e451.png)

無事、GitLabも動いてるし、14.1に上がっているので閉幕。
GitLabの認証でGoogle OAuth2を利用 

## 概要
GCE：ubuntu 18.04 lts
GitLab: 14.1.2-ee

GitLabからGKEを作成しようとしたがGCPの認証を行ってからしてねとメッセージが出たので認証を行う

## 認証情報の作成
前提条件として事前にGCPのプロジェクトを作成済み
認証情報 > 認証情報を作成 > Oauth クライアントIDをクリック 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1901173/3d54d5ec-4a43-5f70-7e7d-5e28ccb5adb9.png)
#### 以下のように情報を入力していく
- アプリケーション種類：ウェブアプリケーションを選択
- 名前：GitLab(分かりやすければ何でもよい）
- 承認済みの JavaScript 生成元
    - URL：https://gitlab.hogefuga.com
- 承認済みのリダイレクト URI
    - https://gitlab.hogefuga.net/users/auth/google_oauth2/callback
    - https://gitlab.hogefuga.net/-/google_api/auth/callback  

承認済みのリダイレクト URIはGitLabが用意しているもので決まり事です、ドメインの部分は自身の環境に合わせたドメインにしてください
また、Google は生の IPアドレスを受け付けないので、ドメイン名を指定する必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1901173/fe784661-818d-06b8-18ef-5cc6c712453e.png)
作成を押すとクライアントIDとクライアントシークレットが表示される。
後で必要になるので、メモするかページを開いたままにしておく。（閉じても後で確認出来ます）
## APIの有効化
以下の3つのAPIを有効化しておく必要がある 

* Google Kubernetes Engine API
* Cloud Resource Manager API
* Cloud Billing API

APIの有効化は[Google API Console](https://console.developers.google.com/apis/dashboard)を開き該当APIを選択して、APIを有効にするをクリック

## OAuth同意画面
パンくずリストっぽいものが表示され順番に入力していく
##### 1. OAuth 同意画面
   アプリ名：わかりやすい名前
   ユーザーサポートメール：取り合えず自分のメールアドレス
   デベロッパーの連絡先情報：取り合えず自分のメールアドレス
 
##### 2. スコープ
現在では利用しないため入力なし

##### 3. テストユーザー 
公開ステータスをテストにしている場合、認証を認めるユーザーのユーザー情報（今回メールアドレス）を入力
上記入力しないと認証されない
![cc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1901173/948be34e-1596-7471-15f1-9e2cb219c555.png)
## GitLabでの作業
GitLabを動作させてるマシンにログインし、設定を行う

    sudo vi /etc/gitlab/gitlab.rb

よりOminiAuthを有効にする。

    gitlab_rails['omniauth_enabled'] = true
    gitlab_rails['omniauth_allow_single_sign_on'] = ['google_oauth2']
    gitlab_rails['omniauth_external_providers'] = ['google_oauth2']
    gitlab_rails['omniauth_block_auto_created_users'] = false
    gitlab_rails['omniauth_providers'] = [
      {
        "name" => "google_oauth2",
        "app_id" => "メモに残しているクライアントID",
        "app_secret" => "メモに残しているクライアントシークレット",
        "args" => { "access_type" => "offline", "approval_prompt" => '' }
      }
    ]
再設定を行う

    sudo gitlab-ctl reconfigure

これで認証されるはず
AWS 認定ソリューションアーキテクト アソシエイト 合格するまで

2021年8月16日に「AWS 認定ソリューションアーキテクト アソシエイト(SAA-C02)」試験を受け合格しました。
受けるまでの過程や購入した教材、学習時間などをできるだけ細かく記載していきます。
受験を考えている方の参考になれば幸いです。

# 受験しようと思うまで
プログラミングスクール(2021年7月まで在学)でAWSを使って、Ruby on Railsを使ったポートフォリオをデプロイしました。

* この時に行ったこと
    * VPC関連(サブネット、ルートテーブル、インターネットゲートウェイ、セキュリティグループ)
    * ALB
    * AMI
    * EC2(t2.micro)
    * RDS(MySQL)
    * S3
    * Lambda
    * Cloud9
    * IAM(IAMロールの作成、IAMユーザーの作成)

習ったのはポートフォリオをデプロイするため最小で最安になるような構成と超基礎的な機能です。
在学中に習ったことの物足りなさやクラウドインフラが楽しかったというのもあり、在学終盤ごろにAWSの資格に興味が沸きました。

# 購入したもの

* 全部Udemyの教材です。セールの時に購入しました。
    * 【世界で3万人が受講】演習テスト: AWS 認定 ソリューションアーキテクトアソシエイト ￥1,610(セール)
    * 【世界で2万人が受講】演習テスト: AWS 認定 クラウドプラクティショナー ￥1,730(セール)
    * これだけでOK！ AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座（SAA-C02試験対応版） ￥1,610(セール)



# 学習過程と学習時間
* <strong>【世界で2万人が受講】演習テスト: AWS 認定 クラウドプラクティショナーを試す。［1時間]</strong>
     * 講座内容は65問の模試形式の問題が全6回分あり、模試終了後に1問ごとに丁寧な解説があります。これを初めて受験して正解率が<font color="red">43%</font>で4回目にして<font color="green">73%</font>になる。これは簡単に取得できそうだと思い、認定ソリューションアーキテクトアソシエイト取得を志す。
  
* <strong>【世界で3万人が受講】演習テスト: AWS 認定 ソリューションアーキテクトアソシエイトを試す。［1時間]</strong>
    * 上記と同様の内容です、これを初めて受験して正解率が<font color="red">10%</font>で問題内容の想像すらつかず、ヤバいと思いました。
  

* <strong>これだけでOK！ AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座）の解説・ハンズオン動画を見る［20時間]</strong>
    * サービス解説とハンズオン動画が32時間分あります。32時間分ありましたが1.75~2倍速くらいがちょうどよかったので20時間程度見たことになると思います、またハンズオンは講師の方の画面を見ればいいと思い見ることに専念しました。

* <strong><font color="red"> 動画視聴が終わったことをきっかけに、3日後に試験予約をする。</font>［1時間]</strong>
    * これはかなりミステイクでした、反省すべき点です。また試験予約やユーザー登録が少し複雑で大変と感じました。

* <strong>2つの教材の模試をひたすら繰り返す。［18時間]</strong>
    * 初回の正解率が<font color="red">35%</font>で積んだと思いましたが、初回の試験で合格できたら自分にご褒美をあげるアメとムチ作戦でなんとか気力を保つことできました。
    * 1つの模試の所要時間としては平均して40分程度で問題を解き、20分程度で正解や解説を確認する形になりますので、8回分の模試を総計で18回繰り返したことになります。

# 試験について
試験内容は130分間で65問の単一選択問題と複数選択問題のミックスです。
試験を取り扱っている会社が2社あります。ピアソンVUEとPSIです。
受験料はいずれも￥15,000 + 税だったと思います。
また受験方法が2種類あり、在宅リモート受験とテストセンター受験を2社それぞれが扱っています。
初めはピアソンVUEの在宅リモート受験で臨もうと思いましたが、予約手続きが上手くいかずエラーを繰り返しピアソンVUEからアカウントロックのような扱いを受けてしまいましたのでPSIのテストセンター受験をチョイスしました。
テストセンター受験をチョイスした際に在宅リモート受験とテストセンター受験のメリットとデメリットを考えました。

<strong>在宅リモート受験の<font color="green">メリット</font>と<font color="red">デメリット</font></strong>

* <font color="green">テスト直前まで勉強に集中できる。</font>
* <font color="red">部屋がキレイで静かな環境でなければいけない。</font>
* <font color="red">試験会社のテスト管理ソフトをインストールが必要であったりする。</font>

<strong>テストセンター受験の<font color="green">メリット</font>と<font color="red">デメリット</font></strong>

* <font color="green">試験環境・事務手続きはテストセンターが提供・処理してくれる。</font>
* <font color="red">移動時間などがあるのでテスト直前まで勉強に集中できない。</font>

比較した結果、テストセンター受験を採用とさせて頂きました。またPSIの在宅リモート受験はテスト前に試験官と英語でコミュニケーションが必要でしたのでちょっと面倒臭いと私は思いました。（ピアソンVUEは日本語に対応しているそうです。）

# 試験を終えて
試験終了を選択すると試験についてのアンケートに答えて、試験結果が表示されました。
合格できるかどうかかなり不安でしたが、<font color="green">合格</font>と表示されて安堵しました。:cracker:

# 模試や試験を受ける際の心構え
* 商品知識豊富な営業マンのようにサービス説明をできるレベルになるべし
* Well-Architected Framework と AWSベストプラクティス に則った選択肢を導くべし

私はこの2点はかなり重要だと感じました。AWS認定は3年間で再認定が必要となりますので、次回も合格できるようにAWS学習を続けようと思います。
Unity git管理用.gitignoreファイルメモ

Unityを初めて動かしたときに全てのファイルをgit管理してpushにめちゃくちゃ　時間かかってしまったのでバージョン管理する必要のないファイルをコピペで貼れるようにドキュメントを残していきます。

### .gitignoreに貼り付けるコード

```
/[Ll]ibrary/
/[Tt]emp/
/[Oo]bj/
/[Bb]uild/
/[Bb]uilds/
/Assets/AssetStoreTools*

# Autogenerated VS/MD solution and project files
ExportedObj/
*.csproj
*.unityproj
*.sln
*.suo
*.tmp
*.user
*.userprefs
*.pidb
*.booproj
*.svd

# Unity3D generated meta files
*.pidb.meta

# Unity3D Generated File On Crash Reports
sysinfo.txt

# Builds
*.apk
*.unitypackage

# Visual Studio
.vs
Release/
Debug/
```
python3 リスト内包表記のデバッグ

```python:python3
def debug(w):
    print(f'word:{w}')
    return w

list_debug = ["apple", "lemon", None, "cat", "inu"]
list_debug = [debug(s) for s in list_debug]
print(list_debug)
```

```text:out
word:apple
word:lemon
word:None
word:cat
word:inu
['apple', 'lemon', None, 'cat', 'inu']
```
GitHubのリポジトリを共有する方法

#はじめに
私がプログラミング学習を始めたばかりの頃、インストラクターとともにアプリを作成していたのですが、その中で当たり前のようにGitHubのリポジトリを共有するよう言われ、どうやって？？と思ったことを鮮明に覚えています。

今回は、GitHubでリポジトリを作成している前提で、リポジトリの共有方法について話を進めていきます。

#リポジトリの共有方法
###１）共有したいリポジトリを選択
###２）Settingsをクリック
###３）画面左側にあるOptionsの中のManage accessをクリック
###４）invite a collaboratorボタンをクリック
###５）Search by username, full name, or emailと書かれた検索ボックスが出てくるので、 それにしたがって招待したい相手を検索する
###６）相手が見つかったら、選択してSelect a collaborator aboveボタンをクリック
###７）すると、相手にメールが届く
###８）招待された側がInvitationしてCloneを行えば共有完了！！

#おわりに
一度やれば大丈夫だとは思いますが、期間が空いてやり方を忘れてしまわないよう、備忘録として残しておきます。
Ruby 配列の基本的な使い方。いろんなメソッドも紹介❗️

# 配列とは
簡単にいうとデータのかたまりのことです。
つまり***データをたくさん詰められるタンスのような役割***をしています。
そして、データ１つ１つは箱のようなもので、***要素***と呼んでいます。

例えば、それぞれ名前(文字列)を格納するようなイメージになります。

箱１つ１つには番号が振られていて、この番号を***添字***と呼んでいます。添字は0から始まります。



# 配列の生成と定義

⚫︎配列の生成

```rb
array = Array.new    #arrayは配列のこと　  #Arrayは配列を表すclass
array = []    #角カッコ(bracket)は配列を表す。

```

⚫︎配列の使い方

```rb
#配列の初期化
array = []

#数字の配列
numbers = [10,20,30]

 文字列の配列
animals = [ "dog",“cat”, “bird” , "lion" ,"monkey" ,"rabbit" ]

# 様々な要素の配列
items = ["poo", 200, "bar" , false , nil]

```

# 配列のメリット
配列のメリットはいろんなデータをまとめて扱えるので便利な処理ができます。

```rb
#例　以下のa,b,c の中の最大値は?
a = 10
b = 20
c = 30

numbers = [a,b,c]
puts numbers.max   #maxメソッドを使うことで,簡単に最大値を出せる。minメソッドで最小値

#補足　　下のやり方で最小値と最大値が出せます。

[3, 5, 1, 2, 4].minmax  # => [1, 5]
```
# 配列のデータの取得
⚫︎配列のデータの取得

```rb
numbers = [16,32,64]
numbers[0]
#要素の番号を添字で指定する。  ***添字(index）は０から始ます。
```

```rb
numbers = [10,20,30,40,50]

#例　　上記の配列の1つ目の要素を取得せよ
puts numbers[0]

#例　　上記の配列の2つ目の要素を取得せよ
puts numbers[1]

#例　　上記の配列の4つ目の要素を取得せよ
puts numbers[3]

#例:上記の配列の最後の要素を取得せよ
puts numbers[-1]
```

# 配列の追加,　更新　,削除

```rb
scores = [10,20,30,40,50]

#追加
scores << 100    
[10, 20, 30, 40, 50, 100]

scores.push(20)       *rubyは()を省略してもok
=> [10, 20, 30, 40, 50, 20]

#更新
scores[1] = 10
=> [10, 10, 30, 40, 50, 20]


#削除
scores.delete_at(2)　　　*3つ目の要素を削除
=> [10, 20, 40, 50]

sports = ["サッカー", "バスケ", "野球", "バレー"]
# 例
sports.delete("サッカー")
```

# 配列のメソッドの調べ方
配列にはいろんなメソッドがあります。覚えるより調べることが大切です。

⚫︎***pryで調べる***

```
[1] pry(main)> ls []
でメソッドを調べることができます。
```


# Rubyの色々なメソッド
よく使うものからマイナーなものまであります。
興味があるものから調べてください。

⚫︎```push```
```rb
animal = ["犬","猫","鳥","象","猿"]
animal.push "ライオン"
puts  animal

犬
猫
鳥
象
猿
ライオン と出力

puts  animalのputsをprintにすると
["犬", "猫", "鳥", "象", "猿", "ライオン"] と出力
# 補足　
#putsとprintの違いは改行をするかしないかの違いです。
```
他に似たものは```pop,shift,unshift```などがあります。

⚫︎```size count length```
```rb
number = [10,20,30,40,50,true,false,nil,true,nil,false]
puts number.size
puts number.count
puts number.length

で11と出力

#size count lengthの違い
#例えばtrueの数を数えたい
#puts number.count(true)で2と出てきます。
#size 大きさ　length長さ
```

⚫︎```sample```
```rb
 fish = ["マグロ","サケ","イワシ","アジ"]
 random_fish = fish.sample
 puts random_fish 
 #上の魚の種類がランダムに出てきます
```

⚫︎```prepend```
```rb
#先頭に配列を追加します。

animal = "速い"
animal.prepend("チーター") 
puts animal                   

#チーター速いと出力されます。
```

⚫︎```maxとmin```

```rb
#最大値と最小値を同時に出力
level = [5,60,80,100,90,30]
puts level.minmax

#５と100が出力
```

⚫︎```drop```
```rb
#先頭の 要素を捨てて、残りの要素を出力
 score = [10,20,30,40,50,60]
 puts score.drop(3)
 
#40,50,60が出力
```
# 補足
投稿日 2021年08月20日に投稿した記事と合わせた記事です。
AtCoder Beginner Contest 206

##[A - Maxi-Buying](https://atcoder.jp/contests/abc206/tasks/abc206_a)

O(1)

```C++:C++
#include <bits/stdc++.h>
 
#define rep(i,n) for(int i=0; i<(n); ++i)
#define fixed_setprecision(n) fixed << setprecision((n))
#define execution_time(ti) printf("Execution Time: %.4lf sec\n", 1.0 * (clock() - ti) / CLOCKS_PER_SEC);
#define pai 3.1415926535897932384
#define NUM_MAX 2e18
#define NUM_MIN -1e9
 
using namespace std;
using ll = long long;
using P = pair<int,int>;
template<class T> inline bool chmax(T& a, T b){ if(a<b){ a=b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b){ if(a>b){ a=b; return 1; } return 0; }
 
int main() {
    int N;
    cin >> N;
 
    int res = N * 1.08;
 
    if(res<206) cout << "Yay!" << endl;
    else if(res>206) cout << ":(" << endl;
    else cout << "so-so" << endl;
 
    return 0;
}
```

##[B - Savings](https://atcoder.jp/contests/abc206/tasks/abc206_b)

O(N)
シミュレートしました

```C++:C++
#include <bits/stdc++.h>
 
#define rep(i,n) for(int i=0; i<(n); ++i)
#define fixed_setprecision(n) fixed << setprecision((n))
#define execution_time(ti) printf("Execution Time: %.4lf sec\n", 1.0 * (clock() - ti) / CLOCKS_PER_SEC);
#define pai 3.1415926535897932384
#define NUM_MAX 2e18
#define NUM_MIN -1e9
 
using namespace std;
using ll = long long;
using P = pair<int,int>;
template<class T> inline bool chmax(T& a, T b){ if(a<b){ a=b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b){ if(a>b){ a=b; return 1; } return 0; }
 
int main() {
    ll N;
    cin >> N;
 
    ll res=0;
    for(ll i=1; i<=N; i++){
        res+=i;
        if(N<=res){
            res = i;
            break;
        }
    }
    cout << res << endl;
 
    return 0;
}
```

##[C - Swappable](https://atcoder.jp/contests/abc206/tasks/abc206_c)

O(N)
まず、
1 9 7 8 1
の入力に対して、
1 1 7 8 9 とソートしても結果は変わらないです。
そして、重複にどう対応するかが問題の鍵です。

重複に対してはupper_boundを使用します。
log Nでindexを検索してくれます。
その後、配列のサイズ - indexを行うと大きい数の個数がわかります。　

```C++:C++
#include <bits/stdc++.h>
 
#define rep(i,n) for(int i=0; i<(n); ++i)
#define fixed_setprecision(n) fixed << setprecision((n))
#define execution_time(ti) printf("Execution Time: %.4lf sec\n", 1.0 * (clock() - ti) / CLOCKS_PER_SEC);
#define pai 3.1415926535897932384
#define NUM_MAX 2e18
#define NUM_MIN -1e9
 
using namespace std;
using ll = long long;
using P = pair<int,int>;
template<class T> inline bool chmax(T& a, T b){ if(a<b){ a=b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b){ if(a>b){ a=b; return 1; } return 0; }
 
int main() {
    int N;
    cin >> N;
 
    vector<int> A(N);
    rep(i, N) cin >> A[i];
    sort(A.begin(), A.end());
 
    ll res=0;
    for(auto const& a:A) {
        auto itupper = upper_bound(A.begin(), A.end(), a);
        if(itupper != A.end()){
            size_t index = distance(A.begin(), itupper);
            res += A.size() - index;
        }        
    }
    cout << res << endl;
 
    return 0;
}
```
【Jest】Mock化する必要性を考えた

jest/type scriptでテストコードを学習中です。
テストの中でmockを使うケースがあり、謎だった部分が少しだけ理解できた点があり、まとめてみました。


## mockとは？

ここでは、「テスト対象の関数で使う、外部のインスタンスやapiなどを模したもの」という理解です。

関数の単体テストを実施するにあたり、「その他の外部の関数やapiなど」を関数内で呼び出して使うとします。
その時に、外部関数やapiの返す値に頼っていると、単体テストの結果が意図した通りにいかないことがあります。

#### 例えば・・・
引数A:「1~10の数字のランダムな数字を返すクラスのインスタンス（またはapiでも可）」を受け取り、
引数B:「数字」と比べ、
どちらが大きいかで成功か、失敗かを返す関数があったとします。

この関数のテストをしたいと考えます。
ですが引数Aがランダムな結果を返す場合、「成功か失敗か」の確実な結果が予測できません。
そのため意図したテストができない状態となります。
そのほかにも、このように外部関数に依存してしまうことで、例えば外部関数の仕組みが変わったときなどにも、このテストがうまくいかなくなってしまいます。

こういう時にmockを使い、「決まった値を返す」ものを作り上げてしまえば、テストの結果が予測できます。

参考1
https://jestjs.io/ja/docs/mock-function-api
参考2
https://qiita.com/1000k/items/aef6aed46b0fc34cc15e
phpですが仕組みがわかりやすかったです！

### 疑問だったこと
上記の仕組みはなんとなく理解できました。
が、いろんなコードを見ていて、「わざわざmockとして返す必要性」がいまいち分からず。。
例えば「5を確実に返す」mockを作った場合、わざわざmockにせず、ベタがきで5を返してしまえばいいのでは？という謎でした。
実際にコードを書いたりメンターさんに質問したりして、少し理解できた気がするので書いてみます。


### コード

テスト対象の関数。

外部クラスのインスタンスであるmostNumと
任意のテストしたい数字のcheckTargetNumを比べます。
ちなみにgetRandomNum()は、ランダムで1~10を返すmostNumの関数。
テストではランダムだと結果が予測できないので、mock化し5を返すようにしています。
（※mostNumのクラスは割愛）

```ts:functions.ts

export const check = ( 
  mostNum:any,//引数1　ちなみにtsでanyを使うのは良くない
  checkTargetNum:number //引数2
  ):string => {

    if(mostNum.getRandomNum() < checkTargetNum){
      return 'エラー';
    }else{
      return '成功';
    }
  }
```

以下、テストコードです。

```ts:functions.test.ts
//テスト対象のコードを書いているファイルを読み込む
const functions = require('../functions.ts');

test('モックのサンプル',() => {

    //モック化ここから---------------------------------

    const testMock = jest.fn();
    //返り値を確実な数字で返すため、
    //テスト対象の関数で使っている外部関数を模したmockを作る。
    //ただし1~10のランダム数値を返すのではなく、確実なテストをするため固定で5を返す。
    testMock.mockImplementationOnce( () => {
        return{
            getRandomNum:() :number=> {
                return 5;
            }
        }
    })
    const textMockInstance = new testMock;//インスタンスを作成

    //モック化ここまで---------------------------------


    //テスト実行
    //textMockInstanceは元の関数の中で5を返すので、下記の結果でテストが成功します。

    expect(functions.check(textMockInstance,6)).toBe('エラー');
    expect(functions.check(textMockInstance,3)).toBe('成功')


　　//今回の疑問は、下記のように引数で5をそのまま渡してしまえば楽なのでは？という疑問でした
    expect(functions.check(5,6)).toBe('エラー');
    expect(functions.check(5,3)).toBe('成功')

})

```


### 何が良くないか？

書いてるうちにあれ？と思ったのですが、ベタがきで5を渡すようにしてしまうと、元の関数で受け取れない。。。ということです。
テスト対象の元の関数は、引数でインスタンスを受け取っています。
ので、5を直接渡せません。

じゃあ渡すにはどうすべきか？と考えると、元の関数を修正する必要があります。
テストのために元の関数を修正するのは本末転倒気味です。
ので、少々面倒でもmockを使うことで、「外部関数やapiに似せた形のものを渡す必要がある」ということでした！

mockの一部しかまだまだわかってないので、こういうところもmockで必要な箇所だとか、こういうパターンもある！などあればコメントいただけると嬉しいです！
基本情報技術者試験勉強0716

本日の積み上げ結果
基本情報処理技術者試験勉強
平成18年春過去問
平成18年秋過去問
AWSのカリキュラムを読む
間違えた問題の復習

UML オブジェクト指向を用いたソフトウェア開発で使用されるモデリング言語。

カーソル操作　プログラム言語は通常レコード単位の処理を行うのに対し，SQLでは集合単位の処理を行うので，その間をカーソルによって橋渡しする。

SSL 個人認証用のディジタル証明書は，PCごとに固有のものを作成する必要がある。

QRコード　縦・横方向に情報をもたせることによって，1次元シンボルよりも多くのデータを記録することができるコード。

ソフトウェア管理ガイドラインは、ソフトウェアの違法複製を防止するため，法人，団体などを対象として，ソフトウェアを使用するに当たって実行されるべき事項をとりまとめたものです。ソフトウェア管理責任者、ソフトウェアユーザといった対象ユーザごとに実施すべき事項を、管理方法や管理体制といった点から具体的に取りまとめています。

オンラインシステムの障害対策　マスタファイルは，オンラインサービスの終了時にバックアップを取得するだけでなく，システムの特性に応じた時期にバックアップファイルを取得する。

セキュリティプロトコルSSL  SSLを利用するWebサーバでは，そのFQDNをディジタル証明書に組み込む。

フラッシュメモリ　不揮発性メモリの一種であり，電気的に全部又は一部を消して内容を書き直せるメモリである。
【実践！Gitコマンド】「git stash」で、ブランチの作業を一時保存する

他のブランチで作業したい、、、
でも作業ブランチを中途半端な状態でコミットさせたくない、、、
そんな時に使えるのが、**「git stash」**。
**変更を一時保存してのちに再開できる**という、スーパー便利コマンド。


## 目次
-  変更を一時保存した後に再開する
-  関連コマンドあれこれ


## 変更を一時保存した後に再開する

### ① 作業ブランチの変更を一時保存
```
$ git stash save -u "作業中"
```
 - **「save」**は省略可能。  
 - **「”作業中”」**の部分で、一時保存する作業に任意のコメントを付けることができる
 - **「-u」**は新規作成ファイル(追跡対象に含まれていないファイル)も一時保存の対象にできるオプション。要は「git add」を実行しない場合につけたほうが良い。  
 
これで一時保存完了。
ちなみに以下のコマンドで一時保存した作業の一覧を確認できる

```
$ git stash list  
stash@{0}: On test: stash 作業中
```

### ② 一時保存した作業を再開する
```
$ git stash pop stash@{0}
```
**stash@{0}**の部分を省略した場合、直近に保存した作業が再開される
※再開すると同時に一時保存リストから削除される
一時保存を残しておきたい場合は**「git stash apply」**コマンドを使用すること！

## 関連コマンドあれこれ

### ▼一時保存した作業を削除する
```
$ git stash drop stash名
```

### ▼一時保存した作業をすべて削除する
```
$ git stash clear
```

### ▼一時保存した作業の詳細を見る
```
$ git stash show stash名 -p
```
- 「-p」オプションでさらに詳細な情報を見ることができる
Tabを移動すると再描画されてデータがロードされない問題

Tabを移動して戻ってくると、ロードした写真が表示されなくて困っていました。

```swift
struct ParentView: View {
    @ObservedObject var photoLibrary: PhotoLibrary
    
    init(photoLibrary: PhotoLibrary) {
        self.photoLibrary =  photoLibrary
    }
   ・・・
```
.onAppearでデータをロードしていましたが、戻ってきたときに元の写真が残ってたり残ってなかったり・・・

で、init()内でロードしたら多分解決しました。

```swift
struct ParentView: View {
    @ObservedObject var photoLibrary: PhotoLibrary
    
    init(photoLibrary: PhotoLibrary) {
        self.photoLibrary =  photoLibrary
        photoLibrary.getAllPhotos() //データをロード
    }
   ・・・
```

参考: ありがとうございます
https://inon29.hateblo.jp/entry/2020/04/05/161913
https://inon29.hateblo.jp/entry/2020/04/04/150120
GameObjectのStaticフラグのメモ

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61266/a55b4163-77c4-b9d4-ea47-33bf5807b499.png)
気付いたらStaticのフラグが変わっていたので自分用にメモ書きしておく

https://docs.unity3d.com/ja/2021.1/Manual/StaticObjects.html

|名前|大別|用途|
|:-:|:-:|:-:|
|Contribute GI|GI|GIの計算にMeshRendererを含むかどうか。以前あった「Lightmap Static」に相当|
|Occluder Static|オクルージョン|Static Occluderとなる。|
|Batching Static|バッチング|静的バッチングの対象になる|
|Navigation Static|ナビゲーション|ナビゲーションの静的計算対象とする|
|Ocludee Static|オクルージョン|Static Ocludeeとなる|
|Off Mesh Link Generation|ナビゲーション|ナビゲーション静的計算時の「メッシュがつながっていない経路」の生成対象とする|
|Reflection Probe Static|GI|BakedのRefrectionProbeの表示対象とする|

Static Occluder、Static Occludeeについてはこちら

https://docs.unity3d.com/ja/2018.4/Manual/OcclusionCulling.html

> Occludee Static をどのような場合に利用できるか説明します。他のオブジェクトを遮ることがない透明なオブジェクトや小さなオブジェクトには、Occluders ではなく Occludees のチェックマークをつけるべきです。このチェックマークが付けられたオブジェクトは、他のオブジェクトによる遮蔽判定のときには考慮され、遮蔽する側として判定された場合には無視されます。これにより計算コストが下がります。

との事で、Occludeeにすると他者に隠された時は消えてくれる＆自分は他者を隠すことは無い、みたいな感じ？
不透明且つデカい遮蔽物ならOccluder、半透明や小さい不透明オブジェクトならOccludeeにするのが一番良いのかな。追って調査しよう。

# 参考資料

https://tsubakit1.hateblo.jp/entry/2016/11/12/235641



、
YubiKey を使って git の ssh 接続を構築する（macOS編）

## ことの発端

社内で２要素認証・多要素認証で ```YubiKey``` を採用しました。
で、購入した ```YubiKey5シリーズ``` には ```FIDO2 (WebAuthn)``` のみならず ```PIV``` 即ち ```ICカード``` の機能を持っているので、 ssh の公開鍵暗号で使うことにしましたので、 macOS での導入手順を示します。

なお、この記事では以下を前提とします。

* 既に ssh の公開鍵暗号方式を使って git のクローンやプッシュを経験している。
* ```PIV``` 機能がある ```YubiKey``` を所有している。
* ```SouceTree``` での設定例。 [^1]

[^1]: コマンドラインを使っても可能です。しかし、 ```GitHub Desktop``` はトークンによる ```https``` アクセスを使用するため使用できません。


## 1. ```YubiKey``` の設定

下記の記事を参考に ```YubiKey``` を設定してください。

https://qiita.com/terukazu/items/c97de5024f089997ae29

※　この記事で説明している取得した公開鍵を ```GitHub``` や ```Bitbucket``` に設定してください。

## 2. ```Yubico PIV Tool``` をインストール

PKCS11 の認証モジュールが必要になりますので、インストールしておきましょう。
デフォルトでインストールすると ```/usr/local/lib/libykcs11.dylib``` に必要な認証モジュールがインストールされます。
ここでは以降、デフォルトでインストールした前提で進めます。


https://developers.yubico.com/yubico-piv-tool/Releases/


## 3. SourceTree の設定

1. メニューから [SouceTree] - [環境設定...] を選択します。
1. タブで　[アカウント]　を選択して、 [追加...] をクリックします。
1. ```ホスト``` を選択し、 ```認証タイプ``` を ```OAuth``` にして ```アカウントを接続``` をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1038343/9532ccee-694e-9a4f-2638-d2628b9d6d95.png)
1. ```保存``` をクリックして終了です。

通常であれば 　```キーを生成``` をクリックするところですが、今回は ```YubiKey``` を使うのでこのままでOKです。
この ```キーを生成``` していないために、アカウントの表示では警告マークが付いていますが、気にしなくて大丈夫です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1038343/1a04b10e-44df-f73b-a937-f458d5cf50e4.png)



## ４. ssh のホスト設定

```~/.ssh/config``` ファイルに下記を追加します。

```config:.ssh/config
Host github.com
  PKCS11Provider /usr/local/lib/libykcs11.dylib
```

```github``` に接続してみましょう。
```YubiKey``` を挿入した後、下記のコマンドを実行します。

```shell
ssh git@github.com
```

すると下記の表示がされますので、 ```YubiKey``` の ```PIN``` を入力し ```Enter``` を押下します。

```shell-session
Enter PIN for 'YubiKey PIV #15801817': 
```

その後、下記のような表示になれば成功です。

```shell-session
PTY allocation request failed on channel 0
Hi terukazu-inoue! You've successfully authenticated, but GitHub does not provide shell access.
Connection to github.com closed.
```

### 5. SourceTree を使ってみる

既に設定は終わっていますので、いつものように git でクローンやプッシュを行います。
その際、下記のようなパスワードの入力ダイアログが表示されるので、 ```YubiKey``` の ```PIN``` を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1038343/65141bec-0bbd-ee01-1a01-ad35b3b85905.png)
モダンな企業への転職を目指してVue.jsの勉強をしてみた！！

## この記事を書くにあたって
私は都内のWeb制作会社で働くエンジニアです。今の現場ではPHPを使ったスクラッチ開発をしています。今後モダンな企業への転職を考えているので勉強面ではLaravelを学んでおり、その延長線上でVueの勉強もしているので記事にまとめてみました。

## Vue.jsとは
[Vue.js公式サイト](https://v1-jp.vuejs.org/)
Evan You氏が創始者である　Javascriptのフレームワークです。リリースは2014年にされました。

Vue.jsは、他のjavascriptのフレームワークと比べてシンプルであり、学習コストが低いと言われています。

## 実際にVue.jsを使ってみた
### インストール
今回はCDNを使って実装しました。インストールの必要はないので、とても簡単にVue.jsを、使うことができます。
中規模開発ではnpmやyarnを利用して、インストールする必要があるみたいですね。

```html
<script src="https://unpkg.com/vue"></script>
```

### Hello Worldを出力
シンプルにHello Worldを表示させてみます。


```html
<!DOCTYPE html>
<html>
<head>
  <title>stady Vue</title>
</head>
<body>
  <div id="app">
    <h1>{{ message }}</h1>
  </div>

  <script src="https://unpkg.com/vue"></script>
  <script src="/app.js"></script>
</body>
</html>
```

```javascript
const app = new Vue({
  el: '#app',
  data: {
    message: 'Hello world'
  }
})
```
![スクリーンショット 2021-08-16 22.23.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/697259/1bd3c167-e478-211b-e8c2-f699d9301af7.png)

### ソースコードについて
HTMLの`script`のCDNからVueのソースコードを取得しています。`javascript`のロジックは`app.js`に切り出しています。

`app.js`では、Vueオブジェクトのインスタンスをnewで生成しています。Vueオブジェクトのインスタンスが生成されることで、Vueアプリケーションが起動します。
設定オブジェクトによって、どのデータ（変数）がDOMのどの要素と関連づけられるのか、どの関数がどのイベントと関連づけられるのか、この設定オブジェクトから取得します。


#### ✅el
まず一つ目のプロパティは`el`です。

```javascript
el: '#app'
```
`el`には、`#app`のように、DOM要素を指し示すセレクタが指定されます。このプロパティの値は、Vueアプリケーションの範囲、Vueの管轄領域を表します。今回は`<div id="app">`タグ内部がVueアプリケーションとして認識されるということです。

#### ✅data
二つ目のプロパティは`data`です。

```javascript
data: {
    message: 'Hello world'
  }
```

`data`は、Vueアプリケーション内で利用できるデータ（変数）を表します。Vueアプリケーション内とはつまり`el`でした範囲です。変数名とその値を組みにしてオブジェクトが指定されます。

#### ✅テンプレート

```html
<div id="app">
  <h1>{{ message }}</h1>
</div>
```

`<h1>{{ message }}</h1>`　に注目してみてください。

- 二重括弧で指定することによって値が表示される。
- 設定オブジェクトのdataプロパティに指定したオブジェクトに含まれている、messageがアプリケーション内で使用できる
- Vueインスタンスが起動すると`{{ message }}`の部分が`Hello World`に書き換えられ、`<h1>Hello world</h1> `というDOMが生成された。

##　まとめ
- `#app` のように、DOM要素を指し示すセレクタが指定されます。このプロパティの値は、Vueアプリーケーションの範囲、Vueの管轄領域を表します。
- `data`は、変数名とその値を組みにしたオブジェクトが指定されます。Vueアプリケーション内で利用できるデータ（変数）を表します。
GraphqQL初心者の受講メモ

# はじめに
[最短・最速で学ぶGraphQL実践入門 新たなAPI規格をマスターしよう！ サーバーサイドCRUD編 (Node.js](https://www.udemy.com/course/graphql-api-crud-nodejs/))
の受講メモです（無料でこれだけ勉強できるなんて、、、）
これだけじゃよくわからないので何かの間違いでこの記事に辿り着いた方は受講をお勧めします

## セットアップ
1. npm initでjsonファイル作成
2. npm install expressでjsonに追加
3. app.jsでexpress読み込み  
appオブジェクトではwebアプリケーションに必要な変数・メソッド保持
- lisetenメソッド：サーバ起動
- nodemonで起動すれば変更保存時自動で再起動
- graphqlHTTPオブジェクト
4. npm install nodemon json追加　　nodmon appで起動
5. npm install graphql express-graphql
6. 一つのエンドポイントを実現するためにミドルウェアappオブジェクトよりappメソッド

## スキーマ定義
graphqlの仕様を表現
データをどのように扱うか、リレーションの定義
1. Movieタイプの生成
2. ルートクエリの作成

## mongoDBの設定
1. クラスター作成
2. ユーザ作成
3. クラスター選択 -> コネクト　-> DB接続url
4. npm install mongoose
5. appにmongooseオブジェクト作成→.connectで接続url設定
6. データ作成

## データベースモデルの作成
1. models -> movie.js
2. モデルをschema.jsで読み込み
3. そのままresolve関数の記述
4. module.exports = new GraphQLSchema→app.jsで読み込み

5. ミドルウェアに追加（一緒にgraphiQL設定）
## ミューテーション（データ更新処理）
1. クエリ同様schemaにミューテーションオブジェクト作成  
☆typeとmodelの違いを調べる必要あり
2. exportsするGraphQLSchemaに追加
3. graphiQLからmutation実行

## DirectorTypeの追加
*流れ予想*  
1. スキーマでDirectorType作成→◯
2. RootQueryのfieldsにdirector追加→×追加には不要、その後実装だった
3. MutationのfieldsにaddDirector追加→◯
4. models -> director.js作成→◯
5. スキーマでdirectorモデル読み込み→×と思いきや◯  
~~addメソッドのnewではなぜかDirector（モデル）ではなくDirectorTypeで作成~~
←講師の勘違い、あってた  
~~再度GraphiQL実行、→mutation失敗~~←resolve関数のsaveメソッド忘れ、解決  
collectionに追加確認、_v属性って何だろう。。。0が入ってたけど→データの更新回数カウント

## Type間にリレーション追加
1. MovieモデルのSchemaにDirectorID追加
2. schema.jsのMovieモデルfieldsにdirector(IDじゃないよ、ID以外の情報も欲しいでしょうが）追加（ここのtypeはDirectorType）、Director情報取得用のresolve追加  
- ってことはmodelファイルの方には単純に保持しているデータ、schemaの方にはそのデータから表示したい情報まで記述か！
- resolve関数のparentってTypeの元になってるモデルファイルで定義したパラメータが入ってる、Typeの親がModelってことなのね
3. schmea.jsのDirectorモデルfieldsにmovies追加、typeは`new GraphQLList(MovieType)`←ただのGraphQLListじゃない  
resolve関数のreturnはfindByIDではなく（そりゃそう、DirectorIDに一致してるMovieIDの映画なんてあるかい）、DirectorIDがparent.idに一致している映画全部を検索する
4. mutationの変更、addMovieにDirectorID追加

## 一覧取得
RootQueryに追加、特に不明点なし

## mutationに更新処理追加
1. updateDirector追加  
※javascriptの&&は左がfalseなら左を返し、左がtrueなら右の値を返す  
戻り値は`findByIdAndUpdate`メソッドでargs.idと一致したdirectorをupdateし、第３引数の{new: true}で変更後の値を取得
2. 同様にupdateMovie追加

## mutationにデリート処理追加
1. deleteMovie追加
※findByIdなどはmongooseのメソッド  
findByAndRemoveで削除
2. deleteDirector追加
家で手軽に始められるIoT化

#対象者

* 「IoTとはなんぞや？」な人
* お家を中を少しでもIoT化したい人

#そもそもIoTとは？

IoTの正式名称は「Internet of Thing」です。
家電製品のようなモノをインターネットに繋げ、より便利に活用することを意味する言葉です。

今の段階だとモノをインターネットと繋げることでどうしたの？って感じだと思いますが。
IoTのおかげで以下のようなことができるようになります。

**【IoTによって便利になること】**

* 真夏に自宅に到着する前に事前にエアコンをつけて部屋を涼しくすることができる
* ベッドのセンサーによって、患者の睡眠状態や呼吸数、心拍数等をモニタリングできる
* 冷蔵庫とスマートフォンを連動させることにより、扉の閉開数（無駄を無くす管理のため）を把握できる


などなど、たくさんの便利なことを可能にします。


#手軽に始められるIoTとは何か？

下記のモノを用意することで、家にある赤外線で動かすことのできる**家電製品を声で全てコントロールできるう**になります。また**スマートフォンを用いることで、家電を遠隔操作することも可能**になります。

#家でのIoT化のために必要なもの

必要なものは以下の通りになります。

1. スマートリモコン（お持ちのスマートスピーカーに対応したモノ）
1. スマートスピーカー（AmazonEchoやGoogleHome等）
1. 赤外線リモコン
1. 赤外線リモコンで動く機会（エアコンやテレビ等）

上記の２と3と4については説明が不要だと思うので省略させていただきますが、「スマートリモコン」は知らないからもいらっしゃるかと思うので簡単に説明させていただくと、スマートリモコンは赤外線を学習することができきます。学習させた赤外線を放つことができ、これにより様々な機器をコントロールできるようになります。


また、１と２を今から買う場合は買うものにもよりますが大体8000円〜10000円もあれば揃えられるかと思います。

#IoT化のための設定

行えるようにするためにはまず設定が必要となります。

細かい手順や、ボタンはどこにあるか？等を細かな説明を行うと大変時間がかかってしまうので省略しますが大体の場合が以下のような設定手順になるかと思います。


Step1：スマートリモコンに操作できるようにしたい機器の赤外線を学習させる
Step2：リモートリモコンとスマートスピーカーを連携できるようスマートスピーカーを設定する
Step3：（声で操作できるようにするためには）トリガーとなるフレーズをスマートスピーカーに設定する


上記の設定が終われば、声やスマートフォンを使って様々な機器を操作できるようになります。
詳しい設定方法は頑張って調べてください🙇‍♂️


---
参考にした記事
https://mono-wireless.com/jp/tech/Internet_of_Things.html
https://www.cross-c.co.jp/column/business/690/
pythonによるランレングス圧縮

## 概要
pythonでランレングス圧縮がしたくなった時に、パッと確認するための備忘録です。

## ランレングス圧縮について
ランレングス圧縮とは、データを圧縮するためのアルゴリズムの一つで、連続して現れる文字を、繰り返した回数で置き換える方法です。
例えば、"AAAABBBBBCC"のような文字列があった際に、"A4B5C2"のように、Aが４回、Bが５回、Cが２回出現したといった形で置き換えを行います。

## 実装について
自分は[こちら](https://atcoder.jp/contests/typical90/tasks/typical90_cf)の問題で利用したため、端から文字列を順にたどっていき、配列に格納する流れで実装しました。
以下の実装では、文字列の長さ分の計算量となっています。

※もっと高速にできる、メモリの消費を抑えるために、こうした方が良いなどあれば、是非コメントお願いします。

```python

def rle(s):
  bef = s[0]
  cnt = 1
  arr = []
  for i in range(1, len(s)):
    if s[i] == bef:
      cnt += 1
    else:
      arr.append([bef, cnt])
      bef = s[i]
      cnt = 1
  arr.append([bef, cnt])
  return arr

```
gRPC ruby の`Google::Rpc::Status.decode`の挙動

この記事は手元でコードを動かしながら書いているわけではなく、ただ調べたことをざっとまとめているだけである。よって、何かミスってるかも。「スニペットでto_protoで、なぜわざわざprotoにリバースしてるんだ」的なツッコミもなしで。あくまで、`Google::Rpc::Status.decode(シリアライズされたリクエスト)`の挙動を見せるのがこの記事の目的だからリバースしてます。


## gRPC ruby の クライアント側で、


```rb
      client = GetPostsService::Stub.new('localhost:5005')

      begin
        post_response = client.get_posts(
          GetPostsRequest.new(param)
        )
        puts(
          Google::Rpc::Status.decode(post_response.to_proto)    ## ここ
        )

      rescue GRPC::BadStatus => e  
        # Handle error here!
      end
```




### case1. status=OK の場合、

```rb
=> <Google::Rpc::Status: code: 0, message: "", details: []>
```

なお、Google::Rpc::Status.decodeの引数に空配列を引数に渡してみると、この場合もstatus=0になった。

```rb
Google::Rpc::Status.decode('')
=> <Google::Rpc::Status: code: 0, message: "", details: []>
```
input要素に入力した文字列がはみ出ないようフォントサイズを調整

input要素に入力した文字列がはみ出る場合、指定したフォントサイズを下限としてはみ出なくなるサイズに調整します。

![capture.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618708/64ec9cef-d38a-7640-7f93-380976dff99e.gif)

####[動作デモ](https://akebi.jp/temp/fontSizeAdjust.html)####

####動作概要####
type=textのinput要素において、valueの文字列が表示範囲からはみ出るにつれて(IEなど一部のブラウザを除き)scrollWidthプロパティの値が増加するので、scrollWidthが初期値より大きければ初期値に収まるまでfontSizeを下げる、という処理を行なっています。

```html:
<!DOCTYPE html>
<html lang='ja'>
<head>
<meta charset='utf-8'>
<title>input[type=text] fontsize自動調整サンプル</title>
<meta name='viewport' content='width=device-width,initial-scale=1'>
<style>
input {
  font-size: 40px;
  width: 280px;
}
</style>
</head>
<body>
<p>
  通常<br>
  <input type='text' value='0123456789'>
</p>
<p>
  自動調整適用<br>
  <input type='text' id='test1' value='0123456789'>
</p>
<p>
  自動調整適用(下限20px)<br>
  <input type='text' id='test2' value='0123456789'>
</p>

<script>
'use strict';
const fontSizeAdjuster = (function() {
  const lowerLimit = 10;
  return {
    adjust: function(e, ls, p) {
      e.style.fontSize = p.defaultFontSize + 'px';
      if(ls < 1) ls = 1;
      for(let i = p.defaultFontSize; i >= ls; i /= 1.02) {
        if(e.scrollWidth <= p.defaultScrollWidth) {
          break;
        }
        e.style.fontSize = i + 'px';
      }
    },
    set: function(e, ls) {
      if(e === undefined || e.tagName !== 'INPUT' || e.type !== 'text') {
        return;
      }
      if(isNaN(ls)) {
        ls = lowerLimit;
      }
      const v = e.value;
      e.value = '';
      const cs = window.getComputedStyle(e);
      const p = {};
      p.defaultFontSize = parseFloat(cs.fontSize);
      p.defaultScrollWidth = e.scrollWidth;
      e.style.height = cs.height;
      e.style.width = cs.width;
      e.style.padding = cs.padding;
      e.value = v;
      const a = this.adjust;
      a(e, ls, p);
      e.addEventListener('input', function() {
        a(e, ls, p);
      });
    },
  };
}());

fontSizeAdjuster.set(document.getElementById('test1'));
fontSizeAdjuster.set(document.getElementById('test2'), 20);
</script>
</body>
</html>
```

####設定方法####

**fontSizeAdjuster.set( 対象input要素 [,フォントサイズ下限] );**
(フォントサイズ下限の単位はpx、省略時は10px)

----

~~iOS/iPadOSの場合は、フォントサイズの変化に伴ってinput要素自体のサイズも少し変動してしまいます。~~　追記: paddingを初期値で固定することで解消しました。
[Ruby] digitsメソッド

##はじめに
RubyでAtCoderを解いていたときに、便利なメソッドを見つけたので記事にしておきます。
よろしくお願いします。

##digitsメソッド

digitsメソッドはinteger型に用意されているメソッドで、桁ごとの数字を一つずつ配列の中に入れてくれるメソッドです。正の整数に使うことができます。

例えば、1234という数字があったとします。これにdigitsメソッドを使うと↓

```ruby
1234.digits
=> [4, 3, 2, 1]

174893.digits
=> [3, 9, 8, 4, 7, 1]
```

また、digitsに引数を渡すことができます。引数を渡した数字を基数として、その記数法で表記した数値を配列に一つずつ入れます。
つまり引数を渡さなかった場合（上記の例）、基数は10となっています。

```ruby:引数を渡した場合
16.digits(16)
=> [0, 1]

3.digits(2)
=> [1, 1]
```

この辺は進数の理解が必要ありますね。
Composeで@Previewを付けたのにプレビューが表示されない件

# 何が起きたのか
Jetpack Composeを導入したのに、@Previewを付けてもプレビューが表示されません。
下記の画像を見てください。正確には、本来Android Studioの画面右側に表示されるはずの「Code / Split / Design」のタブが表示されません。
![スクリーンショット 2021-08-16 20.13.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610553/2e84d1d8-2ca1-6295-0db9-bd8338df7bd0.png)

# 環境

* Android Studio Arctic Fox | 2020.3.1

```app/build.gradle
dependencies {
    implementation("androidx.compose.ui:ui:1.0.1")
    implementation("androidx.compose.ui:ui-tooling:1.0.1")
    implementation("androidx.compose.foundation:foundation:1.0.1")
    implementation("androidx.compose.material:material:1.0.1")
    implementation("androidx.compose.material:material-icons-core:1.0.1")
    implementation("androidx.compose.material:material-icons-extended:1.0.1")
    implementation("androidx.compose.runtime:runtime-livedata:1.0.1")
    implementation("androidx.compose.runtime:runtime-rxjava2:1.0.1")
    androidTestImplementation("androidx.compose.ui:ui-test-junit4:1.0.1")
}
```

# 解決策
下記を追加しましょう。（バージョンは2021年8月16日時点）

```app/build.gradle
plugins {
    id 'kotlin-android'
}

android {
    defaultConfig {
        minSdkVersion 21
    }
    buildFeatures {
        compose true
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = "1.8"
    }
    composeOptions {
        kotlinCompilerExtensionVersion '1.0.1'
    }
}
```
```./build.gradle
buildscript {
    ...
    dependencies {
        classpath "com.android.tools.build:gradle:7.0.0"
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.21"
        ...
    }
}
```

そしてsyncをすると...表示されました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610553/0fe85cd4-f7a1-0359-7d54-166fdd0a2ee3.png)


詳しい記載や、最新のバージョンは下記をご確認ください。
https://developer.android.com/jetpack/compose/interop/adding

# こんなのどこに書いてあったんだ...
Android Developersの「 [Use Android Studio with Jetpack Compose](https://developer.android.com/jetpack/compose/setup) 」のページを見て下さい。
一番下にこんな記載がありました。
> ## Add Jetpack Compose to an existing project
> If you want to use Jetpack Compose in an existing project, you’ll need to configure your project with required settings and dependencies. For more information, see [Adding Jetpack Compose to your app](https://developer.android.com/jetpack/compose/interop/adding).

このリンクをタップすると、上記解決策が書いてあります。
英語のページでもちゃんと読まねば...
SCSを受験した結果とリモート受験ではOnVue一択

# SCS

AWSの資格をプロフェッショナルまで取得したのでスペシャリストに挑戦しました。

プロフェッショナルの記事はこちら

https://qiita.com/instant_baby/items/4b8d3104d7b941126e4a

プロフェッショナル資格を取って約半年の期間を空けて受験しました。
普段業務ではldapを使用したユーザー管理やawsでIAMユーザーの保守運用を主に扱っています。

今回勉強するにあたり、基本的には公式ドキュメントを読み込むことをメインにしました。
時たまkoiwaclubを利用した程度です。

https://aws.koiwaclub.com/

結果的に、↑の問題から類似した問題はほぼほぼ出なかったという印象でした。
AWSのセキュリティに関するあれこれは仕事でそこそこ触っていたので、個人的な難易度としてはSysOps程度の感触です。

IAM、セキュリティグループやNACL、WAF、GuardDuty、いわゆるセキュリティに関わるサービスを網羅するようにドキュメントを読み込んでいけば合格に近づくのではないかと思います。

学習期間は3週間ほどで受験しました。
前日に友人と泥酔してしまい、当日はひどい二日酔いに悩まされました。

ここまでの試験全てで前日泥酔からの合格だったので、
もうここまで来たら受験前日に泥酔した方が受かるんじゃないかと泥酔しながら考えていました。

結果は合格でした。
スコアは834点でした。

![スクリーンショット 2021-08-16 20.16.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1526421/07806bfe-8dc4-2ac2-89fc-0e6d4ec63911.png)

問題全体を通して、内容をしっかり理解できればそこまで頭を悩ませることは少なくなると思います。

問題を一周するのに70分、回答に悩んだフラグが15。
フラグを回収するのに30分かけました。
ここまでで100分を消費し、ここから20分かけて全問見直しをして終了しました。

SAAやSOAを取得していれば行けそうな難易度です。が、プロフェッショナルを取得してから挑むのがおすすめです。

少しでも参考になれば幸いです。
(前日泥酔AWS合格率100%記録はいつまで続くのか。。。)

最後まで閲覧いただきありがとうございました。
MockKでトップレベル関数をモックする

[MockK](https://mockk.io/)でトップレベル関数をモックする方法をメモがてら記載します。

こんな `log` 関数があった場合。

```kotlin:Ext.kt
package com.example

fun log(message: String) {
    Log.d("log", message)
}
```

こんな感じで書けばOKでした。

```kotlin:ExtTest.kt
class ExtTest {

    @Test
    fun test_log() {
        mockkStatic("com.example.ExtKt") // ①
        every { log(any()) } just runs // ②

        // ・・・テストコード・・・
    }
}
```

# ポイント:bulb:
① `mockkStatic` を使用し、トップレベル関数が定義されているクラスを指定します。
今回の場合、

- package が `com.example`
- ファイル名が `Ext.kt`

なので、 `com.example.ExtKt` を指定してあげればOK。

② あとは普通にMockKを使うのと同様に、 `every` を使って `log` 関数が呼ばれた場合の処理を指定してあげます。
【競プロ典型90問】004の解説（python）

## 概要
[競プロ典型90問](https://atcoder.jp/contests/typical90)の解説記事です。
解説の画像を見ても分からない（~~理解力が足りない~~）ことが多々あったので、後で解き直した際に確認できるようまとめました。

※順次、全ての問題の解説記事を挙げていく予定です。
※★５以上の問題は難易度的に後回しにしているため、投稿時期が遅くなる可能性があります。（~~代わりに丁寧に解説してくれる方いたらぜひお願いします~~）

## [問題004-Cross Sum](https://atcoder.jp/contests/typical90/tasks/typical90_d)

### 問題概要
マス(i, j)と同じ行、同じ列にあるマスの合計値を全てのマスで求める。

### 制約

```math

2 <= H, W <= 2000 \\
1 <= Ai <= 99 \\

```
・入力は全て整数。


### 解き方
まず初めに、全てのマスにおいて、順番に合計値を求めていく方法が考えられるかと思います。
この考えでは、マスの総数が$HW ≒ 10^6$で各マスにおける処理が$H+W ≒ 10^3$となるため、TLEになってしまいmます。

上記の方法では、各行、各列の合計を繰り返し求めてしまっています。
そこで、今回は、あらかじめ各行、各列の合計を求めておき、それらの組み合わせを全てのマスにおいて、求める手段をとります。（この方法では、A[i][j]が二重に足されるため、１つ分減算する点にご注意ください。）

実装の流れは以下になります。
1. 各行H、列Wの和をそれぞれ求める。
2. マス i, j と同じ行、同じ列にあるマスの合計値を求める。

1の処理でも２の処理でも$HW$、
すなわち $10^6$ のオーダーで求められるので、十分に間に合います。

![参考画像](https://raw.githubusercontent.com/E869120/kyopro_educational_90/main/editorial/004.jpg "公式解説画像")

引用元：[競プロ典型90問 Github](https://github.com/E869120/kyopro_educational_90)

### 実装

```python:answer.py

# 入力の受け取り
H, W = map(int, input().split())
A = [list(map(int, input().split())) for _ in range(H)]

# 各行の和をLに格納する
L = []
for i in range(H):
  L.append(sum(B[i]))

# 各列の和をRに格納する
R = []
for i in range(W):
  cnt = 0
  for j in range(H):
    cnt += B[j][i]
  R.append(cnt)

# 各マスにおいての行と列の合計値を求め、二重に加算されているA[i][j]を減算する。
B = []

for i in range(H):
  l = []
  for j in range(W):
    sums = L[i] + R[j] - A[i][j]
    l.append(sums)
  B.append(l)

# 答えを出力する
for i in range(H):
  print(*B[i])

```

## 最後に
今回の問題は、必要な値を事前に計算することが大きなポイントでした。

問題の解説を読んでも他の人のコードを見てもさっぱり分からないという方の
力に少しでもなれれば幸いです。
コードの改善点やその他、ご意見などあれば、気軽にコメントください。
また、この記事を読んで理解できた方はぜひLGTMを押していただけると嬉しいです。
（~~記事投稿のモチベになります。~~）

ここまでお読みいただきありがとうございました。
【rebase】develop ブランチに追いつけ！！！【備忘録】

# はじめに
<!-- 発端や概要を記載 -->
チーム開発しているときに自分の作業ブランチがdevelopブランチに取り残されてることってありますよね。今回はそんなお悩みを持つあなたに朗報です。
なんと、developブランチでrebaseすることで解決できます！（みんな知ってる）

# 目次
<!-- タイトルとアンカー名を編集 -->
1. [Chapter1](#Chapter1)
1. [Chapter2](#Chapter2)
1. [Chapter3](#Chapter3)
1. [Chapter3でconflictした場合](#other)
1. [Chapter4](#Chapter4)

<!-- 各チャプター -->
<a id="#Chapter1"></a>
# Chapter1
まずdevelopブランチをチェックアウトして、最新にします。

```言語名:ターミナル
$ git checkout develop
$ git pull --rebase origin develop
```

<a id="#Chapter2"></a>
# Chapter2
次にrebaseしたいブランチ（hogehoge）をチェックアウトし、最新にします。


```言語名:ターミナル
$ git checkout hogehoge
$ git pull --rebase origin hogehoge
```

<a id="#Chapter3"></a>
# Chapter3
次にrebaseしたいブランチ(hogehoge)をチェックアウトした状態で、developブランチでrebaseします。


```言語名:ターミナル
$ git rebase develop
```



<a id="#other"></a>
# Chapter3でconflictした場合
`git status`でどういう状況になっているか確認します。


```言語名:ターミナル
$ git status
```
この段階で怖くなったので逃げたいという方がおられましたら`git rebase --abort`でrebaseを実行する前の状況に戻すこともできます。戻した後はパソコンを閉じて気晴らしにコンビニまで散歩に行っておいしいコーヒーを買って心を落ち着けましょう。

「逃げちゃダメだ逃げちゃダメだ逃げちゃダメだ」という方は、conflictを解消しましょう。（私はVScodeを使って解消しています。）

解消した後は、下記を行いrebaseを続けます。

```言語名:ターミナル
全ての変更点を追加
$ git add -A

conflictが解消されているか確認
$ git status

解消されていることを確認後rebaseを続ける
$ git rebase --continue
```
これでconflictが解消されてrebaseが完了します。

<a id="#Chapter4"></a>
# Chapter4
最後にrebaseが完了したブランチ(hogehoge)をpushします。

```言語名:ターミナル
$ git push --force-with-lease origin hogehoge
```

<a id="#Chapter4"></a>
# 終わりに
これで先に進んでいたdevelopブランチに追いつけるはずです。
記事を書いてみたものの少し自信がないので間違えてる箇所がございましたらご指摘いただけると幸いです。
メールの仕分けをPower Automate Desktopを使って自動化してみた

##訃報はいつ来るかわからない
メール業務の悩みとして、社内で使用している**メールシステムが２つ**あります。
メインはOutlookMailを使っていますが主に店舗向けにP2Netが導入されており、
**そちらに投稿があっても気付かないことが多いです**。

中でも**「訃報」に関する連絡を見落とすと対応が遅れる**為、タイトルに「訃報」が含まれる場合、個人のOutlookMailもしくはLINEに通知がきたらいいのにと常日頃思っていました。

今回は、P2Netの仕組みをNode-REDやintegromat等と連携することができなかった事と、設定の簡単さを優先してPower Automate Desktop（以下PAD）をツールとして選びました。
チーム内で自分だけが使えるのではなく、パートさんでも自分で設定して、触ってもらえるように広げていきたいと思います。
本来の願いだった「通知」には至りませんでしたが、**PADを動作させるだけで10秒もかからずに確認できる**為とても快適になりました。


##P2Netのメールフォルダで「訃報」を検索
**PAD**の**「Webレコーダー機能」**を使用して、
P2Netの受信トレイに「訃報」を含むメールの検索までを自動化しました。
本当は添付ファイルをOutlookMailへ転送したかったのですが、添付ファイルのダウンロードボタン押下後に、「この操作には時間がかかります」というポップアップが出るように設定されており、どうしてもPADで入力できず断念。
![め０－る.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1792185/b0a08240-d20a-93db-0979-3434b01f770b.png)

##使用したツール
Power Automate Desktop
Microsoft Edge
P2Net

##Microsoft Edge　拡張機能のインストール
PADでMicrosoft Edgeを動作させるために事前に準備が必要です。
手順は下記のサイトを参考にしました。
**Power Automateサポート**
https://support.asahi-robo.jp/tutorial/power-automate-desktop/beginner/web-recorder

##制作を終えて
PADは普段使用しているOffice365との親和性が高いため、とても使いやすく感じました。
部内で小さな業務の自動化を体験してもらい、「自分でも作れるんじゃないか？」と感じて欲しいです。
メールシステムが１本化されていればそもそも不要な業務なので、今後「自動化した方がよい業務」と「根本的にやり方を変えたほうがよい業務」を見極めていきたいと思います。
GCPのCloud ShellのPython2.7.16をPython3.7.3に移行する

##GCPでPython3が使いたい！
LINEBOTかLINE NotifyをGCPでPythonを定期で動かして作ろうとしていました。
そこでGCPのCloud Shellを使うことになりました。
###Cloud ShellのPythonのバージョン確認
Cloud ShellのPythonのバージョンを確認してみると...

```shell:cloud_shell
$ python -V

********************************************************************************
Python 2 is deprecated. Upgrade to Python 3 as soon as possible.
See https://cloud.google.com/python/docs/python2-sunset

To suppress this warning, create an empty ~/.cloudshell/no-python-warning file.
The command will automatically proceed in  seconds or on any key.
********************************************************************************
Python 2.7.16
```

おっと！Python2.7.16...

そこでPythonのバージョンをあげるためにpyenvを導入します。
###pyenvの導入
```shell:cloud_shell
$ curl https://pyenv.run | bash
$ pyenv init
$ echo 'export PATH="$HOME/.pyenv/bin:$PATH"' >> ~/.bashrc
$ echo 'eval "$(pyenv init -)"' >> ~/.bashrc
$ echo 'eval "$(pyenv virtualenv-init -)"' >> ~/.bashrc
$ pyenv install 3.7.3 #バージョンはお好きなものを
$ pyenv global 3.7.3
$ source ~/.bashrc
```
これでpyenvを無事に導入することができると思います。
また、早速pyenvを用いてPython 3.7.3をインストールできたと思います。
Pythonのバージョンを見てみましょう

##Pythonのバージョン確認
```shell:cloud_shell
$ python -V
Python 3.7.3
```
無事にGCPでPython3をインストールすることができました！
ついでにpipをpip3に変えておきましょう。

```shell:cloud_shell
$ alias pip=pip3
$ pip --version
pip 18.1 from /usr/lib/python3/dist-packages/pip (python 3.7)
```
これでだいたいの環境が整いました。
GCPでもローカルと同様にPythonの環境構築を行なっておくとスムーズに開発ができます。

基礎部分しか環境構築していないので、あとはいつも通り個人で環境構築してみてください！
特定のタグが無いAWSリソースを探したい

```powershell
$targetResource = @('ec2','rds')
$results = New-Object System.Collections.ArrayList

$targetResource | ForEach-Object {
    $resouces = aws resourcegroupstaggingapi get-resources --resource-type-filter $_
    $resouces = $resouces | ConvertFrom-Json
    $resouces.ResourceTagMappingList | ForEach-Object {
        $tagCheck = $false
        $_.Tags | ForEach-Object {
            if($_.Key -eq "CostDivision") {
                $tagCheck = $true
            }
        }
        if($tagCheck -eq $false) {
            $result = New-Object psobject | Select-Object ResourceARN , Tags
            $result.ResourceARN = $_.ResourceARN
            $result.Tags = $_.Tags
            [void]$results.Add($result)
        }
    }
}
$results
```