OmniAICreator/Qiita-1.07M huggingface dataset:
Jupyter Notebookのcellにxtermを操作する


[colab-xterm](https://github.com/InfuseAI/colab-xterm)はNotebookのCellにxtermを操作することができるのツールです

事例のスクリーンショット

<iframe width="560" height="315" src="https://www.youtube.com/embed/lPjQWYw_vE8" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
---



まず[ColabのNotebook](https://colab.research.google.com/github/infuseai/colab-xterm/blob/main/demo.ipynb)のCellを実行してcolab-xtermを実装する

```bash
!pip install git+https://github.com/popcornylu/colab-xterm
%load_ext colabxterm
```

次のCellを実行してxtermを開始する

```
%xterm
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1623438/9c6b7fe0-8ff7-54d5-8fc4-99564ddfbacb.png)

お楽しみ


https://github.com/InfuseAI/colab-xterm

https://colab.research.google.com/github/infuseai/colab-xterm/blob/main/demo.ipynb
リモートデスクトップ接続中のみスリープを無期限に設定する。

#節電のためにリモートデスクトップ中だけスリープなしにしたい

##まず、タスクスケジューラでタスクを追加します。
![remote1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128851/593db4b6-8e06-b1c2-3cad-77d74a575230.png)

接続時、RemoteOnを実行。切断時、RemoteOffを実行。

##スリープ設定の命令を定義したバッチファイルを用意します。
参考：

https://forgetmenots.doorblog.jp/archives/53337664.html

```Batch:RemoteOn.bat
powercfg /x standby-timeout-ac 0
```

```Batch:RemoteOff.bat
powercfg /change standby-timeout-ac 20
```

この例では、リモート切断後、20分後にスリープになります。


~~powercfgは管理者権限で実行します。~~
管理者権限がなくても、実行できるみたいです。

![remote3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128851/9b9d8f0e-ea41-495e-bd5b-2240ef966a0c.png)

トリガーの設定で「ユーザーセッションへの接続時」、「ユーザーセッションからの切断時」というのがあるので、RemoteOn、RemoteOffにそれぞれ設定します。

「操作」タブの「新規」ボタンで「プログラムの開始」で先程のスクリプト（RemoteOn.bat、RemoteOff.bat）を指定します。

あと、タスクスケジューラの履歴を有効化しておくと、便利ですね。

なんか、もっとスマートな方法ないですかねぇ。
[Android]第二回Contextを掘り下げるの会

#はじめに
前回は、ApplicationContextとActivityContextの違いについて掘り下げたので、今回はそもそもContextは何をしているのか？について掘り下げたいと思います。

https://qiita.com/reo-androider/items/5cd82d02bd8de1ff14cc

#ドキュメントより

>Interface to global information about an application environment.

ドキュメント先輩のお言葉。
グローバル情報へのインターフェース的な意味があります。
ActivityもApplicationもContextを継承しているので、何となくわかったような気がする。

#何をしているのか？
ApplicationContextとActivityContexgの二種類に分けてみていきます。

###ApplicationContext

- Resourceへのアクセス
- Serviceを開始する
- Serviceをバインドする
- ブロードキャストを送信する
- ブロードキャストレシーバーを受信する

###ActivityContext
- Resourceへのアクセス
- Serviceを開始する
- Servieをバインドする
- ダイアログを表示させる
- Activityを開始する
- Fragmantを展開する

ここでいうリソースとは、画像や文字リソース、レイアウトファイルなどの静的コンテンツです。
Androidでは、これらを独立して保持する必要があります。



#おわりに
いかがだったでしょうか。
あまり関わり過ぎると、沼にハマるのでこれくらいにしてやっぞ。

#参考
https://www.geeksforgeeks.org/what-is-context-in-android/?ref=lbp
結局NULL合体演算子（??）はいつ使えばよいのか


# はじめに

PHP７系から追加されたnull合体演算子（??）とPHP5.3系から使えるエルビス演算子（?:）
これらがよくごっちゃになってしまうので、この機会にしっかり使い分けを覚えていこうと思います。


## エルビス演算子
まずはエルビス演算子（?:）から。

エルビスプレスリーに似ていることから命名されたらしいです。
演算子界の**キング・オブ・ロックンロール**ですね。

![エルビス.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694053/f38d3e3e-0446-1317-22e5-70cb2e6f5ceb.png)

エルビス演算子を使うと
三項演算子でこのように書いていたところを
`$a ? $a : $b;`

こう書くことができます。
`$a ?: $b;`

三項演算子の第二項が省略できるなんて、確かにこれはロックです。


### 具体例
それでは具体的な例を書いてみましょう。

 ```
$name = 'カバオ';
echo '名前: '. $name ?: 'うさこ';
```

この場合は **名前: カバオ** と表示されますが、


変数をブランクで定義すると

```
$name = '' ;
echo '名前: '. $name ?: 'うさこ';
```

この場合は **名前: うさこ** になりました。


PHPでfalse判定されるものでやってみると以下のような結果になりました。

|  第一項の値  |  例  |  評価された項  |
| ---- | ---- |---- |
|  ''  |  $name = '';  |  第2項  |
|  null  |  $name = null;  |  第2項  |
|  未定義の変数  |    |  error  |
|  空配列  |  $name = [];  |  error  |
|  0  |  $name = 0;  |  第2項  |
|  '0'  |  $name = '0';  |  第2項  |
|  false  |  $name = false;  |  第2項  |
|  セットされていない変数  |  $name;  |  error  |


未定義・空配列・セットされていない変数以外は、基本的に、第二項が評価されることがわかります。


## NULL合体演算子

では本題のNULL合体演算子（??）を見ていきましょう。
こちらは残念ながら、特に面白いエピソードはありません。

エルビス演算子と違って、nullじゃなければ第一項に落ちてきます。

### 具体例

三項演算子で書くとこういうことになります。
`!is_null($a) ? $a : $b`

これがNULL合体演算子だとこのように書けてしまいます。
`$a ?? $b;`


では先ほどと同様にやってみるとどうなるでしょうか。

```
$name = 'カバオ';
echo '名前: '. $name ?? 'うさこ';
```

この場合は **名前: カバオ** と表示されますが、

```
$name = '' ;
echo '名前: '. $name ?? 'うさこ';
```

この場合は**名前:　**になってしまいました。 
うさこはいずこへ

**nullかどうかをチェックするため、空文字列ならnullでないと評価され、そのものが表示されてしまう**んですね。

なのでnullを定義してあげると

```
$name = null;
echo '名前: '. $name ?? 'うさこ';
```

 **名前：うさこ** になりました。
うさこおかえり

先ほど同様にPHPでfalse判定されるものでやってみるとこうなります。

|  第一項の値  |  例  |  評価された項  |
| ---- | ---- |---- |
|  ''  |  $name = '';  |  第１項  |
|  null  |  $name = null;  |  第２項  |
|  未定義の変数  |    |  第２項  |
|  空配列  |  $name = [];  |  第１項  |
|  0  |  $name = 0;  |  第１項  |
|  '0'  |  $name = '0';  |  第１項  |
|  false  |  $name = false;  |  第１項  |
|  セットされていない変数  |  $name;  |  第１項  |

nullと未定義変数以外は全て第一項に落ちてきました。

## 結局いつ使うのか？

NULL合体演算子結局いつ使えるのでしょうか。
ここでは、使える２パターンを紹介して終わります。

### ① isset地獄から抜けられる
NULL合体演算子の良いところは第一項が存在しない変数でもnoticeが発生しないところ。

```
if (isset($_POST['action'])) {
    $action = $_POST['action'];
} else {
    $action = 'default';
}
```

こんなときにissetしなくていいので便利です。

↓NULL合体演算子を使うとこんなにスッキリ。
`$action = $_POST['action'] ?? 'default';`


### ② 複数の演算子をつなげて使用できる

```
$a = null;
$b = null;
$c = 0;
$result = $a ?? $b ?? $c;
echo $result;  // 0
```

AがnullであればBを代入、さらにBがnullであればCを代入する」ということができます。


コードがすっきりと書けるのはいいですが、
使いようによっては可読性が損なわれてしまうので、場面で使い分けたいと思います。
deviseで二つのアカウントでのログインをしているときのヘッダーの切り替え

## 初めに
この記事では、deviseでadminとuserの二画面を構成し、二つのアカウントで同時にログインをした際に、どのようにヘッダーの切り替えをすることができるのかについて書いていきたいと思います。

先に解決方法を知りたい方は[こちらから](#具体的な解決方法)

## 前提
ruby 2.6.9
rails 5.2.5(多分ここは6系でも大丈夫です）
devise(userとadminの二画面構成 & namespaceでadminのviewは全て/adminがついている)

## 解決したい問題
現在の状態は、application.html.erbでheaderを記述しておりheaderが呼び出される状態になっている。admin側とuser側でheaderのメニューを条件分岐を使用して切り替えている。
userでログインを行い、adminでもログインを行なっている際に、admin側の管理者画面ではない画面を開いた時にもheaderのメニューがuserのheaderに切り替わらない。
もう少し簡単に説明すると、adminの画面、つまり/adminから始める画面では正常にadminのheaderのメニューが表示されるが、userの画面、/から始まる画面ではuser側のheaderのメニューが表示されずadmin側のheaderのメニューが表示されている状態になってしまっている。

```
## application.html.erb
if admin_signed_in? 
  // adminログイン状態の際に、表示したいheaderのメニューを記載
elsif user_signed_in?
  // userログイン状態の際に、表示したいheaderのメニューを記載
else
  // adminでもuserでもログインしていない時に表示するheaderのメニューを記載
end
```

## 原因
原因としては簡単で、if分は上から順番に条件を実行し、trueが返されたものを実行するため今回adminとuserの二つでログインをしていても、初めにadmin_signed_in?でtrueが返されてしまい、user_signed_in?は実行すらされないことが原因となっている。

## 解決方法
解決方法としては、全部で三つが挙げられるかなと思います。今回この記事では2つのアカウントでのログインを許容する一番楽な解決方法にフォーカスして紹介していきたいと考えております。

#### 2つのアカウントでのログインを許容する解決方法

1. 全てのadmin側とuser側のviewに部分テンプレートでheaderを呼び出す（めっちゃめんどくさい）
1. urlのpathを取得し、pathごとにurlを判別する方法

#### ログインしているアカウントは常に一つ
1. userかadminにログインがかかる際に、deviseのreset_sessionを使用してログインしているデータを強制的にログアウトさせる方法（多分reset_sessionを使わずにもっと賢い方法があるはず）

## 具体的な解決方法
> urlのpathを取得し、pathごとにurlを判別する方法

今回この記事ではpathからadminの画面なのかuserの画面なのかを判断して画面ごとに適切なheaderを返すような仕様に変更してきたいと思います。

まず、現在のURLのpathを取得するためにrequestというものを使用します。
requestについては[こちら](https://railsdoc.com/page/request)を参照してください。

今回は、URLの中に/adminが含まれていればadminのheaderを返して含まれていなければuserのheaderのメニューを返す仕様にしていきます。今回はrequestの中のrequest.fullpathを使用して現在いる画面のpathを取得していきます。そして、その受け取ったpathの中に/adminが含まれているか文字列の検索をかけるのでinclude?というメソッドを使用し、/adminが含まれていればtrueを返し、含まれていなければfalseを返すように設定をします。

```
## 実装例

if request.fullpath.include? "/admin"
  //admin側のheaderを返す
else
  // user側のheaderを返す
end
```

上記で/adminが含まれているか、条件分岐をかけることができたのであとはこの内容をapplication.htmlに記述してあげれば一件落着になります。


```
if admin_signed_in? 
  if request.fullpath.include? "/admin"
    //admin側のheaderを返す
  else
    // user側のheaderを返す
  end
elsif user_signed_in?
  // userログイン状態の際に、表示したいheaderのメニューを記載
else
  // adminでもuserでもログインしていない時に表示するheaderのメニューを記載
end
```

## 最後に
これで、adminとuserの両方のアカウントでログインをしていても適切なheaderが返される仕様にすることができました。解決方法のところで紹介した一つのアカウントのログインのみを許容するという仕様も良いのですが、私はいちいちログインし直すのがめんどくさいので、私のようなめんどくさがり屋におすすめな実装方法になるかなと思います。devise最高〜〜〜
warning : LF will be replaced by CRF in エラーとの出会い

###　はじめに

>**💡** 今年から未経験からエンジニアとしてシャバにでて、初めての案件の際に出会ったgitのエラーと対峙したときの備忘録。

### 環境
- windows


### 現象
リモートブランチからローカルに新しくブランチを作り、それをリモートにプッシュする段階でステージングをしようとするとエラーがいっぱい。

```
warning: LF will be replaced by CRLF in ~~ 
The file will have its original line endings in your working directory
```

### 何が起こっているのか
gitのインストールの時に、改行コードに関しての自動変換を有効に設定してしまっていたっぽい。

LF改行コードをCRLFに自動変換しようといている。

### LF vs CR vs CRLF

|改行コード|説明|改行の向き|OS|
|-|-|-|-|
|LF|**Line Feed**<br>カーソルを新しい行に移動すること。|↓|Linux, macOSなど|
|CR|**Carriage Return**<br>カーソルを左端の位置に戻すこと。|←|macOS|
|CRLF|**CRとLFを足した**もの。|↵|Windows|



### 解決方法
`git config --global core.autoCRLF false`
というコマンドで
gitの設定情報をユーザー全体に上書き適用させることでエラー解消！

### 最後に
慣れないWindowsを触っての初めてのエラーデビューでした。
git周りはが手意識があるので絶対克服したい。
新参者につきご指導お待ちしてます。



### 参考
[改行コードの違い「CR」と「LF」と「CRLF」]
([https://vba-create.jp/vba-standard-cr-lf-crlf/])

[git add .したらwarning: LF will be replaced by CRLF inが出まくったのは改行コードを自動変換していたから](https://normalblog.net/system/lf_replaced_crlf/)
メンテナンス画面の表示について考えてみた

メンテナンス画面ってどう出したらいいんだろうと思っていろいろ調べました。

使用頻度は高くないですが、定期的に大規模なリリースをしたりするときにはやっぱり合ったほうがいいなと思います。
またトラブル発生時も対応中であることが伝えられるのでユーザーの不安もある程度解消できますね。

簡単そうに見えて意外といろいろな選択肢があるんだなあと思ったので、調べたことをつらつら書いてゆきます。
弊社はReact, Next.jsベースのWebアプリなのでその場合のパターンが主になります。

## フロントベース（ReactまたはNext.js前提）

### React + CloudFront + S3 + WAF

クラウドフロントにWAFをアタッチする方法です。
WAFからのカスタムエラーレスポンスによってCloudFrontが別のS3バケットからメンテナンスページを取得して返します。

![スクリーンショット 2022-02-02 11.47.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386799/d7c48002-8293-9373-e3be-8d68866063f5.png)


- WAFのアタッチのみで適用でき運用が楽
- フロントエンドの工数がかからない
- サーバーサイドの工数がかからない

### Next.js + Vercel
Next.jsをVercelに乗せた場合です。Vercelはメンテナンスモードをサポートしていないのでそれっぽく自分で実装するしかありません。

1. メンテナンスページをソース内に作成します。
1. 環境変数にNEXT_MAINT_MODEなどの変数をセットし、booleanなどセットしておきます。
1. その値によって分岐処理を書き、メンテナンスページに遷移させる処理を書きます。
1. メンテナンスモードにするときは、Vercel上で環境変数の値を書き換えて再デプロイします。

運用の手間がそこそこかかるのと、開発者がメンテナンス中に本番環境の画面を確認することができないのがネックですね。

## APIベース(ALBを使用している前提)
### ALB + ECS(orEC2)
ALBのリスナルールと固定レスポンス機能を使って503を返す方法です。
メンテナンスモードにする際はリスナルールの優先順位を入れ替えるだけです。

![スクリーンショット 2022-02-02 11.47.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386799/7a96ab23-5e12-2296-d5b3-31a3ef778c77.png)

- ドメインごとにルールを決められる
- 切り替えがやや手間

### ALB + WAF + ECS(orEC2)
ALBにWAFをアタッチするパターンで、503を返すのはWAFのお仕事になります。

![スクリーンショット 2022-02-02 11.47.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386799/85118c9c-b5eb-0e3b-6580-61eb3b3c0e8e.png)

- ドメインごとにルールを決められる
- 特定のIPを許可できる
- WAFのアタッチのみで適用でき運用が楽
- 複数プラットフォーム共用のAPIである場合はWAFのみの設定で済むため管理が楽

## 感想
全サービスが共通のAPIサーバ使っている場合にはALBの固定レスポンスかWAFアタッチが楽だなあと思っています。
リクエスト元のホストを絞ればサービスを限定することができるし、IPホワイトリストを設定すれば開発者はメンテ中も画面を覗くことができるし、ということでおそらく実装するとしたらAPIサービス側でやることになりそうです。

それぞれ長所短所ありますが非常に勉強になりました。

## 参考

https://dev.classmethod.jp/articles/alb-fixed-response/

https://tech-blog.yayoi-kk.co.jp/entry/2019/07/04/110000
レスポンシブな動画カルーセルをjQueryプラグイン「slick.js」を使って実装

## レスポンシブな動画カルーセルの実現
ワードプレスの改修案件が弊社に入り、単品のYouTube動画を掲載していた部分で、複数動画を掲載するうえで動画カルーセルを実現したいという要望があった。
他社が作成したコードに手を入れて、最小限の変更で実現するため、生のhtml、css、JQueryを使って対応することになった。
slick.jsを使った記事が出てきたが、パッと用途にそのまま合うものがなかったので、まとめることにした。

### 完成イメージ

![動画カルーセルイメージ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489992/b2d63f8d-463b-b05d-94b2-7d37c04080e1.png)


### slick.jsを導入する
既存もcdn経由だったので、手っ取り早く対応するため、同じくcdnからとってくることにした。

#### JavaScript

```
<script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.9.0/slick.min.js"></script>
```

#### CSS

```
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.9.0/slick.css"/>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.9.0/slick-theme.css">
```

### click.jsを要素に適用する
今回は、`.slide`というclassに適用させる。
動画は１枚ずつ表示して、１枚ずつスクロールして表示するようにする。
下部に表示される枚数の分かるドットを表示、次や前に進む左右の矢印ボタンも表示する。
自動スライドはオフとする。

```
<script type="text/javascript">
  $('.slide').slick({
    slidesToShow: 1,
    slidesToScroll: 1,
    autoplay: false,
    dots: true,
    accessibility: true,
    arrows: true,
    swipe: true,
    swipeToSlide: true
  });

  $('.slide').bind('touchstart', function() {
    return true;
  });
</script>
```

### HTMLとCSSを用意する・iframeのYouTube動画埋め込みを使う
今回は、iframeのYouTube埋め込みを使ってカルーセルをつくるパターンの紹介とする。

#### HTML

```
<div class="slide-wrapper">
  <div class="slide">
    <div class="slide-item"><iframe width="560" height="315" src="your youtube url" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>
    <div class="slide-item"><iframe width="560" height="315" src="your youtube url" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>
    <div class="slide-item"><iframe width="560" height="315" src="your youtube url" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>
  </div>
</div>
```

#### CSS

```
/* 動画表示領域（表示サイズ）の設定 */
.slide-wrapper {
  width: 100%;
  max-width: 560px;
  margin: 0 auto
}

/* レスポンシブ対応 */
.slide-item {
  position: relative;
  width: 100%;
  padding-top: 56.25%;
}

.slide-item iframe {
  position: absolute;
  top:   0;
  right: 0;
  width: 100%;
  height: 100%;
}

/* 背景が白の場合に表示できるように黒文字としている */
.slick-next:before {
  content: '→';
  color: black;
}

.slick-prev:before {
  content: '←';
  color: black;
}
```

## まとめ
以上、
生のHTML、CSSを使い、Jqueryプラグインの「slick.js」を用いて、レスポンシブ対応の１枚ずつ表示する動画カルーセルを作成する流れでした。
動画を用いたカルーセル／スライダーが必要になり、スパッと実装したい時の参考になれば幸いです。
[py2rb] json.dump json.load

# はじめに
移植やってます。
( from python 3.7 to ruby 2.7 )
# json (Python)
```python
import json

c = {'index': ['a', 'b', 'c']}
path = './test.json'
with open(path, 'w') as fp:
    json.dump(c, fp)
with open(path, 'r') as fp:
    o = json.load(fp, object_hook=dict)
    print(o)

# output
{'index': ['a', 'b', 'c']}
```
https://docs.python.org/ja/3.7/library/json.html#json.dump
# どうすRuby
```ruby
require 'json'

c = {'index' => ['a', 'b', 'c']}
path = './test.json'
File.open(path, 'w') do |fp|
    JSON.dump(c, fp)
end
File.open(path, 'r') do |fp|
  o = JSON.load(fp)
  print(o)
end

# output
{"index"=>["a", "b", "c"]}

#test.json
{"index":["a","b","c"]}
```
https://docs.ruby-lang.org/ja/latest/class/JSON.html

`json`で`=>`が`:`に変換されているのが興味深いです。
# メモ
+ Python の json を学習した
+ 百里を行く者は九十里を半ばとす
既存サイトをSSL化した後にやること

##やることは２つ
###1.　httpにアクセスがあった時、httpsに繋がる（リダイレクト）するように設定する

以下のコードを.htaccessの一番上に書いてアップロード


```
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTPS} !=on [NC]
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>
```

<br>


###2.すべてのページにカノ二カルタグを設定する


```html:index.html
<link rel="kanonical" href="https://example.jp">

```

:::note info
カノ二カルタグとはGoogleがサイトをインデックスして評価する際、httpsのページとhttpのページを同一ページとして評価してもらえるようにするもの
:::
RDS(Aurora)のMySQLパラメータグループのとりあえず設定

毎回忘れてしまうのでメモ代わりの記事。
対象はMySQL8.0系のDBパラメータグループ(AuroraだとDBクラスターパラメータグループ)です。

| パラメータ名 | 値 |
|:-|:-|
| time_zone  | Asia/Tokyo  |
| slow_query_log  | 1  |
| long_query_time  | お好みの秒数  |
| character_set_client  | utf8mb4  |
| character_set_connection  | utf8mb4  |
| character_set_database  | utf8mb4  |
| character_set_results  | utf8mb4  |
| character_set_server  | utf8mb4  |
| skip-character-set-client-handshake  | 1  |

照合順序(collation)はお好きな順序で。
こんな感じでしょうか。
他にもあれば教えてください〜

https://aws.amazon.com/jp/blogs/news/best-practices-for-configuring-parameters-for-amazon-rds-for-mysql-part-3-parameters-related-to-security-operational-manageability-and-connectivity-timeout/
ReactNativeで作ったアプリをexpoを使って公開する方法

# この記事について
ReactNativeで作成したアプリをexpoを利用してアプリを公開する手順についてまとめた。
アプリの審査の一歩手前までの手順書になっている。

この記事はUdemy講座で説明されていた方法をまとめたもので、
自分ではまだ試してはいない。
自分で試して差異があれば、更新する。

https://www.udemy.com/course/react-native-first-step/

# 結論：やることは３つ

1. コードをbuildする
1. 各ストアにアプリを新規登録する
1. buildしたファイルを各ストアにアップロードする

動画見てる限りはとても簡単だった。

# 公開の前にプロジェクトメンバーでアプリを共有する方法

ターミナルで、

```
expo publish
```
publishが終わるとURLが表示され、
それにみんなでアクセスするとexpo client アプリで共有できる。

Androidはこれだけでいいが、iphoneの場合は少し面倒。
## iphoneの場合
expo publishしたときのexpoアカウントをメンバーで共有しておく。
expo client でみんな同じアカウントでログインすればみんなでアプリを共有できる。


# AppleStoreでの公開方法
## app.json設定
アプリ名やバージョン、ios bundleIdentifier、タブレットをサポートするかどうかなどの情報を入れておく。


## iosのbuild
ターミナルで、

```
expo build:ios --release-channel production
```

とすると対話形式で色々聞かれる。

1. apple ID、passを聞かれる
1. どのチームか聞かれる　→　適当なものを選択
1. credential管理どうする？　→　expoに全て任せるを選択すると簡単
1. 証明書どうする？　→　expoに全て任せるを選択すると簡単
1. keyをexpoに任せる？　→　expoに全て任せるを選択すると簡単

これらは初回だけ
本来はappleのサイトでやるところをexpoが代わりにやってくれている

ビルドには時間かかる。
ビルドが終わるとURLが表示される。
URLに飛ぶと、buildされたファイルがダウンロードされる。（ipaファイル）

## AppleStoreにアプリを登録する
アプリ名やboudleIdがある。

## 手動でapplestoreにipaファイルをアップロードする
Transporterというアプリを使うので事前にインストールしておく。
transporterにipaファイルをアップロードする。
storeを見るとアップロードされるか確認できる。
storeの作業中のプロジェクトにアップロードされたipaファイルを選択して、
申請するためのスクショやアプリの説明などを記述したら終わり。

# androidの公開方法
## app.jsonに必要な情報を入れる
androidは-が使えないので要注意

## build
ターミナルで、

```
expo build:android --release-channel production
```

expoに任せるか聞かれるので任せちゃう。

buildが終わると、URLが表示されるので、そのURLにアクセスしてbuildされたファイルダウンロードする。（ipkファイル）

## google play consoleにアップロード
まずはconsoleでアプリを作成でタイトルなどを入れる。
アプリのリリース→製品版→リリースの作成と進んで、表示されたページにダウンロードしたipkファイルをアップロードする。

# 小技
## release-channel
社内用で共有するアプリと世の中に公開するアプリをごっちゃにならないようにchannelが別れている。
stagingもあるそうだ。

### 身内でアプリを共有する

```
expo publish
```

### 世の中にアプリを公開する

```
expo publish　--release-channel production
```
```
expo build　--release-channel production
```
とchannelを指定する。


# expoとStoreの関係
アプリの審査が通ってstoreでアプリが公開されると、
ユーザーはアプリをapple storeからインストールできるようになる。
ユーザーがアプリを起動するたびに
expoサーバーから最新のJSバンドルを持ってくるので、
最新のコードが反映されたものをユーザーは使うことができる。
→これがAppleの再審査がいらない理由かな
頭痛ーる開発チームの勉強会でBitriseについてLTした話

## はじめに📘
私が社内で開発担当しているプロジェクト[**『頭痛ーる』**](https://apps.apple.com/jp/app/%E9%A0%AD%E7%97%9B%E3%83%BC%E3%82%8B/id602991338)の開発チームでおこなっている勉強会の中で**Bitrise**についてLTをしました。
頭痛ーる開発チームではどんな勉強会をしているのかということ、またエンジニアとして初めてLTをした感想を記事にしてみました✏️

よかったら最後まで読んでください！

## 頭痛ーる開発チームではこんなことをしています📗
現在、頭痛ーる開発チームでは週に一度オンラインで2時間の勉強会を開催しています。技術力の向上とチームのコミュニケーションの場として運用しています。

勉強会といってもみんなで同じことを学ぶということはしておらず、各々キャッチアップする技術を宣言して学習内容がカタチになるまで取り組むカジュアルな勉強会です。

私自身、『好きなことをやっているときのパフォーマンスが一番高く、吸収量が多い』と考えている人なので、とても貴重な技術力向上のお時間です。

ただし、学習内容をカタチにするということ、社内LTや記事を書くことでもいいので**『学びを発信する』**ということはルールとして存在しており、ただ好きなことをする会というわけではありません（笑）

## キャッチアップしたこと📕
今回、モバイルアプリ特化のCI/CDサービスBitriseにキャッチアップしました。これまで個人ではCI/CDにあまり触れてこず、いつもキャッチアップを後回しにしていました（笑）
ですが、プライベートで参加しているコミュニティの中でもBitrise体験会というものが開催されており、その体験会をきっかけにキャッチアップすることにしました。

参考にしたのはBitriseの公式ドキュメントとiOSアプリ自動テストの教科書です。

https://devcenter.bitrise.io/

https://gihyo.jp/book/2019/978-4-297-10629-4

CI/CD環境は個人でAppStoreにリリースしていたアプリに構築することにし、Bitriseで構築した環境からApp Store Connectへアプリをビルドするところまでを目標にしました。公式ドキュメントも、自動テストの教科書も両方優れており、途中エラーが発生して詰まりましたが、なんとかCI/CD環境の構築に成功しました。時間にすると15〜20時間いかないぐらいかな？🤔（多分）

## LTしてみた📙
App Store Connectへのビルドが成功した時点で学習内容がカタチになったので、社内でBitriseに関してLTをしてみました。

といってもエンジニアになってはじめてのLTだったので少し緊張...。

資料はCI/CDの基本から若干の詳細とBitriseについてまとめたスライドを作成しました。素朴なスライドですがもしよかったら見てください（笑）

https://drive.google.com/file/d/1HbcYe2QwUl6J7d26e4kH6SdJbCoZ-3a_/view?usp=sharing

資料を使って説明した後は画面共有でBitriseを触りながら体験会的な流れでLTを無事終えました。

## 発信は素晴らしい📘
今回、初めてLTをしてみて感じたのは**『発信は素晴らしい！！』**ということ。

LTのために資料を作成する中で、CI/CDの知識が整理され学習内容がブラッシュアップされたような気がします。また、CI/CDを知らない人を意識しながら資料を作成し、話すことで相手に物事を伝える力が高まった気がします。

あと、先輩エンジニアから言われたことで、「自分の学習範囲ではカバーできないことを他者のLTを聞くことで知るきっかけになる」と言われたときは、発信することで誰かの役に立つこと、若手エンジニアでも先輩エンジニアの力になれることを体感し、LTにチャレンジして本当に良かったと思えました😊

## おわりに📗
技術記事を書くことのハードルがそれほど高くなく、書けばどこかで誰かの役に立つ可能性があり、プラスの要素しかないことと同様に、LTをすることもプラスの要素しかないことを今回経験することができました。

今後はチーム内だけでなく、社内全体や、外部でのLTにもチャレンジしていきたいです！

ご覧いただきありがとうございました👋
【 Javaで書いたソースコードが動作するまでの流れ 】

最近Javaの学習を始めて、まずは`Javaのソースコードで指示した通りの動作`が行われるまでの流れを確認しています。
## ざっくりとした3つの流れ
1.まず、`ソースコード`を書きます。ソースコードが書いてあるファイルを`ソースファイル`と呼び、拡張子は`「.java」`です。
2.次に、そのソースファイルを`コンパイラ`というソフトウェアで`クラスファイル`に`コンパイル`します。クラスファイル内には`バイトコード`という`１と0が複雑にならんでいるもの`が詰まっていて、このファイルの拡張子は`「.class」`になります。
3.最後に、バイトコードを`マシンコード(機械語)`に変換します。変換には`インタプリタ`という内部に`JVM`というしくみをもったソフトウェアを用い、バイトコードを少しずつ読みながら翻訳をしして`CPU`に送って処理を実行します。

このようにして`Javaのソースコードで指示した通りの動作`は行われます。

## 各用語の解説
ソースファイルとは....ソースコードを書き込んだファイルのこと
ソースコードとは....人が読める状態のプログラムのこと
クラスファイルとは....バイトコードが詰まっているファイルのこと
バイトコードとは.....1と0が複雑に並んだコードのこと
マシンコードとは....CPUが解釈できるコード(機械語)
インタプリタとは...バイトコードの変換と実行を行なってくれるソフトウェア
JVM(Java Virtual Machine)....インタプリタ内のしくみ。マシンコードに翻訳しCPUに送信する

## まとめ
つまりJavaのソースコードを実行するためには、
■`ソースコード → バイトコード → マシンコード`
の順に変換していく必要があり、それには、
■`コンパイラやインタプリタ(JVM)`を用いる。
ということです。
任意のサイトのSSLサーバ証明書を取得する（新）

# 背景
定期的にSSL証明書の期限を確認して、切れそうだったら教えてくれるプログラムを作りたいと思って作った（3年前）

https://qiita.com/ShTair/items/b1971dc21d80b25733a3

↑これより、もっといい方法があるんじゃないか？と思ってILSpyを見てた。
だいぶいろいろわかってきたので、最新版を書こうと思った。

# コード
以前書いたコードでは、`HttpClient`の処理の途中で証明書だけ奪ってた。
`HttpClient`はかなり複雑なことをやっているんだけど、最終的には`SslStream`を使っているようなので、それを直接使う。

```c#
public static async Task<X509Certificate2?> GetCertificateAsync(string host, int port = 443)
{
    using var client = new TcpClient(host, port); //※1.1
    using var stream = client.GetStream();
    using var sslStream = new SslStream(stream, false, (_, _, _, _) => true); //※2
    await sslStream.AuthenticateAsClientAsync(host); //※1.2
    return sslStream.RemoteCertificate as X509Certificate2; //※3
}
```

※1: 接続先と認証で、ホスト名を2回使う。※1.2でホスト名が必要なのはなんでだろう？取得した証明書の確認の為か？（SSL SNIの解決のため、ということでした。サーバは複数の証明書を持つことが可能で、どのホスト名の証明書が必要か送らないとダメです。@jzkeyさんありがとうございます。）
※2: 証明書を検査する（ふりをする）コールバック`(_, _, _, _) => true`を設定しないといけない。これをやらないと、証明書にエラーがあったときに例外が発生する。今回はたとえエラーがあっても証明書自体を取得したいので、エラーは無視。
※3: 取得できる証明書の型は`X509Certificate`なんだけど、実体は`X509Certificate2`っぽいので変換。変換しなくてもいいかもしれないけどよくわかっていない。

取得した証明書は、**使い終わったらDisposeする必要がある。**
`sslStream.RemoteCertificate`で証明書を取得すると、`SslStream`の破棄時に証明書が一緒に破棄されなくなるっぽい。

↓`CancellationToken`でキャンセルできるようにしたバージョン

https://gist.github.com/ShTair/30187cec1510f227a0805ecd297c1cd9
shopify + お名前.com（お名前メール）でshopifyにドメインが接続できない

# 前提
- お名前.comで取得した独自ドメインを使う
 - example.com
- https://help.onamae.com/answer/14363
 - お名前メールを使っている
 - そのためネームサーバが**レンタルサーバー SDプラン、お名前メール向けネームサーバー**


# 問題
お名前.comコントロールパネルのDNSレコード設定より以下を登録してもshopify管理画面でドメインが接続できない。

| HOST            | TYPE  | VALUE               |
|:----------------|:------|:--------------------|
| example.com     | A     | 23.227.38.65        |
| www.example.com | CNAME | shops.myshopify.com |




# 結論
1. お名前.comコントロールパネルのグローバルメニュー
1. メニュー一覧
1. お名前メール
1. コントロールパネルにログイン
1. 独自ドメイン設定
1. 対象ドメインの「DNS設定」

と遷移し、**A/CNAME**をここに登録する。
**お名前.comのネームサーバ**ではなく、お名前メールのコントロールパネルから**お名前メールのネームサーバ**にDNSレコード登録する必要があった。
→ドメイン管理画面でレンタルサーバー SDプラン、お名前メールのネームサーバーを使うように設定しているので当然


# 参考
https://help.shopify.com/ja/manual/domains/managing-domains/secure-connections
https://help.shopify.com/ja/manual/domains/add-a-domain/connecting-domains


# 次の問題::送信元メールアドレスが通らない（※おそらく解決済み）
## 現象
**shopify管理画面→ストアの詳細→連絡先情報** で設定する送信元のメールアドレスの疎通確認ができず、
> お客様には、代わりにno-reply@shopify.comが表示される可能性があります。
と警告がでる。


## 対応とそれによって生じた問題
hoge._domainkey CNAME ***
fuga._domainkey CNAME ***
piyo._domainkey CNAME ***
mailervyn       CNAME ***
とDNSレコードに登録すれば良いと表示されるのだが、やはりというかお名前.comのネームサーバに登録しても無意味だったため、お名前メールのネームサーバに登録する必要があると思われる。
~~しかしお名前メールのネームサーバのDNSレコードにはCNAMEが登録できない模様。~~
~~一応同管理画面には~~

> ~~※CNAMEレコードの設定は、上記Aレコードからの変更ボタンから設定できます。~~

~~と記載があるが、登録できない。~~
23.6.26時点でCNAME登録できるようになっていた。


## 公式活用ガイドを見る
http://guide.onamae-server.com/sd/4_16_20_110_5/
こちらの手順を参考に**hoge._domainkey**をサブドメインとして登録を試みたが、

> エラーが発生しました。
> サブドメインに使用できる文字は、半角英数字、半角ハイフン（-）、ドットのみです。またドット
を連続する事はできません。

となり、登録できない。


## 結果
登録できず詰む。
ただしこれによる問題が**shopifyからお客様に送られるメールアドレスが任意のメールアドレスではなくno-reply@shopify.comになる**だけであれば致命的ではない。
しかし「このメールアドレスには返信できません」といった記載や、メールをスレッドで管理できない等の問題は残る。
ReactでQRコードを表示したいというお話

#はじめに

なんか最近ハードウェアとソフトウェア両方ともやってて雑食となりつつある今日この頃。
AWS資格、せめてCRFくらいは取りたいなぁと思いつつ最近はReactで色々やっております。

さて、今回はReact内でQRコードを表示しようとした際にちょっとした事があったので、折角なので新しい物を導入した雑感を記録していこうかと思います。

#開発環境
- AWS EC2 t2.microインスタンス
- Amazon Linux 2 ＋ Cloud9
- Node.js 16.11.1
- React 17.0.2

#事の発端
Webアプリケーションを作っていると、どうしても必要な物というのは色々出てくる。
その中で、2段階認証(俗に言うTOTP)が必要な段階になった。
あまり予算を使いたくない都合上SMSを使った認証は却下して、QRコードとAuthenticatorを利用した仕組みを導入しようとしました。
で、さー`qrcode.react`も導入したし、いざQRコードを表示！ってなった時にこんなエラーが出た訳です。

```
Warning: componentWillReceiveProps has been renamed, and is not recommended for use. See https://reactjs.org/link/unsafe-component-lifecycles for details.

* Move data fetching code or side effects to componentDidUpdate.
* If you're updating state whenever props change, refactor your code to use memoization techniques or move it to static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state
* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.

Please update the following components: QRCodeCanvas
```

ざっくり自己流に翻訳すると、
「えーマジー？componentWillReceivePropsー！？古ーい！componentWillReceivePropsが許されるのは、React17までよねー！キャハハハ！」
って事なわけで今は問題ないけど、将来的にアップデートされたらダメじゃんこれ、な状態です。
表面上は今作れておけば問題ないんだろうけど、将来的に何かあったら嫌だしなー、だったら解消させようかー、という若干の下心を下に解消策を探す旅に出ました。

#そして見つけた新しい子
とりあえず上記のエラーが発生するのはQRコードを表示する為のプログラムが古くて、旧式の関数使っているのがいけないんだよな？
と言う解釈のもと、まずは`qrcode.react`をアップデート。しかし結果は表示変わらず。
そうなると何か別の物を持ってくる必要があるよなー、と言う事でnpmで色々探していると`next-qrcode`と言う物を発見。見た感じ使い勝手はそこまで変わらなさそうなので、これを使ってみようと思った。
基本的な使い方はそれとなくReactのuseStateに似ている為、結構とっつきやすかったと言うのもある。

```
npm i next-qrcode
```
まずはインストールして、

```QR.js
import React from 'react';
import { useQRCode } from 'next-qrcode';

const QR = () => {
  const { Canvas } = useQRCode();
  return (
  <Canvas
    text={'https://qiita.com/AoiReia'} // QRコードで表示される内容。省略できません。
    options={{ // ここの要素は省略可能。ご利用は計画的に。
      type: 'image/webp', // 出力フォーマット。 pngかjpegかwebpから選べる
      quality: 0.95, // クオリティ。 0〜１で1に近い方が綺麗。
      level: 'M', // 補正レベル。 low(L)、medium（Ｍ）、quartile(Ｑ)、high(H)から選べる。
      margin: 3, // クワイエットゾーンの広さを決める。
      scale: 4, // ドット1個につき何px使うかの指標。
      width: 200, // 出力画像の幅の指定。(収まらなかったら無視する)
      color: { // RGBAで色を決める。
        dark: '#010599FF',
        light: '#FFBF60FF',
      },
    }}
  />
  );
}

export default QR;
```
と、かなりざっくり言えばこんな感じで記載をすればいい。
![SS124116.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1953155/0739c053-3e50-09b6-72e1-52fc6e17c248.png)
上記のコードを実際に動かすとこんな風になります。


ちなみにtext要素以外は省略可能だったり、

```.js
  const { Image } = useQRCode();
```
と表記すれればImage出力になったりもするらしい。(ただ、書いている本人には違いはよくわからない。)
詳しくは下記参考サイトにてご確認いただけますと幸いです。

#参考サイト
[React.jsでQRコード生成](https://qiita.com/daisukeoda/items/feac76f5e1b726696c47)
[next-qrcode](https://www.npmjs.com/package/next-qrcode)

#おわりに
色々作っていると必要になる物も多いけど、なんだかんだ探せば大量に出てくる世の中は非常に助かる。
先人の知恵とはよく言った物だが、使えるものはしっかり使わせてもらって、快適なプログラミングライフを送りたいなー、と思った今日この頃でした。
AI人材の育成方法、社内育成の鍵は新卒社員へのAI研修にあり

こんにちは。スキルアップAI編集部です。

<目次>
1.AI人材の採用は熾烈な争い
2.AI人材を社内で育成する方法

# 1.AI人材の採用は熾烈な争い
「[AI人材を簡単解説、AI人材に関する最新データや職種、必要なスキルとは](https://qiita.com/skillup_ai/items/706208f922f9c1409662)」で見たように、AI人材は2030年に12.4万人不足するとも試算されています。また、日本ではデータサイエンスやAIについて学べる大学がまだ多くないことから、政府の会議では新卒AI人材は毎年300人程度と試算※されています。AI人材の供給数の不足により、中途採用・新卒採用ともに企業による獲得競争は将来的により熾烈な争いになることが予想されます。
※[総合科学技術・イノベーション会議　第14回重要課題専門調査会資料6](https://www8.cao.go.jp/cstp/tyousakai/juyoukadai/14kai/siryo6.pdf)

また、優秀なAIエンジニアは海外を目指すケースが多いこと、グローバルな獲得競争になること、カルチャーフィットの問題や他の社員より給与が高額なことによる他部署からの孤立など、せっかく採用したAI人材が定着しない可能性もあります。

採用によってAI人材を獲得するためには、自社の状況にマッチするAI人材をピンポイントで探し出すとともに、魅力的な職場環境や給与を準備する必要があります。

<img width="400" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/889700/06011068-5a45-616d-cd66-7db36a052d85.jpeg">
AI・データ分析人材特化型採用支援サービス「[SkillUp AIgent](https://www.skillupai.com/aigent-business/)」

# 2.AI人材を社内で育成する方法
即効性は無いものの、着実に組織の力を上げる方法は人材育成です。社内育成の場合も、時間軸を意識して計画的に推進することが大切です。

**AI人材育成にかかる時間と手順**
期間としては3年程度の期間を要することが一般的であり、こうした時間軸で動くには、全社的にAI人材の育成、ひいてはDXに取り組み企業の競争力を高めることの重要性が認識されているということも前提として必要です。
次の表はビジネス成果に繋がる成功事例を創出するまでのAI人材育成計画のおおよそのマイルストーンを記載したものです。

![表1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/889700/0cdbdf1a-7f15-a481-b9c6-ee7fc2545a42.png)

**新入社員へのAI教育実施は社内人材育成の鍵となる**
ここで1つ非常に効果的な育成方法をご紹介します。それは新卒の新入社員にAI人材となるための研修を実施することです。
新卒入社世代はデジタルネイティブであり、先端技術の理解と活用方法・事例の理解などのキャッチアップが早い傾向にあります。また、配属前のため学習時間がまとめて取れる唯一にして最後のチャンスでもあります。予算取り、スケジュール調整などのカスタマイズが少なく、新入社員研修の一環として一括で安価に実施できることも後押しします。

![表2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/889700/cde6e24f-9215-a129-7921-51b8ad4b32bd.png)

新卒研修としてAI人材育成を実施することで、通常3年かかるところを1年短縮し、2年で実案件に取り組む体制を整備することも可能となります。

いずれにせよ、人材育成には時間がかかります。3年程度の時間軸で考え、早急に結果を求めないこと。これを短縮したい場合は、新卒社員をAI人材育成の対象とすることを検討しましょう。

さらに詳細を知りたい方は、「[DX時代の人材育成近道は新人AI研修](https://share.hsforms.com/1x8x9ARz4RDamTH7ok9YTAg2mtef)」をダウンロードしてご覧ください。

<img width="400" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/889700/9dc80210-a280-f032-22db-d0496b1d34cb.png">
自社のDX推進を加速する「[2022年度 新入社員向けDX研修](https://bit.ly/34b2g2z)」

# 25卒向け！AIエンジニアになるための長期インターンプログラム参加者募集中！
25卒学生向けに、AIの基礎を学びながら就活も一括サポートする無料カリキュラムを提供しています。
修了するとE資格の受験資格も獲得できるプログラムとなっています！

<img width="700" alt="長期インターン" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/889700/bfce4c26-1ebe-c54d-bacb-e804048a7a08.png">

**特長①AIエンジニアやデータサイエンティストの基礎が身に付く**
AIジェネラリスト基礎講座や機械学習のためのPython入門講座など、市場価値向上のための基礎を習得。

**特長②AI・データ分析領域の優良求人を紹介**
非公開求人や選考直結型インターンをご紹介し、早期内定の獲得をサポート。

**特長③長期インターンプログラム専用の学生コミュニティ参加可**
学生同士で就活情報をシェアしたり、学習を進めるうえでアドバイスをしあったりできるコミュニティに参加可能。

＞＞[長期インターン詳細](https://bit.ly/3pXW5JM)

☆☆☆
スキルアップAIのメールマガジンでは会社のお知らせや講座に関するお得な情報を配信しています。
配信を希望される方は[こちら](https://share.hsforms.com/1_XlReV-4Te-zcxCl9lhffA2mtef)

また、SNSでも様々なコンテンツをお届けしています。興味を持った方は是非チェックしてください♪
Twitterは[こちら](https://twitter.com/SkillupAi)
Facebookは[こちら](https://www.facebook.com/skillupai)
LinkedInは[こちら](https://www.linkedin.com/company/skillup-ai)
スキルアップAI公式YouTube AIビジネスチャンネルは[こちら](https://www.youtube.com/AIBusinessChannel)
アプリでよくみる円形のProgressView

#進行状況を円形で表示する方法です
![Feb-02-2022 11-35-07.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/68fde8d8-dd36-e40a-3554-caf4aac22c0c.gif)

#円形のプログレス・ビューを表示したい
棒状のProgressBarならUIKitにありますが、アプリなどでよくみる円形のProgressを表示したい。

#KDCircularProgressでかんたんに表示
便利なライブラリを使ってかんたんに表示します。

https://github.com/kaandedeoglu/KDCircularProgress

リポジトリからKDCircularProgress.swiftファイルをプロジェクトにドラッグ&ドロップします。

CircularProgressをセットアップします。

```swift
var progress = KDCircularProgress(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
progress.startAngle = -90
progress.progressThickness = 0.2
progress.trackThickness = 0.6
progress.clockwise = true
progress.gradientRotateSpeed = 2
progress.roundedCorners = false
progress.glowMode = .forward
progress.glowAmount = 0.9
progress.set(colors: UIColor.cyan ,UIColor.white, UIColor.magenta, UIColor.white, UIColor.orange)
progress.center = CGPoint(x: view.center.x, y: view.center.y + 25)
view.addSubview(progress)
```

アニメーションをスタートします。

```swift
progress.animate(toAngle: 360, duration: 5, completion: nil)
```

![Feb-02-2022 11-35-07.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/68fde8d8-dd36-e40a-3554-caf4aac22c0c.gif)

#GitHubを探そう

こういうライブラリっていっぱいあるので、好みのものを探してみましょう。

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

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

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
（小ネタ）IBM Cloud: IBM Cloud CLIを使わずにVSI for VPC(Windows)のための暗号化パスワードを復号する方法

(UIやコマンド結果を最新のものに更新しました）

# 1. はじめに

IBM CloudのVSI for VPCにおけるWindows環境のAdministratorのパスワードは、サーバー作成時に指定したSSH鍵（公開鍵）によって暗号化されているため、ログインする際にはまずパスワードを入手する必要があります。

パスワードを取得する方法は[IBM Cloud docs](https://cloud.ibm.com/docs/vpc?topic=vpc-vsi_is_connecting_windows)に記載されており、`ibmcloud is instance-initialization-values INSTANCE [--private-key (KEY | @KEY_FILE)] `を使うように指示があります。

```txt:ibmcloud is instance-initialization-valuesを使った実行例
$ ibmcloud is instance-initialization-values syasuda-win22-nonsec --private-key @.ssh/id_rsa
Getting instance initialization values for syasuda-win22-nonsec under account itz-cp-jpn as user xxx@xx.xxx.xxx...

Keys                 ID                                          Name          Fingerprint
                     r022-2d4b168f-5dc7-4170-8a52-e9036165eef1   key-syasuda   SHA256:xxxxxxxxxxxxxxxxx

Encrypted password   xxxxxxxxxxxxxxxxx
Encryption key CRN   xxxxxxxxxxxxxxxxx
Password             xxxxxxxxxxxxxxxxx
```

でも、ここにEncrypted Passwordがすぐコピペで使えるように記載があるのに・・・と思ったので、直接このEncrypted Passwordからパスワードを復号する方法を紹介します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/90cf3d40-dad9-9346-0579-fe95509e9bf9.png)


# 2. 復号方法

Encrypted Passwordは`=`で終わっているので、きっとBase64でEncodeされているのでしょう。というので、Base64でDecodeした後、opensslコマンドで秘密鍵を使って復号できました。

```txt:opensslを使った実行例
$ echo <Encrypted Password> | base64 -d | openssl rsautl -decrypt -inkey .ssh/id_rsa
xxxxxxxxxxxxxxxxx
```
自分用チートシート 


●●●●●Windowsサーバーで「tailf」コマンドを打ちたい！●●●●●

	Get-Content -Path <ファイルパス> -Wait -Tail <行数>　←この行数分ログが出る

●●●●●PowerShellでのログを残したい！●●●●●

	Start-Transcript <ファイル名> -append
	Stop-Transcript

●●●●●tarファイルの解凍●●●●●

	圧縮
	tar -cvf xxxx.tar directory
	解凍
	tar -xvf xxxx.tar

	圧縮
	tar -zcvf xxxx.tar.gz directory
	解凍
	tar -zxvf xxxx.tar.gz

●●●●●SELinuxの解除無効化●●●●●
	
	# vi /etc/selinux/config
	SELINUX=enforcing
	→disabledに変更
	→rebootで再起動必要！！

●●●●●vi（less） コマンド中で検索する（連続）●●●●●

	上から順番に検索する「/」
	下から検索を行う「?」
	順方向に次の検索結果へジャンプする「n」
	逆方向に前の検索結果へジャンプする「N」

●●●●●Windowsイベントログでのイベント作成コマンド●●●●●

	eventcreate /ID 999 /L application /SO hoge /T INFORMATION /D "Test"

●●●●●LinuxでPythonを抜ける●●●●●

	Ctrl＋D

●●●●●過去に実行したコマンドをすぐ再実行したい●●●●●

	history コマンドを実行
	!<番号> で過去のコマンドを実行できる！

●●●●●Windowsでの画面録画の方法●●●●●

	Windows＋Gで操作パネルを開く
	Windows＋Alt＋Rで録画開始

●●●●●AWSのCLIインストールとその後の動き●●●●●
	
	====
	curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
	unzip awscliv2.zip
	sudo ./aws/install
	====
	上記をまとめて実行。
WordPress/Contact From 7営業スパム撃退スクリプト

#初めに
私は仕事でWordPressを使用したホームページを作るのですが、最近AIや自動化を使ってホームページにお問い合わせが増えてきました。
内容を確認するとお問い合わせフォームに入力するのでは無く、直接送信APIに問い合わせを送っています。IPアドレスを確認すると外国のサーバーが多く、専用のサーバを設置しているのか？踏み台にされているのかは定かではありません。
メールの内容も、本当の営業メールや怪しいLPへのお誘い、英文など様々です。
この状態はあまり良い事ではないと思っていないので情報の把握と除去するIPリストを作成するスクリプトを作成したので公開します。

#コード
まず、下記コードを参考に設置してください。
但し、直接のアクセスは好ましくないのでフォルダ内への設置とアクセス制限をかける事をお勧めします。
※コードはWEB Rootへの設置を前提に記述しているので、必要な個所は訂正してください。

```PHP:spamcheck.php
date_default_timezone_set('Asia/Tokyo');
$msg = "------------------------------------------------------------"."\n";
$msg .= date("Y/m/d H:i:s")."\n";
$msg .= "HTTP_USER_AGENT:".$_SERVER["HTTP_USER_AGENT"]."\n";
$msg .= "REMOTE_ADDR:".$_SERVER["REMOTE_ADDR"]."\n";
$msg .= "REMOTE_HOSTNAME:".gethostbyaddr($_SERVER["REMOTE_ADDR"])."\n";
$msg .= "HTTP_REFERER:".$_SERVER["HTTP_REFERER"]."\n";
$msg .= "HTTP_X_REQUESTED_WITH:".$_SERVER["HTTP_X_REQUESTED_WITH"]."\n";
$msg .= "SCRIPT_FILENAME:".$_SERVER['SCRIPT_FILENAME']."\n";
$msg .= "REQUEST_METHOD:".$_SERVER["REQUEST_METHOD"]."\n";
$msg .= "REQUEST_URI:".$_SERVER["REQUEST_URI"]."\n";
$msg .= "SCRIPT_NAME:".$_SERVER["SCRIPT_NAME"]."\n";
$msg .= "QUERY_STRING:".$_SERVER["QUERY_STRING"]."\n";
$msg .= "PHP_SELF:".$_SERVER["PHP_SELF"]."\n";
$msg .= "_GET:".count($_GET)."\n";
foreach( $_GET as $k => $v ) {
	$msg .= $k.":".$v."\n";
}
$msg .= "_POST:".count($_POST)."\n";
foreach( $_POST as $k => $v ) {
	$msg .= $k.":".$v."\n";
}
$msg .= "_COOKIE:".count($_COOKIE)."\n";
foreach( $_COOKIE as $k => $v ) {
	$msg .= $k.":".$v."\n";
}

$log = true;
if( $_SERVER["REMOTE_ADDR"] == 'xxx.xxx.xxx.xx' ) {  /*出力したくないIP*/
	$check = false;
}
if( $log ) {
    //アクセスログを出力します。/以外に出力する場合は修正してください。
	$fnm = ABSPATH."./log_".date("Ymd").".txt";
	$h = fopen( $fnm, "a" );
	fwrite( $h, $msg );
	fclose( $h );	
}

//
if( $_POST['_wpcf7'] >= 0 && $_POST['check-robot'] == '1' ) {
    //怪しいIPアドレスを出力します。/以外に出力する場合は修正してください。
	$fnm = ABSPATH."./denyip.txt";
	if( !file_exists( $fnm ) ) {
		$h = fopen( $fnm, "a" );
		fclose( $h );	
	}
	$ip = $_SERVER["REMOTE_ADDR"];
	$content = file_get_contents( $fnm );
	if( !strpos( $content, $ip ) ) {
		$h = fopen( $fnm, "a" );
		fwrite( $h, "deny from ".$ip."\n" );
		fclose( $h );	
	}
}
```

アクセス時に上記コードを実行する為に、WordPressへ組み込みます。バージョンアップとかに影響しないようにしてください。今回はwp-config.phpへ組み込むようにしました。

```PHP:wp-config.php
require_once ABSPATH . "./spamcheck.php";
```

お問い合わせフォームにも下記の記述が必要です。
通常はチェックを付けて送信しましが、この場合はチェックを外して送信するようにしてください。

```:コンタクトフォーム
[acceptance check-robot default:on invert] チェックを外して送信します。 [/acceptance]
```

アクセスがあるとdenyip.txtにapacheのアクセス拒否の記述で出力されます。
内容を確認し、.htaccessに追記すると該当するIPからブロックする事ができます。

#最後に
個人的な意見で言えば、営業をかける事は普通の事なので悪い事ではないと思っています。しかし、人が探して入力するのではなく、ロボットで自動的に営業をかけようと考える事がどうかと思います。
効率が求められます事もありますが、営業は人と人との関係を築きながら行うべきだと。
Dockerでrails db:resetしたい

# DBの状態を一旦リセットしたい時。

基本は、以下のコマンドでDBがリセットされる。

```
% docker-compose exec web rails db:reset
```

できない時は、一度リスタートを行うとできる。

```
% docker-compose restart
% docker-compose exec web rails db:reset
```
Accessクエリ 関数【日付操作編】④

備忘録として投稿します。
全13項目【日付操作編】④まであり今回は【日付操作編】④で最後の記事です。
参考にしていただければ幸いです。
#ACCESSの日付操作でよく使用する関数　その４
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2517880/ef41d363-b172-be0e-b566-71280cda4ff7.png)
#まとめ
今回は
⑧指定した日付から月末までのデータを抽出したい。
⑫半期のデータを抽出したい。
⑬偶数月のデータを抽出したい
以上3つの項目についてまとめてみました。
最後までご覧いただきありがとうございました。
また、引き続き他の記事も上げますので参考になさってみて下さい。
Reactを基本からまとめてみた【25】【scroll animation 】

##環境の準備
①ターミナルでreactアプリケーションを作成する。

```
$ npx create-react-app <プロジェクト名>
% cd <プロジェクト名>
% npm start
```
② 必要な環境を整える。

```
$ npm install bootstrap
$ npm install aos --save
```

公式サイト:[Bootstrap5]
(https://getbootstrap.jp/)

③ logo.svg,　setupTests.js,　App.css,　index.css, App.test.js,　reportWebVaitals.js を削除する。

##コンポーネント・ファイル構成

```
src
 ├── img   //画像を入れるファイル
 ├── App.js
 ├── Card.js
 ├── Home.js
 ├── index.js
```

##ファイルを作成及び編集

① App.jsを編集

```App.js
import React from "react";
import "../node_modules/bootstrap/dist/css/bootstrap.min.css";
import Home from "./Home";

function App() {
  return (
    <>
      <h1 className="text-center mt-3">Scroll Animation</h1>
      <Home />
    </>
  );
}

export default App;
```

```index.js
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById("root")
);
```

```Card.js
import React, { Component } from "react";

export default class Card extends Component {
  render() {
    return (
      <div
        data-aos={this.props.aos}
        data-aos-offset={this.props.aos_offset}
        className="col-11 col-md-6 col-lg-3 mx-0 mb-4"
      >
        <div class="card p-0 overflow-hidden h-100 shadow">
          <img src={this.props.img} class="card-img-top" />
          <div class="card-body">
            <h5 class="card-title">{this.props.title}</h5>
            <p class="card-text">{this.props.desc}</p>
          </div>
        </div>
      </div>
    );
  }
}
```

```Home.js
import React, { useEffect } from "react";
import Aos from "aos";
import "aos/dist/aos.css";
import Card from "./Card";
import Img1 from "./img/img8.jpg";

const Home = () => {
  useEffect(() => {
    Aos.init();
  }, []);
  return (
    <section className="py-4 py-lg-5 container">
      <div className="row">
        <Card
          aos="zoom-in"
          aos_offset="100"
          img={Img1}
          title="title"
          desc="desc"
        />
        <Card
          aos="zoom-in"
          aos_offset="100"
          img={Img1}
          title="title"
          desc="desc"
        />
        <Card
          aos="zoom-in"
          aos_offset="100"
          img={Img1}
          title="title"
          desc="desc"
        />
        <Card
          aos="zoom-in"
          aos_offset="100"
          img={Img1}
          title="title"
          desc="desc"
        />
        <Card
          aos="zoom-in"
          aos_offset="100"
          img={Img1}
          title="title"
          desc="desc"
        />
      </div>
    </section>
  );
};

export default Home;
```

##参考サイト
[Animations On Scrolling In React JS | Card Animations On Scroll down | React js scroll animation]
(https://www.youtube.com/watch?v=XVzk1D82GwA)
Databricksクラスターの監視

Databricksではクラスタのオートスケール機能やオートスリープ機能など、インフラコストを効率化する機能が標準で提供されています。 

https://qiita.com/taka_yayoi/items/8d951b660cd87c6c5f18#%E3%82%AF%E3%83%A9%E3%82%B9%E3%82%BF%E3%83%BC%E3%82%B5%E3%82%A4%E3%82%BA%E3%82%AA%E3%83%BC%E3%83%88%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%AA%E3%83%B3%E3%82%B0

https://qiita.com/taka_yayoi/items/991aae376c089df58504

一方で、標準のクラスタ管理機能に加えて細かい制御を実施してたい場合もあります。例えば、Notebook上でストリーミング処理(ユーザーが停止まで動き続ける処理)のテストを実施をしていて、不意に処理を止め忘れているケースでは、クラスタも継続的に起動し続けます。起動している全てのクラスタを監視して、起動時間(uptime)が不自然に長いクラスタを発見できれば問題を解消できます。

Databricksでは、[クラスタ管理のAPI](https://docs.databricks.com/dev-tools/api/latest/clusters.html)を提供されているため、上記のような細かい制御も可能になっています。

クラスタを監視して、設定した閾値よりも長く起動しているクラスタをリストするスクリプトは以下のように構成できます。

```python
import requests
import json, datetime
from urllib.parse import urljoin

WORKSPACE         = 'https://xxxxxxxxxxxxx.cloud.databricks.com'
TOKEN             = 'dapixxxxxxxxxxxxxxxxxxxxxxxxx'
UPTTIME_THRESHOLD = 36000 #36000 seconds = 600 min = 10 hours


url = urljoin(WORKSPACE, '/api/2.0/clusters/list')
headers={'Authorization': f'Bearer {TOKEN}'  }

ret = requests.get(url, headers=headers)

if ret.status_code == 200:
  long_runs = []
  for cluster in ret.json()['clusters']:
    if cluster['state'] == 'RUNNING':
      
      # scan the uptime
      start_time = datetime.datetime.fromtimestamp( cluster['start_time']/1000)
      now = datetime.datetime.now()
      uptime = now - start_time
    
      if uptime > datetime.timedelta(seconds=UPTTIME_THRESHOLD):
        long_runs.append( (cluster['cluster_name'], cluster['cluster_id'], str(uptime))  )
      
  ### output ###
  print(f'UPTTIME_THRESHOLD: {UPTTIME_THRESHOLD} sec')
  print('')
  print('cluster_name, cluser_id, uptime(sec)')
  print('------------------------------------')
  for cluster in long_runs:
    print( ', '.join(cluster) )

else:
  print(f'Status: {ret.status_code}')
  print(ret.text)

```
(注意: 簡単のため、セキュリティ・エラー処理は省いています。)

**実行結果の出力例**

```
UPTTIME_THRESHOLD: 36000 sec

cluster_name, cluser_id, uptime(sec)
------------------------------------
mlflow-cluster123, 0111-120999-wi0qkt9q, 21 days, 11:40:57.331791
testing, 0119-089999-u0oq54ru, 13 days, 15:16:51.334819
```

上記をベースに定義機変更を加えて(例えばAWS SNSなどの通知システムとの連携など)、定期的に実行することで、不用意に起動しているクラスタのシンプルな監視することができるようになります。

https://qiita.com/ktmrmshk/items/84c6a38cce0e7b11cd05

# 参考

* [Databricks Clusters API 2.0](https://docs.databricks.com/dev-tools/api/latest/clusters.html)
    * [`2.0/clusters/list`](https://docs.databricks.com/dev-tools/api/latest/clusters.html#list)

https://qiita.com/taka_yayoi/items/722c7ee42d245406c9ca

https://qiita.com/ktmrmshk/items/84c6a38cce0e7b11cd05
Flask-Bootstrap でDataTables使おうとしてハマったのでメモ

# 環境
Python 3.8.10
Flask
Flask-bootstrap

# 問題
Flask-bootstrapに入っているbootstrap4を用いて、DataTablesを使ってテーブルデータを表示させようとしたらなぜか反映できず

https://datatables.net/

# 原因
javascript読み込みのコードを bodyタグの内に書いていたこと
例： {% block content %}や{% block scripts %} 内に書くとエラーが出る

# 解決
*javascript読み込みコードをheadタグ内に入れたら解決*

## 考察
おそらくFlask-bootstrapは一般的なhtmlファイルとロードの順序とは異なる仕様であるためかと思われる


## 参考
https://qiita.com/shinataka/items/73f150846e5dc7894dd5
Ruby3.1にしたらRails consoleもオートコンプリートされるようになったので無効化する

Ruby3.1からIRBにオートコンプリート機能が実装されました。
irb上で下記のように候補が表示されます。

![スクリーンショット 2022-02-02 9.41.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83424/884f705f-a90d-cae0-ddb7-53fac2c392b9.png)

こちら、最初に見た時はすごい便利そうと思ったのですが、、、

* irbでガリガリコードを書くことほぼないので補完して欲しいシチュエーションが少ない
* 候補を表示するために画面位置がずれる
* Tabでしか候補を移動できない(個人的にはCtrl+nで上、Ctrl+pで下に移動して欲しい)
* 表示が重いときがある

など様々な要因が重なりOFFにしようと思いました。

irbのドキュメントには`--noautocomplete`オプションで無効化できると記載されていますが、Rails開発では`rails c`でirbを起動しているのでこのオプションが指定できずどうやって無効化するのか調べました。

https://docs.ruby-lang.org/en/master/IRB.html

やり方は簡単で、上記のドキュメントに記載されている`.irbrc`をカレントディレクトリに作成することで簡単に無効化できました。

```:.irbrc
IRB.conf[:USE_AUTOCOMPLETE] = false
```

ちなみに、`.irbrc`を作成したら、irbの履歴が.irb_historyファイルに保存されるようになってしまったので下記も追加しました。

```:.irbrc
IRB.conf[:SAVE_HISTORY] = nil
```
pure-python-adbでkillが動かない場合

# ライブラリを修正する

以下にある
%appdata%\..\Local\Packages\PythonSoftwareFoundation.Python.3.x_xxxxxxxx\LocalCache\local-packages\Python39\

site-packages\ppadb\command\transport\\\_\_init__.py
の22行目くらい

```python
#        cmd = "shell:{}".format(cmd)
        cmd = "shell,v2,TERM=xterm256color,raw:{}".format(cmd)
```

こんな感じで使うと動くようになる

```python
self.device.shell("kill -9 `ps -ef | grep " + option + "|grep -v grep | awk '{print $2}'`")
```


# ついでに2重rootの許可とremountも実装するとこんな感じ

```TEXT
diff --git a/ppadb/command/transport/__init__.py b/ppadb/command/transport/__init__.py
index 1adadf6..8bfba12 100644
--- a/ppadb/command/transport/__init__.py
+++ b/ppadb/command/transport/__init__.py
@@ -16,10 +16,23 @@ class Transport(Command):

         return connection

+    def remount(self):
+        conn = self.create_connection(timeout=timeout)
+
+        cmd = "remount:"
+        conn.send(cmd)
+
+        if handler:
+            handler(conn)
+        else:
+            result = conn.read_all()
+            conn.close()
+            return result.decode("utf-8")
+
     def shell(self, cmd, handler=None, timeout=None):
         conn = self.create_connection(timeout=timeout)

-        cmd = "shell:{}".format(cmd)
+        cmd = "shell,v2,TERM=xterm256color,raw:{}".format(cmd)
         conn.send(cmd)

         if handler:
@@ -185,6 +198,8 @@ class Transport(Command):

             if "restarting adbd as root" in result:
                 return True
+            elif "adbd is already running as root" in result:
+                return True
             else:
                 raise RuntimeError(result.strip())

```

# exec-outは以下も追加(screencapしか考慮していない)

```python
    def exec(self, cmd, handler=None, timeout=None):
        conn = self.create_connection(timeout=timeout)

        cmd = "exec:{}".format(cmd)
        conn.send(cmd)

        if handler:
            handler(conn)
        else:
            result = conn.read_all()
            conn.close()
            return result
```


使用例

```python
        buf = self.device.exec("screencap -p")

# 以下は普通関数化すると思う
        try:
            dir_name = os.path.dirname(option)
            os.makedirs(os.path.join("captures", dir_name), exist_ok=True)
            out_path = os.path.join("captures", option + "-" + str(self.test_count) + ".png")
            f = open(out_path, "wb")
            f.write(buf)
            f.close()
```
Amazon Linux 2でcronを使ってバッチ処理を実行する

# 目的
Amazon Linux 2のEC2インスタンスを利用してアプリをデプロイする際にバッチ処理でデータベースのバックアップを取りたいと思い備忘録。
# 前提
Amazon Linux 2ではバッチ処理をするためのcronが標準インストールされている。

# バッチ処理の設定をする
### 設定ファイルを開く

```
$ crontab -e
```

### 書き込む
毎月1日の0時00分にバッチ処理を動かす場合

```bash
0 0 1 * * source ~/venv/bin/activate; 
cd ~/test_app; 
# 標準出力と標準エラー出力をcron.logというファイルに書き出すようにする
python manage.py backup_test > ~/cron.log 2>&1
```

書式以下のようになっている。

```
<分><時><日><月><曜日><実行したいコマンド>
```

# まとめ
バッチ処理の実装は業務では当たり前のことではあるが、なかなか個人で実装することがないと思うので、実装してみた。
【Laravel】Eloquentの並び替えでNULLを後ろに持ってくる

# 環境
Laravel: 8.82.0
PHP: 8.1.2

# `asc`で`NULL`を後に持ってくる

Itemを昇順で並べてみます。

```php:失敗パターン
$user = Auth::user();
$items = $user->items()->orderBy("price", "asc")->get();
```

値段が安いものから表示させたいと、上記のコードで並べてみると、、、、

__非売品__が先に表示されてしまいます。
そう、非売品の__`price`は`NULL`__なんです。

複雑な条件が必要なのか、
はたまた`NULL`と`NULL`でないもので分けて取得する必要があるのか
と色々考えながら、調べておりました。

## `->orderByRaw('column is null asc')`

`->orderByRaw('column is null asc')`を使うと、`NULL`を後ろに回すことができます。
※`column`の部分に DB のカラム名が入ります。

```php:成功パターン
$user = Auth::user();
$items = $user->items()->orderByRaw('price is null asc')
            ->orderBy("price", "asc")->get();
```

これで、値段の安い順に並びつつ、
`NULL`である非売品は、後ろに並びます。