OmniAICreator/Qiita-1.07M huggingface dataset:
【Rails】ストロングパラメーターの使い所について【初学者の疑問点を簡潔に解説】

## はじめに
　本記事は、プログラミングの学習を始めて1ヶ月の初学者が、学習を進めていて疑問に思った点について調べた結果を備忘録も兼ねてまとめたものです。
　そのため、記事の内容に誤りが含まれている可能性があります。ご容赦ください。
　間違いを見つけた方は、お手数ですが、ご指摘いただけますと幸いです。

## 今回の疑問点
　今回の疑問点は、

　　_ストロングパラメーターの使い方について_
　
　です。　

　ストロングパラメーターが必要なタイミングについて疑問を抱きました。
## 疑問点についての解説

###結論
　マスアサインメント機能を使用した場合にストロングパラメーターの記述が必要。特定のカラムやデータを明示してパラメーターを受け取る場合などには記述する必要はない。

###ストロングパラメーターとは
　ストロングパラメーターとは、Mass Assignment脆弱性の対策として、開発者が指定したキーを持つパラメーターのみを受け取れるように制限するものです。指定していないキーを持つパラメーターをエラーとして弾くことができます。

###パラメーターとは
　パラメーターとは、リクエストに含まれて外部から渡されるデータ、情報のことです。
 
###Mass Assignment脆弱性とは
　Mass Assignment脆弱性とは、悪意あるユーザーにより、Webブラウザ上において手作業などでパラメータを書き換えられ、開発者の意図しないデータの登録・更新（例えば、管理者を識別するためのカラム内データの改竄など）が行われてしまう脆弱性です。

###マスアサインメント機能とは
　マスアサインメント機能とは、フォームから送られてきたパラメーターをまとめて保存することができる機能です。とても便利なように見えますが、悪意あるユーザーにより、フォームから送られてきたデータの中に保存したくないパラメーター属性を含められてしまうと、そのまま保存されてしまう危険性があります。この機能が上記の脆弱性につながります。


###ストロングパラメーターの使い所
　ストロングパラメーターは上述の通り、Mass Assignment脆弱性の対策のために使用します。Mass Assignment脆弱性はマスアサインメント機能が原因で生じるものであるため、ストロングパラメーターは、マスアサインメント機能を使用したときにのみ記述し、特定のカラム等を明示する場合などには記述する必要はありません。
　具体例は以下の通りです。

```users_controller.rb
 User.create(params[:user]) 
```
　上記の場合には、送られてきたパラメーターの内、`user`に紐づくものをまとめて受け取っているため、ストロングパラメーターの定義が必要です。

```users_controller.rb
 User.create(name: params[:name], email: params[:email]）
```
 
　上記の場合には、カラムと入力データを指定しているため、ストロングパラメーターの定義は不要です。

###ストロングパラメーターの記述方法

ストロングパラメーターは以下のようにprivate以下に記述します。
※`private`以下に記述したメソッドは、そのクラスの外からのアクセスができません。クラス外部から呼び出したくないメソッドの隔離、可読性の観点から使用されます。

```users_controller.rb
private

  def user_params
  # params.require(:キー(モデル名)).permit(:カラム名１,：カラム名２,・・・).merge(カラム名: 入力データ)
    params.require(:user).permit(:name,:email).merge(user_id: current_user.id)
  end

```

上記の記述について詳解します。

　`params`：フォームから送られてきたパラメーターをハッシュ構造で格納している箱のようなもの。

　`require`：指定したキーに紐づいた`params`内の値だけを抽出する(form_withメソッドで指定したモデル名を指定）。

　`permit`：requireで抽出したキーの中から、さらに取得したいキー（特定のカラム）を指定する。

　`merge`：ハッシュ同士を結合する。paramsに含まれない値（外部キー等）をストロングパラメーターに加えたい場合などに記述。

上記の例では、
**フォームから送られてきたパラメーターの内、Userモデルの、nameカラム及びemailカラムに対するデータの受け取り、user_idカラムに対するcurrent_user.idのみ受け取りを許可する**
という内容となっています。

ストロングパラメーターを定義したら、createアクション等の中で呼び出して使用します。

## まとめ
最後にポイントをまとめます。

- ストロングパラメーターは、マスアサインメント機能により生じるMass Assignment脆弱性の対策として使用されるため、マスアサインメント機能を使用する際に記述する
- ストロングパラメーターは`pravate`以下に`params.require(:キー(モデル名)).permit(:カラム名１,：カラム名２,・・・).merge(カラム名: 入力データ)`の形で記述する
Cloudflare のリソースをPulumi で管理するための初期設定


## はじめに

Cloudflare のリソースを Pulumi で管理したくなり、さっと対応したときのメモから この記事を作成しています。

Pulumi の project は作成済みであることを前提として記載します。
まだ、 project を作成していない方は以下記事や公式ドキュメントを参考に初期設定まで完了させてください。

https://qiita.com/mziyut/items/069c21328bbeb25d5aab

## Project に設定する

今回は、 TypeScript (yarn) を利用する環境なので以下コマンドを実行します。

```bash
yarn add @pulumi/cloudflare
```

<!-- textlint-disable aws-service-name -->

Cloudflare のコンソール画面から API Token を発行し Pulumi の config に設定します

<!-- textlint-enable aws-service-name -->

```bash
pulumi config set cloudflare:apiToken --secret YOUR_TOKEN
```

API Token の発行は以下 URL から行うことが出来ます。
Pulumi で Cloudflare をどこまで操作するかに応じて適切な権限をもった Token を発行してください。

https://dash.cloudflare.com/profile/api-tokens

ここまで設定は完了です。
今まで作成してきたリソースを取り込んで検証してみます

## 作成済みのリソースを読み込む

今回は、検診のため既に作成されている Zone 情報を取得し出力します。
Cloudflare の console から Zone 名と、 Zone ID を確認してください。
※ ID は `xxxxx` 文字に置換しています

```typescript:index.ts
import * as pulumi from "@pulumi/pulumi"
import * as cloudflare from "@pulumi/cloudflare"

export const zoneMziyutCom = cloudflare.Zone.get('xxxxx', 'xxxxxxxxxxxxxxxxxx')
```

`pulumi preview` を実行し 指定した Zone 情報が取得できるか確認しましょう。
※ 情報は `xxxxx` 文字に置換しています

```bash
$ pulumi preview
Outputs:
  + zoneMziyutCom: {
      + id               : "xxxxxxxxxxxxxxxxxx"
      + jumpStart        : output<string>
      + meta             : {
          + phishing_detected : xxxxx
          + wildcard_proxiable: xxxxx
        }
      + nameServers      : [
      +     [0]: "xxxxx"
      +     [1]: "xxxxx"
        ]
      + paused           : xxxxx
      + plan             : "xxxxx"
      + status           : "xxxxx"
      + type             : "xxxxx"
      + urn              : "urn:pulumi:xxxxx::xxxxx::cloudflare:index/zone:Zone::xxxxx"
      + zone             : "xxxxx"
    }

```

## 最後に

上記設定を行うことで Pulumi を用いて Cloudflare のリソースを管理できるようになりました。
今回は読み取りだけですが、リソースの追加なども簡単に対応できます。

## Reference

https://www.pulumi.com/registry/packages/cloudflare/installation-configuration/

https://github.com/pulumi/pulumi-cloudflare
「自炊しない方が良い」エンジニアとは

## この記事を読んで分かること

あなたが**「「自炊しない方が良い」」**かもしれない事実。
怖い方は戻った方が良いかもしれません。

## はじめに

真剣にエンジニア単価とデリバリーアプリ、自炊へ費やす時間について算出してみました。
これを読めば「自炊しないの？」と聞いてくる方に、
**「ブフォッ、それ損してるけど、大丈夫そ？」**と返せるようになります。

### 定数の定義

```python:constants.py
# Uberに関すること
## UberEatsで麻婆豆腐セットを注文した時
mapo_tofu_set = 1280
## サービス利用料
service_fee = 128
## 配達手数料
delivery_fee = 150
## カウントダウン割引
countdown_discount = 150
## PayPayを使った場合の付与
awarded_when_you_use_paypay = 14
## 合計金額: 1394円
totalling　= mapo_tofu_set + service_fee + delivery_fee - (countdown_discount + awarded_when_you_use_paypay)
```

:::note info
カウントダウン割引とは15分周期で手数料が無料になる店舗が変化していく、UberEatsの割引システム。
大体この割引内で使うことが多いので、リアルを追求して採用。
:::

UberEatsを使用した際の合計金額が出ました。
料理も動きも片付けもほとんど必要としないので、この金額(`1394円`)で決定です。

```python:constants.py
# 業務に関すること
## 勤務時間: 10-19(休憩込み-1) = 8
working_hours_per_day = 8
## 勤務日数: 11月でいうと20日
working_days = 20
## 総勤務時間: 160
working_hours = working_hours_per_day * working_days
```

:::note warn
残業に注意してください。
:::

```python:constants.py
# 料理に関すること: 麻婆豆腐を作りたい
'''
材料費
麻婆豆腐: 参考文献(https://recipe.rakuten.co.jp/recipe/1430004480/)
餃子: 参考文献(https://ameblo.jp/michi8michi/entry-12502361348.html)
白ご飯: コシヒカリ5kg→2000円　1合:150g→60円
'''
## 麻婆豆腐(300)+餃子(41)+白ごはん(60) = 401円
cost_of_materials = 300 + 41 + 60
## 買い出し(25分)+料理(餃子45分+麻婆豆腐15分+ご飯炊く(炊飯機並列処理を考慮して10分))+片付け(15分) = 110分
cost_of_hour = 25 + 70 + 15
```

自炊した際の合計金額と必要とする時間が出ました。
さて、自炊にかかる合計金額がデリバリーの合計金額を上回る閾値を求めていきましょう。

### 変数の定義

```python:main.py
# 必要な情報を算出
## 月の手取りを入力
## home_pay_per_month = int(input())
```

とりあえず今は閾値を求めにいきます。

```python:main.py
## 手取り分給: home_pay_per_month / 160 / 60
home_pay_per_minute = home_pay_per_month / working_hours / 60
## 自炊した際にかかっている金額
cost_of_cooking_for_yourself = home_pay_per_minute * cost_of_hour + cost_of_materials
```

このときUberEatsを使った時のコストを左辺に持ってきて、方程式を解いてやります。

```
1394 = (home_pay_per_month/9600) * 110 + 401
(home_pay_per_month/9600) * 110 = 993
home_pay_per_month = 9600 * 9.0273
home_pay_per_month = 86662
```

:::note alert
つまり月に86,662円以上稼いでいる方にとって、
麻婆豆腐セットを自炊することは、単価計算すると生産性を下げている行動となります。
:::

ご注意ください！！！w
p5.jsの関数まとめ part.6 randomSeed()とrandom()

この記事は Qiita p5js アドベントカレンダー7日目の記事です。

## これはなに
p5.jsが用意している関数について理解を深める記事です。
今回はMath、Random系に位置するrandomSeed()とrandom()について。

## random()
乱数を返す関数です。
今後幾度となく使用していくであろう関数だと思います。
ランダム大好き。

### リファレンスより
> ランダムな浮動小数点数を返します。
0、1、2のいずれかの引数を取ります。
引数が与えられていない場合は、0から1まで（ただし1を含まない）の乱数を返します。
1つの引数が与えられ、それが数値である場合、0からその数値まで（ただし含まない）の乱数を返します。
1つの引数が与えられ、それが配列の場合、その配列からランダムな要素を返します。
2つの引数が与えられた場合、第1引数から第2引数まで（ただし含まない）の乱数を返します。
（DeepL翻訳）

いろいろとルールがありますね。
まず返るのは**浮動小数点**なので、ランダムな整数を扱いたい場合は`int()`を併用します。

また注意すべき点としては数値を指定した場合、**その数値は含まれない**こと。
昨日書いた記事、[p5.jsの関数まとめ part.5 constrain()](https://qiita.com/shibuya01055/items/fb7a83d316d522f7a08e)で

```typescript
const count = random(0, constrain(frameCount, 0, 500))
```
というコードを書きました。
差し込んだ画像をみてもらうと分かるのですが、最大が499です。
私はこれをみて「500おしい〜」とか思っていたのですがそうではありませんでした。
random()が返す数値に500は含まれていなかったのです。

### Type
数値を渡す場合のTypeはこちら

```typescript
random(min?: number, max?: number): number;
```
引数

- min はじまりの数値
- max 返る乱数の最大範囲（maxの数値は返らない）
- 0から始める場合、引数は一つで良い

そして引数に配列を渡す場合がこちら

```typescript
random(choices: any[]): any;
```
`any[]`なのか。
例えば`[1, 'hoge', 2, 'huga']`みたいなのはどうなるんでしょうか。

```typescript
function draw() {
  const ary = [1, 'hoge', 2, 'huga']
  console.log(random(ary))
}

=>
1
2
huga 
2
hoge 
1
2
2
```

うん、ちゃんと全部返してくれる。

### どんな時に使えそうか
もはや**どんな時にだって使える**のがこの関数！だと思っています。
ちゃちゃっとこんな感じのコードを書いてみました。

```typescript
function setup() {
  createCanvas(600, 600);
  frameRate(10)
  noStroke()
}

function draw() {
  background(0)
  const x = random(-200, 200)
  const y = random(-200, 200)
  
  let fillColor = x > 150 ? 'red' : 'blue'
  fill(fillColor)
  for(let val=0; val < 100; val++) {
    rect(300, 300, x, y)
  }
}

```

幅が(300, 300)の位置から200以上伸びた時だけ赤、それ以外は青色の矩形を1秒間に10種類、次々と表示します。
![画面収録-2021-12-07-1.25.49.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358229/5e0ffdb0-9c7c-cee4-13de-d2156a811389.gif)
randomを使うことによって簡単に表現の幅を持たせることができるし、使っていれば予期しない描写に出会えること間違いなしです。


## randomSeed()
上記、random()のシード値を設定するものです。

### リファレンスより
> random()のシード値を設定します。
> デフォルトでは、random()はプログラムを実行するたびに異なる結果を返します。ソフトウェアを実行するたびに同じ擬似乱数を返すには、seedパラメータを定数に設定します。（DeepL翻訳）

よくシード値ってきくけど説明できないなと思ったので調べました。
[こちらの記事](https://atmarkit.itmedia.co.jp/fdotnet/dotnettips/035random/random.html#:~:text=%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF%E3%81%A7%E4%B9%B1%E6%95%B0%E3%82%92%E7%94%9F%E6%88%90,%E3%81%BE%E3%81%A3%E3%81%9F%E3%81%8F%E5%90%8C%E3%81%98%E3%82%82%E3%81%AE%E3%81%A8%E3%81%AA%E3%82%8B%E3%80%82)より
> コンピュータで乱数を生成する場合、ある数値をシード値（seed：種）として用い、その値を基にして特定の演算により乱数を生成していく。このため同じシード値を使用した場合、発生する乱数はまったく同じものとなる。

理解しました。
ちなみに私にとって一番身近なシード値はrspecでテストを回すときのシード値です。

### Type
```typescript
randomSeed(seed: number): void;
```

引数

- seed シード値となる整数

### どんな時に使えそうか
背景などの固定したいものを描画したい時に使えそう。
random()はシード値を指定しないと毎回バラバラな乱数を生成するため、randomかつ固定したい時はシード値を設定する。
またrandom()を使用する場合は動作の検証にも使えそうです。


## 参考
[p5.js reference | constrain()](https://p5js.org/reference/#/p5/constrain)
[『Generative Design with p5.js』P_1_2_3_01](https://editor.p5js.org/generative-design/sketches/P_1_2_3_01)
【メモ】Ubuntu Server 日本語化

# 🐼はじめに
Ubuntuクリーンインストール後に日本語化するための手順メモ

# コマンド
```
# apt install language-pack-ja language-pack-ja-base ibus-mozc manpages-ja manpages-ja-dev
# localectl set-locale LANG=ja_JP.UTF-8 LANGUAGE="ja_JP:ja"
```
prometheusのストレージにNFSを使ってはいけない

タイトルが全てです

---

prometheusの構成を考えていて、ストレージをNFSにしようというのは思いつきやすく、運用面からも魅力的に感じます

AWSの場合だと、EBSはAZが固定されるし必要な容量を前もって計算する必要があります（まあ容量は追加できるけど）
が、EFSだと全AZからアクセスできるし、使ったぶんだけの課金なので必要なストレージ容量も考えなくてもよくて運用が圧倒的に楽…！（EBSに比べたら高いけど）

ので、NFSをストレージにしたprometheus環境を作りがちなんですが、これはNGです

https://prometheus.io/docs/prometheus/latest/storage/

![スクリーンショット 2021-12-07 0.54.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122084/9fdba13b-f384-c6d6-9bd9-78a9e2d917ed.png)
公式のドキュメントに思いっきり目立つように注意書きがあります

そして、何が起きるのかというと、この注意書きにも書いてある通り、 `unrecoverable corruptions may happen` です
回復不能な破損が発生する可能性があります、だそうです（自動翻訳）

私も知らずにEFSでprometheusを運用していた頃に経験しています
それまで元気に動いていたprometheusが、ある日突然死にました
再起動しても同じエラーが出続け、最終的に回復は諦めて1日1回のバックアップからリストアしてメトリクスに空白期間を作りつつ復帰させました
（最新のブロックを削除するとかでも再び動作させることは可能だったかも？）
その後調査してサポート外だということを知ったので、おとなしくEBS構成に変更しました

何かしらの発動条件があるかもしれないですが、全く不明なのでおとなしくNFSは諦めるのがよいかと思います
issueでも何度か取り上げられてますが、NFSはサポート外だからダメ、で話は終わっています
https://github.com/prometheus/prometheus/issues/7090
「DemonSlayer」を含む英語ツイートを取得し、「Flourish」でワードクラウド作成

##TwitteRでツイート取得

**英Fkourish**が提供する可視化ASPサービス[**「Flourish」**](https://flourish.studio/)に、**「Word Cloud」**のテンプレートがあることを知りました。
表形式のデータを渡すだけでなく、テキストデータをコピペすることでWord Cloudを作ることもできるそうなので、試してみました。
下記はFlourishで見られるサンプルです。
右パネルにあるテキストからWord Cloudを作っています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/a54e1c2c-ef5a-a85b-46dd-15b055973bb5.png)

ただ、日本語には対応していません。
US（米国）のツイートを取得して試してみます。
**R言語**で**「TwitterR」**を使い取得します。
キーワードは**「#DemonSlayer」**。
英語圏では**「鬼滅の刃」**をこう呼ぶそうです。

```R
##認証情報セット
sumerKey <- "**********"
consumerSecret <- "**********"
accessToken <- "**********"
accessSecret <- "**********"

##処理の準備
library("twitteR")
#httr_oauth_chcheを保存
options(httr_oauth_cache = TRUE)

#認証申請
setup_twitter_oauth(consumerKey, consumerSecret, accessToken, accessSecret)

#ツイート取得。キーワード「#DemonSlayer」。最大10000ツイート取得。英語圏で地域はUS指定
tweets2 <- searchTwitter(
'#DemonSlayer', n = 10000, since = "2021-12-05" , lang="en" , locale="us")

#データフレーム に変換
tweetsdf2 <- twListToDF(tweets2) 
tweetsdf2$text %>% head() #確認

#リツイートは扱わない
library(dplyr) #
library(stringr) #
library(magrittr) #
library(readr) #

#リツイートかどうかを確認
table(tweetsdf2$isRetweet)
FALSE  TRUE 
 1920  8080

#リツイートを外す
tweetsdf3 <- tweetsdf2 %>% filter(isRetweet %in% c("FALSE")) 
table(tweetsdf3$isRetweet)
nrow(tweetsdf3) #取得できているか確認
[1] 1920

#CSVに書き出す
write_csv(tweetsdf3$isRetweet, "tweetsdf3.csv")
```

##FlourishでWord Cloud操作

書き出したCSVからTEXT列のみコピーし、Flourishのテキストエリアにペーストします。

※ペーストする前に、キーワードに使った「#DemonSlayer」の出現回数が突出しているのでを除外（Exclude）設定しておきます（デフォルトで複数設定されています）。
※他のワードが小さくなりすぎ識別できないため。
※ペーストした後で除外キーワードに「#DemonSlayer」を設定するとワードの大きさの調節がうまくいかなかったので、先に設定しておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/209a5fc0-0e32-06f1-e3fc-7f2776b4bb9a.png)

Wordの上位200にしました（デフォルトで250）。
この他にも不要そうなワードをいくつか追加しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/14cbcbe5-dd5b-ad6d-3a83-93302edb3caf.png)

出来上がったWord Cloudです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/0fab23ae-2573-456f-a051-4d7dab3e30f9.png)

Wordの上位だけでなく中間の範囲もの設定もできたり、出現回数を確認できたりしたらいいと思ったのですが、その機能はないようです。

ブラウザの検索機能を使って、出現Wordを確認してみました。

「Akaza」を検索。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/dbbebab7-4a91-2238-bfa8-7cec47d1ff01.png)

「Tanjiro」を検索。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/8b991687-bf62-8133-7dcb-6f11a1b59603.png)

「Uzui」を検索。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/c4ca9e50-c7b5-051f-3e6f-e0d24e67a604.png)

次はRで取得する際に、もう少しフィルタリングしてからFlourishに持って行っこうと思います。

**了**
You are not authorized！って言われた話



この記事は、[UiPath Advent Calendar (produced with UiPath Friends)](https://qiita.com/advent-calendar/2021/uipath "UiPath Advent Calendar") 7日目の記事です。

##はじめに
これはUiPath Orchestratorでの話です。
Orchestratorはバージョン20.10を使用しています。

##いきさつ
実行環境はRPA専用サーバーでUnattendedで動かしOrchestratorで管理しています。
基本的にOrchestratorはRPA専任チームが管理をしていますが、
時間をトリガーにした稼働でRPA起因ではないエラーになった場合
業務担当者にリカバリ作業をしてもらいます。
そのため、業務担当者用にOrchestratorのアカウントを用意しました。
リカバリ作業、つまりジョブの実行をしてもらうだけなのでそれ用の権限設定が必要です。
というわけで業務担当者用の権限を設定して、その権限を割り当てたテストユーザでOrchestratorにログインしてみました。
####問題ないと思いきや・・？
テストユーザでログインし、ジョブを実行します。
問題なく実行できました。
実行したジョブを確認するため「ジョブ」ボタンを選択します。

####出た、なにコレ
You are not authorized！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/974805/2d53fc20-99c5-c778-d6e8-b225ea94acd2.png)

翻訳すると
「あなたには権限がありません！」ですね。
権限がないって言われても・・ジョブの画面は見えるし、ログも確認できるし・・
フォルダーに対する権限はフルでありますわよ！
#####でも、あれ、再実行できない・・？
補足：再実行とは、一度実行したジョブを同じパラメータでもう一度実行できる機能である
下の画像は正常な状態ですが、実際は「停止」のようにグレーの文字になって押せない状態でした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/974805/324f37b6-208a-247a-0283-ac9b3205749d.png)

##何の設定がダメだったのか
ユーザを登録するときに選択したロール（権限）がダメでした！
既定では下記が選択可能です。
　□ Tenant Administrator
　□ Robot
　□ Folder Administrator
　□ Automation User
　□ Allow to be Folder Administrator
　□ Allow to be Automation User
　□ Administrator 
私は「Automation User」を選択していました。
これがいけなかった。

#####選択しないといけなかったロール（権限）は・・
ユーザ登録するときに設定するロールは、テナントに対する権限なのですが、
今回の私のようないきさつの場合、選択しないといけないのは
　Allow to be Folder Administrator
　フォルダーの権限はフルで与える・・そんな時はこれを選んであげよう。

テナントの権限を「Allow to be Folder Administrator」にしたらYou are not authorized！も表示されなくなったし、再実行もできるようになりました。
めでたしめでたし。


##まとめ
You are not authorized！って言われたら権限をチェック
ユーザ登録の時に設定するロールはテナントに対する権限である
テナントに対する権限はAllow to be ～がついてるものを選択してあげる
正直な話、参考に記載した「モダンフォルダーの管理」を読んでいればきっとこんな間違いと遭遇することもなかったでしょう。
私の屍を超えてスムーズなロール設定ライフを送っていただければ幸いです。
同じような問い合わせが来たら私の事を思い出してください。

##参考
[モダン フォルダーの管理](https://docs.uipath.com/orchestrator/lang-ja/v2020.10/docs/administration-of-modern-folders "UiPathモダン フォルダーの管理") 
[既定のロール](https://docs.uipath.com/orchestrator/lang-ja/v2020.10/docs/default-roles#folder-administrator "UiPathプロダクトライフサイクル")
VeeValidateでラジオ・チェック・セレクトボックスのバリデーションをする

本年6月から、マイホムにジョインしましたkokoeです。わっしょい。
そして、こちらは[株式会社マイホム Advent Calendar 2021](https://qiita.com/advent-calendar/2021/myhm) 6日目の記事です♪（あれっ。。間があいてる）

最近、VeeValidateを使ってフォームバリデーションを実装していたのですが、
ラジオ・チェック・セレクトボックスのバリデーションにつまづいたもんで、解決した方法をメモがてら書きのこしていきたいと思います。

## 前提

以下のバージョンで確認しています。

- VeeValidate v3
- Vue.js v2

## ラジオボックス・チェックボックスの必須バリデーションができない！

`required allowFalse=false` を指定します。
https://vee-validate.logaretm.com/v3/guide/rules.html#required

```vue
<ValidationProvider
  vid="foo-checkbox"
  :rules="{ required: { allowFalse: false } }"
>
  <input type="checkbox" v-model="foo" />
</ValidationProvider>
```

## セレクトボックスの必須バリデーションができない！

必須＝デフォルト値以外、という意図で使っています。

### デフォルト値が空のケース

`skip-if-empty=false`を指定します。
https://vee-validate.logaretm.com/v3/api/validation-provider.html#props

```vue
<ValidationProvider
  vid="foo-select"
  rules="required"
  :skip-if-empty="false"
>
  <select v-model="selectValue">
    <option value="">-- 選択 --</option>
    <option value="foo">-- foo --</option>
    <option value="bar">-- bar --</option>
  </select>
</ValidationProvider>
```

### デフォルト値が空以外のケース

カスタムルールをつくりましょう。

```typescript
import { extend } from 'vee-validate';
import type { ValidationRule } from 'vee-validate/dist/types/types';

/**
 * セレクトボックス required
 * required_select:${defaultValue},${defaultValueType} を指定
 *
 * @example
 * この例では、0がデフォルト値で、0をnumber型に変換した値でvalue値と比較する
 * <ValidationProvider rules="required_select:0,number"></ValidationProvider>
 */
const required_select: ValidationRule = {
  validate(
    value: unknown,
    params: [unknown, 'string' | 'number' | 'boolean']
  ) {
    // params[0]：デフォルト値。valueがデフォルト値なら invalid
    const defaultValue = Array.isArray(params) ? params[0] : '';
    // params[1]：デフォルト値の型指定（paramsはstring[]なので）
    const dataType = Array.isArray(params) ? params[1] || 'string' : 'string';

    const formattedDefaultValue = (() => {
      switch (dataType) {
        case 'number':
          return Number(defaultValue);
        case 'boolean':
          return Boolean(defaultValue);
        default:
          return defaultValue;
      }
    })();

    return value !== formattedDefaultValue;
  },
  message: '{_field_}を選択してください'
};

extend('required_select', required_select);
```

### valueを文字列で扱う
```vue
<ValidationProvider
  v-slot="{ errors }"
  vid="foo"
  name="foo select"
  rules="required_select:none,string"
>
  <select v-model="selectValue">
    <option value="none">-- 選択 --</option>
    <option value="foo">-- foo --</option>
    <option value="bar">-- bar --</option>
  </select>
  <p>{{ errors[0] }}</p>
</ValidationProvider>
```

### valueを数値で扱う

```vue
<ValidationProvider
  v-slot="{ errors }"
  vid="foo"
  name="foo select"
  rules="required_select:0,number"
>
  <select v-model.number="selectValue">
    <option value="0">-- 選択 --</option>
    <option value="1">-- foo --</option>
    <option value="2">-- bar --</option>
  </select>
  <p>{{ errors[0] }}</p>
</ValidationProvider>
```

## おわり

使い方覚えると、かなりのバリデーションパターンに対応できてほんとに便利です。
また、次のアドベントカレンダーネタもVeeValidateでいこうかな。

ご覧いただきありがとうございました。ぺこり。
【Julia】でバーンスレイのシダを描こう

# はじめに

Juliaでバーンスレイのシダを描きたいと思います。

▼バーンスレイのシダとは

https://ja.wikipedia.org/wiki/%E3%83%90%E3%83%BC%E3%83%B3%E3%82%BA%E3%83%AA%E3%83%BC%E3%81%AE%E3%82%B7%E3%83%80

バーンスレイのシダとは、植物の形をモデル化しようと数学的に生成されるパターンです。フラクタル図形として表され、拡大しても同じ図形が現れ続ける面白い性質があります。

出力の際、「Images」「ImageView」パッケージを利用します。

# 実装

4つの関数を定義します。

```julia:
#4つの関数の定義

f1 = (x,y) -> (0., 0.16*y)
f2 = (x,y) -> (0.85*x + 0.04*y, -0.04*x + 0.85*y + 1.6)
f3 = (x,y) -> (0.2*x - 0.26*y, 0.23*x + 0.22*y + 1.6)
f4 = (x,y) -> (-0.15*x + 0.28*y, 0.26*x + 0.24*y + 0.44)
fs = [f1, f2, f3, f4]
```

上記の式を利用し、画像行列を生成します。x,y各座標を条件に従って更新していきます。

```julia:
# 計算回数
num = 50000
# Canvas size (pixels)
width, height = 300, 300
image = zeros((width, height))

x, y = 1, 1
for i in 1:num
    
    # ランダムに指定の確率に従って関数が選ばれる
    
    r = rand((1:100))
    if r<=1
        f = fs[1]
    elseif r<=86
        f = fs[2]
    elseif r<=93
        f = fs[3]
    else
        f = fs[4]
    end
        
    x, y = f(x,y)

    #配置を真ん中あたり移動
    #小数を整数に変換
    ix, iy = convert(Int,round(width / 2 + x * width / 10)), convert(Int, round(y * height / 12+1))
    # Set this point of the array to 1 to mark a point in the fern
    #白ドットを打つ、縦方向
    image[ix, iy] = 1.0
end
```

可視化します。

```julia:
# 全体図
using Images, ImageView

# 90度回転して出力
img = colorview(Gray, rotl90(image,1))
```

以下のようにシダの形が表示されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614347/f351c866-cce8-d556-302d-0de609485e83.png)
UnCSSで未使用のCSS削除を自動化する方法

<p>未使用のCSSを自動的に削除して結果を縮小するために、Node.js、Grunt、UnCSS、およびCSSminと呼ばれる別のプラグインを設定する方法を説明します。</p>

##Install Node.js<br>
Node.js Webサイトから最新のディストリビューションをダウンロードし、インストール手順に従います。
##Install Grunt<br>
Node.jsを開き、コマンドプロンプトに次のように入力します。
<pre>npm install -g grunt-cli</pre>
Gruntは自動的にダウンロードされます。
##プロジェクトフォルダを開きます<br>
Node.jsコマンドプロンプトを使用して、UnCSSでスキャンするファイルが含まれているフォルダーに移動します。 これを行うには、ファイルパスを入力します。 例えば：
<pre>cd C:TestProject</pre>
##Install UnCSS and CSSMin<br>
Node.jsコマンドプロンプトに次のように入力します。
<pre>npm install grunt-uncss grunt-contrib-cssmin --save-dev</pre>
UnCSSとCSSMinパッケージは、指定されたプロジェクトフォルダーにインストールされます。
##gruntfile.jsファイルを作成します
プロジェクトのルートディレクトリにgruntfile.jsというJavaScriptファイルを作成します。 gruntfile.jsは、UnCSSなどのプラグインの構成ファイルとして機能します。 Node.jsコマンドプロンプトに次のコードを入力します。
<pre>
module.exports = function (grunt) {
    grunt.initConfig({
        uncss: {
            dist: {
                files: [
                    { src: 'index.html', dest: 'cleancss/tidy.css' }
                ]
            }
        },
        cssmin: {
            dist: {
                files: [
                    { src: 'cleancss/tidy.css', dest: 'cleancss/tidy.css' }
                ]
            }
        }
    });

    // Load the plugins
    grunt.loadNpmTasks('grunt-uncss');
    grunt.loadNpmTasks('grunt-contrib-cssmin');

    // Default tasks
    grunt.registerTask('default', ['uncss', 'cssmin']);
};
</pre>

上記の手順では、UnCSSにindex.htmlファイルをスキャンして未使用のCSSを探し、cleancssという名前のフォルダー内にトリミングされたCSSファイルを作成するように指示しています。 次に、CSSminプラグインは、デフォルトでtidy.cssと呼ばれる新しいCSSファイルを縮小します。 最後の数行は、両方のプラグインをロードして登録するため、特に重要です。
##Grunt実行
最後に、ソースファイルフォルダに戻って、次のようにGruntを実行する必要があります。
<pre>C:TestProject>grunt</pre>

これにより、UnCSSとCSSminが動作するようになります。 すべてを正しく実行すると、指定されたフォルダーでクリーンで縮小されたCSSファイルが待機します。 一部の開発者は、この方法でCSSファイルのサイズが95％以上削減されたと主張しています。 これは、最小限の労力で多くの節約になります。 セットアッププロセスは1回だけ実行する必要があります。 将来的には、Gruntを実行するだけで、プロジェクトから未使用のCSSを自動的に取り除くことができます。
【Julia】でマンデブルロ集合を描こう


# はじめに

Juliaでマンデルブロ集合を描きたいと思います。

▼マンデルブロ集合とは

https://ja.wikipedia.org/wiki/%E3%83%9E%E3%83%B3%E3%83%87%E3%83%AB%E3%83%96%E3%83%AD%E9%9B%86%E5%90%88

マンデルブロ集合とは複素数列において、n → ∞で無限大に発散しない条件を満たす複素数の集合のことです。フラクタル図形として表され、拡大しても同じ図形が現れ続ける面白い性質があります。コンピュータや言語の性能を評価する際に扱われることもあるそうです。

出力の際、「Images」「ImageView」パッケージを利用します。

# 実装

マンデルブロ集合の関数を定義します。

```julia:
# (kx,ky)はウィンドウ座標系 (cx,cy)は複素平面上の座標
function mandelbrot(arr, width, height, xmin, ymin, xcoef, ycoef, maxIt)
	# 各ウィンドウ座標を複素座標に変換
	for ky in 1:height
		cy = ycoef*(height-ky) + ymin
		for kx in 1:width
			cx = xcoef*kx + xmin
			c = complex(cx,cy)
			z = complex(0.0, 0.0)
			flag = true
			
			count = 0
			
			# 複素平面の計算
			for i in 1:maxIt
				count = i
				z = z * z + c
				
				if abs(z) >= 2.0
					flag = false
					break
				end
			end
			
			# 発散したタイミングがcountに代入される
			if flag
				arr[:,ky, kx] .= ( 255.0, 255.0, 255.0 )　#色 juliaのImageライブラリはfloat型でRGBを記述
			else
				if count <= 1
					b_color = 0 #急速な発散は黒に、濃淡
				elseif count <= 3
					b_color = 60
				elseif count <= 5
					b_color = 150
				else
					b_color = 255
				end
				arr[:,ky, kx] .= ( 0, 0, b_color)
			end
		end
	end
end
```

可視化をします。

```julia:
#全体を見るには次の2行を活かし，下の2行をコメントアウト
xmin, xmax, ymin, ymax = -3.0, 1.0, -1.5, 1.5
WIDTH  = 800 ; HEIGHT = 600 # propotional to (x,y) range

#一部を見るには次の2行を活かし，上の2行をコメントアウト
# xmin, xmax, ymin, ymax = 0.1, 0.5, 0.4, 0.8
# WIDTH  = 800 ; HEIGHT = 800 # propotional to (x,y) range

xwidth = xmax - xmin
ywidth = ymax - ymin
maxIt = 256

x_coeff = xwidth/WIDTH
y_coeff = ywidth/HEIGHT

# JuliaのRGB表示、Float型、Indexの順番に注意
array = zeros(Float64, (3,HEIGHT, WIDTH))  # 3 => RGB array
size(array)
mandelbrot( array, WIDTH, HEIGHT, xmin, ymin, x_coeff, y_coeff, maxIt )
```

```julia:
# Juliaのパッケージ、Images ImageViewを使う
# RGBの3次元配列はFloat型でないといけない、

using Images, ImageView
img = colorview(RGB, array)
```

以下のようにマンデルブロ集合を得られました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614347/5d2f739d-5d53-b58b-0cdd-9028f8dcdcd4.png)

また、一部のみ出力してみることもできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614347/44a4f344-e8c4-a8f8-5d53-71a5cf6bc0a1.png)
【SwiftUI】非同期処理中にButtonだけを非活性にしてインジケータを出すModifier

## やりたいこと
Twitterで流れてきたこの記事を読んで
同じことを簡単にiOSのボタンで実現したい

https://qiita.com/laineus/items/0a8337586b8c8344a0c2

## できたもの
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">記事書きました！<br><br>【SwiftUI】非同期処理中にButtonだけを非活性にしてインジケータを出すModifier <a href="https://twitter.com/hashtag/Qiita?src=hash&amp;ref_src=twsrc%5Etfw">#Qiita</a> <a href="https://t.co/OOKqiMQ4eB">https://t.co/OOKqiMQ4eB</a> <a href="https://t.co/rzcXiRDOtm">pic.twitter.com/rzcXiRDOtm</a></p>&mdash; Yusuke Miyata (@yuskey38) <a href="https://twitter.com/yuskey38/status/1467880505127608322?ref_src=twsrc%5Etfw">December 6, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## 参考
https://qiita.com/kamimi01/items/370637b30a713d5bacea

## やったこと
### Modifierを作る

こんな感じで使えるようにModifierを作ります

```swift
Button()
  .modifier(...)
```

この場合`content`はこのmodifierをつけるButtonのことです


```swift 
struct Loadable: ViewModifier {
    @Binding var isLoading: Bool
    var progressColor: Color = .gray

    func body(content: Content) -> some View {
        ZStack {
            if isLoading {
                content.opacity(0.3)
                ProgressView()
                    .progressViewStyle(CircularProgressViewStyle(tint: progressColor))
            } else {
                content
            }
        }.scaledToFit()
    }
}
```

### Buttonで使う
実際の使い方はこんな感じです。

```swift
struct ContentView: View {
    @State private var isLoading: Bool = false

    var body: some View {
        Button(action: {
            isLoading.toggle()
            DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
                isLoading.toggle()
            }
        }) {
            Text("Start")
                .frame(width: 200, height: 40, alignment: .center)
                .background(.orange)
                .foregroundColor(.white)
                .cornerRadius(20)
        }
        .disabled(isLoading)
        .modifier(Loadable(isLoading: $isLoading))
    }
}
```
axiosでcookieを送る方法（フロントエンド側）

#概要
こんにちは！
今日はaxiosを用いてcookieを送る方法を説明します。
HTTPヘッダにcookieをつける形で送ります。
実際にリクエストヘッダにcookieがついているかどうかは以前に記事にしたので [【HTTPヘッダ, 検証モード】APIにリクエストをしたときのリクエスト・レスポンスヘッダを確認する。](https://qiita.com/ykkamm/items/258bac725f118826c295 "以前の記事")をみてみてください！

#手順
（例）

```typescript
const resData = axios.post(
        'http://localhost:3001/users',
        answers,
        { withCredentials: true },
      )
```

このように引数を一つ追加してあげて、```{ withCredentials: true }```とすることでcookieをHTTPヘッダにつけて送ることができます。
バックエンドも開発している場合、バックエンドのCORSの設定も変える必要があるのですが、それはまた後日記事にしようと思います。

#余談
自分はバックエンドでsession管理を行うためにcookieを送る必要がありました。
[EKS] configmap/aws-authを保護したかった

# はじめに
いい感じの対応策は出てません
もしかしたら、何かほんの少し参考になるような部分もあるかも…

# どういう話なの
EKSクラスタにアクセスできるユーザーは、awsのIAMエンティティに紐付いており

- EKSクラスタを作成したIAMエンティティ
    - k8sクラスタ内では`system:masters`でのアクセスになる
- configMap/aws-authに設定されているIAMエンティティ
    - どのIAMエンティティにk8s側でどの権限を与えるか、を設定する

のどちらかになります
クラスタを作成したIAMエンティティはひとつだけだし設定も何もないので、実質的には`configmap/aws-auth`の設定が全てになります
たったひとつの単なるconfigmapにクラスタの接続に関するほぼ全てが詰まっています

これの編集に失敗すれば、クラスタへのアクセス方法は失われます
当然削除なんて以ての外です、クラスタは即死します
nodeのクラスタへのアクセスもここで管理しているので、サービスも死にます

死ぬ確率を下げたり死んだ時の傷を浅くするために何ができるのかを考えてみようという話です

# やってしまわないために

- 今のとこ、k8sにリソースの削除保護という概念はない（確かないはず）
    - https://github.com/kubernetes/kubernetes/issues/10179
- 削除保護はできないけど、dataをimmutableにすることはできる（1.19以降）
    - https://kubernetes.io/ja/docs/concepts/configuration/configmap/#configmap-immutable
    - これをすると、権限追加処理を自動化している場合に少し面倒になるかも
- RBACでなんとか頑張る
    - aws-authを触れる権限をなるべく絞る
        - とはいっても、所詮はnamespace:kube-systemにあるconfigmapのひとつなので、あまりガチガチにすると通常の運用に影響が出てしまう
        - resourceNamesでリソース名を対象にした権限制御は可能だが、これは許可するもので、特定のリソースをeditを拒否するような用途はできなさそう

# やってしまった時のために

- クラスタを作成したIAMエンティティを記録しておく
    - aws-authがなくてもアクセスできる唯一の者
    - すでに削除済みでも、同名のIAMエンティティを作成すればそれでアクセスできるらしい
- クラスタを作成するIAMエンティティを固定する
    - クラスタを作成したIAMユーザーがわかっても、そのユーザーがすぐに対応できるとは限らない
    - IAMユーザーの使い回しはよくないので、クラスタを作成するIAMロールを決めてそれをassumeRoleする形になるか
- 現状のaws-authの管理を確認
    - パッとapplyし直せるように
    - patchやeditで運用してると今どうなってたっけ…ってなる
    - テンプレートで自動化とかしてたら意外と現状deployしてるものが手元に残らなかったり、生成するのも意外と手間取ったり

# やってしまったら

- 復帰を目指す
    - まだクラスタにアクセスできるIAMエンティティでaws-authをapply
        - クラスタを作成したIAMエンティティがわからない場合、awsに問い合わせたら時間がかかるけど特定してくれるらしい
            - cloudtrailに記録されるので保存期間内ならそっちを探す
            - こうなったら総当りするほうが早そう
- クラスタを作り直す
    - クラスタをIAMエンティティがどうしてもわからない、とかで問い合わせて回答を待ってるよりいっそ新しいクラスタを作り直したほうがサービス復帰は早そう
    - DBなどはk8sクラスタ外で運用していて、k8sで扱ってるのはステートレスなコンピューティングのみ、という場合は比較的早く復帰できそう
        - terraformなどを使っていれば尚更
    - DBなどもクラスタで管理してるステートフルなクラスタだと大変そう
    - （一般的な事故・障害対応として、クラスタ作り直しは手順整えて通しで確認するくらいやっておいてもよさそう）

# ちなみに
EKSのapiでなんとかできるようになる未来があるようです
https://github.com/aws/containers-roadmap/issues/185

# ふと思ったけど
これ、このconfigmapに限らずclusterroleとかも消したら死ぬんじゃないかと思いました
k8s難しいですね
データ分析を始めるために取った資格3つ

## データ分析をやることになったときの話

私は開発ディレクターの仕事をしているのですが、
新卒で入った会社でDMP（データマネジメントプラットフォーム）の開発プロジェクトに携わることになったのを機に、

* CRMデータ分析
* 広告レポートの分析（ビジュアライズ）
* 広告のログ分析

といったデータ分析をやることになりました。
当時の状況としては、

* 学歴的には文系（数学苦手）
* 統計は学生のとき単位落として以来苦手意識あり
* AIってなんかすごいやつでしょ

くらいの感じで全くデータ分析が分かっていなかったのですが、
社内で教えてくれる人もおらず、各種の勉強会もレベルが高すぎる感じがして、
まずは資格を取るところから始めたのでそのときのことを書いていこうと思います。

## 統計検定

統計には前述の通り苦手意識があったのですが、
当時の上司に勧められて受験することにしました。

https://www.toukei-kentei.jp/

筆記試験は年2回ですが、CBT方式（2級・3級のみ）でも受験できます。

私は2級を取ったのですが、基礎的な統計リテラシーという意味では3級で十分だと思います。
データの扱いの基礎や様々なグラフの使い分けなど、基本がバランスよく出題されるイメージです。

私は後々機械学習を使ったプロダクトに携わることになったので、
その点では2級の範囲の学習がかなり役立ちました。

統計になじみのない方が勉強を始めるときの入門書としてはこれが圧倒的おすすめ。

https://www.amazon.co.jp/%E3%83%9E%E3%83%B3%E3%82%AC%E3%81%A7%E3%82%8F%E3%81%8B%E3%82%8B%E7%B5%B1%E8%A8%88%E5%AD%A6-%E9%AB%98%E6%A9%8B-%E4%BF%A1/dp/4274065707

## データベーススペシャリスト

みんな大好き情報処理技術者試験。

https://www.jitec.ipa.go.jp/1_11seido/db.html

データベーススペシャリストは高度区分ですが、論文がないので負担は少なめだと思います（※腕の負担）。
既に応用情報技術者試験に合格していたので受けてみたというところが大きいです。

試験内容としてはデータベース設計の比重が大きいので、
既に整備されているデータを分析して可視化する業務であれば得るところが少ないかもしれませんが、
実業務では元データがぐちゃぐちゃなことも多いので、あるべきデータベースの姿を学ぶという意味では勉強になりました。

私の場合だとSQLは書ける状態だったので、知識の面では復習の意味合いが強かったです。
RDBの構造について理解しており、SQLが多少書けるようであれば試験は受けなくてもいいかもしれません。
高度情報は知名度が高いので自信にはなります。

合格体験記を昨年書いたのでよろしければどうぞ。
https://qiita.com/hiroeis/items/bf0a0ac644fc576ebd69

## 個人情報保護士

いわゆる情報系の試験ではないですが、個人情報保護士も受験しました。

https://www.joho-gakushu.or.jp/piip/

~~当時「メールアドレスをハッシュ化したものは個人情報にあたるか」という話で揉めて腹が立ったので取りました。~~

個人情報保護法とマイナンバー法の理解を問われる試験です。
純粋に法律の設問ももちろんありますが、
例えば「メールアドレスよりも病歴の方が厳重に管理されるべき」など、
データの取扱いについて勉強になる内容が多く、以後のデータの管理にも活かせました。

セキュリティ分野はいわゆる情報セキュリティだけでなく、
部屋の入退室管理など物理的なセキュリティも含まれるのでその点は新鮮で勉強になりました。
座席表を壁に掲示しておいてはいけないよとか。

実は2016年に取得してからしばらく放置していたのですが、
今年（2021年）更新手続きを取りました。
更新時研修の資料がかなり充実していて、短時間で知識をアップデートでき非常に良かったです。

個人情報保護法はちょこちょこ改正されるので、継続的にキャッチアップが必要な方には良い資格かなと思います。

## 資格を取ってよかったこと

資格試験の参考書は学習内容がコンパクトに分かりやすくまとまっているので勉強しやすかったです。
データ分析の分野だと学生時代にしっかり学んだ人にかなわないという話になりがちですが、
これらの資格の勉強を経て専門家とある程度話せるリテラシーはつけられたかなと思います。

あと、個人的にはコツコツ勉強するのが苦手なので、試験の締切効果で勉強が捗ってよかったです。

データ分析に挑戦してみたい方、次に取る資格を検討されている方の参考になれば幸いです。
android studioを使って歩数計を作って詰まった部分と余談

#参考ページ
https://qiita.com/FlatMountain/items/cec2013bf095261277c9

以上のサイト以外にもいろいろなサイトを参考にしました。そのうえで私が詰まった部分をまとめます。

#つまりポイント
##1つめ
Android10から？パーミッションの取得が必要のようです。

```java 
requestPermissions(new String[]{Manifest.permission.ACTIVITY_RECOGNITION}, 1);
```
これがわからずに1時間くらいはまりましたｗ
##2つめ
端末によってはバックグラウンドでのServiceが制限されるようです。
私のxiomi製端末を場合
【アプリアイコン長押し】→【アプリ情報】→【バッテリーセーバー】→ 「バッテリーセーバー(推奨)」→「制御しない」へ設定変更
で正常にバックグラウンドで動作するようになりました。中華制スマホは特にバックグラウンドでの動作が厳しくなっているので注意が必要です。
##そのほかの部分
Service内で歩数をカウントするがそれをリアルタイムでActivityに表示する方法としてApplicationクラスを使った。具体的にはinterfaceでリスナーを作りカウントするたびに呼び出すという方法。

```java
public interface StepListener {
    void onStep();
}
public class MyApplication extends Application {
    private int step;
    private long totalStep=0;
    private StepListener stepListener;
    public void setStep(int step){
        this.step=step;
        if (stepListener!=null) stepListener.onStep();
    }

    public long getTotalStep() {
        return totalStep;
    }
    public void setTotalStep(long totalStep) {
        this.totalStep = totalStep;
    }

    public int getStep(){
        return step;
    }
    public void setStepListener(StepListener stepListener){
        this.stepListener=stepListener;
    }
}
```

//Service側

```java
public class PedometerService extends Service {
    private int mCounter=0;
    private long totalStep=0;
    MyApplication testApplication;
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        testApplication=(MyApplication) getApplication();
        testApplication.setStep(mCounter);
        testApplication.setTotalStep(totalStep);

        SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR);
        sensorManager.registerListener(new SensorEventListener() {
            @Override
            public void onSensorChanged(SensorEvent event) {
                testApplication.setStep(mCounter++);
                testApplication.setTotalStep(totalStep++);
            }
            @Override
            public void onAccuracyChanged(Sensor sensor, int accuracy) {}
        }, sensor, SensorManager.SENSOR_DELAY_UI);
        return START_NOT_STICKY;
    }
}
```
あとは表示したいActivityでStepListenerを実装した。
問題がある箇所もあるだろうが一応全体としてはこのような感じで実装した。
歩数を保存するタイミングについては500歩歩いたら保存するようにした。これはonDestroyが呼び出されずにServiceが終了してしまうことがあるためだ。もう一つは日付が変わるタイミングにalramをセットして値を保存する方式にした。
#まとめ
はじめてqiitaで記事を書いたのでいろいろとつたない部分がありますが読んでくださりありがとうございました。
#宣伝
歩数計も搭載した脳トレです。暇があれば遊んでみてください。

https://play.google.com/store/apps/details?id=com.nisinis.brainbreak
Atcoder 解答例 ABC 093 C - Same Integers

#ABC 093 C - Same Integers 解答例
問題は[こちら](https://atcoder.jp/contests/abc093/tasks/arc094_a)

解答例が見当たらなかったため、備忘録がてら投稿します。
何かアドバイスがあれば気軽にコメントください。


```C++
#include <iostream>
#include <string>
#include <cmath>
#include <algorithm>

using namespace std;


int main() {
	int ABC[3];

	int X;
	int M = 0;
	int sum = 0;

	for (int i = 0; i < 3; i++) {
		cin >> ABC[i];

		if (M <= ABC[i]) M = ABC[i];
		
		sum += ABC[i];
	}

	while (1) {
		if (3*M % 2 == sum%2) break;
		else M++;
	}

	cout << (3*M - sum) / 2 << endl;

	return 0;
}
```
AWSアカウントも年末の大掃除をしよう

本記事は[AWS Advent Calendar 2021](https://qiita.com/advent-calendar/2021/aws)のカレンダー2の13日目の記事です。

今年も残すところあと僅かとなりました。
年末といえば大掃除ですが、部屋の大掃除だけでなくAWSアカウントの大掃除もしてみてはいかがでしょうか。
不要なリソースを削除することで、コスト削減はもちろん、すっきりした気持ちで新年を迎えたいですね。
本記事では、私が大掃除中に遭遇したエラーと対処法をTipsを交えながら紹介します。

# 削除対象
複数のCloudFormationスタックを持ったあるサービスです。
残念ながらサービス終了となったため、削除することになりました。

# 削除方法
デプロイ時と逆順でCloudFormationスタックを削除しました。
CloudFormationで定義していると、削除も楽ですね。

# 遭遇したエラーと対処法
### The bucket you tried to delete is not empty. You must delete all versions in the bucket.

空でないS3バケットを含むスタックを削除した時に発生するエラーです。
S3バケットを空にしてからスタックを削除しましょう。

**Tips**: サイズが大きいS3バケットは空にするのに時間がかかるので、ライフサイクルルールを設定して空にするのがおすすめです。バージョニングを設定している場合は、2つのライフサイクルルールの設定が必要となります。詳しくは[こちら](https://aws.amazon.com/jp/premiumsupport/knowledge-center/s3-empty-bucket-lifecycle-rule/
)をご確認ください。


### Resource handler returned message: "Lambda was unable to delete xxx because it is a replicated function. Please see our documentation for Deleting Lambda@Edge Functions and Replicas.

CloudFrontの削除直後にLambda@Edgeを削除した時に発生するエラーです。
CloudFrontに紐づけられていたLambda@Edgeのレプリカが削除されるのを待つ必要があります。
レプリカは通常、数時間以内に削除されます。詳しくは[こちら](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-edge-delete-replicas.html)をご確認ください。
CloudFrontを削除して少し時間をおいてから再度Lambda@Edgeの削除を試みましょう。

### role (arn:aws:iam:xxx) is invalid or cannot be assumed

IAMロールを誤って削除してしまった時に発生するエラーです。削除する順番を誤った場合に発生します。
同じ名前と権限を持つのロールを作成してから再度削除しましょう。

### The specified hosted zone contains non-required resource record sets and so cannot be deleted.

ホストゾーンにデフォルト以外のレコードが存在すると発生するエラーです。
デフォルトのNSレコードとSOAレコード以外を削除してからホストゾーンを削除しましょう。

# CloudFormationスタック削除後の注意点
CloudFormationスタックを削除しただけでは消えないリソースがあるため、注意が必要です。
私の場合は下記をAWS Console上で削除する必要がありました。
CloudFormationスタックを削除後に、利用していたサービスを一通り確認するのがよさそうです。

- CloudWatchSyntheticsのLambda関数
- CloudWatchSyntheticsのCloudWatchLogGroup
- Lambdaレイヤー [^1]
- AWS Chatbotのワークスペース

# 最後に
AWSアカウントの大掃除をすることで、すっきりとした気持ちで新年を迎えられそうです。
ぜひ皆さんもやってみてはいかがでしょうか。
なお、お掃除の際は、使用中のリソースを削除しないように[スタックの削除保護](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-protect-stacks.html)などを活用ください。
最後までお読みいただきありがとうございました。

[^1]: Lambdaレイヤーの削除は全レイヤーバージョンを削除する必要があるため、手動で実施するのは大変です。私は下記スクリプトを使いました。よろしければお使いください。

    ```python
    import boto3
    import sys

    # 第1引数にLayer名、第2引数に最新のバージョン番号を指定して実行

    args = sys.argv
    layer_name=args[1]
    latest_version=int(args[2])

    client = boto3.client('lambda')

    for version_number in range(latest_version, 0, -1):
        response = client.delete_layer_version(
            LayerName=layer_name,
            VersionNumber=version_number
        )
    ```
kintone エラー発生プラグイン

Advent Calendar ネタ用に作ったエラー発生プラグインをご紹介
イベント実行ログとエラーを発生させるだけという機能です。

# エラー発生プラグイン概要

複数プラグインの動作を確認するため、エラー発生1プラグイン、エラー発生2プラグインと二つあります。
機能は、まったく同じものです。
プラグインは、インストール順が新しいものから順番に実行されます。

![2021-12-04_20h02_07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/ab3cf3a3-a1e4-aa1d-8e2d-d146743e3f04.png)


# プラグイン設定画面

イベント処理時のリターン情報の扱いとエラー発生のオプション指定があります。
オプションは、一つだけ有効にできます。
ちょっと便利なプラグインを流用したので、設定画面もほとんど一緒。

- F01: return; // event 情報無しでリターン
- F02: return null; // nullでリターン
- F03: return false; // falseでリターン
- F04: return "XXXX"; // "XXXX" でリターン
- F05: return undefined; // undefined でリターン
- F06:  // return なし
- F07: 未定義変数エラー
- F08: 未定義変数エラーハンドリング

![2021-12-08_23h22_38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/5ffbf2e8-bee0-27f1-bffa-49a75085d6ff.png)
![2021-12-08_23h22_54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/417386d0-6c2e-4264-a3ef-e3a2fc70dcab.png)


# エラー発生ログ

レコード編集画面の実行ログです。
エラー発生1プラグインが、編集画面表示イベント内でエラーになり、後続のエラー発生2プラグインのイベント処理が実行されていません。
こんな感じで、プラグイン設定でプラグインの動作をログで確認できます。

![2021-12-07_00h06_07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/2458d545-65b2-e8da-249b-53780cc3a64f.png)


# エラー発生処理概要

指定されたプラグイン設定によって、イベント処理の終了方法を変えるだけです。

```エラー発生処理-抜粋.js
    "use strict";
    console.log('plugin1 start:');
...
    // 詳細画面、編集、追加画面
    kintone.events.on(["app.record.index.show","app.record.detail.show","app.record.edit.show","app.record.create.show"], function(event) {
        console.log('plugin1 event:', event);
        if (tinyInfosById.F01.state) {
            console.log('plugin1 event: 無しでリターン');
            return; // event 無しでリターン
        }
        if (tinyInfosById.F02.state) {
            console.log('plugin1 event: nullでリターン');
            return null; // nullでリターン
        }
        if (tinyInfosById.F03.state) {
            console.log('plugin1 event: falseでリターン');
            return null; // falseでリターン
        }
        if (tinyInfosById.F04.state) {
            console.log('plugin1 event: "XXXX" でリターン');
            return "XXXX"; // "XXXX"でリターン
        }
        if (tinyInfosById.F05.state) {
            console.log('plugin1 event: undefined でリターン');
            return undefined; // undefinedでリターン
        }
        if (tinyInfosById.F07.state) {
            xxxx; // 未定義変数エラー
        }
        if (tinyInfosById.F08.state) {
            try {
                xxxx; // 未定義変数エラーハンドリング
            }
            catch(err) {
                console.log('plugin1 error:', err);
            }
        }
        if (tinyInfosById.F06.state) {
            console.log('plugin1 event: return なし');
        }
        else {
            return event;
        }
    });
```
scope

###scopeとは
Railsのスコープ機能を利用するためのメソッド。
スコープ機能というのは、クエリを定義することができる機能で、何度も同じクエリを使うような場合に、メンテナンス性を上げることができる。

**◆出来ること**
・並べ替えや絞り込みを行う
・クエリを定義して使い回す

>**クエリとは？**
　データベースに対する命令文。
　find_by、where、order、limit、distinctなど

###scopeの基本構文

```
class モデル名 < ApplicationRecord
  scope :スコープの名前, -> { 条件式 }
end

定義したスコープは以下のように呼び出す事が出来る
モデル名.スコープ名

例：
class Blog < ApplicationRecord
    scope :published, -> { where(published: true) }
end

Blog.published
```

###参考記事
[【Rails入門説明書】scopeについて解説](https://web-camp.io/magazine/archives/17679)
[【Rails】 モデルのスコープ機能(scope)の使い方を１から理解する](https://pikawaka.com/rails/scope)
[クエリメソッドをまとめてみた[Rails]](https://qiita.com/takuyanin/items/ed2641dcb5fad35f9067)
PythonからLocalStackのS3へ繋ぐ際のendpoint_urlの設定


たくさんはまったので備忘録。

LocalStackへ接続するにあたりAWSアクセスキー、AWSシークレットキーの代わりにエンドポイントURLを設定する必要があるが、
`s3fs`を利用していると（内部的には`boto3`を利用しているらしい）
`endpoint_url`の引数の設定の仕方が意地悪（公式ドキュメント化されていないらしい。

https://stackoverflow.com/questions/49215833/s3fs-custom-endpoint-url

>There is an undocumented parameter in the current verison client_kwargs={'endpoint_url': 'https:...'} which is the desired one.
  

また、`docker-compose`ではコンテナ名がドメインのエイリアスに使えるのだが
こちらの記事

https://qiita.com/okashoi/items/1ddf3724ad5c166e417b

を参考にさせていただいて、
エイリアス名を固定で`.env`ファイルに外出ししようとしたのだが
作成されるコンテナ名には`_n`のsuffixがつき、
`_`が使われているとエンドポイントURLのValidationエラーに引っかかって
`ValueError: Invalid endpoint:`のエラーを返す（涙）

ケバブケース（`-`）に置き換えて`docker-compose.yml`ファイル内で
`container_name`を設定してあげることで解決

※なお、コンテナ間での通信が不要であれば上記記事のやり方が適切かと思います

```Python:hoge.py
import os
import boto3
import s3fs

endpoint_url=os.getenv("S3_ENDPOINT", None)

boto3.resource('s3', endpoint_url=endpoint_url)
s3fs.S3FileSystem(client_kwargs=dict(endpoint_url=endpoint_url))
```

```docker-compose.yml
version: "3.7"

services:
  python:
    environment:
      S3_ENDPOINT: "http://aws-container:4572"
      AWS_ACCESS_KEY_ID: "dummy"
      AWS_SECRET_ACCESS_KEY: "dummy"
    tty: true
    container_name: python-container
    depends_on:
      - aws

  aws:
    image: localstack/localstack:0.11.5
    environment:
      SERVICES: "s3"
      AWS_ACCESS_KEY_ID: "dummy"
      AWS_SECRET_ACCESS_KEY: "dummy"
    ports:
      - "4566:4566"
      - "4572:4572"
    container_name: aws-container
```
Notionのシンプルテーブルで列の幅を変更する

アルプ株式会社でエンジニアをしています、集約のエンティティ@pictinyです。
これは[Notion Advent Calendar 2021](https://qiita.com/advent-calendar/2021/notion) 6日目のエントリです。
5日目は[Notionを使ってTwitter予約投稿に近いものを作ってみた](https://qiita.com/inaho3517/items/2c2a277d497c52364d27)でした。

# シンプルテーブルの列の幅
シンプルテーブルの列の幅を変更したいことがあります。

列の罫線にマウスオーバーするとポインタが `↔` に変化し、罫線が強調されます。
そのまま罫線をドラッグすると幅を変更できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427952/d79ac18d-9a11-1204-9f77-f6b576b2016b.png)

なお、列の幅は変更できますが行の幅は変更できません。

# まとめ
ExcelやGoogle Spreadsheetではヘッダーの罫線をダブルクリックすると幅が自動調節されますが、シンプルテーブルでは残念ながら実装されていません。ドラッグでいい感じに調整しましょう。
Google AnalyticsのAPIでリアルタイムの閲覧者数が分かるノードを公開してみました。 #noderedjp


こんばんわ、この記事は[Node-REDアドベントカレンダー](https://qiita.com/advent-calendar/2021/node-red)6日目の記事です。

Google AnalyticsのAPIを使うノードが無かったので作ってみました。

https://flows.nodered.org/node/node-red-contrib-google-analytics

## Webサイトなどの現在の閲覧者数がリアルタイムで分かります。

他のAPIなども触れたら良かったのですが、とりあえずアルファ版ということでリアルタイムの数字だけ取ってみました。

ちなみに、GA4のリアルタイムは過去30分間のユーザーという値になります。

例えば僕のQiitaの実際のアナリティクス画面で見ると13人が見ているらしいです。

> ![](https://i.gyazo.com/a07d64b9a1364cbb051ece55fb7cebf8.png)

これをこのノードを使うことでこんな感じで取得できます。

> ![](https://i.gyazo.com/4fbe966f93012c4a8f02c1085c388d59.png)

使い方はnpmのページなどをご覧ください。

https://www.npmjs.com/package/node-red-contrib-google-analytics

※クレデンシャル情報を環境変数に入れるあたりのロジックがあるので、enebularなどのクラウド環境だとまだちゃんと使えないかもしれないです。

## Webサイトの閲覧者数に応じてデバイス制御とか

やれそうですよね。

数年前にまだGA4出てたか出てないかのときにこの辺のAPI探ったけど実装力無くて断念した記憶があります。

**個人的にここだけの機能が欲しかった** ので一旦満足...笑

取り急ぎ、Webサイトの閲覧者数に応じたインタラクションとかに使えたらと思ってますが、他の用途でも使える気がするのでこんなのに使いたい！みたいな話があればぜひコメント下さい :) 


## 過去にもこんなノード作ってます。

去年もアドベントカレンダーでGmailのノードを作ってみてました。

https://flows.nodered.org/node/node-red-contrib-gmail-fetch

https://qiita.com/n0bisuke/items/a884c33fd578db4e05e4

アドベントカレンダーごとに何か自作ノード作ってみる流れ良いかもしれません。

明日は@miraimeisatuさんの「2021衆議院選挙を分析した話」らしいです！楽しみですね！

それでは！良いお年を！
php artisan config:cacheを叩いてハマった


.envの設定が反映されなかったのでキャッシュを消そうとした際に、
`php artisan config:cache`を叩いてエラーにハマりました。

本来叩きたかったコマンドは、

```
php artisan cache:clear
```

になります。これで全てのアプリケーションキャッシュが削除されます。

今回勘違いして叩いたのは

```
php artisan config:cache
```
configの読み込みを早くするためのキャッシュを作成するコマンドで
実行すると`bootstrap/cache/config.php`配下に`config.php`が生成されます。
`config.php`にはconfig配下の各ファイルから読み込まれたキャッシュが配列で作られます。

このコマンドを実行するとキャッシュを一度クリアにして、
再度キャッシュするという動作を行い、もう.envファイルを読み込まなくなるという罠があります。

ただ、config:cacheを使うことによって設定ファイルをまとめることができるのでアプリをスピードアップできるメリットがあります。そうなってもいいように.envファイルの値をそのまま使うのではなく
configファイルとenvファイルに分けて

```
// configファイル
`api_key` => env('API_KEY')
// envファイル
API_KEY=hogefugapiyo....
```
というように使うことを推奨されているようです。
こうすれば.envが読み込まれなくてもconfigファイルから情報が取れるんですね。

公式もこのように言っています↓
>開発期間中にconfig:cacheコマンドを実行する場合は、設定ファイルの中で必ずenv関数だけを使用してください。設定ファイルがキャッシュされると、.envファイルはロードされなくなり、env関数の呼び出しはすべてnullを返します。
https://readouble.com/laravel/8.x/ja/helpers.html?header=env()

cache:clearとconfig:cacheの違いを明確に分かっていないとハマります。ご安全に！
bitcoinjsで英語以外のニーモニックコードを出力する

# はじめに

https://qiita.com/shu-kob/items/4b0dadf2415fb08b9fa7

↑の続き

今回はbitcoinjsのbip39で英語以外のニーモニックを出力してみましょう。

# 前回の復習

```getMnemonic.js
const bip39 = require('bip39');

function getMnemonic() {
    const mnemonic = bip39.generateMnemonic(256);
    return mnemonic;
}

const mnemonic = getMnemonic();

console.log(mnemonic);
```

前回のコードを実行すると、英語でニーモニックコードが出力されましたね。

```
genre awkward fix input supreme much social regular liar employ pattern trumpet review sketch dose jar lava ask plunge rubber twenty space weekend elevator
```

※記事に載っているニーモニックは絶対に使わないでくださいね。

# 英語以外で出力

英語以外で出力しようと思ったら簡単です。

```getMnemonic.js
bip39.setDefaultWordlist('japanese');
```

この一行を足すだけです。

```getMnemonic.js
const bip39 = require('bip39');

function getMnemonic() {
    bip39.setDefaultWordlist('japanese');
    const mnemonic = bip39.generateMnemonic();
    return mnemonic;
}

const mnemonic = getMnemonic(256);

console.log(mnemonic);
```

```
おばさん　たあい　おさない　さびしい　てんすう　うきわ　つめたい　つるみく　あめりか　かんち　ひねる　ちさい　きせい　すあし　せっさたくま　どあい　にきび　しいん　せんげん　よてい　かいしゃ　ずひょう　うけとる　ごがつ
```

中国語簡体字だとこう。

```getMnemonic.js
bip39.setDefaultWordlist('chinese_simplified');
```

```
米 伐 粒 柱 践 尸 册 金 党 杨 梅 撞 晶 熔 吗 贡 沉 偷 实 玻 组 粮 刑 耕
```

韓国語だとこう。

```getMnemonic.js
bip39.setDefaultWordlist('korean');
```

```
사계절 잘못 감각 햇볕 시청 올가을 오징어 자율 진찰 나란히 실습 영국 벌레 이민 법률 녹차 복도 창고 지극히 전철 음성 침묵 행사 저렇게
```

フランス語だとこう。

```getMnemonic.js
bip39.setDefaultWordlist('french');
```

```
crémeux flatteur buvable déranger trivial baril équerre frère toxine remise lundi anguleux maillon cigogne suffixe cynique quiétude digital toboggan haricot fiasco adhésif colère gambader
```

bitcoinjsのbip39では、jsonで各言語の単語を全て保持しています。
https://github.com/bitcoinjs/bip39/tree/master/src/wordlists

- 中国語簡体字
- 中国語繁体字
- チェコ語
- 英語
- フランス語
- イタリア語
- 日本語
- 韓国語
- ポルトガル語
- スペイン語

に対応しています。

日本人であれば英語と日本語しか使わないですが、いろんな言語で遊んでみましょう！
クローンしたスプライトを特定する

Scratchでは一つのスプライトからクローンを使っていくつもの複製を作ることができます。しかし、クローンされたスプライトを特定するための機能が用意されていません。そこで、クローンを作るたびに通し番号を打つことで、クローンしたスプライトを特定できるようにすると便利です。

まず二つの変数を用意します。
一つはクローンに割り当てる通し番号を保存するもの。これは「このスプライトのみ」という設定を行います。今回は「番号」という名前の変数を作成しました。
もう一つは、今までクローンした中で最大の通し番号を保存するもの。これは「すべてのスプライト用」という設定を行います。今回は「最大番号」という名前の変数を作成しました。

<img width=30%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75307/e315dad1-0822-b5a9-08d1-f56727c9e1ee.png">

次にクローンを作るときに、通し番号を設定します。そして最大の通し番号を一つ増やします。

<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75307/bdf8ff20-e18a-3b78-4252-1ddb13403db2.png">

ここまで準備できると、クローンの通し番号を「番号」変数の値として手に入れることができます。

<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75307/7e5170f0-dde9-ad25-f2b4-80ec58e66e23.png">

サンプルプロジェクト
https://scratch.mit.edu/projects/593323890

![スクリーンショット](https://cdn2.scratch.mit.edu/get_image/project/593323890_480x320.png)