OmniAICreator/Qiita-1.07M huggingface dataset:
BigQuery コマンド一覧

・ログインし直す

```
　$ gcloud init
```
・現在のログイン情報を出力する

```
　$ gcloud info
```

・既存テーブルのスキーマ情報を取得する

```
bq show --project_id=プロジェクトID --schema --format=prettyjson データセット.テーブル名 > ファイル名.json
```

・テーブルを作成する

```
bq mk プロジェクト名:データセット名.テーブル名 ローカルファイルpath\テーブル名.json
```

・テーブルを更新する

```
bq update プロジェクト名:データセット名.テーブル名 ローカルファイルpath\テーブル名.json
```

・空テーブルにデータを投入する

```
bq load --project_id=プロジェクトID --allow_quoted_newlines=true --field_delimiter="," --ignore_unknown_values=TRUE --max_bad_records=0 --skip_leading_rows=1 --source_format=CSV プロジェクトID:データセットID.テーブル名 ローカルpath/実データcsv ローカルpat/テーブル.json
```

・テーブルをコピーする

```
bq cp コピー元データセット名.コピー元テーブル名 コピー先データセット名.コピー先テーブル名
```

・proxyを設定する

```
gcloud config set proxy/address アドレス
gcloud config set proxy/port 番号
gcloud config set proxy/type httpなど
```
・bq queryでSQL結果をcsvに落とす
```
bq query --nouse_legacy_sql --format=csv --max_rows=2147483647 'SELECT * FROM `test`' > /bin/source/test.csv

```

・新規スケジュールクエリ作成
```
bq query --project_id=プロジェクトID --use_legacy_sql=false --replace=true --destination_table=データセット名.テーブル名 --display_name=スケジュールクエリ名 --schedule="every day 21:00" < C:\Users\test\Desktop\sqlが保存されているテキスト.sql
```

・既存のスケジュールクエリの実行ユーザーをサービスアカウントに切り替える場合
```
bq update --transfer_config --update_credentials --service_account_name=サービスアカウント名 リソース名
※リソース名…スケジュールクエリ発行時に発番されるID
```
・パーティションの有効期限設定
https://cloud.google.com/bigquery/docs/managing-partitioned-tables?hl=ja#sql
```
bq update --time_partitioning_expiration 172800 プロジェクト名:データセット名.テーブル名
```

テーブルのスキーマ情報取得
```
bq show --schema プロジェクト:データセット.テーブルID
```
PowerShell 第6回 関数名の重複

#はじめに
前回、別ファイルのPowerShell Scriptの実行について試しましたが、そういえばスコープとか、参照元と参照先の関数名が重複したらどうなんだろうか？と思いました。
少し調べてみたのですが、ぱっと見では見つかりませんでした。
そこで、単一ファイル内で関数の重複を試してみることにしました。
試した結果、納得！となりました。

#今回実施する内容
一つのファイルに同一の関数名で関数を作成するとどうなるかを試します。

#ソースコード(Git Hub)
[PowerShell_06_SameFunctionName](https://github.com/Build-Mount/PowerShell_06_SameFunctionName)

#環境
OS: Windows 10 JP (64bit)
PowerShell version: 5.1.19041.1

#参考
[PowerShell 第5回 他のPowerShell Scriptを実行](https://qiita.com/Mount/items/14b29995b7d9571f3df2)
PowerShell Scriptから他のPowerShell Scriptを実行する方法を紹介しています。

#用語

#同一関数の動き
一つのファイルに同一関数を記載します。それを実行するとどうなるでしょうか？

##ソースコード

```PowerShell:SameFunctionName.ps1
function ShowMessage {
	[CmdletBinding()]
	param (
		[Parameter(Mandatory = $true)]
		[string]$Message
	)
    Write-Host "1番目の関数：" -NoNewline
	Write-Host $Message
}

function ShowMessage {
	[CmdletBinding()]
	param (
		[Parameter(Mandatory = $true)]
		[string]$Message
	)
    Write-Host "2番目の関数：" -NoNewline
	Write-Host $Message
}

function ShowMessage {
	[CmdletBinding()]
	param (
		[Parameter(Mandatory = $true)]
		[string]$Message
	)
    Write-Host "3番目の関数：" -NoNewline
	Write-Host $Message
}

try {
    ShowMessage("同一関数が三つあります。")
} catch {
    Write-Host $Error[0]
}
```

##動作結果

```
3番目の関数：同一関数が三つあります。
```

最後に記載した3番目の関数が実行されました。
エラーが出るのではないか？と思っていたので、動作して驚きました。
が、これが動作するということは、同じ関数を定義すると**上書き**しているってことですね。
そうか！Shellだから、コマンドを順に実行する動作なのねと。

ということでそれを確認するために、次の実験です。

#同一関数の動き2（関数と関数の間に実行文を書く）
一つのファイルに同一関数を記載します。
関数定義と関数定義の間にその関数を実行します。実行するとどうなるでしょうか？

##ソースコード

```PowerShell:SameFunctionName2.ps1
function ShowMessage {
	[CmdletBinding()]
	param (
		[Parameter(Mandatory = $true)]
		[string]$Message
	)
    Write-Host "1番目の関数：" -NoNewline
	Write-Host $Message
}

ShowMessage("同一関数が三つあります。")

function ShowMessage {
	[CmdletBinding()]
	param (
		[Parameter(Mandatory = $true)]
		[string]$Message
	)
    Write-Host "2番目の関数：" -NoNewline
	Write-Host $Message
}

ShowMessage("同一関数が三つあります。")

function ShowMessage {
	[CmdletBinding()]
	param (
		[Parameter(Mandatory = $true)]
		[string]$Message
	)
    Write-Host "3番目の関数：" -NoNewline
	Write-Host $Message
}

try {
    ShowMessage("同一関数が三つあります。")
} catch {
    Write-Host $Error[0]
}
```

##動作結果

```
1番目の関数：同一関数が三つあります。
2番目の関数：同一関数が三つあります。
3番目の関数：同一関数が三つあります。
```

思った通り、順番に実行されています。関数名は同じですが、その直前に定義されている関数が実行されています。

#おわりに
わかってしまえば納得の結果でした。
が、VB ScriptとかJava Scriptとかを多くやってきた身としては、ちょっと戸惑いました。
PowerShellの基本中の基本なんでしょうけど。

ということで、次回は、別ファイルに同一関数がある場合について記載したいと思います。
まあ、すでに答えはわかってしまいましたが、独特な記載も少しあるようなので、それらもメモしておこうと思います。
if,else問題

#21時から翌朝6時までにオウムに喋られると問題があるのでその場合は「NG」、それ以外は「OK」と出力するメソッドを作成します。オウムが喋る時をtrue、喋らない時をfalseと入力することにし、時刻も同時に入力します。


答えと解釈

```
def parrot_trouble(talking, hour)
  if talking && (hour < 6 || hour >= 21)
    puts "NG"
  else
    puts "OK"
  end
end
```


これは呼び出し方です

```
parrot_trouble(talking, hour)
```

日本語訳するとしたらこんな感じ
オウムがtalkingするのはNGです。（6時-21時の間は）
それ以外の場合はOK

&&と||の使い方
「A && B」で「AかつB」
「A || B」で「AまたはB」
【今日の学びメモ】画像は最適化する

プロジェクト内に画像を置くときは、不要な情報を削除し最適化してからアップロードする。
これは無意味にデータサイズが大きくなるのを防ぐため。

インターン先では、無料で使える **[Image Optim](https://imageoptim.com/mac)** を使った。
最適化したい画像をドラッグ & ドロップするだけなので操作が簡単だし、データサイズが約半分になったりした。

これまで画像の最適化について考えたことすらなかったのでメモ。
カート機能①カート内商品の合計金額を出す inject 税込価格の表示 / ECサイト

<h2>はじめに</h2>
カート機能を作成中です。今回はカート内商品の合計金額を出すやり方を学習しました。

<h3>前提条件</h3>
ここで登場するテーブル・モデルは、
Customer
Item
Cart_item　です。←(CustomerとItemの中間テーブルになる。）
（Cartモデルを作成している記事が多いですが、Cartモデルは作成していません。）

＊ログインしなくても商品の閲覧はできるが、カートには入れられない。


<h2>マイグレーションファイル</h2>

customer_id,item_idは外部キーで、個数はnull:falseにしています。

<details><summary>マイグレーションファイル</summary><div>


```
class CreateCartItems < ActiveRecord::Migration[5.2]
  def change
    create_table :cart_items do |t|
    

     t.integer :item_id
      t.integer :customer_id
      t.integer :quantity,null: false

      t.timestamps
    end
  end
end
```



</div></details>

<h2>モデルファイル</h2>

```
class CartItem < ApplicationRecord
    belongs_to :item
    belongs_to :customer
    
    validates :item_id, :quantity, presence: true
    validates :quantity, numericality:{ only_integer: true }
    
  def sum_of_price
    item.taxin_price * quantity
  end  
end
```

カート内しょうひんの合計金額を出すところで重要なのは、
```def sum_of_price
    item.taxin_price * quantity
  end```です。
sum_of_priceで、ある商品の税込価格❌数量が出るようにしました。

taxin_priceというのは、item.rbで定義しています。

```perl:item.rb
def taxin_price
        price*1.1
    end
```
itemのテーブルには税抜価格であるpriceというカラムを作成しており、
taxin_priceというカラムはありませんが、ここで定義することにより、item.taxin_priceで税込価格が取り出せるようになりました。
以下の記事を参考にしました。

https://teratail.com/questions/320691

https://qiita.com/komayuka/items/79752ed56e28292be4f8

<h2>最難関　コントローラー</h2>

``` perl:cart_items_controller.rb
def index
    @cart_items= current_customer.cart_items.all
    # カートに入ってる商品の合計金額
    @total = @cart_items.inject(0) { |sum, item| sum + item.sum_of_price }
  end
```
カート内商品の一覧画面で、カート内商品の合計金額を算出します。

モデルファイルの記述や、
```@total = @cart_items.inject(0) { |sum, item| sum + item.sum_of_price }```は、以下の記事を参考に記述し、実装しましたが、初心者にはコードの意味が理解できなかったので、、
読み解いていきたいと思います。

https://qiita.com/akmhmgc/items/a40b91aa4f469c397f85


<h3>コードの解読</h3>

```@total = @cart_items.inject(0) { |sum, item| sum + item.sum_of_price }```

<h5>inject(0)って何??</h5>
配列の合計を算出するらしい。
```配列オブジェクト.inject {|初期値, 要素| ブロック処理 }```が基本の形
inject(0)の(0)は、初期値は0ですよ〜ということのよう。

<h5> { |sum, item| sum + item.sum_of_price }で行ってることは？</h5>
<h6>１回目の動作</h6>
@cart_itemsから、カートに入ってる１つ目のitem取り出して、
sumにitem.sum_of_priceを足す。（sumの初期値は inject(0)で０）

<h6>2回目以降の動作</h6>
次のitem取り出して、sumにitem.sum_of_priceを足す。

これで、最終的にカート内商品の合計金額が出る！！！

<h6>injectは”注入”
sumにモデルで定義してるitem.sum_of_priceがどんどん注入されてくイメージ！</h6>

以下の記事で理解できました！

https://www.sejuku.net/blog/19219

<h2>viewファイル</h2>

```perl:cart_item.html.erb
¥<%= @total.round.to_s(:delimited)%>
```

これで合計金額出せました！！
【UiPath】設定ファイルの書き方（基本編）

# はじめに

この投稿は、RPAツール「UiPath」での 設定ファイルの書き方 について記事です。

UiPathのコミュニティ「UiPath Friends」が企画する「UiPathブログ発信チャレンジ2021サマー」の 20日目の投稿でもあります。

企画の内容は [**こちら**](https://note.com/shumpei_w/n/n651cbdbec4e8) 。カレンダーのURLは [**こちら**](http://u0u1.net/sUwZ) です。

https://twitter.com/ShumpeiWatanabe/status/1405168150736359427

# 設定ファイルと「固定」の話

「設定ファイルには何を書くべきなの？」という議論になると、良く「固定の値だ」とか「後で変更する可能性のある値だ」という意見が出ますが、個人的には「どちらも正解」だと思います。

設定ファイルには `「仕様的に設定ファイルに出しておいたほうが良い値」`を書くもので、その例として「たとえば、固定の値」や「たとえば、後で変更する可能性のある値」が登場します。

なので「固定」という言葉にとらわれないほうが良いと思います。そもそも「固定の定義って何？」「固定のレベルってどれくらいから？」「月1回変更って変動？年1回なら固定？」というように、基準は、人によって違うものです。

![tenbin.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/e92f1404-c012-0e95-d253-dc3c595e43e3.png)

# 何を書けば良いのか分からない

最初は「設定ファイルに何を書けば良いか分からない」と思います。これは実装経験を積むにつれて自動的に身につくものなので、最初は分からなくても大丈夫です。

以下で「どういうものがあるか」の種類をあげてみます。

```
＜設定ファイルに書く例＞
1）後で変える可能性があるもの（設定ファイルに出しておけば後で変えやすい）
　- 数値　　　（例：エラー時にリトライする回数）
　- 文字列　　（例：結果メールの送信先アドレス）
　- メッセージ（例：結果メールにセットする件名）
　- フラグ　　（例：結果メールを送信するか）

2）そんなに変わらないけどプログラム（xamlファイル）中に書きたくないもの
　- URL　　　（例：ログインURL） ※ 「テスト環境」と「本番環境」という意味では変わる可能性が高いもの

3）設定ファイルで並べて管理したいもの
　- 数値　　　（例：要素が見つかるまでの待機時間）
　- メッセージ（例：エラー時の固定メッセージ）

4）ルールをもたせるもの
　- ファイル名（例：yyyyMMdd.txt　処理中に「yyyymmdd」をNow.ToString("yyyyMMdd")でReplaceする）

5）ロジックのスイッチや、書くことで処理内容を伝えるもの
　- 処理方式　（暗号ハッシュ作成方式：SHA-256）
```

5はあまり遭遇しませんが「その値次第で処理内容も変えてしまうような項目」を指します。何をしているかを伝える意味合いもあり、ストラテジーパターン的な要素も持ちます。

https://qiita.com/d-tsuji/items/186af7006b44703c0379

# 設定ファイルのシートは分けるべきか

ReFrameworkの設定ファイルでは、以下のように「Settings、Constants、Assets」と分かれています。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/b8742a9b-8d30-8cfc-a750-47f0add5b5a3.png)

真似をして「シートを分ける」のも良いと思います。
1つのシートにまとめて書いて進めて、項目数が多くなったら、シート分けても良いと思います。

# どう書けばわかりやすいか

項目の名前は「わかりやすい」ほうが良いので、無理に英語にせず「日本語」が良いと思います。また、名前に「接頭辞」を付けると分類がしやすいです。（例：ファイルパス_注文書）

シートでは「種類や処理ブロック」ごとに項目を纏めると分かりやすくなります。場合によっては「セルの背景色」を分けても良いと思います。

Framework的な項目は「上部」に書いて、業務個別の項目は「下部」に書くなどの順番も意識すると更に読みやすいです。

エクセルという特性を利用すれば、意図的に「見やすい設定ファイル」が作れます。

また、ユーザーは「変えても大丈夫なもの」と「変えたら動かなくなるもの」の区別はつかないので、「この列は変更しないでください。」「このセルはYESまたはNOの値を設定して下さい」と注記を「大きく赤字で書く」のも良いかもしれません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/a344347f-1e59-686e-7ea3-a282c88cd3d3.png)



# 終わりに

いかがでしたでしょうか？
設定ファイルの書き方の、なにかの参考になれば幸いです。
次回はもうすこしTips的なことを書きたいと思います。

この記事が参考になったら、 LGTMをお願いします。閲覧ありがとうございました。
rex0220 ちょっと便利なプラグイン テーブル関連

ちょっと便利なプラグインで、テーブルをちょっと便利にする機能をご紹介。
先頭行追加など kintone の少し使いにくいところをちょっとだけ便利にするプラグインです。

# ちょっと便利なプラグインの概要

プラグインのインストールなどは、[kintone ちょっと便利なプラグイン](https://qiita.com/rex0220/items/45883f15ccd34a68b8af)
バージョン毎にだんだん機能が増えて、Ver.8 で３５機能指定できます。
単機能をバラバラに追加していったので、だいぶわかりにくくなってきました。


# ちょっと便利なプラグイン　テーブル関連機能

プラグイン設定画面で、対象機能をチェックして「保存」するだけです。簡単ですね。
kintone のテーブル関連の機能として、下記があります。
利用する機能のチェックを選択します。

- F21 テーブル行の追加・削除ボタンを左に表示
- F22 テーブル行の追加ボタンを隠す
- F23 テーブル行の削除ボタンを隠す
- F24 テーブルのヘッダ固定
- F29 詳細画面でテーブル内文字列複数行を縦スクロール表示
- F30 詳細画面でテーブル行数表示
- F31 詳細画面でテーブルフィルター
- F32 詳細画面でテーブル行番号追加
- F33 追加・編集画面でテーブル先頭行追加　※ファイル項目がないテーブル

![2021-07-20_09h19_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/0d2450c9-2598-0aa2-42fb-679d3d15ba9b.png)


# レコード編集画面の例

追加・編集画面で、便利な機能です。

- F21 テーブル行の追加・削除ボタンを左に表示
    - テーブルの左側に追加・削除ボタンが表示されています。
    - テーブルに項目が多く横に長い場合は、便利です。
- F24 テーブルのヘッダ固定
    - テーブル行数が多い場合、下にスクロールしてもヘッダ行が固定表示されます。
- F33 追加・編集画面でテーブル先頭行追加　※ファイル項目がないテーブル


![2021-07-19_22h56_53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/fdbfc907-19d6-b1db-e25a-54f4441e951a.png)

# 縦横に長いテーブルの編集操作例

テーブルのヘッダ固定で、縦横に長いテーブルの編集がやりやすくなります。

![2021-07-20_09h00_19.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/608fa880-69d4-bb91-4103-194fde5abae3.gif)

# スクロールボタン、スクロールショートカット機能
テーブル限定ではありませんが、縦横に移動するときに便利な機能です。

- F11 スクロールボタンをツールバーに表示
    - クリックすると、左右にスクロールします。
- F12 スクロールショートカット機能
    - 編集画面で入力エリアにカーソルがあると、ショートカットが機能しません。
入力エリア外をクリックしてください。

    - 左端へ [ctrl+left]
    - 左へ [ctrl+shift+left] 1ページ分左スクロール
    - 右へ [ctrl+shift+right] 1ページ分右スクロール
    - 右端へ [ctrl+right]
    - ページ先頭　[ctrl+up]
    - １ページアップ [ctrl+shift+up]
    - １ページダウン　[ctrl+shift+down]
    - ページ最終　[ctrl+down]

![2021-07-20_09h10_56.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/fa19d551-755c-c0ef-497c-5bc3fc1a115f.gif)

# テーブル行複写プラグインとの連携

ちょっと便利なプラグインは、テーブル行複写プラグインと連携できます。

![2021-07-20_09h21_11.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/67d4aa1c-a49e-70cc-dd4b-11a21870d9f9.gif)

# まとめ

テーブルに項目が多い場合に、ちょっと便利なプラグインで操作を楽にしてみましょう。
WioLTE: LED を点灯させる

WioLTE で LED を点灯させるプログラムです。
参考ページ
[LedSetRGB](https://seeedjp.github.io/Wiki/Wio_LTE_for_Arduino/Reference-ja.html#ledsetrgb)

![wiolte_aug21_2024.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/e8ba7c7d-2671-8ed2-cadd-a3d9e881a2cd.jpeg)


## プログラム

```text:led_test/led_test.ino
#include <WioLTEforArduino.h>

WioLTE Wio;

void setup() {
  delay(300);

  SerialUSB.println("");
  SerialUSB.println("--- START ---------------------------------------------------");
  
  SerialUSB.println("### I/O Initialize.");
  Wio.Init();

  SerialUSB.println("### Setup completed.");
}

void loop() {
  Wio.LedSetRGB(0, 0, 3);
  delay(1500);
    Wio.LedSetRGB(0, 3, 0);
  delay(1500);
      Wio.LedSetRGB(3, 0, 0);
  delay(1500);
      Wio.LedSetRGB(0, 0, 0);
   delay(1500); 
}
```

実行させると、
青 -> 緑 -> 赤 -> 消灯　と 1.5秒毎に変化します。

## Arduion IDE
2.3.2 を使いました。
ボードは、 Seeed Wio LTE Cat.1 です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/3617e2e0-7e50-9bc5-c64b-8a8beef24bd8.png)
HTMLで画像をRetina対応させる

# はじめに
コードを読んでいたら、html の imgタグに`srcset`という見慣れない属性があったので調べた。

# Retinaとは
RetinaとはApple社が開発したディスプレイのこと。
通常のディスプレイと比べ高画質であり、同じ画像でもぼやけて見えてしまいやすい。
そのため、しばしば Retina用の画像を別で用意する。

# srcset属性
**これまでよく使っていた imgタグ**

```
<img src="hoge.png"/>
```

**今回初めて目にした imgタグ**

```
<imt src="hoge.png" srcset="hoge.png 1x, hoge@2x.png 2x"/>
```

hoge.png と hoge@&#;2x.png を見比べたところ、大きさだけが異なる同じ画像だった。
<br>
結論から言うと、`srcset`はHTML5.1から追加された属性で、複数の画像と解像度の組み合わせを指定し、表示ディスプレイの解像度に応じて画像を使い分ける役割があるらしい。


画像の指定は、解像度が低い順に`srcset = "画像ファイル名 解像度, ..."`といったフォーマットで記述する。

Internet Explorerには対応していないため、`src="hoge.png"`の記述も残しておく必要があることに注意。

# 画像の用意
Retina用画像は通常の画像の2倍の大きさで用意し、ファイル名を`hoge@2x.png`などとすることが多い。

# おわりに
pictureタグも調べたい。

# 参考

- https://creative.eccom.jp/922/
- https://jobtech.jp/html_css/3852/
Ubuntuのunattended-upgradesが「WARNING System is on battery power, stopping」で動いて無かった

最近のUbuntuではunattended-upgradesでセキュリティ更新をanacronから自動で適用することができるように初期で設定されています。

https://help.ubuntu.com/community/AutomaticSecurityUpdates

他にも一通りの動きを調べました。

https://yomon.hatenablog.com/entry/2021/07/ubuntu_unattended_upgrade

# 事象

自身のUbuntu環境のunattended-upgradesのログを見ると以下のようなメッセージが出ていました。

```/var/log/unattended-upgrades/unattended-upgrades.log
2021-07-04 21:57:47,276 WARNING System is on battery power, stopping
2021-07-05 06:20:17,150 WARNING System is on battery power, stopping
```

もしかして動いて無いかと思い、試しに `unattended-upgrade` を直接打ってみても同じメッセージで動いて無いです。

```sh
$  sudo unattended-upgrade --dry-run --verbose
System is on battery power, stopping
```


# 原因
以下で停止しているようです。


```py
def should_stop():
    # type: () -> bool
    """
    Return True if u-u needs to stop due to signal received or due to the
    system started to run on battery.
    """
    if SIGNAL_STOP_REQUEST:
        logging.warning("SIGNAL received, stopping")
        return True
    try:
        if apt_pkg.config.find_b("Unattended-Upgrade::OnlyOnACPower", True) \
           and subprocess.call("on_ac_power") == 1:
            logging.warning("System is on battery power, stopping")
            return True
```
https://github.com/mvo5/unattended-upgrades/blob/2.6/unattended-upgrade#L675-L678

特にこの部分見てみれば良さそうです。

```py
 if apt_pkg.config.find_b("Unattended-Upgrade::OnlyOnACPower", True) \
           and subprocess.call("on_ac_power") == 1:
```


# 対応

## on_ac_power

まずは `subprocess.call("on_ac_power") == 1` から。

Manで見てみると以下の通り。

```sh
$ man on_ac_power
ON_AC_POWER(1)                                 General Commands Manual
NAME
       on_ac_power - test whether computer is running on AC power

SYNOPSIS
       on_ac_power

DESCRIPTION
       on_ac_power checks whether the system is running on abundant power (such as AC mains, an USB charger, etc), as
       opposed to battery power.

OPTIONS
       None.

EXIT STATUS
       0 (true)  System is on mains power
       1 (false) System is not on mains power
       255 (false)    Power status could not be determined
～省略～
```

実際に自身の環境で叩いてみると `1` となっています。

```sh
$ on_ac_power;echo $?
1
```

ここは変更する内容でも無いのでそのままにします。

## Unattended-Upgrade::OnlyOnACPower
次に `nattended-Upgrade::OnlyOnACPower` です。

ずっとコード繋ぎっぱなしのマシンなのですが、こちらがデフォルトでTrueとなっていました。

```/etc/apt/apt.conf.d/50unattended-upgrades
// Download and install upgrades only on AC power
// (i.e. skip or gracefully stop updates on battery)
// Unattended-Upgrade::OnlyOnACPower "true";
```

これをFalseに変えます。

```
Unattended-Upgrade::OnlyOnACPower "false";
```


# 確認
後は実際に動かして確認しておきます。

```sh
# DryRun
sudo unattended-upgrade -d dry-run

# 即時実行
sudo unattended-upgrade -d
```
【Kubernetes】podに外部からアクセスするにはService を使う　no.3

![名称未設定のデザイン (12).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/e26e5130-3300-9e6f-9a51-8c7bbf78a2f4.png)

こんにちは。まゆみです。

Kubernetesについての記事をシリーズで書いています

前回の記事で、Kubernetesを使ってdeploymentオブジェクトを作る方法を書きました。

それによって、podが作られpodのなかにあるContainerも実行されるのですが、 <font color="Red">今の段階では外部からPodにアクセスする事ができません。</font>

なぜならば、podにディフォルトで付与されるIPアドレスはinternal IP アドレスになるからです。

![2021-07-18_10-24-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/8d8ca8f0-daf6-dec0-384d-3a31509e0dfb.png)


では、Clusterの外部から、どのようにしてPodのなかのアプリケーションにアクセスしたら良いのでしょうか？

今回の記事ではその解決方法を書いていこうと思います

(ClusterにPodを作っているという前提でこの記事を書いています。前回の記事でPodを作ってダッシュボードでClusterの状態を確かめるところまでしたので、今回はその続きになります)

ではさっそくはじめていきますね。

#kubectl exposeを使う

![2021-07-20_8-31-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/1f61a119-b282-f195-0278-f4036f35638f.png)
引用元：[Kubernetesドキュメント](https://kubernetes.io/ja/docs/tutorials/kubernetes-basics/expose/expose-intro/)

ディフォルトのままでは、deploymentオブジェクトは外部からアクセスできないので

```
kubectl expose deployment <deployment名> --port=<ポート番号> --type=<タイプ>
```
とコマンドを打ち <font color="Red">Serviceオブジェクトを作ります。</font>

『expose(公開する/露出する)』という言葉の意味通り、exposeを使えば、オブジェクトを外部からアクセスできるようにします

--portオプションには、コンテナ化したアプリに開けられたポート番号を書きます。

--type=に書く<タイプ>には、次のものがあります

>--type=ClusterIP (ディフォルトのタイプであり、クラスターの内部からしかアクセスできない)
--type=NodePort
--type=LoadBalancer

今回は、上記の3つのタイプのうちClusterIPでは外部からアクセスできません。

トラフィックが増えPodが増えた時のことを考えて今回はLoadBalancerをタイプとして書こうと思います。

これでService オブジェクトができました。

Service オブジェクトを見てみましょう

```
kubectl get services
```

![2021-07-18_13-55-58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/85e3bf5a-8932-10fb-23c8-bac82f3687c5.png)

kubectl get services のコマンドで2つのオブジェクトが表示されていますが、下のkubernetesと書かれているものが、ディフォルトで自動的に作られるものになります。そしてTYPEも『ClusterIP』になっています

あなたが先ほどのプロセスで作ったserviceオブジェクト(ここでは、『first-app』という名前で表示されている)に、EXTERNAL-IPの欄がありますが、常に<pending>という状態になっていて、external-IP アドレスが使えません。

ですが、次のコマンドで、今作ったservice オブジェクトの詳細を見ることができ、その中に <font color="Red">外部からアクセスできるIPアドレスの情報が載っています</font>

```
minikube service <serviceオブジェクト名>
```

![2021-07-20_8-36-05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/3c0a4127-3ac8-ca23-82d3-f91a36682543.png)


無事にアクセスできました


![2021-07-20_8-39-26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/03bbc400-f86e-c80a-339f-135d32b3091a.png)

#まとめ

今回の記事はここで締めくくらせていただきますね。

次回の記事では、Clusterがクラッシュした時にKubernetesがどのように対応してくれるのか書いていこうと思います

よろしくお願いします　＼(^o^)／
Firebase Realtime Database からエクスポートした JSON を CSV に変換する

# 概要

Firebase Realtime Database で取得していたログを Excel で集計しようと思い、いざエクスポートしようとしたら JSON でしかエクスポートできないじゃん？ってなったので、エクスポートした JSON を CSV に変換する雑な node.js のコードをメモしておく。(改めて調べたら[既存ライブラリ](https://www.npmjs.com/package/json2csv)があったのでそちらでも良いのかもしれない)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44388/b51ecd5e-0e6e-d713-ae9d-645b1dcb55ef.png)

少ししか調べていないが、Web インタフェースだけではなく SDK や CLI 経由でもおそらく JSON しか取得できない。

# JSON -> CSV 変換コード

gist にも載せてる、無駄な処理が多いが結果はうまくいった。
https://gist.github.com/yakimelon/123cba8c227562ce141792908a4d9ecd

```JsonToCsv.js
function replace(text) {
    return text
        // 余計な文字の削除
        .replace(/(".*" : \{|\{|\}|".*" : |^      )/g, '')
        // 1つのデータの塊を1列に変換
        .replace(/",\r?\n/g, '", ')
        // 半角スペースをすべて削除
        .replace(/ /g, '')
        // 行間のカンマとその行を削除
        .replace(/"\r?\n,/g, '"')
        // 行と行の間にある3つの改行を1つに変換する
        .replace(/\r?\n\r?\n/g, '\n')
}

const fs = require('fs');
const text = fs.readFileSync("input.json", 'utf-8');
console.log(replace(text));

try {
    fs.writeFileSync("output.csv", replace(text));
    console.log("Success!");
} catch(e) {
    console.log("Failed...")
}
```

## 使い方

1. node.js の環境構築をする
1. 任意のフォルダを作る
1. 上記 js コードを `JsonToCsv.js` という名前で同じフォルダに配置
1. 変換したい json ファイルを `input.json` という名前で同じフォルダに配置
1. `node JsonToCsv.js` を実行する
1. 変換された csv ファイルが `output.csv` という名前で出力される

# まとめ

軽いコードを書こうと思ったときに node.js は意外と便利でした。
Lark Suite (無料で200GB使えてマインドマップも作成できるサービス)

## Lark Suite: 統合型コラボレーションツール

https://www.larksuite.com/ja_jp/

マインドマップの利用方法は、
ドキュメントを作成し、そこから`＋`にマウスカーソルを合わせて選択。

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/b037d89f-faae-cda8-a7b9-cfc73b0a2297.png)

フルスクリーン表示もできる。

![1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/0a20458d-96d3-86a2-4b96-c9c7568957c3.png)
BEM で CSS の要素を命名する

# はじめに
インターン先が BEM という CSS の命名規則を採用していた。
良い機会なので、ドキュメントを読んで自分なりにまとめてみる。


# BEM とは
**B**lock、**E**lement、**M**odifier の頭文字をとった、コンポーネントベースの CSS記述手法。
UI を独立したブロックに分割することで、複雑なデザインの実装やコードの再利用を容易にしている。
また、タグに直接 CSS を記述したり、`id`を与えたりすることは非推奨とされる。

# Block と Element
BEM において各要素は、大きく **Block** と **Element** の 2種類に分けられる。
名前は `classname` 属性で与えられ、`red`や`big`など特徴を説明する単語ではなく、`form`や`error`など役割を表すものでなければならない。

### Block
他要素の影響を受けない独立した要素で、それ自体を使い回すことができる。
周囲に影響を与えてはならず、`margin`や`position`は指定しない。
子要素に **Element** を持ち得る。
**Block** の名前は、属する **Element** に対して名前空間を定義する。
### Element
親要素（**Block**）がなければ使うことができない要素で、**Block** の一部。
**Element** どうしのネストも可能だが、あくまで属する先は **Block** である。
**Block** 無しで、いきなり **Element** を記述することはできない。
<br>

例えば`width: 100%;`というスタイルがあたっている場合、横幅は親要素の横幅に依存するため、この要素は **Element** となる。

どうしても **Block** 内を細かく分けたい場合は、**Service Block** と呼ばれる要素を用いるらしい。

# Modifier
上で書いた通り、**Block** と **Element** の名前は役割を表す言葉でなければならない。
これに対し、大きさや状態等を表す名前を持つのが **Modifier** である。
主に以下の 2パターンに当てはまった名前を持つ。

### 真偽値
`true`か`false`で答えられるような状態を表す単語。
`disable`や`visible`など。

### キーバリュー
ある **key** と、それに対する **value** の2単語をアンダースコアで繋いだ文字列。
`size_s`や`color_black`など。
<br>

**Modifier** を含んだクラス名を単体で使うことはできず、必ずメインの **Block** か **Element** 名と併せて定義する。

ある一つの要素に対し、色違いや状態違いなどを定義するときに使う。

```css:例
<div class="button">
    メインのボタン
</div>
<div class="button button_focused">
    フォーカス時のボタン
</div>
<div class="button button_color_red">
    メインのボタンの赤色バージョン
</div>
```

# クラス名の付け方
**Block** 名と **Element** 名の間は`__`（アンダースコア 2つ）で、**Block** / **Element** 名と **Modifier** の間は`_`（アンダースコア 1つ）で繋げる。
**Block** / **Element** / **Modifier** それぞれが 2単語以上になる場合、単語間は`-`（ハイフン 1つ）で区切る。

```css:例
<div class="list">
    <div class="list__item list__item_color-primary">
        要素1
    </div>
    <div class="list__item list__item_color-secondary">
        要素2
    </div>
</div>
```

**Modifier** の前の`_`を`--`（アンダースコア 2つ）とする場合や、**Block** 名をアッパーキャメルケースにする場合もあるっぽい。

# Mix
ある要素について、**Block** 属性と **Element** 属性を同時に与える技術。

例えば単体で使い回すことができるコンポーネントを、ある親要素の中に`margin`を指定して配置したいときなどに用いる。

```css:例
<div class="carousel">
    <div class="card carousel__card">
        カルーセル内に配置したカード
    </div>
</div>
<div class="card">
    カード単体でも使える
</div>
```

# おわりに
まだ分かりきっていない部分もあるので、理解が進んだら適宜追記する。

# 参考

- https://en.bem.info/methodology/quick-start/
- https://jobtech.jp/html_css/4209/
AWSに接続するグローバルIPを確認する

リモートでの案件となるとPACファイルの設定などで一般的なIPとAWSへ接続するときのIPが違うこともあるかと思います。
そういったときはAWSドメインに対してのグローバルIPを確認したくなります。
以下のURLでAWSに対してのグローバルIPが確認できました。
https://checkip.amazonaws.com/

curlの場合

```
curl checkip.amazonaws.com
```

以下のElasticsearchに関する設定を見ていた時にあったグローバルIP確認URLの共有でした。
参考URL
https://aws.amazon.com/jp/premiumsupport/knowledge-center/anonymous-not-authorized-elasticsearch/
【Rails】関連付けメソッドのキャッシュ制御

# はじめに

Rails には、関連先のメソッドを呼び出す時に、キャッシュを使用することで高速化する仕組みがあります。
しかし、キャッシュではなく、データーベースから直接読み込みしたい場合があると思います。
今回はそのような場合のキャッシュ制御方法についてご紹介したいと思います。

# 関連性

以下のような```Animal```モデル、```Panda```モデルの構成を作成します。

```ruby:animal.rb
class Animal < ApplicationRecord
  has_many :pandas
end
```

```ruby:panda.rb
class Panda < ApplicationRecord
  belongs_to :animal
end
```


# キャッシュ制御

```reload```メソッド を使用することで、キャッシュを破棄してくれます。

```ruby
animal = Animal.first
animal.pandas                 # データベースから pandas を取得する
animal.pandas.size            # pandas のキャッシュコピーが使われる
animal.pandas.reload.empty?   # pandas のキャッシュコピーが破棄される
                              # その後データベースから再度読み込まれる
```

# まとめ

まだまだ知らないことが多いので、引き続き勉強ですね〜

# 参考
* Railsガイド - キャッシュ制御
    * https://railsguides.jp/association_basics.html#%E3%82%AD%E3%83%A3%E3%83%83%E3%82%B7%E3%83%A5%E5%88%B6%E5%BE%A1

---
### 会社紹介

**株式会社 Mosaica**  
最先端テクノロジーで社会課題を解決し、持続可能な未来を創造する IT カンパニー。
AI ソリューション、クラウド統合、DX 推進、経営コンサルティングなど包括的なサービスでビジネス変革を支援しています。  

詳しくは [公式サイト](https://mosaica.co.jp/) までお気軽にご相談ください。
公式サイト： https://mosaica.co.jp/
package.jsonにfilesを書かないあなたは、誰かを少しだけ不幸にしています

## 先に結論だけ

`package.json`に`files`フィールドを指定すると、`node_modules`に保存されるファイルサイズが減ります。

## はじめに

この記事は、[npm](https://www.npmjs.com/)の[package.json](https://docs.npmjs.com/cli/v7/configuring-npm/package-json)に指定するフィールド、[files](https://docs.npmjs.com/cli/v7/configuring-npm/package-json#files)の指定方法と効用を解説、共有するためのものです。


### 想定する読者

この記事は、以下の読者を想定して書かれています。

+ JavaScriptの開発経験がある
+ npmを使ったことがある
+ npmやGitHubでnpmモジュールを公開している

### 想定する環境

この記事は、以下の環境を想定して書かれています。記事を読む前に、お手元の環境をご確認ください。

```shell
$ npm --version
7.15.1
```

## filesフィールドとは

[files](https://docs.npmjs.com/cli/v7/configuring-npm/package-json#files)フィールドとは、package.jsonファイル内の設定フィールドです。このフィールドはnpmパッケージがインストールされたとき、どのファイルをnode_modulesにコピーするかを設定します。

たとえば、以下のようなnpmパッケージ用のリポジトリがあるとします。

```
example-project/
  ├ src/
  │  ├ srcA.js 
  │  └ srcB.js
  ├ lib/
  │  └ bundle.js
  ├ esm/
  │  └ module.js
  ├ __test__/
  │  ├ testA.spec.js 
  │  └ testB.spec.js
  ├ package.json
  ├ LICENSE
  ├ jest.config.js
  └ README.md
```

package.jsonには、以下のように`files`フィールドが設定されています。

*▼package.json*

```json
{
  "name": "example-project",
  "files": [
    "lib",
    "esm"
  ],
}
```

このnpmパッケージをインストールします。

```shell
npm install --save-dev example-project
```


すると、node_modulesには以下のようにファイルがインストールされます。

```
node_modules/
  └ example-project/
    ├ lib/
    │  └ bundle.js
    ├ esm/
    │  └ module.js
    ├ package.json
    ├ LICENSE
    └ README.md
```

filesフィールドに指定されていないファイルは、node_modulesにはインストールされません。

## filesフィールドの挙動

filesフィールドの挙動を、[公式ドキュメント](https://docs.npmjs.com/cli/v7/configuring-npm/package-json#files)から読み解いていきます。

### ファイルの指定方法は？

filesフィールドにはstring配列を指定します。stringの中身は.gitignoreなどでおなじみのglobパターンを指定します。

### 省略するとどうなるか

filesフィールドは省略可能です。省略した場合`["*"]`として解釈されます。このパターンはすべてのファイルにマッチします。

### `.npmignore`と併用するとどうなるか

.npmignoreとfilesを併用した場合、ルートディレクトリとサブディレクトリで挙動が異なります。

+ ルートディレクトリの場合 : filesフィールドが優先されます。
+ サブディレクトリの場合 : .npmignoreが優先されます。

### 指定に関係なく無視されるファイルと、指定しても含まれるファイル

filesフィールドの設定にかかわらず、必ずパッケージに含まれるファイルと無視されるファイルがあります。詳しいリストは[公式ドキュメント](https://docs.npmjs.com/cli/v7/configuring-npm/package-json#files)を参照してください。

#### 無視されるファイル

`.git`ディレクトリや`package-lock.json`など、インストール先に影響を与えないファイルは無視されます。

#### 含まれるファイル

`package.json`や`LICENCE`など、インストール先に影響を与えたり尊重されるべきファイルはfilesフィールドの設定にかかわらずパッケージに含まれます。

## filesフィールドの効用

filesフィールドを指定することで、インストール先のnode_modulesディレクトリのファイルサイズを減らせます。

たとえば以下のようなファイルはパッケージの動作に影響を与えません。filesフィールドを設定して除外するべきです。

+ 単体テストファイル
+ バンドル / トランスパイル前のソースファイル
+ バンドル / トランスパイルのための設定ファイル(webpack.config.jsやtsconfig.json)
+ APIドキュメント
+ サンプルコード

以上、ありがとうございました。
【MySQL】「SET sql_mode = ' '」は何をしているのか


#結論
SQLモードを明示的にクリアすることで、デフォルトのSQLモード設定を利用することを指定しています。

#SQLモードとは
>サーバー SQL モードは、MySQL でサポートされる SQL 構文、および実行されるデータ妥当性チェックの種類を定義します。これにより、MySQL をさまざまな環境で使用したり、MySQL をほかのデータベースサーバーと一緒に使用したりすることが、さらに容易になります。MySQL サーバーは、これらのモードを各クライアントに個別に適用します。

参考：[5.1.7 サーバー SQL モード](https://dev.mysql.com/doc/refman/5.6/ja/sql-mode.html)

#現在のSQLモードの確認

SQLモードには複数の項目があり、個別にON/OFFを指定できます。
MySQL5.7のデフォルトのSQLモード設定では、以下に示す７つの項目がONになっています。

```sql
SELECT @@global.sql_mode;

-- 出力（以下はデフォルトの設定）
+-------------------------------------------------------------------------------------------------------------------------------------------+
| @@global.sql_mode                                                                                                                         |
+-------------------------------------------------------------------------------------------------------------------------------------------+
| ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+-------------------------------------------------------------------------------------------------------------------------------------------+
```

それぞれのモードについては[5.1.7 サーバー SQL モード](https://dev.mysql.com/doc/refman/5.6/ja/sql-mode.html)を参照のこと。

#SQLモードの設定

###1.SETコマンドで設定する

```sql
-- デフォルトの設定にする場合
SET GLOBAL sql_mode = '';

-- 特定の項目をオンにする場合
SET GLOBAL sql_mode = '<モード名>';
```

###2.my.cnfなどの設定ファイルにmodeを追記してMySQLを再起動する
```
sql-mode='<モード名>'
```
Before starting UiPath:条件分岐

## 皆もすなるQiitaといふものを、儂もしてみむとてするなり。

と言う訳で、こん＊＊は！はなっち！です。

★★★この記事はUiPathブログ発信チャレンジ2021サマー、7/20の記事です。★★★

今回は、ちょっとしたシリーズです。UiPathを使うに当たって、UiPathの機能ではなく、コンピュータ言語を使う上での基礎知識を展開していこうと思います。

#条件分岐

事務作業をしていると、ある項目がＡだったらこう処理をする、Ａでなかったら…と処理が分かれる場合があると思います。
ロボットにその処理をさせるには、「条件分岐」アクティビティを使用します。英語だったら「If」アクティビティですね。

コンピュータの世界で、条件分岐は、ある条件を満たす場合と、満たさない場合と、２分岐します。

　　　　if   ある項目がAですか？
　　　　    はい、Aです。
　　　　    いいえ、Aではありません。

　　「はい、Aです」の場合は、「条件分岐」アクティビティの「Then」の方に流れます。
　　「いいえ、Aではありません」の場合は、「Else」の方に流れます。

「ある項目がAである」は、「Condition」のところに記述します。
ただ、「ある項目がAですか？」に書いては、ロボットは理解してくれませんので、理解できる様に記述します。

　　　　項目 = "A"
　　　　項目.Equals("A")

この記述は、式の評価結果がBoolean型になるようにします。
極論、Booleanとしての値、｢True」／「False」を記述してもOKです。Boolean型の変数だけでもOKです。
例えば「条件分岐」アクティビティ以前の処理結果を「Boolean型の変数」に格納し、ロボットの処理を制御する事が出来ます。

式の評価結果がBoolean型となるような条件に、以下のようなものもあります。

　　　　数値.CompareTo(1).Equals(1) 　　　　⇒ 数値が1より大きいか？
　　　　数値.CompareTo(2).Equals(0)　　　　  ⇒  数値が2か？
　　　　配列.Contains(値)　　　　　　　　　 ⇒ 配列の要素の中に、値が含まれているか？
　　　　文字列.SubString(0,2).Equals("AB")　　⇒ 文字列の先頭1文字が"AB"であるか？

他にもいろいろあります。業務要件に合わせて、記述しましょう。

##おわりに
いかがでした？

条件分岐は、代入に次いで使用率が高いと思っています。日々の生活でも、「雨が降りそう？」はい⇒傘を持っていく、いいえ⇒傘を持っていかないなどは、条件分岐ですね。

是非UiPathでのロボ開発の一助になればと思っています。

ありがとうございました！
【R】headerなしファイルを読み込んで連結

参考ページ

https://qiita.com/dokokano_panda/items/8962650700130bd99ab7


https://qiita.com/yuba/items/d09e387a1ec191eb2738


下準備：ヘッダー用意
ヘッダー情報づくり→txt化
参考②

①対象データの仕分け
年度ごとにデータフォルダを分ける

②年度フォルダを読み込む
setwd()

③対象file名リストの読み込み

④for ループ

⑤読み込み→ヘッダー付け→必要列抽出→連結
Pythonでインストール成功後のライブラリーを読み込まなくなった場合の最も簡単な解決方法

プログラム初心者の初投稿なので、参考にしていただく場合にはその点ご了承ください。初心者が初心者に向けた内容のつもりで記述しています。
もし誤りがございましたらご指導お願いいたします。

エディター：Visual Studio Code
仮想環境：myvenv
利用したい外部ライブラリー:pytube

実はこれまでも同様な問題が発生したことが度々あったのですが、誤魔化し誤魔化し回避してきたので、今回は徹底的に調べて自分なりの解決策のセオリーを作りたいと思ってやりました。

今回、"from pytube"でエラーが生じました。
他の外部ライブラリーで試行するも、同様の結果でした。

前提確認として、pip及びpip3両方でインストールを行い、list,freeze,showなどでインストールが成功していることも確認できています。

そこでいろいろ調べたところ、原因はカレントディレクトリ―で動いている他にも複数のPythonが存在するせいではないかとの結論に至りました。

(Visual Studio以外にも、Anacondaもインストールして動かしていること、複数のディレクトリにPythonブログラムを配置していること
などで生じているという仮説で、どのディレクトリーのどのプログラムとの関係かまでは特定することはできていないので、
間違っている可能性はあります。)

そこで、カレントディレクトリ―のパイソンが読み込むパスを指定することで解決できるだろうと推測して解決方法を探しました。

解決方法:外部ライブラリーのインストールされたフォルダ(今回はmyvenvのLibフォルダ)のpathを通す。
使うもの:標準ライブラリー sys

![0a2d71140dbfbf8be76d9cab303ddd21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1113969/1c006781-686a-b319-4aa0-bf6a75433ea6.png)




(インストールしたライブラリーのpathはpip show のLocationの該当箇所をコピペするだけです,蛇足ですが"R"はraw文字列です、分からない方は別途ググってください)
調べるなかでpathを通す方法もOSの環境変数Pathに追加したりする初心者としては恐怖を感じる方法などの紹介も多かったのですが、
作りたいプログラムの中で読ませたい外部ライブラリー（場合によってはモジュール）を毎回sys.path.append()で追加するこの方法が、
直感的にも理解が容易ですし、事故の起こりにくさという点でも優れているのではないかと思いました。
2021/07/18開催 Connpassイベントランキング

# 申込数TOP5

|順位|イベント名|グループ|申込数|定員|
|:---:|:---|:---|:---:|:---:|
|:one:|[Git/GitHubを使った個人学習と使い方勉強会](https://codebase.connpass.com/event/217395/)|[CODE BASE OKINAWA](https://codebase.connpass.com/)|100|115|
|:two:|[【Git/GitHubを使った個人学習と使い方勉強会】の事前勉強会](https://codebase.connpass.com/event/219197/)|[CODE BASE OKINAWA](https://codebase.connpass.com/)|81|100|
|:three:|[第52回 CoderDojo Owari](https://coderdojoowari.connpass.com/event/209598/)|[CoderDojo Owari](https://coderdojoowari.connpass.com/)|23||
|:four:|[【aspida検証生配信】NuxtにTS製APIクライアント導入なるか！？エンジニア3名でハンズオン](https://connpass.com/event/218512/)||16|50|
|:five:|[入門 統計的因果推論  輪読会 #7](https://thinkerslab.connpass.com/event/218646/)|[思考ラボ](https://thinkerslab.connpass.com/)|15|50|
Embedded Pythonでget-pip.pyに失敗するときの対処方法

# TL;DR

軽量Python環境installでSSLErrorが出たときの対処方法です。

```
>python get-pip.py
Collecting pip
  WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1123)'))': /packages/47/ca/f0d790b6e18b3a6f3bd5e80c2ee4edbb5807286c21cdd0862ca933f751dd/pip-21.1.3-py3-none-any.whl
  WARNING: Retrying (Retry(total=3, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1123)'))': /packages/47/ca/f0d790b6e18b3a6f3bd5e80c2ee4edbb5807286c21cdd0862ca933f751dd/pip-21.1.3-py3-none-any.whl
  WARNING: Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1123)'))': /packages/47/ca/f0d790b6e18b3a6f3bd5e80c2ee4edbb5807286c21cdd0862ca933f751dd/pip-21.1.3-py3-none-any.whl
  WARNING: Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1123)'))': /packages/47/ca/f0d790b6e18b3a6f3bd5e80c2ee4edbb5807286c21cdd0862ca933f751dd/pip-21.1.3-py3-none-any.whl
  WARNING: Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1123)'))': /packages/47/ca/f0d790b6e18b3a6f3bd5e80c2ee4edbb5807286c21cdd0862ca933f751dd/pip-21.1.3-py3-none-any.whl
ERROR: Could not install packages due to an OSError: HTTPSConnectionPool(host='files.pythonhosted.org', port=443): Max retries exceeded with url: /packages/47/ca/f0d790b6e18b3a6f3bd5e80c2ee4edbb5807286c21cdd0862ca933f751dd/pip-21.1.3-py3-none-any.whl (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1123)')))
```

これが出たら、

```
python get-pip.py --trusted-host=files.pythonhosted.org --trusted-host=pypi.org
```

こうする。

pipに失敗するときも同様

```
python -m pip install xxxx --trusted-host=files.pythonhosted.org --trusted-host=pypi.org
```

# 参考記事

このサイトを参考に軽量python環境を構築していたらハマったのでシェアです。

https://qiita.com/mm_sys/items/1fd3a50a930dac3db299

解決方法はこちらから
https://www.programmersought.com/article/10851483786/
【JavaScript】オブジェクト のバリューだけ取得するメソッドを書いたら、すでにそのメソッドあった話。

オブジェクト のバリューだけ取得するメソッドを書いたら、すでにそのメソッドあった話。
相変わらず語彙力がなくてタイトルがゴミですが気にせずいきましょう
企業様の課題に取り組んでる最中に、以下のようなオブジェクト のバリューだけを取得したくなった。


```javascript

const obj =  {foo: {num: 2}, bar: {num: -1}, buz: {num: null}, qux: {}, quux: null}
```

**自分が書いたバリューだけを取得する方法**

```javascript

const newArray = Object.entries(obj)
// オブジェクトを配列にするメソッド

 // ["foo", {…}]
 // ["bar", {…}]
 // ["buz", {…}]
 // ["qux", {…}]

// 配列の配列みたいなものが返ってきた

// 格配列の一番目の要素はオブジェクトのキーだったもの

newArray.map(function(element){
  // まず一つずつ配列取り出せた
  element.shift();
  // そしてfoo,barにあたる要素を削除できた
  // shift();は一番目の要素を削除するメソッド

});
console.log(newArray)

```

考え方としては、
格配列の一番目の要素はオブジェクトのキー
なのでそれを削除するべく、
配列に各処理をする。

mapは各処理をした後に新しく配列を作り直してくれるらしい




**模範解答**


```javascript

Object.values(obj)

```

[{num: 2},{num: 4}]とバリューが配列で取得できます。


俺が頑張って考えたのに、なんと元からあるメソッド使えば１秒でできたのかい！！
悔しいけど、面白い、、、www

実装したいことをすぐコードに表すより、このメソッドないかなー？と
一旦立ち止まって調べるようにしよう。と思えたのが収穫でした。
authenticate_user! メソッドが効かない

### 行いたい事
　「出品」ボタンを押したときに、ユーザーがログインをしていなければログイン画面に飛ぶようにしたい。

```ruby:item_controller.rb
class ItemController < ApplicationController
  before_action :move_to_index, except: :index
  before_action :authenticate_user!, except: :index
    
    def index
    end
  
    def new
    end
  
    def create
    end
    
    private

end
```

上記の様に

```ruby
$ authenticate_user! 
```

メソッドをbefore_actionで書いてみたが、ログイン画面に遷移しない・・・・なぜ？？

## before_actionの順番を変える事で解決しました。

```ruby:item_controller.rb
class ItemController < ApplicationController
  before_action :authenticate_user!, except: :index
  before_action :move_to_index, except: :index
    
    def index
    end
  
    def new
    end
  
    def create
    end
    
    private

end
```

コードは上から順番に読み込まれるので、
<strong> ログインページに飛ばしてくれるメソッド　</strong> よりも
<strong> index以外のアクションをしようものなら問答無用にトップページに飛ばしてしまう </strong>　
メソッドが先に働いてしまっていた。
WPFのポインティングデバイスイベントのクセ

.NETでは標準でイマドキの入力装置のイベントを検知してくれるのだが、
少々クセがある。
将来迷わないようここにそのルールを記しておきたい。

#クセとは
ポインティングデバイスは3種類、マウス・ペン・タッチ（指）があるのだが、他のイベントも発行してしまうのだ。
例えばタッチ（指）ではTouchDownの他に、StylusDownも発行する（ﾅﾝﾃﾞﾔﾈﾝ）
しかもStylusの方が先に来るからややこしい。

#問題点
当然、今使っているのがマウスなのかペンなのか、分からなければ困る。
同じドラッグでもペンならレフトボタンの状態は関係ないとか、タッチなら指二本を制御するとか。

#解決方法
とにかくまずはイベントを拾ってみる。
動作イベントはどうでもいい。入力の瞬間さえ判別できればあとはフラグでどうとでもなる。

```XAML

        private void PreviewStylusDown(object sender, StylusDownEventArgs e)
        {
            Debug.Print("StylusDown");
        }

        private void PreviewTouchDown(object sender, TouchEventArgs e)
        {
            Debug.Print("TouchDown");
        }

        private void MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Debug.Print("MouseLeftButton");
        }

        private void PreviewTouchUp(object sender, TouchEventArgs e)
        {
            Debug.Print("TouchUp");
        }

        private void PreviewStylusUp(object sender, StylusEventArgs e)
        {
            Debug.Print("SyulsUp");
        }

        private void PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            Debug.Print("MouseLeftUp");
        }
```
こんな具合。

**マウス**
>MouseLeftButton
>MouseLeftUp

マウスのみのようだ

**ペン**
>StylusDown
>MouseLeftDown
>StylusUp
>MouseLeftUp

ペンとマウスが反応する。
・・・と思いきやぐっと押すと・・・

>StylusDown
>StylusUp

ペンだけ反応する。

**タッチ**
>StylusDown
>TouchDown
>MouseLeftButton
>SyulsUp
>TouchUp
>MouseLeftUp

全部反応する。
・・・と思いきや、グッと押さえて離すと結果が違う。
>StylusDown
>TouchDown
>SyulsUp
>TouchUp

何故かマウスイベントが発生しない（メーカーによるのだろうか？）

#発生イベントの整理
まとめるとこうなる。

| イベント/入力 |マウス | ペン | タッチ |
|:-----------|------------:|:------------:|:------------:|
| StylusDown |        | 〇         |〇
| TouchDown   |      |        |〇
| MouseLeftButton   | 〇        | △        |△

さて困ったぞ。
タッチとマウスは簡単だが、ペンをエレガントに判定する方法が無い。
強引に毎イベント判定が一番シンプルか・・・？
yup > メモ > 同値を２回入力させる場合の、入力値のチェック



メールアドレスやパスワードなど、同じ値を２回入力させたい場合


例えば、↓こういう場合

![スクリーンショット 2021-07-20 1.35.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49910/115095ae-7a47-ebcf-daa0-1df5cccfecae.png "スクリーンショット 2021-07-20 1.35.20.png")



```
validationSchema: Yup.object({
  password: Yup.string().required('Password is required'),
  passwordConfirmation: Yup.string()
     .oneOf([Yup.ref('password'), null], 'Passwords must match')
});
```
Storybook > メモ > Publicフォルダに格納したファイル等を使用する





package.jsonの storybookに ` -s ./public`を追加する



```
{
  "scripts": {
    "start-storybook": "start-storybook -p 6006"
    　↓
    "start-storybook": "start-storybook -p 6006 -s ./public"
  }
}
```



`build-storybook`も同様

```
{
  "scripts": {
    "build-storybook": "build-storybook",
    　↓
    "build-storybook": "build-storybook -s public",
  }
}
```



参考:
[Images, fonts, and assets](https://storybook.js.org/docs/react/configure/images-and-assets)
C言語でゼロから作る機械学習♯01.5【排他的論理和 ~XOR~ ｜ヘッダーファイル作成】

今回はXORの説明と今までに作成した関数を切り取り、ヘッダーファイルにするという事をやっていきます。
コードは[こちら](https://github.com/SyuSaginomiya/Machine-learning-made-from-scratch-in-C-language)
<h1>XOR｜排他的論理和</h1>
XOR、入力層1層・中間層1層・出力層1層の多重パーセプトロンとして考えることのできる排他的論理和をとても簡単に作っていきましょう。
プロトタイプ宣言を他の関数の下にして、

```C
int XOR(int p, int q);
```
関数のプログラムは～↓

```C
int XOR(int p, int q){
  return AND(OR(p,q)*W+b,NAND(p,q)*W+b);
}
```
こう！　はい、完成。
XORは中間層にORとNANDの2つのニューロンを持ち、ANDという出力層を持つ多重パーセプトロンとして考えることができます。
なので今までに制作した関数を上記コードのように組み合わせることで簡単に作ることができちゃいます！
あとは、

```c
  printf("AND \t OR \t NAND \t NOR \t XOR\n");
  printf("%d \t %d \t %d \t %d \t %d\n\n",AND(in1,in2), OR(in1,in2), NAND(in1,in2), NOR(in1,in2), XOR(in1,in2));
```
というように論理式の結果を表示する部分を上記のようなプログラムに書き換えて表示させてみましょう。
今回追加した分は「firstprogX」として新しいアプリを作っています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1720496/f5119789-e331-a9bf-4488-bbc66458856f.png)
XORが実現できました～！

<h1>ヘッダーファイルの作成</h1>
多重パーセプトロンになってくるとプログラムが大きくなってしまうので複数のプログラムに分けようと思います。
ひとまず、今回制作した論理回路の関数を切り取ってみましょう。

<h2>関数の切り取り</h2>
本来ならば、ヘッダーファイル（logic.h）とその関数を記述したサブプログラムファイル（logic.c）を作って分割コンパイルするのがいいのでしょうが、個人的にはヘッダーファイルにまとめてしまいます。
ここはそれぞれのやり方でファイルを作成してくださいね。

切り取り自体は簡単です。
今までのプログラムコードですと下に書いていた関数群を選択し、そのままCtrl＋xで切り取って
新しくlogic.hなどというファイルを作成、貼り付けて
それらのコードの上の行に

```c
#ifndef LOGIC_H   //二重インクルード防止
#define LOGIC_H

#define W 1
#define b 0
```
を記述すればヘッダーファイルは完成です。
あとはメインのプログラムから重みとバイアスの定義・プロトタイプ宣言の行を削除して、`#include "logic.h"`　で作成したヘッダーファイルをインクルードするよと記述して完了です。
今回のプログラムは「secondprog.c」としました。
コンパイルと実行の様子はこのような感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1720496/e10b850c-1e2b-2f0e-14e7-dd50071f59aa.png)

<h1>さいごに</h1>
2021年7月20日時点では簡単な説明で……
時間がありましたら、図なども使用してもっと説明を追加しようと思います。
それではまたどこかの記事で会いましょう。
AWS CodeStar とは

## 勉強前イメージ

開発するのに使うAWSのサービス？

## 調査

### AWS CodeStar とは

開発環境をすばやく構築できるサービスで、
codecommit, codebuild, codedeplpy, codepipeline をシームレスにつなげます。
クラウドベースの開発環境構築を構築でき、ブラウザで開発ができます。
また、複数人でアクセスして同時にPJをすすめることもできます。

### AWS CodeStar の特徴

- 数分で開始できる

普通であればいろいろ構築しないといけないところ、
クリックのみでアプリケーションの構築環境を作成することができます。

- 1つの場所で管理

CodeStarのプロジェクトダッシュボードから1つのアクティビティを監視でき、
全段階にわたって進行状況を確認することができます。

- セキュアに作業

CodeStarはIAMのポリシーが組み込まれており、
プロジェクトの所有者・コントリビューター・ビューワーのアクセスを管理できます。

- プロジェクトテンプレートから選択可能

さまざまなアプリケーションを簡単に開発でき、
Java、JavaScript、PHP、Ruby、C#、Python などのプログラミング言語でプロジェクトを開始できます。

### 費用

AWS CodeStar自体の追加料金はないですが、
一緒に使用するEC2やlambdaの使用料金はかかります。

## 勉強後イメージ

作ってみたけど、追加でcloud9でIDE作れるってすごい。。。

## 参考

- [AWS CodeStarの特徴や使い方について](https://www.acrovision.jp/service/aws/?p=2683)
- [AWS CodeStarとは](https://www.acrovision.jp/service/aws/?p=512)
LoLをプレイする時にAutoHotKeyが起動していたらAutoHotKeyを終了させる常駐VBS

## 概要
LoLでランク戦に挑んだら強制退出させられた事がありますか？
私は何度もあります😭
そこでLeagueClient.exeとAutoHotkey.exeが同時に起動していたらAutoHotkey.exeを終了させるVBScriptをコピペで作りました。このスクリプトに適当な名前aaa.vbsを付けてをスタートアップに入れておけばもう悲しい思いをしなくてすみますね😄

## VBScript
```vb
Option Explicit
'------------------------------------------------------------------------------
'管理者権限でこのスクリプトを実行する
'------------------------------------------------------------------------------
Dim WMI, OS, Value, Shell
do while WScript.Arguments.Count = 0 and WScript.Version >= 5.7
    '##### WScript5.7 または Vista 以上かをチェック
    Set WMI = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\.\root\cimv2")
    Set OS = WMI.ExecQuery("SELECT *FROM Win32_OperatingSystem")
    For Each Value in OS
    if left(Value.Version, 3) < 6.0 then exit do
    Next

    '##### 管理者権限で実行
    Set Shell = CreateObject("Shell.Application")
    Shell.ShellExecute "wscript.exe", """" & WScript.ScriptFullName & """ uac", "", "runas"

    WScript.Quit
loop

'-------------------------------------------------------------------------------
' プロセスの取得
'-------------------------------------------------------------------------------
Function getProcesses(processName)
    Dim service
    Set service = CreateObject("WbemScripting.SWbemLocator").ConnectServer
    Set getProcesses = service.ExecQuery("Select * From Win32_Process Where Caption='" & processName & "'")
    Set service = Nothing
End Function

'----------------------------------------------------------
' LeagueClientが起動している時にAutoHotkeyが起動していたら終了させる
'----------------------------------------------------------
Dim processesAutoHotkey, processesLeagueClient, process
Do While 1
    Set processesAutoHotkey = getProcesses("AutoHotkey.exe")
    Set processesLeagueClient = getProcesses("LeagueClient.exe")
    if 0 < processesAutoHotkey.Count and 0 < processesLeagueClient.Count then
        For Each process in processesAutoHotkey
          process.Terminate
        Next
        MsgBox("AutoHotkey.exeを停止しました")
    end if
    WScript.Sleep 10000
Loop
```
Nature Remo / Remo-Mini のデータを複数台取得する

# Nature Remo のデータを自動で取得して記録したい

Nature Remo の API (https://developer.nature.global/) を使って、データを取得する方法は複数のページで公開されているのですが
- 複数台のNature Remoを使いたい
- Nature Remo/ Remo Mini 混在の環境で動かしたい
- GASを使ってデータを集めたい
- Sheetがなかったら自動で作成してほしい
- Remoを途中で追加してもコードを変更しないようにしたい 
ということを満たすコードがなかったので、既存のコードをベースに書いてみました

```
var access_token = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'//アクセストークン
var spreadsheetId = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'//スプレッドシートID

function remo() {
  var data = getNatureRemoData();

 for( d_cnt in data ){
//   Logger.log (data[d_cnt])
  var sheetname = data[d_cnt].name
  if (SpreadsheetApp.openById(spreadsheetId).getSheetByName(sheetname) ){
      writeRemoData(sheetname,data[d_cnt]);
  }else{
      initRemoData(sheetname,data[d_cnt]);
      writeRemoData(sheetname,data[d_cnt]);
   }
 }

}

function getNatureRemoData() {　　　　　　//Remo API
  var url = "https://api.nature.global/1/devices";
  var headers = {
    "Content-Type" : "application/json;",
    'Authorization': 'Bearer ' + access_token,
  };

  var postData = {
  };

  var options = {
    "method" : "get",
    "headers" : headers,
  };

  var data = JSON.parse(UrlFetchApp.fetch(url, options));
  return data;
}

function initRemoData(sheet,data){
   SpreadsheetApp.openById(spreadsheetId).insertSheet(sheet)
  if (data.firmware_version.match(/mini/)){   //Miniなら室温だけ、Remoなら湿度と照度も書き出し
    SpreadsheetApp.openById(spreadsheetId).getSheetByName(sheet).appendRow(["時刻","取得時刻","室温"])
  }else{
    SpreadsheetApp.openById(spreadsheetId).getSheetByName(sheet).appendRow(["時刻","取得時刻","室温","湿度","照度","人感"])
  }  
}

function writeRemoData(sheet, data) {
  if (data.firmware_version.match(/mini/)){   //Miniなら室温だけ、Remoなら湿度と照度も書き出し
  var jtm = Utilities.formatDate(new Date(data.newest_events.te.created_at), 'Asia/Tokyo', 'yyyy-MM-dd HH:mm:ss');
    SpreadsheetApp.openById(spreadsheetId).getSheetByName(sheet).appendRow([new Date(), jtm,data.newest_events.te.val])
  }else{
  if (dayjs.dayjs(new Date(data.newest_events.te.created_at)).isAfter(new Date(data.newest_events.hu.created_at))){
    date1 = new Date(data.newest_events.te.created_at)
  }else{date1 = new Date(data.newest_events.hu.created_at)}
  if (dayjs.dayjs(new Date(data.newest_events.il.created_at)).isAfter(date1)){
    date1 = new Date(data.newest_events.il.created_at);
  }
  var jtm = Utilities.formatDate(date1, 'Asia/Tokyo', 'yyyy-MM-dd HH:mm:ss');
    SpreadsheetApp.openById(spreadsheetId).getSheetByName(sheet).appendRow([new Date(), jtm,data.newest_events.te.val, data.newest_events.hu.val, data.newest_events.il.val,data.newest_events.mo.val])
  }
}```

たいして特徴もないのですが、Remoに設定されている `name` をもとにしてシートを自動で作成するのと
RemoかMiniかを判定して書き込む内容を判断します
あと時刻は取得時間ではなく、Remoの取得時間をJSTに変換して記録するようにしました
プロビジョニングプロファイルまわりまとめ

## プロビジョニングプロファイル
- プロビジョニングプロファイル = 証明書 ＋ App ID ＋ 端末UDID
- Macにインストールするとアプリを端末にインストール可能
- 形式：xxxxxx.mobileprovision

## プロビジョニングプロファイル作成手順
### 証明書要求準備
1. キーチェーンアクセスから証明書署名要求（CSR）を作成
- キーチェーンアクセス → 証明書アシスタント → 認証局に証明書を要求
でCSRを作成
- 公開鍵 / 秘密鍵のペアを作成

### 証明書（Certificates）作成
1. Apple Developer Centerの「Certificates, Identifiers & Profiles」にアクセス
- Certificatesのとなりの「＋」をクリック
- 開発用の場合はiOS App Development、製品用の場合はiOS Distribution (App Store and Ad Hoc)を選択
- CSRををアップロードすることで証明書（CER）を発行
- 発行した証明書（CER）をMacにダウンロードしてダブルクリックするとキーチェーンに登録

### App ID登録
1. Apple developerの「Certificates Identifiers & Profiles」にアクセス
2. ＋をクリックしてApp IDsを選択してApp IDを登録

### UDID登録
1. 実機とMacをつなぎ、iTunesで確認。
1. 概要のiPhoneのシリアル番号のシリアル番号をクリックするとUDIDに変わる。
2.「Certificates Identifiers & Profiles」にアクセス
- 画面左から「Devices」を選択し、「＋」で新しく追加でDeviceを登録
- Device Nameは後々分かるものにし、UDIDをiTunesからコピーして登録

### プロビジョニングプロファイルの作成
1.「Certificates Identifiers & Profiles」にアクセス
2.「Profiles」 から「＋」をクリック
3. Development、Distributionの該当のものを選択
4. 該当のApp IDを選択
5. 該当のCertificateを選択
6. ダウンロードしてダブルクリックでキーチェーンに登録