OmniAICreator/Qiita-1.07M huggingface dataset:
Minecraftのgametestで、アイテム右クリックでForm表示したい。

# 導入
　貴方はMinecraftというゲームをご存じでしょうか。まぁあの神ゲーを知らないという方、そうそういないと思います。
　さて、この記事では、特定のアイテムを持った状態で右クリックしたこと(アイテム使用したこと)を検知する方法と、そこからFormを表示する方法を記していきたいと思います。

# 特定のアイテムを持って右クリックしたことを検知する
　なにかしらアイテムを持った状態で右クリックしたことは、world.events.beforeItemUseを使うことによって検知できます。beforeItemUseという部分からわかる通り、アイテム使用から右クリックを検知しているので、PEの場合は画面長押しによってイベントが発生します。使用したアイテムの種類は、beforeItemUseEvent Classのitemから、typeIdやnameTag,dataを用いて条件分岐することで調べます。

```js
import { world } from "@minecraft/server";


//リンゴを持った状態で右クリックするとキルされる
world.events.beforeItemUse.subscribe((ev)=>{
    if(ev.item.typeId != "minecraft:apple") return;

    ev.source.kill();
});
```

# 右クリックしたプレイヤーにformを表示する
　上記のサンプルコードの通り、右クリックしたプレイヤーはsourceで取得することができます。form.show()の実引数にsourceを指定すれば、右クリックしたプレイヤーにformを表示させることが可能です。
```js
import { world } from "@minecraft/server";
import { ActionFormData } form "@minecraft/server-ui";

const form = new ActionFormData().title("a").body("b").button("c");
world.events.beforeItemUse((ev)=>{
    form.show(ev.source);
});
```
注意すべきなのは、sourceで取得したインスタンスがEntity型だということです。そのため、Player.tell()など、Player型なら使えるいくつかのメゾットが使用できません。もしPlayer型でしか実装されていないメゾットを使いたい場合、Entity型からPlayer型に変換する必要があります。しかし、Javascriptではオブジェクト型のキャストはできないため、変換する機構を自分で実装する必要があります。
具体的には、world.getPlayers()で得たプレイヤー一覧から、sourceと同一人物を探します。
```js
function entityToPlayer(source){
    for(let player of world.getPlayers({"nameTag":source.nameTag})){
        return player;
    }
}
```

# 最後に
　この記事を書こうと思ったとき、一番書きたかったのは「form.show()の実引数がEnittyだと表示されないから、アイテム使用検知からのform表示の際には、sourceの型に注意してね。」ということだったのですが、記事の内容が正しいかどうかを調べるために検証していたら、アップデートだかなんだかでEntity型のままでも正しく表示されるようになっていたため、情報の鮮度は大事だなと改めて思った次第です。アンテナしっかり張らないとですね。
ランダムにページ遷移する

# もちろんもっとよい方法があるはず　

　ランダムにページの表示内容を変えたい。ゴールとしては、データベースから一組の検索結果を得て、それをページ内に埋め込んでいく、みたいなことを考えているのだけれど、ちょっと停滞。　
　でも、クリスマスに向けて、とりあえず「なんとか動く」に持ち込みたい。ということで、データベースも検索もなしに、見た目「似た挙動」にする、というのが、今回のお題だ。ゴミ箱行きになる可能性大なプランBだけれど、セーフティーネットとして。

## ランダムな画像を表示する。
　一番簡単なのは、「こんなふうにデータを埋め込んだページ」というできあがりを何種類も作って、スクショして、画像として用意する。そしてそれをランダム表示する。codeは同じ女子部メンバーのこちらを拝借。

https://zenn.dev/minn/articles/6f568e76e8b150
```
    String _imgURL;
    List<String> imgURLs = [
      //表示したい画像のURL
    ];
    final ram = Random(DateTime.now().millisecondsSinceEpoch);//乱数の種を時間ごとに変更するためのDataTime
    _imgURL = imgURLs[ram.nextInt(imgURLs.length)];
```
```
      body: Center(
        child: Image.asset(_imgURL),
            ),
```

　よしよし、ちゃんと動く。
　でも問題は、まずPageを作って、全体をビルドして、そのPageに到達したところでスクショを取る、それを何回も繰り返して必要なだけ画像を用意するという、超アナログな作業。いくらプランBでも、ちょっと悲しい。

## ランダムにページ遷移する。

　Pageのフォーマットはできている。引数をデータベースから引っぱってこれればそれでいい。でも、まだ引っぱってこれない。スクショを取るために何度も引数を手入力していて、思った。スクショを取るんじゃなく、作ったページに飛べれば、一手間減るじゃないか。
　一番安易な発想は、StringをFunctionに変えてページ遷移をListに並べるという方法だったのだが、これはここに入れられないとか、引数がなんとかかんとかとか、私はに対処できそうにないエラー相手に右往左往。そもそもListの中になにを設定していいのかもよくわかってない初心者の手を出すことじゃないのかもしれない。　
　そうこうするうちに、エラーメッセージに、widgetという言葉が何度も出ているのに気づいた。もしかして、Listの中にWidget入れるというのはアリなのか。だったらこれでどう？　

```
  @override
  Widget build(BuildContext context) {

    Widget _nextURL;
    List<Widget> nextURLs = [
      //ここに表示したいPageを指定
      Center(child: PageA()),
      Center(child: PageB()),
      Center(child: PageC()),
    ];
    final ram = Random(DateTime.now().millisecondsSinceEpoch);
    _nextURL = nextURLs[ram.nextInt(nextURLs.length)];

    return Scaffold(
      body: _nextURL,
    );
  }
```

　できた〜。ListにCenterが並んでるのがもっさりした雰囲気だけど、ともかく望んでいることはできたわ、ほっほっほ。

## Listの入れ子ができたら・・・　
　いっそ、引数一覧というListをListの中に並べられたら、何Pageも用意して遷移するのじゃなく、そのPageの変更一つで済む、というわけだけど、今回はそこまで狙わない。いや、できるかな、やってみようかな・・・どうしよう・・・

## いずれにせよ、これはあくまでプランB、ゴミ箱行きになったら、それはそれでよし。

　でも、どなたか、関数のListやListの入れ子についてご教示くださったら、泣いて喜びます(ﾟﾟ)(｡｡)ﾍﾟｺｯ
【雑記】Qiitaでのアウトプットで得られるもの

Qiita Advent Calendar企画応援の一環で、参画出来そうなカレンダーを見つけたので良い機会と思い、Qiitaでのアウトプットというアプローチについて、自分の考えをさっぱりとまとめて見ようと思いました。

## 軽く自己紹介
30代未経験から都内自社開発でWEBエンジニア3年目。
フロントエンドバックエンド問わず、フルスタックになんでも出来るマンを目指し、
来年2月より新天地で頑張る予定。

## 本題
さて私が考える **「Qiitaでのアウトプットで得られるもの」** ですが、
結論は以下の3つです。

 1 . 自身の学習における理解と記憶への定着
 2 . 記事の需要やトレンド
 3 . いいねやストックによるContribution

一つずつ掘り下げていきます。

### 1 . 自身の学習における理解と記憶への定着
何よりもこれが1番アウトプットをする原動力かなと思っています。
学習の中で、概念を掴んだり、大枠での理解が出来たなあと思い込んでいても、
実際じゃあ人に説明して理解させることが出来るレベルかと言われると微妙なことは良くあります。

これは一般的な話かもしれませんが、学びを得る為の効率的なアプローチとして、アウトプットは非常に有効と考えています。記事にして、同じ課題にぶち当たった人に説明するように書くことで、理解と記憶への定着を図ります。なので、他にも似たような記事が既に世に存在していたとしても、そこは気にせずアウトプットすれば良いと思っています。

そもそも、アウトプットがQiitaである理由ですが、自分の場合は学習の中心が技術的な内容が多い為、それに特化したプラットホームである方が、「見られやすい」のが理由です。沢山見られた方が良いフィードバックも得られやすいですからね。

###  2 . 記事の需要やトレンド
いいねやストックの多くつく記事にはより価値があると考えられます。もし、それがある課題についての一つの解法だとすれば、その問題自体が多くの人がぶち当たる問題かもしれないし、記事自体のクォリティーが高く、多くの人から共感を得る内容だったのかもしれません。

自分なりに投稿後の結果を振り返り、分析することで、より良いアウトプットをする為の研究材料となります。勿論アウトプットする事自体が目的でもあるのですが、せっかく投稿するなら、クォリティーは高めていきたいですよね。


###  3 . いいねやストックによるContribution
[QiitaのContributionの計算方法](https://help.qiita.com/ja/articles/qiita-contribution)によると、記事を投稿するだけでもContribution出来ていると言えるのですが、やはり、いいねやストックして貰えるのは嬉しいもので、投稿のモチベーションになります。Youtuberじゃないですが、いつか[盾を貰えるよう](https://help.qiita.com/ja/articles/qiita-award)精進しています。

また（これは私の体感ですが）比較的Qiitaでは読者からのフィードバックも得られやすく、間違っている内容にはどんどんツッコんで貰えるので、それも学びになりますし、質問板で困っている初心者を見つけたら助けてあげるのも良いアウトプットですし、Contributionになるかと思います。

## まとめ

私はこれらをQiitaでのアウトプットで日々得ることで、エンジニアとしてこれからもマイペースに成長していきたいと思っています。Qiitaを利用する人の置かれている環境や立場、モチベーション、そもそも目的は人それぞれですが、成長を一つの目的として掲げている人は是非一緒に投稿頑張っていきましょう〜。
Leetcode 451. Sort Characters By Frequency

# 451. Sort Characters By Frequency

https://leetcode.com/problems/sort-characters-by-frequency/

## 難易度
### Medium

## アプローチ
### Hashmap

```java
class Solution {
    public String frequencySort(String s) {
        HashMap<Character, Integer> hashMap = new HashMap<>();

        for (char c : s.toCharArray()) {
            hashMap.put(c, hashMap.getOrDefault(c, 0) + 1);
        }

        return hashMap.entrySet().stream()
                .sorted(Map.Entry.comparingByValue((o1, o2) -> -o1.compareTo(o2)))
                .map(entry -> String.valueOf(entry.getKey()).repeat(entry.getValue()))
                .map(String::valueOf)
                .collect(Collectors.joining());

/*
        return hashMap.entrySet().stream()
                .sorted((o1, o2) -> o2.getValue() - o1.getValue())
                .map(obj -> String.valueOf(obj.getKey()).repeat(obj.getValue()))
                .map(String::valueOf)
                .collect(Collectors.joining());
*/
    }
}
```

- こちらの[回答](https://leetcode.com/problems/sort-characters-by-frequency/discuss/1534433/Java-11-simple-lambda-approach)を参照しました
Salesforce CMS

[まとめページに戻る](https://qiita.com/Keiji_otsubo/items/60afc2a8d211b6f7d89f)
[まとめN～Z](https://qiita.com/Keiji_otsubo/items/92f92bb9f668ca9688be)


+ [Salesforce CMSでの「表」の表現について](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000LIAZM)

英語ですが、Wordpressと連携している例を解説してくれています。

確かにデザイン面では自由度はあがりそうな気がします。

[CMS Connect for WordPress](https://meighanrockssf.com/2018/01/25/cms-connect-for-wordpress/)
Dockerイメージ・コンテナ・ネットワークをフィルターして削除する方法

## 環境

Docker version 20.10.17, build 100c701

## コンテナ

### 特定イメージを用いるコンテナ一覧

```shell
docker ps -a -f="ancestor=${TARGET_IMAGE}"
```

rust:1-alpine3.16の場合

```shell
docker ps -a -f="ancestor=rust:1-alpine3.16
```

### 特定イメージを用いるコンテナ一覧を削除

```shell
docker ps -a -f="ancestor=${TARGET_IMAGE}" | awk 'NR>1{print $1}' | xargs docker rm
```

rust:1-alpine3.16の場合

```shell
docker ps -a -f="ancestor=rust:1-alpine3.16" | awk 'NR>1{print $1}' | xargs docker rm
```

## イメージ

### 一覧

```shell
docker images
```

### 指定のイメージ名

```shell
docker images ${TARGET_IMAGE_NAME}
```

タグを指定せずとも使える。

```shell
$ docker images mcr.microsoft.com/openjdk/jdk
REPOSITORY                      TAG         IMAGE ID       CREATED       SIZE
mcr.microsoft.com/openjdk/jdk   17-ubuntu   7e7e1637f85a   2 weeks ago   413MB
mcr.microsoft.com/openjdk/jdk   11-ubuntu   4c64ada6086f   2 weeks ago   398MB
# 完全一致の必要がある。Tabキーで補完が効く。
$ docker images jdk
REPOSITORY   TAG       IMAGE ID   CREATED   SIZE
```

### レポジトリが\<none\>を表示

```shell
$ docker images | awk 'NR>1{ if($1 == "<none>") {print $0} }'
<none>                                          <none>         7c837e1dd39d   11 days ago     1.32GB
<none>                                          <none>         5449976ef777   11 days ago     1.27GB
<none>                                          <none>         17710c13d665   11 days ago     1.32GB         
```

### レポジトリが\<none\>を削除

```shell
docker images | awk 'NR>1{ if($1 == "<none>") {print $3} }' | xargs docker rmi
```

## ネットワーク

### 一覧

```shell
docker networks ls
# 又は
docker network list
```

### 指定のものを表示

```shell
# 名前。部分検索をしてくれる。
$ docker network ls -f="name=none"
NETWORK ID     NAME      DRIVER    SCOPE
d6399d0e8f30   none      null      local
# driver
$ docker network ls -f="driver=bridge"
NETWORK ID     NAME                     DRIVER    SCOPE
136344c54e59   bridge                   bridge    local
```

## 指定のものを削除

```shell
docker network ls -f="name=none" | awk 'NR>1{print $1}' | xargs docker network rm
```

## 参考

<https://docs.docker.jp/v19.03/engine/reference/commandline/ps.html>

## お役立ち

<https://qiita.com/mom0tomo/items/911b92cc18871f52a2a0>
日本人1億3千万人のうち一体何人がAPIについてしっかり理解しているのか

## だから、APIて何やねん！

デベロッパーの皆さん、ご機嫌よう。
お待たせ致しました(誰も待っていない)。
前回無職の友人の為にコードを知らなくてもカッコいいWEBサイトを作れる様にどう教えたら良いかと考えた結果チュートリアル動画を作っていたのですがせっかく1人の為に作るならYouTubeにでもあげたら100万人くらいの人の役に立つかも知れないと思い立ちチャンネルを作って動画を上げた話 を書きましたが、アップから３週間ほど経ち、**100万人登録まであと99万9998人までいきました。**
で、せっかくチャンネル作ったのだから、他に何のコンテンツを上げようかと思ったのですが、次はバックエンドの方、ウェブ初心者の為にAPIについて語ってみようかなと。

## APIの理解は超重要
結構前にここでもAPIについて書いた様な気がするのですが、プログラマー諸先輩からも茶飲み坊主が何も分かっておらん　みたいな意見も含めて色々なコメントやメッセージを頂きました思い出。
やはり、プログラムを学べば学ぶほど、**世界中のプログラマー達が作った*AP*を、その*I*、つまりインターフェイスを通じて使わせてもらって**はじめて大きなプログラムも動くんだなという事を実感し、さらに複雑なウェブエコシステムのコアとも言うべきAPIという言葉、概念がよく分かっていないと、色々な解説書を読んでも腹落ちがしないという事になってしまうからです。
APIという言葉は、AP、APPLICATION PROGRAMMING とI、INTERFACEと分けて考えるとかなり分かりやすく、**APはいわゆるただのプログラム、そしてそのプログラムを使用する為のインターフェースがI**と、*インプットとアウトプットの2つの穴が付いた、中身の見えない機械*　ってイメージをすれば分かりやすいんじゃないかと思っていて、その辺を解説してみました。
日本人口の1億人くらいはAPIについてあまり深く理解が進んでいないと思われるので、そのうちの1千万人位のお役に立てればと思っています。
**1千万再生まであと999万9900くらい**なので、皆さまよろしくお願い致します。
<br>
<iframe width="560" height="315" src="https://www.youtube.com/embed/GnPrSwQVx_E" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<br>
最近はコードの勉強も、動画7割テキスト3割くらいで、見ながら書くというスタイルになってきたので、技術解説的な内容は動画で、文学的ポエムは文章で、気の向いた時に自己表現として粗製濫造していこうかなと思っている秋の夕暮れ。
英英辞書から単語の定義をスクレイピングしてみた

参考サイト
https://excel-ubara.com/excelvba4/EXCEL_VBA_401.html
https://powervbadesktop.com/web0/

英検準1級の勉強を始めたので英英辞書から単語の定義を取得するVBAを組んでみた。

# WebDriverにwebページの指定をする
```
Const dictionaryURL As String = "https://www.oxfordlearnersdictionaries.com/definition/english/"

Set Driver = New Selenium.WebDriver

targetUrl = dictionaryURL & word

Driver.AddArgument "headless"
Driver.Start "Chrome"
Driver.Get targetUrl
```

英英辞書はoxfordを使う
oxfordの辞書は
https://www.oxfordlearnersdictionaries.com/definition/english/
の後に単語を付ければいいので
```
dictionaryURL & word
```
で指定している

<img width="400" alt="dictionary" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99234/a803266b-34de-3ee0-b2b3-8bc0abd66121.png">

```
Driver.AddArgument "headless"
```
上記指定でChromeをバックグラウンドで実行できる


# ディベロッパーツールでタグを特定する

## 単語の定義をドラック > 右クリック > 検証

<img width="400" alt="dictionary" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99234/ac204bc4-3a32-8945-ceef-e25a19a3fa8c.png">

## タグを確認する

class="def"であることが分かる

<img width="400" alt="dictionary" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99234/9d80889e-8fc5-585a-9e6a-83214ac6696b.png">


# タグを指定して要素を特定する



```
Dim defElements  As WebElements
Dim defs As String
Dim defCnt As Integer
Dim ans As Integer

Set defElements = Driver.FindElementsByClass("def")
    
'すべての説明を結合する
For defCnt = 1 To defElements.Count
    defs = defs & defCnt & vbCrLf & defElements.Item(defCnt).Text & vbCrLf
Next


ans = InputBox("入力する定義を選択してください" & vbCrLf & _
                        "99=全ての定義を入力する" & vbCrLf & vbCrLf & _
                        defs)

Select Case ans
    Case 99
        Cells(ActiveCell.Row, columnEngDesc).Value = defs
    Case Else
        Cells(ActiveCell.Row, columnEngDesc).Value = defElements.Item(ans).Text

End Select

```

```
Set defElements = Driver.FindElementsByClass("def")
```
上記でdefクラスの要素に絞り込む


```
For defCnt = 1 To defElements.Count
    defs = defs & defCnt & vbCrLf & defElements.Item(defCnt).Text & vbCrLf
Next
```
すべての定義を結合する


```
ans = InputBox("入力する定義を選択してください" & vbCrLf & _
                        "99=全ての定義を入力する" & vbCrLf & vbCrLf & _
                        defs)

Select Case ans
    Case 99
        ActiveCell.offset(0,1).Value = defs
    Case Else
        ActiveCell.offset(0,1).Value = defElements.Item(ans).Text

End Select
```

<img width="400" alt="dictionary" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99234/33644ef8-1900-d4d8-2fff-4b53b294643e.png">

結合した定義をinputboxで表示しどの定義を取得するか番号を入力してもらう
99を入力した場合はすべての定義を入力する
React+TypeScript 百人一首読み上げプログラム その2

# はじめに

昨日のプログラムは自動で次々と読み上げるものでしたが、それはそれで環境ソフトにもなるし良いのですが、スマホでうまく動かないことが判明したので作り変えました。

ボタン「次の札を引いて読み上げる」を押すと次の札が選ばれて読み上げられます。

ボタンを押すたびにシャフルするのではなく、起動時にシャフルするので100枚読み上げるまでダブりで読むことはありません。


# 実行例

<p class="codepen" data-height="300" data-default-tab="result" data-slug-hash="ExROjgb" data-user="kalz2q" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/kalz2q/pen/ExROjgb">
  hyakuninisshu02</a> by kalz2q (<a href="https://codepen.io/kalz2q">@kalz2q</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

# 追記
データをだいぶきれいにしました。

読み上げデータ、プログラムのなかではspeechと言う変数に入っているデータですが、私の環境ではイヤホンで読み上げの頭が切れるので、データの頭に「ん。」を入れています。必要なければエディターで一括削除して下さい。 

自動で読み上げる方式から、読み上げボタンに変えたのでプログラムがすっきりしました。

使い勝手も良くなったと思います。
EFSをEC2にマウントする際、詰まったポイントをまとめてみた

## はじめに
職場でEFSをEC2にマウントする機会がありました
すんなり終わると思っていたのですが、何点か戸惑うポイントがあったので、そちらについて整理していきます

## 作業概要
![スクリーンショット 2022-11-27 14.38.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2666121/83fb1481-73cb-0c85-5ec2-d2dc925773f4.png)
#### 1 EFSの構築及びセキュリティグループの設定
以下の参考リンクをもとにEFSの構築とセキュリティグループの設定を実施しました
ほぼそのままでしたが、マウントされるEC2にアタッチされていたセキュリティグループのアウトバウンド通信を開け忘れていて、少し詰まりました

https://dev.classmethod.jp/articles/ec2-efs-mount-for-beginner/

#### 2 EFSのマウント
マウントポイントは
EC2:/home/applicaiton/shared
EEF:/shared_EFS

にてマウントしました
その際のコマンドは以下のようになります

```Linux.
sudo mount -t nfs -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport 【EFSのファイルシステムID】.efs.【リージョンID】.amazonaws.com:/shared_EFS /home/applicaiton/shared
```

#### 3 EC2のマウントポイントの権限変更
今回の要件は、特定のグループに所属するユーザのみが本ファイルの書き込み(w)及び実行(x)ができることなので、まず以下コマンドでマウントポイントとしてるディレクトリの権限変更をします

```Linux.
chomd 774 home/applicaiton/shared
chown <ユーザ所有権> <グループ所有権>　home/applicaiton/shared
```
これで今回の要件で指定したユーザとそんユーザが所属グループしか、ファイルの本ファイルの書き込み(w)及び実行(x)ができなくなりました

##### 参考
https://qiita.com/shisama/items/5f4c4fa768642aad9e06

https://webkaru.net/linux/chown-command/

#### 4 ユーザの追加
既に作成されているユーザを指定のグループに追加します

```Linux.
usermod -aG <指定のグループ> <指定のユーザ>
```
ただこのグループ追加のさいにSSSDに関するエラーがでました。
そのため一旦/var/lib/sss/db/にあるファイルを削除することで、本エラーは解決しました

###### 参考
https://eng-entrance.com/linux-user-add

https://qiita.com/orangain/items/056db6ffc16d765a8187

https://www.rootusers.com/how-to-clear-the-sssd-cache-in-linux/

#### 5 fstabで自動マウントの設定

以下コマンドで自動マウントの設定を追加します
これで本作業は終了です
```Linux.
【マウントターゲットID】.efs.ap-northeast-1.amazonaws.com:/EFS側のマウントポイント EC2側のマウントポイント nfs4 nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport 0 0
```
ちなみに、fstabが正しく設定されているか（自動マウントの設定ができているか）は、以下のコマンドで確認できます

```Linux.
umout
*マウント解除

mount -a
*fstabに記載されている内容を実行

mount
*マウントされているボリュームを表示
```

###### 参考
https://manual.iij.jp/p2/nas/d-3-2-7.html


#### 詰まったポイント
###### ・エンドポイントを作成するか問題
公式ドキュメントには[こちらのリンク](https://docs.aws.amazon.com/ja_jp/efs/latest/ug/efs-vpc-endpoints.html)のように、VPCエンドポイントについての記載があります
作業当日色々悩んだ果てに、結局エンドポイントを作成してしまいましたが、後日AWSの方に問い合わせたところ、**今回の構築のようにEFSをEC2にマウントするだけであるならば、VPCエンドポイントの作成は不要**とのことでした

仮に、VPCとEFS APIとの間にプライベート接続を確立する際には必要になります
→例えば、CLIを使用してEFSを操作する際などですね

###### ・EC2にアタッチされていたセキュリティグループのNFS開け忘れ
今回はEC2とマウントターゲット（EFS作成時に作成される）間のNFS通信ですので、セキュリティグループを対応させておく必要があります
EC2にアタッチされていたセキュリティグループのアウトバウンドに、NFSの開け忘れがありました
プライベート構築する際には、EC2にアタッチするアウトバウンドを全開けすることが多いので、盲点だったなと反省しております


## おわり
無料でアンチウイルスしたい

# 対象者
一般的なWindowsユーザー

# まえがき
無料でマルウェアの対策をしたい。
Windows Defenderが強化されたおかげで最近は何も入れなくてもいいと思ってる。
それでも追加で何かしておきたい。
無料で使えて期限も無くてスパムのような広告も無くてインストールとかも必要ないアンチウイルスソフトが欲しい。

# 無料で使えて期限も無くてスパムのような広告も無くてインストールとかも必要ないアンチウイルスソフト
## Microsoft セーフティ スキャナー
https://learn.microsoft.com/ja-jp/microsoft-365/security/intelligence/safety-scanner-download?view=o365-worldwide
Microsoftが提供しているマルウェアスキャナー。
最新状態を保つためにダウンロードしてから10日間しか使えない。
フルスキャンの場合はかなり時間がかかる。(3日かかった)
実行結果の詳細は
``
C:\Windows\debug\msert.log
``
に記録される。

## AdwCleaner
https://www.malwarebytes.com/adwcleaner
Malwarebytesが提供しているアドウェアスキャナー。
更新がある場合は更新される。
スキャンする場所が少ないのですぐにスキャンできる。

## Norton Power Eraser
https://support.norton.com/sp/ja/jp/home/current/solutions/kb20100824120155EN
Nortonが提供しているマルウェアスキャナー。
ルートキットのスキャンも可能(要再起動)。

#
オススメがあれば教えてください。
bigquery.jobUserを忘れるな(今年一番やらかしたこと)

# はじめに
22年ももう少しで終わりです。昨年もアドベントカレンダーで、SpannerとBQについて簡単な記事を書きました。相変わらずSpannerへの愛はあるのですが、機会に恵まれず。。
  
さて、今年1年で一番ミスったことをまとめようと思います。

# できごと
```
さぁ、やることが決まったぞ。IAM権限持ってる方にBQの操作権限もらおう！
とりあえずデータは書き込まないでいいから、"BigQuery データ閲覧者"の付与を依頼しよ。

------------------

 あれ、、Queryが実行できない。。権限不足、、？ いや、参照権限はもらったぞ？
 おいおい？ バグかなこれは～
```

はい。これを今年数回やりました。学習能力がありません。  
数回目のミスで、「あ、、、またやってしまった。。」と自分で自分を責めてしまいます。
反省しています。自戒の意も込めてこの記事をしたためます。

# 対応
Queryを実施するためにか下記の権限が必要です。
```
IAM 事前定義ロール
bigquery.jobUser（Bigqueryジョブユーザー）
```

#考察
[BigQuery データ閲覧者](https://cloud.google.com/bigquery/docs/access-control?hl=ja#bigquery.dataViewer)の説明には下記文面が書かれてあります。

>テーブルまたはビューからデータとメタデータを読み取る。
  
これだけ見ると、"データが見える = Queryが実行できる" と勘違いしてしまいがちです。
WEBコンソールでも、プレビューからデータを見ることができます。

また、Google CloudのIAMのポリシーとしては、閲覧者の定義は下記になります。
>roles/viewer (閲覧者) :
>既存のリソースやデータの表示（ただし変更は不可能）など、状態に影響しない読み取り専用アクションに必要な権限。

いいじゃん。データ見れるんだからQueryさせてよ！という感情が湧いてきます。
ではどう認識して、腹落ちすればハッピーになるのか。

## 課金からの目線
Bigqueryの製品仕様として、データ処理量によって課金されます。
しかし、Google Cloudの閲覧者のポリシーとしては、"リソースがどういう状態にあるか"の確認をする意が強い側面を感じています。

そのため、BigqueryでQueryが実施できちゃうと、データは見れるんだけど、課金されちゃうよ！という事態になってしまいます。Queryを実施するのはもう、閲覧者以上の行為という位置づけなのだと思います。

## データ編集の目線
実はこちらも何度かハマっているのですが、***BigQuery データ編集者*** を持っていてもQueryは実施できません。
え。。。。

Bigqueryでのデータ編集としての位置づけは、レコードに対してのアクションではなく、テーブルに対してのアクションの位置づけが強いです。
なので、Insert文どころか、Queryでレコードを操作するという概念ではない位置づけと理解しています。



# おわりに
案件によってですが、IAM管理者が多忙のため、なかなか捕まらず、権限の付与が遅れてしまうことが多々あります。
そのため、Bigqueryでデータを扱うのなら、ジョブユーザーはほぼ無意識レベルで必要と認識しておきましょう。
そもそも、検証環境があるならそこでしっかりと調査をしてから申請しなさいよと、言うことは重々承知ではありますが、誰かの助けになればと思います。

まだ12月は始まったばかりなので、残りも"権限不足で困らないように"過ごしましょう！
Javascriptで作るTodoリスト

## はじめに
普段はReactをよく使っていますが、Javascriptをもっと理解することができればもっと楽しいだろうなと感じています。
```React```も```Vue```も```Angular```も原始はJavascriptなので、Javascript力をつけることで根本的にフロントエンドに強くなれるのかなと思います。
まずはTodoリストを作ります。

## Javascriptは何をしている？
ブラウザはhtmlドキュメントを解析して、DOMツリーを構築します。

https://developer.mozilla.org/ja/docs/Web/Performance/How_browsers_work#dom_%E3%83%84%E3%83%AA%E3%83%BC%E3%81%AE%E6%A7%8B%E7%AF%89

DOMツリーはその名の通り木構造で構成され、タグや文字列などは個々のNodeになります。
各Nodeはクラスのインスタンスとして表されます。例えば```<body>```タグは```HTMLBodyElement```のインスタンスです。

https://ja.javascript.info/basic-dom-node-properties#ref-403

JavascriptはDOM APIを使うことにより、DOM操作を行うことができます。

## やってみる
以下のようなhtmlドキュメントを用意します。
```index.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Todo List</title>
    </head>
    <body>
      <h1>Todo List</h1>
      <form>
        <input class="input_element" type="text" name="todo_input" />
        <button type="submit" class="submit_button">Add</button>
      </form>
      <div id="todo_list_wrapper">
        <ul class="todo_list"></ul>
      </div>
    </body>
    <script src="sample.js"></script>
    </html>

```
```javascript
    document.querySelectorAll("*")
```
↑ ブラウザのconsoleでDOMツリーのNodeを確認することができます。

#### 目次
1. APIを使い、DOMツリーの要素に対してアクセスする
1. submit時の関数を作成する
1. 特定のイベントをフックにして、2で作成した関数を発火させる

#### 1. 要素へのアクセス
```sample.js
    const inputElement = document.querySelector('.input_element');
    const submitButton = document.querySelector('.submit_button');
    const todoList = document.querySelector('.todo_list');
```
取得されるDOM要素は以下のようになります。
![スクリーンショット 2022-12-03 13.43.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2849988/8aec6604-9ce6-7f35-0995-1e1ce2aafefd.png)

#### 2. submit時の関数の作成
```sample.js
    const handleSubmit = (event) => {
        event.preventDefault();
        const newItem = document.createElement('li');
        const newItemText = document.createTextNode(inputElement.value);
        newItem.appendChild(newItemText);
        todoList.appendChild(newItem);
        inputElement.value = "";
    }
```
1. ```document.createElement('li')``` => Todoリストは```<ul>```要素で構成されているため、そこに追加するための```<li>```要素を作成します。
1. ```<li>```の中身(子要素)となるTextNodeを作成します。
    - inputに入力された文字列はvalueプロパティを参照すればいいため、```inputElement.value```で取得できます。
1. ```appendChild```を使うことによって、```newItem```と```newItemText```を親子関係にします。
1. ```newItemText```を子要素にもつ```newItem```を```ul```の子要素に追加すればいいため、```appendChild```を使って```todoList```の子要素に```newItem```を追加します。
1. 追加したら```input```を空にします。

↓ ```preventDefault```について

https://qiita.com/yokoto/items/27c56ebc4b818167ef9e

#### 3. フックで発火するようにする
```sample.js
    submitButton.addEventListener('click', handleSubmit);
```
```addEventListener```でクリックイベントをフックにして、2で作成したhandleSubmitを発火させるようにします。

https://developer.mozilla.org/ja/docs/Web/API/EventTarget/addEventListener
Redshift を利用したストリームパイプラインの新たな可能性

## まえがき
Redshiftへのストリームパイプラインの構成として様々な手法が存在すると思います。
本記事では新たな可能性としていくつかの手法が登場していきているので、それらを実際に動かして評価していきたいと思います。

:::note warn
執筆者の都合で大変申し訳ございませんが、12/3 正午 時点でまだ検証作業を続けている途中です。
記事は検証作業が全て完了次第、アップデートします。今しばらくお待ち下さい。
:::


### 従来からある手法
**1. データストリーム -> Kinesis Data Firehose (KDF) -> S3 -> ( COPYコマンド ) -> Redshift**
S3上のデータ（のパス）を手組みのジョブ経由で Redshift に連携する、最もプリミティブな方式。
前回実行分との差分も管理が必要。
- **Pros**
    - 特になし ( 強いて言うなら自由度が高いぐらいか )
- **Cons**
    - ロードジョブの開発が必要 (イベントベースでSQSに取り込んでCOPYを実行する など)
    - 前回実行分との差分も管理が必要
- **データ鮮度 (目安)**
    - 10分以内

**2. データストリーム -> KDF -> Redshift**
KDF から直接Redshiftに連携する方式。内部的にはCOPYが実行されている。[参考](https://docs.aws.amazon.com/ja_jp/firehose/latest/dev/create-destination.html#create-destination-redshift)
- **Pros**
    - Redshiftへのロード処理の実装が不要
- **Cons**
    - KDF のコスト
- **データ鮮度 (目安)**
    - 10分以内

### 新たな可能性
**1. Redshift Spectrum を使う構成 ( データストリーム -> KDF -> S3 <- Redshift Spectrum**
技術スタック自体は従来からあるものですが、ストリームパイプラインでの適用は検討されることが少ないのではないでしょうか。しかし、パフォーマンスが問題にならないケースにおいては Redshift Serverless と組み合わせることでコスパの良いニアリアル分析パイプラインが作れるのでは？という仮説から、本記事内での検証対象としております。
- **Pros**
    - Redshiftへのロードが不要
    - コスパの良いニアリアル分析パイプライン
- **Cons**
    - クエリ応答速度が遅くなる
    - ファイルサイズやパーティションのチューニングが必要
- **データ鮮度 (目安)**
    - 10分以内

**2. データストリーム -> KDF -> S3 -> ( Auto COPY ) -> Redshift**
2022/11/29 プレビューが公開れた。[What’s New](https://aws.amazon.com/jp/about-aws/whats-new/2022/11/amazon-redshift-supports-auto-copy-amazon-s3/)
定期実行するCOPYジョブが前回実行との差分を自動ロードしてくれるのでCOPYコマンドの管理が不要。
- **Pros**
    - ロードジョブを手組で作る必要が無い
    - 差分ファイルを随時取り込んでくれる
- **Cons**
    - Previewのため、通常のCOPYと比較して多くの制限がある
- **データ鮮度**
    - 不明 (実際に検証してみる。)

**3. データストリーム -> ( Redshift Streaming ) -> Redshift**
これまで Preview として公開されていたが、2022/11/29 にようやくGAとなった。 [What’s New](https://aws.amazon.com/jp/about-aws/whats-new/2022/11/amazon-redshift-real-time-streaming-ingestion-kds-msk/)
ストリームデータソースから直接取込み、Materialized View (MV) としてデータを保持する。Streaming for Apache Kafka (MSK) もサポートされている。また、追加コストなしでストリーミングデータのダウンストリーム処理および変換を実行することができる点も嬉しいポイント。

- **Pros**
    - ストリームから直接データを取り込むので他の手法に比べて圧倒的にリアルタイム性能が良い
    - 追加費用なしなので、従来からある KDF を使った方式よりコスパが良い
- **Cons**
    - MVの更新が必要（自動更新 がどこまで使えるか検証）
    - MV と他のテーブルの直接JOINができない(はず)ので、実体化が必要
    - 実体化まで含めてのデータ鮮度となるとどこまでデータ鮮度が保てるか不明 (こちらも検証する)
- **データ鮮度**
    - データ鮮度は秒単位 (のはず)


## 1. Redshift Spectrum を使う構成
WIP
## 2. Auto-copy from Amazon S3  を使う構成
WIP
## 3. Real-time streaming ingestion for Amazon Kinesis Data Streams (KDS) を使う構成
WIP
## まとめ
WIP
新しい風！留学制度 -モブプロ開発を行っているチームでやっている取り組み-

# はじめに

本記事は[モブプロ開発を行っているチームでやっている取り組み Advent Calendar 2022](https://qiita.com/advent-calendar/2022/mob_torikumi_example)の19日目の記事です

今回はチームで実験的に行っている「留学制度」について紹介します
留学制度自体は割と行われている企業はあるかと思います。私たちのところも割と同じ感じで行っていますが、その経緯などが面白いかなと思うので簡単に紹介します

# 前回

https://qiita.com/Sicut_study/items/7e6b8f24162fb418ceef

# Chapter#18 新人現る

ミュート「じんさんいます？」
じん「はい、いますよ」

ここはZOOMの中なので、よく見る光景だ

ミュート「私のところに2年目の新人の方がきて、お弁当注文のリマインドをするラインボットについて話してたんだけど」
じん「あー、お弁当注文のボットその方が作ってるみたいな話してましたね」
ミュート「その人が、2年間ほぼ開発というよりはログ調査ばかりの運用が多くて、自分で何か作ったのにとても感動したっていってたんですよ」
じん「それはよかったですね！しかし、私たちの会社ではチームで設計から運用までしているので、運用だけしかやらせてもらえていないのはかわいそうですね」
ミュート「運用とか軽微な修正ばかりで、それ以外はメンターの人が作業しちゃうらしいですよ、納期が早いとかで」
じん「それはチーム的にはあまりよくないですね。全員がすべての作業について把握して、できる状態でないといまキーパーソンで開発している方が辞めた際には積みますよ。あと、せっかくの新人の大事な期間にその作業させてるのはだめですね」
ミュート「一番モチベーションの高い期間ですもんね」

アール「私はじんさんのおかげで、いろいろ経験させてもらってるのでチームに恵まれました」
じん「それが普通になってないとだめなんですよ。いまのやり方では負債が増えてアジャイルなんて到底できているとは言えません」

ミュート「それでそのあと相談されたんだけど、今の仕事じゃなくてデザイナーチームに移動したいって言ってました」
じん「なるほど。デザイナーチームに移動はできなくはないと思いますが、コーディングは最低限出来ないと厳しいと思いますね」
ベープ「ワンさんってフロントエンドとかある程度かけるんですか？」

その2年目の新人の方は、犬派とすごい主張していたことから「ワンさん」と呼んでいる
ちなみに私とベープさんが猫派

ミュート「いやー、ほとんどやらせてもらってないみたいで、JSも危ういと思います、、」
じん「それは彼女のキャリアのためにもまずいですね」
ミュート「そうだよね、、」

じん「では、うちがそろそろ新しい案件やることになるのでその案件に参加してもらって画面のデザインをFigmaでつくってもらってReact+TypeScriptで実装してもらうのはどうでしょう？みなさん教えられますよね？」

そうして、その日のうちに話は進み、上長の許可をとってワンさんの案件参加がきまった

# 留学制度について

留学制度は、社内の別のチームに勉強をするために数カ月ほど移籍する制度のことを呼んでいます
私のチームではアジャイルがある程度進んでおりよくなっているので、この習慣や雰囲気、モチベーション、技術を次は別チームに普及するフェーズだと考えていました

そこで行った取り組みの一環が留学制度になります

ここでは、私たちが使っているフロントエンドの技術を学んでもらったり、モブプログラミングをはじめとしたスクラムについて学んでもらおうと2カ月ほど取り組んでいます

やったこととしては
- 要件定義から画面設計を行い、Figmaでデザインする
- JavaScriptの基本的な学習
- TypeScriptの学習
- React+ChakraUIを利用した画面作成

までを2カ月ほどかけて行いました

デザインがとても好きだった方だったので自由にFigmaでデザインをするのが楽しかったようで、それがそのままReactで再現できたがよい経験と本人はお話ししておりました

基本的には留学制度できた方がReactになれるまではひたすらモブプログラミングでタイピストをやってもらっていました
また、チームとしてはReactを別の人に教えるという経験を通してより深く理解することができました

今回はたまたま本人が相談してくれたので、私たちのチームが本人のために動くことができました
しかし、社内にはおそらくそのように感じている新人がまだいますし、新人にログ調査ばかりさせているチームも存在します。そのような現状を改善しなければならないという課題を理解することができ、これからもどんどん留学制度をしていく必要があるなと感じました

今回の留学制度は「BIRDプロジェクト」と呼んで行っていました
「Basic Department Reserch」からそのように読んでおり、今回のチームは「カワセミ」と鳥の名前を付けています

これからもどんどん留学制度で数カ月のチームができて色々な鳥の名前がついてくれたらと考えています

# 次回

https://qiita.com/Sicut_study/items/183fde6658cc6f88362a

# おわりに

今回は留学制度の簡単な説明と、私が経験した課題について書きました
留学制度はアジャイル組織を作るのには必須な制度だと思っています。チームを強くして組織を強くするのに大事です

またここではBIRDプロジェクトとして鳥の名前をチームにつけていますが、チームに何かしらの名前をつけて愛着をもつのもかなりおススメなのでやってみてください
ExpressRouteの主な実装手順と2種類のピアリング

●ExpressRoute回線と2種類のピアリング
ExpressRouteを利用する際は、ExpressRoute回線というリソースを作成し、そのリソース内でピアリング情報を構成する。この情報はExpressRputeピアリングとよばれ、接続先に応じた次の2種類のピアリングが用意されている。

■Azureプライベートピアリング
Azure仮想ネットワークとの接続に使用するピアリング。これにより、仮想ネットワークに接続された仮想マシンとクラウドサービスにプライベートIPアドレスで接続できるようになる。

■Microsoftピアリング
マイクロソフトのオンラインサービスであるMicrosoft 365やAzure PaaSサービスとの接続に使用するピアリング。ただ、Microsoftピアリングでの接続に利用できるのはパブリックIPアドレスのみ。そのため、パブリックIPアドレスの準備に加えて、オンプレミスネットワーク側ではNATを使用してプライベートIPアドレスをパブリックIPアドレスに変換する必要もある。

●ExpressRouteの主な実装手順
１、ExpressRoute回線の作成
２、ExpressRouteピアリングの構成
３、ExpressRouteゲートウェイの作成
４、接続の作成と確認

ExpressRoute回線を作成すると、個々のExpressRoute回線を識別するための「サービスキー」と呼ばれるIDが発行される。サービスキーは接続ポロバイダー側での初期設定に必要な情報。

■ExpressRouteゲートウェイ
VPNゲートウェイの作成時と同様、ゲートウェイサブネットには「GatewaySubnet」と名前をつける必要がある。アドレス範囲は/27以下の値を使用することが推奨されている。
Vue3とExpress, Socket.ioで5段階評価サイトを作ってみた

# はじめに

今回はVuetifyがVue3に対応したという事で、Vueを書いてみようという気分になりましたのでそのお話について書いていきます。
Vue自体は1年前くらいにVuetifyが使えるという理由から、Vue2を個人的に少し書いてみたり、案件で一部Vueを書いていたしていました。
それ以降はReactにのめりこみReactばかりになっていたのですが、Vue3にVuetifyが対応したことやTypeScriptが使えること、Svelteの人気が上がってきたことから久しぶりにVueを今回書いてみました

# アプリの構想

今回作成したのは「5段階評価サイト」というものです。
ユーザーが任意のルームに参加して、「AさんのVueの能力」などのテーマに対してみんなで5段階で評価を投稿して、一斉に公開、平均点が表示されるシステムを作りました

なぜこのサイトを作ったかというと、普段モブプログラミングで実装をしている私のチームでは人事評価などはチームのメンバーでやるのがふさわしいという話になりました。そこで、以下の「Hatjitsu」というサイトを利用して試しに各エンジニアスキルについて5段階評価をおこなってみました

https://hatjitsu.toolforge.org/

このサイトはフィボナッチ数列でチケットの工数を見積もるものなので、5段階(1-5)で投票はできず、なおかつ平均点をいちいち計算する必要がありました。しかし、リアルタイムで平均点を出して色々議論する時間もとても良いものだと思い、平均点をリアルタイムで投票して出すだけのサイトがほしいなと思うようになりました

# 今回作成したもの

今回は`Vue3`、`TypeScript`、`Express(Node.js)`、`Socket.io`、 `Firebase`を利用して「Average Poker」というものを作成してみました

まずは以下のログイン画面から参加者は参加者同士で決めたルーム番号と名前を入力してルームに入ります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/1d14cddd-98cc-88d5-e18e-69b9aaa4531e.png)

入ると以下の画面が表示されます
こだわったのはポーカーという名前からカジノ感をだすようなUIにしました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/97e43568-3a13-fc62-7207-17213cc1bbf2.png)

この画面からは参加者の情報や、今回の評価するテーマを記入したり、チャットをしたり、実際に投票をすることができます。全員が投票をすると`SHOW DOWN`から平均点が出力されるようになります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/cc71b8a8-c5e9-9c83-7dbe-b6aa4af0908c.png)

入力の内容や投票の情報はすべて`Socket`を利用してリアルタイムに同期するようになっています

# 作成の流れ

今回は`Socket.io`を利用することをメインにサイトを作成しました
`Socket.io`の使い方を学ぶのに利用したのは以下の動画です

https://www.youtube.com/watch?v=dSllP4TRJls

こちらはすべてReactでフロントが書かれていますが、それをVueで書き直して作成しました
そこである程度Vue3については学習ができました

Socket.ioの使い方がわかればあとは問題なく実装できるのでフロントを作成するだけで完成まで行きました

1つ課題だったのは、「後から参加したユーザーに過去の情報を与える」という点でした
たとえば、1人目のユーザーが参加していて、次のユーザーが参加したときにそこまでの投票情報や人数がすでに何人いるかなどの情報を与える必要がありました

そこで`firestore`を利用して参加したときに同じルームのユーザーの情報を取得して、退出時に自分の情報をデータベースから消すという処理をいれて工夫しました

# おわりに

アプリが解決するのは全員の合計点を人数で割って平均点を出すという単純なものですが、単純だからこそリアルタイムでできるようなものが調べた感じでは存在していなかったです

アジャイルをやるうえで、チームでの評価はとても大事になりますし、その評価をリアルタイムにして本人も混ざって議論するのはとてもよいかなと思ったので作成してみました

Socketについてある程度理解でき、Vueを久しぶりに書くことができたので良い経験になりました
Vite + React の Hello World

最近Vite(ヴィート)が熱いと聞いたので、
関わってる団体のホームページをVite+Reactで作ってみました。

ということでHello Worldの手順を共有します。

## Viteの最高なところ
* ビルドが高速

以上。

![画面収録 2022-12-03 13.28.12.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581713/a028a970-a48b-619b-7cca-170e8084a248.gif)


## Hello Worldの手順

1. nodeのVersionをある程度最新にする(割愛)
1. コマンドを叩く
    1. ProjectNameを入力
    1. 使うフレームワークの選択
    1. TSかJSかの選択
1. ディレクトリの移動とサーバーの起動


### コマンドを叩く
```
yarn create vite
```
以下対話方式で聞かれる項目に入力していきます。

#### ProjectNameの入力
こんな感じにプロジェクトの名前を入れてください。

![test_—_test__yarn_create_vite_—_zsh__figterm__▸_node_—_80×24_と_画面収録_2022-12-03_13_28_12_mov.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581713/63497251-0a25-f70c-77d7-cbb4195a8903.png)

#### 使うフレームワークの選択
以下のようにVue, React, Svelteなどのフレームワーク？が並ぶので選択します。
今回はReactを用いるので、Reactを選択して次に進みます。

![test_—_test__yarn_create_vite_—_zsh__figterm__▸_node_—_80×24_と_画面収録_2022-12-03_13_28_12_mov.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581713/ba262aba-4f25-44f9-5c8c-7b8afd4baa52.png)



#### TSかJSかの選択
TSを使います。(脅迫)

![test_—_test__yarn_create_vite_—_zsh__figterm__▸_node_—_80×24_と_画面収録_2022-12-03_13_28_12_mov.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581713/f561d80c-d5eb-1e82-a9fe-2fa695aa2400.png)

### ディレクトリの移動とサーバーの起動

```
cd {先程入力したプロジェクト名}
yarn
yarn dev
```



↓こうなれば勝ちです。
![Vite___React___TS_と_Vite___React___TS.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581713/21affd3b-2bd1-1337-cc4e-6373ae47aaac.png)

あとは煮るなり、焼くなりしましょう。

お疲れさまでした。

## まとめ

著しく簡単ですね。
いい時代だなあと思いました。

みんなでviteの速さに恍惚としましょう。

不一
RUN/PROLOG互換の処理系N-Prologのご紹介

# はじめに
Prologのカレンダーを見つけてうれしくなった私です。でも、まだ記事の投稿がありませんね。学術的にも実務的にもまったく用をなさない記事かもしれませんが、ちょいとしゃしゃり出てみることとしました。しばらくお付き合いくださいませ。

# ノスタルジー
1980年代、ライフボート社からRUN/PROLOGというPrologインタプリタが販売されていました。言語処理系を購入しようとするとうん十万円は普通にした時代になんと2万円というお手頃値段で販売されていました。利用した方も多かったのではないかと思います。同時期にProlog-KABAという優秀な処理系も存在したのですが、こちらは8万円くらいしたように覚えています。私はRUN/PRologのお世話になりました。マニュアルももう色あせてバラバラになっています。

![IMG_1117.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33927/b39418a2-c2ac-e4db-5361-53e66524e272.jpeg)


# N-Prologとは
RUN/PROLOG互換のPrologインタプリタ・コンパイラです。性能はSWI-Prologには遠く及びませんが、取り扱いをできるだけ簡単にし、RUN/PROLOGの雰囲気に近づけるようにしています。当初、ISO-Prolog互換を目指していたのですが、ISO-Prolog規格のできの悪さにうんざりして離脱、懐かしのRUN/PROLOG互換にしたものです。SWI-PrologはISO-Prolog互換ではありませんが、これには作者のJanさんの深い思いが込められているものと私は思っています。


# 利用可能なOS
ほぼすべてのLinuxで動作します。また協力者の方によりMacOSでも動作するようになりました。OSより　npl　と入力すると起動します。対話モードがスタートします。assert述語を使って手入力することもできますが、かったるいのでエディタを起動しましょう。Linux標準のnanoを起動するようにしてあります。

![bandicam 2022-12-03 13-10-33-955.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33927/a539c0b6-eb94-3544-459e-311989674abb.jpeg)

![bandicam 2022-12-03 13-13-49-607.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33927/1629059c-0589-98d6-776a-a813f6b856c1.jpeg)

![bandicam 2022-12-03 13-15-02-320.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33927/2c0d3f3a-57a8-e7a8-5d25-0bf01143c3b9.jpeg)


RUN/PROLOGではPC-9801上のMS-DOSで起動しました。エディタは簡易なスクリーンエディタが付属していたように覚えています。


# 漢字もOK
RUN/PROLOGはシフトJISによる漢字も使えました。N-Prologもunicode対応にしてあります。あの動物データベースもオリジナルと同様に処理することができます。

![bandicam 2022-12-03 13-23-28-865.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33927/e074520f-53f4-0ec4-6d24-4820d1b498b4.jpeg)


# コンパイラ内蔵
RUN/PROLOGはインタプリタのみでした。N-Prologはコンパイラもついています。といってもC言語に変換、動的リンクをするタイプでありそれほど高速化はできません。一応、一部最適化を入れてありnqueensなんかはSWI並みに高速に動作します。
![bandicam 2022-12-03 13-31-44-636.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33927/f9a60cdc-82c8-a5b9-f297-2d07c9c68a8c.jpeg)

![bandicam 2022-12-03 13-30-57-227.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33927/14561d3c-0233-3982-b9b2-491dce560d1b.jpeg)


PC-9801で8queenを動作させると最初の解が表示されるまでに数秒、十数秒かかっていました。今では全解探索を一瞬にやってのけます。コンピューターは進歩したものです。


# DCGも内蔵
DCGも起動時に動作するようにしてあります。DCG構文を使って遊ぶこともできます。

![bandicam 2022-12-03 13-37-30-218.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33927/ea9d41df-25e9-ba13-851d-15002e330c99.jpeg)

![bandicam 2022-12-03 13-40-00-706.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33927/b062ca74-9343-a105-f5c6-150474b80555.jpeg)


# 古本
Prologブームの頃に多数の本が出版されました。今でも古本屋さんに行くと容易に入手可能と思います。こんな本があります。
![IMG_1118.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33927/c0c5046c-2db7-aa77-ffc7-80b0b0d31a41.jpeg)



# どうぞ懐かしんでください
その昔、卒論はPrologのことでした、という方も多いことでしょう。計算機科学を教える大学ではLispあるいはPrologが必須だそうです。どうぞRUN/PROLOGを思い出してお楽しみください。N-PrologはOSSとして下記において公開しています。

https://github.com/sasagawa888/nprolog
[ServiceNow] カタログアイテムで添付されたExcelファイル内の内容を変数に反映する

# 概要
Attachment変数にExcelファイルを添付すると、ファイルを読み込み、ファイル内の値を各変数に反映させるような処理をやってみる。

# 画面イメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358025/fdebcd48-f662-5b8a-59dd-bad7bda8ae19.png)

# 環境
Tokyo

# 処理の流れ
Excel読み込み処理はスクリプトインクルードで定義。
Attachment変数にonChangeのクライアントスクリプトを設定し、その中で「Excel読み込み処理の呼び出し～変数に値を格納」までの処理を行う。

# Excelファイルの内容
以下のようなファイルを対象とする。

| Question | Anser |
|:-:|:-:|
| 名前は？ | 田中太郎 |
| 出身は？ | 東京都 |
| 年齢は？ | 28 |
| 勤め先は？ | ABC Company |

# 実装
## カタログアイテム
以下の変数を定義したカタログアイテムを用意
* Excelファイルを添付するためのAttachment変数
* Excelファイルの内容を格納するための変数

## スクリプトインクルード
クライアントスクリプトから呼び出すため、「Client callable」にはチェックをいれておくこと。

```js
var ExcelScript = Class.create();
ExcelScript.prototype = Object.extendsObject(global.AbstractAjaxProcessor, {
    fileLoad: function() {
        var parser = new sn_impex.GlideExcelParser();
        var attachment = new GlideSysAttachment();

        // Excelファイルの読み込み
        var file = this.getParameter('sysparm_file'); // 添付ファイルのsys_idはクライアントから受け取る
        var attachmentStream = attachment.getContentStream(file);
		parser.setSheetName("Sheet2");
        parser.parse(attachmentStream);

        // ヘッダーを格納
        var headers = parser.getColumnHeaders();
        var header1 = headers[0];
        var header2 = headers[1];

        // 各行の値をJsonに格納
		var obj = {};
		var i = 1;
        while (parser.next()) {
            var row = parser.getRow();
			var name = "q" + i;
			obj[name] = row[header2];
			i++;
        }

		return JSON.stringify(obj);
    },
    type: 'ExcelScript'
});
```

## クライアントスクリプト
トリガーは、Attachment変数のonChange。

```js
function onChange(control, oldValue, newValue, isLoading) {
    if (isLoading || newValue == '') {
        return;
    }

    var ga = new GlideAjax('global.ExcelScript');
    ga.addParam('sysparm_name', 'fileLoad');
    ga.addParam('sysparm_file', newValue);
    ga.getXMLAnswer(function(answer) {
		var json = JSON.parse(answer);
		
		g_form.setValue('question1',json.q1);
		g_form.setValue('question2',json.q2);
		g_form.setValue('question3',json.q3);
		g_form.setValue('question4',json.q4);
    });
}
```

# 補足
## Excelファイルのふりがな
Excelを読み込んで値を取得する際、セルにふりがなが設定している場合、ふりがなも一緒に取得してしまう。
そのため、読み込み対象のセルのふりがなはあらかじめ削除しておく必要がある。

例えば以下のセルを読み込むと、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358025/b1f95d9e-3b0d-3b8c-dfe8-373eb3941e78.png)
ふりがなまで格納されている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358025/03e872c2-3c94-31ae-dc04-55dfe70abb9d.png)

# 参考
* [GlideSysAttachment | ServiceNow Developers](https://developer.servicenow.com/dev.do#!/reference/api/tokyo/server/no-namespace/c_GlideSysAttachmentScopedAPI)
* [GlideExcelParser - Scoped, Global | ServiceNow Developers](https://developer.servicenow.com/dev.do#!/reference/api/tokyo/server/sn_impex-namespace/GlideExcelParserScopedAPI)
* [GlideAjax | ServiceNow Developers](https://developer.servicenow.com/dev.do#!/reference/api/tokyo/client/c_GlideAjaxAPI)
カスタムオブジェクトにデータをインポートする(データインポートウィザード)


# カスタムオブジェクトを準備します

+ **カスタムオブジェクトと準備したフィールド**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/7b795b53-5c88-05c2-6e2d-7efa29ebf9fe.png)

+ **先にタブを設定します**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/b6c0377b-4df1-1e6a-81da-77d6c32b9e61.png)

+ **最近参照したデータのビューにフィールドを追加します**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/f6d3f8b3-7284-d6de-a38e-19ade68a1eb8.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/30cff96a-72c7-6c01-df4e-5bb35d2474dd.png)

ちゃんとカスタムフィールドが追加できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/3e8df7c4-e887-a0a0-a599-a1ad092ad21d.png)

まぁ。これでオブジェクト側の準備ができました。


# データをインポートします

+ **データインポートウィザード**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/e40e5b44-ba62-660b-b0fb-c0b8009bd696.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/d83fae38-b8b8-1af6-87d1-fdabe5d78dd2.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/1fa225af-eb36-9bbf-3bb2-69da0c577a0f.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/910a5d48-b9c9-ad70-ac77-b0f0fcfc473f.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/74d2525d-185d-2ebf-2114-2384f093146f.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/d4af6417-a6b5-4687-cf20-a078fbb00735.png)

無事にインポートできたようです。　エラーはありませんね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/422a0a18-5c2d-5694-17dc-6df43f3e7306.png)

# レコードの確認

全てのビューで確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/a02946d2-64c0-b518-eea9-04bd9af1b642.png)

せっかくなのでビューにフィールドを追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/51255f53-9f93-4c3f-92d3-014e191dcf3b.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/69d45bd1-19ae-b4f2-85f7-e0459305560c.png)


これで見栄えもよくなりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/06637995-8bce-be86-a13d-e7bc809eb188.png)
VSCodeでFlutter(dart)のコードに自動でセミコロンを挿入する設定

意外と知られていない！？

# 挙動

- タイミング： ファイル保存時
- VSCodeでdartファイルにセミコロンを挿入


![画面収録 2022-12-03 13.18.38.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183059/a99f7eff-b366-4cc5-a633-1af942e0e4a3.gif)|
|:-:|


## settings.json

`settings.json`の`quickfix`の設定で`insertSemicolon`を`true`に

```settings.json
{
  "[dart]": {
    "editor.formatOnSave": true,
    "editor.codeActionsOnSave": {
      "quickfix.insertSemicolon": true,
    }
  }
}
```


quickfixの全設定は参考にリンクを載せましたので参考にしてみてください。

意外と知られていない？ので、記事にしてみました。
`Typescript`、`Javascript`とかだと`Prettier`を使わないといけないですが、`Dart`は公式VSCodeの拡張だけ追加するだけでいいのでサポート手厚い言語ですねー

# 参考
- [Dart公式 VSCode推奨設定](https://dartcode.org/docs/recommended-settings/)
- [Dart QuickFix設定](https://dartcode.org/docs/refactorings-and-code-fixes/)
- [Dart 全設定](https://dartcode.org/docs/settings/)
【Unity】Transform型とは

# 初めに
Unityでゲームを作っている時に、Transformやtransform、GameObjectやgameObjectなど文字の大きさが違うことによりエラーが出ることが多かった。
どうやらTransformはどうやらunityの型らしい。
型については以前にまとめたがUnityの型があるのかと。
何となーくの理解でコードを書いていると、途中で頭が混乱するので一度振り返る。

# Transform型とは
ゲームオブジェクトの位置、回転、大きさを表すクラスのことである。
MonoBehaviourを継承することで変数としてtransformという名前で保持する。

公式リファレンス
https://docs.unity3d.com/ja/2019.4/Manual/Transforms.html

# ざっとまとめると
Transformは型(クラス)である。
intやfloat、void等を使う(構文を作成する)ように、位置、回転、大きさを表したい時に使用すれば良い。
Transform型を使う時にtransformと小文字にするとエラーが出るので注意です。
CodeIQ:等比？ 等差？ フィボナッチ？？の解答

@nabetaniさんのCodeIQの問題です。問題と解説はこちら
->http://nabetani.sakura.ne.jp/codeiq/codeiq_b2889.html

等比数列は、小数点にならないように、A/B=B/CをA*C=B*Bに変形して使いました。(geo/1)
(追記:解説によると桁数が大きくなると上記の方法が使えない言語があるそうですが、
SWI-Prologでは使えるようです。そもそも有理数が使えるようですが）
フィボナッチ数列はfibo40/1で入力値での成立を確認した後fib40/1で1までたどりました。

```Prolog
%SWI-Prolog (7.4.2,7.6.4)
%:-initialization(start). %ideone
%start.

ari([_,_]).
ari([A,B,C|T]):-B-A =:= C-B, ari([B,C|T]).

geo([_,_]).
geo([A,B,C|T]):-A*C =:= B*B, geo([B,C|T]).

fib40([1,1]).
fib40([Y,Z]):-X is Y-Z,X > 0, fib40([Z,X]).

fibo40([Y,Z]):-fib40([Y,Z]).
fibo40([X,Y,Z|T]):-Z =:= X-Y, fibo40([Y,Z|T]).

solv40(L0,R):-
     reverse(L0,L), (ari(L) -> R='A'; (geo(L) -> R='G';
     (fibo40(L) -> R='F'; R='x'))).

start40({}):-!.
start40([f(S,Q)|T]):-
     atomics_to_string(L,"\s",S), maplist(atom_number,L,L1),
     solv40(L1,R), disp40(R,Q), start40(T).

start:-list(L),start40(L).

disp40(R,Q):-(R==Q -> Str="good "; Str=" bad "), write(" "), write(Str), writeln(R).

list([f("160816114 194672138 235655746 285267482 345323794",'G'),
f("9845600625 9876856500 9908211600 9939666240 9971220736",'G'),
f("9715064832 9751864320 9788803200 9825882000 9863101250",'G'),
f("1234 6912 12590 18268 23946",'A'),
f("9999999990 9999999991 9999999992 9999999993 9999999994",'A'),
f("1 2000000000 3999999999 5999999998 7999999997",'A'),
f("13 21 34 55 89",'F'),
f("121393 196418 317811 514229 832040",'F'),
f("1134903170 1836311903 2971215073 4807526976 7778742049",'F'),
f("9983848527 9987006973 9990166419 9993326864 9996488308",x),
f("969323029 1568397607 2537720636 4106118243 6643838879",x),
f("1032569015 1670731762 2703300777 4374032539 7077333316",x)]).
```
Keycloakを使った自前認証を試してみた

学校法人角川ドワンゴ学園でプログラミングコーチをしている @miya0 です。生徒からのプログラミング学習に関する質問や相談を解決するのが主な仕事です。一から技術を試して学ぶのが好きです。

# はじめに
自前で簡単に認証トークンを発行できる認可サーバが作れるソフトウェアを紹介します。
試しやすさを重視して、今回はDockerを用いた公式ハンズオン手順を説明します。

# Keycloakとは
RedHat社が開発・公開している認証認可のOSSソフトウェアです。
- OpenID Connect(OIDC)
- Security Assertion Markup Language(SAML)
- OAuth 2.0
などのSingle Sign-On(SSO)プロトコルに対応しています。

これによって、オープンソースでIdPとして運用・利用できます。
Keycloakでは、認証のバックエンドとしてActiveDirectory(AD)も利用できるため、KeycloakをIdPとして導入することで、Windowsログインで使っているIDとパスワードを使って、インターネット上のサービスに対しても利用可能となります。
私たちの身近では、GitHubやTwitterなどとのサービス連携に使われることがあります。

より詳細な実践や概念、システム構成などは[大手技術系の記事で連載](https://atmarkit.itmedia.co.jp/ait/series/7363/)されていました。

# ハンズオン

- 今回は公式に沿って、執筆時の最新Verを用いてDocker上で試します。
    - https://www.keycloak.org/getting-started/getting-started-docker
    - ID / Password は admin / admin, localhostは8080ポートを使います。

```bash:実行コマンド
docker run -p 8080:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak:20.0.1 start-dev
```

docker-compose.ymlに書いて、docker-compose upしたい場合は下記。

```yaml:docker-compose.yml
version: '3'
services:
  keycloak:
    image: quay.io/keycloak/keycloak:20.0.1
    ports:
      - 8080:8080
    environment:
      - KEYCLOAK_USER=admin
      - KEYCLOAK_PASSWORD=admin
```

### 管理画面にログイン
- http://localhost:8080/admin
![ログイン画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985158/26b198f7-3592-cf0d-6df5-2c894e424c95.png)

### 準備・設定 
左のmaster選択後、Create Realmを選択し、Realm nameの欄にmyrealmと入力してCreate。
![作成画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985158/e1afecda-c502-19d5-d5f2-216183e2c99a.png)
新規ユーザーの作成後、Credentialsの設定を行い、Set Passwordを行う。この時初回ログイン時のパスワード変更をスキップするためにTemporaryはOFFにする。
![Credentialsの設定時](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985158/adba5d6f-4767-41d8-ff62-7911feeb5fcc.png)

![ユーザーアカウント設定完了](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985158/5e69a640-570a-00b3-0732-7a02f225dfb8.png)

Clientsの選択後、Client type:OpenID Connect/Client ID:myclient と入力し、Saveする。
![Clients設定](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985158/3949180b-1ed0-1201-da26-c892c3a62b76.png)

その後、Access settings内の２つの項目をKeycloak公式アプリに設定する。
```
Valid redirect URIs: https://www.keycloak.org/app/*
Web origins: https://www.keycloak.org
```
![設定](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985158/9da7030b-dd75-3d23-ac18-65bae7cfd8f4.png)

### 動作確認と設定ミス時の画面例
下記公式アプリに対して、作成したrealmとClientを設定してSaveを行い、Sign inする。
これで、動作確認は完了です！
https://www.keycloak.org/app/
![Sign in](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985158/e94ba794-14b8-0b9e-fcc1-dcaa93c8667e.png)


どこかで設定などを間違えている場合は、下記のようなエラーが出ます。エラー文が出ているので、これを確認しつつ、ハンズオンを読み返しながら、再確認しましょう。
![Error](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985158/b4a3d301-2c81-9e80-0235-6744e1518491.png)


加えて、詳細な機能ごとのハンズオンガイドなどは下記から学習することができます。
https://www.keycloak.org/guides#server

# 終わりに
今回は、OSSとして後発で開発された認証認可ソフトウェアを試してみました。
OAuth2.0の学習のおまけとして、よければ取り組んでみてください！
iOSアプリ開発で始めるLint駆動開発

私がコードレビューをするとき、文字や文体の誤りや不備はあまり重視していません。それらを確認するのは IDE や静的解析ツールの責務として考えているので、人間は API の使い方やアルゴリズムなどを確認すれば良いと考えています（ただ実際は見る場合も多い）。静的解析で解決できる問題は、機械にやらしたい。そのために Lint は整備したい、Linterに指摘して欲しい。本記事は Lint 関連で私がやることを紹介します。

## Xcode

開発を進めていくと、非推奨の関数が発生することがあります。いま入れ替える必要はないけど、いつか入れ替えたい。そのときは、Xcode の機能を利用します。

```swift
@available(*, deprecated, message: "show() を使ってください", renamed: "show")
func showDog() {
    print("name: \(name)")
}
    
func show() {
    print("name: \(name)")
}
```

![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24345/6c51d84e-ff3d-9cda-170c-a17c3446c8e6.png)

ありがとう、Xcode。関数の置換が分かりやすいですね。

## SwiftLint

上記例は自作した関数に対してですが、標準ライブラリが提供する API に同様の制約を付けるのは難しいです。その場合は、サードパーティーの Lint ツールでカスタムルールで対応します。

例として、ある架空の開発チームにおいて、配列の要素を追加する場合に `append()` ではなく `append(contentsOf: )` を使うという独自のチームルールがあったと仮定します。

```swift
class LintRule {
    
    var list: [Int] = []
    
    func append() {
        // NG にしたい
        list.append(1)
        list.append(2)
        list.append(3)
        
        // OK にしたい
        list.append(contentsOf: [1, 2, 3])
    }
}
```

このルールの厄介なところは、`append()` でも `append(contentsOf: )` でもビルドはできるので、ビルドエラーで検出できません。目視が必要になります。しかし人間には限界があります。

そこで、Lintを使って自動検出しましょう。今回は SwiftLint を使用しました。`append` を `contentsOf` なしで使用している箇所を表す正規表現を書いてあげれば、大丈夫です。

```yml
# カスタムルール
custom_rules:
  # append() ではなく append(contentsOf: ) を使うように設定する
  must_use_append_contentsOf:
    included: "LintDrivenDevSample\/.+\\.swift"
    name: "must use append(contentsOf: )"
    regex: "\\.append\\((?![\\s]*contentsOf)"
    match_kinds:
      - identifier
    message: "要素追加は append() ではなく append(contentsOf: ) を使ってください"
    severity: error
```

![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24345/38c671af-69f3-f717-75f7-9fc09639aaa3.png)


無事に Lint エラーがでたので、`append()` を `append(contentsOf: )` を置換箇所が静的解析で分かりました。ありがとう、Lint。

## まとめ

最近は Apple Silicon の登場でビルド時間が短縮されて開発環境はよくなりました。ただ、ビルド前に分かれば、より時間の短縮に繋がります。事前の静的解析でよい開発体験をしましょう。今回のサンプルは [mitsuharu/LintDrivenDevSample](https://github.com/mitsuharu/LintDrivenDevSample) で公開しています。

## おまけ

このサンプルプロジェクトを作る際に SwiftLint の GitHub を覗いてたところ、つい最近 (11/30) に Swift Package Manager Plugin に[対応]([https://github.com/realm/SwiftLint/pull/4603](https://github.com/realm/SwiftLint/pull/4603))してました。やったね！

<details><summary>導入例</summary><div>

まだ main ブランチしかなので、mainブランチか対応する　commit ab143685a4fce456183565e302fbaa47cd3e8d83 を指定します

![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24345/977805c0-e408-a714-65ed-75abd40f6682.png)

チェックは不要で追加します

![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24345/afb89ab2-efd8-79d6-8aa9-c821a6f8a0de.png)

TARGETS から Buikd Phases の Run Build Tool Plug-ins で SwiftLintPlugin を追加すればOKです

![05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24345/0dd7a092-dac3-4808-8b42-a552cd67ce72.png)
</div></details>
【Swift】初心者のランダム通話アプリ開発奮闘記 #6

# 今日の積み上げ
MapKit ライブラリを使って、地図情報をプレビューに表示させたかった。。
が、質問させていただいた通り、なぜかプレビューに期待値通りの地図情報が表示されないという事象が発生。。
お得意の10分分からなければ、質問する精神で、Qiitaに爆弾投下
https://qiita.com/pilloty/questions/238df6c73a017434d539

推しがいるメイドカフェの座標を表示させることが今後の目標です！！

![Xcode.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/997222/828b8b1a-2794-bc4f-737e-ed6367fadd85.png)