OmniAICreator/Qiita-1.07M huggingface dataset:
GitHub Actions でファイルの存在チェックをして、存在しない時にエラーにする


[`hashFiles`に](https://docs.github.com/en/actions/learn-github-actions/expressions#hashfiles)存在しないファイルパスを渡すと空文字を返すので、　`if` でチェックして `exit 1` すればいい。

```.github/workflow/hoge.yml
name: hoge
on: workflow_dispatch
  inputs:
    deploy_env:
      description: deploy env
      required: true
# 省略..
jobs:
  some_job:
    runs_on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@2

      # 例えば環境変数ファイルを作る処理とかがこの辺に入る

      - name: File exists?
        if: ${{ hashFiles(format('.env.{0}', github.event.inputs.deploy_env)) == '' }}
        run: exit 1
```




と思ったけど普通に[ `test` すれば](https://atmarkit.itmedia.co.jp/ait/articles/1807/05/news041.html)いいだけか。。
【React】外部リンクに飛ぶ方法【Javascript】

<h2>外部のページに飛びたい</h2>
ReactでSPAアプリ作成時にReactRouter外の外部のページに飛びたい。
しかし、useHistoryやLinkでは飛べない。

そういう場面に直面して解決したのでその方法をここに記します。

<h2>実装方法</h2>

```react:リンクで飛ぶ
//現在のタブで開く
<a href="https://www.google.com/">Text</a>
//新しいタブで開く
<a target="_blank" href="https://www.google.com/">Text</a>
```

```react:何らか処理後に飛ぶ
export const Hoge () => {
  
  現在のタブで開く
  function onClickHandleA () {
    window.location.replace("https://www.google.com/")
  }

  //新しいタブで開く
  function onClickHandleB () {
    window.open("https://www.google.com/", '_blank');
  }

  return (
  <div>
    <div onclick={onClickHandleA }>
      Text
    </div>
    <div onclick={onClickHandleB }>
      Text
    </div>
  </div>
  )
}
```

<h2>参考</h2>

https://isolution.pro/q/so55912464/react-router-gaibu-rinku
plutoによるdeprecation/removalの自動検知

Kubernetesクラスタをバージョンアップする際にマニフェストを[deprecation-guide](https://kubernetes.io/docs/reference/using-api/deprecation-guide/)を参照しており、適宜grepしながら確認していく作業を自動化したかったので、[pluto](https://github.com/FairwindsOps/pluto)で解決できないか試した。

以下はその備忘録。

## plutoとは

https://github.com/FairwindsOps/pluto

このツールが生まれた背景はREADMEにも記載されているが、

- 新たにリリースされたKubernetesの非推奨/廃止APIの使用箇所を検出することは困難。
- api問い合わせ時にetcdに意図しない形で保持されてしまう危険性がある。（ちゃんと追えてないので間違ってたらごめんなさい)

## 今回やらないこと

ArgoCD + Helm Chartで管理しているため、`detect-helm`によるチェックは行わない。

## 検証

公式の[Installation](https://pluto.docs.fairwinds.com/installation/#binary)に従いインストール。

```
$ brew install FairwindsOps/tap/pluto
$ pluto version
Version:5.1.1 Commit:188501530c46948d0062d7a3a78c730edcb79cab
```

以下は`detect-files`の実行例。
再帰的にディレクトリ内のマニフェストをチェックしてくれる。

```
pluto detect-files
NAME            KIND      VERSION              REPLACEMENT            REMOVED   DEPRECATED  
xxxxxxxxxxxxx   Ingress   extensions/v1beta1   networking.k8s.io/v1   true      true        
xxxxxxxxxxxxx   Ingress   extensions/v1beta1   networking.k8s.io/v1   true      true        
``    
```

## 自動化について
[pluto | Github Action Usage](https://github.com/FairwindsOps/pluto#github-action-usage)を参考にして、
今回はCI時に変更を検知した場合にpr-commentで通知するようなケースを導入した。

以下は最小限のCI。

```yaml
  check-kubernetes-manifest:
    runs-on: ubuntu-latest
    name: check k8s manifest
    steps:
      - name: Checkout
        uses: actions/checkout@v2
        with:
          fetch-depth: 0
      - name: Download Pluto
        uses: FairwindsOps/pluto/github-action@master
      - name: Use pluto
        id: pluto
        run: |
          pluto detect-files
```

次に自分が良いと思ったケースを参考程度に。
`pluto detect-files`実行時に検知した場合は、CI時にPRに対してコメントを行い、変更を促すようにした。
PRへのコメントは[mshick/add-pr-comment](https://github.com/mshick/add-pr-comment)を利用させていただいた。

```yaml
#　略
      - name: Use pluto
        id: pluto
        run: |
          # 複数行にわたる出力の変数化はこのように書く
          echo 'content<<EOF' >> $GITHUB_ENV
          pluto detect-files -d kubernetes -o json | jq >> $GITHUB_ENV
          echo 'EOF' >> $GITHUB_ENV
          
          # exit statusを元に後続のstepを実行
          pluto detect-files -d kubernetes
      - uses: mshick/add-pr-comment@v1
        if: failure()
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          message: |
            ## Pluto detect deprecation/removal
            Fix from the documents below.
            [Kubernetes | Deprecated API Migration Guide](https://kubernetes.io/docs/reference/using-api/deprecation-guide/)
            ```json
            ${{ env.content }}
            ```
          repo-token: ${{ secrets.GITHUB_TOKEN }}
          repo-token-user-login: 'github-actions[bot]'
          allow-repeats: false
```

## おわりに

Plutoいいよーって話と、それだけだとありふれているので、検知した場合の利用ケースについても紹介しました。
ArgoCD + Helm Chartの場合にうまく検知できる方法はないかと模索中だったが、やらないことに決めてます。
理由はRenovateでHelm Chartのバージョン更新を検知して、常に最新になるような運用にこれからしてく予定だからです。。。
その辺はまた今度まとめようと思います。

## 参考
- https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#multiline-strings
- https://kubernetes.io/docs/reference/using-api/deprecation-guide/
- https://pluto.docs.fairwinds.com/
webpackのバージョンを上げたらBabelを使っていてもIEで表示ができなくなった

## 事象

Webpack4系でBabelを使ってIE11対応を行なっていたが、Webpackを5系にあげるとバベってくれなくなった。
ビルドされた成果物を見ると、たしかにアロー関数が残っている。

## 原因

Webpack側で明示的に指定が必要になりました。

https://webpack.js.org/migrate/5/#need-to-support-an-older-browser-like-ie-11

以下を`webpack.config.js`に追加することでなおりました。

```webpack.config.js
module.exports = {
  const settings = {
    target: ['web', 'es5']
  }
}
```

はよIEなくなってくれ〜
ミュータブルなクラスとイミュータブルなクラス

# (イ)ミュータブルとは？
作成した時の状態から更新できるかの違いです。
特別な理由がない限り、イミュータブルなクラスとすることを勧めます。

| | ミュータブル | イミュータブル |
| ---- | ---- | ---- |
| 更新 | ○ | × |
| 値の入れ方 | setter | constructor |

# ミュータブルなクラス

```java
/*
 * 単純な構造体となってしまいがち
 * (データの出し入れだけで振る舞いがない)
 */
public class User {
    private String firstName;
    private String familyName;

    /** constructor */
    public User() {}

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getFirstName() {
        return this.firstName;
    }

    public void setFamilyName(String familyName) {
        this.familyName = familyName;
    }

    public String getFamilyName() {
        return this.familyName;
    }
}

public class 山田太郎 {
    private User user;

    /** constructor */
    public 山田太郎() {
        User user = new User();
        /*
         * Bad: コード上では入れ忘れを検知できない
         */
        // user.setFirstName("太郎");
        user.setFamilyName("山田");
        this.user = user;
    }

    public String getFullName() {
        /*
         * Bad: 不要な更新ができてしまう
         */
        this.user.setFirstName("鈴木");

        /*
         * 利用側で処理を書きがち
         *   →色んな所に同じ処理が散らばる
         */
        return this.user.getFirstName() + this.user.getFamilyName();
    }
}
```

# イミュータブルなクラス

```java
/*
 * 単純な構造体ではないので、必要なモノの取捨選択ができる
 */
public class User {
    private String firstName;
    private String familyName;

    /** constructor */
    public User(String firstName, String familyName) throws Exception {
        /*
         * Good: 生成時に整合性の判断ができる
         *         →ここで判断できない場合は利用側に任せることとなる
         */
        if (Objects.isNull(firstName) || Objects.isNull(familyName)) {
            throw new Exception();
        }

        this.firstName = firstName;
        this.familyName = familyName;
    }

    public String getFullName() {
        return this.familyName + this.firstName;
    }
}

public class 山田太郎 {
    private User user;

    /** constructor */
    public 山田太郎() throws Exception {
        /*
         * Good: コードで入れ忘れを検知できない
         * Bad?: 引数が膨大となる可能性がある
         *         →設計を見直すきっかけとなる
         */
        this.user = new User("太郎", "山田");
    }

    public String getFullName() {
        return this.user.getFullName();
    }
}
```
[Kotlin]委譲を掘り下げる

##はじめに
度々出てくる委譲を良く分からずに使ってしまっているので、掘り下げたいと思います。
##委譲とは？
一言で表すと、「任せる」すること。
あるオブジェクトが、他のオブジェクトの処理を委託します。
##継承との違い
まず、継承とは親クラスのメンバをオーバーライドする形で機能を引き継ぐことです。
某ピンク饅頭キャラのように親の機能を「コピー」します。
親の機能を完コピした子クラスは、自分ものとしてメソッドを使うことができます。

そして、委譲とは子が親の機能に「委託」することです。

これが、ざっくりとした違いです。

##メリデメの話
これだけだと、抽象的すぎるのでメリットとデメリットを整理しておきましょう。

###継承のメリット
- コードの再利用が簡単

###継承のデメリット
- 変更時に影響範囲が継承先に広がることがある

###委譲のメリット
- 親の機能や責務を引き継がなくて済む

###委譲のデメリット
- 「任せる」分だけインスタンス生成が必要

##どんな課題を解決してくれるのか？
委譲のメリットにもあるように、親クラスの機能や責務を引き継がなくて済むことがあります。
Androidだと、Activity/FragmentでViewModelを委譲としてインスタンス化すると思います。
それも、責務が混在しないためにやっているのだなと改めて思いました。

##おわりに
思うところがあれば、追記していきます。

そんなに大した概念ではないかなと思うのですが、意外とメリデメ分かってないのでそこの整理が出来て良かったです。
Kotlinでは、`by`を使えば簡単に委譲を実現できます。

##参考
https://blog.y-yuki.net/entry/2019/05/31/003000

https://tomosoft.jp/design/?p=3444

https://ikenox.info/blog/inheritance-and-delegation-and-interface/
AWSの資格を二つ取得して感じたこと

みなさんこんにちは、グリドンです。

前回の記事を読んでくださった皆さん、ありがとうございます。
前回の記事から、気づけば1年が空いてしまいました。みなさんは、2021年良い年になったでしょうか。


さて、今回は2021年滑り込みでAWS Certified Developer - Associateの資格を取得したので、どのように資格取得に挑んだかを書こうと思います。

#AWSの試験とは
簡単に説明すると、Amazon Web Services（AWS）が提供している、クラウドのサービスの理解度を図る試験です。
認定レベルはいくつかあります。

- 基礎コース
- アソシエイト ←<font color="red">今回私が受験したレベル</font>
- プロフェッショナル
- 専門知識

AWSに全く詳しくなかった一年前は、基礎コースの「クラウドプラクティショナー」の資格を取得しました。
「クラウドプラクティショナー」の試験、まだAWSについて詳しくしらない方などにはおすすめ。また、試験に合格すると次回の試験料が半額になるクーポンももらえます。
難しいレベルになればなるほど、試験料が上がるのでこちらの試験を先に取得すると良いと思います。

詳しく知りたい方は、[こちら](https://aws.amazon.com/jp/certification/)のURLを参考にして下さい。

#どのように勉強したか
以前、クラウドプラクティショナーの資格を取得した時もそうなんですが、僕は基本的にUdemyで勉強します。
他のオンライン授業サービスを利用したことはないので、どれが一番良いかなど比べての評価はできませんが、
Udemyはたくさんの講師の方がいて、自分の好きな講師を選ぶことができるので、Udemyが好きな一つの理由です。
<ins>今回私が受講したのはこちらのコース</ins>
https://www.udemy.com/share/101WES3@8MkoBjAew9IyD6eFeeAPtg3-lWrUv76uun-CVWK0dIkpuD9shpwgQLpARPUdc8pH/
 
正直に言うと、、、
あまりよくなかったです。
まあ、安い時で1000円ちょいだったので、文句をいうこともできませんがw
何が具体的に悪かったかと言うと、

- 何を言ってるのかわからない（アクセントの問題）
- 教える内容が薄い
- 付属のテストの内容が薄い（グラマーミスとかも多かった）

正直、これだけで本番受けるのは心配でした。

なので、下記の模擬試験を追加で購入しました。
https://digitalcloud.training/courses/aws-certified-developer-associate-practice-exams/
この人は、Udemyでも授業を複数提供していて、クラウドプラクティショナーの勉強はこの先生の授業を受講しました。

追加で購入した問題集のよかった点は、

- 本番に近い問題がたくさん出てきた
- 隙間時間にやりたいだけ問題を解くことができた

と、個人的には買ってよかったと思います。

スマホで見にくかったり、どれぐらいやったかの進捗がうまく保存されなかったり、使いづらい所もありましたが、
本番で同じような問題も出てきたし、合格できたのはこの問題集のおかげかと思います。


#試験の予約方法
試験の予約方法は、下記のリンクに詳しく載っています。
https://aws.amazon.com/jp/certification/certification-prep/testing/

私は、Cloud Practitionerも、Developer Associateも自宅でオンラインで受験しました。
動作など遅いな〜やりにくいな〜と感じることもありますが、やはり自宅で受験したい時にできるのは非常に便利です。

ちょっとした裏技ですが、英語で受験すると追加で30分受験時間を与えてもらえます。
あと、試験管も英語で選ぶと試験時間の選択肢も広がるので、英語が可能な人は英語での受験をおすすめします。


#試験当日
上記で登録した試験当日にパソコンでログインします。
9時からの場合、チェックインなど時間がかかる場合があるので30分くらいは早めにチェックインを開始することをおすすめします。
初めて受験した時ですが、チェックインに待ち時間があり開始時刻が大幅に遅れることがありました。
当日このようなことが起きると、精神てきによくないので余裕を持ってチェックインを開始して下さい。

結果は、試験をサブミットした時点で画面に表示されます。
正式な通知はその日または次の日には、送られてきて証明書のダウンロードも可能です。

#まとめ
以上、私のAWSの試験記録でした。
これから試験を受ける方の少しでも参考になれば嬉しいです。
AWS Cloud Practitioner Essential まとめ6

# [AWS Cloud Practitiner Essential] (https://explore.skillbuilder.aws/learn/course/1875/play/27620/aws-cloud-practitioner-essentials-japanese-ri-ben-yu-shi-xie-ban) 殴りがき

## Amazon CloudWatch

クラウド内で使っているサービス(AWS インフラストラクチャ) も クラウド内で実行しているアプリケーション(自分達のサービス)もどちらも監視・可視化できる。

- 一元的な場所からすべてのメトリクスにアクセスできる -> 分散した監視対象を一括して可視化できる。
    - AWSのクラウドサービス
    - クラウド内で実行するアプリケーション
    - オンプレミスのアプリケーション　など。
- MTTRを短縮できるため、コストが下がる。

### ダッシュボード
ClaudWatchで監視しているものをダッシュボードで一覧できる。

### Amazon CloudWatch アラーム
監視したいメトリクスを指定して閾値を設定するだけ。
閾値を上回った・下回った場合にアクションを実行するアラームが作成できる。
<b>メトリクス: リソースに関連付けられている変数</b>
アマゾンSNSと統合できるため、アラームと通知を同時にできる。

ex: EC2を停止し忘れるのを防ぐため、EC2のCPU使用率が一定の閾値を下回った(使用していないと判断できる)際に、自動的に停止するアラームを作成できる。


## AWS CloudTrail

<b>AWS環境内で発生したユーザーアクティビティとAPIコールの詳細を確認できる</b>
AWSへのすべてのAPIリクエストを記録する。誰が・いつ・何を・どのように。
ログは、S3のバケットに無制限に保存する。

- 監査の際の証明となる。
- 記録する情報は
    - APIコール元のID
    - APIコール時刻
    - APIコールもとのソースIPアドレス　など。(何を使ってリクエストを送ったのかわかる。)
    - APIの事象
- イベント発生後15分以内に記録される
- 閲覧時は、各情報を絞り込みができる。

### CloudTrail Insights
CloudTrailのオプション機能。
<b>AWSアカウントの異常なAPI実行を自動的に検出できる。</b>

## AWS Trusted Advisor
AWSサービスを使う上でベストプラクティスに基づいて適切な方針を自動アドバイスしてくれる。
以下の項目についてそれぞれアドバイスをくれる。

- コスト最適化
- パフォーマンス
- セキュリティ
- 耐障害性
- サービスの制限

カテゴリの評価は以下の通り。

- 緑: 問題が検出されなかった
- オレンジ: 調査が推奨される
- 赤: 修正アクションが推奨される
ローカル端末に接続したデバイスをリモート端末で使う方法


# はじめに

Azure上に構築したサーバーにアプリをインストールしようとしたものの、アプリをDVDからインストールする必要があったので、その際に「ローカル端末のデバイス（※この時はDVDドライブ）をリモート端末で使う方法」を調べて実践してみました。

コロナ禍になってから自宅でのリモートワーク（テレワーク）が多くなりましたが、「自宅でリモートワーク中に社内のPCやサーバーでローカル端末上のデバイスを使う」という際にもこの方法を利用できると思います。

# 手順

* リモートデスクトップ接続の画面を開き、さらに［ローカルリソース］タブを開いて、［ローカルデバイスとリソース］内の［詳細］を押します。

![image (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/ab419774-86ae-fd55-54ab-9a047de6303e.png)

* ［ローカルデバイスとリソース］の画面で、リモート端末で利用したいデバイスにチェックを入れます。
 * ここではBD-REドライブ（Dドライブ）を指定しています。

![image (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/c2e19ebe-aa5f-6fa5-2e2b-98ad44206309.png)

* ここまで設定した状態でリモートデスクトップ接続を実行すると、リモート端末のエクスプローラー上において、ローカル端末上のデバイスが［リダイレクトされたドライブとフォルダー］という項目に表示されます。
 * ここでは［NKOJIMA-HP830のD］という名前になっています。
* 新たにリモート端末に接続されたデバイスがDVDドライブなどの場合、このデバイス上のインストールメディアからアプリをインストールすることも可能です。

![image (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/90359585-da40-a7e7-d61a-92c6d336e00d.png)


# 参考URL

* [Azureに構築したVMで、ローカルマシンの物理DVDドライブに入れたディスクを認識させることはできますか？](https://social.msdn.microsoft.com/Forums/ja-JP/338fdd79-b9d0-4c87-9024-b8e28e01c91f/azure1239527083316891237512383vm123911228912525125401245912523125?forum=windowsazureja)
ARでメタバース 巨大ロボットを出現させる 

#大迫力の３Dオブジェクトを操作する方法

<img src=https://user-images.githubusercontent.com/23278992/124874290-83292400-e002-11eb-948f-13302a5806ed.gif>

#コンピュータのパワーでよりパワフルなコンテンツを

ARってなんだか難しそうな印象ありますか？

#ARKitを使ってスマホでかんたん表示

実はかんたんだったりします。
AppleがARをかんたんに扱えるフレームワークを出してくれています。

#手順
アップルのサイトからUSDZモデルを手に入れます。
https://developer.apple.com/jp/augmented-reality/quick-look/

ロボットという名前のUSDZファイルを読み込んでシーンに追加します。

```swift
guard let robot = try? Entity.load(named: "robot") else { return }
let anchor = AnchorEntity(plane: .horizontal) // 平面に配置する
anchor.addChild(robot)
arView.scene.addAnchor(anchor)
```

ロボットを100倍のスケールに大きくします。

```swift
robot.setScale([100,100,100], relativeTo: robot)
```

ロボットを動かします。

```swift
for animation in robot.availableAnimations {
    robot.playAnimation(animation.repeat()) // 歩行アニメーション
}

robot.move(to: Transform(translation: [0,0,20]), relativeTo: robot, duration: 4, timingFunction: .easeInOut) // 実際に移動させる
```

詳しいサンプルコードはこちら

https://github.com/john-rocky/RealityKit-Sampler

#ゲームや、映像、舞台インタラクションなど様々なコンテンツに

ARコンテンツを表示するのは意外とかんたんです。色々な表現の可能性を探りたいですね。

🐣
****
フリーランスエンジニアです。
お仕事のご相談こちらまで
rockyshikoku@gmail.com

Core MLやARKitを使ったアプリを作っています。
機械学習／AR関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
ArcGIS Onlineでのベクトルタイルスタイル（matchとcaseは使えない？）

## はじめに
これまでに自分のベクトルタイルをArcGISオンラインで表示する方法をためました。次は、ArcGISで表示するためのベクトルタイルスタイルの作業が必要です。

過去、match等の表現が上手く表示されなかった経験があったので、本当に使うことができないのか改めて実験してみました。
（matchを上手に使うと、単一のスタイルレイヤーから、異なる色や線幅の表現が可能になります。その結果、大幅にスタイルレイヤ数を減らすことができるというメリットがあります。）

## 環境
* nodejsのローカルホストサーバーを立ち上げ、VectorTileServer用のindexとresources/styles/root.jsonを準備。(こんな感じのサーバーです。→　[レポジトリ](https://github.com/ubukawa/imadegawa))
* ベクトルタイルはオフィスのArcGIS Onlineで実験（ArcGIS API for JavaScriptのバージョン不明。4でないかもしれません。）





## 実験結果

### Filterでのmatchの利用
まず、ポリゴンデータで、gridcodeの20,30,80をもっているものだけtrueにするというフィルターでよく使うmatch表現を試してみました。以下のものです。

```
      "filter": [
        "match",
        [
          "get",
          "gridcode"
        ],
        [
          20,
          30,
          80
        ],
        true,
        false
      ],
```

この結果、私の環境のArcGIS Onlineではベクトルタイルを地図上にロードできませんでした。しかし、この場合は、以下の表現ならArcGISでもOKです。

```
      "filter": [
        "any",
        [
          "in",
          "gridcode",
          20, 30, 80
        ]
      ],
```


## paint
次に、ペイントの中で色の種類を変えられるか試してみました。色が変えられれば線の太さなども同様だと思うので実験はfill-colorのみで行いました。

```
      "paint": {
        "fill-color": [
          "match",
          [
            "get",
            "gridcode"
          ],
          20,
          "#DAEDD0",
          30,
          "#ECF3DD",
          "#F6EFEF"
        ]
      },
```

この結果、私の環境のArcGIS Onlineではベクトルタイルを地図上にロードできましたが、ポリゴン（Fill）の色は出てきませんでした。Fill colorのところが理解されていないようです。

次は、例えばcaseは使えるのか試してみました。

```
      "paint": {
        "fill-color": [
          "case",
          [
            "has",
            "gridcode"
          ],
          "#DAEDD0",
          "#F6EFEF"
        ]
      },
```
この結果も表示されませんでした。caseは少しパターンを変えて下も実験しました。

```
        "fill-color": [
          "case",
          [
            "get",
            "gridcode"
          ],
          20,
          "#DAEDD0",
          "#F6EFEF"
        ]
```

これも表示されませんでした。

## その他
他のArcGIS Online用のスタイルを見てみました。
例えば、ArcGISのLivingAtlasのベクトルタイルスタイルを見ても（例えば[こちら](https://basemaps.arcgis.com/arcgis/rest/services/World_Basemap_v2/VectorTileServer/resources/styles)）一つのスタイルレイヤで複数の色や線幅を表現しているものはないようです。

## 結論
私の環境では、matchとcaseは使うことができませんでした。
したがって、ArcGIS Online用のスタイルは、基本的に「一つのレイヤで一色（あるいは一種類の線幅）」と考えた方が良さそうです。
（ただし、ベクトルタイルのデータの中に描画情報を入れて、それを直接参照する形にすれば一つのレイヤでも好きなように表現できるかもしれませんね。）

注意：
環境の違いや、書き方の違いなどで、もしかしたら可能なのかもしれません。ここでのメモは、あくまで私が実験してみた結果のメモです。

## 参考文献
[ESRI LivingAtlas world basemap v2 Style](https://basemaps.arcgis.com/arcgis/rest/services/World_Basemap_v2/VectorTileServer)
AppArmorでApache用のプロファイル作る

## AppArmorとは
プログラムごとにファイルアクセス、システムコール等の制限(強制アクセス制御 MAC)を行うLinuxモジュールで、ubuntuには最初から入っている。
アプリの作り込みが甘い、ApacheやPHP等のゼロデイで任意コード実行される、等仮にあっても変な場所へアクセスするのを外的に防いでくれる。
多層防御のために重要で、是非設定しておきたい。
※例えば脆弱性によるWebShell設置などは当然パーミッション設定でも防ぐべきだが、仮にそこが漏れてもAppArmorで書き込み許可していなければ弾いてくれる

制限ルールは「プロファイル」として実行ファイルごとに作る。
少なくともubuntu 20.04ではApache用プロファイルはout of the boxの形では無いが、共通部分はパーツとして用意してくれているので、これと学習ツールを使ってプロファイルを作る。
難しそうだが実は割と簡単にできる。
(おそらく環境により必要なルールが変わるので、デフォルトを用意しても制限キツすぎて脳死で除外されるか、ガバガバで無意味になるかにしかならないと思う)

なお、apacheから他のプログラムを呼び出すような場合も、親プロセスのルールを継承させることもできるし、別プロファイルに切り替えることもできるため、問題なく使える。

## インストール
そのものはubuntuに一体で入っているが、ツールはインストール必要。

```
sudo apt install auditd apparmor-utils
```

## プロファイル作成
まずaa-genprofを使って実際のプログラムの挙動からルールを自動生成、その後に手でよしなに修正する。

### Step 1 自動生成
```sudo aa-genprof /usr/sbin/apache2``` で学習状態に入るので、apacheにアクセスして色々なアクセスを実施。
起動時のみアクセスするファイルなどもあるので、別ターミナルでapacheの停止・起動もしておく。
終わったら (S)can を指定して今までの挙動から提案されるルールを取捨選択していく。
終わったら(F)で終了。


* 可能ならファイル単位ではなくワイルドカードでフォルダ単位指定をしてシンプルに(Globを選ぶ)
  * /var/www/html/myproject/** r など
* 権限は最小限に。書き込み(w)、実行(x)は特に。
  * /var/www/html/myproject/logs/* rwk のように必要な箇所だけ付与
* 一般的に使われるルールの固まり(abstractions)が用意されており、これが使そうなら提示してくれるので可能ならそれを選ぶ (中身は/etc/apparmor.d/abstractions/にある)

### Step 2 手修正
Step1で出来たルールが/etc/apparmor.d/usr.sbin.apache2に出来ているので、globで纏めたり、広すぎる許可を狭めたりの手調整を行う。
ターゲットやrwxk等の権限設定の書き方は[公式ドキュメント](https://gitlab.com/apparmor/apparmor/-/wikis/QuickProfileLanguage)を参照。


またフラグ attach_disconnected を追加したほうが良さそう。パス解決時に頭に/があるものとして見てくれるもので、無いとパス解決が上手くいかずDENIEDになる処理があった。

```
profile /usr/sbin/apache2 flags=(attach_disconnected) { #←このflags=(...)を追加
```

## 作ったプロファイルの読み込み
```
sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.apache2
```
以降 修正した場合の反映もこれ

## 設定適用
* 強制モード (enforce mode)
    * プロファイルで許可していないものは単純にアクセス禁止する。本番は当然こちら。
* 不平/学習モード (complaion mode)
    * 不許可アクセスのログだけ取得して実行は妨げない。いきなり禁止が怖い場合はこちらでしばらく動かしてみて、```aa-logprof```でログをスキャンして問題ないか確認する。

```
sudo aa-enforce /usr/sbin/apache2 #強制モード
または
sudo aa-complain /usr/sbin/apache2 #不平モード／学習モード(止めずにログだけ出す)

sudo systemctl restart apache2 #apacheも再起動しないと反映されない模様

sudo aa-status #設定状況の確認 complain/enforce modeにapacheが入っているのを確認する

```

## 確認
適当にfile_get_content()で許可している場所、許可してない場所のデータを読み込み、前者だけが読み込めることを確認する。

## ログ確認
auditd入れてあれば/var/log/audit/audit.logにログが出る。
無い場合はsyslogに吐かれる。
問題があった場合は```aa-logprof```でポリシーをアップデート →[ドキュメント](https://gitlab.com/apparmor/apparmor/-/wikis/AppArmor_Failures)

## SIEM(Wazuh)へのログ送信
(Wazuh 4.2時点)デフォルト設定でaudit.logから読み込んでくれる。
ただしパーミッションエラーのアラートレベルは低いようなのでアラート飛ばしたい場合は注意。
→ [アラートレベル変更方法](https://documentation.wazuh.com/current/learning-wazuh/replace-stock-rule.html)

## 補足
apache用にmod_apparmorというものも有るが、上記の通り別に無くても問題ない。
ハット機能を使って事細かく設定できるようなので、設定を詰めたい場合は便利だと思う。

## 参考
[AppArmor wiki](https://wiki.apparmor.net)
[ubuntu wiki](https://wiki.apparmor.net)
[mod_apparmor](https://gitlab.com/apparmor/apparmor/-/wikis/mod_apparmor)
composer require linecorp/line-bot-sdk導入時のエラー解決

#概要
composer require linecorp/line-bot-sdkのエラー解決。いくつかネット記事を回ったものの、同じ解決法をとっている人がいなかったので。

環境は以下です。
Cloud9
PHP 7.3.30
Laravel Framework 6.20.44

#エラー内容
```
$ composer require linecorp/line-bot-sdk
Using version ^7.3 for linecorp/line-bot-sdk
./composer.json has been updated
Running composer update linecorp/line-bot-sdk
Loading composer repositories with package information
Updating dependencies
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - Root composer.json requires linecorp/line-bot-sdk ^7.3 -> satisfiable by linecorp/line-bot-sdk[7.3.0].
    - linecorp/line-bot-sdk 7.3.0 requires ext-curl * -> it is missing from your system. Install or enable PHP's curl extension.

To enable extensions, verify that they are enabled in your .ini files:

///中略

You can also run `php --ini` inside terminal to see which files are used by PHP in CLI mode.

Installation failed, reverting ./composer.json and ./composer.lock to their original content.
```

#解決方法

### １、拡張curl導入（やる必要なかった）

エラーの内容から、拡張curlが無い、あるいは無効だからインストールに失敗したらしいと予想。

```$ sudo apt-get install php-curl
```
拡張curlはエラー無く導入できたと思われた。再度導入を試みるも同様のエラー。

###２、無効化されている可能性

導入と同時に有効化されるはずだが、php.iniで無効化されている可能性を考え、php.iniを開く。「extension=curl」で検索をかけるが見つからなかった。
以下コマンドで入ってるモジュールを調べたところ、そもそも拡張curlが入ってないらしい。どうやら１の段階で拡張curl導入に失敗していた。

```
$ php -m
[PHP Modules]
bcmath
calendar
Core
ctype
date
///後略
```

###３、再度コマンドを変えて拡張curlを導入
```
$ sudo apt-get install php7.3-curl
```
違うコマンドを見つけたので拡張curlの導入を再度試みる。

###４、line-bot-sdkを導入
```
$ composer require linecorp/line-bot-sdk
```
成功！　そういえばエラーのとこにもバージョン指定してあったね。見通しが立つのは早かったけど、コマンドを見つけるまでに時間がかかった。

#参考記事
大変お世話になりました。ありがとうございます。
参照日（2022/01/17）
https://qiita.com/____easy/items/06406fc62bd7464ad651
https://qiita.com/mktro/items/d164bd4a88fc51f2a99d
grepを使っての、空白行削除およびコメントアウト行削除した結果

grepを使っての、空白行削除およびコメントアウト行削除した結果を
表示する方法

```
grep -v "^$" /etc/ssh/sshd_config | grep -v "#"
```

https://qiita.com/notakaos/items/91d807f3151694e6c7a8
Azure Synapse Analyticsでデータをロードする時にファイルは分割した方がいい？分割しなくてもいい？

#データロード時のファイルは分割した方がいいか？分割しない方がいいか？
Azure Synapse Analytics SQLプールでCSVなどのファイルをロードする場合、ファイルは分割した方が高速にロードできるのか、分割しない方が高速にロードできるのか？
これは結論から言いますと、**「ロードするファイルが圧縮されているのか、圧縮されていないかによって異なる」**という事のようです。

このポイントについて実際にAzure Synapse Analytics SQLプールで検証を行ってみました。

#検証内容
TPCHの「lineitem」データをAzure DataLakeストレージに格納し、DataLakeストレージからSynapse AnalyticsへPolybaseを使ってロードしました。
ロードする件数は600,037,902件となります。
※ロード時のリソースクラスは「xlargerc」に指定。

以下4つのパターンで様々なDWUcにてロード処理を確認しました。

||ファイル分割数|1ファイルあたりの容量|圧縮あり|
|:-:|:-:|:-:|:-:|
|パターン１|60|約1.24GB|なし|
|パターン２|60|約375.45MB|gzip圧縮|
|パターン３|1|約74.11GB|なし|
|パターン４|1|約22.05GB|gzip圧縮|

パターン１はパターン３のファイルを60分割したものになります。
また、パターン２、パターン４はそれぞれパターン１、パターン３のデータをgzip圧縮したものになります。

#検証結果
今回は４つのcDWUにて検証を行いましたが結果は以下の通りです。

||パターン１(60分割、非圧縮)|パターン２（60分割、gzip圧縮）|パターン３(非分割、非圧縮)|パターン４(非分割、gzip圧縮)|
|:-:|:-:|:-:|:-:|:-:|
DW100c|36分59秒|39分11秒|31分56秒|51分01秒|
DW500c|6分30秒|5分39秒|6分16秒|41分46秒|
DW1000c|3分44秒|3分43秒|4分28秒|45分57秒|
DW2000c|2分7秒|1分42秒|2分10秒|44分53秒|


#検証結果からの考察
今回の検証結果からわかることは**非圧縮の場合は、ファイルは分割していようが、分割していまいがロードの時間に大差がない**という事です。
よって、非圧縮の時、ファイルが分割されていない場合には、内部で勝手にファイルが分割されパラレルロードしてくれているようです。

一方で**ファイルが圧縮（gzip）されている場合は、明示的にファイルを分割しなければパラレルロードされない**ようです。
今回の検証では圧縮されたファイルは、すべてのDWUcでAzure Synapse Analytics SQLプールの最小スペックである、DW100c相当のパフォーマンスしか出ませんでした。

なので、結論は以下の通りです。
##非圧縮のファイルのPolybaseによるロード
ファイルの分割はしてもしなくてもどちらでも性能に大差なし。
DWUcの値を大きくすれば、その恩恵を受けることが可能。

##圧縮したファイルのPolybaseによるロード
ファイルの分割を推奨。
ファイルを分割しなかった場合、DWUcを大きくしてもその恩恵を受けることが出来ず、DW100cのパフォーマンスとなる。

#最後に
今回の結果からは、非圧縮ファイルと圧縮ファイルでの動きの違いが確認出来ました。
結果だけでみると、非圧縮ファイルの方が、分割などの処理を検討する必要がないのでいいように思います。

ただ、今回の検証で着目したのはあくまで、__DataLakeストレージからSynapse Analyticsへのロード処理の部分__です。
一方で、システム全体のワークロードから考えると、非圧縮ファイルの場合以下のようなステップとなると思います。
__①非圧縮ファイルのDataLakeストレージへのアップロード__
__②DataLakeストレージからAzure Synapse Analyticsへのロード__

また、圧縮ファイルの場合のステップは以下の通りです。
__⓪ファイルの圧縮__
__①非圧縮ファイルのDataLakeストレージへのアップロード__
__②DataLakeストレージからAzure Synapse Analyticsへのロード__

ファイルを圧縮するのか、非圧縮のままでいいのかは上記の⓪~②までの全体のワークロードを鑑みて決定する必要がありそうです。
そして、**圧縮ファイルを取り込むとなった場合には、必ず分割を検討**した方が良さそうです。

ちなみにファイルを60に分割したのは、Azure Synapse Analytics SQLプールの__ディストリビューションの数が60__である為です。
一方で今回の検証から言えることは、ファイルの分割数は60ではなく、300に分割した方が理想的かもしれません。
これはDW6000c以上のDWUcになった場合に上手くリソースを使いきれない可能性があるためです。
（こんなに大きなDWUcで動かすことはめったにないので、そこまで気にする必要が無いかもしれませんが。。。）
Nuxt.jsにChart.jsを導入してグラフを表示する

## はじめに
Nuxt.jsを使用しChart.jsで棒グラフを作成する
プロジェクトがあったのでその備忘録
※API連携は次の記事で書きます

## 環境
macOS
Docker

## ゴール
国語、算数、理科、英語、社会(5教科)の
テストの点数をグラフにして表示
<img width="400" alt="スクリーンショット 2022-01-17 21.48.09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1986536/14d7d633-a2d7-ca08-8bac-5dbcec5ec40c.png">

## Chart.jsインストール
```
root $ docker-compose run front yarn add vue-chartjs chart.js
```

## BarChart.vue作成
Nuxt.jsのcomponentsディレクトリへChart.vueを作成

```
front $ touch components/BarChart.vue
```

```BarChart.vue
<script>
import { Bar, mixins } from 'vue-chartjs'
const { reactiveProp } = mixins

export default {
  extends: Bar,
  mixins: [reactiveProp],
  props: {
    chartdata: {
      type: Object,
      default: null
    },
    options: {
      type: Object,
      default: null
    }
  },
  mounted () {
    this.renderChart(this.chartData, this.options)
  }
}
</script>
```

## Chart.vueの作成(親ページ)

```
front $ touch pages/Chart.vue
```

```Chart.vue
<template>
  <v-main>
    <v-container>
      <v-row>
        <BarChart
          :chart-data="bar_data_collection"
          :options="bar_options"
        />
      </v-row>
    </v-container>
  </v-main>
</template>

<script>
import BarChart from '~/components/BarChart.vue'

export default {
  components: {
    BarChart
  },
  data () {
    return {
      bar_data_collection: { datasets: [], options: {} }
    }
  },
  mounted () {
    this.barFillData()
  },
  methods: {
    barFillData () {
      this.bar_data_collection = {
        labels: ['国語', '算数', '理科', '英語', '社会'],
        datasets: [
          {
            backgroundColor: [
              'rgba(255, 99, 132, 0.2)',
              'rgba(54, 162, 235, 0.2)',
              'rgba(255, 206, 86, 0.2)',
              'rgba(75, 192, 192, 0.2)',
              'rgba(153, 102, 255, 0.2)'
            ],
            data: [50, 60, 70, 80, 90, 70]
          }
        ]
      }
      this.bar_options = {
        title: {
          display: true,
          fontSize: 18,
          text: '学力確認テスト'
        },
        responsive: true,
        maintainAspectRatio: false,
        legend: {
          position: 'top',
          display: false
        },
        layout: {
          padding: 0
        },
        scales: {
          yAxes: [
            {
              ticks: {
                beginAtZero: true,
                min: 0,
                max: 100
              }
            }
          ]
        }
      }
    }
  }
}
</script>

```

## 備考
グラフのスタイルやオプションは数多くあるので
公式サイトを確認すると良いと思います→　[Chart.js公式](https://misc.0o0o.org/chartjs-doc-ja/)

以上、お疲れ様でした
Cloudflare PagesのGitクローン失敗（ an internal error occurred）

「git リポジトリのクローンを作成しています」のタイミングで毎回失敗する

```text
Initializing build environment. This may take up to a few minutes to complete
Success: Finished initializing build environment
Cloning repository...
Failed: an internal error occurred
```

# ファイル数 or ファイルサイズが原因

[Cloudflare Pages “Failed due to an internal error”](https://community.cloudflare.com/t/cloudflare-pages-failed-due-to-an-internal-error/262234/16)によるとGitリポジトリの総ファイル数か個々のファイルサイズが制限を超えると発生する。

- 総ファイル数：最大20,000個
- 最大ファイルサイズ：25MB

[Limits · Cloudflare Pages docs](https://developers.cloudflare.com/pages/platform/limits)
Vim-PrettierにはPrettierが入っていないだと…

![https://images.unsplash.com/photo-1513124130903-ea989a7706fd?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb](https://images.unsplash.com/photo-1513124130903-ea989a7706fd?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb)

VimでPrettierを使えるようにする手順のメモ。

### 対象読者

- Vimの初心者
- Macユーザー
- コード整形にPrettierを使いたい人
- VScodeのPrettierしか使ったことがなく、Prettierを単体でインストールしたことがない人


### 本記事でわかること

- Vim-Prettierのインストール方法
- Vim-Prettierの設定

それではまず、Vim-Prettierのインストール方法から説明していこう。

## Vim-Prettierのインストール方法

![https://images.unsplash.com/photo-1598970434795-0c54fe7c0648?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb](https://images.unsplash.com/photo-1598970434795-0c54fe7c0648?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb)

Vimのプラグインのインストールにはいくつか方法がある。ここではVimのバージョン８から標準搭載されたパッケージマネージャを使った方法のみ扱う。

次のコマンドをTerminalで実行：

```jsx
git clone --depth 1 [https://github.com/prettier/vim-prettier](https://github.com/prettier/vim-prettier) ~/.vim/pack/plugins/start/vim-prettier
```

実行後にいくつかダウンロードが行われ、次のディレクトリができているはずだ。

```jsx
~/.vim/pack/plugins/start/vim-prettier
```

続いて、Prettier本体をインストールしよう。

## Prettier本体のインストール

![https://images.unsplash.com/photo-1517384444713-ec340d75746d?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb](https://images.unsplash.com/photo-1517384444713-ec340d75746d?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb)

グローバルにインストールしたい場合：

```jsx
npm i -g prettier
```

ローカルにインストールしたい場合：

```jsx
cd ~/.vim/pack/plugins/start/vim-prettier
npm install
```

これでVimでPrettierを使う準備は整った。

次はVim-Prettierの使うための設定について見ていこう

## Vim-Prettierの設定

仮で`Index.js`という名前のファイルを用意する。

`Index.js`をVimで開いて、次のコードを記述：

```jsx
let array={0:"zero",1:"one"};
```

このコードをPrettierで整形：

- NOMARL modeに切り替え
- 次のコマンドを実行：
    
    `:Prettier`
    

すると、コードが次のように、スペースが追加されただろう。

```jsx
let array = { 0: "zero", 1: "one" };
```

もし:Prettierを実行後に次のエラーメッセージが出た場合、Prettierがインストールされていない。

```jsx
no prettier executable installation found
```

Prettier本体のインストールからやり直そう。

ただ、毎回整形するときに:Prettierと入力するのは面倒だろう。

条件に応じて自動で整形するように設定しよう

## Prettierを自動実行するための設定

![https://images.unsplash.com/photo-1483058712412-4245e9b90334?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb](https://images.unsplash.com/photo-1483058712412-4245e9b90334?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb)

vimrcファイルを開く：

```jsx
vim ~/.vimrc
```

次のコードをコピペでvimrcファイルにはりつけ：

```jsx
augroup fmt
autocmd!
autocmd BufWritePre,TextChanged,InsertLeave *.js,*.jsx,*.mjs,*.ts,*.tsx,*.css,*.less,*.scss,*.json,*.graphql,*.md,*.vue,*.svelte,*.yaml,*.html PrettierAsync
augroup END
```

これでPrettierが次の場合実行される。

- ファイルが保存される前
- テキストが変更された後
- INSERTモードから抜けた後

コードがキビキビ整形されて快感ではないだろうか？

## 余談

はじめVim-Prettierをインストールしたとき、Prettierが同梱されているものと思い込んでいた。

これまでVScodeでPrettierを使用していて、そのとき使っていたPrettierは拡張機能のインストールと同時にPrettier本体もインストールされていた（はず）ため、自らPrettierをインストールした経験がない。

思い込みによって、Vim-Prettier実行（:Prettier)にエラーメッセージが出ていたが、まさかPrettier本体をインストールされていないとは思わなかった。

[エラー内容を検索したところ、このQiita記事によって解決した。](https://qiita.com/73cha/items/aecb84af18eed9646f1c)

一応Vim-Prettierの公式ドキュメントにもPrettier本体がない場合はインストールするよう書いているが見落としていた。

こんなことで時間を消費しないようエラーメッセージの内容をよく解釈するよう気をつけたい。
querySelectorはdocument以外のElementでも使える

HTML

```HTML
<body>
  <div class="first-element">
    <div class="some-child">Hi!</div>
  </div>
  <div class="second-element">
    <div class="some-child">Bye!</div>
  </div>
</body>
```


JS

```javascript
const $second = document.querySelector('.second-element');
const $child = $element.querySelector('.some-child');
console.log($child.innerText);
// => Bye!
```

Reactだと↓のように使えたりして便利(子要素のref使えというツッコミはなしで
`ref.current.querySelector('.some-child')`
モジュール系のエラーが出たとき

#結論
とりあえず`yarn upgrade`を行う。
これをすれば大抵のモジュールエラーは解決すると思います。

自分も某colors.jsでエラーが出ていたところをアップデートしたら直りました。

#それでも直らない場合

一旦モジュールを入れる前まで戻してみるのも人流の手であると言えます。
gitのヒストリーを遡って確認してみるといいかもしれません。
Windows10にEmacs風キーバインドを設定する

ググると[AutoHotKey](https://www.autohotkey.com/)を使う方法が結構出てくるけど、公式ツールでできそうだったのでやってみる。Emacs風というかmacOS風のやつ

1. [Microsoft PowerToys](https://github.com/microsoft/PowerToys)をインストールする。
    - MSがオープンで開発してる公式のツールなので信頼性が高い気がする
1. Keyboard Manager でバインドし直す。
    - `ctrl(left)-a` -> `Home`
    - `ctrl(left)-b` -> `Left`
    - `ctrl(left)-d` -> `Delete`
    - `ctrl(left)-e` -> `End`
    - `ctrl(left)-f` -> `Right`
    - `ctrl(left)-h` -> `Backspace`
    - `ctrl(left)-k` -> `shift-End`
    - `ctrl(left)-m` -> `Enter`
    - `ctrl(left)-n` -> `Down`
    - `ctrl(left)-p` -> `Up`
    - `ctrl(left)-y` -> `ctrl-v`
    - `ctrl(left)-shift-j` -> `IME Convert`
    - `ctrl(left)-shift-;` -> `IME Non-Convert`
    - `win(left)-a` -> `ctrl-a`
    - `win(left)-c` -> `ctrl-c`
    - `win(left)-f` -> `ctrl-f`
    - `win(left)-n` -> `ctrl-n`
    - `win(left)-r` -> `ctrl-r`
    - `win(left)-t` -> `ctrl-t`
    - `win(left)-w` -> `ctrl-w` 
    - `win(left)-x` -> `ctrl-x`
    - `win(left)-p` -> `ctrl-p`
    - `win(left)-n` -> `ctrl-n`
    - `ctrl(left)-d` -> `ctrl(right)-d` (windowsterminal.exe)
    - `ctrl(left)-k` -> `ctrl(right)-k` (windowsterminal.exe)
1. 1. caps lock を ctrlに
    - これは[ctrl2cap](https://docs.microsoft.com/en-us/sysinternals/downloads/ctrl2cap)で。

問題点: 

- WSL使うときに困る。
    - バインドを変えたキーを押すと `^@` が送信される
        - eg. `ctrl-h` -> `backspace` をおしたとき、`showkey -a` で確認すると `^@        0 0000 0x00` がctrlボタンを**離したとき**に送信されてる。
        - https://github.com/microsoft/PowerToys/issues/6024 これに似てるけどちがうっぽい
        - **Windows Terminal 使うとこの問題起きない。**
    - Ubuntuのもともとのバインドとぶつかる
        - ctrl-d でターミナル切ったりするのがやりづらくなる
        - [プロファイル切り替え機能](https://github.com/microsoft/PowerToys/issues/1881)とか[除外するアプリをリストする機能](https://github.com/microsoft/PowerToys/issues/8809)のissueがあるので、いつかサポートされるかもしれない。
        - ハック的な方法。windowsterminal.exeにたいして元のキーバインドを上書きする。
            - たとえば`ctrl-d` をwindowsterminal.exeではバインドなしで、その他のアプリ上では `delete` にさせたいとき、
                - 「すべてのアプリ」を対象に `ctrl(left)-d` -> `Delete` をバインドする
                - 「windowsterminal.exe」を対象に`ctrl(left)-d` -> `ctrl(right)-d` をバインドする
- インポート/エクスポート機能がない
    - さまざまな環境をセットアップする場合はネックになりそう。
- ctrl-k で kill line みたいな高度なことはできない

OSが違うんだから、WindowsつかうときはWindowsの操作に慣れるというほうがいい気はするんだけど、アローキーをホームポジションを崩すことなく使えるバインドを使いたい気持ちにあらがえない時に。
LINEBotで社内の問い合わせに対応！‥したかった

#問い合わせ先がわからない！！

とある企業で社内のデジタル化を推進する部署に所属をしているかきもとと申します:relaxed:
日々の業務に取り組む中で**『これってどこの部署に聞いたらいいのか？』**と問い合わせ先を探すことがしばしば。店舗で勤務しているときは今以上に分からず、とにかくそれっぽい部署に連絡をしていました。

何かいいものが無いかと考えているときに出会ったのが、LINEbotです。
LINEbotに聞いて返事をしてくれれば、大変助かる！ということで作成してみようと思いました。

##使用したもの
・Heroku
・Node-RED
・Googleスプレッドシート

##Node-REDのフロー
![フロー.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2487483/451ea40a-d14f-4a01-8a19-248bfc0c291c.jpeg)


見様見真似で繋いでみました。
LINEで問い合わせ内容（単語）を入力すると一致した問い合わせ先を教えてくれます。
【例】レジ　⇒　ストアオペレーション部

##完成に至らなかった理由

![nakami.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2487483/7d3366d6-0031-34dc-ecbb-01c00c720801.jpeg)

正しく返答できなかった理由として、GoogleスプレッドシートのAPIを正しく取得できなかったことが考えられます。
Googleスプレッドシートのnodeを取得できたことに喜んだ初心者です。まだまだ先は長そう。

##作成を終えて
初めてLINEbotの作成をして5日間が過ぎました。まだ5日です。
いまは、身近なLINEを使用して身の回りの課題解決が出来るかも！という思いでいっぱいです。
とは思いながらも今回実装したかった動きをさせることが出来なかったので、まずはこれを完成させてみようと思います。

最後まで読んでいただきありがとうございました。
VSCodeのターミナルでnpmが認識されないときの対処法

Node.jsをインストールしたにも関わらず、VSCodeでnpm認識されなくて非常に困った。
コマンドプロンプトでは認識されており、当然、Windowsの環境変数でPATHも設定されている。

試したこと
①VSCodeの再起動
→ダメだった
②PCの再起動
→npmが認識されるようになった。

パスを通さないといけないかなと思って、いろいろ調べたけど理解できずに困り、苦肉の策でPCを再起動したら普通に認識するようになりました。
2時間くらいかけたな、、、

エンジニア初心者はつらい。。。
Javaインナークラスについて

## はじめに
今回はJavaのインナークラスについて調べました。
JavaGoldの勉強をした際に出てきたので、要点をまとめようと思いました。

## ゴール
インナークラスの役割と各インナークラスの違いについて理解する。

## インナークラスとは
クラス内に定義されたクラスのことをインナークラスと言います。

## インナークラスの役割とは
役割としては、情報隠蔽(カプセル化)を提供します。
公開する情報を最小化することで、想定していなかったような使われ方を防ぐことができます。

## インナークラスの種類
インナークラスの種類は大きく以下の4つに分けられます。

・インナークラス：クラスの中に定義したクラス
・staticインナークラス：staticで修飾したインナークラス
・ローカルクラス：メソッド内で定義したクラス
・匿名クラス：ローカルクラスで名前のないクラス

また、4つのクラスと修飾子の関係を下記の表にまとめます。

|      |  public  |  protected  |  private  |  abstract  |  final  |  static  |
| :----: | :----: | :----: | :----: | :----: | :----: | :----: |
|  インナークラス  |  ○  |  ○  |  ○  |  ○  |  ○  |  ×  |
|  staticインナークラス  |  ○  |  ○  |  ○  |  ○  |  ○  |  ×  |
|  ローカルクラス  |  ×  |  ×  |  ×  |  ○  |  ○  |  ○  |
|  匿名クラス  |  ×  |  ×  |  ×  |  ×  |  ×  |  ×  |


## 使用例

### ・インナークラス

```java
public class Outer {
    class Inner{
        public void test(){
            System.out.println("インナークラスです");
        }
    }

    public static void main(String[] args){
        Outer out = new Outer();
		Inner in = out.new Inner();
        in.test();
    }
}
```
実行結果

```
インナークラスです
```
インナークラスのインスタンスを生成するには、エンクロージングクラス(インナークラスを囲むクラス)のインスタンスを先に生成しておく必要があります。
 
### ・staticインナークラス

```java
public class Outer {
    public static class Inner{
        public void test(){
            System.out.println("staticインナークラスです");
        }
    }

    public static void main(String[] args){
		Inner in = new Inner();
        in.test();
    }
}
```
実行結果

```
staticインナークラスです
```
staticインナークラスはエンクロージングクラスのインスタンスがなくてもインスタンス化できます。

### ・ローカルクラス

```java
public class Sample{
	public static void main(String[] args){
		test();
	}
	public static void test(){
		class LocalClass{
			    LocalClass(){
				    System.out.println("ローカルクラス");
			    }
		}
		new LocalClass();
	}
}
```
実行結果

```
ローカルクラスです
```
ローカルラスはメソッドの中でクラスを宣言し、そのメソッド内のみで利用します。  
ローカルラスの定義は、ローカル変数と同様に、メソッドブロック内に記述します。


### ・匿名クラス

```java
class Sample{
	void test(){
		System.out.println("スーパークラスです");
	}
}
public class Main {
	public static void main(String[] args) {
		Sample sp = new Sample(){
			void test(){
				System.out.println("匿名クラスです");
			}
		};
		sp.test();
	}
}
```
実行結果

```
匿名クラスです
```
匿名クラスは、その場限りのサブクラスを定義し、オーバーライドしたメソッドを利用します。

## さいごに
インナークラスの役割と各インナークラスの違いについて理解できましたでしょうか？  
記事を書く際に、改めて要点をまとめられたので自身にとっても良いアウトプットとなりました。
AzureADとkintone(Cybozu)でSSOを構成する

#はじめに
AzureADをIDPとしてkintoneにSSO（シングルサインオン）を行うための設定を行いました。いくつかハマりポイントがあったので覚書です。

#手順
基本的には下記の通りに進めます。

https://docs.microsoft.com/ja-jp/azure/active-directory/saas-apps/kintone-tutorial

##[kintone]の環境構築

こちらからお試しの環境を作成して検証しました。

https://kintone.cybozu.co.jp/trial/

この時に下記のような形式のURLが発行されます。
```https://<companyname>.cybozu.com ```
##[AzureAD]SAML構成
チュートリアル通りに進めました。

##[kintone]の設定

1. kintoneの画面で歯車の設定アイコンから[cybozu.com共通管理]を開きます。
1. 左のメニューから[システム管理]-[セキュリティ]-[ログイン]を開きます。
1. 下の方にスクロールすると[SAML認証]メニューがあるので、[SAML認証を有効にする]をチェックして有効化します。
    1. [Identity ProviderのSSOエンドポイントURL（HTTP-Redirect）]にAzure portal からコピーしたログイン URL の値を貼り付けます。
    1. [cybozu.comからのログアウト後に遷移するURL]に次の値を入力します。
```https://login.microsoftonline.com/common/wsfederation?wa=wsignout1.0 ```
    1. [参照]ボタンを押してAzure portal からダウンロードした証明書ファイルをアップロードします。
1. [保存]ボタンを押します。

##ユーザー
自動プロビジョニングはできないので、AzureADとkintoneでそれぞれユーザーを作成して連携します。

##動作確認

下記のサイトに入ってAzureADで設定したkintoneのアプリを開くと、kintoneにSSOでアクセスすることができます。

https://myapps.microsoft.com


#おわりに
kintoneの設定画面にたどり着くのが一苦労でした。

#参考文献

https://developer.cybozu.io/hc/ja/articles/204376450-Azure-Active-Directory-%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6-cybozu-com-%E3%81%AB%E3%82%B7%E3%83%B3%E3%82%B0%E3%83%AB%E3%82%B5%E3%82%A4%E3%83%B3%E3%82%AA%E3%83%B3

https://developer.cybozu.io/hc/ja/articles/4410046680601
clamscanの結果をWazuhで取り込む方法

Wazuhは神なのでClamAVの実行結果を取り込んでアラートを出すルールを標準で用意してくれている。
しかしながらこのルールはデーモン実行(clamd)のログを前提としており、都度実行の場合は何かしらの対応が必要になる。
常駐させるほどではないけど定期実行はして結果はSIEMに送っておきたい、という場合に上手く誤魔化してclamdと同じように読ませる方法があったので以下紹介。

## 方法
wazuh標準のclamd結果の読み込みは、単にsyslogに書かれたclamdのログを見ているだけです。
そのため、clamscanの実行結果をclamdっぽくsyslogに書いてやれば標準ルールで読み込んでくれる。
つまり以下のように**logger -i -t clamd**にパイプで流して実行するだけ。

```
#実行例
/usr/bin/clamscan \
    --exclude-dir=^/proc/ \  #  procやsysなども無差別に見に行こうとするので除外指定が必要
    --exclude-dir=^/sys/ \
    --exclude-dir=^/dev/ \
    --exclude-dir=^/home/hogehoge/clamav/infected \  #隔離フォルダ
    --infected \ #感染してるファイルのみ表示(サマリは出る)
    --move=/home/hogehoge/clamav/infected \  #感染ファイルは隔離フォルダに移動する指示
    --recursive / | logger -i -t clamd  # ← clamdっぽくsyslogにログ記録
```

デフォルト設定にsyslogからのclamav読み込みは書いてあるので(4.2時点)、特にwazuh側の追加設定はいらないはず。
要素一つのジャグ配列とWrite-Output


powershellで配列を作成していたら変な挙動をしたのでメモ。
まずは下記のようにジャグ配列を作る。

```powershell:newArray1.ps1
# 要素が一つのジャグ配列
$new = @()
$add = 1,2,3
$new += ,$add

# $newの中身
$new.Count #=> 1
$new       #=> 1,2,3
```
powershellは配列の構造が分かりにくいけど中身はこんな感じになっている。
**$new = @(@(1,2,3))**

次に上のコードを関数にしてみる。

```powershell:newArray2.ps1
function New-Array{
    # 要素が一つのジャグ配列を作成
    $new = @()
    $add = 1,2,3
    $new += ,$add

    return $new
}

# New-Arrayでジャグ配列を作成
$array = New-Array

# $arrayの中身
$array.Count #=> 1ではなく3が返る
$array       #=> 1,2,3
```
関数の戻り値として扱うとジャグ配列がただの配列になってしまう。
**$array = @(1,2,3)**

returnをWrite-Output に変更するとうまくいくみたい。

```powershell:newArray3.ps1
function New-Array{
    # 要素が一つのジャグ配列を作成
    $new = @()
    $add = 1,2,3
    $new += ,$add

    Write-Output $new -NoEnumerate
}

# New-Arrayでジャグ配列を作成
$array = New-Array

# $arrayの中身
$array.Count #=> 1が返る
$array       #=> 1,2,3
```

**help Write-Output -example**
の最後の例で理由が確認できる。

関数の戻り値　=>　パイプライン経由の値ということなのかな？
深層機械学習の環境構築（Windows10 21H2 + WSL2 + Docker Desktop）

Windows上で深層機械学習のNVIDIA GPUを使用した環境構築するも、なぜかうまく動かない事が多かったのでしっかりと基本を抑える為にまとめてみる。

# 環境
Windows10 Pro 21H2
NVIDIA GeForce GTX 1060 6GB


## 環境構築の方針
Windows10 21H2でWSL2からGPUを使用できるようになったので、基本はDockerで環境構築を行う。
深層学習用のライブラリは、依存しているライブラリの数も多くそれらを切り替える環境構築するよりはDocker上で環境構築するのが良いだろう。

NVIDIAのWSL関係のドキュメントは以下
https://docs.nvidia.com/cuda/wsl-user-guide/index.html


## NVIDIA Driver
NVIDIAドライバはホストOS（すなわちWindows10）にインストールする。

https://developer.nvidia.com/cuda/wsl/download

上記からダウンロードするべしとなっているが、2022年1月現在上記でダウンロードされるドライバのバージョンは510.06。
GeForce Experience上では511.23にアップデートできるようになっているがアップデートして良いのかわからず。
一応ドキュメントに従ってアップデートをせずに510.06を使用する事とする。

ちなみにNVIDIAのドライバはGameReadyドライバとStudioドライバの2種類あるが、上記からダウンロードできたのはGameReadyドライバだった。

## NVIDIA CUDA
NVIDAが開発したGPUプログラム開発環境。画像編集ソフトや動画編集ソフトで使用する事もあるのでWindowsにインストールしている人も多いだろう。
今回はDocker上に開発環境を構築するのでWindows上にインストールするのは必須では無い。

## NVIDIA cuDNN
NVIDIA CUDA Deep Neural Networkの略。ディープ ニューラル ネットワークでの使用を目的としたGPUで高速化されたライブラリ。
深層機械学習のライブラリではGPUを使用する際に
cuDNNを依存している事がある。
こちらもDocker上に開発環境を構築するのでWindows上にインストールするのは必須では無い。

# インストールと設定

## WSL2のインストールと設定
マイクロソフトから丁寧なドキュメントが公開されている。
https://docs.microsoft.com/ja-jp/windows/wsl/install

ちょっと古いセットアップ方法とかだと、様々ダウンロードしたりとあったけど現在はコマンド一発でインストール可能。素晴らしい。

```powershell
wsl --install
```

WSL2の開発に必要な情報は以下にまとめられている。
https://docs.microsoft.com/ja-jp/windows/wsl/setup/environment#set-up-your-linux-username-and-password


## Docker Desktop for Windowsのインストールと設定

以下からダウンロード
https://www.docker.com/products/docker-desktop
インストーラのConfiguration画面では「 Install required Windows components for WSL 2」の選択を忘れずに。

### インストール後の設定画面
![WS000004.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212702/c4ab5370-9b36-fb14-bbeb-b93a4a16ef23.jpeg)


- Use the WSL2 based engine にチェックが入っている事
- Use Docker Compose V2 のチェックが入っている事

「Use Docker Compose V2」にチェックが入っている事となっているが、Docker ComposeのV1からV2に移行の過程のようなので、元にするdocker-compose.ymlによってはチェックを外さないと動かないケースがあるかもしれない。
V2がメインになってくる事が容易に想像できるのでチェックはつけておく。

# Dockerイメージ
Dockerイメージを0から用意する必要は無く、ある程度設定されたDockerイメージがNVIDIAから公開されている。
ベースになるライブラリがインストール済みのイメージをベースにDockerイメージを作成するのが良い。

https://developer.nvidia.com/ai-hpc-containers


# 起動確認
Docker上でGPUが有効になっているか確認を行う。CUDAが有効になっているDockerイメージでベンチマークを行ってみる。

```
$ docker run --gpus all nvcr.io/nvidia/k8s/cuda-sample:nbody nbody -gpu -benchmark
```

結果

```
> Windowed mode
> Simulation data stored in video memory
> Single precision floating point simulation
> 1 Devices used for simulation
GPU Device 0: "Pascal" with compute capability 6.1

> Compute 6.1 CUDA device: [NVIDIA GeForce GTX 1060 6GB]
10240 bodies, total time for 10 iterations: 7.996 ms
= 131.131 billion interactions per second
= 2622.615 single-precision GFLOP/s at 20 flops per interaction
```

きちんとGPUが認識していればOK。今回は**NVIDIA GeForce GTX 1060 6GB**が正しく認識されている。
GASで使えるライブラリを増やしてみる

## はじめに
GASでライブラリを使う方法が結構独特だったので、今回は具体的にMomentライブラリを追加する流れをまとめてみようと思います。といきたいところですが、Momentライブラリが使えなくなっていたので、代替手段を調べてみるとDay.jsライブラリを使っていこうと思います。

## GASで使えるライブラリを増やしてみる
### Day.jsライブラリとは

- Dateオブジェクトを扱いしやすくなる関数がまとまったライブラリ
- 日付計算等が簡単にできる
    - GASでもDateオブジェクトを扱えるが、使い方が結構独特
- 具体的にできること
    - 日時を好きなフォーマットで表示すること
    - 日時の演算（足し算、引き算など）
    - 日時の比較

以下は参考

https://qiita.com/tobita0000/items/0f9d0067398efdc2931e

#### スクリプト

```javascript
function myFunction() {
    var today = dayjs.dayjs('2022-01-17'); 
    var today_formatted = today.format('YYYY/MM/DD HH:mm'); // 任意の形にできる
    
    Logger.log(today_formatted);
}

```

### 実際にMomentライブラリを追加してみる
- エディタ画面左側のサイドバーから、ライブラリを選択する
    - ![スクリーンショット 2022-01-16 22.38.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581736/b2f1f16f-8f66-d903-1374-b37cec0bb8b2.png)
- スクリプトIDを記入して検索、追加
    - Day.jsライブラリのスクリプトID：1ShsRhHc8tgPy5wGOzUvgEhOedJUQD53m-gd8lG2MOgs-dXC_aCZn9lFB
    - ![スクリーンショット 2022-01-17 20.57.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581736/5d14daab-547f-8ba7-5623-595891653a1e.png)
- 追加されていると表示される
    - ![スクリーンショット 2022-01-17 21.07.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581736/a5d6d00e-36cd-ebfe-3536-93669f3615b1.png)

## さいごに
今回は簡単ではありますが、Day.jsライブラリを具体例としてGASのライブラリ追加方法をまとめました。
Linux入門 3-7 正規表現を使用したテキストファイルの検索

[](参照ソース)
[Udemyの動画講座]:https://www.udemy.com/course/linuxlpic/?utm_source=bene-content-marketing&utm_campaign=normal&utm_content=story&utm_term=career&utm_medium=udemyads
[Linux入門 3-6]:https://qiita.com/hoglet/items/3c944e8bc4b8bfa9a230
[Linux入門 3-8]:https://qiita.com/hoglet/items/34bf1c9b93bdb917ea1c

# はじめに
Linux初学者である自分向け用の記事です。[Udemyの動画講座]を参考にしました。
僕の勉強法は`動画を見る`→`実際に動かしてみる`→`問題演習`という流れです。

前回まで：[Linux入門 3-6]

***
# 3. LinuC 101 Ver .10.0(問題、テスト、演習)
# 正規表現を使用したテキストファイルの検索
## 正規表現

```
. 任意の一文字
* 直前の文字の0回以上の繰り返し
? 直前の文字の0回、1回
+ 直前の文字の1回以上の繰り返し
[] []で囲んだ文字の一文字
[a-z] a-zまでの文字
[^a] a以外
() ()内の文字を一文字として扱う
{n} 直前の文字のn回繰り返し
{min, max} 直前の文字のmin以上max以下の繰り返し
^ 行の先頭
$ 行の末尾
¥ 次の文字を正規表現とする。
¥t タブ
¥n 改行
| いずれか複数の条件
```

正規表現チェッカーで学習しよう。

https://weblabo.oscasierra.net/tools/regex/

## grep
文字列と正規表現を用いて検索するコマンド
–v: 特定の文字列を含まない行を抽出
–E: 正規表現を用いて文字を抽出（デフォルトでも正規表現は利用されるが、限定されている。-Eで拡張できる）
–F: 正規表現を利用しない
–n: 行数を付加して抽出
–i: 文字列の大文字と小文字を区別しない

```s
[root@c6140de26466 3]# cat test.txt 
Hi
this
is this file
123 456
abcde
ABCDE
[ABCDE]
[root@c6140de26466 3]# grep this test.txt 
this
is this file
[root@c6140de26466 3]# grep -i abcde test.txt 
abcde
ABCDE
[ABCDE]
[root@c6140de26466 3]# grep \\[ABCDE\\] test.txt 
[ABCDE]
[root@c6140de26466 3]# grep -F [ABCDE] test.txt 
[ABCDE]
[root@c6140de26466 3]# grep 'is(.*?)file' test.txt 
[root@c6140de26466 3]# grep -E 'is(.*?)file' test.txt 
is this file
[root@c6140de26466 3]# egrep 'is(.*?)file' test.txt 
is this file
```

## egrep
正規表現を用いて文字列の検索をする。(grep –Eと同様)
–n: 行数も表示
–v: 検索文字列を含まない行を抽出
–i: 文字列の大文字と小文字を区別しない

## fgrep
正規表現を利用しない(grep –Fと同様)
–n: 行数も表示
–v: 検索文字列を含まない行を抽出
–i: 文字列の大文字と小文字を区別しない

# エディタを使った基本的なファイル編集の実行
エディタの基本
Linuxで利用するエディタには、主にvi, vim, nanoがあります。
## vi
Linuxの標準的なエディタ。使用方法は前章をご参照ください。
## vim
viを改良したもので以下のような特徴がある

- シェル、C言語、pythonなどのプログラミング言語の編集に色がつき利用しやすい
- gzip, zipなどの圧縮されたファイルの編集ができる
- vimdiffを用いて、複数のファイルを比較・編集できる

## nano
Ubuntuでの標準エディタ。操作が簡単で比較的簡単に利用開始できる。

```s
[root@c6140de26466 3]# yum install nano
```

## EDITOR
エディタのパスを指定して、デフォルトのエディタを変更することができる。

```s
[root@c6140de26466 3]# export EDITOR=/usr/bin/vim
```



*To Be Continued...*
[Linux入門 3-8] へ
***