OmniAICreator/Qiita-1.07M huggingface dataset:
mayaのカメラを保護したい

レイアウトの人がカメラを設定して
カメラのアニメーションをつけた後に
アニメーションの人にパスするときに
アニメーションではカメラをいじらないでほしい場合もあるそうで。

じゃぁカメラをかなり頑張らないと編集できない状態にしてみよう　という試み

案出し
-
幾つか考えられるが

- カメラ自体をリファレンスする
- カメラのアニメーションもリファレンスする
- カメラをabcキャッシュにする
- カメラノードをロックする

と　色々考えられるのでやってみますか

カメラ自体をリファレンスする
-

カメラを適当に保存して、新規シーンにリファレンス
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/38554577-396b-f8ad-8260-1e5a75c754f0.png)

- キーは打てない
- ロック状態にはできない
- キーフレーム打てないけど動かせはする

さて、ここで問題が
- break　Connectionsできる
- からの　キーフレーム再設定できる

ん～　わりと簡単に突破できるので駄目ー


カメラ自体をリファレンスする　あらかじめアトリビュートロックしておく
-

リファレンスしてるんだからロックの状態を変更できないはず！
なので、保存する際にロックしてしまえば・・・・

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/07292581-0b8b-d43f-4b23-f7e1d9209a59.png)

さあどうだ

- アンロックできない

お、これなら・・・・
ここで、新たな敵が参入

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/a6b2da0e-e98b-8bca-6f47-69fdeca7da4a.png)

コレ

ポチポチやったらロックがよぅ！アンロックされたよぅ！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/1842107b-d159-cbe8-830a-747ef600f401.png)

こうなっちまったら
- break　Connectionsできる
- からの　キーフレーム設定

で突破されてしまう・・・・

カメラをabcキャッシュにする
-
キャッシュにしちまえば・・・・

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/af18de59-3b13-797e-3212-a1ac090748f3.png)

なるほど・・・キャッシュになるのはキーフレーム部分・・・・
結構簡単に突破できますね
読み込み方次第なのかなぁ・・・

カメラノードをロックする
-
カメラ(アニメーション付き)を import して、
lockNode でロックしてしまえば・・・・・

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/4ad0376a-2051-1596-6616-fc03b5b674a8.png) < 余裕っす

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/c721669a-4ea0-ef8a-43cb-51cae01b560d.png)


いやまって、カメラロックボタン強すぎる。
なにこれ、エクスカリバーなの？

カメラのアニメーションもリファレンスする
-

もう諦めモードですが、まぁ一応。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/daf5e159-2601-567e-c392-eedfb2b98c2f.png)

ん～
- break　Connections
- からの　キーフレーム設定

ですわよねぇ・・・・

まとめ
-

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/4ad0376a-2051-1596-6616-fc03b5b674a8.png)
これが強すぎる。

あまり気にしてなかったけど、かなりの強制力を持っている。

これは対抗できる方法があるのか・・・

次回に続きます。
ColaboratoryでGoogleのdracoを使えるようにする

以下をセルで実行します。
素直にcmakeでMakefileを作ってmakeすれば実行ファイルを作成できました。

```
!git clone https://github.com/google/draco.git
%cd draco
%mkdir build
%cd build
!cmake ../
!make
%cd /content
```
NotionのDatabaseでID列を作って自動採番（auto increment/オートインクリメント）を実現する

Notionでデータベースを作成したときに、下記のようにNewで新しい行を追加したときにID列のを自動採番したかったのですが、やり方がわかりづらかったのでその手順と仕組を紹介します。
![スクリーンショット 2022-12-14 23.27.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238254/504f0c8a-77b3-0cc0-0824-90d809940733.png)

こちらのページをそのまま使わせていただきました。

https://notionthings.com/2022/03/06/auto-increment-table-row-ids/

# NotionのDatabaseで自動採番列を作る方法

Notionのデータベースのデフォルトの機能では自動採番がまだ実装されていないようで、少し複雑な処理を自分で作る必要があります。

## 1. テーブルを作成する

まずは対象となるデータベースを作成して、最初にLong ID列を用意します。今回はSampleという名前のテーブルを作成しました。
Formulaで`id()`を返すように設定しておきます。

![スクリーンショット 2022-12-14 23.49.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238254/0c9d2682-45c5-e26e-b12d-b0ed91c12eb3.png)

## 2. 親となる別のテーブルを用意する

1.で作成したテーブルとは別に、参照用の親テーブルを作成します。
今回はMasterという名前で作成しました。そのテーブルに同じくMasterという名前のレコードを1つだけ作成しておきます。

![スクリーンショット 2022-12-15 0.16.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238254/8d28764e-2297-be6a-1980-31c8fc8b06a0.png)



## 3. 親へのRelationを設定する

SampleテーブルのPropertyでMasterへのRelationを双方向で作成します。
こちらのスクショの後に、Show on MasterプロパティをONにしてください。

![スクリーンショット 2022-12-14 23.35.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238254/150bebb7-3383-a0fb-ae95-479d9c491974.png)



## 4. テーブルのFilterで親テーブルのレコード名を設定する

![スクリーンショット 2022-12-14 23.57.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238254/6f3e7788-968a-a53c-5c4a-5d90ff956d40.png)



## 5. 親テーブルのCreated IDs Rollup列を作成する

MasterテーブルにCreated IDｓ Rollupという名前の列を作り、SampleテーブルのLong　IDを参照する列を作ります

![スクリーンショット 2022-12-15 0.06.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238254/5075ecb6-bd49-b294-163c-58e6f87a58db.png)


## 6.  親テーブルにCreated IDs列を作ってCreated IDs Rollup列を参照するようにする


![スクリーンショット 2022-12-15 0.07.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238254/d19f6901-0eeb-5d66-5041-d01e509b1a28.png)

## 7. 親テーブルのCreated IDsをRollupして参照する列を追加

![スクリーンショット 2022-12-15 0.08.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238254/28470fc4-feba-acea-ad07-684c65bda16a.png)


## 8. テーブルのID列下記のFormulaを入力する

```
length(replaceAll(replaceAll(replaceAll(prop("Created IDs"), format(prop("Long ID")), "T"), "[^T]*$", ""), "[^,]", "")) + 1
```

![スクリーンショット 2022-12-15 0.09.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238254/d00fd8db-3138-ba59-c156-d5843dbb5a86.png)


これでできるようになったはずです。


## 解説

親テーブルと対象となるテーブルでIDをRollupして通すことにより、全レコードのIDが連続して取得できます。
それに対して、自分自身のLongID以降のIDを削除し、区切り文字であるカンマの数を数えることで自動採番を実現しています。

# 参考

https://notionthings.com/2022/03/06/auto-increment-table-row-ids/

https://dev.classmethod.jp/articles/create-task-dependencies-with-notion-relation/
TXシャドウボムというのをつくってみました　

# 作成物について
https://twitter.com/wotakuro/status/1585603363659337728

まずは作っているものです。

このように動き回る toioをボトルマンで当てると言った内容のゲームを作っています。

#配布場所等
Android版実行ファイル：
https://github.com/wotakuro/toio_and_bm_project/releases

WebGL版実行ファイル：
https://wotakuro.github.io/TxShadowBombGL/

# 大まかな構成
アプリケーションは toio SDK for Unityを利用して作成しております。
Androidアプリとして書き出し、Android搭載のプロジェクターとtoioコアキューブが直接通信をしてゲームを進行させています。
また下に投影している部分は toioの開発者マットを敷いていて、絶対位置を取得して設定したエリアから出ないように制御もしています。

※プレイエリアから出ない様子はこちら
https://twitter.com/wotakuro/status/1517539396257390598

# 3Dプリンターによる造形物
こちらでは toioだけだなく 3Dプリンターで作成した側を toioにつけて動かしています。
https://www.youtube.com/watch?v=Gb1a6g5Lbfw


こういう形でガワ部分を作ったのにはいくつか理由があります。
・見た目で盛り上がる！（これ一番重要です！）
・toioが小さくて的として当てるのが難しかったので少し大きくする
・toioが軽く、強い勢いで当たると姿勢が崩れるなどしたので、重さを増すためにも使用

この TXシャドウボムのガワですが、最初からこのような形ではありませんでした。

https://twitter.com/wotakuro/status/1483446963962249216
初期型はこんな感じでした。
当初はすごい勢いでキャップが当たるなどしたら少しバランスを崩して、衝突判定が2回入るなどの問題に当たりました・・・。

とある場所で「３Dプリンターだけではレゴの接着力には及ばないので、実際にレゴのパーツで接着したほうが良いです。あと重心も低く・・・」というアドバイスを受けて、現在の形となりました。

# ソフトウェアでの工夫について

今回工夫したことが ユーザー側でプレイエリアを設定できるようなコンフィグを作りました。
これによって、どのtoioプレイマットでもある程度遊べるようにしています。

またプレイマットが検知されなかった場合、自動的にフォールバックして動作するようにも作っています。
これによって、プレイマットがなくても最悪遊べるようにもしています。

このように 1つのアプリと toioがあればいろんなシチュエーションで遊べるようにしたというのが工夫です。

またプレイマットの検知も少し工夫が入っています。
それはプレイマットを検知するときにtoioを軽く回転させる処理をしています。
これは、ゴミがあったなどの理由から toioマットにおいているにも関わらず、toioマットを検知しなかった対策になります。


こんな感じで、TXシャドウボムという形で作ってみました。
ReactHooksについてまとめる（Ref Hooks）

# 概要
Refは、DOMノードやタイムアウトIDなど、レンダリングに使用されない情報をコンポーネントに保持させることができる。
Stateとは異なり、Refを更新してもコンポーネントは再レンダリングされません。RefはReactのパラダイムからの「逃げ道」です。組み込みのブラウザAPIなど、React以外のシステムで動作させる必要がある場合に便利です。

## useRef
useRefは同じオブジェクトを返します。currentプロパティを変更して情報を保存して、あとでそれを読み出すことができます。

**refを変更しても、再レンダリングは行われません。** つまり、refはコンポーネントの視覚的な出力に影響を与えない情報を保存するのに最適なのです。例えば、インターバルIDを保存しておき、後でそれを取得する必要がある場合、それをrefに入れることができます。ref内の値を更新するには、そのcurrentプロパティを手動で変更する必要があります。

### refを使用することによるメリット

- 再レンダリングされても情報を保存することができる
- refを変更しても、再レンダリングのトリガーにはならない（stateとは異なります。）
- コンポーネント間で共有される。

refを変更しても再レンダリングを行わないということは、画面に表示したい情報を保存するにはrefは適切ではありません。

https://codesandbox.io/embed/epic-glitter-87mv6d?fontsize=14&hidenavigation=1&theme=dark

上のcodesandboxの中で、`{ref.current}`を画面に表示するように修正しても、ボタンをクリックして`ref.current`に加算してるのにも関わらず画面は再レンダリングされないために表示は`0`の初期値のまま変わりません。



### refを利用してDOMを操作する

refオブジェクトを宣言します。`useRef`の引数には初期値を入れます。
```jsx
import { useRef } from 'react';

function MyComponent() {
    const inputRef = useRef(null);
    // ...
```

次に、作成したrefオブジェクトを操作したいDOMのref属性に代入します。
```jsx
return <input ref={inputRef} />;
```

refオブジェクトのcurrentプロパティから<input>のDOMノードにアクセスして、`forcus()`などのDOMのメソッドを呼び出すことができます。

```jsx
function handleClick() {
    inputRef.current.focus();
}
```

useRefを使用した例

https://codesandbox.io/embed/sweet-banzai-k2uec3?fontsize=14&hidenavigation=1&theme=dark

### カスタムコンポーネントに対して、reｆを使用したい時

```jsx
const inputRef = useRef(null);

return <MyInput ref={inputRef} />;
```
↑ だとカスタムコンポーネントにrefsを与えられない旨のWarningが表示されます。

```
Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
```

そんな時は `forwardRef`でラップして、その中のDOMにref属性を与えることで親コンポーネントからrefを取得することができるようになります。

```jsx
import { forwardRef } from 'react';

const MyInput = forwardRef(({ value, onChange }, ref) => {
  return (
    <input
      value={value}
      onChange={onChange}
      ref={ref}
    />
  );
});

export default MyInput;
```

## useImperativeHandle
refで参照できるDOMの関数をカスタマイズすることができます。

例えば、<input> DOMノード全体を公開するのではなく、その中の2つのメソッド（focusとscrollIntoView）のみを使用したいとします。これを行うには、実際のブラウザDOMを別のrefに保持します。そして、useImperativeHandle を使って親コンポーネントが呼び出したいメソッドの`forcus()`と`scrollIntoView()`だけを含む関数を定義します。

```jsx
import { forwardRef, useRef, useImperativeHandle } from 'react';

const MyInput = forwardRef(function MyInput(props, ref) {
  const inputRef = useRef(null);

  useImperativeHandle(ref, () => {
    return {
      focus() {
        inputRef.current.focus();
      },
      scrollIntoView() {
        inputRef.current.scrollIntoView();
      },
    };
  }, []);

  return <input {...props} ref={inputRef} />;
});
```

useImprerativeHandleの使用例

https://codesandbox.io/embed/keen-neco-2gvco8?fontsize=14&hidenavigation=1&theme=dark


### カスタマイズ
使用するメソッドは、DOM のメソッドと完全に一致する必要はありません。なので、開発者が任意にカスタマイズして処理を作成することも可能です。

以下の例では、ボタンをクリックした際に親コンポーネントがリストをスクロールしてテキストボックスにフォーカスを当てる動きを `scrollAndFocusAddComment` が行っています。

https://codesandbox.io/embed/reverent-gianmarco-8jvis1?fontsize=14&hidenavigation=1&theme=dark


# 参考
https://beta.reactjs.org/apis/react/useRef

https://beta.reactjs.org/apis/react/useImperativeHandle
〇✕ゲーム

# はじめに

今回は**HTML**、**JS**、**CSS**だけで〇✕ゲームが作れるので簡単に紹介したいと思います。

# 〇✕ゲームって？
ほとんどの人が一度はやったことがあるとは思いますが一応説明すると、

「３×３のマス目」があって〇と✕を交互に置いていって縦、横、斜めのどれかで先に３つ揃った方の勝ちというルールです。

簡単ですね。　

# 完成形
「**〇の番！**」と表示されていて、クリックしたマス目の場所が〇になります。
![〇✕ゲームHTML.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003776/a8ea05d1-eed5-3468-e134-4de35d54857a.png)


# HTMLコード
![html.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003776/b7e72777-8f31-2f98-d567-b610935f70f4.png)

# cssコード
![css.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003776/0b962a77-4c4f-6b68-4ae1-0f18bcd9891e.png)

# JSコード（少し長いです）
![1~37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003776/bf087553-aa75-12d3-541f-9b558bcc8c47.png)
![37~73.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003776/e060199d-4fab-718b-de7f-817334c8bfa0.png)
![74~109.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003776/f11e71c6-2aa8-886c-8ca6-cd4e079fcabe.png)
![110~146.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003776/01db4cdd-3f7b-2070-ee57-a53a3535c0c4.png)
![147~182.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003776/503150a1-a20c-769b-bfb2-e635c62467a9.png)
![183~219.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003776/7e1ecdb2-5929-e858-7c43-df622eedc285.png)
![219~241.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003776/5b8fe73a-6a36-83c9-393d-78889e68cde5.png)

# 最後に
簡易的なゲームならすぐに作れてしまうのがプログラミングを学ぶ上での醍醐味の一つかもしれないですね。他にも色々やってみたいです。

![引き分け.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003776/4c0787c5-611c-67fc-008d-23f883cabc33.png)
DevContainerとGit（Github）の便利TIPS集


みなさん、DevContainerは使っていますか？最近個人開発の中でDevContainerを触ってみたところ便利な機能や設定をいくつか発見しましたので、備忘録がてら共有したいと思います。

## Dev > Containers: Copy Git Configは必ずONに！
この設定にチェックを入れることで、ローカルのgitの設定（git config --global で設定しているもの）がDevContainer上でも引き継がれます。GPGキーも引き継がれるのでとても便利！[^1]
DevContainerの設定はコマンドパレットを開いて`Dev Containers:  Settings for Dev Containers` から確認できますよ！

## ghを使えると便利！
devContainerを０から作成する画面の`Select additional features to install` から`GitHub CLI`が選べるのですが、これがとても便利！大きなできることを挙げると
- PRの作成・確認（途中までCLIで作って続きはブラウザから！も可能）
- Issuの一覧確認
- Gistの作成
- GPG・SSH　Keyの設定

## ghの設定方法
ghはGithubCLIをインストールするのみですと、GHの環境変数がローカルから引き継がれず新しい環境を作るたびにGHの設定が必要になります。以下は環境変数をローカルから引き継ぐ時に私が行った方法です。[HOST]はMac側での操作が必須の作業となります。
1. [HOST] `cat ~/config/gh/hosts.yaml` 等のコマンドでGHの設定を確認する。
2. [HOST]  シェルの`.シェル名rc`に下記を追記する
    ```
    export GITHUB_TOKEN="[1.で確認したoauth_tokenのValue]"
    export GITHUB_USER="[１. で確認したuserのValue]"
    ```
3. シェルを再起動し、`code (DevContainerしたいDir)` し、Rebuild Containerを行う。

## ターミナルでgit commitで開かれるエディターがデフォルトVSCodeになった！
何も設定せずに、ターミナルでgit commit と打つとエディターに移ると思うのですが今まではデフォルトがnanoでExitのキーバインドがVSCodeのキーバインドと被っておりCommitしずらいという問題がありました。
しかし、デフォルトがVSCodeになったことで可読性や描きやすさが大幅に向上しました！
DevContainer上では確認していますが、ローカルのターミナルは未検証ですが、検証する際は` git config --global core.editor vim` 等にしてからがおすすめです。
    

## git push時に `fatal: detected dubious ownership in repository at '/workspaces/プロジェクト名　...`というエラーが出る時の対処方法

自分の場合は、プロジェクトのルートディレクトリーのownerだけがrootになっており、これを修正する必要がありました。 そのときは、`chown [各ファイルの所有者の名前]　.`というコマンドを打つことによって権限周りを正常に戻し、Pushが可能になります。



---
参考資料
https://github.com/devcontainers/features/tree/main/src/github-cli
https://webkaru.net/linux/chown-command/

[^1]: [GPGの設定方法について](https://qiita.com/yuriacats/items/c331f6d8dda75a2819f2)の記事も書いてます…！
Shift-right系の論文や書籍を調べてみた

## はじめに
最近テストや品質保証の世界で頻繁にShift-rightやTesting in productionという言葉を聞くので、世界的にどれぐらいメジャーなのかを調べてみました。そこから新しい知識や次の調査項目が見つかるといいな、と思いつつ。

## 調べ方
基本的にはGoogle scholarでキーワード検索をします。関係ない分野のPaper等が引っ掛かる可能性もあるので、検索後人手でフィルタリングをします。

## Shift-right
まずは一番広い用語と思われるShift-rightからです。

検索キーワード："Shift-right testing"
ヒット数：10

数としてはそこまで多くないことがわかります。アカデミックな分野ではまだあまり用語としては使われていないようです。
[こちらの修士論文](https://www.theseus.fi/bitstream/handle/10024/135804/Williams_Paivi.pdf?sequence=1&isAllowed=y)では以下のように書かれており、Testing in productionと同義であるという言い方がなされています。一定のリスクを許容した上で、ユーザのフィードバックを早く受ける、ということの価値は理解するものの、それは果たしてTestingなのか、という疑問はわきますね。
>Wagner’s definition of shift right testing is simply testing software in production. Shift right testing ideology is making a conscious decision to carry a certain level of risk deploying to production so that the business can get end user feedback faster and beat their competition to market. Delivery teams can also validate a hypothesis they are experimenting with

また、アカデミックな分野ではないですが、[このブログ](https://www.dynatrace.com/news/blog/what-is-shift-left-and-what-is-shift-right/)には以下がShift right testsに分類されると書かれています。
- A/B testing.
- Synthetic monitoring.
- Chaos engineering.
- Canary releases.
- Blue-green deployment.

## Testing in production
次に、前述の通りShift-right testingと近い用語であるTesting in productionです。
下表のとおり、Shift-right testingよりはヒット数が多いですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529567/26a4e491-3737-099e-47ab-c41d93ebcaa9.png)

[この発表](https://www.researchgate.net/publication/325788525_Strategy_for_Continuous_Testing_in_iDevOps)では、”feature toggling”、”A/B testing”、”monitoring”がTesting in productionに分類されると説明されています。

おそらく単にシフトライトと呼ぶよりはTesting in productionの方が意味が明確であるため、アカデミックな分野では用語として使いやすいのかもしれません。

## Chaos testing
まだ調査中なのでおまけ的な扱いですが、Chaos testingについても調べてみたので掲載しておきます。
結論から言うと、全然ヒットしませんでした。おそらく、前述の通りChaos engineeringで調査するのがよかったのでしょう。ここについてはこれからの課題として残しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529567/37431607-ef8f-c9ed-9905-28d69ba53153.png)

## まとめ
調査してみた結果、Testing in productionで調べると少なくない数の文献が見つかりました。
調査のモチベーションとしては、本質的にシフトライトしなければならないテストとは何なのか、ということだったので、見つかった文献を読むのに加えてTesting in productionに分類される技法などをより詳細に調べることで、当初の疑問を解決したいと思います。
Amazon Textractを試す

re:Invent 2022にてAI、MLに関するアップデート情報を見ていた所、Amazon Textractがアップデートという情報を見つけました。
私自身もこんなサービスもあったのかと思ったので、紹介させていただきます。

### ■概要
まずAmazon Textractとは何という話ですが、以下が概要になります。

Amazon Textract は、スキャンしたドキュメントからテキスト、手書き文字、およびデータを自動的に抽出する機械学習 (ML) サービスです。これは、単純な光学文字認識 (OCR) のレベルにとどまらず、フォームやラベルからデータを識別、理解、および抽出します。

### ■コンソール画面紹介
では実際にコンソール画面を見てみます。（新機能を試す為、オレゴンリージョンです）
開くと下記のような画面に進みましたので、画面右の「Amazon Textractを試す」を押下し、実際に触っていこうと思います。

![画像1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954355/9fdc6b65-321d-5b8a-45f2-b86179c1e505.png)


### ■テンプレートでの挙動
「Amazon Textractを試す」に進むと、早速テンプレート画像が表示されました。
取得項目には、「生のテキスト」「フォーム」「テーブル」「クエリ」「署名」の5項目あります。
下記テンプレート項目のキャプチャになります。（今回クエリの項目はなかったです）

生のテキスト
![テンプレ1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954355/77ac208a-0452-74e3-0daf-cd473b9eb5c6.png)

フォーム
![テンプレ2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954355/184091af-18ed-4c64-deb0-5e0df539af34.png)

テーブル
![テンプレ3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954355/80b3234a-f2dd-f3a1-35db-e9d1d5ea7e92.png)

結果はダウンロードする事もでき、zip形式で取得できます。
中身はcsv、textなどに分けられ、結果をまとめたjsonもありました。

### ■アップデートされた機能について
アップデートされた機能は２つあります。
1つ目は、上記の取得項目の中の署名の項目です。

書類への署名箇所を署名として認識されています。
![署名.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954355/1b74d592-7798-cbf7-2013-edf38bda2041.png)

２つ目は、Analyze Leadingです。
これは複数画像をタイプ別に自動で分類および分割し、重要な情報フィールドを抽出する、という内容のようです。

下記スクショの通り、サマリー部分に項目毎の合計が表示されます。

![Analyze.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954355/c0be1bd3-70f3-0425-90a4-b86aefde8f7e.png)

### ■手書きしたものをスキャン
実際に手書きしたものをスキャンしてみます。↓

サンプル１枚目
![S__21028892.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954355/03a4389a-8f94-9f24-8a6a-6bcf1bb461ee.jpeg)

サンプル2枚目
![S__21028912.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954355/043ce481-9ffe-3fe7-7d0e-79f321a60324.jpeg)

### ■１枚目スキャン
想定通り、スキャンされました！
![サンプル結果1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954355/16229eac-2383-a302-4cd7-414caad7b40a.png)

新機能の署名も問題なく検出されました！
サインっぽく書かなくても検出されるんですね
![サンプル結果2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954355/958dc96d-77bf-e7d8-d434-5facb71dc107.png)

### ■2枚目スキャン
テーブルも想定通りいけました！

![サンプル結果3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954355/63812df3-8c24-9999-729f-13df61b8c357.png)

### ■おわりに
手書きしたものでもしっかり認識できていますね！
特にサインの所は署名と判断されないと思ってたので、少し驚きでした。

現在の業務上ではなかなか使う機会がなさそうですが、大量の書類の整理に悩まされている方は是非利用してみてください！
【Vue】Vue3が標準の時代にVue2アプリを構築する手順の備忘録

## 概要
ネット記事のほとんどが Vue3 前提の情報ばかりになってしまったが、
Vue3 に未対応の一部のライブラリやプラグインを利用する等の理由で、Vue2 のアプリ構築方法を探している人のための構築手順の備忘録。

更に、ライブラリ対応の一例として v2 の Vuetify を導入する。

[Vue CLI](https://cli.vuejs.org/) は現在メンテナンスモードになっており、通常のVueアプリ構築では利用非推奨となっていることに注意する。

## 前提

- Vue： v2.6.14
- Vue CLI： v5.0.8
- Vuetify： v2.6.13
- TypeScript は使用しない

## Vue2 アプリ構築手順

Vue CLI をグローバルインストールする

```bash
npm install -g @vue/cli
```

Vue CLIで Vue2 のプロジェクトを作成する

```bash
# プロジェクト生成（今回は「vue2-demo」という名前で作った）
vue create vue2-demo
```

以降、以下のように質問形式でVueバージョンなどを答える

```bash
#  Vueのバージョンを選択（v2 を選択）
? Please pick a preset: 
  Default ([Vue 3] babel, eslint) 
❯ Default ([Vue 2] babel, eslint) 
  Manually select features 

# yarn と npm どちらのパッケージマネージャを利用するか（npm を選択）
? Pick the package manager to use when installing dependencies: 
  Use Yarn 
❯ Use NPM 


# 以降、自動で処理が進む...
✨  Creating project in /Users/tommy/github/test/vue2-demo.
🗃  Initializing git repository...
⚙️  Installing CLI plugins. This might take a while...

added 86 packages, and audited 935 packages in 5s

102 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
⚓  Running completion hooks...

📄  Generating README.md...

# ここまで表示されたらプロジェクト生成完了！！
🎉  Successfully created project vue2-demo.
👉  Get started with the following commands:

 $ cd vue2-demo
 $ npm run serve
```

### 動作確認

ローカルサーバ起動

```bash
npm run serve
```

`localhost:8080` にアクセスして以下の画面が出ればOK
![Vue2確認.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/2bde7110-c903-262c-e38e-f1b10692db9f.png)


## Vuetify v2を導入してみる
Vuetify v2 のコンポーネントはまだ v3 に完全移行できておらず、v2でしか利用できないコンポーネントがある場合は、Vue2 のプロジェクトに Vuetify v2 を追加しなければいけない。

以下のコマンドを実行して Vuetify をアプリに追加する

```bash
vue add vuetify
```

以降、質問形式でバージョンを答える

```bash
# コマンド実行後
📦  Installing vue-cli-plugin-vuetify...


added 8 packages, and audited 943 packages in 2m

103 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
✔  Successfully installed plugin: vue-cli-plugin-vuetify

# プリセットを選択（デフォルトで選択されている推奨設定で OK）
? Choose a preset: (Use arrow keys)
  Vuetify 2 - Configure Vue CLI (advanced) 
❯ Vuetify 2 - Vue CLI (recommended) 
  Vuetify 2 - Prototype (rapid development) 
  Vuetify 3 - Vite (preview) 
  Vuetify 3 - Vue CLI (preview) 

# 下記の表示が出たら追加完了
 vuetify  Discord community: https://community.vuetifyjs.com
 vuetify  Github: https://github.com/vuetifyjs/vuetify
 vuetify  Support Vuetify: https://github.com/sponsors/johnleider
```

### 動作確認

ローカルサーバ起動

```bash
npm run serve
```

`localhost:8080` にアクセスして以下の画面が出ればOK
![Vuetifyv2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/991f0f7b-20b8-b709-fd4d-4ae179b503e3.png)

同じ画面にアクセスしているが、見た目が Vuetify 追加によって少し変化している。
あとは、[公式ドキュメント](https://vuetifyjs.com/ja/)をみながらコンポーネントを追加利用するなどできる。
Azure Backupの３つのシナリオ

●Azure Backup
Azure仮想マシンのディスクであるVHDファイルは、Azureストレージアカウント内に格納される。そしてAzureストレージアカウントでは冗長性を担保するために最低でもローカル冗長ストレージ(LRS)が構成されており、３つにミラーリングされている。そのためAzureデータセンター内でのディスク障害によって仮想マシンのディスｋが失われる可能性低いが事前のバックアップは重要。

Azureにはシンプルで信頼性の高いクラウドサービスのバックアップソリューションとしてAzure Backupというサービスが用意されている。効率的な増し分バックアップを行い、バックアップデータは暗号化された上で信頼性の高いRecovery Servicesコンテナーという場所に保存される。Recovery Servicesコンテナーでは既定でgeo冗長(GRS)で構成されるため、リモートサイトも含めて計６重のバックアップデータのコピーを維持できる。

●Azure Backupの３つのシナリオ

・ファイルおよびフォルダ、システム状態の保護
Windows OSを実行するコンピューターにAzureBackupのエージェントプログラムであるMARSえージェントを導入し、ファイルとフォルダ、システム状態の保護を行うというシナリオ。
Azureエージェントともよばれる。

・仮想マシンの保護
Azure上で実行されるWindowsまたはLinuxの仮想マシンんを保護するシナリオ。

・ワークロードの保護
ネットワークにSystem Center Data Protection Manager(DPM)をベースとしたMicrosoft Azure Backup Server(MABS)を導入することで、ネットワーク上のWindowsコンピューターが実行する様々なワークロードデータを保護するシナリオ。
【CommonLisp】exportされていないシンボルを参照する方法

## 結論

:ではなく::を使おう

```common-lisp:human.lisp
(provide :human)

(defpackage :human
  (:use :cl))
(in-package :human)

(defun hello ()
  (format t "hello!!~%"))
```

```common-lisp:main.lisp
(provide :main)

(defpackage :main
  (:use :cl)
  (:export :main))
(in-package :main)

(require :human "human.lisp")

(defun main ()
  (human::hello) ; -> hello!!
  )
```
関数

## 関数とは
何らかの入力を受け、処理を行い、出力を返すもの。
このため、メソッドも関数の一種になる。

### 戻り値を返す関数の代入
関数は変数に代入できるという特徴を有しています。そのため、関数の一種であるメソッドを変数に代入することができます。

```java
import java.util.function.Function;

public class Main {
	// 文字を受け取り、その文字数を返す関数
	public static Integer len(String word) {
		return word.length();
	}

	public static void main(String[] args) {
		// 変数funcにlenメソッドへの参照を代入
		Function<String, Integer> func = Main::len;
		// applyで代入された関数を適用
		int a = func.apply("Tokyo");
		System.out.println(a);
	}
}
```

*Function
関数型インタフェースなので、ラムダ式またはメソッド参照の代入先として使用可能

### メソッドのアドレスの格納
変数名 = クラス名::そのクラスの静的メソッド名
変数名 = インスタンス名::そのインスタンスのメソッド名

### 戻り値を返さない関数

```java
	public static void main(String[] args) {
		Consumer<String> func = System.out::println;
		// acceptで、代入された関数を適用
		func.accept("Tokyo");
	}
```

### 引数がない関数を格納する
```java
	public static void main(String[] args) {
		Supplier<String> func = System::lineSeparator;
		// acceptで、代入された関数を適用
		System.out.println("Tokyo" + func.get() + "OSAKA");
	}
```

## 参考資料
スッキリわかるJava入門 実践編 第3版 (スッキリわかる入門シリーズ)
アウトプット初心者がアウトプットから得られたこと

## はじめに
Advent Calendar2022 16日目、テーマは"アウトプット"です。
こういったイベントの参加は初めてですが、せっかくの機会ですので記事を書いてみました！
Qiita歴2年にも満たないアウトプット初心者ですが、アウトプットを始めてみて感じたことをまとめました。温かい目で見守っていただければと思います。


## 現状ときっかけ
まず、私のアウトプット歴から。
現在のアウトプット頻度についてはQiita以外のアウトプットも含めると、大体1〜2ヶ月に1投稿くらいのペースです。投稿頻度が高いわけではありませんが、自分が継続できるペースでアウトプットするようにしています。
初めて技術系の記事を投稿したのは去年の3月3日で、その内容は[「M1mac Pyaudioインストール時エラー対応」](https://qiita.com/m_ina/items/a2c37cf9457bd21c76b6)でした。環境構築ではまったので自分用メモの記事として記録を残しつつ誰かの役に立てばいいかな？くらいの軽い気持ちで投稿しました。そのため、良い記事を書くぞ！！という気合いの入った記事ではありません。それでも初めて記事を投稿したことで、自分の中のアウトプットに対するイメージに変化がありました。今思えば、この投稿は私にとっては大きな一歩だったのかなと思います。

## アウトプットに対するイメージの変化
記事を投稿する前のアウトプットのイメージはこんな感じでした。
 - 内容に間違いがあってはいけないのでハードルが高そう。
 - 自分が知っている情報が正確かわからない。
 - 記事を書くなら難しい内容じゃなくていいのかな？
 - その内容について誰かが既に投稿しているから書く意味がないのでは？
 - そもそも何を書けば良いかわからない。
 - 書いたところで記事を見てくれる人はいるのかな？

でも、実際に自分で記事を投稿してみて自分の中のアウトプットに対するイメージが間違っていることに気づきました。
- 内容に間違いがあった時、その間違いを指摘してもらえることがあるので逆に勉強になる
- 正確な情報を書くためには公式ページなど正確な情報源からの情報収集が必要になること
- 書く内容は何でも良いこと（同じ内容でも伝え方や目線が違うため読者のターゲットが異なる）
- アウトプットをするためにはインプットが必要になること
- 思っているよりも記事を見てくれている人がいること
- 誰かが見てくれていることが自分のモチベーションに繋がること


# アウトプットを心がけたことで得られたこと
### インプットをするようになった
これがアウトプットをするようになってから一番大きく変わったところかなと思います。アウトプットするためには記事のネタが必要です。そのネタ探しや興味のあるものを見つける方法の一つがインプットをすることです。そのため、インプットの機会を増やしました。インプットすることで単純に知識量が増えるので自分にとってプラスになります。私の場合はQiita等の技術系サイトのトレンド記事を見る、技術書を読むこと、勉強会への参加などをするようになりました。特にトレンド記事は自分が普段調べないような内容の記事もあるのでインプット内容に偏りがなく、かつ最新の情報を収集できるのでおすすめです。

### 公式ページを見る癖がついた
駆け出しエンジニアは調べ物をするとき公式ページよりも先に誰かの記事を見るということが多いのかな？と思います。私もその一人で公式ページは説明が難しかったり、英語だったりと正確に情報を読み取ることが難しいイメージがあり、誰かが噛み砕いて説明してくれている記事の方が読みやすいので敬遠しがちでした。ただ、つよつよ先輩エンジニアさんたちをみていると、調べものをするときは最初に公式ページを読んでいました。これは誰かが書いた記事は情報が間違っていたり古かったりするため、やはり正確な情報を得るためには情報の発信元から得るのことが一番手っ取り早いからです。アウトプットするまでは公式ページを読むことを毛嫌いしていましたが、思っていたほどハードルが高いわけでは無いことに気づけたので、結果的に情報収集の速度が上がったと思います。

### 自分のモチベーションアップにつながる
やはり自分の記事のview数が増えたり、いいねやコメントなどの反応がもらえると嬉しいですね。どこかの誰かの役に立っているという実感がありますし、もう１記事書いてみようかなという気持ちにもなります。そうなると、記事を書くためにインプットする->記事を書く->インプットをする...という良い循環が生まれて、モチベーションの向上や維持に繋がりました。

### その他
- どこかの誰かの役に立っていること
- 記事が自分の資産になること
- 記事を自分の言葉で書くことで、その内容の深い理解に繋がること


## まとめ
初めての記事を書く以前はアウトプットすることの壁はとても高いように思えていたのですが、一度アウトプットしてみると思っているよりも大したことがなかったことに気づきました。アウトプットは"誰かに情報を共有をすること"ではありますが、結果的に自分の能力向上にも繋がる有効な手段なのかなと思います。私自身も無理せず自分のペースでアウトプットを継続していこうと思います。
この記事が誰かのアウトプットのきっかけになれば良いなと思います。
ここまで読んでいただきありがとうございました！
cファイル先頭にlanguage modes specified are incompatible c/c++(1027)と表示されるとき

### 問題
vscodeで新しくcファイルを作ると、ファイルの先頭に赤い波線が引かれ、language modes specified are incompatible c/c++(1027)というメッセージが出ました。
### 原因
cmakeが関係してると思います。詳しいことはわかりませんでした。
### 解決法
ctrl+shift+pでコマンドパレットを表示→c/c++ edit configurationで、c_cpp_properties.jsonを編集します。
configurationProviderをms-vscode.cmake-toolsから、ms-vscode.cpptoolsに変えるとエラーが消えました。
DoctrineとEloquent比較大全15: バッチ削除

day15の今日は複数データ（大量データ）をまとめて削除する方法を見ていきます。

## Doctrine

```php
<?php

declare(strict_types=1);

use App\Entity\Author;
use App\Entity\Book;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Query\ResultSetMapping;

require __DIR__.'/../vendor/autoload.php';

/** @var EntityManagerInterface $entityManager */
$entityManager = require __DIR__.'/bootstrap.php';

// エンティティを使ってやる
foreach ($entityManager->getRepository(Book::class)->findAll() as $book) {
    $entityManager->remove($book);
}
$entityManager->flush(); // begin + 全件のdelete + commitがここで行われる

// エンティティを使えないぐらい多い件数を扱う場合
$conn = $entityManager->getConnection();
$conn->beginTransaction();
for ($i = 1; $i <= 1000000; $i++) {
    $conn->delete('books', ['id' => $i]);
}
$conn->commit();

```
<https://github.com/77web/doctrine-vs-eloquent/blob/3f3119288d597aa035accb364a49ddf221c0ec9b/Doctrine/Usecase/batch_delete.php>

- エンティティのインスタンスを作ることを許容できる場合、通常のEntityManagerを使った削除で十分です。DELETE文はEntityManager::flush()を呼んだときにトランザクション付きでまとめて実行されます。
- エンティティのインスタンスを作ることが許容できないぐらい大量のバッチ削除を行いたい場合はDBALのConnectionに対する `delete()` メソッドで実行することもできます。


## Eloquent

```php
<?php

declare(strict_types=1);

use App\Models\Book;
use Illuminate\Support\Facades\DB;

require __DIR__.'/../vendor/autoload.php';
require __DIR__.'/bootstrap.php';

DB::beginTransaction();
for ($i = 1; $i <= 100000; $i++) {
    DB::delete('DELETE FROM books WHERE id = ?', [$i]);
}
DB::commit();
```
<https://github.com/77web/doctrine-vs-eloquent/blob/3f3119288d597aa035accb364a49ddf221c0ec9b/Eloquent/Usecase/batch_delete.php>

- insert, updateと同様、モデルに対してバッチ削除をするにはサードパーティのプラグインパッケージが必要です。
カプセル化の演習（setterに戻り値つけて笑われた話）

# 問題
口座から引き出す機能のみをもったシステムを実装してください。

```java
public class ATM {
    public static void main(String[] args) {
		
		BankAccount myAccount = new BankAccount();
		myAccount.setWithdrawal(800);//800円を引き落とす。
        myAccount.setWithdrawal(-800);//不正に残高を増やそうと試みるｗ
		System.out.println("現在の預金残高：" + myAccount.getBalance() + "円");
	}
}
//演算結果
//入力された数値が正しくありません。
//現在の預金残高：9200円


class BankAccount {
	//預金残高を保存するプライベートなインスタンス変数balanceを定義
	private int balance;
	
	public BankAccount() {
		this.balance = 10000;//口座の予算を10000円に設定するコンストラクタ
	}
	// 	プライベートなインスタンス変数balanceのgetterメソッド
	public int getBalance() {
		return this.balance;
	}

	//  プライベートなインスタンス変数balanceのsetterメソッド
	public void setWithdrawal(int withdrawal) {
		if(withdrawal >= 0) {//不正に残高を増やせないよう対策
			this.balance -= withdrawal;
		}else {
			System.out.println("入力された数値が正しくありません。");
		}
	}
}

```

# 補足
- カプセル化
→private修飾子を使うことで参照したり更新したりできないようにする。
- getter、setter
→名前の通り、privateな変数を参照（get）したり、更新（set）したりするメソッド。もちろんpublicなメソッド。
→どちらかに条件をつけて機能に制限を設けたり、getterだけにして参照しかできないようにしたりできる。
→Eclipseだと自動で作ってくれる機能あり（便利！）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984665/b445ca91-7709-3ace-0e4a-9ffe8d94ea3a.png)

# setterに戻り値つけて笑われた
geetterは`public int getBalance()`のように修飾子の後に戻り値の方を書きます。
setterは`public void setWithdrawal(int withdrawal)`のように`void`をつけて書きます。
ところが私は間違えて`public int setWithdrawal(int withdrawal)`と書いていました。引数が間違っているのでそもそもコンパイルエラーですが、もし引数名と変数名が同じものでしたらそのまま動きます。しかし講師の方に指摘されたのは`「getterいらなくなりません？」`

たしかに！！

まあおかげでしっかり覚えられました。ｗ
Linuxでhistory（コマンド履歴）を削除する方法

Linuxはhistoryコマンドや上下の矢印キーで直近使用したコマンドをすぐに呼び出せるのでとても便利ですよね。
ですが、引数にパスワードをつけてコマンドを利用した時など、何らかの理由でコマンド履歴を残したくない時もあると思います。

今回はhistoryのコマンド履歴の内容を ~~証拠隠滅~~ 削除する方法を紹介します。

# history（コマンド履歴）の内容を修正する
historyコマンドや上下の矢印キーを押した時に表示されるコマンド履歴は`~/.bash_history`ファイルに記載されているので、これを直接編集してやればよい。

### ファイルを編集する
```
$ vi ~/.bash_history
```
### 行番号を表示
```
:set number
```
viのコマンドモード（ESCキー押した時のやつ）で上記を実行すると左側に行番号が表示される。
### 1行削除したい場合
```
dd
```
上記のコマンドでカーソルのある行を削除できる。
### 指定範囲の複数行を削除したい場合
```
:[Starting Line Number],[Ending Line Number]d
```
例えば100行目から150行目を削除したい場合は`:100,150d`と打つ。

# 余談
historyコマンドのオプションでも履歴を消す機能はあるが使い勝手が微妙すぎる。
### コマンド履歴から全ての項目を削除する
```
$ history -c
```
全て消すのは怪しすぎるし自分で使う分にも不便でしょ…。
### コマンド履歴を番号指定で個別に削除する
```
$ history -d 番号
```
一見すると便利コマンドだが、これをやると今度は`history -d 番号`がコマンド履歴に残ってしまうのでしょっぱい。

# おわりに
引数にパスワードつけちゃったのを消すくらいなら`history -d 番号`でも全く問題ないと思います。
`vi ~/.bash_history`自体は履歴に残りますが、それを差し置いても消したいコマンド履歴が大量にある時なんかに是非。

~~業務中に関しては「善はゆっくり、悪は急げ」です。~~
namedtupleについて

## namedtupleについて知ろう！
参考
* [namedtupleで美しいpythonを書く！（翻訳）](https://qiita.com/Seny/items/add4d03876f505442136)
* [namedtuple ってなに？](https://python.ms/namedtuple/#_1-%E4%BD%BF%E3%81%84%E9%81%93)
* [【Python】namedtupleで名前付きタプルを使用する](https://tech.nkhn37.net/python-collections-namedtuple/)

>namedtupleとは、pythonの標準ライブラリーcollectionsモジュールからインポートできるデータ型のこと。namedtupleは第一引数にクラス名、第二引数に属性を記述し、<b>クラスを生成して返す関数</b>です。

## namedtupleの使い方
~~~python:exam.py
from collections import namedtuple

Human = namedtuple('Human', ['name', 'gender'])

my_info = Human('taro', 'man')

print('名前:', my_info.name)
print('性別:', my_info.gender)
print('インデックス0:', my_info[0])
print('インデックス1:', my_info[1])
# 可変長引数
print('可変長引数:', *my_info)
# アンパック
name, gender = my_info
print('アンパック:', name, gender)

>>>
名前: taro
性別: man
インデックス0: taro
インデックス1: man
可変長引数: taro man
アンパック: taro man
~~~
namedtupleでは、ファクトリ関数（クロージャ）が文字列に対してsplite関数を呼び出す。そのため、上記コードのリスト部分のような2つの要素でも、以下のコードのように文字列として渡すこともできる。
~~~python:exam2.py
from collections import namedtuple

gender = namedtuple('man', 'jiro taro')
~~~

## namedtupleの継承
namedtupleはクラスを生成するクラスなので、継承を行いメソッドやプロパティを追加することができる。
~~~python:exam3.py
from collections import namedtuple

Human = namedtuple('Human', ['name', 'gender'])


class Human_kind(Human):
    def name_categorize(self):
        if len(self.name) >= 6:
            return 'longname'
        else:
            return 'shortname'


H = Human_kind('sorajiro', 'man')
print(H.name_categorize())
~~~
## メソッドを使ってみよう！

# 既存のリストからnamedtupleを作る_makeメソッド
~~~python:exam4.py
from collections import namedtuple

Human = namedtuple('Human', ['name', 'age'])

data = ['saku', 22]
human_data = Human._make(data)
print(human_data)
print(human_data.name)
print(human_data.age)

>>>
Human(name='saku', age=22)
saku
22
~~~
# フィールド名を取得する_fieldsメソッド
~~~python:exam5.py
from collections import namedtuple

Human = namedtuple('Human', ['name', 'age'])

H = Human('saku', 22)
print(H._fields)

>>>('name', 'age')
~~~
# 辞書型で情報を取得する_asdict
~~~python:exam6.py
from collections import namedtuple

Human = namedtuple('Human', ['name', 'age'])

H = Human('jiro', 78)
H_dict = H._asdict()

print(type(H_dict))
print(H_dict)
print(H_dict['name'])
print(H_dict['age'])

>>>
<class 'dict'>
{'name': 'jiro', 'age': 78}
jiro
78
~~~
ついに pip に bpy が来た

https://qiita.com/ousttrue/items/db68f5a1939fd3a9d982

Blender-3.4 で、自前ビルドが必要だった bpy が pip に来ました。

> bpy 3.4.0 is available on PyPi, and can be installed through pip install bpy. 

:::note warn
https://pypi.org/project/bpy/

左側に以下のような記述があります。

> Requires: Python ==3.11.*

Blenderがその時々で使用しているVersionの python が必要です。
(blender-4.4 => python-3.11)
:::

# install

```
> pip install bpy
```

:::note warn 
numpy のバージョンを下げる

```
A module that was compiled using NumPy 1.x cannot be run in
NumPy 2.2.4 as it may crash. To support both 1.x and 2.x
versions of NumPy, modules must be compiled with NumPy 2.0.
Some module may need to rebuild instead e.g. with 'pybind11>=2.12'.
```

```
> pip install numpy<2.0
```
:::

# 使用例

最初はいつもの、`Camera`, `Cube`, `Light` の初期状態です。

```python
import bpy

o = bpy.context.active_object
print(o)
```

## ロードする

### blend

```python
bpy.ops.wm.open_mainfile(filepath=BLEND_PATH)
```

### bvh

```python
ret = bpy.ops.import_anim.bvh(  # type: ignore
    filepath=BVH_PATH,
    use_fps_scale=True,
    update_scene_duration=True,)
if ret != FINISHED:
    raise Exception()
```

## rendering する

### EEVEE

```python
import bpy
# bpy.context.scene.render.engine = 'CYCLES' # EEVEE動くようです
bpy.ops.render.render()
bpy.data.images['Render Result'].save_render(filepath='image.png')
```

## object にアクセスする

```python
active = bpy.context.active_object
print(active)
```

```python
for o in bpy.data.objects:
  print(o)
```
変数変換とヤコビヤン：個人的メモ

# 多重積分のヤコビヤンの由来

https://k-san.link/jacobian-def/

```math
\int\int_D f_x(x,y)dxdy
```
に対して

```math
x=p(u,v)\\
y=q(u,v)
```
と変数変換する。

$dxdy$を考える。

```math
dx =　 \frac{\partial p}{\partial u} du + \frac{\partial p}{\partial v} dv\\
dy =　 \frac{\partial q}{\partial u} du + \frac{\partial q}{\partial v} dv
```
である。
ここで、**ベクトル**として考える。$\vec{dx},\vec{dy}$を考える。

```math
\vec{dx} =　 \frac{\partial p}{\partial u} \vec{du} + \frac{\partial p}{\partial v} \vec{dv}\\
\vec{dy} =　 \frac{\partial q}{\partial u} \vec{du} + \frac{\partial q}{\partial v} \vec{dv}
```

面積は外積なので

```math
\vec{dx} \times \vec{dy} = (\frac{\partial p}{\partial u} \vec{du} + \frac{\partial p}{\partial v} \vec{dv}) \times
(\frac{\partial q}{\partial u} \vec{du} + \frac{\partial q}{\partial v} \vec{dv})

```
ここで、同じベクトル同士の外積は0,外積の掛け算順序が変わる場合は-1がつくことより


```math
\vec{dx} \times \vec{dy} =(
\frac{\partial p}{\partial u} \frac{\partial q}{\partial v}
-
\frac{\partial q}{\partial u} \frac{\partial p}{\partial v})
\vec{du} \times \vec{dv}
```

ここで、ベクトルから積分の考えに戻すと、

```math
dxdy 
=|J|dudv\\
J=\frac{\partial p}{\partial u} \frac{\partial q}{\partial v}
-
\frac{\partial q}{\partial u} \frac{\partial p}{\partial v}
```

となる。
強引だが、こう理解しとけば、ヤコビヤンがどちらをどちらで微分するか悩まなくて済む！


# 確率変数の確率密度関数の変換

https://mcm-www.jwu.ac.jp/~konno/pdf/statga19.pdf

http://nlp.dse.ibaraki.ac.jp/~shinnou/siryou/toukei-kentei/1-stat-var-trans.pdf

$(X,Y)$が$f_{xy}(X,Y)$の確率密度関数に従って分布している。

```math
x=p(u,v)\\
y=q(u,v)
```
と変数変換する。
逆に

```math
u=g(x,y)\\
v=h(x,y)
```
とする。

$(U,V)$の分布$f_{uv}(X,Y)$を考える。

```math
\begin{eqnarray}
P(U \leq u,V \leq v)&=& \int \int_{g(x,y) \leq u,h(x,y) \leq v} f_{xy}(x,y)dxdy\\

&=& \int \int_{g(x,y) \leq u,h(x,y) \leq v} f_{xy}(p(u,v),q(u,v))J(\frac{x,y}{u,v})dudv\\

&=& \int_{-\infty}^{u} \int_{-\infty}^{v} f_{xy}(p(u,v),q(u,v))J(\frac{x,y}{u,v})dudv\\

\end{eqnarray}
```
そもそも、

```math
P(U \leq u,V \leq v) = \int_{-\infty}^{u} \int_{-\infty}^{v} f_{uv}(u,v)dudv
```
であった。2つを比較することで

```math
f_{uv}(u,v) = f_{xy}(p(u,v),q(u,v))J(\frac{x,y}{u,v})
```
が導かれる。

ヤコビアンの分母分子の入れ替えは逆数になるので

```math
f_{uv}(u,v) = f_{xy}(p(u,v),q(u,v))\frac{1}{J(\frac{u,v}{x,y})}
```
も導ける
31歳でIT業界に突撃して2年経った。振り返る。

# 目的
記事を執筆した目的としては、「中途でIT業界に入ってきた人間のキャリア例」を共有しておきたいという意図です。
検討している方が多くいらっしゃると思うので、パターンの一例になれば幸いです。

# 初めに
筆者の経歴を簡単に並べておきます。
半導体業界からIT業界に来ました。刺激的な毎日を過ごしています。

## 大学時代
- 大学は駅弁で電気電子工学を専攻。C言語の講義はあったが、何を言っているのかさっぱりわからなかったし興味も無かった。

## 半導体時代
- 新卒で半導体ICをテストするコードを書く仕事をTOTAL6年ぐらいしていた。C、C++を書いたり、回路の設計をしたりがメイン業務。電気信号を入れて出力される電気信号をキャッチして〜みたいなことをコードで実現するイメージ。
    - 何故か改善ツール作成の槍玉にあげられ、perlとかtcl/tkとかでツール作ったりしてた。コーディングは好きだったので色々作らせてもらえた。
    - テストが漏れたら大惨事な環境だったので、とても貴重な経験でした(量産でトラブりました⇨胃痛待ったなし)。
    - 自然と納期が短くなる謎現象との戦い。事あるごとにスケジュールを詰め直して納期に向かってがんばる。

## IT時代
- 何故かWEB系面白そうじゃーん。と思ってHTMLとかCSSとかかじってみる。既に31歳。好きなことやりなよと言ってくれた嫁には感謝してます。
- 運良く自社開発企業に内定。突撃したところ要求されるスキルが違い過ぎて絶望する。
    - コーディングできればいけるっしょ！！というノリで突撃したら「HTTPとは、PORTとは、セッションとは」という基本的なところがわからなさすぎた。
    - 高度資格コンプリートしてる変態(尊敬)の人から2日程度座学を受けてから、「BIG-IP構築してみて」という無茶振りで絶望。
        - ただ、基礎からみっちり学べだおかげで今に活きています。本当に感謝。
    - 結果的にフロントエンド、バックエンド、インフラ(AWS)と広く触れたのでいい経験をさせてもらえました。本当に感謝。

- 前工程の仕事したいなあという動機から、自社アプリの導入コンサルみたいな仕事につく。要件定義とか設計とかディレクションとか。
    - 給与規定変更で年収DOWN（え？？マイナス影響なの自分だけ？？？？？？）。
    - マネジメント業務もさせてもらったのはいい経験でした。プレイングマネージャーダメ絶対。

- 前職ではやりたい方向性とは異なる方針に切り替わっていったため、開発業務を継続するために自社開発企業へ転職。
    - 入社したらエンジニア1人なんだけど...(´・ω・｀)
    - 会社が漫画みたいなレベルでゴタゴタしてて意気消沈...(´・ω・｀)
    - 事前に会社のことは調査してから入社するの大事...(´・ω・｀)
    - もちろん引き継ぎは無し。周囲へのヒアリングなどで運用立て直し(気合い)。リバースエンジニアリングゥゥゥゥ(気合い)。

- なんやかんやあって色んなことを勉強できたなあという所感。
- 記事執筆時の知識の習得度合いとしては、予習無しで応用情報の午前突破できるぐらい。なんとなく過去問を2つ解いたら7割ぐらい取れた。

## 今後のキャリア
何を血迷ったか某有名外資に応募してみたところ、書類⇨オンライン試験→Interviewまで進むという奇跡が起きた。
当時は「何を見てくれたのか本当に謎だ...」という気持ちだったが、チャンスがあることを認識できたことは大きい。フィードバックも貰えて課題も明確になりました。
結果的には落ちたんですが、その時の体験が凄まじく良かったので、同じような体験が得られる企業に行きたいなあとぼんやり思ってます。
技術的な嗜好だったり業務内容だったり、色々な要素はあると思うんだけど、結局仕事は対人なんですよね。

ということで、今後必要になってくるスキルは以下をイメージ。
- 縦割り組織でエンジニアとして働くために、専門領域を作る。
- 英語力を向上させる。TOEICは515です...(´・ω・｀)
- atcoderで緑。いま灰色です...250ぐらい...(´・ω・｀)
- leetcodeのmediumを実装できる。
    - easyなら実装できます！paizaならSです！と書いて自尊心を保ちます...

## 最後に
最初のうちはどういうキャリアを歩みたいかハッキリしないと思います。ただ、大枠の軸は決めておかないと私みたいに半端な状態になってしまいますので気をつけてください。目的に対して適切な手段は何か？という点を情報収集してみてください。

何か一つでも「へー」と思ってもらえたら嬉しいです！皆で精進していきましょう！
非エンジニア（経理の人）がSnowflakeをいじってみた。

# 自己紹介
こんにちは。サ藤と申します。
普段はCData Software Japan という外資系ソフトウェアベンダーのOperations Manager というポジションで、経理をはじめとしたバックオフィスのオペレーション全般を担当しています。タイトルにもあるとおり私はエンジニア職では無く、純度100%の事務畑の人間です。ペーパーワーク大好き。ファイリング作業サイコゥー。

ITに関する知識レベルとしては
- ずっとIT業界で事務をやってる。
- Excel職人（笑）
- 管理部のパソコン大先生（笑）
- VBA, Python, R, は完全に理解した（笑）

と言った感じで、本職じゃ無いけど趣味でプログラミング言語に触ることもあるよ～というレベル感です。
あとは放送大学の情報コースに在席して、データサイエンスまわりのことを少しずつ勉強しています。

# Snowflakeについて
この記事をご覧になっている皆様には説明不要かと思いますが、Snowflakeとはコンピュートリソースというアーキテクチャーを採用したクラウド型のデータウェアハウスです。その技術的な凄さについては経理の人の知識レベルでは全く理解出来ませんでした！すみません！！

クラウド型であることから設備投資を必要とせず、固定資産管理が不要なため経理の人にも優しいです。また、「リソースモニター」の機能では消費クレジットにしきい値を設定して、アラートを出したり、ウェアハウスの実行を一時停止したりすることが出来ます。この機能をちゃんと設定することで、突然の高額請求が来て運用担当者を呼び出して詰めるといった業務や予算統制の心労の負荷を軽減することができそうです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954401/972a09c3-2d07-14e8-5cb0-d31db6ef821d.png)
リソースモニターの画面。消費クレジットのしきい値条件などを設定できる。

ちなみに私が働いているCData Software の製品もSnowflakeへの接続に対応しています。

https://www.cdata.com/jp/drivers/snowflake/

ERP にある会計データ、Google Analytics にあるウェブマーケのデータ、CRM にある売上情報などを自社製品を活用してSnowflake に突っ込んで、超カッコイイKPIダッシュボードを作るのが僕の夢です。（現在は具体的な構築方法を検討し、今後はさらに検討を加速させていくことも検討しているフェーズ。）

# 使ってみた
今回はマーケットプレイスにあるDBを使用して、簡単なデータのビジュアライズをしてみました。
Snowflake のData Marketplace では共有されているデータを利用することが出来ます。データプロバイダーが販売するデータを購入することもできるようですが、無料で使えるデータも充実しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954401/1920c77c-2f7e-91c3-6fd6-6ff40cfbd81d.png)
無料で使えるものも充実していて結構感動した。レポーティングの材料になりそうなものも多い。

特に理由はないけどコロナウィルスに関するデータをチョイス
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954401/c973ab9a-8c07-f0cd-1245-69b6f35eb0ba.png)
Getを押すだけでデータが使えるようになる。レプリケーションなのかデータへのアクセス権が付与されるのかは経理のおじさんにとって謎だが、使えるようになることは確か。

データが使えるようになったので簡単なSQLを実行してみる。

```
SELECT * FROM "COVID19"."kaziajg" WHERE "Location Name" = 'Japan' AND "Indicator Name" = 'Deaths, per million people' ORDER BY "Date"
```

結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954401/57178b15-dac3-a1bb-de24-7dddfc5f87d2.png)
SQLがちゃんと書けているのか常に不安なので、実行結果がすぐプレビューに出てくるのがうれしい。

ビジュアライズしてみる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954401/14efb6ac-19a8-4415-f01b-9d711b4e50f6.png)
実行結果が表示されているところにある「Chart」を押すとカッコイイグラフがすぐに作れる。10秒で出来た。
色合いがカッコイイ…。

# 感想
非エンジニアの経理のおじさんがSnowflakeをいじってみました。

「プログラミングの知識一切不要！」とまではいきませんが、初期設定からデータをグラフ化するまでに書いたコード（らしきもの）は本記事に出てくるSQL文だけです。
記事を書くにあたり「難しかったら社内のエンジニアの手を借りなければ…」などと思っていましたが、少しだけ勉強すれば本職のエンジニアでなくてもデータの分析基板が作れそうだと感じました。

今後は社内の実データをSnowflakeへぶち込んで、会社の業績がいつでもわかるダッシュボードを作っていきたいと思います。
ボタンの連続入力防止方法

トグルメニューを実装した時に、連続クリックすると、遅れてクリックした回数分アニメーションが再生してしまう不具合がありましたので、その対策を紹介します。


~~~ html
<dl class="toggle">
  <dt>開閉ボタン</dt>
  <dd style="display:none;">
    <li>開閉コンテンツリスト<br>
    開閉コンテンツリスト2
  </li></dd>
</dl>
~~~

~~~ js
$(function(){
  $('.toggle dt').click(function(){
    $(this).next().slideToggle(600);
  });
});
~~~
上のコードで連続クリックするとその回数だけアニメーションが保存され、遅れて何回もアニメーションしてしまいます。
~~~ js
$(function(){
  $('.toggle dt').click(function(){
    $(this).next().stop(true, false).slideToggle(600);
  });
});
~~~
上のコードは`.stop(true, false)`を追加しました。これで連続クリックすると、現在のアニメーションを途中で中断して次のアニメーションに移行する動きをします。
~~~ js
$(function(){
  $('.toggle dt').click(function(){
    if($(this).next().not(':animated').length >= 1){
      $(this).next().slideToggle(600);
    }
  });
});
~~~
2つ目はアニメーションする要素（開閉するコンテンツ）が動作していないときだけ、開閉する動作をします。つまりクリックすると、0.6秒のデッドタイムがあります。

個人サイトでも、企業サイトでも連続動作するサイトをちらほら見かけますよね。ひと工夫するだけでこの不具合は解消されるので、みんなもやってみよう！

### 参考
https://www.j10.net/blog/2015/12/011006.html

https://hirashimatakumi.com/blog/1486.html
Salesforce SOQLの基礎とSQLとの違い

# これは何？
この記事は「[24日後に立派なSalesforceエンジニアになるWEBエンジニア Advent Calendar 2022](https://qiita.com/advent-calendar/2022/kakakaori)」の20日目の記事です5日後に立派なSalesforceエンジニアになるために今日からはSOQLについて学んでいきます。

# SOQLとは？
SOQLとはSalesforce Object Query Languageの略。
SQLのような感じでデータベースにアクセスしてレコードを取得するのに使う。

```sql:
SELECT Fields FROM ObjectName WHERE Condition
```
# どうやって使うのか？
SOQLはApexやSalesforce CLI、REST API などから呼び出すことができる。

## Apexの場合
```apex:
List<Account> accts = [SELECT Id FROM Account];
```

## Salesforce CLIの場合
```
sfdx force:data:soql:query -u DevHub --query "SELECT Id FROM Account"
```

## REST APIの場合
```
GET https://yourInstance.salesforce.com/services/data/v56.0/query?​q=SELECT+Id+FROM+Account
```
## Bulk APIの場合
```
POST https://yourInstance.salesforce.com/services/data/v56.0/jobs/query
{
  "operation": "query",
  "query": "SELECT Id FROM Account"
}
```
# SQLとの違い
## INSERT、UPDATE、DELETE ができない。
SOQLには INSERT、UPDATE、DELETE ステートメントにあたるものが存在しない。なので以下はSELECTにフォーカスを当ててみていこうと思う。

## joinが使えない
SOQLはSQLのjoinが使えず、1つのSOQLクエリで複数のObjectからデータを取ってくる時にはリレーションを使う。そのため参照関係が定義されていないオブジェクト同士をくっつけてデータを取得することはできない。
構文の書き方が親から子レコードを参照するときと子から親レコードを参照するときで異なるのでそれぞれ見ていく。

### 子から親レコードを引いてくる
これは比較的簡単。子から見ると親は1人なので以下のように書くことで、子である`Contact`に紐づいた親`Account`の`Name`を参照することができる。
```sql:
SELECT Account.Name FROM Contact
```

### 親レコードから子レコードを引いてくる
先ほどの逆の場合は以下のようにサブクエリを発行することで値を参照する。
```sql:
SELECT Id,(SELECT Id,Name FROM Contacts) FROM Account
```
サブクエリ内に書かれている`Contacts`は子リレーション名と呼ばれるもので、どのような子リレーション名が定義されているかは`設定 > オブジェクト > オブジェクト名 > 項目とリレーション > 項目名`の以下の場所から確認ができる。
![スクリーンショット 2022-12-14 22.56.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200812/63dc42b9-95e7-86bf-f2f8-591f6f7e96ae.png)
今回の場合は標準項目の例を挙げたが、カスタム項目で参照項目を作っているときは`子リレーション名__ｒ`で指定することになる。

## select * が使えない
あと大きく違う点として `select *` が使えない。
ただ[FIELDS()関数](https://developer.salesforce.com/docs/atlas.ja-jp.soql_sosl.meta/soql_sosl/sforce_api_calls_soql_select_fields.htm)を使うと一部制限はあるものの、おおよそ似たような処理は行うことができる。

FIELDS()関数では以下の３種類が用意されている。
| 関数 | 説明 |
|:-|:-|
| FIELDS(ALL)  | オブジェクトのすべての項目を選択  |
| FIELDS(CUSTOM)  | オブジェクトのカスタム項目を選択  |
| FIELDS(STANDARD)  | オブジェクトの標準項目を選択  |

ただしこれらには項目レベルのセキュリティが考慮されるため、SOQLの実行者が**参照権限を持つカラムしか表示されない**のでその点は注意が必要。
またこれら3つはそれぞれ以下のように利用制限に差がある部分も把握しておく必要がありそう。
|  | FIELDS(STANDARD) | FIELDS(ALL) と FIELDS(CUSTOM)   |
|:-|:-|:-|
| Apex  |  実行可能 |  不可能 |
| Bulk API   | 実行可能  |  不可能 |
| CLI  | 実行可能  | LIMIT 200以下に絞れば可能  |
| SOAP API および REST API  | 実行可能  |  LIMIT 200以下に絞れば可能 |

## is NULL ではなく = NULL
今まで書いてきた内容に比べると些細な違いだがSOQLではNULLと一致するものは `= NULL`で抜いてくる。
```sql:
SELECT Account.Name FROM Contact WHERE Phone = NULL
```

## BETWEEN が使えない
これも些細だが`between A and B`が使えないので`<`と`>`で代用する。

# 最後に
今日はSOQLについて、SQLとの違いを中心に学びました。joinが思うようにできないのは、実際コードを書いていて少し辛いシーンもありますが、それ以外はほぼSQLと同様に扱うことができるので、ウェブエンジニアとしては触りやすそうです。
明日はSOQLと似たようなものにSOSLというものがあるので、それについてみていこうと思います。
PWAはスマホアプリの替わりになれるのか

この記事は[NTTコムウェア Advent Calendar 2022](https://qiita.com/advent-calendar/2022/nttcomware) 18日目の記事です。

今回は、私が実際にPWAでサービスをリリースして感じたメリットや課題をまとめていきます。

# PWAとは
PWA(Progressive web apps)は、Webサイトをネイティブアプリのようにインストールして利用できるようにする技術。

アプリと同じようにホーム画面に追加できるため、ユーザからすればアプリと何が違うのか感じられない状態にでき、開発者からすればWebの世界の延長でネイティブアプリを開発したかのようにできるメリットがある。

::: note
実際の導入事例としては日本では日経電子版やSuumoがPWA対応していることで有名。
[日経の事例紹介](https://web.dev/nikkei/)
[Suumoの事例紹介](https://web.dev/suumo/)
:::

# 機能面での比較
PWAはあくまでもWebサイトであるため、ネイティブアプリでできることがすべてできるわけでは無い。
とはいえ機能的に最近はかなりネイティブアプリに近づきつつある
|  | PWA | ネイティブアプリ |
|:-:|:-:|:-:|
| ホーム画面へのインストール  | [可※](https://caniuse.com/?search=pwa) |  可 |
| インストール元 | Webサイトから直接  | アプリストア経由  |
| カメラ/マイク | [可※](https://caniuse.com/?search=getUserMedia) | 可 |
| GPS | [可※](https://caniuse.com/?search=geolocation) | 可 |
| 加速度センサー | [可※](https://caniuse.com/?search=acceleration) | 可 |
| プッシュ通知 |  [可※](https://caniuse.com/?search=Notification) | 可 |

※ 可になっていてもブラウザによっては対応してない場合もあるため注意

# PWAのメリット
実際に私が使ってみて感じたこととしては
- Webとの親和性が高い
例えばTwitterのリンクから直接飛んでそのまま利用することができる。
- アプリストアのような審査が無いためアップデートがしやすい
- GoogleやAppleへ手数料の支払いが不要

上手に使えばWebとアプリの良いとこどりができるのがPWA最大の強みかもしれない

# PWAの課題
- ユーザへの導入フローが致命的に悪い
- 対応していないブラウザもあり利用者の環境を選ぶ
- マネタイズがアプリに比べて難しい（特にゲーム系の場合は）

## 導入フローの課題

- PWA対応のサイトをホーム画面に追加できることをユーザーはまず知らない
- ユーザーはアプリストアで検索するクセがついており、アプリストアに無いものは見つけることができない
- PWAをホームスクリーンに追加する方法がわかりにくい(特にiOS)
![pwainstall.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2318187/643e3ca1-7a10-0fc2-f61d-a288fc1add76.png)
これ以外の方法でインストール(ホーム画面に追加)する方法が無いため、なんとかユーザーにこの画面下のアイコンを押させてインストールさせる必要があるが、ハードルが高いことは間違いない。

## 対応ブラウザの課題
導入フロー以外にもそもそもPWAのインストールが不能な環境が存在する

PWAのインストール可否
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2318187/50735069-6104-783a-3982-ca49ec7a36ce.png)
引用: https://caniuse.com/?search=PWA

Androidは比較的対応が広くほとんどの人が問題なく利用できるレベルになっているが、厄介なのはiOSである。

iOSではSafariしか対応していないため、Chrome等の別ブラウザを日常使いしている人はそもそもPWAをインストールすることができない。

また、TwitterやLINE等のアプリからURLリンクを踏むと、実はiOSではアプリ内ブラウザ(WebView)で開くことになるためPWAのインストールができない。
これは結構致命的で例えば、PWAサイトのリンクをLINEで友人に送ってもその友人はインストールできない事象に見舞われることになる。

## マネタイズの課題
ビジネスとして考えるとマネタイズしにくいのというのは致命的であるが、
アプリと比べると、広告、アプリ内課金の2大マネタイズ要素共に劣っているのが現状。

### 広告
- Webサイトと同じ扱いになるため広告単価が低い
UIはアプリと同じようなのに単価だけが低いのを受け入れられるか
動画広告のような高単価の広告フォーマットはPWAに対応していない場合がほとんど。
- 一定の実績が求められる
アプリであればAdMob等でアプリリリースさえできれば誰でも広告を掲載できるが、PWAの場合はWebサイト扱いなので一定数以上アクセスがなければ審査を通ることができない。
- ゲーム等のテキスト情報の少ないジャンルと相性が悪い
Web広告の審査条件には、コンテンツ量＝文字数が一定以上あるかどうかで判定されるため、PWAでゲームを作るとほとんど文字がないWebサイト扱いされてしまい審査を通すことが困難

### アプリ内課金
- 通常のWebサイトと同じでクレジットカード登録したり、Paypal経由にしたりの対応が必要
- アプリで気軽に課金できるUXと比べると劣っていると言わざるをえない
- ただし手数料をAppleやGoogleに持って行かれないのは魅力的

# まとめ
趣味で使うのであれば十分利用可能なレベルになっている

ビジネスで利用したい場合は次の条件を満たせばPWAにしてもよいと思う
・新規ユーザーの獲得をアプリストアに頼らず自前で用意できる場合
・アプリ内でのマネタイズを考えていない場合
・マネタイズするにしても広告以外の方法で考えている場合
・自前で広告プラットフォームを持っている場合

# おわりに
まだまだ発展途上な部分は多いものの、条件を満たせばWebとの親和性からPWAのパワーを発揮できるサービスはたくさんあると思います。

皆さんもこれを機にPWAでサービスを考えてみてはいかがでしょうか。

---
:::note warn
本稿に記載されている情報は、2022年12月時点のもので、各製品やサービスは常に機能追加/変更が行われているため、ご留意ください
:::
記載されている会社名、製品名、サービス名は、各社の商標または登録商標です。
MVCモデルについて

## MVCモデルとは
MVCモデルは、モデル(Model)、ビュー(View)、コントローラー(Controller)の3つに役割を分担してアプリケーションを作成していく手法。
モデル、ビュー、コントローラーの各役割は以下。

### モデル(Model)
モデルはコントローラーから依頼を受けて計算処理やデータの格納などを行う。

### ビュー(View)
ビューはユーザーが見る画面を表示する。

### コントローラー(Controller)
コントローラーはユーザーから要求を受け取り、モデル、ビューにそれぞれ依頼を出す。

#### MVCモデルの具体的な動き
１．ユーザーが、アプリケーションに備わっている機能(検索、登録など)を要求
２．コントローラーが要求を受け付ける
３．コントローラーがモデルに処理の実行を依頼する
４．モデルが処理を実行する
５．コントローラーが処理結果の反映をビューに依頼する
６．ビューがユーザーの要求結果を表示する
７．ユーザーが要求結果を見る