OmniAICreator/Qiita-1.07M huggingface dataset:
WiFi.localIP()をESP_LOGDやsprintfで出力する方法

デバイス自身のIPアドレスを得ることができる [WiFi.localIP()](https://www.arduino.cc/en/Reference/WiFiLocalIP) は、[IPAddressクラス](https://www.arduino.cc/en/Reference/EthernetIPAddress)を返します。
この情報を利用しようと、例えば `Serial.print(WiFi.localIP());` とすれば、IPアドレスが表示されます。

これはIPAddressクラスが Printクラスを継承し、 `printTo()` が実装されているため、あたかも文字列のように出力できますが、実際は4つのuint8_tで構成されているため、printに対応していない出力では、以下のように表示できません。

```c++:コード
ESP_LOGD(TAG, "localIP(): %s", wifi->localIP());
```

```:結果
[  5028][D][example.ino:20] setup(): localIP(): ⸮⸮@?⸮⸮⸮=
```

※ [ESP_LOGD](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/log.html)は、ESP32プラットフォーム向けのログライブラリで定義されているマクロで、sprintfのようにフォーマット文字列が利用できます。

## 対策

`toString()` と `c_str()` を利用しましょう。

```c++:コード
ESP_LOGD(TAG, "localIP(): %s", wifi->localIP().toString().c_str());
```

```:結果
[  4829][D][example.ino:20] setup(): localIP(): 192.168.1.102
```

IPAddressクラスにはStringを返す `toString()` が実装されています。String自体はフォーマット文字 "%s" では表示できませんが、Stringの `c_str()` で `std::string` を返すことで、 "%s" で表示できるようになります。

EoT
Android振動のさせ方

今回はAndroidの実装で振動をさせることになったので、やり方を残しておこうと思います。

※こちらAPI level 26以上　API level 31未満のやり方です。
API level 31ではDeprecatedになっており、VibratorManagerを使用します。

# Manifestの設定

AndroidManifest.xmlでVIBRATEの許可します。


```AndroidManifest.xml
<uses-permission android:name="android.permission.VIBRATE"/>
```

# Activity
``` MainActivity.kt
 val vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
 val vibrationEffect = VibrationEffect.createOneShot(500, 200)
 vibrator.vibrate(vibrationEffect)
```

これで振動できます。
createOneShotで振動の設定をします。
第一引数は振動するミリ秒数。これは正の数でなければなりません。
第二引数は振動の強さ。これは、1〜255、またはの値である必要があります。


また今度API level 31のやり方を調べて記事にしてみようと思います。
LINE BOTアプリとLIFFを利用して既存WEBサービスをログインレス化する part.2

# 概要
下記のpart.1の記事ではLINE側で発行されたIDと既存サービスのIDの紐付けを安全に行う方法を解説しました。
本記事ではLIFFとLINE側が用意している認証認可機能を利用してログインレスシステムを実現いたします。

https://qiita.com/akahori_s/items/3d063c1eca18b57b4616

またpart.1同様下記のサンプルプログラムを利用して解説を行います。

https://github.com/aka-ao/spring-boot-app-with-line-bot

# 解説
### 1. 前提
前提としてWEBサービスをHTML、CSS、JSなどを生成するVIEW機能とその中のコンテンツデータを取得及び更新するAPIに分離しています。
今回後者のAPI部分をLINE側が用意している認証認可機能を利用します。

### 2. LIFF初期化
LIFFを利用するためにまず初期化を行います。
```javascript
liff.init({
  liffId: defaultLiffId,
  withLoginOnExternalBrowser: true
})
.then(() => {
  console.log("liff init success");
 });
```

### 3. アクセストークン取得
LIFFでは下記のコードのようにgetAccessTokenメソッドを呼ぶことでアクセストークンを取得できる機能が用意されています。
下記の例ではAPIサーバ側のLINEIDを取得するAPIを呼んでいます。
取得したアクセストークンはヘッダに詰めてAPIサーバに送信します。
```javascript
const accessToken = liff.getAccessToken();
axios.get("{change your domain}/liff/getLineId",{
  headers: {
    'Authorization': 'Bearer ' + accessToken
  }
})
.then(function(response){
  const userId = response.data;
  alert(userId);
});
```

### 4. userId取得
送信したアクセストークンAPIサーバ側で抽出し、LINEのアクセストークン検証APIに送ります。そうするとpart.1で取得したLINE側のuserIdが取得できます。Springでは下記のように実装すればuserIdを取得できます。(LineAuthResponseクラスは自分で実装しています。サンプルプログラムを参照してください。)
```java
ResponseEntity<LineAuthResponse> auth
  = restTemplate
    .getForEntity(URI.create("https://api.line.me/oauth2/v2.1/verify?access_token=" + accessToken)
    , LineAuthResponse.class);
```

このuserIdはDBにWEBサービス側のIDとセットで保存されています。
そのためuserIdをキーにしてDB検索すればどのユーザがLIFFを通じてアクセスしてきているかログインせずに安全に特定する事ができます。
例えばECサイトなどで特定したユーザに紐づく属性情報（住所や購入履歴など）を返しても問題ない
もし特定できなければ、紐付けできていないユーザか不正にアクセスしているかのどちらかなので401などのレスポンスを返すようにします。

- アクセストークン検証API
https://developers.line.biz/ja/reference/line-login/#verify-access-token

# まとめ
ログインレスでシステムを構築することで、ユーザビリティを向上させることができます。
その際に課題となるセキュリティ面の保証をLINEというプラットフォームに任せることで簡単に実装できます。
ユーザ目線でも認知度が高いプラットフォームなので安心して使うことができるのではないでしょうか。また、ミニアプリとしてサービス展開できます。アプリのようにインストールして使う必要がないのでうまく活用すれば新規ユーザの獲得も見込めると思います。

# 免責
この記事にはセキュリティに関する内容が含まれています。
細心の注意を払って記事を執筆していますが、この記事によって起こった損害については一切保証しかねます。
この記事を参考にし同様の実装を行う際には改めて問題はないか検討し、自己責任で適応していただきますようお願い致します。
Postgres: Power BI で利用しやすくする為の Unpivot SQL

# 背景
Power BI のビジュアルでは Unpivot してあるとスライサーで利用しやすいので
Postgre 上での Unpivot 方法を備忘録

# 概要
Union で繋げる道もあるけれど、重くなるので Unnest を使う

# 詳細
変換の前後をみることで、Unpivot の結果が分かるかな、と
## 変換前：元データ
PLC からの取得データだと、以下のように大量の列にデータがばらけてたりする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/ad766424-90a1-2b54-89d1-158232044122.png)

```sql:元データ作成用
CREATE TEMP TABLE pivotTable ("ID" int, "Interests1" text, "Interests2" text, "Interests3" text, "Knowledges1" text, "Knowledges2" text, "Knowledges3" text);
INSERT INTO pivotTable VALUES (1, 'Movie', 'Game', 'Music', 'C#', 'Yaml', 'JSON'), (2, 'Music', 'Game', 'Tennis', 'C#', 'JSON', 'PowerPlatform');
```

## 変換後：取得したい結果
こんな感じにしたい
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/2b667d59-2b22-1776-8f4f-3a032cfabcc5.png)

## SQL
こんな感じでグループ単位で unnest() していけば OK
```sql:Unpivot方法
SELECT 
	"ID",
	unnest(array['First', 'Second', 'Third']) AS "Order",
	unnest(array["Interests1", "Interests2", "Interests3"]) AS "Interest",
    unnest(array["Knowledges1", "Knowledges2", "Knowledges3"]) AS "Knowledge"
FROM pivotTable
ORDER BY "ID";
```

# あとがき
半角大文字小文字を意識した列名にする場合は "ID" のように二重引用符が必要なんだと最近知ったけど・・

触ったことないもの使うと新しいことが沢山あって楽しいですね


# 参考
元ネタは、安定の stakoverflow。久しく投稿してないけど・・

https://stackoverflow.com/questions/1128737/equivalent-to-unpivot-in-postgresql?msclkid=0d3cd24fab1211ecaf02ce1620b5992b

```sql:Union版
SELECT id,
       'a' AS colname,
       a AS thing
FROM foo
UNION ALL
SELECT id,
       'b' AS colname, 
       b AS thing
FROM foo
UNION ALL
SELECT id, 
       'c' AS colname,
       c AS thing
FROM foo
ORDER BY id;
```

```sql:unnest版
SELECT id,
       unnest(array['a', 'b', 'c']) AS colname,
       unnest(array[a, b, c]) AS thing
FROM foo
ORDER BY id;
```

# keyword
Equivalent to unpivot() in PostgreSQL
delegateメソッドとは

## delegateメソッドとは
メソッドを簡単に委譲できるメソッド。

例えば、``Userモデル``ログイン情報があり、それに関連する名前などの情報は``Profilemモデル``があったとする。

```model/user.rb
class User < ApplicationRecord
  has_one :profile
end
```

``profile``の中にある、``name``要素を取り出したい時、``user.profile.name``のようにメソッドチェーンしたものを書く。

しかし毎回メソッドチェーンしたものを呼び出すのも面倒なので、
``user.name``にしたい。そんな時に``delegate``を使う。

なお下記は``delegate``を使用しない場合の記述。
```model/user.rb
class User < ApplicationRecord
  has_one :profile
 
  def name
    profile.name
  end
end
```

## 使い方
```rb
delegate :メソッド名（カラム名）, to: :関連付けしているモデル名
```

```model/user.rb
class User < ApplicationRecord
  has_one :profile
 
  delegate :name, to: :profile
end
```

``delegate``には複数のメソッドを指定できる。

```rb
#基本の型
delegate :name, :age, :address, :twitter, to: :profile
```

## オプション
**prefix**
``delegate``はパブリックメソッドとして定義するので、もし重要なデータなどを指定してしまうと、可能性として低いが面倒なことが起きることもあるので、``privateメソッド``として``delegate``を定義することが可能になっている。
```rb
delegate :date_of_birth, to: :profile, private: true
```
↑上記と同義になり、アクセスできる範囲を狭めることが可能。
```rb
private

def date_of_birth
  user.date_of_birth
end
```

**allow_nil**
``:allow_nilオプション``を付与すると、``profile``が``nil``だった場合に、``user.name``は例外ではなく、``nil``を返すようにできる。
```rb
delegate :name, to: :profile, allow_nil: true
```
下記のようにぼっち演算子をつけたメソッドを定義したものと同義になる。
```rb
def name
    profile&.name
  end
```

## 参考記事
[Railsガイド](https://railsguides.jp/active_support_core_extensions.html#%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%81%AE%E5%A7%94%E8%AD%B2)
[【Ruby on Rails】delegateの使い方【委譲は便利】](https://sakurawi.hateblo.jp/entry/delegate)
[【Rails】delegateで省エネする方法を、公式リファレンスから理解する](https://coffee-engineer4.com/2021/05/17/%E3%80%90rails%E3%80%91delegate%E3%81%A7%E7%9C%81%E3%82%A8%E3%83%8D%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95%E3%82%92%E3%80%81%E5%85%AC%E5%BC%8F%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9/)
きみはポラリス。文学とプログラムの違い。

データに関する記事を書こう！

https://qiita.com/official-events/30be12dd14c0aad2c1c2

テーマ2『データに関する記事を書こう！』参加記事です。

きみはポラリス。統計における分類。

https://qiita.com/kaizen_nagoya/items/30524efd7cb1d249006c

で、きみはポラリス 新潮文庫, [三浦 しをん](https://ja.wikipedia.org/wiki/三浦しをん) を紹介した。
<img width="200" alt="51ZnO0Vsf2L._SX351_BO1,204,203,200_.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51423/72006a45-420d-18ce-26c8-b075f6f68f36.jpeg">
https://www.amazon.co.jp/dp/4101167605/
https://bookmeter.com/books/2750307
https://booklog.jp/item/1/4101167605
>不思議な日常生活の短編集11話。手紙ではじまり、手紙で終わる。怖い話あり、恐ろしい話あり、暗い話あり、黒い話あり。ポラリスはポールが極という意味で、北極星のことを指す。北極星は、北半球では夜空で動かない。これらの話では、誰が動かないのだろう。著者と助産師さんは動じない。登場人物を操っている。「私（助産師）がポラリス」が本当の題名かも。あるいは「きみは（産婦）がポラリス）」で合っているのかも。解説：中村うさぎ。p.389。「が、ひとつひとつがまったく違った味をもちながらも、じつは、そのほぼすべてに共通しているテーマがひとつあるように、私には思えたのです。いかがでしょう、シェフ？　どの皿にも共通して使われている、ひとつの調味料。

>それは、「秘密」ではありますまいか？」

他の人の感想を読んでいて、違和感があった。

# 自分には合わない

プロログラムでも「自分には合わない」と思うことがある。
使うとき、書き直すとき、評価するときに感じる。

文学で「自分には合わない」と書く人は、読者視点だけで、作者視点で書いていない可能性があるかもしれない。
読者であっても、感想を書くのであれば、書き手の視点があると嬉しい。

万葉集私注　土屋文明は、読み手の視点を解釈しようとしていて勉強になる。

https://bookmeter.com/books/3862098

読み手の視点は推測しきれるものではない。いくつかの候補をあげるだけにしておくのが好ましいと感じている。

## 読むだけ

読むだけで、自分には合わないと思うのは、文学の消費者ではありえる。
ソフトウェアでは読むだけは、使うだけに言い換えてみる。
ソフトウェアを使うだけの消費者は、自分には合わないと思うことはありえる。

 自分には合わない

## 書き足す、書き直す

プログラムと文学で、同じ側面と違う側面があるだろう。

文学の評論で、一人称、二人称、三人称の３つの立場がありえる。
書きての視点で述べるか、読み手の視点で述べるか、出版社を含む読み手・書き手以外の立場で述べるか。

文学における第三者は、あまり意味がないかもしれない。


## 評価する

読むのでも、書くのでもない評価というのは難しい。

金になるかどうかというのは、市場を巨視的に分析するだけでなく、個々の消費者の行動を微視的に分析するだけでも不十分な可能性がある。

どちらの分類にも属さない分析ができると、何か突破口が見えるかもしれない。

人の利用だけでなく、ソフトウェアの動作結果は、他のソフトウェアが利用する場合があり、網で分析するとよい。


# まとめに代えて

文学とプログラムは、相似な構造が、社会的にも、人間としても、文字としての記録としての３つの軸で比較可能なのだろう。

社会的な分析では、政策組織、流通組織、法制度などについて、検討するとよい事象がある。

人間としては、発話行為の果たす役割を定式化するとよいかもしれない。

文字としては、字形、文字符号、大きさ、密度などの表現形式と、単語の出現頻度、共出現をはじめ機械学習による処理の自動化の可能性について、考察できるかもしれない。

大量のプログラムと文学を同一の学習をしたものと、
別々の学習をしたものの３つを用意して、
なにがしかの自動生成で利用するとよいかもしれない。

文学とプログラムの違いは、当初はないという前提で来た。
違いも体系的に記述するとよいかもしれない。

プログラムは詩のように描こう

https://qiita.com/kaizen_nagoya/items/dd2a912f23b18e0f8893

programming like making a poem.

https://qiita.com/kaizen_nagoya/items/07ed8747f0811d070070

### 最後までおよみいただきありがとうございました。

いいね　💚、フォローをお願いします。
#### Thank you very much for reading to the last sentence.

Please press the like icon 💚　and follow me for your happy life.
React プロジェクトで Google Fonts を使う

# React プロジェクトで Google Fonts を使う

おしゃれなフォントを見つけたので適用方法をメモ書き

## 1. importコード生成

https://fonts.google.com/

まずは、`Google Fonts`でいい感じのFontを見つけます

見つけたら、`+ Select this style`をクリックします

![google_fonts_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341857/ae27d662-48ba-757e-9a2b-18dc8ec8fad2.png)

すると、右側にナビゲーションが出てきます
(出てこない場合は画面上のメニュー内のアイコンをクリック)

![google_fonts_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341857/d969b484-09f2-00be-1390-d148dc298db2.png)

ここでいったん置いておく

## 2. React App で読み込む

React側でCSSを適用させます

### 2-1. style.css を作成

style.cssを作成し、ナビゲーションメニューに出てきた
`@import`の部分をコピペします

また、`body`タグの`font-family`をGoogleFontsのFont名にします

```css:style.css
@import url('https://fonts.googleapis.com/css2?family=Zen+Maru+Gothic&display=swap');

body {
  font-family: 'Zen Maru Gothic', sans-serif;
}
```

### 2-2. cssを読み込む

作成したcssを、フォント適用させたいコンポーネントでimportします

```tsx:App.tsx
import './style.css';

function App () {
  // 
}
```

完了!
Vue.js v-modelで値をバインドする方法

# 概要
v-modelによって,入力された値をVueで定義したプロパティの値にバインドする機能について記載します。

# 記述方法
```
<input v-model="変数名">
```
`変数名`にはVueオブジェクト内に定義した変数の名前を指定します。
  
# 実例
```html
<body>
    <h1>Vue.js</h1>
    <div id="app">
        <div><test v-bind:name="name" /></div>
        <div><input type="text" v-model="name"></div>
    </div>

    <script>
        var test = Vue.component('test',
        {
            props:['name'],
            template: '<p class="test">{{ name }}!</p>',
        })

        var app = new Vue({
            el: '#app',
            data:{
                name:''
            }
        });
    </script>
</body>
```

添付した画像のようにテキストエリアに入力した値が出力されます。
![スクリーンショット 2022-03-27 17.02.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594871/aafb0493-2730-d649-48c5-21f462a5a984.png)
NULL のはずなのに if 文が反応しない問題

# 目次
[1.NULL のはずなのに if 文が反応しない](#1-null-のはずなのに-if-文が反応しない)
[2.Collection には isEmpty()を使う](#2-collection-には-isempty-を使う)

Laravelを使ったブログサイト作成中に気になったことがあったのでアウトプットとして書いてみます。

# 1. NULL のはずなのに if 文が反応しない


ブログ記事一覧ページで、
**記事にサムネイルがある場合はそれを表示し、無い場合は no images の写真をサムネイルとして表示する。**
という機能を実装させるため、下記のようなコードを blade に書きました。

```php5
@if($post->images !== null)
    @foreach ($post->images as $image)
        ...省略
    @break
    @endforeach
@else
        ...省略
@endif
```

しかし、全ての記事が null ではない方の処理がされてしまいました。
サムネイル無しで投稿したブログも全て、
`@if($post->images !== null)`の処理をされてしまい、
本来表示されるはずの no images の写真が表示されず空白になってしまいました。
`empty` や `isset` などに変えても同様の結果でした。
 
# 2. Collection には isEmpty() を使う

おかしいなと思い、デバッグで `$post->images` の中身を確認してみたところ、

`object(Illuminate\Database\Eloquent\Collection)#1280 ....`　とのこと。

どうやら Collection が入っているため、普通の配列とは違うようです。
色々調べた結果、Collectionのメソッド、`isEmpty()` を使うのが正しいみたいです！

というわけで修正後がこちら！！

```php5
@if($post->images->isNotEmpty())
    @foreach ($post->images as $image)
        ...省略
    @break
    @endforeach
@else
        ...省略
@endif
```

これで正しく動いてくれました！

デバッグって優秀.....そして Collection についてもっと勉強しよう。
今日のアウトプットはこれで以上です！
令和元年秋期試験午前問題　問54について

# はじめに
基本情報の勉強をしていて、分からない問題がありましたので、整理しました。

# 公式はこちら

https://www.jitec.ipa.go.jp/1_04hanni_sukiru/_index_mondai.html

https://www.jitec.ipa.go.jp/1_04hanni_sukiru/mondai_kaitou_2019h31.html#01aki

# 問題について
令和元年秋期試験午前問題　問54

10人のメンバで構成されているプロジェクトチームにメンバ2人を増員する。次の条件でメンバ同士が打合せを行う場合，打合せの回数は何回増えるか。

〔条件〕
打合せは1対1で行う。
各メンバが，他の全てのメンバと1回ずつ打合せを行う。

# 問題の意味について
まず、問題の意味から確認していきましょう。

まず、ここに人が、10人います。
![1BDF0B4E-6CC1-4F46-989E-9E81F2D17361.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148394/fd028dd4-f778-a5d1-5d76-3949b1f3093d.png)

話し合いは2人でします。
![7B964ED2-68B7-436A-8FED-CA3EFDE41E4F.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148394/fbcbacaf-76c6-b4b0-b429-1284eb0c2efb.png)



普段は、10人で話し合いをしていました。
![EF188C69-D02F-4937-BBCE-5CBE09D282F3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148394/f3c78bf9-811b-3e92-83f2-9876bd72c0da.png)




そこに、2人来ました。
![08E75EDF-1EE4-414E-848F-99CE5905FE57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148394/922d87db-0e68-ba2b-660f-82314a11e3b6.png)



これからは、12人で話し合いたいと思います。
![60487C68-C856-4432-A03F-F40E21AD49BA.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148394/7560262c-ee0b-8533-55d1-966de20d267c.png)



次の、打合せの回数は、いつもの打ち合わせの回数と比べて、何回増えるのでしょうか？



# 考え方

まず、打ち合わせの数を数える必要があります。
![71F097E4-6F1B-4678-93C4-F9539370BB11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148394/c8d12f9a-a4c6-371a-7823-d40861c871bf.png)

### 10人から2人を選ぶ組合せ数はこちらです。

![06DEFA45-838E-40A7-BBDA-1B37A73D4B0A.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148394/757c15cb-bbdc-0422-ec8b-8b9acee6db08.png)

![CFEB8AB3-6759-44BB-A20C-EEB13B87447A.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148394/b894bc69-57f3-373c-5d85-d3ff73bb7df5.png)

計算するとこんな式になります。

=45

45通りです。



### 12人から2人を選ぶ組合せ数はこちらです。

![6F3B0F1D-EF03-4A96-BD88-C472D20EE2CD.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148394/bb61e973-a381-b898-4dc2-f5b9ca4c5229.png)

計算するとこんな式になります。

![60F5DDC6-F3A3-4EEF-8DF0-122D456F639B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148394/1e154f18-3334-e889-c0eb-021367cdee50.png)


=66

66通りです。


### あとは差を求めるだけ。

66通り-45通り
=21通り


21通りとなります！
【Laravel】マルチログインで認証ミドルウェアのリダイレクト先をGuard(認証)別で指定する

# 環境
- PHP 8.0.3
- Laravel 8.79.0
# 今回実現したい事
- ルーティングで`middleware auth:〇〇`を使ってログインしていないユーザはGuard(認証)別のログインページにリダイレクトしたい
- `redirectTo`をオーバーライドしただけではGurardが分からないためGuard別のリダイレクトが出来ない
# 結論
Authenticateクラスの`unauthenticated`をオーバーライドして`redirectTo`メソッドの第二引数に$guardsを追加して使う。下記のようにすることで`redirectTo`でguardが分かるようになる。

```php:Authenticate.php
use Illuminate\Auth\Middleware\Authenticate as Middleware;
use Illuminate\Auth\AuthenticationException;

class Authenticate extends Middleware
{
    protected function unauthenticated($request, array $guards)
    {
        throw new AuthenticationException(
            'Unauthenticated.', $guards, $this->redirectTo($request, $guards) // $guardsを第二引数に追加
        );
    }

    protected function redirectTo($request, $guards) // $guardsを第二引数に追加
    {
        if (! $request->expectsJson()) {
            // middlewareがauth:adminならroute('admin.login.form')にリダイレクトされる
            if(in_array('admin', $guards)) {
                return route('admin.login.form');
            }
            
            // middlewareがauth:userならroute('user.login.form')にリダイレクトされる
            if(in_array('user', $guards)) {
                return route('user.login.form');
            }
        }
    }
}
```
シェルスクリプトで書くgit エイリアス

:::note warn
この記事は、gitエイリアスを作るにあたって[より適した方法](https://git-scm.com/book/ja/v2/Git-%E3%81%AE%E5%9F%BA%E6%9C%AC-Git-%E3%82%A8%E3%82%A4%E3%83%AA%E3%82%A2%E3%82%B9)を紹介していません。
:::
# 動機
シェルスクリプトを触れるようになりたいということで、はじめの一歩として普段よく使うgitコマンドをカスタマイズしてみることにしました。

# やりかた
適当なディレクトリに「git-hoge」という名のシェルスクリプトを配置し、実行権限をつけてパスを通せば「git hoge」コマンドが動くようになります。
### git-hogeを配置
```
$ cd ~
$ mkdir .bin
$ cd .bin
$ vim git-br
```
```sh:git-br
1 !#/bin/sh
2 git branch $@
```
引数をすべてうけいれられる
### git-hogeに実行権限をつける
```
chmod u+x git-br 
```
### パスを通す
```sh:.bashrc
export PATH=$PATH:シェルスクリプトを置いたディレクトリへのパス
```
# なんで動くんだ

git側の機能です。
git-hoge形式の名前がついていれば、パスが通っていて実行権限のあるシェルスクリプトをgitが探してきてサブコマンドとして動くようにしてくれます。

# もっといいやり方
冒頭にも警告をおきましたが、これにはもっと楽な方法があります。
そちらについても[記事を書いた](https://qiita.com/iNomaG/items/54edb514125bfe6a140c?utm_campaign=post_article&utm_medium=twitter&utm_source=twitter_share)のでご覧になってください。
FlutterやDartで非同期APIコードのフルスタックトレースを出力する方法


```dart
import 'dart:async';
import 'package:stack_trace/stack_trace.dart';

void main() async {
  Chain.capture(() async {
    await okFunc();
    await errFunc();
  }, onError: (error, stack) {
    print(error);
    print(stack);
    // 下記だとChain.capture内のスタックを除去して見やすくしてくれる。
    // print(new Trace.from(stack).terse);
  });
}

Future<void> okFunc() async {
  print('ok');
}

Future<void> errFunc() async {
  await Future.delayed(const Duration(seconds: 1));
  throw 'oh no!';
}
```

非同期系の処理は、スタックが途切れてしまうので何かしらコードに工夫しないと、全てのスタックトレースが出ません。

今回の例だと、capture使っても使わなくてもmainから実行しているせいか？全部出ます。

しかし、flutterなどのボタンイベントでhttpコールなどすると途切れるので有用だと思います。
GoogleColabでweb上のGIFを画像に分解して保存

# コード
GoogleColabのVM内に画像を保存する関係で、大きいサイズのファイルを扱うのは避ける。
また、インスタンスが切れてしまえば保存したデータは全てリセットされる。

画像を保存するディレクトリをVM上に作成
```python
import os
path_content = '/content/img/' #VM上のディレクトリを指定
if not os.path.exists(path_content):
    os.mkdir(path_content)
```

Googleの画像検索などで画像を開いたときに、"画像アドレスをコピー"したものを`url`に入れる。
```python
import requests
from PIL import Image, ImageSequence
import io
import numpy as np
url = "" #保存したい画像の画像アドレス
fname_img = "img" #保存したい画像のファイル名
fname_imgext = "png" #保存したい画像の拡張子

response = requests.get(url)
image = response.content
img = Image.open(io.BytesIO(image))
for idx, frame in enumerate(ImageSequence.Iterator(img)):
    fname = "{}{}-{}.{}".format(path_content, fname_img, idx, fname_imgext)
    frame.save(fname)
```

画像アドレスに対して、`request`を使ったGETリクエストを送信。
GETリクエストに対するレスポンスボディをバイナリ形式で取得して、`io.BytesIO()`でBytesオブジェクトにすれば、`Image.open()`で画像データを開ける。

もちろんGIFだけでなく画像ならこの方法でいけた。


# おわりに
勉強した内容やふと思いついた内容を試すときに、いちいちマイドライブから読み出すのは認証する手間もあって面倒だった。
というわけで、web上のデータをダウンロードして保存する処理の方がコピペして使いまわせるし、自分的に楽なのではと思ったのが始まり。
Ruby on Rails 超簡単レベル上げ機能


5投稿ごとに1レベ上がる。
次のレベル上がるまであと何投稿かを表示する。
```ruby:users_controller
 def show
    @user = User.find(params[:id]) 
    @count = @user.tweets.count
    @level = @count / 5
    @next_level = 5 - (@count % 5)
 end
```

```erb:users/show.html.erb
 <h3>投稿数<%= @count %></h3>
 <h3><%= @level %>Lv</h3>
 <h3>あと<%= @next_level %>投稿でレベルup</h3>
```

![スクリーンショット 2022-03-27 19.44.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1081227/fec181f8-a831-7145-e8f0-441637226993.png)
DockerでRuby on Railsの環境を構築する際のDockerfileのコマンド及びコード理解

## なぜ記事を書こうと思ったか
  Rails用のDockerfileを作成する際にコマンド及びコードの理解を備忘録として残すため。

## Dockerfileとコマンド説明
Dockerfile
```
FROM ruby:[バージョン]
RUN set -x && curl -sL https://deb.nodesource.com/setup_14.x | bash -

RUN set -x && curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
    echo 'deb http://dl.yarnpkg.com/debian/ stable main' > /etc/apt/sources.list.d/yarn.list

RUN set -x && apt-get update -qq && apt-get install -yq nodejs yarn vim default-mysql-client

RUN mkdir /app
WORKDIR /app
COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock
RUN bundle install
COPY . /app

# Add a script to be executed every time the container starts.
COPY ./forDocker/rails/entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

# Start the main process.
CMD ["rails", "server", "-b", "0.0.0.0"]
```

  以下にコマンド及びコードの解説を致します。
1. Dockerfileコマンド
- FROM

  Dockerイメージとバージョンの指定

- RUN

  コンテナ内で実行するコマンドの指定

- WORKDIR

  Dockerfileで設定した命令の作業ディレクトリの指定

- COPY

  ローカルのディレクトリ及びファイルをDockerコンテナにマウント

- ENTRYPOINT

  最初に実行するコマンドの指定

- EXPOSE

  Dockerコンテナを公開するポート番号の指定

- CMD

  デフォルトで実行するコマンドの指定

2．コード理解と用語理解
- `set -x`

  [set]はシェルの設定を確認、変更するコマンドで[-x]によって、シェルが実行したコマンドとその引数を出力。

- `curl -sL https://deb.nodesource.com/setup_14.x | bash -`

  NodeSourceをインストール。数字部分でNode.jsのバージョンを指定。(今回の場合はNodejsバージョン14を指定)

- `set -x && curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \ echo 'deb http://dl.yarnpkg.com/debian/ stable main' > /etc/apt/sources.list.d/yarn.list`

  Debian系で新しいyarnをインストールできるようにする。

- `apt-get`

  Debian系のディストリビューションのパッケージ管理システムであるAPTライブラリを利用してパッケージを操作管理するコマンド

- `apt-get update -qq && apt-get install -yq nodejs yarn vim default-mysql-client`

  APTパッケージ管理システムのアップデート及びnodejs、yarnなどのインストール

- `chmod +x /usr/bin/entrypoint.sh`

  全てのユーザーに/usr/bin/entrypoint.shの実行権限を与える。

## 最後に
  私の記事だけで理解できない部分があったら、適宜調べてみて下さい。

  一つ一つのコードを理解することで、理解できていない事が少なくなり、成長していけると信じています笑

  ここまで読んで頂き有難うございました〜。

## 参考記事
- [Nginx+Rails6.0+MySQL8.0+Adminer：docker-compose で rails new | Zenn | 北山淳也](https://zenn.dev/junki555/articles/13da16e4f10c9dee2bb9)

- [DockerfileのRUN命令](https://qiita.com/sky0621/items/d837c566b04464469fdb)

- [DockerでRuby on Railsの環境構築を行うためのステップ【Rails 6対応】](https://qiita.com/kodai_0122/items/795438d738386c2c1966)

- [dockerfileのEXPOSEとネットワークオプション](https://zenn.dev/suiudou/articles/5e1dfd1008bf29)

- [【 set 】コマンド――シェルの設定を確認、変更する](https://atmarkit.itmedia.co.jp/ait/articles/1805/10/news023.html)

- [NodeSource Node.js Binary Distributions - GitHub](https://github.com/nodesource/distributions)

- [Ruby:2.6 のdockerコンテナでrails6.0を入れようとしたらyarnがコケた | 北山淳也 | zenn](https://zenn.dev/junki555/articles/7a7892c305358d65bede)

- [apt-get - パッケージの操作・管理 - Linuxコマンド](https://webkaru.net/linux/apt-get-command/)

- [chmod コマンド](https://qiita.com/ntkgcj/items/6450e25c5564ccaa1b95)
きみはポラリス。統計における分類。

データに関する記事を書こう！

https://qiita.com/official-events/30be12dd14c0aad2c1c2

テーマ2『データに関する記事を書こう！』参加記事です。

「ありますまいか」親近(既視)感調査

https://qiita.com/kaizen_nagoya/items/973bd27605a1522e2b67

で、きみはポラリス 新潮文庫, [三浦 しをん](https://ja.wikipedia.org/wiki/三浦しをん) を紹介した。
<img width="200" alt="51ZnO0Vsf2L._SX351_BO1,204,203,200_.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51423/72006a45-420d-18ce-26c8-b075f6f68f36.jpeg">
https://www.amazon.co.jp/dp/4101167605/
https://bookmeter.com/books/2750307
https://booklog.jp/item/1/4101167605
>不思議な日常生活の短編集11話。手紙ではじまり、手紙で終わる。怖い話あり、恐ろしい話あり、暗い話あり、黒い話あり。ポラリスはポールが極という意味で、北極星のことを指す。北極星は、北半球では夜空で動かない。これらの話では、誰が動かないのだろう。著者と助産師さんは動じない。登場人物を操っている。「私（助産師）がポラリス」が本当の題名かも。あるいは「きみは（産婦）がポラリス）」で合っているのかも。解説：中村うさぎ。p.389。「が、ひとつひとつがまったく違った味をもちながらも、じつは、そのほぼすべてに共通しているテーマがひとつあるように、私には思えたのです。いかがでしょう、シェフ？　どの皿にも共通して使われている、ひとつの調味料。

>それは、「秘密」ではありますまいか？」

そうだ、ここで「ありますまいか」に馴染んでいたんだ。

ポラリスは北極星。夜、道を歩くときに参考にする。
それに対して、昼、道を歩くときに参考にするのが太陽。

夜は月だという人もいるかもしれない。

そこで、自分の知り合いと、作家と、Qiitaで参考にさせていただいている人などを、３つに分類しようと思った。

なぜかというと、データを集めたら、分類することは、一つの手段だから。

データサイエンティストが役に立たないといわれることがあるのは、
その人が専門分野を持っていない場合。

最低でも１つは必要。
できれば、５つあるとよいというのが自説。


データサイエンティストへの５つの門。あなたはいくつの門をくぐりましたか？統計と確率(8)

https://qiita.com/kaizen_nagoya/items/ee5fa7b2a7f7c2b450d4

自分がデータ分析の対象にしている分野で大事なのは、分布の形と時定数。

主に次の１０分野のデータを扱って来た。

経済学
電磁気学
プログラミング
規格
特許
機械工学
法学
化学
医学
遺伝子工学

分野名が大きい概念では、細かいことはやっていないかもしれない。

# 分類
左の学問が、右の分類を取るといいという話ではない。
自分が扱っているのは、右の分類の事象だけで、それ以外は扱っていないという趣旨。

経済学：巨視(macro)経済学、微視(micro)経済学、中間（meso)経済学
電磁気学：電気回路（電源）、電子回路（半導体）、無線（空中線）
プログラミング：プログラミング言語、通信規約、オペレーティングシステム
規格：情報技術、電気・電子、機械・自動車
特許：通信、論理回路、遺伝子
機械工学：電動機、熱、金属
法学：憲法、民法、商法
化学：無機、有機

# 文学

人生で影響を受けた本100冊。

https://qiita.com/kaizen_nagoya/items/16af53acbb147a94172e

人生で影響を受けた本100冊に10冊足す計画（8冊）

https://qiita.com/kaizen_nagoya/items/3ae6633725df77261df8

で紹介した人を中心に分類してみる。

## きみは太陽
与謝野晶子
小川眞理子
中家奈津子
## きみはポラリス
栗本薫
三浦しをん
中村うさぎ
## きみは月
佐伯裕子
上橋 菜穂子
有川 浩
AWS MWAA (Amazon Managed Workflows for Apache Airflow) にて、`airflow.exceptions.AirflowTaskTimeout: DagBag import timeout`のエラー

# はじめに
AWS MWAA (Amazon Managed Workflows for Apache Airflow) にてワークフロー実行中に表題のエラーに遭遇したため、その解決法について簡潔にまとめます。

# 何が起きたか？
ワークフローを実行するとエラーが起き、タスクのエラーログには以下のように出ていました。

```txt
Executor reports task instance <TaskInstance: hoge_dag.hoge_task manual__yyyy-mm-ddTHH:MM:SS+00:00 [queued]> finished (failed) although the task says its queued. (Info: None) Was the task killed externally?
```

どうやらタスクはキューされているのに、実行できていないようです。これだけではエラーの原因がわからずですが、サーバーログの方に原因がきちんと出ていました。

以下ログ
```txt
airflow.exceptions.AirflowTaskTimeout: DagBag import timeout for hoge_dag.py after 30.0s.
Please take a look at these docs to improve your DAG import time:
* https://***.apache.org/docs/apache-***/2.2.2/best-practices.html#top-level-python-code
* https://***.apache.org/docs/apache-***/2.2.2/best-practices.html#reducing-dag-complexity, PID: 909

ERROR - Failed to execute task Dag 'hoge_dag' could not be found; either it does not exist or it failed to parse..
```
DAGをimportしようとしたが、タイムアウトになってしまっているようですね。

# 原因
直接的な原因は上で記載した通りタイムアウトです。


以下のAirflowの`Best Practices`が載っているページの`Reducing DAG complexity`の項を見ると、タスクの数や分岐など、DAGの構造が複雑になるほどパフォーマンスに影響があることが分かります。
今回の僕のケースでは、分岐を多く含むDAGとして構築していたため、DAGをimportする時間が伸びてしまったと考えられました。

https://airflow.apache.org/docs/apache-airflow/stable/best-practices.html#reducing-dag-complexity

# どう解決したか？
原因のところで述べたように、DAGの複雑性を低くするかタイムアウト時間を伸ばすことでエラーは解決します。
今回はタイムアウト時間を伸ばす方法をとります。
エラーログにも出ているように、デフォルトのタイムアウト設定値は`30秒`なので、これを伸ばしてやります。

タイムアウトの設定は`core.dagbag_import_timeout`の変数で設定されています。
https://airflow.apache.org/docs/apache-airflow/stable/configurations-ref.html#dagbag-import-timeout

MWAAの場合は、`airflow.cfg`が公開されておらず直接編集できないので、MWAAのリソースを作成する際に環境変数としてセットしてやる必要があります。

僕はCloud Formationにて作成していたため、template.yamlに以下のように追記しました。

```yaml
  MwaaEnvironment:
    Type: AWS::MWAA::Environment
    Properties:
      ・
      ・
      AirflowConfigurationOptions:
        # dagの読み込みタイムアウト
        core.dagbag_import_timeout: 60
```
Android x86とWindowsのデュアルブート構築(NVRAM編)

# 導入
Android x86を導入時にGRUB2をインストールする設定にしておけば、BIOSのブートシーケンスに自動的に登録される…はずなのだが、何故か私の環境では登録されなかった。
環境を作り直すたびにBIOSに登録する方法を忘れているので、備忘録を兼ねて記録する。

# 環境
Android x86(lineage OS)
cm-x86_64-14.1-r5.iso
通常のx86だとGrubが入らなかった。

# 手順
1. ***Windowsの回復ディスクから***、コマンドプロンプトを起動する。
1. 下記のコマンドでWindowsのブートマネージャをコピー。
   ```
   BCDEDIT /COPY {bootmgr} /d "Android x86"
   ```
   コピーが成功すると{コピー先のid}が表示されるので、{}まで含めてコピーしておく。

1. Grubのパスを登録する。
   ```
   bcdedit /set {コピー先のid} path \EFI\Android\grubx64.efi
   ```
1. `bcdefit /enum firmware`でGrubが正しく登録されているか確認する。

# 感想
面倒くさがってWindows上からコピーしようとしたのがダメだった。
コマンド上は成功しても、実態として反映されないので、この記事をまねる際にはお気を付けください。

# 参考サイト
https://solomon-review.net/uefi-windows-boot-manager-recovery/
git branch と毎回打つのはめんどくさい

# 背景
cuiでgitを使っていて、git branch だのgit checkout だのをしょっちゅう手打ちすることに気づきました。
gitコマンドは [wordle](https://www.nytimes.com/games/wordle/index.html)ではないので、最初の数文字だけでわかってほしいです。

つまり、
```
git br
```
とかでbranchを確認したいのです。

# 結論
gitリポジトリ内でこれを叩きます。
```
$ git config alias.br branch
```
すると以下ができるようになります。
```
$ git br
  aaa
  bbb
* master

```
# 何が起きたのか

.gitディレクトリ内部のconfigが更新されています


```
$ cd .git
$ ls
COMMIT_EDITMSG	hooks		objects
HEAD		index		refs
config		info
description	logs
```

```
$cat config
[core]
	repositoryformatversion = 0
	filemode = true
	bare = false
	logallrefupdates = true
	ignorecase = true
	precomposeunicode = true
[alias]
	br = branch
```
[alias]に br = branch という記述が追加されているのがわかります。

試しにここで、もうひとつエイリアスを追加してみます。
```
$git config alias.co checkout
$cat config
[core]
	repositoryformatversion = 0
	filemode = true
	bare = false
	logallrefupdates = true
	ignorecase = true
	precomposeunicode = true
[alias]
	br = branch
	co = checkout
```
記述が増えました。

### globalに設定する方法
globalオプションをつければ、適用範囲をリポジトリ単位からユーザー単位に広げることができます
```
$ git config --global alias.br branch
```
この場合は、ホームディレクトリ直下にある.gitconfigが更新されます。

```
$ cd ~
$ cat .gitconfig
[user]
	email = hogehoge@mail
	name = hoge
[alias]
	br = branch
```

# 参考

[Git の基本 - Git エイリアス](https://git-scm.com/book/ja/v2/Git-%E3%81%AE%E5%9F%BA%E6%9C%AC-Git-%E3%82%A8%E3%82%A4%E3%83%AA%E3%82%A2%E3%82%B9)
[git configの適用範囲](https://qiita.com/C_HERO/items/c35e679f0b03a5f06469)
観察力を鍛えるための絵画の感想アプリを作成しました

# はじめに
### 記事の目的
**ポートフォリオとして作成したWebアプリケーションの紹介記事です。**
こちらのURLで公開中です。
https://picture-app-9da4b.web.app/
また、Githubのコードはこちらです。
https://github.com/rickeysan/picture-app

## 作成した人
未経験からのエンジニア転職を目指しています。前回はPHP(Laravel)でポートフォリオとして習慣化アプリを作成しました。このとき、フロントエンドの知識不足を感じ、モダンなJavaScriptとReactの勉強をしています。

Reactのポートフォリオと検索すると、ToDoリストばかりが出てきてしまい、あまり面白い題材がないなと感じています。今回作成したアプリは、基本的な構造は投稿サイトのようなものですが、題材（テーマ？）にはこだわりました。

# 1. アプリの概要
絵画をじっくりと観察する（事実だけを抽出する）ことにより、観察力を鍛えることができるアプリです。元ネタは下記の本になります。
www.amazon.co.jp/dp/415209642X

著書によると、名画をじっくりと見ることは、観察力を鍛えることにつながり、この能力は日常生活や仕事でも役に立つということだそうです。また、さまざまなテクニックについて、ハンズオン形式で解説されており、充実した内容でした。名画を観察して、その絵から分かることを140字で要約し（文章として書き）、投稿できるアプリがあれば面白いのではと思いました。なかなか一人では絵画を客観的に見る訓練は難しいと考え、今回は絵画の感想（感想と言っても、客観的な事実だけを記述する）を投稿するアプリを作成しました。


## 2. アプリの特徴
なるべく気軽に試した欲しいという思いから、ユーザー登録などの機能は実装していません。アプリは投稿エリアと一覧エリアに分かれており、投稿エリアでは右側に絵画をランダムに表示しています。この絵画の情報は、メトロポリタン美術館のAPIを活用しました。その絵を見て、左側に名前とコメント（絵画から分かる客観的な事実）を入力できるフォームがあります。
![743D3F67-250B-47F1-ACC1-977098B23194.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1851421/b628ec99-78e4-811b-5bf9-d542dbefa8f8.jpeg)
また、投稿エリアではこれまでの投稿を一覧で見ることができます。また、簡単にですが、検索機能も作成しました。

![スクリーンショット 2022-03-27 18.58.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1851421/8ebf6b39-33a4-ea37-91bc-9e63f3471b19.png)


# 3. 使用した技術スタック
使用技術
tailwindcss 3.0.23
React 17.0.2 
TypeScript 4.6.2
axios 0.26.1
トロポリタン美術館の外部API
Firebase 

各々の技術を使ってみての感想を記述していきます。

tailwindcss
今回はせっかくReactを使っているので、相性が良いとされるTailwindCssと、そのフレームワークであるdaisyUIを用いました。今回CSSのフレームワークを久しぶりに使いました（Bootstrapも昔、簡単なWebページを作成するのに使ったくらいです）
daisyUIのドキュメントを見れば、豊富なコンポーネントがあり、コピーアンドペーストで作成できるのは、非常に便利だと思いました。アプリの規模が違いますが、前回の習慣化アプリはフレームワークを使わずCssを全て記述したので、フレームワークを使う恩恵は確かにあると感じました。ただ、tailwindCssのクラス名の扱いに慣れる必要があったり、HTMLが汚くなる（コードの見通しが悪くなる）などの欠点をありました。

React 
初めて自作アプリのReactで実装したので、かなり手こずりました。最初にコンポーネントの設計をきちんとしていなかったためか、あちこちでstateのバケツリレー（親コンポーネントからひ孫コンポーネントまで）が発生しました。あまり綺麗なコードではありませんが、Reduxなどを用いたstate管理の必要性がわかったのは良かったと思います。また、再レンダリングを抑えるなども今後の課題です。


Firebase
FirebaseはYouTubeの動画で勉強しました。書籍などは買わずに、公式サイトと動画で十分でしたが、CRUD処理まで開設している動画は、Youtubeでは日本語でなかったたので、海外の方（英語）の動画で勉強しました。また、FireBaseのデータベースは、MySQLではなく、NoSQLです。データベースがディレクトリ構造になっていることが特徴だと感じました。

axios + 外部API
今回初めて、アプリ制作に外部のAPIを使用しました。非同期処理は、APIで絵画の情報を取得する処理と、ユーザーの投稿データをFirebaseのDBに登録する部分に、async構文で記述しました。もっと大規模なアプリだと、非同期処理も多く出現し、処理の終了タイミングを考慮しなければならないのではと考えています。


TypeScript
TypeScriptに関しては、ちょっと変数の定義の時に型付けを行うのに使った程度で、もっと勉強が必要であると実感しました。
CloudEndure Migration とは

## 勉強前イメージ

正直はじめて聞いたサービス名

## 調査

### CloudEndure Migration とは

AWSのエージェント型サービスでクラウドへの移行を自動化するものです。
オンプレからクラウド、またクラウドからクラウドと様々な移行が可能です。
サービスとしては無償で利用できますが、CloudEndure利用時のインスタンスには費用が発生します。

### CloudEndure Migration の特徴

- 移行が簡単

物理でも仮想でも、クラウドでもどのインフラからでもアプリケーションの移行を可能にします。
AWSのどのリージョンでも使用できます。

- コスト削減ができる

CloudEndure Migrationは上記でも記載しましたが、無償で移行でき
前払いなども必要ないです。

- ダウンタイムを最小化できる

CloudEndure Migrationではソースマシンが自動的にコピーされますが
スナップショットの作成やディスクへの書き込みは行われないのでパフォーマンスへの影響は最小園に抑えられ、
マシンの再起動も不要です。
継続的にレプリがされるので、ダウンタイムを最小限にしてテストを行ったりできるので
カットオーバー(移行先にサーバを立ち上げること)の期間を短縮できます。

### 移行までの流れ

ざっくりと以下のようになります。

- CloudEndureのアカウントと上奥
- 移行先のサーバの立ち上げ、CloudEndureのエージェントをインストール
- エージェントがレプリするサーバにデータのコピーを送信
- レプリサーバは受け取ったデータを移行先サーバのEBSに書き込む
- カットオーバー実施後はスナップショットが作成されターゲットのEC2インスタンスにアタッチされる

## 勉強後イメージ

移行するのに似たようなサービス、SMSあったような気がする・・・
何が違うんだっけ？

## 参考

- [CloudEndure Migration を使ったAWS移行を計画する](https://dev.classmethod.jp/articles/migration_with_cloudendure/)
- [CloudEndure Migration AWSとは？移行を自動化する](https://www.skyarch.net/column/cloudendure-migration-aws/)
速習 .proto ファイルの書き方

# はじめに

.proto ファイルの記述をサクっと始めるための記事。
基礎的な内容のみに絞り記述する。

公式ドキュメントは [Language Guide (proto3)](https://developers.google.com/protocol-buffers/docs/proto3) である。

# .proto ファイルの書き方

## 構文

ファイルの全体像を先に示す。

```protobuf
syntax = "proto3";

package myapp;

service AddressBookService {
  rpc Search (SearchRequest) returns (SearchResponse);
}

message SearchRequest {
  string name = 1;
}

message SearchResponse {
  Person person = 1;
}

message Person {
  int32 id = 1;
  string name = 2;
  string email = 3;
}
```

### バージョン
バージョンを指定する。

```protobuf
syntax = "proto3;
```

### パッケージ
パッケージを指定する。
名前の衝突を避けるための名前空間の役割を果たす。

```protobuf
pakcage myapp;
```

### import
import 文で他のパッケージを読み込むことができる。
対象には `パッケージ名.オブジェクト` でアクセスすることができる。

```protobuf
import "../other_app/addressbook.proto";

message OtherApp {
	other_app.Person = 1;
}
```

### サービスとメソッド
サービスとはメソッドを論理的にまとめたものである。
メソッドは1つのエンドポイントとなる。

```protobuf
service AddressBookService {
  rpc Search (SearchRequest) returns (SearchResponse);
}
```

## スカラー型

型には主にスカラー型とメッセージ型の2つがある。
その他にはリスト、マップ、Enum などがある。

本記事ではではよく使いそうなスカラー型を抜粋する。
全てのスカラー型は [Scalar Value Types](https://developers.google.com/protocol-buffers/docs/proto3#scalar) に書いてある。

### 整数

```protobuf
int32
int64

float
double
```

### 文字列

```protobuf
string
```

### 真偽値

```protobuf
bool
```

### バイト文字列

```
bytes
```

## メッセージ型
メッセージ型と呼ばれる複数のフィールドを持つ型を定義できる。
コードを自動生成する際に、構造体やクラスとして書き出される。

```protobuf
message Person {
	int32 id = 1;
	string name = 2;
	repeated string items = 4;

    string phone_number = 5 [deprecated = true]

	reserved 3, 6 to 10;
	reserved "fax_number";
}
```

### タグナンバー
なぜ 1 や 2　を代入しているのかと感じるが、これはタグナンバーと呼ばれるものである。
コードのシリアライズ後のフォーマットでフィールドを識別するために使用される。

メッセージ内で一意である必要がある。

### 廃盤
運用中にフィールドを削除した場合、そのタグナンバーは廃盤とすることが望ましい。
再利用すると、フィールド識別上の不具合につながる可能性があるためである。

### reserved
廃盤であることを明示する識別子。

### deprecated
非奨励であることを明示するオプション。

## 列挙型
0始まりで記述する。

```protobuf
enum PhoneType {
	option allow_alias = true;

	UNKOWN = 0;
	MOBILE = 1;
	OFFICE = 2;
	SCHOOL = 2;
}
```

### allow_alias
同じ値に異なるラベルを割り当てることを許可するオプション。
ラベルを2つ以上指定した場合、エイリアスとして動作する。

## リスト
いわゆる配列である。

```protobuf
repeated string items = 1;
```

### repeated
リスト（配列）を表現する識別子。
スカラー型、メッセージ型のどちらにも適用可能。

## マップ
いわゆる連想配列である。

```protobuf
map<string, AddressBook> address_books = 1;
```

### キー
キーには整数値、文字列、真偽値のみ指定可能。

## Well Known Types
Build-in で事前定義された便利なメッセージ型郡。
日時、期間、Any などが揃っている。
[google.prorotbuf]((https://developers.google.com/protocol-buffers/docs/reference/google.protobuf)) パッケージで定義されている。

```protobuf
import "google/protobuf/timestamp.proto";
import "google/protobuf/duration.proto";
```

# 終わりに
gRPC の記事も書いたのでよかったらぜひ。

https://qiita.com/hiro_hira/items/a4e06a3e7e8c8dfef4df
C++でWindowsのGUIアプリケーションを作成する (.NET Framework)

# C++でWindowsのGUIアプリケーションを作成する
WinAPIを使わずに.NET Frameworkでアプリケーションを作成します。
他人が見てもわかるように書いてるつもりですが、一応自分用にメモ書きということで、

## 注意
- Visual Studio 2019
- .NET Framework
- C++
- Windows

## 手順
- 「CLR 空のプロジェクト (.NET Framework)」→「プロジェクト」→「新しい項目の追加」→「Windows フォーム」→ソリューションを閉じる→ソリューションを再度開く→5番目の手順のコードをコピペして編集

### 1.「CLR 空のプロジェクト (.NET Framework)」選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1015774/290f614c-c7fd-5796-7bc4-dd1c199257fc.png)
「CLR 空のプロジェクト (.NET Framework)」を選択する。
※コンソールアプリじゃないですよ

### 2. 項目を入力して作成ボタンをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1015774/7b952c40-4b81-fc54-fe4e-e7ba10ac586f.png)
それぞれ項目を入力してから「作成(C)」をクリックする。
ここでは.NET Framework 4.5にしていますが、そちらで決めてください。

### 3. 「新しい項目の追加(W)...」を選択して「Windows フォーム」を追加する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1015774/b5756ced-7fa0-fffc-27f9-fe97ebd8fecf.png)
メニューバーから「プロジェクト(P)」→「新しい項目の追加(W)...」を選択する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1015774/56accd7d-20f1-e4a3-aacc-ce4cc894402c.png)
「Windows フォーム」を選択して追加する。

### 4. 一旦ソリューション閉じて再度開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1015774/e4f221df-c782-d47d-060e-ec5fa545321a.png)
このようなエラーが出ると思われるのでソリューションを閉じると治る。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1015774/7c0496f6-672f-43bf-ebce-9753c89baeb6.png)
メニューバーの「ファイル(F)」→「ソリューションを閉じる(T)」を選択

### 5. MyForm.cppを編集
MyForm.cppを以下のように編集した。
```cpp
#include "MyForm.h"

using namespace Project1;

int WinMain() {
	MyForm^ form = gcnew MyForm();
	form->ShowDialog();
	return 0;
}
```
これをしないとエントリーポイントの関数が存在しないため、起動できない。
using namespaceのProject1については使うネームスペース名(プロジェクト名)にすること。
WinMain()ではなくmain()で関数定義するとコンソールが表示されるので注意

## 終わりに
これで楽しくC++でGUIがつくれちゃいます！！

## 参考サイト
- https://syokado.exblog.jp/29398798/
- http://y-okamoto-psy1949.la.coocan.jp/VCpp/OnVSCpp2019/
【AWS環境構築メモ⑥】ACMでSSL証明書を発行する

## 0.はじめに

**ACMでHTTP化に必要なSSL証明書を発行します。**

- **ACM**
AWS Certificate Managerの略。SSL証明書発行サービス。

![スクリーンショット 2022-03-27 17.27.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/891391/9354f572-1e83-b467-d3a2-ecfec2717a72.png)

## 1.前回の記事

**[【AWS環境構築メモ⑤】EC2インスタンスを作成する](https://qiita.com/yuuichimizuta/items/279bef2573c30b4175a5)**

## 2.前提条件

- **AWSアカウント作成済み**
- **リージョンはアジアパシフィック(東京) ap-northeast-1**
- **VPC作成済み**
- **セキュリティーグループ作成済み**
- **EC2インスタンス作成済み**

## 3.作成手順(サマリー)

|順番|手順|
|---|---|
|1|ACMでSSL証明書発行|

## 4.作成手順

### 1.ACMでSSL証明書発行

![スクリーンショット 2022-03-27 17.53.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/891391/92ae13bb-0280-9b16-5be9-e4bd67bb6d7d.png)

- **[証明書をリクエスト]をクリックする**

![スクリーンショット 2022-03-27 17.53.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/891391/44c018db-b5e4-9141-f165-1fe75a0b7640.png)

- **[パブリック証明書をリクエスト]を選択**
- **[次へ]をクリックする**

![スクリーンショット 2022-03-27 18.13.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/891391/5d2ce853-3044-2243-2d07-5b7bc5cb1a69.png)

- **ドメイン名**
  - Route53に登録してある対象のドメイン名を指定
- **検証方法を選択**
  - [DNS 検証 -　推奨]を選択する
- **タグ**
  - 分かりやすいタグを任意で追加
- **[リクエスト]をクリックする**

**画像準備中。。。**

- **検証用のCNAMEレコードが発行される**
- **[Route53でのレコードの作成]をクリックし、レコードを作成する**
- **以下の状態になれば成功です**
  - 状況が検証保留中から発行済に変わる
- **Route53のレコードにCNAMEが追加されているのを確認**

**参考 : [ACMでSSL証明書を発行してみた](https://zenn.dev/mn87/articles/90609fffd8c634)**

<font color="Green">**SSL証明書の発行が完了しました**</font>

## 5.最後に

HTTPS化させる準備が整いました。

**次回はELBの作成を行います。**
**次回 : [【AWS環境構築メモ⑦】ELBを作成する](https://qiita.com/yuuichimizuta/items/d7dabc1b4b21de0e7e60)**

## 6.参考

https://zenn.dev/mn87/articles/90609fffd8c634

https://mseeeen.msen.jp/access-your-ec2-web-server-via-elastic-load-balancing/
where文が思い通りに動かない

# 目次
[1.where文のちょっとした違い](#1-where文のちょっとした違い)
[2.大前提条件](#2-大前提条件)

Laravelの勉強で少し躓いた部分があったのでアウトプットします。

# 1. where文のちょっとした違い

ブログサイトの、ブログ検索機能を作るにあたり、
**「公開中の記事の中から、タイトルか本文が検索ワードと一致した記事だけを表示する」**
という where文 を書きました。
```php
$posts = Post::where('title', 'like', "% {{$request->search_word}} %")
->orWhere('content', 'like', "% {{$request->search_word}} %")
->where('is_published', 1)
->get();
```

しかしこれだと思い通りの動きをしてくれず、非公開中の記事まで表示されてしまいました。
`->where('is_published', 1)`この部分が反応していないのです。

# 2. 大前提条件

色々調べた結果、上記の書き方は
**「タイトルが検索ワードと一致する記事、
　もしくは本文が検索ワードと一致する記事か公開中の記事。」**
という風になっていました。
簡単に言うと、**A or ( B && C )** ということです。

ただ、実装したいのは、**A && ( B or C ）** なので、

```php
$posts = Post::where('is_published' ,1)
->where(function($query){
 $query->where('title', 'like', "% {{$request->search_word}} %")
 ->orWhere('content', 'like', "% {{$request->search_word}} %")
})->get();
```

こうするのが正解です。

`where('is_published' ,1)` を大前提条件として、その中で条件に合った記事を取得するということです。


ただ正直、
**「最初の書き方のまま `->where('is_published', 1)` を一番最初に持ってくればいいんじゃないの！？」** 
と思いましたが、わかりやすくて正しい書き方はこちらのようです。
ただ動く書き方ではなく、正しい書き方ができるようにならなきゃな〜〜。
今日のアウトプットは以上です！
【ソート】昇順と降順の覚え方

昇順と降順がややこしくてどっちだったっけ？とよくなるので、メモついでに。

# 覚え方

昇順は「小さいのが上」
降順は「大きいのが上」
古い日時は小さく、新しい日時は大きい


# 🔼 昇順 ASC

Ascending order

### 「小さいのが上」

- 数字
    - 1
    - 2
    - 3

- 名前
    - apple
    - bed
    - cat

- 日時
    - 1/1
    - 2/1
    - 12/31


# 🔽 降順 DESC

Descending order

### 「大きいのが上」

- 数字
    - 3
    - 2
    - 1

- 名前
    - cat
    - bed
    - apple

- 日時
    - 12/31
    - 2/1
    - 1/1
OCIへログインしてみよう

# 手順
１．OCIログインURLにアクセスする
２．ログイン情報を入力し、ログイン


## 1.OCIログインURLにアクセスする
①以下のURLにアクセスする
https://cloud.oracle.com
②「Cloud Account Name」にテナント名を入力し、「Next」ボタンをクリックする
テナント名：christmaseve
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562390/8e40f105-6776-57f5-0623-2183f63c6a1c.png)

③「Continue」をクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562390/95227807-a78d-0736-4c84-f43d7d47cd51.png)

## 2.ログイン情報を入力し、ログイン
④ユーザー名とパスワードを入力し、サインインする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562390/cee8cfcd-943e-b8b2-94df-e8f16f1a347d.png)

⑤OCIコンソールのホーム画面が表示される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562390/13b75c85-9fe1-ea26-4872-ca3dfd897f35.png)

## 参考サイト

https://oracle-japan.github.io/ocitutorials

https://oracle-japan.github.io/ocitutorials/beginners/getting-started/
PHPでSQLのSELECTを使用する方法

・PHPでSQLのSELECTを使用する方法
①query構文でSELECT
②whileとfetch_assocで各レコード毎に操作


画像の通り、dataというテーブルがあったとする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2596732/22affa92-5b32-1c40-0468-d7013742cbee.png)

例)
```
<?php
$db = new mysqli("localhost:8889", "root", "root", "mydb");
$records = $db->query("select * from data");
if ($records) {
    while ($record = $records->fetch_assoc()) {
        echo $record['name'] . "<br>";
    }
} else {
    echo $db->error;
}
?>

```

補足画像)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2596732/9412cc7f-031e-8f63-fe39-051b650ef16a.png)

結果)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2596732/18107a06-4f65-ac28-9037-5fda6b385f11.png)
GitHub Issue から ATOM Feed を作る

# 背景

あるリポジトリの Issue を RSS リーダーでチェックしたい。

どうやら Issue 単独で RSS は配信していない模様。
以下によると Wiki のフィードはあるらしい。

https://a244.hateblo.jp/entry/2017/09/24/101922

ないものは仕方ないので、自前で Issue からフィードを作成してみる。

# 方法

## 実装

愚直に GitHub API で Issue を取得してフィードを生成する。
フィードの生成には FeedGenerator を利用した。

https://pypi.org/project/feedgen/

```python
from feedgen.feed import FeedGenerator
import json
import os
import requests


USER = os.environ['USER']
REPO = os.environ['REPO']
REQUEST_HEADER = {
    'Accept': 'application/vnd.github.v3+json'
}
REQUEST_URI = f'https://api.github.com/repos/{USER}/{REPO}/issues?per_page=30'

response = requests.get(REQUEST_URI, headers=REQUEST_HEADER)
issues = json.loads(response.text)

feed = FeedGenerator()
# feed.id などフィードの設定をする

for issue in issues:
    entry = feed.add_entry(order='append')
    # entry.id などエントリの設定をする
    entry.content(content=issue['body'], type='html')

feed.atom_file(f'{USER}/{REPO}/atom.xml')
```

## 実行結果

https://github.com/octocat/hello-world/issues の ATOM Feed を作ってみる。

```xml
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <id>tag:issue2atom,2006-01-02:/octocat/hello-world/issues</id>
    <title>octocat/hello-world - GitHub Issues</title>
    <updated>2022-03-26T15:02:35.517122+00:00</updated>
    <author>
        <name>octocat</name>
    </author>
    <link href="https://github.com/octocat/hello-world/issues" rel="alternate" />
    <generator uri="https://lkiesow.github.io/python-feedgen" version="0.9.0">python-feedgen</generator>
    <subtitle>GitHub Issues of octocat/hello-world</subtitle>
    <entry>
        <id>tag:issue2atom,2006-01-02:/octocat/hello-world/issues/2237</id>
        <title>Check This out</title>
        <updated>2022-03-25T05:46:38+00:00</updated>
        <content type="html">&lt;p&gt;This is a test body&lt;/p&gt;</content>
        <link href="https://github.com/octocat/Hello-World/issues/2237" rel="alternate" />
        <summary>This is a test body...</summary>
        <published>2022-03-25T05:45:05+00:00</published>
    </entry>
    :
</feed>
```

生成された ATOM を RSS リーダーの Inoreader に食わせた結果。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49525/4dab48ff-e312-74c0-2ce6-11731b5adc24.png)

# ポイント

## Markdown を HTML 化

上記コードでは生の Markdown が配信されてしまうため、HTML に変換する。

```python
import markdown
from mdx_gfm import GithubFlavoredMarkdownExtension


body_html = markdown.markdown(
    issue['body'], extensions=[GithubFlavoredMarkdownExtension()]
)
```

GitHub Flavored Markdown (GFM) の Extension を使っているが、メンテされなくなっているようで少し心配。

https://github.com/zopieux/py-gfm

なお、`feedgen.entry.content()` はデフォルトで HTML Escape をしてくれる点に注意。これに気付かず、自前で `html.escape()` したせいでうまく表示されないことがあった。

# すぐ使いたい

GitHub Actions 化した。
Workflow の schedule で定期的に ATOM を生成し、GitHub Pages に公開ができる。

https://github.com/tsubasaogawa/issue2atom

https://github.com/marketplace/actions/issue2atom
【Java】modelMapperでList<A>⇔List<B>, String⇔LocalDate, String⇔LocalDateTimeを変換する。

# 参考

https://www.baeldung.com/java-modelmapper-lists

# List\<HogeEntity\> → List\<HogeDto\> のマッピング
```java
List<HogeEntity> entities = // DBからHogeEntityリスト取得
List<HogeDto> dtos = modelMapper.map(entities , new TypeToken<List<HogeDto>>() {}.getType());
```

# String ⇔ LocalDate のマッピング
```java
// String to LocalDate
mapper.addConverter(
    new AbstractConverter<String, LocalDate>() {
        @Override
        protected LocalDate convert(String source) {
            if (source == null) {
                return null;
            }
            DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            return LocalDate.parse(source, format);
        }

    }
);

// LocalDate to String
mapper.addConverter(
    new AbstractConverter<LocalDate, String>() {
        @Override
        protected String convert(LocalDate source) {
            if (source == null) {
                return null;
            }
            DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            return source.format(format);
         }
    }
);
```

# String ⇔ LocalDateTimeのマッピング
```java
// String to LocalDateTime
mapper.addConverter(
    new AbstractConverter<String, LocalDateTime>() {
        @Override
        protected LocalDateTime convert(String source) {
            if (source == null) {
                return null;
            }
            DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            return LocalDateTime.parse(source, format);
        }
    }
);

// LocalDateTime to String
mapper.addConverter(
    new AbstractConverter<LocalDateTime, String>() {
        @Override
        protected String convert(LocalDateTime source) {
            if (source == null) {
                return null;
            }
            DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            return source.format(format);
        }
    }
);
```
【勉強メモ】オプショナルバインディング　swift

このページに訪れていただきありがとうございます。
このページでは実務でswiftを触ることが増えてきたので、勉強の一貫でオプショナルバインディングをアウトプットしました。
目新しい情報はないのですが、最後までお読みいただけますと幸いです。

## 前提の知識
・swiftにはオプショナル型とそれ以外の形がある
・swiftにはnilという何もないという値がある。(null的な？)
・nilはオプショナル型にしか格納できない値
・オプショナル型に格納されている値を使用する場合はアンラップする必要がある。
・アンラップには強制的な方法と安全な方法がある。
・安全なアンラップがオプショナルバインディング

## オプショナルバインディングとは
optional型の値を安全に取り出す方法
ifやguardを使って変数がnilでないことを確認して、処理をする方法です。

## オプショナルバインディングの書き方

### if を使った方法
```
var optionalNum:Int? = 1
if let num = optionalNum {
  nilでないときの処理(numを使うことでアンラップされた状態として使用することができる)
} else {
　nilのときの処理
}
```
### guardを使った方法
```
var optionalNum:Int? = 1
guard let num = optionalNum else {
  nilのときの処理
  return
} これ以降がnil出ないときの処理を記述することができる。
```
ifとguardの違いとしては、ifはアンラップされた定数はifブロックの中でしか使用することができない。
一方でguard文では外でも使用することができる。
## 【関係知識】オプショナル型の宣言方法
```
var num : Optional<型> =　格納する値
var num:Int?
```
## 【関係知識】強制的なアンラップのやり方
オプショナル型の変数を取り出すときに!をつけることでアンラップすることができる。
```
var num:Int?
num = 1
var total = num! + 1
print(total) //2となる
```

## なぜ強制的アンラップを注意しないといけないのか
強制的なアンラップはnilが入っていようがいないが強制的にアンラップするため、確実にnilが入っていないときのみ利用できる。
そのため、nilが入っていた場合はプログラムにエラーが出てしまう。
よくつかうのは@IBOutletで部品を宣言するときに使う印象


参考文献
https://mogi0506.com/swift-optional/
https://thinkit.co.jp/article/13489