OmniAICreator/Qiita-1.07M huggingface dataset:
ワナビーだった私からワナビーのみんなへ、競技プログラミングを始めてワナビーから抜け出そうぜって話をします

# はじめに
この記事は

* プログラマに対する憧れはあるが、具体的にどうこうしたりはしない人
* なんとなく「プログラミングやったら得意だろうな」という自信だけはあるが、何も書いたことはない人
* こういうプログラミング関係の記事を読むだけ読んで理解した気にはなるけど、実際にプログラムを書いたことはない人

に向けて書かれたものです。

よくネットスラングで、あれをしたいこれをしたいっていうだけで何もしない人のことを
ワナビー（wanna beから）というのですが、上に書かれているのは典型的なワナビー像ですね。
そんな典型的な奴いるか？という感じですが、つい2年ほど前までは私がそうでした。

その頃の自分みたいな人に少しでもエールが届けばいいなあと思い
[競技プログラミングを始めたばかりの人に伝えたいこと Advent Calendar 2021](https://qiita.com/advent-calendar/2021/pre-competitive) の
18 日目の記事として書かさせてもらいます


# 自己紹介
こんにちは、ナナメです。
プログラミング未経験から競技プログラミングを始めて、
先日のAGCで、競プロ歴2年、コンテスト99回目の参加で青コーダーになることができました
![IMG_1299.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1425097/d8e825f8-1f94-ef36-5462-5c8f3b65f7fd.jpeg)

<br>
<br>

…………と、競プロ歴の話になったら言っています。
しかし、実は私、2013年にあったABCの002，003回に参加してるんです
そして6年半なにもせず、2020年から再開しています
上のコンテスト成績のグラフにそれを加えるとこうなります

![IMG_129999.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1425097/3c15b975-c2b5-e61b-261c-8bc0919eeab6.jpeg)

自分、6年半、ワナビーやってました。



# ワナビーやってた理由
2013年頃、あまり国内に競技プログラミングの環境が整ってなかったんですよね
なんかぷよぷよでフォローした人がプログラミングのサイト作ったらしいしやってみるか、と思って参加して、
B問題で詰まって、「な～んだ、これは最初からデキる人がやるためのやつじゃん。クソゲ～」ってなって
チーター本を初版で買い、読んでも分からないので積ん読をし、
しかし他のものを制作するにも基礎となるプログラミングのスキルがなく、何も作れないまま6年半、
特にプログラミングを書かず、でもプログラミングは向いてるんだろうな、という根拠のない自信だけを胸に過ごしていました。


# でも今は違う！！
競技プログラミング環境めっちゃある！！
基礎の基礎からでも初められる！！
成長のための取っ掛かり、メッチャクチャあるのな！！

だからさ、始めようぜ！競技プログラミング！！
本当に完全な初心者から初めた俺が全部書くからよ！！


# AtCoder始めるまで
## 環境整えるの、めんどくさいよな！！！！
→[paiza.io](https://paiza.io/ja/projects/new)を使いましょう
ページを開いて言語を選んだら即プログラミング可能な便利サイトです

paizaの代表さんも[使って問題ない](https://twitter.com/rk611/status/1280414544859328512)って言ってます
めちゃくちゃ便利なのよ。ログインしなくても保存してくれるし

ビジュアルスタジオをダウンロードして～とか、
インプットを入れるフォルダを作って～とか無しで即完了！


## 標準出力、意味わかんねえよな！！！！
→[アルゴ式](https://algo-method.com/)をやれば良し

コンテンツ＞入力を受け取る (beta)＞画面に値を表示する (標準出力)
からなぞって行くだけで自然と理解できると思います。
アルゴ式はデフォルトがC++ですが、（C++は競プロの環境が整っているのでオススメ）
C++以外にも多数の言語で対応してて、そのままコピー→貼り付けでAtCoderでも対応できます。

この記事を書くためにアルゴ式触ってみたけどめちゃくちゃ便利じゃん
アルゴ式見るまでは、[Atcoderの最初の問題](https://atcoder.jp/contests/practice/tasks/practice_1)とか、
提出結果のACの提出から取ってきて、使えそうなとこを使う みたいな説明だったのに、
こんな楽な方法が今あるのか、ずり～～～


## やる気、出ねえよな！！！！！
→わかる～ワナビー続けると踏ん切りつかなくなるよな。
だから今のうちに参加登録しといて、何やってもレートがついてしまう状態にしとこうぜ

アカウント作って、参加登録押して、Rated参加を押しちゃえ
https://atcoder.jp/contests/abc232
ABC232は今日の21時からだから、20時30分にタイマーをセットしといてな！


とにかくやってみて、ハマるも良し！飽きるも良し！
向いてないって分かったらそれはそれでいいってことで！

順位とかは気にしなくていい！　当面の間ライバルは自分だから！
終わって15分後くらいにレーティングが出るから、マイページで[直近のコンテスト成績証]をクリックして、感想を書いてツイートすればもうあなたも競技プログラマ！GOGOGO！！！！
tomcat 設定１－4 Java tomcat setenv.sh


```bash

cd /usr/local

curl -OL --header "Cookie: oraclelicense=accept-securebackup-cookie" "http://download.oracle.com/otn-pub/java/jdk/8u131-b11/d54c1d3a095b4ff2b6607d096fa80163/jdk-8u131-linux-x64.tar.gz"

tar xvzf ./jdk-8u131-linux-x64.tar.gz

mv jdk1.8.0_131 java

export JAVA_HOME=/usr/local/java

echo $JAVA_HOME

cd /usr/local/tomcat/bin/

vi setenv.sh

下線部追記
ーーーーーーーーーーーーーーーーーーーーーーーーーーーー
CATALINA_OPTS="-server -Xmx1024m -Xms1024m -Xss228k"
export CATALINA_OPTS
ーーーーーーーーーーーーーーーーーーーーーーーーーーーー

-Xmx	最大ヒープサイズ(最大メモリ使用量)
-Xms	初期ヒープサイズ(初期メモリ使用量)
-Xss	プロセスに割り当てられるスタックサイズ(228k以上必要になります)

参考にするとこんな感じかな

ヒープの初期サイズ	リージョンサイズ
4GB未満	　　　　　　　　　1MB
4GB以上 ~ 8GB未満	      2MB
8GB以上 ~ 16GB未満	      4MB
16GB以上 ~ 32GB未満	      8MB
32GB以上 ~ 64GB未満	      16MB
64GB以上	　　　　       32MB

#①注意点
初期サイズXmsと最大サイズXmxが大きく異る場合は相談しましょう。

```

```

/usr/local/tomcat/bin/shutdown.sh

Using CATALINA_BASE:   /usr/local/tomcat
Using CATALINA_HOME:   /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME:        /usr/local/java
Using CLASSPATH:       /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
Using CATALINA_OPTS:   -server -Xmx1024m -Xms1024m -Xss228k
```

```
/usr/local/tomcat/bin/startup.sh

Using CATALINA_BASE:   /usr/local/tomcat
Using CATALINA_HOME:   /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME:        /usr/local/java
Using CLASSPATH:       /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
Using CATALINA_OPTS:   -server -Xmx1024m -Xms1024m -Xss228k
Tomcat started.

```

```

ps aux | grep tomcat
root     27344  9.2  7.2 4028616 136544 pts/0  Sl   22:13   0:07 /usr/local/java/bin/java -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -server -Xmx1024m -Xms1024m -Xss512k -Dignore.endorsed.dirs= -classpath /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/tomcat -Dcatalina.home=/usr/local/tomcat -Djava.io.tmpdir=/usr/local/tomcat/temp org.apache.catalina.startup.Bootstrap start
root     27368  0.0  0.0 112812   980 pts/0    S+   22:14   0:00 grep --color=auto tomcat


setenv.th内のヒープサイズを表示

ps -ef |grep java
tomcat   14607     1 59 08:12 pts/0    00:00:02 //bin/java -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -server -Xmx1024m -Xms1024m -Xss228k -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -classpath /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/tomcat -Dcatalina.home=/usr/local/tomcat -Djava.io.tmpdir=/usr/local/tomcat/temp org.apache.catalina.startup.Bootstrap start
tomcat   14631 14532  0 08:12 pts/0    00:00:00 grep --color=auto java

```
Mac: DjangoRestFrameworkを利用したdjangoプロジェクト立ち上げ時のメモ

まずはanacondaを利用して仮想環境を起動する。

毎回インストールが必要になるものは下記の三つ

```
pip install django
pip install djangorestframework
pip install django-filter 
```
djangorestframeworkはdjangoでAPIを作成するのに必要な肝となるもの。
django-filterを使うことでクエリパラメータのキーにモデルのフィールド名を入れて、バリュー値で検索が可能になる。

```

django-admin startproject test_project
cd test_project
django-admin startapp testapp
```
プロジェクトを作成し、manage.pyなどプロジェクトに必要なものも自動で追加する。
その後プロジェクト内にアプリを作成する。アプリは複数作成可能。
慣性付きの移動

氷の上を滑るような慣性のついた移動を行うときには、移動距離が少しずつ変化するような実装を行います。

右（あるいは左）に移動するときには、すぐに座標を移動するのではなく、まず速度を少しずつ増やします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75307/3b69d0a4-ec5a-a8fb-8736-8038cdcb310a.png)

何も移動されていなかったら、０になるまで少しずつ速度を落とします。

<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75307/334b8043-6afb-1c83-bd0e-93fd8385929f.png">

最後に、速度の分だけスプライトを移動します。

<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75307/20b34440-6728-65e4-d9fd-6adbb73955a4.png">

サンプルプログラム

https://scratch.mit.edu/projects/619077492

![スクリーンショット](https://cdn2.scratch.mit.edu/get_image/project/619077492_480x320.png)
MySQL PostgreSQL SQLiteの概要

#本記事の内容
本記事は表題の通り、3種類のデータベースに関して概要をまとめたものであり、筆者の備忘録的な記事となります。

#PostgreSQL
読み方：ポストグレエスキューエル。ポスグレ。

###説明
RDBMSにオブジェクト思考概念を導入したORDBMSの代表的製品。

移植が容易であり、日本語にも対応している。
#MySQL
読み方：マイエスキューエル。

###説明
高速性と堅牢性を兼ね備えたマルチユーザ・マルチスレッドのRDBMS。
世界的に広く使用されており、そのため関係記事が多く存在する。
また、日本語にも対応している。

#SQLite
読み方：エスキューライト。
###説明
著作権が放棄されており、誰でもが使用できる。
組み込み形式。
コンパクトで消費メモリが少ないため、処理能力が低いデバイスでも組み込み可能。

>ATMなどの複数の端末からデータベースに操作を試みるようなシステムは、「クライアントサーバ型」である「PostgreSQL」、「MySQL」のどちらかを採用すべきです。逆にそのソフトウェア内で完結するようなデータのやり取りをしたい場合は、「SQLite」を採用します。

#参考記事
https://bigdata-tools.com/sql-db/

https://algorithm.joho.info/programming/sql-db/mysql-postgresql-sqlite-oracle-db/
【初心者向け】TailwindCSS ver3.0の導入について

## 背景
next.jsとTailwindCSSの組み合わせを試す機会があったので以下を備忘に残します。
基本、公式に記載のドキュメント通りで詰まることはないはずなのですが、公式が言っていることもいまいちわからない初心者向けの記事です。

## 【概要】ざっくりいうと以下が要点

- 4つのインストールの方法があるよ
- Next.jsの場合は、Framework Guidesから行うが簡単だよ。CLIでインストールすると何を行っているか理解しやすく勉強になるよ
- ver2.0ではjust-in-time(JIT)モードはオプションだったけど、3.0ではJITがデフォルトになっているよ。3.0は最近リリースされたので多くのネットの情報は古くなっているので注意が必要だよ

## 4つのインストール方法の紹介

公式([https://tailwindcss.com/docs/installation](https://tailwindcss.com/docs/installation))を参照すると、4つの方法がある。

1. CLIを使ってインストール　→動きを知るという意味ではわかりやすい
2. PostCSSのプラグインとしてTailwindCSSをインストール　→1,3,4どれも当てはまらないときにどうぞ
3. Next.jsなど有名どころのフレームワークのガイドに従ってインストール　→パフォ的にはこっちが実用的
4. CDNを使ってインストール　→ちょっとお試ししたいときにどうぞ

4番は、ちょっとお試しで使いたい場合に行う方法で本番環境での使用は非推奨です。

そうなると候補は1～3になるのですが、ここでは１と３の内容をみていきます。

### CLIでのインストールの具体的な操作と解説
**Tailwind CSSのインストール**
ちなみにDのオプションは-save-devのエイリアスです（役割はここでは割愛）

```bash
npm install -D tailwindcss
npx tailwindcss init
```


**tailwind.config.jsの追記**
content部分に適用するファイルと拡張子を記載します。
src配下のすべてのサブディレクトリのファイルかつ拡張子がhtmlとjsのものに対して、適用させる場合は以下のような記述になります。(ここがいまいち不明な人はワイルドカードでの指定の仕方などをググるとよいでしょう)

```json
module.exports = {
  content: ["./src/**/*.{html,js}"],
  theme: {
    extend: {},
  },
  plugins: [],
}
```

**inputファイルの作成**
src/input.cssというファイルを作成し、以下のような記述をします。VSCode上では警告が出るかもしれませんが無視してOKです。気になる人は「PostCSS Language Support」というExtensionを導入することで消せます。

```css
@tailwind base;
@tailwind components;
@tailwind utilities;
```

**適用するCSSファイルのbuild**
上記のinput.cssから実際に適用するCSSファイルを作成します。
(以下の例ではdist/output.cssとしていますが、next.jsの場合はpublic配下がよいかも)
そのためのコマンドが以下です。

```bash
npx tailwindcss -i ./src/input.css -o ./dist/output.css --watch
```

watchのオプションをいれることで、tailwind.config.jsのcontentで指定したソースに変更があった場合自動で再ビルドがかかるようになります（変更をwatchするわけです）

watchしている間は、npm run dev などほかのコマンドは受け付けてくれないので

別のターミナルを起動してそこで実施するとよいでしょう。

※Ver2.0のデフォルトでは、このファイルの容量がとても大きかったのですがjust-in-timeモードがデフォルトになったので必要な量だけをファイルに吐き出してくれるようになりました。

**HTMLでstylesheetを適用する**
buildされたCSSファイルをHTML上で指定します。

```html
<link href="/dist/output.css" rel="stylesheet">
.
.
.
<div className='text-[#384359] text-left self-center font-bold text-xl'>
```

以上で終了です。

### Next.jsなど有名どころのフレームワークのガイドに従ってインストール（追記）
簡単にNext.jsを例に見ていきます。
といってもやり方はCLIの場合とほとんど変わりません

■PJを作る

```bash
npx create-next-app my-project
cd my-project
```

■必要なライブラリをインストールしてinitでtailwind.config.js and postcss.config.jsを作成する

```bash
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
```

tailwind.config.jsは以下のようなイメージ

```json
module.exports = {
  content: [
    "./pages/**/*.{js,ts,jsx,tsx}",
    "./components/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}
```

■globals.cssのの用意

```css
@tailwind base;
@tailwind components;
@tailwind utilities;
```
使い方も役割も一緒

■_app.tsxで読み込む

```tsx:_app.tsx
import '../styles/globals.css';
```

あとはnpm run dev　で動かせばOK。
この状態で以下の様に記述をしても随時CSSの変更が反映される。

```tsx:index.tsx
    <h1 className="text-3xl font-bold underline">
      Hello world!
    </h1>

```
   



### その他の注意点

Next.jsを使っている方はインストールするだけなら、3番の「ガイドにしたがってインストール」の方が若干楽かもです（output.cssを作る過程がnpm run devに含まれているだけ)
ただ、内部の動きを理解する意味でもCLIでのインストール手順を理解しておくことをお勧めします。

また、3.0は2021年の12月になってからリリースされたのでネットの情報は微妙に古い可能性があります。ググるときは要注意です。
SpresenseとDualSenseをつなぐ

Qiita Advent calendar2021の記事です。

:::note
Spresenseの関係会社に勤務していますが、業務外の個人活動の紹介です。
当記事は会社と関係ありません。
:::

:::note alert
誤った基板上のピン接続により故障する可能性があります。
自己責任でお願いします。
:::

AuduinoProMicroやAuduinoProMiniとUSBHostSeildを使い、UART通信でDualSenseの入力をSpresenseで受け取るようにしました。

https://www.switch-science.com/catalog/1622/

このProMiniは今はリンクが切れているようです。
「WayinTop Pro mini ATMEGA328P 3.3V 8M マイコンモジュール 2個 FT232RL USB-TTLシリアル変換器 3.3V/5V切り替え 1個 専用USBケーブ」

https://www.amazon.co.jp/gp/product/B086QKY6JF/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1

https://www.amazon.co.jp/gp/product/B074HTPK13/ref=ppx_yo_dt_b_asin_title_o09_s00?ie=UTF8&psc=1

Micro ProやMini ProとUSBホストシールドを接続する方法はこちらを参考にしました。

https://thom.hateblo.jp/entry/2020/11/21/011120

####ライブラリ

こちらのライブラリを使用させていただきます。

https://github.com/felis/USB_Host_Shield_2.0

PS5USB.inoを用いました。

ProMiniへ書き込むときの接続の様子

<img width="200" alt="20211219_141636.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/3836bfb0-f1e3-6cb2-d973-d2a4960eb8dd.jpeg">

SpresenseにつなげたいのでUARTで出力させます。
もしPro Microを使う場合は出力がそのままだとUSBになりますので、スクリプト中の”Serial”を”Serial1”にしました。

参考

https://trac.switch-science.com/wiki/Guide/ArduinoLeonardo#USB%E3%81%A8%E3%82%B7%E3%83%AA%E3%82%A2%E3%83%AB%E9%80%9A%E4%BF%A1%E3%81%AE%E5%88%86%E9%9B%A2

####Micro/MiniProとSpresenseの接続
|Micro/MiniPro|Spresense
|---|---|
|GND|GND|
|RAW|VOUT (5V)|
|TXO|D7|
|RXI|D8|

####Spresenseに書き込むスケッチ

<details><summary> サンプルコード　簡単なUART通信</summary><div>

``` 
#include <SoftwareSerial.h>

SoftwareSerial mySerial(7, 8); 

//receive sketch
void setup() 
{
  Serial.begin(115200);
  mySerial.begin(115200);
  
  Serial.print("test start");
}

void loop() {
  while(mySerial.available()) {
    Serial.write(mySerial.read());
//    if(mySerial.available()==0)
//      Serial.println("");
  }
}

```

</div></details>


####実行の様子

https://youtu.be/hWo7uwwlJho

BT用のライブラリを使うと無線化もできました。
感謝です。
もうメンテされてないライブラリに最新のlog4jを強制する方法

# 問題
直接的にlog4jを利用している場合は、更新 or logbackへの移行 を行えばよい
しかし、脆弱なlog4jへの依存があるライブラリは、ライブラリ側の更新を待つ必要がある
そして、ある程度の規模のライブラリでも、結構な確率でメンテされておらず更新が見込めない

# 対処
```gradle:build.gradle
ext["log4j2.version"] = "2.17.0"
```
外部から最新バージョンの使用を強制するため動作は保証されないが、脆弱なまま放置するよりはマシである
アルファベットの連続データを取得するVBScript

A、B、C、D・・AA、AB・・BA、BB・・と続くデータ（要するに Excel の列名）をテキストで取り出す VBScript

```vb:GetAlphabetSequence.vbs
Dim val
val = CLng(GetInput("連続データの個数を入力してください"))
CreateObject("WScript.Shell").Exec("clip").StdIn.Write GetAlphabetSequence(val)
Msgbox "アルファベットの連続データを " & val & " 個コピーしました。"
```
```vb
Function GetAlphabetSequence(ByVal seq_length)

	Dim i, r, n, str, alphabetSequence

	For i = 1 To seq_length
	    n = i
	    str = ""

	    Do While n > 26
	        r = n Mod 26: If r = 0 Then r = 26
	        n = n \ 26: If r = 26 Then n = n - 1
	        str = Chr(r + 64) & str
	    Loop

	    If n <> 0 Then str = Chr(n + 64) & str
	    alphabetSequence = alphabetSequence + str + vbCrLf
	Next
	
	GetAlphabetSequence = alphabetSequence

End Function
```

```vb
'// InputBox の入力値を返す
Function GetInput(ByVal msg)
    Dim val
    val = InputBox(msg)
    If IsEmpty(val) Then MsgBox "キャンセルされました。": WScript.Quit
    If val = "" Then MsgBox "何も入力されていません。": WScript.Quit
    GetInput = val
End Function
【Django】settigs.py に記載するログイン関連の設定を整理してみた

# settings.py に記載する ログイン関連の設定を整理

```py:settings.py
# ここの設定を整理
LOGIN_URL = ''
LOGIN_REDIRECT_URL = ''
LOGOUT_REDIRECT_URL = ''
```

## LOGIN_URL

`LOGIN_URL` には、実際のログイン処理を実行するページ(URL)を指定する。

```py:settings.py
LOGIN_URL = 'app:login'
```

このように指定した場合、 app アプリケーションの name='login' のページで
ログイン認証が行えるようになる。

```py:urls.py
from django.urls import path
from . import views
from django.contrib.auth import views as auth_views

app_name = 'app'
urlpatterns = [
    path('', views.index, name='index'),
    path('login/', auth_views.LoginView.as_view(template_name='app/login.html'), name='login'),
    path('logout/', auth_views.LogoutView.as_view(), name='logout'),
]
```

例えば、↑のようなurls.pyを用意すると、

http://url/login/ (login.html)
ページにて、ログイン認証が行える。

app:login = app_name:name属性の対応っぽい

逆に、`LOGIN_URL` に指定していないページでは、
認証関連のフィールドが利用できない。
{% if request.user.is_authenticated %} のような条件分岐が無効になってしまう。

## LOGIN_REDIRECT_URL

`LOGIN_REDIRECT_URL` には、ログイン処理を実行して認証されたときに飛ぶ先のURLを指定する。

```py:settings.py
LOGIN_REDIRECT_URL = 'app:index'
```

このように指定した場合、ログイン認証が承認されたときに、
app アプリケーションの name='index'のページにリダイレクトされる。

## LOGOUT_REDIRECT_URL

もはや説明不要だけど
`LOGOUT_REDIRECT_URL` には、ログアウト処理を実行したときに飛ぶ先のURLを指定する。

```py:settigs.py
LOGOUT_REDIRECT_URL = 'app:login'
```

このように設定した場合、ログアウト処理が実行されたときに、
app アプリケーションの name='login'のページにリダイレクトされる。

# まとめ

- LOGIN_URL = 'app:login'
    → ログイン処理が行えるページ
- LOGIN_REDIRECT_URL = 'app:index'
    → ログイン完了したときにリダイレクトする先
- LOGOUT_REDIRECT_URL = 'app:index'
    → ログアウトしたときにリダイレクトする先

# 所感

LOGIN_URLの理解が苦戦した
ログインのページ以外でログイン認証実装しようとしてずっと無反応で頭抱えてしまっていた
[python] shutilを用いたファイル・フォルダ操作（コピー・削除・移動）

# 初めに
pythonでのファイル・ディレクトリ操作時に使用されるshutilライブラリの使用方法を記載する。

## 紹介内容

|関数|処理|内容|
|---|---|---|
|.copyfile(src, dst)|コピー|ファイルのコピー|
|.copy(src, dst)	|コピー|ファイルのコピーもしくはディレクトリ下へコピー|
|.copy2(src, dst)|コピー|ファイルのコピーもしくはディレクトリ下へコピー（メタデータ含む）|
|.copytree(src, dst)|コピー|ディレクトリツリーのコピー（メタデータ含む）|
|.rmtree(src)|削除|ディレクトリツリーの削除|
|.move(src, dst)|移動|ディレクトリツリーの移動（メタデータ含む）|


# shutil
ファイルやディレクトリを操作する際に、使用するライブラリ。
標準的に導入されているため、外部からのインストールは基本的に不要。

```python
import shutil
```

公式ドキュメント
>モジュールはファイルやファイルの集まりに対する高水準の操作方法を多数提供します。
特にファイルのコピーや削除のための関数が用意されています。

https://docs.python.org/ja/3/library/shutil.html

# コピー
ファイルおよびディレクトリのコピーは以下の関数で実施する。
以下の例では、srcからdstへコピーを行う。

|関数|内容|
|---|---|
|.copyfile(src, dst)|ファイルのコピー|
|.copy(src, dst)|ファイルのコピーもしくはディレクトリ下へコピー|
|.copy2(src, dst)|ファイルのコピーもしくはディレクトリ下へコピー（メタデータ含む）|
|.copytree(src, dst)|ディレクトリツリーのコピー（メタデータ含む）|

## ファイル
ファイルがコピー（複製）される。
ファイルパスからファイルパスを指定する。

```bash:コピー処理前
.
┗ test_old
   ┗ old.txt
```

```python
import shutil
path_old = './test_old/old.txt'
path_new = './test_old/new.txt'

shutil.copyfile(path_old, path_new)
# shutil.copy(path_old, path_new) # コピー動作は同様
# shutil.copy2(path_old, path_new) # コピー動作は同様 ※メタデータのコピーあり
```
```bash:コピー処理後
.
┗ test_old
   ┣ old.txt
   ┗ new.txt
```

## ディレクトリ下
コピーするファイルパスを指定し、移動先にディレクトリを指定する。
移動先のディレクトリに、指定したファイルがコピーされる。

```bash:コピー処理前
.
┣ test_old
┃  ┗ old.txt
┗ test_new
```

```python
import shutil
path_old = './test_old/old.txt'
path_new = './test_new' # ディレクトリを指定することが可能

shutil.copy(path_old, path_new)
# shutil.copy2(path_old, path_new) # コピー動作は同様 ※メタデータのコピーあり
```
```bash:コピー処理後
.
┣ test_old
┃  ┗ old.txt
┗ test_new
   ┗ old.txt
```

## ディレクトリツリー
ディレクトリからディレクトリを指定し、指定したディレクトリ以下のディレクトリツリーをコピーする。

```bash:コピー処理前
.
┗ test_old
   ┗ old.txt
```

```python
import shutil
path_old = './test_old'
path_new = './test_new'

shutil.copytree(path_old, path_new)
```
```bash:コピー処理後
.
┣ test_old
┃  ┗ old.txt
┗ test_new
   ┗ old.txt
```

# 削除
ファイルおよびディレクトリ削除は、shutil.rmtreeで行う。

## ディレクトリツリー
指定したファイルもしくはディレクトリを削除する。
ディレクトリを指定した場合は、そのディレクトリを含む、ディレクトリツリーが削除される。

```bash:削除処理前
.
┣ test_old
┃  ┗ old.txt
┗ test_new
   ┗ old.txt
```

```python
import shutil
path_old = './test_old'

shutil.rmtree(path_old)
```
```bash:削除処理後
.
┗ test_new
   ┗ old.txt
```

# 移動

ファイルおよびディレクトリの移動は、shutil.moveで行う。
移動動作は、ファイルおよびディレクトリのコピー後、元を削除することで実施される。
したがって、上記のコピーと削除を組み合わせた動作結果となる。

## ファイル
ファイルパスからファイルパスを指定する。
元のファイルは、コピー後に削除される。

```bash:移動処理前
.
┗ test_old
   ┗ old.txt
```

```python
import shutil
path_old = './test_old/old.txt'
path_new = './test_old/new.txt'

shutil.move(path_old, path_new)
```

```bash:移動処理後
.
┗ test_old
   ┗ new.txt
```

## ディレクトリ
ディレクトリからディレクトリへの移動を指定する。
指定された元のディレクトリは、ディレクトリツリーの移動後、削除される。

```bash:移動処理前
.
┗ test_old
   ┗ old.txt
```

```python
import shutil
path_old = './test_old'
path_new = './test_new'

shutil.move(path_old, path_new)
```

```bash:移動処理後
.
┗ test_new
   ┗ old.txt
```
データサイエンティスト検定リテラシーレベルを受けてみた。

 - [はじめに](#はじめに)
   - [データサイエンティスト検定リテラシーレベルとは](#データサイエンティスト検定リテラシーレベルとは)
   - [受験動機](#受験動機)
   - [受験時の筆者のレベル](#受験時の筆者のレベル)
 - [勉強方法](#勉強方法)
   - [学習期間](#学習期間)
   - [参考書](#参考書)
   - [講座](#講座)
     - [講座の良かった部分](#講座の良かった部分)
     - [講座の不満な部分](#講座の不満な部分)
   - [単語帳アプリ](#単語帳アプリ)
     - [アプリの良かった部分](#アプリの良かった部分)
     - [アプリの不満な部分](#アプリの不満な部分)
 - [試験当日](#試験当日)
 - [今後](#今後)

## はじめに
### データサイエンティスト検定リテラシーレベルとは
一般社団法人データサイエンティスト協会が実施するデータサイエンティストの「見習いレベル」としての実務能力と知識を有することを証明する試験です。  
試験の実施形態は全国の試験会場でのCBT試験となり、第1回の試験は2021年9月11日から9月30日に実施されました。  
ちなみに合否発表は同年11月2日に発表され、幸いにも合格することができました。  
出題範囲は「データサイエンス力」「データエンジニアリング力」「ビジネス力」から見習いレベル？の問題が出題されているようです。  
詳細は[こちら](https://www.datascientist.or.jp/dskentei/)を参照ください。  
今後は「独り立ちレベル」「棟梁レベル」「業界を代表するレベル」とレベルアップした試験が実施されることが予想されます。

### 受験動機
筆者自身が所属する会社がデータを扱うことを生業としているので、業務遂行に於いてアドバンテージとまでは言いませんが、少しでも会社のブランディングに貢献する意味と、自身の実力を試す意味で受験しました。

### 受験時の筆者のレベル
出題範囲3分野共に大枠としての知識は持っている程度です。  
※SQLだけはシステム開発での実務経験があり、ある程度対応できるレベル。

## 勉強方法
できるだけ「お金をかけない」主義なのでケチケチで学習しました。

### 学習期間
試験日を予約してからの約1ヶ月に集中して学習しました。

### 参考書
特になし。

### 講座
スキルアップAI株式会社が無料の「[DS検定リテラシーレベル対応データサイエンティスト基礎講座](https://www.skillupai.com/ds/)」を提供してくださっているので利用させていただきました。  
この講座を先ず1回通しで受講し、2回目に解らないまたは不安のあるキーワードを書き出し、調べた内容を後述する「単語帳」で繰り返し"聞く"方法で学習しました。

#### 講座の良かった部分
無料なのにそこそこボリューミー。  
ビデオ講座なので、止めたり早送りできる。

#### 講座の不満な部分
SQLのセクションでDBサーバのインストールまでは不要かな、というのが正直な感想です。  
無料のためかテキストが提供されなかった。

### 単語帳アプリ
スマホでキーワードと答え・解説のセットを自身でCSVファイルにして取り込むことで任意の学習ができる[アプリ](https://play.google.com/store/apps/details?id=com.langholic.wordholic&hl=ja)です。

#### アプリの良かった部分
キーワードと答え・解説を読み上げてくれるところです。  
多少変な読み上げがありますが、そこは無料で利用できるアプリなので文句は言いません。  
忘却曲線に合わせた効率的な反復復習ができようでしたが、今回筆者はひたすら"聞く"機能しか利用しませんでしたので、宝の持ち腐れ感は否めません。

#### アプリの不満な部分
長い文章の表示には無理があります。  
スマホを横向きにして、キーワードと答え・解説毎にスライドショーで利用することで、ある程度課題は解決できました。  
まあ、単語帳なので、用途が違う使い方には対応できないのは当たり前ですね。

## 試験当日
試験時間の2時間前くらいには会場近くのカフェにて単語帳アプリで復習していました。  
試験開始20分前には会場に入り受付を済ませてボーッした後に試験部屋に案内され試験開始。  
今回の試験では焦るような問題が出題されなかったので、落ち着いて問題を見直すことができました。

## 今後
レベルアップした試験がアナウンスされるはずなので、都度挑戦する予定です。
Dell XPS 13 9300 でスリープ復帰後に Wifi に接続できなくなる

# Dell XPS 13 9300 でスリープ復帰後に Wifi に接続できなくなる

Dell XPS 13 9300 でスリープ復帰後に Wifi に接続できなくなるという問題が発生します。

Dell XPS 13 9300 では、`Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter` というネットワークインターフェースが搭載されています。

スリープ復帰後に、Wifi に自動再接続できなくなったときに デバイスマネージャーで、`Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter`をいったん停止してから、開始することで復帰するのを確認したので、ドライバに何らかのバグがある可能性があるのを疑いました。

https://www.dell.com/support/home/ja-jp/?app=drivers から取得できる最新のドライバでは修正されませんでした。

そこで、 [インテル® ドライバー & サポート・アシスタント](https://www.intel.co.jp/content/www/jp/ja/support/detect.html) から Killer(R) Wi-Fi のドライバを検索したところ

https://www.intel.co.jp/content/www/jp/ja/support/detect.html

Dell のサイトからダウンロードできるドライバより新しい Ver `22.90.0.5` のドライバを取得してインストールしたところ、スリープ解除後に Wifi に自動接続できなくなる問題は解消しました。

なお BIOS バージョンは 1.8.0 を適用済みです。
Dell のサイトから BIOS 含めて他のドライバをすべて最新を適用してから、もしそれでも問題が起きる場合に試すといいと思います。

## 追記 (2022/1/8)

2022/1/3 に Ver `22.100.1.1` のドライバが公開されています。以下サイトから直接ダウンロードできます。
(サイトには `インテル® Killer™ 1550、AX1650、AX1675 の場合22.100.0.3` とありますが、 `22.100.1.1` がインストールされました)

https://www.intel.co.jp/content/www/jp/ja/download/19779/intel-killer-performance-suite.html

上記サイトから直接ダウンロード & インストールしたので確認していないですが、おそらく [インテル® ドライバー & サポート・アシスタント](https://www.intel.co.jp/content/www/jp/ja/support/detect.html) からも取得できると思います。

## 余談

Dell XPS 13 9300 の Wifi の通信速度は2015年に購入した富士通のノートPC の Wifi の転送速度より遅いです。

Killer(R) Wi-Fi というモジュールを採用しているためなのか、購入した日に速度計測してがっかりしたのを覚えています。
XPS 13 って結構高価格のノートPC なので、普通の Intel の Wi-Fi モジュール使ってほしい。
あるいは 通常の Intel製のモジュール並の品質のモジュールを使ってほしい。

Killer ブランドの製品はもともと Rivet Networks という会社のもので、Intel が買収したものらしい。
なのでドライバもインテル® ドライバー & サポート・アシスタントからドライバを取得できる模様。

https://pc.watch.impress.co.jp/docs/news/1253794.html
DOTweenって便利なんだぜ！

#初めに
今回は便利なアセットの代名詞「DOTween」を紹介しようと思います。
私もこれを知ってめちゃくちゃ便利だと思ったので、Unityやり始めるそこの君に是非おすすめしたいです。
※誤字脱字や日本語がおかしくなってる部分があるかもしれませんが、そこも踏まえてみてください！

#目次
>1,DOTweenとは
2.具体的な内容や記述方法

#DOTweenとは
![d28cf7c5-1e07-4494-81e3-bc3ca7539da6.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/866543/226fe6e9-79fc-5a65-f2a2-79258d829df2.jpeg)
DOTweenとは簡単にいうとスクリプトで数行記述することによって、そのオブジェクトをアニメーションすることができるものです。
無料版以外にもPro版もあります。
Aseetストア；https://assetstore.unity.com/packages/tools/animation/dotween-hotween-v2-27676?locale=ja-JP
GitHub；https://github.com/Demigiant/dotween

#具体的な内容や記述方法
DOTweenの機能はめちゃくちゃあるので何個かピックアップして紹介しようと思います。

##目次
>1.まず初めに使うために
2.移動系
3.回転系
4.スケール系
5.その他

##1.まず初めに使うために
まずDOTweenを使うには、一番上のusingって書いてあるところに

```
using DG.Tweening;
```

と記述します。これを忘れるとエラーだらけになるので気をつけましょう。

##2.移動系
ここではオブジェクトの移動について紹介しようと思います。

###DOMove

```
transform.DOMove(new Vector3(2, 0, 0),1f);
```

これを使えば簡単にしてした座標まで指定した秒数で移動することができます。

###DOPath

```
transform.DOPath(point, 1f);
```
これを使えば指定した座標のリストを時間を指定して移動することができます。
これを利用すれば簡易的な周回するbotなどを作れそうですね。

##3.回転系
ここではオブジェクトの回転について紹介しようと思います。
###DORotate

```
transform.DORotate(new Vector3(2, 2, 2), 1f);
```
これを使用すれば、指定した値の方向に指定した時間で回転することができます。
ちょっとした、オープニングのアニメーションなどに使えそうです。

###DOLookAt
```
transform.DOLookAt(Target.transform.position, 1f);
```
これは指定したオブジェクトに向かって振り向くことができます。

##4.スケール系
ここではスケールに関することについて紹介しようと思います。

##DOScale

```
transform.DOScale(new Vector3(2, 2, 2), 1f);
```
これを利用することで指定したスケールに指定した時間で拡大縮小することができます。

##その他
ここでは、さっきまで紹介していたもの以外でおすすめのものを紹介しようと思います。

##DOColor

```
image.DOColor(Color.red,1f);
```
これを使うことによって指定した色に指定した時間で変更することができます。

##DOFade

```
image.DOFade(0,1);
```
これを使うとそのImageのアルファ値を指定した時間で変更することができます。

##DOShakePotision

```
transform.DOShakePotision(1,1);
```
揺れ幅と揺れ時間を指定するとオブジェクトをランダムに揺らすことができます。
これを利用すると衝撃でカメラを揺らすことができそうですね。

#最後に
実際に昔ちょっと作って飽きてやめたゲームでDOTweenを使ってシーン移動したものを貼り付けておきます。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">こんな感じでステージ移動するのもいいな<br>あとURPのライトいい <a href="https://t.co/HDHvKHheXa">pic.twitter.com/HDHvKHheXa</a></p>&mdash; Upon (@Upon_Main) <a href="https://twitter.com/Upon_Main/status/1421744840555995137?ref_src=twsrc%5Etfw">August 1, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 
今回は便利なアセットの代名詞DOTweenを紹介しました。
参考になれば嬉しいです。
よければTwitterのフォローお願いします！ゲーム開発の進捗などを載せています！
⇨https://twitter.com/Upon_Main
Twilio Flex導入に苦戦した話

## はじめに

この記事は[Twilio Flex Advent Calendar 2021](https://qiita.com/advent-calendar/2021/twilio-flex)の19日目の記事です

https://qiita.com/advent-calendar/2021/twilio-flex


普段開発しているプロダクトとは別にフィジビリ等の用途で、アプリケーションに組み込むものとは別にコールセンターの対応が必要になり、Twilio Flexというものの存在に行き着きました

そこでTwilio Flexの導入を決めたのですが、すんなりうまく行かなかったので備忘録としてその経緯をここに残します

## Twilio Flexとは

Twilioは電話やSMSなどコミュニケーションに関するクラウドAPIを提供するSaaSで、プログラマティックに発着信・自動応答メッセージなどを扱うことができます

機能が豊富で様々な事が可能な一方、APIを経由した機能実装する必要があり、コールセンターそのものにのみ関心があるユーザーからは導入へのハードルがありました

そこで登場したのがTwilio Flexです

https://www.twilio.com/ja/flex

Twilio Flexはサーバー管理や開発が不要で、コールセンター構築を行うことができます

またインフラをTwilio側で管理しているため、大規模になっても自動でスケールし非常に実績もあります

## Twilio Flex導入で起きた問題

開発が不要で手軽にコールセンター構築する必要があったため、以下の記事よりTwilio Flexのセットアップを行いました

https://qiita.com/mobilebiz/items/28ca15684e2f4a82b7f2

Flexのタブから開始ボタンを押すことによってセットアップが可能とのことだったのですが、タブを開いた所そのボタンが見当たりませんでした

![スクリーンショット 2021-12-18 22.18.00.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18783/d683f8a1-f29a-3803-aa98-4a1f5f69bcac.jpeg)

画面の指示通り、`Create my Flex Account` とあるようにFlex用のアカウント作成する必要があるとのことだったので、新規アカウントの作成を行いました

アカウント作成後新しいアカウントでFlexが使えると思いきや、同様の画面が表示され全く同じ事象が発生

![スクリーンショット_2021-12-18_22_18_00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18783/13783e61-0782-d73a-48cf-0625135bc865.png)

何度も同じ作業をした結果、新規Twilioアカウントが大量に生成されました

![スクリーンショット_2021-12-18_22_29_36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18783/21aaff92-d3f6-d5f2-2e4d-5a56cd700c0f.png)

さらにはTwilioアカウントを有効化する際にSMSによる認証が必要なのですが、アカウントと紐付け可能な電話番号の数には上限があり、試行錯誤できない状態に陥り詰みました...

## 先に解決策

上記のような事象に陥り、先に解決策だけ提示しておきます

それは新規アカウント有効化時にTwilioの利用目的を選択する必要があるのですが、Flexを利用する選択肢を選ばなきゃいけないというものでした

![unnamed.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18783/ff4af223-af26-61f1-265b-68810e4df7a7.png)

自分は当初Twilio導入動機を集計するためのアンケートだと思っていたのですが、選択肢によってアカウント自体のセットアップの設定が変わるみたいです。。。

## 解決に至るまで

まずはアカウント内のサポート問い合わせ画面からサポートケースをあげようとした所403で何もできず...
(アカウントのグレード等関係あるのか利用できる条件が分かれば教えて欲しい...)

![スクリーンショット_2021-12-19_13_29_09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18783/87ec9a61-c2fa-87f0-5d90-f3b28dcb5eae.png)

続いて、以下の問い合わせ先に詳しい状況を記載して問い合わせ

https://www.twilio.com/japan/help/sales

こちらフォーム自体Twilio導入に向けた営業向けの問い合わせ先？だったため、結果的に返信等の音沙汰がありませんでした...

最終的に `help@twilio.com` へ問い合わせのメールを送りました

その結果、すぐさま返信があり、詳しい状況の報告を行いました

メールのやり取りだけでは問題が解決しそうになかったので、zoomをすることになり拙い英語でやり取りしながら、問題の発生状況を共有しました

(そこでzoomの機能としてリモート操作を使い、zoom越しにパソコンを自由にいじってもらう機能があって感動した)

そして、Twilioチーム内で原因を調査していただき、上記のような回答をいただき問題が解決しました

![スクリーンショット 2021-12-19 13.39.35.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18783/2e50211d-c9c1-70b1-8799-971fe988ceb2.jpeg)

Twilio Flex自体一切プログラミングすることなくコールセンター業務ができて最高です！

## まとめ

Twilio Flexを導入しようとしたが、Flexを起動できずアカウントを作成ループ問題に直面しました

解決方法として、Twilioのアカウントセットアップ時に選ぶ選択肢を正しく選ぶ必要があります

また、その解決法を知るまでにTwilioサポートの方々に迅速かつ真摯に問題に向き合っていただきました！

その対応速度と内容について非常に感動しました！
(そもそも問い合わせ方法として間違っている可能性があるので、正しいフローがあればどなたか教授いただけると幸いです)

以上Twilio Flex導入に苦戦した話でした
PHP: stripe API 使い方 (List all customers)

こちらのページの続きです。
[stripe API 使い方 (List all customers)](https://qiita.com/ekzemplaro/items/ed152ef41f1e81811519)

#PHP Requests でカスタマーの一覧を取得#

必要なライブラリーのインストール

```bash
composer require rmccue/requests
composer require vlucas/phpdotenv
```

ツリー構造

```text
$ tree -a -L 1
.
├── .env -> ../.env
├── composer.json
├── composer.lock
├── get_customers_requests.php
└── vendor
```

```php:get_customers_requests.php
#! /usr/bin/php
<?php
// ------------------------------------------------------------------
//	get_customers_requests.php
//
//					Dec/19/2021
// ------------------------------------------------------------------
require_once("vendor/autoload.php");
//
fputs (STDERR,"*** 開始 ***\n");

Requests::register_autoloader();

$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load();

$secret_key = $_ENV['SECRET_KEY'];

$url = 'https://api.stripe.com/v1/customers';

$headers = array('Accept' => 'application/json');
$options = array('auth' => array($secret_key, ''));

$request = WpOrg\Requests\Requests::get($url, $headers, $options);

var_dump($request->status_code);

$json_string = $request->body;

$dict_aa = json_decode ($json_string,true);

// var_dump ($dict_aa["data"]);

foreach ($dict_aa["data"] as $value)
	{
	print $value["id"] . "\n";
	}

fputs (STDERR,"*** 終了 ***\n");
// ------------------------------------------------------------------
?>
```


実行結果

```text
$ ./get_customers_requests.php 
*** 開始 ***
PHP Deprecated:  The PSR-0 `Requests_...` class names in the Request library are deprecated. Switch to the PSR-4 `WpOrg\Requests\...` class names at your earliest convenience. in /home/uchida/projects/stripe/php_requests/vendor/rmccue/requests/library/Requests.php on line 24
int(200)
cus_KmrIU4hzWqYt7R
cus_KmoG4k1wiKxSDc
cus_KmnqmJhBAvPGMq
cus_KmnpiRFjm8he97
*** 終了 ***
```

#PHP sdk でカスタマーの一覧を取得#

必要なライブラリーのインストール

```bash
composer require stripe/stripe-php
composer require vlucas/phpdotenv
```

ツリー構造

```text
$ tree -a -L 1
.
├── .env -> ../.env
├── composer.json
├── composer.lock
├── get_customers_sdk.php
└── vendor
```

```php:get_customers_sdk.php
#! /usr/bin/php
<?php
// ------------------------------------------------------------------
//	get_customers_sdk.php
//
//					Dec/19/2021
// ------------------------------------------------------------------
require_once("vendor/autoload.php");
//
fputs (STDERR,"*** 開始 ***\n");

$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load();

$secret_key = $_ENV['SECRET_KEY'];

$stripe = new \Stripe\StripeClient($secret_key);

$cc = $stripe->customers->all(['limit' => 10]);

// var_dump ($cc["data"]);

foreach ($cc["data"] as $value)
	{
	print $value["id"] . "\n";
	}

fputs (STDERR,"*** 終了 ***\n");
// ------------------------------------------------------------------
?>
```

実行結果

```text
$ ./get_customers_sdk.php 
*** 開始 ***
cus_KmrIU4hzWqYt7R
cus_KmoG4k1wiKxSDc
cus_KmnqmJhBAvPGMq
cus_KmnpiRFjm8he97
*** 終了 ***
```
脆弱なlog4jへの依存を1コマンドで把握する

# log4shellについて
- [Log4jの深刻な脆弱性CVE-2021-44228についてまとめてみた](https://piyolog.hatenadiary.jp/entry/2021/12/13/045541)

# 問題
log4jの対応を行う上での最大の問題は、膨大な依存の中から完全に取り除く必要がある点である
直接的にlog4jを利用している場合は、更新 or logbackへの移行 を行えばよい
しかし、外部ライブラリやフレームワークが利用している場合は、そもそも依存の把握自体が困難になる

# 対処
## 方法1 gradale dependencies
gradleの`dependencies` タスクを利用する
現時点の全ての依存のリストを出力することができる
ただ、単純な依存ツリーを吐き出しているだけなので、ある程度の規模のアプリケーションでは数万行になる
そのため、特定のバージョンのライブラリを取り除く目的にはあまり適していない

## 方法2 OWASP dependency check
OWASP(Open Web Application Security Project)の[dependency check plugin](https://owasp.org/www-project-dependency-check/)を利用する
セキュリティに特化していて、CVEなどのデータベースを基に、脆弱な依存を集計してリストアップできる
そのため、どのライブラリが依存しているのか把握しやすい
また、リストアップされない = 脆弱な依存は存在しない = 対応が完了 というハンドリングの判断に利用できる

Gradle projectであれば、以下の1コマンドで実行できる

```shell
./gradlew dependencyCheckAnalyze
```

# 結論
log4shellの対応にはOWASPのdependency check pluginを使用すべき
DBのインデックスとは

## 勉強前イメージ

検索しやすくする・・・みたいな感じだった気がする

## 調査

### インデックス とは

索引という意味で、データベースのテーブルへの検索処理を高速させるものになります。
インデックスをはると、膨大なデータベースの中の特定データを検索する際にどこにそのデータが存在するかを短時間で特定できます。
テーブルとは別にインデックス用のデータとして作成され、テーブルとは別で管理されるイメージです。

### インデックスの効果について

インデックスには効果として現れる場合と現れない場合があります。
効果として現れる場合の特徴は以下になります。
特にデータが多いとそもそも全文を検索しながら確認を行うようなもので遅くなります。
- データの行数が多い
- 検索対象の項目に値の重複や偏りが少ない
- 表の更新・追加等が少ない

現れづらいのは以下になります。
そもそもデータが少なかったらインデックスをはったとしても時間の差分はあまりない場合があります。
- データの行数が少ない
- 検索の際に表の殆どのデータを取得する

### インデックスの種類

インデックスはいくつか種類がありますが、代表的なものは以下になります。

- Bツリーインデックス

木構造のインデックスでoracleのデフォルトのインデックスになります。
ルートノード・ブランチノード(※1)には関連付けられている子要素が持ってるキーの値のデータと位置情報が格納されています。
リーフノード(※2)にはキーの値とレコードの位置を示す位置情報が格納されています。

※1
ルートノード(親要素のないブロック)
ブランチノード(親要素・子要素どちらも持ってるブロック)

※2
リーフノード(子要素のないブロック)

- ビットマップインデックス

キーの値を含む行をビット1を立てて表すインデックスで、
ビット1が立っている行の格納位置を取得した後、取得した位置情報を使ってデータにアクセスします。

- ハッシュインデックス

Mysql等で使用されているインデックスで、
キーの値をハッシュ化した値をデータに格納し、検索の際にはハッシュ化したキーの値の場所に直接アクセスします。

## 勉強後イメージ

なんか前もちょっとやったような気もするけど出てこないので見てみた。
ルートノードとかも初めて知った。
どこに何があるか早く検索できるためだね。
よく使うSQLとかだったらインデックスはるのが効果的？

## 参考

- [インデックスとは？仕組みをわかりやすく解説](https://products.sint.co.jp/siob/blog/index)
- [インデックスとは（データベース）](https://medium-company.com/%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9-%E3%82%A4%E3%83%B3%E3%83%87%E3%83%83%E3%82%AF%E3%82%B9/)
【git】.gitignore を記載したのに、管理対象から外れないとき【初歩】

# すでにgitで管理されてしまってるファイルのignore方法

すごい初歩的な内容です

すでにgit add されてしまっているファイルは、
.gitignoreの記載に関係なく変更を追跡してしまう。

この場合は、git rm で 管理対象から外す

```
git rm --cached file名
```

.gitignoreをいくら変更しても反応しないので頭おかしくなりそうでしたが、
灯台下暗しでした。

[参考](https://www-creators.com/archives/1662)
ssh: connect to host github.com port 22: Operation timed out

## エラー内容
徳丸本でハンズオンした後、git pushとかgit fetchができなくなっていました。
www.amazon.co.jp/dp/4797393165

```sh:zsh
$ ssh -T github.com
ssh: connect to host github.com port 22: Operation timed out
```

## 原因
ssh鍵を再発行して、githubに公開鍵を登録し直しましたが、相変わらずでした。

ググったところ、こちらの公式ページにたどり着きました。
https://docs.github.com/en/authentication/troubleshooting-ssh/using-ssh-over-the-https-port
試しに443ポートで接続すると、つながりました。どうやら、知らないうちにファイアウォールを設定していたみたいです。

```sh:zsh
$ ssh -T -p 443 git@ssh.github.com
Hi username! You've successfully authenticated, but GitHub does not provide shell access.
```

## 解決方法
ssh設定ファイルに443ポートを設定します。

```:~/.ssh/config
Host github.com
    User git
    Hostname ssh.github.com
    Port 443
    IdentityFile ~/.ssh/id_rsa # 秘密鍵ファイル
```

以上です
bash で数値計算しようとして罠に

# bash で数値計算しようとして罠に

## bash で数値計算する方法

Bash で数値計算しようとすると

```bash
NUM=1
RESULT=$(expr $NUM + 1)
echo $RESULT
```

これで計算できます。Bashの場合はもっと良い方法として、

```bash
NUM=1
RESULT=$(($NUM + 1))
echo $RESULT
```

この書き方もあります。どうやらこっちの方が早いらしいです。

## 罠

ある時、 `expr`を利用していたものを `$(( ... ))` の書き方に変更しました。
すると、把握していなかった `expr` と `$(( ... ))` の動きの違いにはまり混乱しました。

…

ある日…、`01_hoge.tgz` みたいなファイル名があった場合に、`02_hoge.tgz` みたいな番号を計算して出そうとしていました。

最初次のように書いていました。

```bash
NUM=$(ls *_hoge.tgz | tail -n1 | cut -d_ -f1)
RESULT=$(expr $NUM + 1 )
echo $RESULT
```

これで動いていました。そして、リファクタリングをして、

```bash
NUM=$(ls *_hoge.tgz | tail -n1 | cut -d_ -f1)
RESULT=$(( $NUM + 1 ))
echo $RESULT
```

このように書き換えました。これも動きました。最初は。
しばらくして、番号が、`08_hoge.tgz` が表れた時…

```plain
value too great for base (error token is "08")
```

とエラーが起きました…。

`$(( ... ))` は 0xFF(16進数) や 071(8進数)といった表記を解釈するようです。
対して `expr` はあくまで10進数の数値であることを前提にしているようです。

今回は、2桁に揃えるために0で埋めていたために、8進数として解釈され、存在しない `8` という数字でエラーが起きました。最初うまく動いていただけに、しばらく気づけませんでした…。

結論、今回は意図して、`expr` を使うのが良いということがわかりました。

## 最後に

`$(( ... ))` は`0xFF`や`010`といった表記を解釈して、`expr`はあくまで10進数として解釈するという話は忘れないようにしましょうという話でした。

特に、01, 02, 03, ... みたいな連番を作りたい場合は、特に気を付けましょう。
お手軽なコンポーネント依存性管理方法

## はじめに
ちょっとしたアプリやライブラリを作っていて、コンポーネントの依存性を管理したくなる時があります。例えば、「あるコンポーネントは毎回作成したいけど他のコンポーネントはシングルトンにしたい。そして、それらのコンポーネント間に依存関係がある。」と言った場合です。

もちろん、世の中には依存性管理のためのライブラリがいくつもあるのでそれらを活用するのも良いでしょう。しかし、わざわざライブラリを導入するほどでもないということも多いかと思います。そんな時に私が使っているお手軽な方法を紹介したいと思います。

## 前提

Controller、Service、Repositoryという3つのコンポーネントがあって、それらに依存関係があるとします。なお、Controllerは毎回新規のインスタンスが生成され、ServiceとRepositoryはシングルトンとして扱われるものとします。

シーケンス図で表すとこんな感じでしょうか。

```
+------------+    +------------+    +------------+  
| Controller |    |  Service   |    | Repository |  
+-----+------+    +-----+------+    +-----+------+  
      |                 |                 |         
      |    execute()    |                 |         
      +---------------->|    execute()    |         
      |                 |---------------->|         
      |                 |<----------------+         
      |<----------------+                 |          
```

コードも示してみます。

各コンポーネントの中では、自身の文字列表現と後続のコンポーネントの実行結果を連結しています。これは、呼び出しごとに新インスタンスが生成されているのか、同じインスタンスが使われているのか後ほど確認するためです。

```kotlin:Controller
class Controller(private val service: Service) {
    fun execute(): String {
        return this.toString() + " -> " + service.execute()
    }
}
```

```kotlin:Service
class Service(private val repository: Repository) {
    fun execute(): String {
        return this.toString()+ " -> " + repository.execute()
    }
}
```

```kotlin:Repository
class Repository {
    fun execute(): String {
        return this.toString()
    }
}
```

## 解決方法

私はこんな感じのコードを書いてコンポーネントの依存関係を管理します。

```kotlin:Container
object Container {
    // 呼ばれるたびに新規インスタンス作成
    val controller get() = Controller(service)
    // シングルトン
    val service by lazy { Service(repository) }
    // シングルトン
    val repository by lazy { Repository() }
}
```

### ポイント
このクラスのポイントは3つです。

- 依存先コンポーネントはプロパティ経由で得る
- `get()`を使うことでControllerのインスタンスは毎回生成
- `lazy`を使うことでSeriverとRepositoryのインスタンスは1度だけ生成（実質的にシングルトン）

1度だけだ生成するなら`lazy`を使う代わりに`val service = Service(repository)`のようにプロパティのinitializerを使えばいいのではないかと思ったかもしれません。しかし、これはうまくいかないのです。参照している`repository`プロパティはまだ宣言されていないのでコンパイルエラーになります。もちろん先に`repository`を宣言した上で`service`プロパティを宣言すればinitializerを使う方法でも構わないのですが、`lazy`を使うことでプロパティの宣言順序を気にする必要がなくなります。

### Containerの利用例

上述のContainerを利用してみましょう。

```kotlin:main
fun main() {
    val controller1 = Container.controller
    println(controller1.execute())

    val controller2 = Container.controller
    println(controller2.execute())
}
```

実行結果はこんな感じになります。

```
example.Controller@6ce253f1 -> example.Service@53d8d10a -> example.Repository@e9e54c2
example.Controller@65ab7765 -> example.Service@53d8d10a -> example.Repository@e9e54c2
```

以下のことがわかりますね。

- Controllerは1度目と2度目の呼び出しで異なるインスタンス
- ServiceとRepositoryは1度目と2度目の呼び出しで同じインスタンス

## おわりに

`get()`や`lazy`など、標準で組み込まれている機能を使うことでコンポーネントの依存性管理が簡単にできることを紹介しました。

もし良ければお試しください。
この方法ではうまくいかないケースがあるなどのフィードバックも歓迎です。
BagCをUIFlowでPuiPuiモルカー

BagCをUIFlowでPuiPuiモルカー
-------------------------------
M5stickCの拡張ユニット「BagC」と「Joystick」をUIFlowで設定
m5stackのサンプルプログラムだけで簡単に動かせます
羊毛フエルトで作ったモルカーを被せました。
![pui.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228252/829df331-c9be-5c2c-9033-80975c0c0f3e.gif)
![IMG_4868.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228252/5c429901-6c4b-5f9c-c5c9-cfc62c3b7f40.jpeg)


必要なもの
----------------------
（本体）M5stickC、BagC　
　羊毛フエルト、ニードル、スポンジ、目玉用ボタン（100均の手芸コーナーに揃っています）
（リモコン）M5stickC、Joystick　
![IMG_4877.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228252/b0492a3b-e2f7-c985-2892-27060a203913.jpeg)


UIFlowでサンプルファイルを開く
------------------------
UIFlowのサンプルはM5stickのGitHubサイトから
M5-ProductExampleCodes-masterをダウンロードし
\Hat\BugC\UIFlow\With_the_controllerにある
bugc.m5f（BagC用）とbugc_ctl.m5f（Joystick用）を利用します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228252/5884739e-614d-9f71-4254-b29b06ad4911.png)

https://github.com/m5stack/M5-ProductExampleCodes

![bugc2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228252/a7bc03d7-7197-0aa5-d6b4-bfcdbbc408e5.jpeg)

M5stickCにBagCを接続しbugc.m5fを開き、M5stickCに書き込むとこんな感じ

![bugc5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228252/a85d6791-675e-3be4-17cb-31dee44a5ca2.jpeg)


羊毛フエルトでモルカーをつくる
------------------------------------------
BagCに被せる大きさにスポンジをカットし
これに羊毛フエルトを、ニードルで根気よく刺し固めます。
タイヤなどのパーツ、目玉ボタンを取り付け、スポンジを取り外してBagCに被せれば完成
![IMG_4881.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228252/9f0177c8-dfd8-3b86-f24b-1ad687152789.jpeg)



まとめ
-----------------------------
今回はサンプルプログラムだけで設定しました
モーター軸の回転だけで前進や後退させていますので
少し斜めに移動する場合があります。
その場合はモーター回転のパラメータを調整します
iPadでアプリをリリース

# Apple Developer Programにサインイン
![IMG_2235.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/d5feb1ad-f131-05b0-1f7d-cde642b44ae1.png)

# Swiftパッケージ
Alamofireをインストールしてみます。
![IMG_2236.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/2e69e814-da8d-f3a0-f3b6-a6f709642e05.png)

「Swiftパッケージ」を選択

![IMG_2237.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/4d8aac69-388d-ebdc-80e9-a46c02ed62de.png)

パッケージURLを入力したらキーボードでreturnキーを押しましょう
「プロジェクトに追加」で追加されます。

# 使えないパッケージもある
![IMG_2244.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/01100d97-c85c-1b55-9268-28841d117cd4.jpeg)

Objective-Cを含むライブラリは仕様できない模様。
「ターゲットタイプ"ClangTrget"には対応していません。」と出てビルドできなくなります。

# 提出準備
![IMG_2265.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/0238830d-cce3-8475-7aac-db4835ac7416.jpeg)
左側にある「App設定」を選択します
![IMG_2252.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/06549b94-2ed2-17d6-b6cc-661faf4e1aa8.jpeg)
![IMG_2253 2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/47593ee5-7fc9-4863-2ad5-2620cb3a1a0c.jpeg)

|項目|機能|Xcodeでの表示|
|---|---|--|
|名前|ホーム画面での表示名|Display Name|
|アイコン|アプリのアイコン|AppIcon|
|機能|アクセス許可ダイアログ|info.plist|
|チームおよびバンドルID||Bundle Identifier|
|バージョン番号||Version|

全て設定が終わったら「App Store Connectにアップロード」

![IMG_2255.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/37312e8f-274e-4294-8750-2196eb3acd60.jpeg)

- APP STORE名
- 優先する言語
- SKU

SKUはチームおよびバンドルIDで設定したものを設定するのがいいと思います。

![IMG_2257.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/12db1d9f-4dcb-f86c-1e14-0cffce6e7782.jpeg)

ここまでくればあとはApp Store Connectで今まで通りの手順で審査に出すことができます。

# 便利な点
- 設定するアイコンが1枚でいい
- Buildの番号をいちいち変えなくていい
- Xcodeのように複雑ではないので操作を間違えようがない
- プレビューが速い

# 不便な点
- コードが書きにくい
- 実機を持っていないと提出用のスクショが作れない。
- iPhoneのみ対応にできない
- 使えないライブラリがある

# おわり
https://apps.apple.com/jp/app/%E3%83%A1%E3%83%A2-cui%E9%A2%A8/id1600911080

![無題131_20211217233157 2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/676fedf6-1b3f-0952-32cb-cd03f8534239.png)

今回作ったアプリです
数時間で作ったので低クオです笑
それにしても審査長すぎだよー

まだできない事は多いですが、iPadやiPhoneでアプリが作れるってやばいです
pythonからpyperを使ってRを実行し、出力グラフ画像をbase64取得

# はじめに
pandasのデータフレームと連携する形での記述。
最近確実に需要のない記事ばっかり、、(;´Д｀)

# 環境
 - windows10
 - python 3.9.4
 - R 4.12

pip

```shell
pip install pyper
```

R(package)

```
install.packages("ggplot2")
install.packages("shiny", dependencies = TRUE)
```
※何らかの形でggplot2とshinyをインストールすればよいかと
※shinyはbase64のエンコードに必要

# コード

```python
import pyper
import numpy
import pandas

# ランダムデータフレーム作成
n = 100
randomArray = numpy.random.normal(0, 10, n)
df = pandas.DataFrame({"xData": randomArray})

# Rの実行オブジェクト作成
r = pyper.R()
# pandasのオブジェクトをRで扱えるようにする
r = pyper.R(use_pandas="True")
# 作成したデータフレームを設定
r.assign("p_df", df)

r(
    """
# ライブラリインポート
library(ggplot2)
library(shiny)

# グラフのプロットデータ作成
p <- ggplot(data = p_df,
      mapping = aes(x=xData)) +
      geom_density(fill = "gold")

# 画像出力(サイズは dpi*width × dpi*height のピクセルサイズとなる)
ggsave(filename = "sample.png",
       plot = p,
       device = "png",
       width = 6.4, height = 4.8,
       dpi = 100)

# base64変換
b64image <- base64enc::dataURI(file = "sample.png", mime = "image/png")
"""
)

# Rで変換した内容を取得
res = r.get("b64image")
# とりあえずは標準出力
print(res)
```

# 終わりに
shinyはbase64encだけ実行できれば良いとは思うんだけど、やたらサイズがデカい、、細かくパッケージインストールする方法とかbase64エンコードできるほかのパッケージとかあるかも、、
聴く音楽でランニングのタイムが変わるかを検証


(時速と目標タイムをプログラムで求めてみました)

運動不足解消にたまに音楽聞きながら走るのですがふと疑問に思ったことがあります。
それは
#「聞く音楽によって走る速さは変わるのか」

今回は１回目はバラード系、２回目はロック系を流しながら走ってタイムの違いが出るかを、自宅の近くにある往復で約３キロの河川敷を走って検証しました。ちなみに個人的にはロックのほうが良いタイムで走れると思っています。

１回目のプレイリストはこんな感じです。
![IMG_6934[1].PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2301724/2b53657a-9738-776e-9891-94b19b1a64c0.png)
タイムは11分9秒99でした。
![IMG_6940[1].PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2301724/347f7454-7a93-0d80-df33-469f50ea0fd1.png)
次にロックを流しながら走りました。
プレイリストはこんな感じです。
![IMG_6942[1].PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2301724/21d6009f-281d-9f47-7e70-20d193444a65.png)

タイムは10分51秒39でした。
![IMG_6946[1].PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2301724/bc98d733-d9ce-1c82-d2bc-74e8756fa8a8.png)

ここで自分はどれくらいのスピードで走っているのかをプログラムで求めてみました。
それがこちらです。
![スクリーンショット (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2301724/baac7ecb-d74e-6f1f-b18c-76f05d95b75d.png)

自分は時速16.14kmと16.59kmでした。

#検証結果
バラードを流した時とロックを流した時では予想通りロックを流したほうが良いタイムで走れました。
皆様も運動不足の解消にロックを流しながら走ってみてはどうでしょうか。
ただテンション上がって最初から飛ばさないように気を付けないといけないかもしれません。
SPAとSSRの違いについて（備忘録）

## 概要
ポートフォリオでアプリを制作している中でSPAとSSRの違いについて学習したので備忘録として記載しておきます。


## SPAとSSRの違い
簡単に言うと２つの主な違いはレンダリング方法が異なるということです。
それぞれの特徴は以下の通りです。

## SPA
SPAはSingle Page Applicationの略称です。
クライアント側でレンダリングを実行するので、CSR（Client Side Rendring）とも呼ばれます。
##### 仕組み
1. ホスティングサーバーにリクエストを送り、HTML、CSS、JavaScriptファイルが返却されます。
1. 受け取ったファイル内の各データを取得するためにJavaScirptがAPIを叩きAPIサーバーからデータを取得します。
1. APIから返却されたデータをもとにクライアント側で初期レンダリングされ、ブラウザが表示されます。

##### メリット
- ページ遷移の際にサーバー側へ問い合わせをする必要がないため、__各ページの描画が早い__。

##### デメリット
- クライアント側でレンダリングを行うため、__初期描画に時間がかかる__。

## SSR
SSRはServer Side Renderingの略称です。
サーバー側でレンダリングを行います。
##### 仕組み
1. ホスティングサーバーが最初の一度だけ、APIサーバーにリクエストを送りHTMLファイル内のデータを取得します。
1. データを取得したあとホスティングサーバー側で先にレンダリングが行われます。
1. ホスティングサーバーからレンダリング済みのファイルが返却され、ブラウザが表示されます。

※ *初期レンダリング後はSPAと同様にクライアント側からAPIサーバーのデータを取得する。*

##### メリット
- SPAのメリットに加えて、サーバー側でレンダリングが行われるため__初期描画が早い__。

##### デメリット
- Node.jsを実行できる環境が必要。

## 参考文献
[SPA, SSR, SSGの違いについて図解でまとめてみた](https://shimablogs.com/spa-ssr-ssg-difference)
アニメフィルターをかけるなら、iOSでAIパワーをつかえる

#iPhoneでCGキャラ風アニメフィルターをつかう方法

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/4ea01ccc-be50-0e9d-15c5-d0edc64211cb.png", width=300><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/35c4beca-e23c-4f64-0e34-1569b1240466.png", width=300>

短いコードでAIのアニメフィルターをつかう方法です。

#アニメフィルターを使ってみたい

写真をアニメ風に変換するフィルターをたまに見かけるけれど、あれってどうやっているのだろう。

###AIの画風変換がつかえそうだけど、AIを使うのって難しいのでは？

写真をアニメ風のスタイルに変換してくれるAIがあるらしい。
しかし、AIってそんな簡単につかえるのだろうか？

#CoreMLを使えばかんたん

AppleのCoreMLというAIフレームワークを使えば、簡単にAIを使える。

#具体的手順

####1. [CoreML-Models](https://github.com/john-rocky/CoreML-Models)のGoogleドライブリンクからAnimeGAN2Face_Paint_512​​_v2のCoreMLモデルをダウンロード。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/69ab09c1-9c5d-aeb1-7c96-a00fb9e30309.png", width=400>

https://github.com/john-rocky/CoreML-Models

####2. ダウンロードしたモデルをXcodeプロジェクトにドラッグ&ドロップ。

####3. Swiftでモデルを実行

```swift
guard let model = try? VNCoreMLModel(for: animegan2face_paint_512_v2(configuration: MLModelConfiguration()).model) else {fatalError("model initialization failed")}
let coreMLRequest = VNCoreMLRequest(model: model)
let handler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer, options: [:])
try? handler.perform([coreMLRequest])
guard let result = coreMLRequest.results?.first as? VNPixelBufferObservation else { return }
let resultCIImage = CIImage(cvPixelBuffer: result.pixelBuffer)
let resultUIImage = UIImage(ciImage: resultCIImage)
```

🐣
****
フリーランスエンジニアです。
お仕事のご相談こちらまで
簡単な開発内容をお書き添えの上、お気軽にご連絡ください。
rockyshikoku@gmail.com

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

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)