OmniAICreator/Qiita-1.07M huggingface dataset:
WSL + Ubuntu 20.04に AWS CLI を入れる


当たり前だが入ってない
```bash
$ aws --version

Command 'aws' not found, but can be installed with:

sudo apt install awscli
```


以下が入ってるか確認します

```bash
/usr/lib/x86_64-linux-gnu/libc.so.6
curl
unzip
groff
less
```
```bash
$ /usr/lib/x86_64-linux-gnu/libc.so.6
GNU C Library (Ubuntu GLIBC 2.31-0ubuntu9.2) stable release version 2.31.
Copyright (C) 2020 Free Software Foundation, Inc.
...以下略
```

```bash
$ curl --version
curl 7.68.0 (x86_64-pc-linux-gnu) libcurl/7.68.0 OpenSSL/1.1.1f zlib/1.2.11 brotli/1.0.7 libidn2/2.2.0 libpsl/0.21.0 (+libidn2/2.2.0) libssh/0.9.3/openssl/zlib nghttp2/1.40.0 librtmp/2.3
...以下略
```

```bash
$ unzip --version

Command 'unzip' not found, but can be installed with:

sudo apt install unzip
```


```bash
$ groff --version
GNU groff version 1.22.4
Copyright (C) 2018 Free Software Foundation, Inc.
...以下略
```

```bash
$ less --version
less 551 (GNU regular expressions)
Copyright (C) 1984-2019  Mark Nudelman
...以下略
```



unzip 入ってないので入れる
```bash
$ sudo apt install unzip
Reading package lists... Done
Building dependency tree
Reading state information... Done
Suggested packages:
  zip
The following NEW packages will be installed:
...などなど以下略
```

AWS CLIをダウンロード
```bash
$ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "/tmp/awscliv2.zip"
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 43.6M  100 43.6M    0     0  6403k      0  0:00:06  0:00:06 --:--:-- 5051k
```
AWS CLIをインストール

```bash
$ unzip /tmp/awscliv2.zip -d /tmp/ && sudo /tmp/aws/install -i /usr/local/aws-cli -b /usr/local/bin
Archive:  /tmp/awscliv2.zip
   creating: /tmp/aws/
   creating: /tmp/aws/dist/
  inflating: /tmp/aws/install
...以下略
```

確認
```bash
aws --version
aws-cli/2.4.21 Python/3.8.8 Linux/4.19.128-microsoft-standard exe/x86_64.ubuntu.20 prompt/off
```

上手に入りました
【JavaScript】DataTransfer.files (FileList) の順番はドラッグしたときに掴んだファイルによって変わる

# 結論
文章だと説明しにくいので例をあげます。

以下のファイルを選択したとします。
`1.txt`
`2.txt`
`3.txt`
`4.txt`

上記の状態から「どのファイルを掴んでドラッグを始めたか」によって `FileList` の順番が変わります。
`1.txt` を掴んでドラッグを始めた場合 `1, 2, 3, 4`
`2.txt` を掴んでドラッグを始めた場合 `2, 3, 4, 1`
`3.txt` を掴んでドラッグを始めた場合 `3, 4, 1, 2`
`4.txt` を掴んでドラッグを始めた場合 `4, 1, 2, 3`

てっきりファイル名昇順だと思い込んでいたのでハマりました😅
コードに「かもしれない運転」より「Just In Time」

# コードに「かもしれない運転」より「Just In Time」
車の免許を取るときに、「かもしれない運転で危機意識を高めよう！」と言われたことはありませんか？
かもしれない運転とは、**曲がり角から小学生が飛び出してくるかもしれない**のように予測しながら運転することです。
しかし、コードに、**かもしれない運転**は必要ありません。
と言いながら、私は個人開発ではあれも欲しいこれも欲しいと考えてしまい、なかなか進まない人間の1人です。

## 開発者の予測は大体外れる
コードに「かもしれない運転」は必要ない理由は、**開発者の予測は大体外れるから**です。
それはそうですよね、だって開発者はユーザーじゃないんだから。
車の運転では予測が外れた方が嬉しいですが、実際の開発では予測をなるべく外さないことが理想です。

### 予測を外すとどうなるのか
- リソースが無駄になる
- 無駄なコードが増えて、保守しにくいコードになる

## コードは「Just In Time」を意識する
「Just In Time」とは、ざっくりいうと**必要なものを、必要なときに、必要な数だけつくること**です。
詳しくは、こちらを参考にしてください。
[【図解】ジャストインタイム（just in time）とは？ トヨタ生産方式の特徴](https://www.kaonavi.jp/dictionary/just-in-time/)
つまり、「この機能も必要だろう」「もっと汎用性を高めよう」などとは考えずに、現時点で必要とされているものだけを書きましょう。

## まとめ
**コードに「かもしれない運転」より「Just In Time」**
「あなたはできているのですか？」と聞かれると、全くできていません。
個人開発ではあれもこれもとなりますし、インターンでも「これがあったらかっこいいな」みたいに考えています。
しかし、個人的にはある程度のアイデアレベルの予測は必要で、その予測が当たったことが分かれば、コードに変換することが良いのではと考えています。

**もし何か意見やコメントがあれば教えてください！**
【Rails】find_or_initialize_byとfind_or_create_byの違い

# find_or_create_by

条件を指定して初めの1件を取得(find)し、1件もなければ作成(create)
作成する時に呼ぶメソッドが**create**なので、新規作成して保存まで行う


```ruby
Category.find_or_create_by!(name: "ディナー")
  Category Load (0.6ms)  SELECT "categories".* FROM "categories" WHERE "categories"."name" = $1 LIMIT $2  [["name", "ディナー"], ["LIMIT", 1]]
  TRANSACTION (0.5ms)  BEGIN
  Category Create (2.0ms)  INSERT INTO "categories" ("name", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id"  [["name", "ディナー"], ["created_at", "2022-02-21 12:19:12.868048"], ["updated_at", "2022-02-21 12:19:12.868048"]]
  TRANSACTION (1.4ms)  COMMIT
=> #<Category:0x00007fed472719b0 id: 1, name: "ディナー", created_at: Mon, 21 Feb 2022 12:19:12.868048000 JST +09:00, updated_at: Mon, 21 Feb 2022 12:19:12.868048000 JST +09:00>
```

```ruby
Category.find_or_create_by!(name: "その他")
  Category Load (0.6ms)  SELECT "categories".* FROM "categories" WHERE "categories"."name" = $1 LIMIT $2  [["name", "その他"], ["LIMIT", 1]]
=> #<Category:0x00007fed4483f0e8 id: 2, name: "その他", created_at: Thu, 03 Feb 2022 12:20:21.014342000 JST +09:00, updated_at: Thu, 03 Feb 2022 12:20:21.014342000 JST +09:00>
```

# find_or_initialize_by
条件を指定して初めの1件を取得(find)し、1件もなければ作成(new)
作成する時に呼ぶメソッドが**new**なので、保存はしない

# 参考

https://railsdoc.com/page/find_or_initialize_by

https://railsdoc.com/page/find_or_create_by
Expressのデフォルトエラーハンドリングが作動しない？？

# なにが起こったか？
```ts
app.use((
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    err: any,
    req: express.Request,
    res: express.Response<BaseResponse.BaseApiResponse<{}>>,
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    next: any
) => {
    SentryLib.captureException(err)
    LoggerLib.debug(`${err}`)
    res.status(500).json({
        data: {},
        error: { message: 'standard error', code: 'ServerError' },
    })
    next()
})
```

```ts
export default class Controller {
    /**
     *
     * @param {express.Request} req
     * @param {express.Response} res
     */
    public static async get(
        req: express.Request<
            {},
            AreaPublicApiResponse.GetApiResponse,
            any,
            {}
        >,
        res: express.Response,
        next: express.NextFunction
    ) {
        throw Error('エラーですよ')
    }
}
```

上記のようにデフォルトエラーハンドリングの実装を行っていて、APIで強制的にエラーを出すように設定してみたがデフォルトのエラーハンドリングが機能しない

公式を確認してみる
https://expressjs.com/ja/guide/error-handling.html

```ts
app.get('/', (req, res, next) => {
  setTimeout(() => {
    try {
      throw new Error('BROKEN')
    } catch (err) {
      next(err)
    }
  }, 100)
})
```

nextを実行しないとどうやらデフォルトハンドリングまで行ってくれないらしい
Railsに慣れちゃってたので、エラーが起きたら自動的に検知してくれると勘違いしていた

# 修正版
```ts
export default class Controller {
    /**
     *
     * @param {express.Request} req
     * @param {express.Response} res
     */
    public static async get(
        req: express.Request<
            {},
            AreaPublicApiResponse.GetApiResponse,
            any,
            {}
        >,
        res: express.Response,
        next: express.NextFunction
    ) {
    　　　　try {
        throw Error('エラーですよ')
      } catch (e) {
        next(e) // nextを実行
      }
    }
}
```

無事動くようになりました！

# nextが呼ばれないとどうなるか
> If the current middleware function does not end the request-response cycle, it must call next() to pass control to the next middleware function. Otherwise, the request will be left hanging.
An Express application can use the following types of middleware:

ref: https://expressjs.com/en/guide/using-middleware.html

リクエストが滞留してしまうということが書かれている
同期的なエラーはExpressでデフォルトでハンドリングしてくれるが、非同期関数で発生するエラーはハンドリングしてくれないので、リクエストが滞留してしまいサーバーダウンの原因にもなってしまう恐れも

# Express v 5.xでは非同期関数のエラーも自動でnext()が呼ばれるようになる
> Starting with Express 5, route handlers and middleware that return a Promise will call next(value) automatically when they reject or throw an error. For example:

ref: https://expressjs.com/en/guide/error-handling.html
【Rspec,Rails】full_title helperの単体テスト

# テストの対象となる機能
application helperに次のようなfull_title helperを定義している。

```rb:appplication_helper.rb
module ApplicationHelper
  BASE_TITLE = "HOGE".freeze

  def full_title(page_title)
    page_title.blank? ? BASE_TITLE : "#{page_title} - #{BASE_TITLE}"
  end
end
```
ページタイトルを取得して、ベースタイトルとともにtitleタグに動的な表示を行うために作られた、普通のタイトルヘルパーである。

Rspecによって、この機能のテストを記述したい。

# helperの単体テスト

この機能のテストを記述するにあたっては、次のように、他の要素のテストとともに、system specへテストを記述する方法もある。

```rb:system_spec
expect(page).to have_title "#{content.name} - HOGE"
#content.nameという内容をタイトルに表示したい場合を想定している。
```

ただし、この方法だと、ページが増えるたびにこれをsystem_specに記述することになるし、このhelperの本質である「動的な表示をテスト」している記述であるかと言われれば、そうとも言えない。

そこで、このhelperの単体のテストを別途設け、そこに条件分岐を与えた上で、条件に応じた動的な表示の機能があるかをテストしていきたい。

具体的には、spec/helpers/application_helper_spec.rbを作成し、次のようなテストを書く。

```rb:application_helper_spec.rb
require 'rails_helper'

RSpec.describe ApplicationHelper, type: :helper do
  describe "#full_title" do
    it "引数が渡されている場合に動的な表示がなされること" do
      expect(full_title('sample')).to eq('sample - HOGE')
    end

    it "引数が空白の場合に動的な表示がなされること" do
      expect(full_title('')).to eq('HOGE')
    end

    it "引数がnilの場合に動的な表示がなされること" do
      expect(full_title(nil)).to eq('HOGE')
    end
  end
end
```
注意点はfull_title helperを「タイトルを表示するためのもの」として扱わないこと、

つまり、viewに特有の概念や「タイトル」という言葉を、application_helper_spec内で使うべきでないということである。

full_titleという名前ではあるが、このヘルパーは本来、viewや特定のタイトルに依存しない、汎用的な機能である。

単に、与えられた引数を取得し、元々ある定数と一緒に返すという機能に過ぎない。

たとえ、与えられた引数がviewやタイトルに関係のない内容であっても、この機能自体は担保されていないといけない。

「機能」をテストするために作られた、application_helper_specというファイルで実行される内容は、あくまでも機能をテストすることに終始すべきである。
Heroku で デプロイ エラー （~version not specified in package.json）

# 開発環境
対象	バージョン
| 対象        | version     | 
|:-----------|------------:|
| Node.js    | v15.4.0     |
| npm        | 7.0.15      |

# 発生している問題・エラー
作成途中だったアプリを一時中断して、Nuxt.jsの学習をしていた。
久しぶりに途中だったアプリを`git push heroku main`をしたら、下記のエラーが出るようになってしまった。
どうやら、`Node version not specified in package.json`という部分が問題のようだった。
これは、Nodeのバージョンがpackage.jsonに記述されていないことらしい。
以前は普通にデプロイ出来てたのに、なぜこうなってしまったかは分からなかった。
```デプロイログ.
remote: -----> Build failed
remote:        
remote:        We're sorry this build is failing! You can troubleshoot common issues here:
remote:        https://devcenter.heroku.com/articles/troubleshooting-node-deploys
remote:        
remote:        Some possible problems:
remote:        
remote:        - Node version not specified in package.json
remote:          https://devcenter.heroku.com/articles/nodejs-support#specifying-a-node-js-version
remote:        
remote:        Love,
remote:        Heroku
remote:        
remote:  !     Push rejected, failed to compile Node.js app.
remote: 
remote:  !     Push failed
remote:  !
remote:  ! ## Warning - The same version of this code has already been built: 2e1b37e888e9ad2a5e50da16618bf37879e28f8a
remote:  !
remote:  ! We have detected that you have triggered a build from source code with version 2e1b37e888e9ad2a5e50da16618bf37879e28f8a
remote:  ! at least twice. One common cause of this behavior is attempting to deploy code from a different branch.
remote:  !
remote:  ! If you are developing on a branch and deploying via git you must run:
remote:  !
remote:  !     git push heroku <branchname>:main
remote:  !
remote:  ! This article goes into details on the behavior:
remote:  !   https://devcenter.heroku.com/articles/duplicate-build-version
remote: 
remote: Verifying deploy...
remote: 
remote: !       Push rejected to .
remote: 
To https://git.heroku.com/~.git
 ! [remote rejected] main -> main (pre-receive hook declined)
error: failed to push some refs to 'https://git.heroku.com/~.git'
```
# 解決手順
(https://devcenter.heroku.com/articles/troubleshooting-node-deploys) の「Other Available Runtimes」 を参考にして
package.jsonに`"engines": {~}`を加えて、mainブランチにpushしたら解決できた。
今回の場合は、node.jsにエラーメッセージが出てたので、`"node": "15.4.0"` を加えた。
```package.json
{
  "name": "example-app",
  "description": "a really cool app",
  "version": "1.0.0",
  "engines": {
    "node": "15.4.0"
  }
}
```
# 参考記事
https://qiita.com/AK_-_-_-I/items/ad2f45d4a1c79c38d55f
[iOS/Android]FirebaseAuthの電話番号認証(SMS)にてボット判定(reCAPTCHA 検証)をなくす方法

# 概要
この記事ではFirebaseAuthの電話番号認証(SMS)にてボット判定(reCAPTCHA 検証)をなくす方法についてご紹介します。
今回iOS,Androidそれぞれボット判定を消す事が出来たのでそれぞれ解説します！

# そもそもボット判定とは？
以下のような画面を指します。まずこのような画面が表示されたあとに
![スクリーンショット 2022-02-25 11.02.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49347/a06d2f79-d54f-4d07-8e5d-b14e5c108553.png)

このような画面が出る場合があります。
![l_mm_captcha_05_w290.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49347/89a1a2e7-ae64-e3c5-d431-334d8a8acb5f.jpeg)


これをユーザにサインアップ、ログインしてもらう度に実施してもらうのはユーザビリティ的に微妙なので、
上記の画面を消す設定をご紹介します！


# iOS
まずはiOSから説明していきます。
基本的には公式に書いてある[こちらの記事](https://firebase.google.com/docs/auth/ios/phone-auth#start-receiving-silent-notifications)を参考にしてもらえれば大丈夫なのですが、こちらの記事に書かれていない設定がプラスα必要なのでそちらも合わせて解説します。

## Xcodeでプロジェクトのプッシュ通知を有効にする
[こちらの記事](https://firebase.google.com/docs/auth/ios/phone-auth#start-receiving-silent-notifications)の1.のステップにある通りにプロジェクトのプッシュ通知を有効にしてください。



## APNs認証キーを登録する
以下の画像のようにFirebaseのコンソールからAPNs認証キーを登録してください。
![152635872-0c22c6af-1dad-407b-be43-5976621754cc-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49347/9bbf2e04-911f-d8eb-74e3-2b86a097c41b.png)


## Remote notificationsを有効にする
公式の記事だとAPNsを登録するまでやればOKなように書かれていたのですが、プラスで設定を追加する必要がありました…！(ここがハマりました)

`Background Modes` -> `Remote notifications`を有効にすることでボット判定が出なくなります！
![スクリーンショット 2022-02-25 12.02.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49347/68c3567f-ef2c-74d8-d978-cf8d0144e414.png)



# Android
Androidは公式に書いてある[こちらの記事](https://firebase.google.com/docs/auth/android/phone-auth#enable-app-verification)の通りに実装してもらえれば大丈夫です！

## Android DeviceCheck APIを有効にする
FireBaseに紐づく[GCPプロジェクト](https://console.cloud.google.com/apis/library/androidcheck.googleapis.com)を有効にします。
![スクリーンショット 2022-02-25 11.01.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49347/7e44806b-fedc-c419-3878-7188f3034d7e.png)

有効にすると以下のように表示が変わります。
![スクリーンショット 2022-02-25 11.02.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49347/675870ac-1501-6f35-f636-34c8d6cb4cc7.png)


## アプリのSHA-256フィンガープリントを登録する
![C-251_fansta-project-stg_-_プロジェクトの設定_-_Firebase_コンソール.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49347/bde493ce-b996-e89e-cf86-78eaa35fc653.png)

上記の設定をすることでAndroidでもボット判定が出なくなります！


基本的には公式の通りにやれば大丈夫なのですが、
iOSのRemote notificationsの部分だけ記事を書いた当時記載がなくハマりました。

以上がiOS,Androidの設定方法の解説になります！
[Stripe Updates] Stripe Checkout / Payment Linksの決済ページで、フォントやボタンの形状をカスタマイズできるようになりました


Stripeが用意する決済フォーム（Checkout）では、これまで「ロゴ・アイコンの表示」「背景色・ボタン色の変更」の２種類がカスタマイズ可能でした。

![スクリーンショット 0004-02-17 11.39.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/03266ec2-bb58-efbb-df7b-36ab8926eb61.png)

今回のアップデートから、Checkoutページのフォントと、ボタンやフォームの形状についてもカスタマイズ可能になります。

# 設定のカスタマイズはDashboardから

背景色のカスタマイズなどと同様、スタイルのカスタマイズはDashboardから行います。

[設定>ブランディング](https://dashboard.stripe.com/settings/branding)で、[CheckoutとPayment Links]タブを選択しましょう。

![スクリーンショット 0004-02-17 11.41.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/5fb03583-a417-3a91-22a7-fac3ca55a0de.png)

[カスタマイズ]ボタンをクリックすると、CheckoutとPayment Linksで利用する決済フォームのカスタマイズ画面が開きます。

フォントの変更は[タイポグラフィー]の[フォント]から、ボタンやフォーム形状は[スタイル]の[形状]から変更できます。

![スクリーンショット 0004-02-17 11.43.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/2cdbb136-a125-0a26-4f27-180e667b44f7.png)

## フォントはプリセットから選ぶ仕組み

設定できるフォントは、2022/2時点では以下の種類です。

![スクリーンショット 0004-02-17 11.44.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/d48d4f04-f9fb-df34-0eb1-e9dce013edb2.png)

また、言語によっては利用できないフォントもありますので、必ずプレビュー画面で表示を確認した上でご利用ください。


# [PR] Stripe開発者向け情報をQiitaにて配信中！

- [Stripe Updates]：開発者向けStripeアップデート紹介・解説
- ユースケース別のStripe製品や実装サンプルの紹介
- Stripeと外部サービス・OSSとの連携方法やTipsの紹介
- 初心者向けのチュートリアル(予定)

など、Stripeを利用してオンラインビジネスを始める方法について週に２〜３本ペースで更新中です。

-> [Stripe Organizationsをフォローして最新情報をQiitaで受け取る](https://qiita.com/organizations/stripe)
CentOS8×PHP7.3「Failed to download metadata for repo 'AppStream'」で怒られる時

## 現象
~~~
Error: Failed to download metadata for repo 'AppStream': Cannot prepare internal mirrorlist: No URLs in mirrorlist
~~~

## 原因
2021年末でCentOS8のサポートが切れたので、**ミラーサイトが停止している**ご様子でした。👼

## 解決策
リポジトリのダウンロードの向き先を**アーカイブ**に変更します！
```
$ sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
$ sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
```
## PHPのバージョンを変更する場合
CentOS8のデフォルトのPHPバージョンは**PHP7.2**になります。
**別バージョン**を使用したい場合は、remiリポジトリを使用する必要があります。

remiリポジトリをインストールして、再度エラーが出る場合は、、、

:::note info
囲んじゃいましょう。
:::

~~~
# 向き先変更
$ sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
$ sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*

# remiリポジトリ
$ dnf -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm
$ dnf -y install https://rpms.remirepo.net/enterprise/remi-release-8.rpm

# さらに向き先変更
$ sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
$ sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
~~~

何か良い方法があれば、教えていただきたいです。。。

## 参考
https://qiita.com/yamada-hakase/items/cb1b6124e11ca65e2a2b
https://www.na3.jp/entry/20220213/p1
「Adblockが有効だと特定の要素が消えちゃう！」が起きないサイトを作る方法

[Adblock](https://chrome.google.com/webstore/detail/adblock-plus-free-ad-bloc/cfhdojbkjhnklbpkdaibdccddilifddb?hl=ja)とは、ブラウザの拡張機能で、Webサイトに表示される広告を自動で非表示にしてくれるというものです。

※ この記事では、「Adblockは悪か」、といった話題には触れず、以下の前提で進めます。

- 世の中にはAdblockを導入しているユーザーが居る
- そういったユーザーでもサイトを利用できる状態にしたい
  - ＝ 広告以外の要素が意図せず非表示になるのを防ぎたい

この拡張機能が有効なユーザーがサイトを表示した際、広告ではない要素まで消えてしまうという事象が起きることがあります。

~~例えば今だと、某有名レシピサイトさんの右カラムが丸ごと消失してしまうようです。~~
治ったようです。

# 関係ない要素が消える理由

Adblockには、いくつかの仕組みで広告を検知しているようですが、そのうちの一つが、id名による検知です。

要素のid名に`#ad_*`のようなものが設定されていると、広告と認識され、非表示にされます。

実際にAdblock導入すると、以下のようなシンプルなCSSが追加されます。

```css
#ad_mobile, #ad_module, #ad_wrapper, ..略.. {
  display: none !important;
}
```

経験上、Webサイトを作っていて意図せず要素が消失してしまう場合、多くの場合これによるものだと思います。

「ブラウザのシークレットウィンドウだと表示されるけど、通常のウィンドウだと表示されなくなる要素がある」
的な事象のときは、Adblockを疑ってみてください。

## 対策

対策は、広告じゃない要素に`ad_*`といった命名をしないことです。

特に、メインページ上部に置くスライダーや、サイト内の別コンテンツを紹介するバナーなどに、adと命名してしまうようです。
vue3.0 composition-api interfaceを入れ子にしたデータをリアクティブにInjectする

vue 3.0でスマホアプリを開発中です。
ユーザー認証を行い、権限ごとにFooterメニューの中身を変更したいと考えました。
テスト駆動で行いたいため、
ユーザーと権限の型をインターフェースで定義しています。
また、Footerメニューと権限の選択などはvueのInject機能で実装します。

アプリ構造
```
App.vue
main.ts
　\views
   FooterMenu.vue（フッターメニュー）
   LoginMenu.vue（ログインさせたり権限選択を変えたり）
   Contents.vue（表示するコンテンツ）
 \stores
   UserStore.ts(共有するProvideInjectのもの)
```

データは
```
IUser（Name:string、Role：IRole）
IRole（RoleName:string、isManager:boolean）
```
という形でUserの中にRoleを持たせています。

使う時は、
```
export class AppUser implements IUser {....}
export class AppRole implements IRole {....}
```

storeKeyを利用して
```userStore.ts
import { InjectionKey,inject } from 'vue';
import { IUser, IRole } from '../interfaces/IUser';
export const UserStoreKey: InjectionKey<IUser>  = Symbol("User");

export function useUserStore() {
    const store = inject(UserStoreKey);
    if(!store) {
        throw new Error('store not found');
    }
    return store;
} 
```
こういうのを用意。InjectionKeyで検索すれば詳しく解説している人がいます！

```App.vue
<script setup lang="ts">
import { onMounted, provide, reactive } from 'vue'
import { UserStoreKey } from './stores/UserStore';

const expRole = new AppRole();
const expUser = reactive(new AppUser());
expUser.Role = expRole;
provide ( UserStoreKey, expUser);
</script>
```
App.vueにてInjectionするのですが、この時に、reactive()を付けます。
付けないとLoginMenu.vueで変更したものがFooter.vueに反映されなかったりします。
また、refで各値を作っても良さそうですが、入れ子になっていると上手く動かなかったりします。

使い方の注意は
```Footer.vue
<script setup lang="ts">
import { useUserStore } from '../stores/UserStore';

const currentRole = useUserStore();
const { Role } = toRefs(currentRole);

</script>
```
toRefsしないとFooter.vueでリアクティブになりません。
Pythonでディレクトリを（存在するかどうか確かめて存在しなかったら）作成する

# 1. はじめに
ディレクトリの作成方法やチェック方法をよく忘れるので、自分の備忘録的に残しておきます。
僕と同じようにすぐ忘れちゃう系エンジニアや駆け出しエンジニアのお役に立てればと思い、しれっと初投稿。

ちなみに「あと10秒しか調べる時間がない…！」という危機に直面中の人は「[まとめ](#6-まとめ)」に飛んでください。

自分の動作環境は簡便ですがこんな感じです。
バージョン：Python 3.9.1
OS：Windows 10

# 2. ディレクトリ作成
ディレクトリを作成する関数を調べると以下の2つが出てきました。
```python:python
import os

os.mkdir([ディレクトリパス])    # 1つめ
os.makedirs([ディレクトリパス]) # 2つめ
```
ただし、1つ目の`os.mkdir`は、「...../存在しないディレクトリ/存在しないディレクトリ」のように深い階層で存在しないディレクトリ群を作ることができないようなので、基本的には2つ目の`os.makedirs`を使っていくのがよさそうです。

よって今回は`os.makedirs`でディレクトリの作成方法をメモします（公式ドキュメントのリンクは[まとめ](#6-まとめ)に貼っておきます）。
というわけで、ディレクトリ作成のコードは以下。

```python:python
import os

dir = 'mydir' # 新たに作成するディレクトリ名やパス名
os.makedirs(dir) # 指定した名前（パス）でディレクトリを作成
```


**以上です！いかがでしたか？お疲れさまでした！**


…とはいかず、これはそのディレクトリがまだ存在していない時限定で、既に存在するディレクトリを同様に作成しようとすると以下のようなエラーが発生してしまいました。
```python
FileExistsError: [WinError 183] 既に存在するファイルを作成することはできません。: 'mydir'
```

# 3. ディレクトリの存在をチェックして作成（方法1）
というわけで、「まずは作りたいディレクトリの存在をチェックして、存在しなかった場合には作成する」ための方法は以下。
よく紹介されている方法なので（後述の方法2より1行多いけど）メモ。
```python:python
import os

dir = "mydir"
if not os.path.exists(dir): # ディレクトリが存在するか確認
    os.makedirs(dir) # ディレクトリ作成
```
`os.path.exists(dir)` は、指定したディレクトリ*dir*が存在すれば`True`、なければ`False`を返します。
ディレクトリが存在しなかったとき（`False`だったとき）だけ作成したいので、`if not`で判定しています。
重ねて作成しようとしたときに親切に何か出力したい時なんかがあれば使える感じかしら？

ちなみに`os.path.exists()`は、**ディレクトリだけでなくファイルが存在するかどうかのチェックにも使える**ので覚えておこう（自分に言ってます）。

# 4. ディレクトリの存在をチェックして作成（方法2）
`makedirs`のコードを見たところ、方法1のようにif文を使わなくても、**以下1行でできてしまう**ようでした。
（ドキュメントを見るとこの方法はバージョン3.2から追加実装されたそう）
```python:python
import os

dir = "mydir"
os.makedirs(dir, exist_ok=True) 
```
`makedirs`の引数に「`exist_ok=True`」を入れると、方法1のようにif文で2行書かなくても良いようです。
デフォルトだと（引数に書かないと）「`exist_ok=False`」になっているので、方法1のようにif文で分岐が必要になるわけです。
というわけで、**比較的最近のバージョンを使っているのであればこれが一番楽そう**ですね。

# 5. makedirs() の `exist_ok=True`に関する余談
ここからはちょっと細かい話。
このmakedirsのコードを見ると、引数まで書くと`makedirs(name, mode=0o777, exist_ok=False)`となっています。
[公式ドキュメント](https://docs.python.org/ja/3.9/library/os.html?highlight=makedirs#os.makedirs)を読んでみると、第2引数のmodeはディレクトリの権限モードを表すらしく、3.4.1より以前では動作が不安定な部分もあったようです。
以下、公式ドキュメントからの引用です。
> Python 3.4.1 より前、 exist_ok が True でそのディレクトリが既存の場合でも、 makedirs() は mode が既存ディレクトリのモードと合わない場合にはエラーにしようとしていました。このモードチェックの振る舞いを安全に実装することが出来なかったため、 Python 3.4.1 でこのチェックは削除されました。

というわけで、恐らくpython 3.4.1以降での使用を推奨する感じ、ということでしょうか…？

# 6. まとめ
ディレクトリを作成するコードを書くときは、
```python:python
import os

os.makedirs("ディレクトリパス", exist_ok=True)
```
が一番簡単らしい。
ただし `exist_ok=True`でファイルが既存かどうかチェックする機能が実装されたのはpython 3.2以降みたいだし、3.4.1より前ではちょっとエラーが出ちゃう場合もあるかも知れないから、バージョンには注意してね！（自分に言ってます）

公式ドキュメントはこちら。⇒　[Python 3.9.1ドキュメント os.makedirs](https://docs.python.org/ja/3.9/library/os.html?highlight=makedirs#os.makedirs)
Visual Studioのサインインとプロキシ

# 背景
Visual Studioのプロキシ環境(ID/パス有)下でのサインインに苦労したのでメモ。

# サポートによる記述

ここを変えろと書いてあった。
`C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE`

`devenv.exe.config`

上記ファイルの、<system.net>のセクションの内側に下記を入れる。
`<system.net>`
`  <defaultProxy enabled="false" useDefaultCredentials="false">`
`    <proxy bypassonlocal="True" usesystemdefault="false" proxyaddress="http://XX.XX.XX.XX:8080" />`
`  </defaultProxy>`
`</system.net>`

defaultProxy enabled="false"は、サポートにはtrueと書いてあるが、ID/パス入力時はfalseにすると良いらしい。

また、IEがデフォルトブラウザの場合、インターネットオプション->セキュリティ->信頼済みサイトで、「サイト」をクリックし、下記をWebサイト(信頼済みサイト)に加える。
`https://www.microsoft.com`

さらに、インターネットオプション->接続->LANの設定で、
「設定を自動的に検出する」にチェックを入れた。
(ただし、自動構成スクリプトを使用する、になっている為、LANにプロキシ サーバーを使用する、の環境の場合は不明。)
【Excelアドイン】フィルターにセル参照を設定してみる

## クエリへフィルターを追加する
テーブル数式が設定されているアンカーセルをダブルクリックします。
お馴染みの「クエリビルダ」が起動します。
![Qiita 2022-02-25 Figure 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/fe6891bf-a091-7f6a-c146-4b9c2e0ecdcd.png)
”選択”階層領域から”売上日”フィールドを、ドラッグ＆ドロップで”フィルター”領域に設定します。
![Qiita 2022-02-25 Figure 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/d0829b84-9721-c312-0dff-1d3b5d4946a1.png)
## フィルターにセル参照を設定する
セル$\color{Blue}{\rm B2}$に”売上日”と入力します。
”売上日”フィルターの値フィールド(From：左側)を選択した状態で、Excelワークシートのセル$\color{Blue}{\rm C2}$をダブルクリックして、セル参照を転送します。
同じように”売上日”フィルターの値フィールド(To：右側)に、セル$\color{Blue}{\rm D2}$のセル参照を転送します。
OKボタンを押して、クエリビルダを終了します。
![Qiita 2022-02-25 Figure 3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/d930fb9b-2e95-9c09-434f-3631832132fa.png)
では、セル$\color{Blue}{\rm C2}$をダブルクリックしてみます。先ほど設定したセル参照により、定義したクエリとのリンクが存在しているので、日付オプションダイアログが表示されます。もちろん直接セル$\color{Blue}{\rm C2}$や$\color{Blue}{\rm D2}$に日付を入力してもかまいません。
![Qiita 2022-02-25 Figure 4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/50354dc1-aaf3-32e5-5aa7-8a74cfb90017.png)
このようにしてセル$\color{Blue}{\rm C2}$および$\color{Blue}{\rm D2}$のフィルター値を変更すると、直ちに再計算が行われテーブルが更新されます。
試してみてください。
![Qiita 2022-02-25 Figure 5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/68b65ae5-4484-fc6a-bb01-6093fe765e94.png)
IP制限方法について

最近、ある特定のアプリのみIP制限したいとの要望があったため調べてみた

## tomcatでのIP制限方法
tomcatでのIP制限はコンテキスト単位で設定することができる。
下記のxmlを追加するだけ。※hoge=コンテキスト名
$TOMCAT_HOME/conf/Catalina/localhost/hoge.xml
```
例 ローカルのみ制限する場合
<Context antiResourceLocking="false" privileged="true" >
  <Valve className="org.apache.catalina.valves.RemoteAddrValve"
         allow="127.0.0.1" />
</Context>

例 特定のIPからアクセス拒否する場合
<Context antiResourceLocking="false" privileged="true" >
  <Valve className="org.apache.catalina.valves.RemoteAddrValve"
         allow="10.128.128.44" />
</Context>
```
alloow: アクセスを許可するIPアドレス、ホスト名を指定する。
deny:   アクセスを拒否するIPアドレス、ホスト名を指定する。

## 備考
他にも全コンテキストで制限する方法(server.xmlに記述する)、
apacheで制限する方法、サーバー単位で設定する方法があるが、
別の機会に紹介したいと思います。
歴史からオブジェクト指向を捉える

そもそも、私自身はじめはオブジェクト指向言語という言葉自体が抽象的でピンと来ませんでした。「なんか聞いたことはある」「JavascriptとかPythonとかもそうらしい。知らんけど」程度です。そんな中、「オブジェクト指向言語でなぜつくるのか」を読んだので、印象に残った箇所をまとめます。

# オブジェクト指向とは
　ざっくりいうと、「ソフトウェア開発を楽にするための総合的な技術」です。オブジェクト指向はプログラミング技術として発案されましたが、現在では、汎用の整理術として要求仕様や設計内容の図式表現にも用いられているため「総合的な技術」となっています。

　オブジェクト指向が用いられている技術として、プログラミング言語に絞ると**C++、Java, Javascript, Python, Ruby**などが挙げられます。現在用いられているほとんどの言語がオブジェクト指向なんですね。

# オブジェクト指向言語の歴史
　現在非常に多く用いられているオブジェクト指向言語(以下、**OOP**(Object Oriented Programming))ですが、この技術が誕生した背景に注目すると、より理解が深まります。

## 機械語が用いられていた黎明期
　そもそもコンピューターは2進数で書かれた**機械語**しか理解できません。このため、プログラムを用意する時、最終的に**機械語**で書かれた命令群を用意しなければなりません。
　現在では、JavaやPythonなどのプログラミング言語があるため、プログラマーが**機械語**を意識する必要はありません。しかし、コンピューターが発明された1940年代にはそのようなものはなく、プログラマーが一文字一文字手入力で記述する必要がありました。

``` :機械語によるプログラム例
A10010
8B160210
01D0
A10410
```
ちんぷんかんぷんですね。。。
もうちょっと進みましょう。

## 機械語から進化したアセンブリ言語
　次に登場した**アセンブリ言語**では、無機質な機械語をより人間にわかりやすい記号で記述できるようになりました。

``` :アセンブリ言語によるプログラム例
MOV AX, X
MOV DX, Y
ADD AX, DX
MOV Z, AX
```

人間にわかりやすいといっても、この状態でもほぼ何をしているかわかりません。。。
ただ、`MOV`で何かを動かしていて、`ADD`で何かを追加していることはぼんやり想像できるような気がしないでもないです（ほぼわからん）。

## 高級言語の発明
　次に**高級言語**が登場しました。**高級言語**ではコンピューターが理解する言語を一つ一つ記述するのではなく、より人間にわかりやすいように「**高級な**」形式で表現します。また、ここからサブルーチン（メソッド）も利用できるようになりました。

```FORTRUN:高級言語であるFORTRUNによるプログラム例
z = x + y
```
　だいぶわかりやすくなりましたね。実はこれまでの意味不明のプログラム例はこの記述を表現するものだったんです。これまでに用いられていた、機械語やアセンブリ言語と比較して**高級言語**が便利であることは明らかです。

　しかし、1960年代当時、この進化では追いつかないほどにソフトウェア需要は増大しており、NATO（北大西洋条約機構）の国際会議では「20世紀末には全人口がプログラマーになってもソフトウェア需要をカバーしきれない」として、「ソフトウェア危機」を発表しました。

## 構造化プログラミング言語
　そんな「ソフトウェア危機」に対応するべく、登場したのが**構造化プログラミング言語**です。代表的なものとして**C言語, ALGOL, Pascal**などがあります。

　構造化プログラミング言語では、「わかりやすい構造」が重視され、プログラムのロジックが「順次進行」「条件分岐(if文, case文, while文)」「繰り返し　(for文)」の３つの構造で表現されています。今では当たり前のように感じますが、それまで主流だったCOBOLやFORTMANでは基本三構造を素直に書けなかったため、こうした言語の登場は大きな進化でした。

### 構造化プログラミング言語の弱点
　しかし、**構造化プログラミング言語**にも弱点がありました。その一つが**貧弱な再利用**です。この時代では、構造化プログラミング言語で再利用できるのは「メソッド」のみであり、コード変換や入出力処理、数値計算などの基本的な処理についてのものしかありませんでした。このため、当時増大するアプリケーションの規模に対して、機能の再利用性が不足していました。

## オブジェクト指向言語の登場
　そんな中登場したのが、**「クラス(カプセル化)」「ポリモーフィズム」「継承」** の三大要素を備えた**オブジェクト指向言語**でした。これらの要素をもう少しくだけた表現に直すと「重複した無駄なロジックを排除し、必要な機能を整理整頓する仕組み」です。こうした機能には強力な再利用性があり、構造化プログラミング言語の課題を全てカバーするものでした。三大要素については[こちら](https://shimapuku.com/programming/java-basic/three-major-elements)で詳細に説明されています。
Nutanixという製品はVMなのでしょうか？それともHCIなのでしょうか？

ハードウェア的な質問失礼いたします。

件名の通りなのですが
Nutanixという製品はVMなのでしょうか？
それともHCIなのでしょうか？

というのもググった感じではどちらとも取れる感じなのです……

とココまで書いて
[【図解】HCI（Hyper-Converged Infrastructure）とは？わかりやすく解説 - カゴヤのサーバー研究室](https://www.kagoya.jp/howto/engineer/itsystem/hci/)
を見た所
図と
```
簡単に言うとHCIでは1台の物理サーバーのなかに、サーバー仮想化に必要なサーバー・ネットワーク・ストレージの機能が含まれているのです。拡張が必要なときには、イーサネットによって追加の物理サーバーを接続することで実現できます。HCIを採用することでサーバー仮想化は、このようにシンプルな構成で実現できるようになりました。
```
で概ね理解出来ました。

Nutanix≒HCI∋VM
ですねっ

とメモ書き失礼します。

HCI　ハイパーコンバージドインフラストラクチャ
【Chromeデベロッパーツール・全て学べる】動画集

### 自己紹介
ジーズアカデミー講師 山崎と申します。
EdgeもコアはChromiumですから、デベロッパーツールは同じですからね。
今回、私のJavaScriptの授業（初級者向け）でのサポート動画をYoutube配信したものをまとめました。


:::note info
一つ一つが奥が深く解説が長いので「ブックマーク」して見ることをおススメいたします
:::

## ◆動画集一覧
HTML/CSS/JavaScripを使った制作には「Chromeデベロッパーツール」は必須スキルです！
デザインの調整、他サイトの構造見たり、エラーの確認、デバッグ等で良く使います。
※一部新しい機能は、今後追加していきます。

:::note warn
デベロッパーツールは奥が深いので、初学者には「#1,#2」だけをおススメします。
デベロッパーツールは奥が深い～
:::

 
| タイトル | 対象 | 動画🔗 | 
| ---- | ---- |  ---- | 
| #1「 Elements/Console 」<br><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104530/fcff5325-2521-adac-0e3e-fb33c9af98c1.jpeg" width="400"> | **Webデザイナー/ フロントエンド** | https://youtu.be/PjZyPfXdJFA | 
| #2「 JavaScriptデバッガ― / Sources」<br><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104530/7e829ee8-3a00-a74d-2e8b-c97f05372f3a.jpeg" width="400"> | **フロントエンド**  | https://youtu.be/TXi5g4J17ds |
| #3「 ブラウザApplicaation機能 」<br> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104530/52dda1f9-2ac1-858e-7d02-059d6d62ebaf.jpeg" width="400">| **フロントエンド** | https://youtu.be/DsHhKs9V03o | 
| #4「 Lighthouse 」<br><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104530/a8b9a0d6-5401-f979-8b90-e0fefb14618a.jpeg" width="400"> | **Webデザイナー/ フロントエンド**  |  https://youtu.be/srayKfhg5Ho |
| #5「 セキュリティ＆ネットワーク機能 」<br><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104530/efc0985f-ad96-fece-afef-7925e8057a50.jpeg" width="400"> | **Webデザイナー/ フロントエンド**  | https://youtu.be/Sn1oaEJwt0k | 
| #6「 CSSアニメーション検証機能 」<br><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104530/3d10870d-084c-82f0-024a-83058c7e5cf9.jpeg" width="400"> | **Webデザイナー**  | https://youtu.be/zICHhUf6-Nw |
| #7 新機能「 Recorder」を使って操作記録を残せ！<br>
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104530/6ea2bbdd-f9ec-eb4b-0010-3a220c0f66a6.jpeg" width="400"> | **Webデザイナー/ フロントエンド**  | https://youtu.be/4iH16Qj0j80 |


初学者のために「Webデザイナー/ フロントエンド」と領域を記載してますが、両方覚えて損にはなりません。
※一部、実務で使用してない機能は紹介だけにしてます。
 


 
  
-----------

:::message
今後も講義動画増えたら、こちらを更新していきます。
ブックマークしていただければ幸いです。
:::


https://www.youtube.com/channel/UCmMFmjhf1BXB1tlLcbkVRrg
 
-----------
Ubuntu で apt-get update が失敗する

# Ubuntu で `apt update` `apt-get update` が失敗する

## `apt update` `apt-get update` コマンドで 404 Not Found が発生してエラーになる

```bash
$ sudo apt update

Err:11 http://jp.archive.ubuntu.com/ubuntu zesty/universe Sources
  404  Not Found
```

## 404 Not Found の解決方法（１）

古いUbuntuを使っているので `/etc/apt/source.list` を書き換える。

```bash
# バックアップ
$ sudo cp -p /etc/apt/sources.list /etc/apt/sources.list.back
# 置換
$ sudo sed -i -e 's/archive.ubuntu.com\|security.ubuntu.com/old-releases.ubuntu.com/g' /etc/apt/sources.list
# キャッシュ削除
$ sudo rm -rf /var/lib/apt/lists/*
```

## 404 Not Found の解決方法（２）

[sources.list を作り直す場合](https://help.ubuntu.com/community/Repositories/CommandLine)

## ValueErrorが出てエラー終了する

```bash
$ lsb_release -s -i
Traceback (most recent call last):
  File "/usr/bin/lsb_release", line 95, in <module>
    main()
  File "/usr/bin/lsb_release", line 59, in main
    distinfo = lsb_release.get_distro_information()
  File "/usr/lib/python3/dist-packages/lsb_release.py", line 398, in get_distro_information
    distinfo = guess_debian_release()
  File "/usr/lib/python3/dist-packages/lsb_release.py", line 288, in guess_debian_release
    get_distro_info(distinfo['ID'])
  File "/usr/lib/python3/dist-packages/lsb_release.py", line 48, in get_distro_info
    RELEASES_ORDER.sort(key=lambda n: float(n[0]))
  File "/usr/lib/python3/dist-packages/lsb_release.py", line 48, in <lambda>
    RELEASES_ORDER.sort(key=lambda n: float(n[0]))
ValueError: could not convert string to float: '6.06 LTS'
```

## ValueErrorの解決方法

Pythonスクリプト `/usr/share/pyshared/lsb_release.py` を修正する

```diff
-RELEASES_ORDER.sort(key=lambda n: float(n[0])) 
+RELEASES_ORDER.sort(key=lambda n: float(n[0].split()[0]))
```
[Xcode]Unable to install "アプリ名" Error の対応

[Xcode]Unable to install "アプリ名" Error の対応

たまにこれに悩まれる人は、スマホのデータを消してみてください

# はじめに

冒頭で、説明させてもらいましたが、職場で、Unable to install "アプリ名"のエラー出てとても困ったんですよね。

何度かなってしまった時に、一番最初に考えないといけないのが、***スマホ容量の問題***

もしお困りでしたらぜひチェックしてみてください。


---

【About】(http://qiita.com/sunstripe) - サンストライプ

---

## 制作チーム：サンストライプ

[![sunstripe_logo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80600/322f2d60-f19d-af9e-2b6f-7290ca546848.png)](http://sunstripe.main.jp/)
http://sunstripe.main.jp/

(月１ WEBコンテンツをリリースして便利な世の中を作っていくぞ！！ボランティアプログラマー/デザイナー/イラストレーター/その他クリエイター声優募集中!!)

緩募


### 地域情報 THEメディア
THE メディア 地域活性化をテーマに様々なリリース情報も含め、記事をお届けしてます！！
https://the.themedia.jp/

### ゼロからはじめる演劇ワークショップ
多様化の時代に向けて他者理解を鍛える

https://workshop.themedia.jp/

### プログラミングワークショップ・ウェブ塾の開講！！！
様々なテーマでプログラミングに囚われずに取り組んでいきます。
詳しくはこちら　↓　↓　↓　↓　↓　↓　↓　↓
[プログラミングサロン 月１だけのプログラミング学習塾](https://workshop.themedia.jp/posts/7057553?fbclid=IwAR32CfRQ7RvDOhvuogoSwqxDLMOU7Jvuzljlnx-TMc27qBPX1BnWsfLcBR8
)

### 協力応援 / 支援者の集い
## チーム：サンストライプ
https://twitter.com/sunstripe2011

#### プログラミングラボ
https://twitter.com/PLab2020

一緒にポートフォリオを作りませんか？現場の体験やそれぞれの立場から年齢関係なく作品を作りたい方々と一緒にチームを作って、作品を作っています。現場に行きたい人には、職場紹介や職場の体験や悩み相談なども受けております。
様々な職種からプログラミングの知識を得たい、デザインの知識を得たい、データーベースの知識を得たいという人が集まっております。
週１のミーティングにそれぞれの近況と作業報告して、たまにリモート飲み会などをしております！！

興味がある方は、DMに話しかけてみてください。

#### トラストヒューマン
http://trusthuman.co.jp/
私たちは何よりも信頼､人と考えてます｡

｢コンサルティング｣と｢クリエイティブ｣の両角度から｢人材戦略パートナー｣としてトータル的にサポートします！！

### キャリア教育事業

#### 青空プログラミング
[![青空プログラミング100px.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80600/603d53ab-828b-645e-a415-1b6f158d7356.png)](https://actcoin.jp/project/detail.php?id=600)

[![ダウンロード (9).jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80600/9bde9318-28c2-ce74-d4c5-326168061bcc.jpeg)](https://www.youtube.com/hashtag/%E9%9D%92%E7%A9%BA%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0)

#### 広域学習支援プラットフォーム『のびのび日和』
https://slc-lab.amebaownd.com/

#スポンサー募集

## ネリム
https://nerim.co.jp/
配信事業などを映像コンテンツなどの制作しております

## ビヨンドXプロジェクト

[ビヨンドXプロジェクト全体会議](https://www.youtube.com/playlist?list=PLaR6-YWiGWkYhEHWnt8f1z-JC0g3nwwC9)
40 代おっさん Calendarサービスについて学ぶ

## 本記事ついて

本記事は プログラミング初学者の私が学習していく中でわからない単語や概要をなるべくわかりやすい様にまとめたものです。
もし誤りなどありましたらコメントにてお知らせいただけるとありがたいです。

## Calendarサービス

Calendarサービスとは
GASでGoogleカレンダーを操作するためのクラスとメンバーを提供するサービス

|クラス|説明|
|------|------|
|CalendarApp|CalendarAppサービスのトップレベルオブジェクト|
|Calendar|カレンダーを操作する機能を提供する|
|CalendarEvent|単一のイベントを提供する機能を提供する|

Calendarサービスのクラスは、CalendarApp→Calendar→CalendarEventと言う構造になっている。

流れ
CalendarAppクラスのメンバーでカレンダーを取得、そのカレンダーに対してCalendarクラスのメンバーを取得と言う流れになる。

＊Googleカレンダーのイベントは、配列で取り扱うことが多い

## 参考資料

<https://www.amazon.co.jp/%E8%A9%B3%E8%A7%A3-Google-Apps-Script%E5%AE%8C%E5%85%A8%E5%85%A5%E9%96%80-%E7%AC%AC3%E7%89%88/dp/4798064742>
開発におけるフィードバックの意味合い

タイミングごとに、
誰からのフィードバックなのかが変わるのだと思う。

投げてたボールが返ってきたぞ、の意味合いなのだと思っている。




でも、上位の存在からのリターンという認識が近しいのではないのかな。



つまり顧客側、あるいは末端のユーザ様からのお返事だと認識している。



違うと感じたら、コメントください。
【AWS】Webアプリケーションを作りたいと思った場合のシステム構成図

今回はAWSにてWebアプリケーションを構築したい場合、どういった構成がとれるのか、といった議題で執筆しようと思います。

# VPCを構築
まずVPCを構築しましょう。VPCとは、「Virtual Private Cloud」の略でAWS上に仮想ネットワークを構築することが可能です。

AWS上にVPCを東京リージョンで構築したとすると下記図になるかと思います
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306026/5e8f5146-4980-0369-9920-9feb5989c394.png)

#  サブネットを構築
次にサブネットを構築しましょう。サブネットにはインターネットとのアクセスを可能とする「パブリックサブネット」とVPC内で通信を行いインターネットとのアクセスを許可しない「プライベートサブネット」と大きく二つに分かれます。

パブリックサブネットとプライベートサブネットの違いは「インターネットゲートウェイ（IGW）」がサブネットのルートテーブルに設定しているかどうかと覚えているとよいかと思います。

では上記の図にパブリックサブネットとプライベートサブネットを構築してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306026/b60e75ea-73dd-6f10-1dd4-7e78d6cbf1f7.png)


ここでAvaliability Zone（アベイラビリティゾーン）というのが図に記載されていますが、アベイラビリティゾーンとはデータセンターと思ってください。データセンターを跨ぐことで、例えば災害などでデータセンターが停電などになった場合、サーバーが停止あるいは故障してしまう可能性があるのを防ぐことができます。図のような構成を「マルチAZ」構成と呼びます。

基本的にAWSでサーバー構築する場合はマルチAZ構成で構築することをおすすめします。

# EC2の構築
ここまで？？が飛んでいるかも知れませんが、ここからが本題みたいなところです。「Webサーバー」の登場です。

WebサーバーにはEC2やECSなどコンピューティングサービスを選択するとよいでしょう。また、サーバーレスアプリケーションとしてLambdaを選択するのもよいかと思います。

今回はEC2で開発するとします。

筆者はWindows系で開発することが多いので、EC2のWindows Serverを選択し、EC2構築後は日本語設定やIISを構築した後、.NETフレームワークのインストールなどを行い、C#でのアプリケーションを構築したりします。

ではEC2の構築した後のシステム構成を下記図に記載します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306026/731e713a-c2c1-eadc-6a90-0b7577e3cafa.png)

パブリックサブネットにEC2を構築しました。

# ALB（アプリケーションロードバランサー）の構築
ロードバランサーの機能を持つ「ELB」を用いてそれぞれのサブネットに構築しているEC2に振り分けを行います。

インターネットから例えば「 https://www.miya.com 」とURLをたたくと、今後投稿予定ではありますが、ACM（AWS Certificate Manager）にてhttpsを実現し、www.miya.comはRoute53にてドメイン解決を行い、www.miya.comをALBのURLをドメイン登録しておくとALBからそれぞれのサブネットに構築しているEC2へ振り分けをしてくれます。

冗長構成としての役割ともなりますし、例えばABテストなどにも活用することが可能です。同一セッションであれば同じサーバーへルーティングする「スティッキーセッション」を用いることでアクセスしているサーバー依存のアプリケーションにも対応しています。

ではALBの構成も図に記載します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306026/72d9bf1c-5a0b-2942-f3bc-9b7d73af9777.png)

# RDSの構築
最後にデータベースの構築をしましょう。例えばショッピングサイトなどのECサイトを構築した場合、注文履歴などをデータベースに登録する必要があります。Web上で買い物した場合にDBに書き込みを行うためにRDSを用います。

AWSにはRDSのほかにも、「DynamoDB」や「Redshift」、「ElasticCache」などがあります。リレーショナルデータベースが必要な場合やSQLを利用したい場合はRDSを選択しましょう。

RDSにはOracleやPostgreSQLなど幅広いリレーショナルデータベース管理システムが対応しています。その中でもAWSでは「Amazon Aurora」を推奨しています。Auroraを利用することで性能が格段に高まるので、できる限りAuroraを利用することをおすすめします。

# 最終的なシステム構成図
インターネット経由で接続をした場合、下記構成になるかと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306026/aaca0183-9e88-f681-2992-cb238196926a.png)

上記の構成には、まだネットワークACLやセキュリティーグループなどのファイヤーウォールの設定やルートテーブルの設定、ACMやRoute53の話ができていないため、説明としては不十分ですが今後投稿していけばと思います。
Python リストのある要素だけ除去したいとき

# 要素１つ

方法1. itertoolsのchainで範囲を指定する
方法2. listのpopメソッド

```python
import itertools

# 5番目の要素を取り除きたい
ls = [0,1,2,3,4,5,6,7,8,9,10]

# generater
genr = itertools.chain(range(0,5),range(6,11))
print('generater: ', [ls[i] for i in genr])

# pop
ls.pop(5)
print('pop: ', ls)
```

```
generater:  [0, 1, 2, 3, 4, 6, 7, 8, 9, 10]
pop:  [0, 1, 2, 3, 4, 6, 7, 8, 9, 10]
```

# 複数要素

方法1. itertoolsのchainで範囲を指定する
方法2. sortedのreverse & listのpopメソッド or delメソッド

```python
import itertools

# 5番目と８番目の要素(5と8)を取り除きたい
ls = [0,1,2,3,4,5,6,7,8,9,10]

# generater
genr = itertools.chain(range(0,5),range(6,8), range(9,11))
print('generater: ', [ls[i] for i in genr])

# pop or del
# 普通に削除すると、次に削除する要素位置を-1する必要がある
# 直感的に削除するためには、
# 削除したい要素を降順にソートすることで実現できる
for i in sorted([5,8], reverse=True):
    ls.pop(i)
    # del　でも結果は同じ
    # del ls[i]
print('pop(del): ', ls)
```
```
generater:  [0, 1, 2, 3, 4, 6, 7, 9, 10]
pop(del):  [0, 1, 2, 3, 4, 6, 7, 9, 10]
```
Reactでenvを導入したらエラーが起きた

## 前提

フロントエンドでwebpackを使用して開発をしている

下記が設定していた`webpack.config.js`

    const path = require("path")
    const HtmlWebpackPlugin = require("html-webpack-plugin")

    module.exports = {
      mode: "development",
      entry: path.resolve(__dirname, "./src/index.tsx"),
      output: {
        path: path.resolve(__dirname, "dist"),
        filename: "index.js",
      },
      resolve: {
        modules: [path.resolve(__dirname, "node_modules")],
        extensions: [".ts", ".tsx", ".js"],
      },
      module: {
        rules: [
          {
            test: [/\.ts$/, /\.tsx$/],
            use: [
              {
                loader: "babel-loader",
                options: {
                  presets: ["@babel/preset-env", "@babel/preset-react", "@babel/preset-typescript"],
                  plugins: ["@babel/plugin-transform-runtime"],
                },
              },
            ],
          },
          {
            test: /\.png/,
            type: "asset/resource",
          },
        ],
      },
      plugins: [
        new HtmlWebpackPlugin({
          template: path.resolve(__dirname, "./src/index.html"),
        }),
      ],
      devServer: {
        port: 8111,
        static: {
          directory: path.join(__dirname, "dist"),
        },
      },
    }

## 今まで
`yarn add dotenv`コマンドを実行し、envを使用する際に下記のように記入していた

index.ts

    import dotenv from "dotenv"

    dotenv.config()　　　　　　　 
    
    process.env.〇〇

## エラー

ターミナルで`npx webpack serve --config webpack.config.js`を叩いてブラウザで描画させようとしたら、
`ERROR in ./node_modules/dotenv/lib/main.js`というエラーが出た...

## 解決策

`yarn add -D dotenv-webpack`
コマンドを実行し、dotenv-webnpackを導入

webpack.config.jsに追加

    const Dotenv = require("dotenv-webpack")
    module.exports = {
    省略
    plugins: [
        new Dotenv(),
      ],
     }

index.ts

    const { TEST } = process.env //分割代入
    const test = TEST

必要だと思っていた下記を記入しなくてよくなった！

    import dotenv from "dotenv"
    dotenv.config()　　　　　　　

## 最後に

解決するまで意外と時間がかかってしまったので作成しました。
今まではNode.jsだったのでenvの使い方が違っていました...

## 参考記事

https://www.npmjs.com/package/dotenv-webpack
React Native 0.67.x にアップデートしようと思ったら、Expo 44.x の対応でいろいろあった件

先日、React Native を 0.67.x にアップデートしました。経験的に、React Native のメジャーアップデート（数字的にはマイナーバージョンアップデート？）の場合は、何から問題があったりしますが、今回は違った大変さだったので、記録として残したいと思います。

## React Native 0.67.x にアップデートしよう

既存アプリを早速 0.67 に挙げたところ、Android でビルドに失敗しました。ログを確認したところ、[Gradle が 7.2 にアップデート](https://github.com/facebook/react-native/blob/main/CHANGELOG.md#android-specific-4) されたことに伴い、Expo で失敗していました。Expo を Bare Workflow で利用してました。すぐさま、Expo の issue を見に行ったところ、対応中ということで、対応版のリリースを待つことになりました。

翌週、対応修正された Expo 44.0.6 が無事にリリースされました。それではと、0.67 のアップデート作業を再開したところ、今度は、iOS がビルドできない・・・。


## Expo 44.x に対応する

またまた、Expo の issue を覗きに行きました。Expo 44.x で「Swift ネイティブモジュールのサポートに伴い、Objective-C と Swift の統合で問題が起った。具体的には、ヘッダーファイルのインポートで Swift が正しく解釈できないために問題が起こる」とのこと。詳しくは [Kudo さんのコメント](https://github.com/expo/expo/issues/15622#issuecomment-997225774) を参照してください。

iOS 向けにネイティブモジュールを利用している一部のライブラリで、この Expo 由来の問題が発生しました。Expo の導入で、どうしても Expo の設定に引っ張られるため、対応せざるを得ないようでした。

Expo は素晴らしいサービスですが、React Native アプリの１ライブラリである Expo のせいで、他のライブラリを修正対応しないといけないのは何か考えることはあります。しかし、Expo 並のクオリティがあるもの、代わりになるものもそうそうないので、対応しました。

Expo チームが既に有名所のライブラリで issue や PR を出して、修正に動いていたので、ライブラリを対応版にアップデートするだけすみました。中には、うちのライブラリは Expo 向けじゃないから、そのままクローズするところもありましたが、これも正しい対応だと思います。また、リリースが遅いライブラリに関しては [patch-package](https://github.com/ds300/patch-package) を使って、自分でパッチを作って対応しました。

その他、自分で管理していたライブラリは Expo の問題には影響しなかったのですが、Gradle 7 対応にライブラリをアップデートしました。

## まとめ

React Native のアップデートで何か問題は起こるだろうと思って挑んだところ、React Native 本体とは異なるところで振り回されました。今回のアップデートは久々に疲れた。Expo の改修も前向きな意味があるものなので、いつかやらないといけないことを今回やったと思えば、よい前借りだったのではないかと思っています。
DynamoDBに作成済みのテーブルを複製したい！（手作業ではやりたくない）

仕事でDynamoDBの既存テーブルを複製する必要があり、一つずつ手作業で作成するのは大変だし、設定が漏れてしまう可能性もあるため、2コマンドで複製できるようにしてみました。

# テーブル情報作成用シェルスクリプト

第一引数に指定したテーブルの情報をコピーして`XXXX_copy`というテーブル名で出力するシェルスクリプトを作成します

```create-table-description.sh
#!/bin/sh

# テーブル名
TABLE_NAME=$1
TABLE_NAME_COPY=$1_copy

# 指定テーブルの定義を取得
DESCRIPTION=`aws dynamodb describe-table --table-name $TABLE_NAME`

# 必要な項目以外は削除
CONTENTS=`echo $DESCRIPTION |
          jq '.Table' |
          jq 'del(.ProvisionedThroughput.NumberOfDecreasesToday)' |
          jq 'del(.ProvisionedThroughput.LastIncreaseDateTime)' |
          jq 'del(.ProvisionedThroughput.LastDecreaseDateTime)' |
          jq 'del(.TableSizeBytes)' |
          jq 'del(.TableStatus)' |
          jq 'del(.ItemCount)' |
          jq 'del(.CreationDateTime)' |
          jq 'del(.TableArn)' |
          jq 'del(.TableId)' |
          jq 'del(.LatestStreamLabel)' |
          jq 'del(.LatestStreamArn)' |
          # テーブル名を変換して出力
          jq --arg table "$TABLE_NAME_COPY" '.TableName = $table'
          `

# グローバルセカンダリインデックスがある場合
if test `echo $CONTENTS | jq 'has("GlobalSecondaryIndexes")'` = true; then
  echo has GlobalSecondaryIndexes
  CONTENTS=`echo $CONTENTS |
            jq 'del(.GlobalSecondaryIndexes[].IndexArn)' |
            jq 'del(.GlobalSecondaryIndexes[].ItemCount)' |
            jq 'del(.GlobalSecondaryIndexes[].IndexStatus)' |
            jq 'del(.GlobalSecondaryIndexes[].IndexSizeBytes)' |
            jq 'del(.GlobalSecondaryIndexes[].ProvisionedThroughput.NumberOfDecreasesToday)' |
            jq 'del(.GlobalSecondaryIndexes[].ProvisionedThroughput.LastIncreaseDateTime)' |
            jq 'del(.GlobalSecondaryIndexes[].ProvisionedThroughput.LastDecreaseDateTime)'
            `
fi

# ローカルセカンダリインデックスがある場合
if test `echo $CONTENTS | jq 'has("LocalSecondaryIndexes")'` = true; then
  echo has LocalSecondaryIndexes
  CONTENTS=`echo $CONTENTS |
            jq 'del(.LocalSecondaryIndexes[].IndexArn)' |
            jq 'del(.LocalSecondaryIndexes[].IndexStatus)' |
            jq 'del(.LocalSecondaryIndexes[].ItemCount)' |
            jq 'del(.LocalSecondaryIndexes[].IndexSizeBytes)' |
            jq 'del(.LocalSecondaryIndexes[].ProvisionedThroughput.NumberOfDecreasesToday)' |
            jq 'del(.LocalSecondaryIndexes[].ProvisionedThroughput.LastIncreaseDateTime)' |
            jq 'del(.LocalSecondaryIndexes[].ProvisionedThroughput.LastDecreaseDateTime)' 
            `
fi

# jsonファイル出力
echo $CONTENTS > $TABLE_NAME_COPY.json
```

# DynamoDBにテーブルを作成

### 前提

- aws-cliインストール済み
  - `aws configure`でDynamoDBの読み書き可能なアカウントの認証情報を設定していること
- jqインストール済み
  - https://stedolan.github.io/jq/manual/　

### 実行 

```shell
# テーブル情報作成
./create-table-description.sh Test
# コピーテーブルを作成
aws dynamodb create-table --cli-input-json file://Test_copy.json
```

# 補足

データのコピーについてはDataPipelineでExport/Importする必要があるようです
https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/DynamoDBPipeline.html


# 参考
https://www.hands-lab.com/tech/t188/
https://docs.aws.amazon.com/cli/latest/reference/dynamodb/create-table.html
VRChat Unity

# VRChatにアバターとUpLoadしてみる

- もとねた　YouTube [【VRChat】超簡単！アバターをアップロードする方法【初心者必見】](https://www.youtube.com/watch?v=JzI_ZdFTTpw)
- Unity2019
- 【3Dモデル】[『のん』BASIC PACK](https://booth.pm/ja/items/3204884)

## 2022/02/26 Unity起動するも VRChatがVisitorでNG...

- NONを[DL](https://booth.pm/ja/items/3204884?registration=1)
- シェーダーの[DL](https://unity-chan.com/download/releaseNote.php?id=UTS2_0)
- VRChat SDK3の[DL](https://vrchat.com/home/download)
- Unity ３D＞新規作成
- SDK3 をインポート
- シェーダーをインポート
- アバターをインポート
- VRChatに接続
- AutoFix
- ダイナミックボーンの削除
- VRChatのアカウントがVisitorなのでUPできず．．．

## 2022/02/25 チャレンジ開始

- 動画をみて Unity2019のインストール
ProxmoxVEのPinningによるCPUパフォーマンス向上

## はじめに
実機のマシンに限りなく近い性能を出すためにGPU Passthrough、HugePageといった設定を行なってきた。CPU Pinningという手法を今回試してみる

## CPU Pinningとは
物理マシンで12スレッドあり、仮想マシンに4スレッド割り当てた場合を考える。物理CPUの4スレッドだけを使用すると思ってしまうが、実際には12スレッドを満遍なく使用する。例えば2スレッド5台の場合には複数の仮想マシンの処理を同じ物理スレッドで行うためパフォーマンスが低下してしまう。
物理スレッドと仮想スレッドを1対1で固定するのがCPU Pinningである。

## 効果あるの？
MicrosoftのCpuStresを負荷確認に使用
https://docs.microsoft.com/ja-jp/sysinternals/downloads/cpustres
スレッドの効率をSandraでベンチマークした
https://www.sisoftware.co.uk/

CPUをCpuStresで使用率100%にする
![スクリーンショット 0004-02-25 5.01.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65278/92128893-cbf4-80c4-c6f9-b3d5f60e9545.png)

### 設定前
親から見た使用状況。スレッドが4以上に分散していることがわかる
![スクリーンショット 0004-02-25 5.02.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65278/d2984757-89ca-0474-16a0-1f0c749db0c7.png)
Sandraの結果
![スクリーンショット 0004-02-25 5.09.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65278/158d89ee-2b99-f020-cf48-f1e05bcc7767.png)
![スクリーンショット 0004-02-25 5.10.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65278/18f56ebf-8919-967f-6fdc-967ac14e718e.png)

### 設定後
スレッドが4に固定されている
![スクリーンショット 0004-02-25 5.14.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65278/5460a95d-8285-6e68-dcc0-3fb18d8327be.png)
Sandraの結果。スレッド間の帯域幅が向上していることがわかる
![スクリーンショット 0004-02-25 5.20.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65278/11c326f5-4178-44df-71fb-0c26de148764.png)
![スクリーンショット 0004-02-25 5.21.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65278/c5a1009a-8457-3732-364d-af28b5f51780.png)

## 基本的な設定方法

### 追記
ProxmoxVEのアップデートによりCUIでtasksetを実行するのと同じことがGUI上でできるようになったので、そちらの方法を推奨

https://qiita.com/disksystem/items/f0e96dcded20d33772dc

仮想マシン起動後にホストの方で以下のようなコマンドを実行する

```bash
taskset --cpu-list --all-tasks --pid 固定するスレッド番号 プロセスID
```

スレッド番号は0始まりで12スレッドなら0〜11となる。数値を入力しても良いが、「0-3」等の範囲指定もできる。プロセスIDはVMのプロセスIDを指定する。
VMのプロセスIDは「/run/qemu-server/VM番号.pid」で取得できるので、4スレッド、VM番号107の場合は以下のコマンドとなる

```bash
taskset --cpu-list --all-tasks --pid 0-3 $(< /run/qemu-server/107.pid)
```