OmniAICreator/Qiita-1.07M huggingface dataset:
CSSで近似スーパー楕円 (Approximated superellipse by CSS)


スーパー楕円に近い形をCSSでシンプルに表現することができたので備忘録。

完全なスーパー楕円はCSSのみで実現するのは非常に難しく、Web上では擬似要素を用いて近似した形をつけるなどの手法でスーパー楕円を表現しているものが散見される。これらは曲線の接合部分が環境によっては不自然になったり、`image`要素などをマスクするのに使いづらかったりと問題点が多い。

この手法では、CSSの`border-radius`プロパティと`transform`プロパティにより変形することで、擬似要素を用いない単一の`div`要素で近似スーパー楕円を表現している。

<p class="codepen" data-height="265" data-theme-id="dark" data-default-tab="css,result" data-user="kozycorner" data-slug-hash="ExNVywd" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="Approximated super ellipsox by CSS">
  <span>See the Pen <a href="https://codepen.io/kozycorner/pen/ExNVywd">
  Approximated super ellipsox by CSS</a> by Kozy a.k.a. Tab (<a href="https://codepen.io/kozycorner">@kozycorner</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

## 説明

斜めのスーパー楕円に見える図形をなんとか`border-radius`で描画できたので、`transform`の`rotete`プロパティにてまっすぐに見えるようにしている。

![borer-radius.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326374/748e81ab-9ea4-6b99-c711-d4cf45bc8312.png)

`rotete`しているので、`image`要素を配置してアイコンにする場合などは中の要素に対して逆向きの`rotate`を指定するとよい。

## 資料

### スーパー楕円の式

```math
\left| \frac{x}{a} \right| ^{n} + \left| \frac{y}{b} \right| ^{n} = 1
```


$n$：スーパー楕円の丸みを決める値
$a,b$：大きさ

$n$は$2$のときが楕円（$a=b$なら正円）で、それより大きいほど長方形（$a=b$なら正方形）に近づく。理想的なスーパー楕円は$n=2.5$とされているらしい。

### 今回近似したスーパー楕円との比較

薄い赤色でオーバーレイしているのが今回CSSで近似したスーパー楕円。$n=2.3$のスーパー楕円とほぼ同じことが確認できる。

![superellipse.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326374/2f2ac23c-6817-2ce5-4a1a-66b37cbe62c1.png)

```math
\left| x \right| ^{n} + \left| y \right| ^{n} = 1
```

## 課題（CSSのみでは解決不可能かも）

- $a=b$（縦横が同じ大きさ）のものしか作れない
- $n$の値を変更した形は試した限りでは実現できなかった（本当は$n=2.5$を目指してた）

高度なことがしたければ大人しくJavaScriptかSVGを使う方が早い（戒め）

## 参考

- [CSS Superellipse](https://sbx.webflow.io/css-superellipse)
- [Superellipse - Wikipedia](https://en.wikipedia.org/wiki/Superellipse)
- [border-radius - CSS: Cascading Style Sheets | MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/border-radius)
さらっと「これどれくらいでできる」って聞かれたときの対処法

#「そっすねー３ヶ月くらいじゃないすかー？」

根拠のない予測は地獄の始まりです。

「こんなはずじゃなかった」の連発でもともと想定していた期間の
2倍、3倍の時間がかかってしまったなんて事にもなりかねません。

どれくらいの時間で終わるか考えることを「工数見積り」とか「工数予測」などといったりします。
私が最初にエンジニアとして働いた環境では工数見積りの方法について
誰も知見を持っていなかったのでなんどか痛い目にあいました。

書籍を読んだり、外部のエンジニアに話を聞いたりしながら工数見積り術を学んで
小規模なプロジェクトであれば大体ちゃんと予想できるようになってきたので
ざっくりとした工数見積りのコツを昔の自分のような人にお伝えできればと思います。

#目次
- なぜ工数見積りは難しいのか。
- 最速最小のプロトタイプを作る。
- 影響範囲を考える。

#なぜ工数見積りは難しいのか。

##1. 依頼者が何を欲しいのか最初の段階では依頼者も知らない。
嘘みたいなホントのよくある話です。
相手がソフトウェアの専門家でない場合、完成品の要件はおろか、画面イメージまで定まっていません。
この段階で完璧な要件定義をしようとすると依頼者はその場ではOKを出すものの
完成品をみてから根底をひっくり返して来ることがあります。
ソフトウェアは一回作ったら最利用できるため、
新規の開発はほぼ必ず何か今までにない事が含まれています。

##2. 人間は未来を正確に予測できない。
基本的にソフトウェア開発は今まで作った事がないものを作る事になります。
やった事がないことがどのくらいかかるかという予測はとても難しいです。
過去に似たようなことをやった事がある場合でも完全に再利用可能なものでなければ
思わぬ落とし穴がある事があります。
以前使ったライブラリの思わぬところにバグがあったり、
今回使う事になったライブラリとのバージョン不整合があったりします。
また、データを受け取ったら中身が言われていた物と違ったり、
開発環境のデータと本番環境のデータが違うといったこともあり得ます。


##3. 性格と経験によってバラツキが生じる
慎重な性格の人や、過去に見積りで失敗して痛い目にあった人は余裕を持った予測をする傾向があります。
余裕を持って予測することは非常に大事ですが度が過ぎるとその人の評価が下がったり
プロジェクトがなくなってしまい、ビジネスが出来なくなってしまいます。
チームで作業する場合、人の予測を理解しないまま鵜呑みにしないほうがいいでしょう。

#最速最小のプロトタイプを作る。

##1. 不確実性の一番大きいところを潰す。
プロジェクトを始める前が最も見積りが難しく予測した工数が実際の工数と前後してしまう可能性が高いです。
より細かい要件定義や、設計、実装を進めていく中で徐々に正確な予測ができるようになります。

予測が難しい事、不確実性が時間とともに減少していく様を不確実性コーンと呼ぶ事があります。
工数見積りの精度がプロジェクトの始めで依頼者に理解して貰う際に役に立つことがあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181998/cbeb7084-51b4-e305-5fa0-817f922a900c.png)

プロトタイプを作ることはこの不確実性コーンの一番大きい左側から右側に進めていく作業です。
環境の構築、技術的に最も難しい所の検証までこの段階でできると後の予測が楽になってきます。

##2. 作っているものが正しいか確認できる。
プロトタイプを作ることで依頼者との認識のすり合わせがしやすくなります。
全体の画面イメージとあわせて期待するアウトプットの認識をすり合わせましょう。
正確な要望、要件の理解が正確な見積りの最低条件です。


#影響範囲を考える。

##1. システムの影響範囲
ソフトウェアの多くはフロントエンド(UI）、バックエンド（API, データベース）を持っていて
工数を予測する作業はどの範囲に変更が必要なのかを見極めましょう。
この方法はプロジェクトの全貌が見えていないのに予測しなければならない際に有用です。
UIのみ変えればいい場合とUIに加えてビジネスロジックに変更がある場合は
UIのみの場合と比べて2~4倍時間が必要などというと納得してもらいやすく、
作業を依頼する側も概算を立てれます。

また多くの開発されるソフトウェアは外部のシステムと連携しています。
既存のデータベースに変更を加えたり、他システムで使っているAPIを利用したりすることがあります。
これにより必要な工数が長くなることもあれば短くなることもあります。
どちらにせよ外部システムとの連携は工数に大きく影響してくるので
必ずできるだけ細かく仕様を確認するようにしましょう。

##2. 人の影響範囲
プロジェクトによっては自分のチームのみで完結しない仕事もあります。
そもそもの責任者が営業サイドであったり、必要なデータは多部署が持っていたり、
あったこともない人が要望を出してくることがあります。

依頼者がいってきたことをただ聞いてやっていると思わぬところで今までやってきた作業が
全く意味がないものになってしまうことも世の中では珍しくないことなので
依頼者の後ろに誰がいるのか、依頼者とコミュニケーションを取りながら予期せぬどんでん返しを
極力無くしていきましょう。

また、データの連携は送るだけと思っていても意外と時間がかかる事があるので
期間を長めに見積もりつつ最優先で対応することをおすすめします。

---
以上、いかがでしたでしょうか。
今回は正確に工数を予測することを主眼として書きましたが、
そもそも必要のないものを作らず、利用者に対して価値のあるものを作るために
要件定義をしっかりする事も重要です。

これを読まれた方が私のように自分の過去の気楽な予想に苦しめられることの無いように、
また価値ある製品を作っていくために少しでも役に立てば嬉しいです。
Raspberry Pi Picoを買ってLチカするまで 前半 : 環境設定

# 目次
## 前半
- Raspberry Pi Picoを買ってみた
- Windows Subsystem for Linux (WSL)の導入

## 後半
- WSLでのRaspberry Pi Pico開発環境の設定
- Lチカプログラムの書き込み

<a id="anchor1"></a>
# Raspberry Pi Picoを買ってみた
2021/02/01 [Raspberry Pi Pico](https://www.raspberrypi.org/products/raspberry-pi-pico/)を以下で購入、なかなか小さくていい感じ
https://www.switch-science.com/catalog/6900/

上 : Raspberry Pi Zero, 下 : Raspberry Pi Pico
![RPiPicoAndRPiZero.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1039974/751385a8-6e3b-3e2d-ea0c-0158d2a16cf8.jpeg)

# Windows Subsystem for Linux (WSL)の導入
手元で気軽に触れるPCがWindows機しかなかったため、WSLで開発する
https://docs.microsoft.com/ja-jp/windows/wsl/install-win10

## WSLとは
https://docs.microsoft.com/ja-jp/windows/wsl/about より引用：

> Windows Subsystem for Linux を使用すると、開発者は、仮想マシンのオーバーヘッドなしで、ほとんどのコマンド ライン ツール、ユーティリティ、アプリケーションを含む GNU/Linux 環境を変更せずそのまま Windows 上で直接実行できます。

## WSLの有効化
1.［スタート］→［設定］に移動
2.［アプリ］に移動
3.「関連設定」→［プログラムと機能］をクリック
4.［Windows の機能の有効化または無効化］にチェックをつける

## Linuxディストリビューションのインストール、設定
- Microsoft StoreでUbuntu20.04を検索する
- 入手、インストールを行う
- インストール後立ち上がったコンソールにて、ユーザーネームとパスワードを設定する

以上でWSLの設定までは完了、後半ではRaspberry Pi Picoの開発環境などをインストールしてみます
Web Serial API を最短の手順で試したくてやったこと（micro:bit を利用）

以下の記事を見かけて、記事のトピックの 1つになっている「[Web Serial API](https://www.chromestatus.com/feature/6577673212002304)」がとても気になり、それをサクッと試したくなって進めた手順のメモです。

●Webアプリがジョイコンなどに対応する「WebHID」、NFCタグを読み書きする「Web NFC」、シリアルポートで通信する「Web Serial」など、Chrome 89ベータではデフォルトで有効に － Publickey
　https://www.publickey1.jp/blog/21/webwebhidnfcweb_nfcweb_serialchrome_89.html

## 準備
とりあえず、シリアル通信で文字列か何かの値を送る元を準備して、そのデバイスと PC をつなぎ、以下のサンプルページを利用すれば最速で試せるだろう、と思って進めました。

https://googlechromelabs.github.io/serial-terminal/
![serial.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/68516f62-99b8-3a1d-d5b2-f73907d1a9fb.jpeg)

PC にデータを送る元として使えるものは、うちにあるものだと M5Stackシリーズや Arduino系のデバイスもありましたが、プログラムをサクッと準備して書き込める micro:bit を今回は利用することにしました。

それと Web Serial API について、冒頭に掲載した記事の記載で、ベータ版で提供されている Chrome の release 89 にならないとデフォルトで使えない（2021年2月3日時点）という話がありました。
それについて、「[Chrome Platform Status」の該当箇所](https://www.chromestatus.com/feature/6577673212002304
)を見ると、その通りの情報が書かれているのも再確認できました。

![利用可能なバージョン.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/1d32f079-8d5c-a10c-9e15-5f2c70e88bc2.jpeg)

安定版は release 88 でデフォルトで利用できるバージョンではないものの、この機能を有効化するための手順を踏めば良いというのはありましたが。
自分は別の選択肢となる、release 89 で提供されているベータ版を使って試す、というやり方にしました。

### micro:bit にプログラムを書き込む
micro:bit でシリアル通信を実行するためのプログラムを用意します。

micro:bit にプログラムを書き込むために「[Microsoft MakeCode for micro:bit](https://makecode.microbit.org/)」を使いました。ブラウザ上でプログラム作成からプログラム書き込みまで手軽に行うことができるためです。

プログラムの内容はシンプルに、加速度センサーの値をシリアル通信で一定時間ごとに書き出す、というものにしました。
![マイクロビットのプログラム.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/3c8ce46c-8750-6dd5-4b36-24b28b2e1277.jpeg)

このプログラムを micro:bit に書き込みます。

## 動作している様子
micro:bit の準備ができたら、それを PC に USB につないだままにして、冒頭に記載していた以下の URL にアクセスします（今回は Chrome のベータ版 にて）。
　https://googlechromelabs.github.io/serial-terminal/

あとは、画面左上の「Connectボタン」を押して、その後に出てきた画面で micro:bit のつながったシリアルポートを選択します。
そうすると、以下のツイートの動画のように、Chrome で開いた Webページ上で、一定の時間間隔で数字が表示されていきます。
さらに、micro:bit を傾けると、その数値が変化しているのが分かるかと思います。

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">Web Serial API のサンプルを試してみるだけの動画。<br><br>micro:bit からシリアル通信で、加速度センサーの値を書きだしたものを、Web上に表示している。 <a href="https://t.co/fkRzXfOz0J">pic.twitter.com/fkRzXfOz0J</a></p>&mdash; you (@youtoy) <a href="https://twitter.com/youtoy/status/1356936812514529283?ref_src=twsrc%5Etfw">February 3, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

無事に試すことができました。

## その他
後で見てみる！

●Getting started with the Web Serial API
　https://codelabs.developers.google.com/codelabs/web-serial#0

## 追記
その後、Web Serial API の仕様を読んで、必要そうな処理を抜き出してきて、以下のように書き込み処理を実装してみました。

●Web Serial API を使った micro:bit への値の書き込み - Qiita
　https://qiita.com/youtoy/items/f77dc205e817f31a4e18

↓こちらの仕様を読みました
●Web Serial API
　https://wicg.github.io/serial/

## 追記2
読み取り処理の実装も試して、うまくいきました。

●Web Serial API を使って micro:bit からセンサーの値を読み取る（途中段階まで） - Qiita
　https://qiita.com/youtoy/items/9606c58369796a65f8f5
●Web Serial API を使って micro:bit からセンサーの値（XYZ）を読み取る＆リアルタイムなグラフ化 - Qiita
　https://qiita.com/youtoy/items/6394a5570ddd54a2ce87
【HTML】iframeのsandbox属性について

#プログラミング勉強日記
2021年2月3日
[昨日の記事](https://qiita.com/mzmz__02/items/c74a388c8ade33d7b4c0)でiframeの使い方についてまとめた。しかし、iframeで外部のWebページを埋め込むにはセキュリティ面でリスクがある。セキュリティを高めるために利用できる設定であるsandbox属性についてまとめる。

#sandboxとは
　サンドボックスは直訳すると「砂場」で、砂場で遊んでいる子供が安全であるようにサンドボックスはコンピュータの中で構築された安全な仮想環境のことでる。他と切り離されて、問題が起きてもその外側には影響が出ないようになっている。つまり、サンドボックスは攻撃されることを前提とした仮想環境であり、コンピュータをマルウェアから感染を防ぐ安全である仕組みのことである。

#sandbox属性でサンドボックス化する
　iframeではsandbox属性を指定することで、埋め込みコンテンツができることに制限をかける。

```html:使い方
<!-- すべての制限をかける -->
<iframe src="~" sandbox></iframe>
<!-- フォーム送信だけ許可 -->
<iframe src="~" sandbox="allow-forms"></iframe>
<!-- フォーム送信とポップアップを許可
     (複数の制限を解除するときには半角スペース区切り) -->
<iframe src="~" sandbox="allow-forms allow-popups"></iframe>
```

##sandbox属性の属性値
　sandboxだけ書いた場合には、以下の項目はすべて許可されなくなる。<b>allow-scriptsとallow-same-originの2つの値を指定すると、sandbox属性が無効になる</b>ので注意する。

| 属性値 | 説明 |
|:--:|:--:|
| allow-downloads-without-user-activation | ユーザーによる操作のないダウンロードを許可 |
| allow-scripts | スクリプト（ポップアップを除く）の実行を許可 |
| allow-forms | フォームからのデータ送信を許可 |
| allow-popups | ポップアップ・ウィンドウの表示を許可 |
| allow-same-origin | 通常のオリジンと同じポリシーを適用 |
| allow-modals | モーダルウィンドウを許可 |
| allow-orientation-lock | 画面の向きのロックを許可 |
| allow-pointer-lock | Pointer Lock API（マウスカーソルの固定）を許可 |
| allow-presentation | プレゼンテーションモードを許可 |
| allow-popups-to-escape-sandbox | 埋め込みコンテンツから別のウィンドウを開いたときに、sandboxの制限を引き継がないようにする |
| allow-top-navigation | 埋め込み元のページ遷移の操作を許可 |

#参考文献
[iframeのセキュリティを高めるsandboxの設定](https://blanche-toile.com/web/iframe-sandbox)
[サンドボックスとは？その仕組みやメリットデメリットについて徹底解説](https://cybersecurity-jp.com/security-measures/30234)
[Unity]Addressableキー存在確認　なぜかAddressableのデータを読み込めない？

この記事は伝えたいことが１個しかありません。
#Addressableのバージョンは1.16.10です

１．Addressableのキーの存在確認。
２．Addressableが読み込めていない。

<h5>１．Addressableのキーの存在確認。</h5>
　　専用のAPIあったら教えてほしい。
　　keyは大文字小文字の区別をつけないとだめです。

```csharp:keycheck.cs
using UnityEngine.ResourceManagement.ResourceLocations;

public static bool Exist<T>(string key, out IResourceLocation location)
{
    location = null;
    foreach (var local in Addressables.ResourceLocators)
    {
        local.Locate(key, typeof(T), out IList<IResourceLocation> resourceLocations);
        if (resourceLocations != null)
        {
            if (resourceLocations.Count >= 2) DebugS.LogWarning($"key = {key} type = {typeof(T).Name} is Find {resourceLocations.Count} datas.");
            location = resourceLocations[0];
            return true;
        }
    }
    return false;
}

```

<h5>２．Addressableが読み込めていない。</h5>
　１．のキーチェックでタイミングによってはデータをチェックできたりできなかったりしてました。
　チェックができない理由はAddressableが初期がされる以前にアクセスしているから。
　回避方法は「await Addressables.InitializeAsync().Task;」とかやった後にチェックする。
　当方UniTask使いゆえサンプル書いたけどあとはフィーリングでなんとかして！

```csharp:LoadData.cs
public async UniTask LoadInitialData(string KeyName)
{
    await Addressables.InitializeAsync(); // ここ重要
    if (Exists<T>(keyName, out var location))
        instance = await Addressables.LoadAssetAsync<T>(location);
    if (instance == null) instance = CreateInstance<T>();
}

```

<h2>もしかしてまだAddressable正式版じゃない説ある！ある？</h2>
そもそもなんでAddressables.LoadAssetAsync<T>(keydata)で存在しなかったらInvalidExceptionになるんだよおかしいだろ！例外キャッチできないし、そも例外はスマートじゃないだろいい加減にしろ！


<h2>コメントで教えてもらいました</h2>
存在確認が良い感じにいけたので共有を兼ねてここにも張り付けておきます！

```csharp:Hoge.cs
    public static async UniTask<bool> Exists(string pathToAsset)
        => (await Addressables.LoadResourceLocationsAsync(pathToAsset)).Any();
```
@taishi-matsumuraさんありがとうございます！
Depth画像の特定のピクセルにアクセスしたいとき

## 経緯
最近、Depth画像の特定のピクセルの距離を求めたいときがありました。そこで、特定のピクセルにアクセスする方法を調べたので共有します。ピクセル(RGB)への色々なアクセス方法を知りたい方は[こちら](https://qiita.com/hmichu/items/0a399d9e3bbf3a2a4454)の記事が参考になると思います。

## 方法
自分はrealsenseで取得した16UC1のDepthデータのピクセルを取得しました。下のようにat<>を使えばいけます。depth_img(Mat型)の座標(x, y)を取得したいと仮定しています。

```c++
depth_img.at<ushort>(y,x)
```
他の16U以外の場合は以下のようにして取得できます。

```c++
Mat.at<short>(y,x) // CV_16S 
Mat.at<int>(y,x) // CV_32S
Mat.at<float>(y,x) // CV_32F
Mat.at<double>(y,x) // CV_64F
```
詳しくは[公式](https://docs.opencv.org/3.4/d3/d63/classcv_1_1Mat.html)をご覧ください。

## まとめ
realsenseのピクセルにdepth scaleを掛けて距離を算出してみたんですが、結構ガバガバな気がします。3mぐらいの距離あるはずなのに0.1mとかザラにあります(笑)。やっぱりすべてのピクセルの値を正確に取得するのは難しいのかな。

**間違いや質問、ご意見等ありましたらお気軽にコメントください。頑張って答えますので(笑)。**
回帰分析を勉強したのでまとめる

# まとめようと思った経緯
自分が統計学について学習していく中で、統計学から統計的学習へと内容を移行していく際に回帰分析の部分が橋渡しになっていると感じ、この部分についてもう一度深く理解する必要があると感じたため、今回記事にすることにしました。
あくまで個人のまとめなのでわかりにくい部分があると思いますのでその点についてはご了承ください。

# 母回帰方程式
$$ y_i = β_1 + β_2 x_i + εi ・・・①$$

このモデルを**母回帰方程式**といい、$ β_1,β_2 $を**母回帰係数**という。また、$ εi $は**誤差項**と呼ばれ、以下の条件を満たす

* 期待値は０: $ E(εi) = 0 $
* 分散は一定で$ σ^2 $: $ V(εi) = σ^2 $ 
* 異なった誤差項は無相関になる

以上の点から、先述した母回帰方程式の期待値は以下になる。

$$ E(y_i) = β_1 + β_2 X\_i $$

# 最小二乗法

①式において、$ X_i $によって説明できない誤差項は、
$$ ε_i = Y_i - (β_1 + β\_2 X\_i) $$

である。このままだと$ ε_i $は正負の数字が混ざっており、それだと計算に支障が出るため、符号の影響を取り除くために２乗する。

```math
\begin{align}
S &= Σε_i^2 \\
&= Σ\big(Y_i - (β_1 + β_2 X_i)\big)^2
\end{align}
```

このように定義すると、Sは$Y_i$が$X_i$で説明できない部分の総和を表しているから、できるだけ小さい方がいいと考えられる。<br>ここで、$\hat{β_1}, \hat{β\_2}$をそれぞれ$β\_1, β\_2$の推定量とし、**最小二乗推定量**と呼ぶ。

Sを最小にする$\hat{β_1}, \hat{β\_2}$は、以下の偏微分を０とした２つの方程式

```math
\frac{∂S}{∂β_1} = -2Σ(Y_i - β_1 - β_2 X_i) = 0 \\
\frac{∂S}{∂β_2} = -2Σ(Y_i - β_1 - β_2 X_i)X_i = 0
```
を解くことで求められる。これを整理して、

```math
nβ_1 + (ΣX_i)β_2 = ΣY_i \\
(ΣX_i)β_1 + (ΣX_i^2)β_2 = ΣX_i Y_i
```
を得る。これを**正規方程式**という。これを解くと、$\hat{β_1}, \hat{β\_2}$は、$\bar{X}, \bar{Y}$

を$X_i, Y_i$の標本平均として

```math
\hat{β_1} = \bar{Y} - \hat{β_2} \bar{X} \\
\hat{β_2} = \frac{Σ(X_i - \bar{X})(Y_i - \bar{Y})}{Σ(X_i - \bar{X})}
```

特に、$\hat{β_2}$については
$$ \frac{XとYの共分散}{Xの分散}$$
で求めることができる。

また、
$$ Y = \hat{β_1} + \hat{β\_2} X $$
を**標本回帰方程式**と呼ぶ

ここで、実際の値$Y_i$について、回帰方程式によって出された回帰値$Y_i$からのずれ

```math
\begin{align}
\hat{e_i} &= Y_i - \hat{Y_i} \\
&= Y_i - \hat{β_1} - \hat{β_2} X_i
\end{align}
```
はXで説明されずに残った点であり、**回帰残差**という。$\hat{e_i}$は誤差項$ε_i$の推定量となっている。

誤差項$ε_i$の分散$σ^2$は回帰方程式の当てはまりの良さを示しているが、

$$ s^2 = \frac{Σ\hat{e_i}^2}{(n-2)} $$
で推定される。

# 決定係数
モデルの当てはまりの良さの基準として、一般に**決定係数$η^2$**が用いられる。$Y_i$のばらつきの総和は$Σ(Y_i - \bar{Y})^2$であるが、これは$X_i$で説明できる部分とそうでない部分に分けることができる。

$$ Σ(Y_i - \bar{Y})^2 = Σ(\hat{Y_i} - \bar{Y})^2 + Σ\hat{e_i}^2 $$
この時、右辺の一項が回帰方程式で説明できる部分であり、二項が説明できない変動を表している。

決定係数$η^2$は、$Y_i$の変動のうち、$X_i$の回帰方程式で説明できる変動の割合を示しており、以下で求められる。

$$ η^2 = 1 - \frac{Σ\hat{e_i}^2}{Σ(Y_i - \bar{Y})^2} = \frac{Σ(\hat{Y_i} - \bar{Y})^2}{Σ(Y_i - \bar{Y})^2} $$
GLCMテクスチャ

# GLCM:Gray-Level Co-occurrence Matrix

ある矩形のデータの中に、指定された角度と距離に対してどのくらい信号のペアが見つかったかを信号強度でまとめた表です。
主にテクスチャ解析に利用されます。

* Texture ?  
物の表面の質感、手触り、模様などを指す概念
テクスチャ解析は、粗い、滑らか、絹のような光沢、でこぼこ、などのような一般的な材質を、ピクセル強度の画像空間的変動の関数として数量化する試みのことを言います。
![GLCM1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379410/88fd4cd7-99ab-5438-1f01-05f713b02f04.png)

* ほにゃららMatrix ??
マトリクスと名がついている通り、行列を作るアルゴリズムです。
![GLCM.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379410/0554d814-83bc-a54a-7350-9f499ed9bee2.png)

# 仕組み
画像内にある、特定のピクセル値のペアをカウントして並べた行列です。  
![GLCM2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379410/42b935b5-b397-6cb0-b4b1-6806f3ccac8a.png)

## ペアの探索は角度とオフセットを指定
指定した角度とオフセットでペアを探します。
角度は、一直線に探す方向です。
オフセットは、何個飛ばしで探すか（1のときは隣り合わせ）です。
一般に、角度は4種類です。より細かく探索する方法を提唱できたら新しいかもしれません。
![GLCM3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379410/042fee01-10aa-eade-4e80-6317ecaad8fa.png)

# 得られる定量値
エントロピーやエナジーなど、表から算出可能な特徴量を計算できます。
専門的なソフトウェアでは、GLCMを反映したパラメトリック画像を作成できるものがありますが、これを作るときは、元画像の対応するペアの位置にある画素を、GLCMのペア数にマップするなどの方法があるようです。
（エントロピーなどの一般の画像特徴をマップする方法として、カーネルサイズを指定して、そのサイズ内で計算した特徴量を、該当位置（i,j）の画素値にマップする方法があります。ただし、真の解析結果との対応のない特徴マップになります）

Tatsuaki Kobayashi
Visionary Imaging Services, Inc.
AWS Lambda とは？

## 勉強前イメージ

トリガーベースでなにか実行するようなやつ。
うまく言葉で言えない。

## 調査

### AWS Lambda とは？

サーバレスでコードを実行することが出来る。
サーバレスなので、EC2インスタンスを立てることもなくすぐに始められる。
費用は使った分だけ。
スケーリングも自動。

### 特徴

- イベントをトリガーにして、処理が実施される
- API Gatewayと組み合わせると簡単なwebサービスを作れる

### Lambda には無料枠がある

- 月間100万リクエストまで
- 1GBの関数を月間40万秒まで無料で実行可能

### Lambda で使える言語

主な言語は以下。
カスタムすれば他の言語も使用できるみたいです。

- Python 2.7, 3.6, 3.7
- Node.js 6.10, 8.10, 10.x
- Ruby 2.5

## 勉強後イメージ

やりたいことがあるので、軽くLambdaを調べてみた。
大体イメージと合ってたけど、lamdaだと思ってたらlambdaだったのか。。。

## 参考

- [AWS Lambdaの特徴と用途](https://www.acrovision.jp/service/aws/?p=2403)
- [AWS Lambdaとは？初心者向けにサービス内容やメリットを解説](https://techblog.nhn-techorus.com/archives/14795)
- [【AWS入門】Lambdaの概要とサンプルコードで手を動かしながら実践入門](https://fukatsu.tech/aws-lambda)
【Python】Workbook.move_sheetメソッドを使ってシートを移動させる。

pythonを使用してExcelファイルの操作を勉強しています。
本日の気づき(復習)は、シートの移動に関してです。
pythonでExcelを操作するため、openpyxlというパッケージを使用しています。

左から順に「001」「002」「003」～「010」という名前のシートを持つ
ブック「テスト」があると仮定して、シート「005」を移動させたいとします。
# Workbook.move_sheetメソッド

```python
wb.move_sheet(シート名, offset=移動する値)
```
上記のように記述すると
現在のシートの位置を基準にoffsetの引数の数だけ移動してくれます。
ちなみに、「offset=1」だったら右へ一つ分。「offset=-1」であれば左へ一つ分移動します。

```python:例）move_sheet.py
from openpyxl import load_workbook

wb = load_workbook('テスト.xlsx')

wb.move_sheet('005', offset=-1)

wb.save('テスト_移動後.xlsx')

```
### 末尾へ移動
上記の応用で今度は末尾へシートを移動させます。
今回は、順番も総シート数も解っているので「offset=5」にすればいいだけなのですが
それだと味気ないので、ちょっと工夫してみます。

先日復習していたlen関数を使って移動を試みます。

```python:例）move_end_sheet.py
from openpyxl import load_workbook

wb = load_workbook('テスト.xlsx')

wb.move_sheet('005', offset=len(wb.sheetnames))

wb.save('テスト_末尾へ移動後.xlsx')

```
エラー出るかなと不安でしたが、しっかり移動してくれました。
これで、100シートとかあっても怖くない！

### 先頭へ移動
こちらも、末尾へ移動同様
「005」シートがどこにあっても先頭へ移動させれるように工夫してみます。

「005」シートがどこにあるのかわからないので
先ずは「005」シートの位置を知るために、Workbook.indexメソッドを使ってみます。

# Workbook.indexメソッド

```python
wb.index(シート)
```
で、シートの数(インデックス番号)を取得できます。
後は、シート数分だけ左に移動するだけです。

```python:例）move_top_sheet.py
from openpyxl import load_workbook

wb = load_workbook('テスト.xlsx')

ws_005 = wb['005']
wb.move_sheet('005', offset=-wb.index(ws_005))

wb.save('テスト_先頭へ移動後.xlsx')
```
これで、先頭に移動してくれた！・・・のですが
ブックを開いて確認してみると何か違和感が・・・。
「005」「001」のシートが選択されている状態なのです。
こちらは原因と対処法が解りましたら追記いたします。

### 追記：グループ解除
上記の「005」「001」のシートが選択されている状態になった原因ですが
もともとブックで選択されていたシートが「001」だったためのようでした。
対処法としては
一旦グループ選択状態を解除して、再度先頭のシートを選択しなおす
と、良いようです。

```python:修正）move_top_sheet.py
from openpyxl import load_workbook

wb = load_workbook('テスト.xlsx')

ws_005 = wb['005']
wb.move_sheet('005', offset=-wb.index(ws_005))

# シートのグループ選択を解除する
for ws in wb.worksheets:
    ws.sheet_view.tabSelected = None
# 再度先頭のシートを選択状態にする
wb.active = 0

wb.save('テスト_先頭へ移動後.xlsx')
```

こちらで、先頭のシートのみが選択状態にする事が出来ました！
N+1問題について

## N+1問題とは

アソシエーションを利用した場合にDBへのアクセスが多くなってしまう問題のことです。
対策をしていないとアプリケーションのパフォーマンスの低下に繋がってしまいます。

例）
#### users テーブル
| Column   | Type   | Options     |
| -------- | ------ | ----------- |
| nickname | string | null: false |
Associations
has_many :tweets

#### tweets テーブル
| Column   | Type    | Options     |
| -------- | ------- | ----------- |
| comment  | string  | null: false |
| user_id  | integer |             |
Associations
belongs_to :user

ツイートが複数存在する一覧画面に、それぞれユーザー名を表示する場合、tweetsに関連するusersの情報の取得に、ツイート数と同じ回数のアクセスが必要になります。（投稿が1万ある場合は1万回以上DBにアクセスすることになります。）


## includeメソッドを使用する
includeメソッドを使用することで引数に指定された関連するモデルを一度のアクセスで取得することができます

```ruby
#モデル名.includes(:紐づくモデル名)
Tweet.includes(:user)
```

引数に関連するモデルをシンボル型で記入します。
このように記述することで、
1：tweetsのすべてのデータを取得する
2：tweetsテーブルに紐づくusersテーブルのデータを取得

２度のアクセスだけて情報を取得することができます。
Railsアプリの立ち上げ方法

# 本記事の内容と目的
- 内容はアプリ立ち上げからGemの導入方法の説明まで 
- Railsアプリの立ち上げ方法の一連の流れを整理する
- Railsアプリの立ち上げをスムーズに行えるようにする

初学者向けの記事です。初めての投稿なので、文章が拙いかもしれませんが、ご容赦ください。

# Railsアプリの立ち上げ
- ターミナルでRailsアプリの立ち上げを行います。
- まずは、アプリを作成するディレクトリに移動します。

```Linux
% cd ~/projects
```

- 次にいよいよrails newコマンドでアプリ立ち上げを行います。
- 今回は、MySQLで作成します。railsのバージョンは6.0.0でし。


```Linux
% rails _6.0.0_ new "アプリ名" -d mysql
```

- 次にデータベースを作成します。

```Linux
% rails db:create
```
# GitHubへの登録
- バージョン管理はGitHubで行うので、リポジトリの登録をします。
- ローカルリポジトリをGitHubDesktopから作成します。
- Current Repository→ Add→ Add Existing Repository
- 上記の順にクリックします。
- 既に作成したアプリを指定します。
- Current Repositoryが新しく立ち上げたアプリになった事を確認。
- first commitというコミットメッセージでcommitします。

- 次にRemort Repositoryを作成するため、Pushします。
- この時にリポジトリをPubricかPrivateか目的に応じて指定します。

# Gemの導入方法
- 今回は、deviseとActive Strageの２つのGemを導入します。
- Gemfileを開きます。
- Gemfileの末尾に下記のように記述します。

```Ruby
gem 'mini_magick'
gem 'image_processing', '~> 1.2'
gem 'devise'
```

- ターミナルでbundle installコマンドを実行します。
- まずはアプリに移動します。その後にコマンド実行します。

```Linux
% ~/projects/”アプリ名”
% bundle install
```

- installを反映するためにrails sコマンドでサーバーを一度立ち上げます。

```Linux
% rails s
```

- 次にActive Strageのデータベースを作成します。

```Linux
% rails active_storage:install
% rails db:migrate
```

- これでActive Strageのデータベースは作成できました。

# 今後の執筆について
- 今後も学習してきた内容をどんどんアップして、実際に作業するときの参考にします。
- 最後までご覧いただきありがとうございました。ご指摘はなんなりとお申し付けください！！！
【Node.js】Messaging API使ってみたので記録残す

## 前書き

ちょっと興味があったけど実際に作るいい感じのものが思い浮かばなかったため、今後使いたいと思った時にすぐに実装できるように導入をまとめました。

## 概要

ざっくりとした処理の流れは以下の通りです。
herokuにデプロイしたサーバー内の処理を変更することでいろいろ実装できそうです。

lineでbotに文字送信 → herokuサーバーにリクエスト → 入力されたものを返す


## 使ったもの

- Node.js
- express
- Messaging API
- heroku


## 実装の流れ

1. LINE Developersでbotを作成
2. herokuにAPIをデプロイ
3. APIのURLをbotのwebhookに登録

## LINE Developersでbotを作成

### providerを作成

名前を入力して作成(provider name != bot name)

![](https://i.imgur.com/mzQNpNB.png)

### Messaging API channelを作成

`Create aMessaging API channel`を選択します。

![](https://i.imgur.com/1VvhAPp.png)

名前などを入力してchannelを作成したら一旦完了です。

## herokuにAPIをデプロイ

デプロイの詳細は割愛して環境変数についてのみ記載します。

### 環境変数

- デプロイしたアプリケーションからMessagingAPIを叩くためには以下の２つが必要です。
    - Channel access token
    - Channel secret


> Channel access token

`Messaging API`のタブに移動し、一番下にあります。
一番最初は発行する必要があります。

![](https://i.imgur.com/6eQR2WQ.png)


> Channel secret

`Basic settings`のタブに移動し、真ん中らへんにあります。

![](https://i.imgur.com/cauJfQ6.png)


## APIのURLをbotのwebhookに登録

https://sample-app.herokuapp.com/

`Use webhook`をオンにして、`Webhook URL`にデプロイしたアプリケーションのURLを貼り付けます。

![](https://i.imgur.com/bNaqusT.png)


### 補足

`Webhook URL`に`https://sample-app.herokuapp.com`と設定した場合

lineでメッセージを送信した際に`POST https://sample-app.herokuapp.com`が叩かれます。


## サンプル

### 動作

![bot.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530479/87f3735f-58a8-f4fd-5fc3-7be3037a05fc.gif)


### コード

https://github.com/d-yamagishi522/line-bot-sample
ディレクトリ変更時のちょっとした小ネタ

#ディレクトリ変更時のちょっとした小ネタ
通常ターミナルやコマンドプロンプト等でディレクトリ変更（cd）を行う際には

$cd [変更先のディレクトリ名]

をタイプするわけですが、変更したいディレクトリのフォルダごとターミナルまたはコマンドプロンプトにドラックすることで簡単にディレクトリの変更を行うことができます。
ENVとENV.fetchの違いを調べてみた


Railsチュートリアルの第7章でpumaの設定する箇所で、以下のような`ENV.fetch`というオブジェクトを初めて目にしたので調べてみました。
(※誤った記述がある場合、ご指摘いただければ幸いです。)

```
environment ENV.fetch("RAILS_ENV") { ENV['RACK_ENV'] || "production" }
```

## 違いは？

```
ENV['hoge']                   // 'hoge'という環境変数が存在しないと、nilが返ってくる
ENV['hoge'] || 'default'      // 存在しない場合のデフォルト値を設定できる
ENV.fetch('hoge', 'default')  // fetchを使うと、引数でデフォルト値を設定できる
```


## コードの意味
Pumaを実行する環境を`RAILS_ENV`の環境にしており、存在しない場合は、`ENV['RACK_ENV']`または、`production`にするという設定。

```
environment ENV.fetch("RAILS_ENV") { ENV['RACK_ENV'] || "production" }
```
(Herokuでは`ENV['RACK_ENV']`にデフォルトで`production`が入っている。)


## 最後に
Railsチュートリアルでは、環境変数が存在しないと、`production`が返ってくるようになっていたが、[Herokuのドキュメント](https://devcenter.heroku.com/articles/deploying-rails-applications-with-the-puma-web-server#environment)では、`development`となっていた。 

```
environment ENV['RACK_ENV'] || 'development'
```

調べてみると、`production`と書いている人や、`development`と書いている人がいたので、その時の状況によって書き方が変わる可能性があるとが分かった。
どういう状況で、書き方を変えるのか意識しながら学習していきたい。
v-forのキーにprimitiveじゃない値は設定できない

#概要
`v-for`で配列のobjectを取り出す時に以下のエラーが発生していたので、その解決策を起筆します。

>**[Avoid using non-primitive value as key, use string/number value instead.]**

```.vue
  <li class="tag" v-for="tag in tags" :key="tag">
    {{tag.tag_name}}
  </li>
```
tagsの中身

>tags: Array(4)
0: Object
1: Object
2: Object
3: Object

#原因
エラー文の通りなのですが、`primitive`じゃない値をキーとして設定するのはよろしくないようです。
今回`tags`という配列の中にobjectが格納されている状態だったので、objectをキーに設定していたため、起こったエラーです。

##プリミティブ値とは
公式より引用
>JavaScript において、プリミティブ (primitive、プリミティブ値、プリミティブデータ型) はオブジェクトでなく、メソッドを持たないデータのことです。 6 種類のプリミティブデータ型があります。文字列、数値、BigInt、真偽値、undefined、そしてシンボル (ECMAScript 2016 で追加) です。

objectはプリミティブじゃない値ということが分かりますね。

#解決策
```.vue
<li class="tag" v-for="tag in tags" :key="tag.tag_id"> <!--:key="tag"から変更-->
  {{tag.tag_name}}
</li>
```

#参考文献
[公式サイト](https://developer.mozilla.org/ja/docs/Glossary/Primitive)
Mac版 XAMPP-VMでポートフォワーディングの設定をする方法

## 発端
Eclipseを使ってJava Servlet/JSPの実習をおこなっている際に、Mac環境の学生からデータベースへの接続でエラーが発生するという報告を受けた。

発生したエラーは以下のもので、

```
java.sql.SQLException: null,  message from server: “Host ‘192.168.64.1’ is not allowed to connect to this MariaDB server”
```

いろいろ調べた結果、XAMPP-VMのポートフォワーディングの設定が正しくおこなわれていないことが原因だった。

ポートフォワーディングの設定をXAMPP-VMのGUIから行なっても保存されないため、設定を永続化するための方法を調査した。

## 対策

1. Finderで自分のアカウントのホームフォルダを開く
( . でファイル名やフォルダ名が始まる)非表示ファイルやフォルダが表示されていなければ、Cmd+Shift+.を押して表示する。
2. ホームフォルダの中に.bitmaniというフォルダが表示されるはずなので確認する。
.bitnami/stackman/machines/xampp/metadata.json というファイルをテキストエディタで開く
3. ファイル内のPortForwardsという項目を以下のように修正して保存する
4. 修正ミスがあるとXAMPPが起動しなくなる可能性があるので、テキストエディタを開いたままXAMPPを起動する
5. XAMPPが起動しない場合は、テキストエディタのUNDO機能を使って元に戻して保存しなおす。

```:metadata.json(部分)
"PortForwards": [
    {
      "LocalPort": 8888,
      "RemotePort": 80,
      "RequireLocal": true,
      "OverSSH": true
    },
    {
      "LocalPort": 8443,
      "RemotePort": 443,
      "RequireLocal": true,
      "OverSSH": true
    },
    {
      "LocalPort": 3306,
      "RemotePort": 3306,
      "RequireLocal": true,
      "OverSSH": true
    }
],
```

上記設定はEclipse同梱のTomcatとの競合を避けるため、HTTPのホスト側ポートを8888版にしてある。
Nomad Wifiを契約してWIMAXホームルーターL02を使ってみたときの備忘録

ただの備忘録的メモですが、公式サイトの方法だと解決できなかったので、カスタマーに聞いて判明した設定方法をここに書いておきます。

#[Nomad Wifi](https://sim.nomad.inc/)とは？
最近よく小さめのSIM会社がいろいろ乱立していますが(どこもSoftbankの回線を使っているところが多い模様)、Nomad wifiは以下の2つのプランしか出しておらずかつ契約期間縛りもないところが魅力的でした。

1. Mini
月20GBまで。2,600円/月。

2. Basic
月100GBまで。3,600円/月。

SIMも契約して大体1日で郵送で送られてきます。
その他、若干解約や契約についてはちょっと不便な点もあったので、そのへんはHPをみて確認してください。

##Nomad SIMをHuaweiのホームルーターL02で使う

公式サイトにも一応方法は書いてあるのですが、まあまあわかりにくかったので、まとめてみました。
プロファイルリスト：
1.SIMをL02に刺す。
2.(必要な場合はリセットボタンを2秒以上長押し)
3.Wifiに接続する(SSIDなどの設定が必要な場合はルーター本体の設定に従う)
3. http://speedwifi.home へアクセス
4. **画面左側の基本設定の通信モード設定から「ハイスピードプラスエリア」をプルダウンで選択**(これをやらないとAPN設定をしても圏外のままです。)
5. 画面右側のログイン画面から、ログインし(ログインIDやpswはL02の底面部に記載)APN設定をする。
・設定タブから「WAN設定」の「プロファイル設定」を選択、ここですでにデフォルトでなにか入っているかもしれませんが、「新規」で以下を入力。

```
プロファイル名：適当な英語文字列を入力	
APN（接続先情報）：plus.4g	
ユーザー名： plus	
パスワード： 4g	
認証タイプ： CHAPかPAPを選択。
IPタイプ： IPv4
```
これでAPN設定は終わりです。しばらくするとWifiが使えるようになります。
1Password を コマンドラインからインストールする [Ubuntu]

# やりたいこと

コマンド経由で **1Password** をインストールする

# 注意

Linux 1Password は Beta 版で、欠けてる部分とかがあるかもとのこと

# 環境

- Ubuntu 20.04

# やること

手順を踏むことで apt でインストールできる

## 鍵の追加

```bash
 sudo apt-key --keyring /usr/share/keyrings/1password.gpg adv --keyserver keyserver.ubuntu.com --recv-keys 3FEF9748469ADBE15DA7CA80AC2D62742012EA22
```

## repository の追加

```bash
 echo 'deb [arch=amd64 signed-by=/usr/share/keyrings/1password.gpg] https://downloads.1password.com/linux/debian edge main' | sudo tee /etc/apt/sources.list.d/1password.list
```

## インストール

```bash
 sudo apt update && sudo apt install 1password
```
C 言語で eval 風関数

## はじめに

`eval` 関数とは文字列を式として評価する関数です。`eval` は C 言語などのコンパイラ言語にはほとんどないですが，JavaScript などのインタプリタ言語で一般的です。ここでは C 言語のための文字列を数式として処理する `eval` 風関数を作成します。ソースコードは [GitHub](https://github.com/Daiji256/eval) にあげてあります。

## 主な仕様

`eval` は引数の数式を計算し，その結果を戻り値とする関数にします。`eval` では `sin`, `exp`, `sqrt` などの `math.h` にある関数が使えるようにします。関数を含めた数式の計算順は次のようになります。計算過程は全て文字列として処理を行います。

1. 関数：`sin`, `exp`, `sqrt` など
1. 括弧：`(`, `)`
1. 乗法，除法：`*`, `\`
1. 加法，減法：`+`, `-`

関数の計算を行う `calcfunc` ，四則演算を行う `calc` を作成します。括弧の処理には `eval` を使用します。プログラムの疑似コード（？）と共に説明します。実際のソースコードは長いので [GitHub](https://github.com/Daiji256/eval) を参照してください。実装は基本的に単純で，上記の箇条書きの順番通りに計算するだけです。

```c
double eval(char *str) {
	for ( 文字列先頭からループ ) {
		if ( 関数があった時 ) {
			str2 = 関数とその引数;
			str3 = num2str(calcfunc(str2));
			str = str2 を str3 に置換;
		}
	}
	for ( 文字列先頭からループ ) {
		if ( 括弧があった時 ) {
			str2 = 括弧内の文字列;
			str3 = num2str(eval(str2));
			str = (str2) を str3 に置換;
		}
	}
	for ( 文字列先頭からループ ) {
		if ( *, / があった時 ) {
			str2 = 計算範囲;
			str3 = num2str(calc(str2));
			str = str2 を str3 に置換;
		}
	}
	for ( 文字列先頭からループ ) {
		if ( +, - があった時 ) {
			str2 = 計算範囲;
			str3 = num2str(calc(str2));
			str = str2 を str3 に置換;
		}
	}
	return atof(str);
}
```

## 処理の流れの例

引数に `3*sqrt(4)+(5-2)` とした時を例にして説明します。まず都合が良くするために全体に `(`, `)` を付けます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699841/34bee713-f01d-5fba-b0bc-d9fdf4dec51a.png" width=50%>

次に計算の順番通りに関数を呼び出し計算します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699841/28c718e1-1b82-0433-ecb3-51e2fa568322.png" width=50%>

次に `*`, `\` による計算を `calc` を用いて行います。最後に `+`, `-` による計算を行います。最終的に残った値を実数値として `return` します。

## まとめ・今後

C 言語用の `eval` 風関数を作成しました。`calc` 等の関数について触れませんでしたが，説明を付け加えるかもしれません。ぜひ構文解析等の勉強に役立てばと思います。今後の課題としてメモリを多用する，処理速度が遅いなどが挙げられるので改善したいです。また，バグがあるかもしません。

## 文献

1. [ソースコード (GitHub)](https://github.com/Daiji256/eval)
送信メールサーバメモ [Postfix × SASL × Gmail]


# 概要

* 通知用の送信メールサーバがほしい
* セキュリティはある程度担保したい
* 設定に時間かけたくない
* SMTPはGmailに任せる
* セキュリティはSASLとGmailのセキュリティ機能に任せる

# 詳細

* 設定に必要なものをインストール

```
sudo apt install postfix
sudo apt install sasl2-bin
```

* postfix設定

```
sudo vi /etc/postfix/main.cf
```

```/etc/postfix/main.cf
:
#====== Append Gmail Config =====
relayhost = [smtp.gmail.com]:587
smtp_use_tls = yes
smtp_tls_CApath = /etc/pki/tls/certs/ca-bundle.crt
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_tls_security_options = noanonymous
smtp_sasl_mechanism_filter = plain
#================================
:

```

* sasl設定(認証情報設定)

```
sudo vi /etc/postfix/sasl_passwd
```

```
[smtp.gmail.com]:587  mailhost-username@xxx.com:password
```

* 認証情報ハッシュ＆有効化

```
$ sudo postmap hash:/etc/postfix/sasl_passwd
```

* メールサーバプロセス起動

```
$ sudo systemctl restart postfix
```

* Gmail側設定
 * 外部アプリ使用許可およびセキュリティレベル変更

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/21dea1e7-ddab-605f-f91c-1a2a0023775a.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/5a097084-8f21-9a9c-fa95-ddea32331fa2.png)



* mailコマンドインストール

```
$ sudo apt install mailutils
```

* 送信テスト

```
$ echo "test mail recieve" | mail -s "mail test via Gmail" user@geeplus.jp
```

* 受信確認

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/cfe3bcc2-db32-d65c-743f-38c3bcb46d7d.png)
railsアプリの開発をしていてdockerでの開発でよく使うコマンドを自分用にまとめてみる（随時更新予定）

## この記事で書くこと
すごく忘れっぽく毎回typoしたり、打ち直したりしていて、そんな自分のためにここを見れば迷わない、と思えるようなコマンドのまとめをする。

## 起動してるコンテナのlogをみたい
```.zsh
docker logs --tail=10 -f コンテナの名前 
```

## バックグラウンドでコンテナを起動

```.zsh
docker-compose up -d コンテナの名前 
```

## 起動してるコンテナを停止したい。
```.zsh
docker-compose stop コンテナの名前 

# 全てを停止は以下
docker-compose stop
```

# 起動しているコンテナの中に入る。

```
docker psで入りたいコンテナ名を確認してから、
docker container exec -it コンテナ名 bash(ubuntuの場合)
```


# Dockerの情報を確認する。（OSが何か知りたい時など）

```
docker info
```
ImageJマクロの関数で複数の戻り値を返す

配列を返せば可能。

```sample.ijm
function double(a, b) {
	a *= 2;
	b *= 2;
	return newArray(a, b);
}
```

のようにする。

```
result = double(1, 2);
//resultは長さ2の配列になり、2, 4が入る
```

この場合、戻り値を受ける変数resultは配列宣言しておく必要はない。強制的に配列になる。

環境　`Windows10, Fiji`
(UE4)Media frameworkについて

参照:[公式ドキュメント](https://docs.unrealengine.com/ja/WorkingWithMedia/MediaFramework/Overview/index.html)
#Media frameworkとは

UnrealEngineで作成したゲーム内に、映像メディアを配置して再生する方法です。
Media Player アセット内で再生、ポーズ、巻き戻しをしたり、それらの調整をブループリントで行うこともできます。
映像再生をプレイヤーが調節できる様に、UMGでUIを作成することも可能です。

そのために、Media Sourceを指定して、エンジンがメディアアセットを探せる様にする必要があります。
___
###⚪︎メディアソースの種類

映像を再生させる為には、ソースの定義が必要です。そこで使うのが、**Media Sourceアセット**です。プロジェクトの一部としてファイルがインクルード[^1]されているものや、ウェブサイトからストリーミングしたり、プラットフォーム固有のメディアを使用する場合に、このアセットを作成する事が前提になります。
![スクリーンショット 2021-02-03 19.01.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939279/c965963c-8dc1-1a8d-7c4e-2fb2164e8c05.png)
プロジェクトを開き、Add newまたはコンテンツブラウザの左クリックでMediaから使用したいソースタイプを選択してMedia sourceを追加します。

####・File Media Source

このアセットは、デバイスまたは共有ローカルネットワークファイル上のメディアファイルを持ち込む為に使用します。[File Path]欄に、メディアファイルの格納場所を指定する事でメディアを呼び出せます。
<font color="grey">*（基本的には、メディアをプロジェクトディレクトエリの[Content]>[Movies]に移行してから指定するのが好ましい使用方法です。）*

####・Image(Img) Media Source

デバイス上の画像シーケンスを再生する際に使われます。連番画像対象で、画像を正しい順番で追加させる為に連続した名前<font color="grey">*(MyImage01.exr や MyImage_01.exr など)*<font color="black">をつける必要があります。
＊公式で[Img Media Sourceの使用ガイド](https://docs.unrealengine.com/ja/WorkingWithMedia/MediaFramework/HowTo/ImgMediaSource/index.html)が公開されています。

####・Stream Media Source

URLをソースとして、ウェブ上のメディアをストリーミングさせる為のアセットです。
<font color="red">＊YouTubeとDailyMotion形式のURLへのリンクには対応されておらず、ホストのファイルに直接リンクさせる必要があるそうです。

####・Platform Media Source

メディアのソースを上書きするアセットです。特定の映像を他のデバイスで再生する場合に、どのプラットフォームでどの映像を再生するか、[Media Sources]セクションで指定します。
こちらも[公式ガイド](https://docs.unrealengine.com/ja/WorkingWithMedia/MediaFramework/HowTo/PlatformMedia/index.html)があります。

####・Media Playlist

これは複数のMedia Sourceを扱い、順番にプレイすることができるアセットです。作成したMedia Sourceアセットを追加し、順番を指定すれば各アセットが自動的に再生されます。
![スクリーンショット 2021-02-03 19.00.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939279/2652af82-74fe-5616-4d99-a159e3bc36c0.png)
Detailsから+をクリックして、作成したメディアソースを追加します。
<font color="red">＊バージョン4.18.1では、[Loop]オプションはプレイリストをループしません。Media Playerアセットの**Loop**オプションを選択すれば、Playlistをループすることができます。

####・Media Sound

映像と関連したオーディオを再生させるためのアセットです。Media Soundコンポーネントを作成した後、連携させたいメディアのBP、アクターに追加する事で使用できます。

####・Media Texture

Media Playerアセットから映像をレンダリングする際に使用します。
これを使って、テクスチャ化されたメディアをレベル内のメッシュに適用する事で、ワールド内のオブジェクトに映像が投影されている様な再現ができます。
使用の際には、メディアが参照しているMediaPlayerをDetailsで定義させる必要があります。

####・Media Player

今までのMedia SourceやMedia Playlistを再生させるには、このアセットを使います。
Media Textureを使って映像再生とMedia Soundコンポーネントを作成し、映像とオーディオが関連付いたメディアを作成します。
![スクリーンショット 2021-02-03 18.55.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939279/f2ffa554-30e3-9605-a4f6-abe1be7f05da.png)
作成時に、「アセットをこのMediaPlayerにリンクさせる」ウィンドウが出てくるので、チェックをつける事でこのアセットに関連したMedia Textureの作成および割り当てが自動的に行われます。

 
[^1]: 他のファイルに書かれている内容を取り込むこと
[UnityC# SimpleSQL SQLite] UnityでSimpleSQLを用いている場合にDBファイルを消さずにDBをリセットする

# 前提
- UnityでSQLiteを用いてデータを管理している
- SQLiteの管理には、有料のORMアセットであるSimpleSQLを用いている
- 開発環境で手軽にDBをリセットしたい
- しかし、DBリセットのためにファイルを消してしまうとDBファイルへのインスペクタ参照が外れてしまう

→ DBファイルを消さずにデータベースをリセットする必要が出てきた。


# 環境
- Unity 2019.2.13f1
- SimpleSQL 2.7.1
- SQLite 3.28.0 
- .NET 4.x

# 方針
モデルクラスを配置しているネームスペースのクラス名を全て取得し、ForEachを回して全てDROP TABLEする

# コード
コア部分は以下のとおり。

```C#
var q = System.AppDomain.CurrentDomain.GetAssemblies ()
            .SelectMany (t => t.GetTypes ())
            .Where (t => t.IsClass && t.Namespace == "myDBModels");
dbManager.BeginTransaction ();
q.ToList ().ForEach (t => dbManager.Execute ("DROP TABLE \"?\"", t.Name));
dbManager.Commit ();
```

間違って実行してしまわないよう、`EditorUtility.DisplayDialog(string title, string info, string ok, string cancel)`で、実行可否を出すダイアログを表示する。
また、今回はデバッグ用なので間違っても実機で実行されてしまわないよう、 `#if UNITY_EDITOR`を指定する。


```C#

public class DBReseter : MonoBehaviour {

    public bool ResetDynamicDB = false;

    void Start () {
#if UNITY_EDITOR
        if (ResetDynamicDB && EditorUtility.DisplayDialog ("Drop Database", "Are you sure delete all data?", "delete", "cancel")) {
            var q = System.AppDomain.CurrentDomain.GetAssemblies ()
                        .SelectMany (t => t.GetTypes ())
                        .Where (t => t.IsClass && t.Namespace == "Models.DynamicDB");

            dbManager.BeginTransaction ();
            q.ToList ().ForEach (t => dbManager.Execute ("DROP TABLE \"?\"", t.Name));
            dbManager.Commit ();
            PlayerPrefs.SetFloat (dynamicDBKey, 0);
   }
#endif
}
```
Hyper-Vってなんぞや？

## はじめに
2021年2月よりインフラエンジニアとして働き始めました。
勤務先がmicrosoft社製品がメインということで、これからwindowsやAzureについて発信していきます！

間違っている部分がありましたらご指摘いただけるとありがたいです。

## Hyper-Vってなんぞ？
###microsoft社が出している仮想化技術
です。

## 仮想化？
### (1)仮想化とは
少し寄り道です。

通常、メモリやハードディスクといったハードウェアの上にOSが動いています。
これらハードウェアをソフトウェアで表すことで、OSの中に別のコンピュータを作り上げることができます。

### (2)メリット
①. 物理サーバーの台数を減らすことにより、省スペース/省エネルギー/省コスト化できる
②. 異なるOS環境を構築できる
③. 環境を用意する費用と時間の削減

### (3)デメリット
①. オーバーヘッド（余分な処理）があるため、ハードウェアに大きく依存するアプリは正しく動作しない可能性

## Hyper-Vの特徴
さて話をHyper-Vへと戻します。
Hyper-Vの特徴は大きく２点
### ①windows serverの機能である
windows同様microsoft社が提供しているため、windows serverおり追加費用が不要で利用が容易であることはメリットとして挙げられます。

## ②ハイパーバイザー型の仮想化技術である
ホスト型の仮想化技術（Virtual Server）と違い、管理OSと同様にハイパーバイザー上で動作するため、
ホスト型に比べてより高速に動作します。


## おわり
Hyper-VとVMware を混同していましたが、VMwareは社名（サービス名）なんですね〜。
Beautifulsoupで文字化けに悩まされているあなたへ

#はじめに
pythonでWebページをスクレイピングする際によく使われている (と思われる) Beautifulsoupモジュール。取得したWebページにをパースした後に日本語の文字化けに悩まされていたので今回はバグ解消した流れを備忘録として書き残しておきます。
#問題のコード
```py
# coding: utf-8
import requests
from bs4 import BeautifulSoup
url = "http://www2.he.tohoku.ac.jp/zengaku/zengaku_info_g.html"
site = requests.get(url)
soup = BeautifulSoup(site.text, "html.parser")
print(soup.find_all(id="content_box"))
```
この状態で実行しても (タグの情報は正確に取れるが) 日本語部分は全て文字化け...
文字コード関連のバグかと思い1行目のcodingの指定をshift_jisなどに変えてみても効果なし
#解決策
はい，簡単なことでした。
6行目`soup = BeautifulSoup(site.text, "html.parser")`でパースされてるのがunicode文字列だから駄目だったんです。
こうしましょう。`soup = BeautifulSoup(site.content, "html.parser")`

**変更点**

| site. | 取得できる形式 |
|:-----------|------------:|
| text       | unicode        | 
| content     | bytes     | 

#参考
[BeautifulSoupの文字化けが止まらない時の解消方法](https://lets-hack.tech/programming/languages/python/beautifulsoup-mojibake/)
mysqlの結果をささっとLinuxコマンドでCSVに変換する

mysqlの出力結果をCSVにしたいと思ったとき、パラメータがすぐにわからない時があります。
たぶんパラメータをいじればできるんでしょうけど、それほどmysqlに詳しくないし調べるのもめんどくさい。
でもgrepやsedを駆使すればいけるんじゃねーかとやってみました。

# tl;dr
mysqlの取得結果をパイプで下記をつなげるだけです。

```
| grep -v "\-\+\-" | sed "s/^| //g" | sed "s/ |$//g" | sed "s/ | /,/g" | sed "s/ //g"
```

# 解説

例えばこんな出力があるとします。

```
+---------+-------------+
|      ID | CREATE_TIME |
+---------+-------------+
|   10508 |  1569301799 |
|   10509 |  1569301801 |
|   10510 |  1569301802 |
|   10511 |  1569301803 |
|   10512 |  1569301804 |
+---------+-------------+
```

この枠組みが邪魔ですね。grepとsedで削除してみます。

```
+---------+-------------+  <---No.1
|      ID | CREATE_TIME |
+---------+-------------+  <---No.1
|   10508 |  1569301799 |
|   10509 |  1569301801 |
|   10510 |  1569301802 |
|   10511 |  1569301803 |
|   10512 |  1569301804 |
+---------+-------------+  <---No.1
|         |             |
No.2     No.4           No.3
```

処理の意味は下記の通りです。

```
| grep -v "\-\+\-"   No.1 : "+"が入った行を省いて
| sed "s/^| //g"     No.2 : 先頭の|を省いて
| sed "s/ |$//g"     No.3 : 最後の|を省いて
| sed "s/ | /,/g"    No.4 : 間の|を,に変えて
| sed "s/ //g"       No.5 : スペースを削除
```

加工結果です。

```
ID,CREATE_TIME
10508,1569301799
10509,1569301801
10510,1569301802
10511,1569301803
10512,1569301804
```

# 注意
sqlの結果にスペースが入ってしまうと、うまくいかなくなります。
あくまで上記は参考に自分でがんばってみてください。
Go: 自作したモジュールの使い方

次のページを参考にしました。
[ローカル環境のみでの Go Modules と自作パッケージ](https://qiita.com/tkj06/items/a5f79417935100045650)

作業フォルダーの準備

```bash
mkdir module_test && cd module_test
go mod init gin_work
go get -u github.com/gin-gonic/gin
```

次のようにプログラムを作成

```text
$ tree
.
├── go.mod
├── go.sum
├── main.go
├── module01
│   └── module01.go
├── module02
│   └── module02.go
└── module03
    └── module03.go
```

```go:main.go
package main

import "github.com/gin-gonic/gin"
import "module_test/module01"
import "module_test/module02"
import "module_test/module03"

// ---------------------------------------------------------------
func main() {
    rr := gin.Default()
    rr.GET("/ping", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "pong",
        })
    })

    rr.GET("/morning", func(c *gin.Context) {
	str_out := module01.Prog01()
        c.JSON(200, gin.H{
            "message": str_out,
        })
    })


    rr.GET("/afternoon", func(c *gin.Context) {
	str_out := module02.Prog02()
        c.JSON(200, gin.H{
            "message": str_out,
        })
    })

    rr.GET("/evening", func(c *gin.Context) {
	str_out := module03.Prog03()
        c.JSON(200, gin.H{
            "message": str_out,
        })
    })

    rr.Run()
}

// ---------------------------------------------------------------
```

```go:module01/module01.go
package module01

func Prog01() string {
	rvalue := "Morning"

	return rvalue
}
```

```go:module02/module02.go
package module02

func Prog02() string {
	rvalue := "Afternoon"

	return rvalue
}
```

```go:module03/module03.go
package module03

func Prog03() string {
	rvalue := "Evening"

	return rvalue
}
```

サーバーの実行

```bash
go run main.go
```

クライアントでアクセス

```bash
curl http://localhost:8080/morning
```

```bash
curl http://localhost:8080/afternoon
```

```bash
curl http://localhost:8080/evening
```
Spotify API + Reactでアーティスト情報を取得してみた

<h2>概要</h2>
APIの勉強をかねて、気になっていたSpotify-APIを使用した
簡単な情報の取得・反映をまとめてみました。

<h2>使用技術</h2>
React
React Hooks
-useState
-useEffect
axios
<h2>はじめに</h2>

```
npx create-react-app ファイル名
```

でローカルのファイルを作成します。

<h2>axiosのインストール</h2>
今回はaxiosを使うのでインストール
--save で package.json にも反映させておきます。

```
npm install axios --save
```
<h2>更新</h2>

```App.js

import React, { useEffect, useState } from "react";
import { Credentials } from "./Credentials";
import axios from "axios";

const Artisttest = () => {
  const spotify = Credentials();
//Credentials.jsにClientIdとClientSecretを格納してます

  const [token, setToken] = useState("");
  const [artists, setArtists] = useState({ artistsName: "", artistsId: "" });

  useEffect(() => {
    // tokenを発行し、権限を付与
    // 付与されたTokenをuseStateのtokenに代入し、値を保持
    axios("https://accounts.spotify.com/api/token", {
      headers: {
        "Content-Type": "application/x-www-form-urlencoded",
        'Authorization':
          "Basic " + btoa(spotify.ClientId + ":" + spotify.ClientSecret),
      },
      data: "grant_type=client_credentials",
      method: "POST",
    }).then((tokenResponse) => {
      console.log(tokenResponse.data.access_token);
      setToken(tokenResponse.data.access_token);

      // / 上記で付与されたtokenを使い、Spotify APIにアクセス
      axios("https://api.spotify.com/v1/artists/取得したいアーティストのID", {
        method: "GET",
        headers: { 'Authorization': "Bearer " + tokenResponse.data.access_token },
      }).then((artistsReaponse) => {
        setArtists({
          artistsName: artistsReaponse.data.name,
          artistsId: artistsReaponse.data.id,
        });
      });
    });
  }, []);
  console.log(artists);
  return (
    <div>
      <h2>{artists.artistsName}</h2>
      <h2>{artists.artistsId}</h2>
    </div>
  );
};

export default Artisttest;
```

<h2>結果</h2>
console
![スクリーンショット 2021-02-03 18.23.34 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624637/bba6651c-865b-715c-34dc-da167302dfcc.png)

ブラウザ画面
![スクリーンショット 2021-02-03 18.23.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624637/74b2cc65-9ccf-c0a9-3425-5d5465acf496.png)

無事取得できました！

```
setArtists({
artistsName: artistsReaponse.data.name,
artistsId: artistsReaponse.data.id,
 });
```
上記の【data】以降の【name】と【id】を【img】や【genre】などに変更することもできます。

<h2>まとめ</h2>
APIを使用したのは初めてだったので、無事できてとても嬉しいです。
これを元にいろいろ作成したいと思います。

楽しかった。

※初学者ですので誤っている点などあるかと思いますが、
その際はコメントなどいただけますと幸いです。
CakePHP4.2.3更新後にCSRFエラー

cakephp/cakephp (4.2.0 => 4.2.3)
にアップデートしたら、更新処理時に以下のエラーが発生するようになった。

```
CSRF token from either the request body or request headers 
did not match or is missing.
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38162/c2021a3a-ebc1-5de5-fdd2-5ee49c0260ec.png)

以下を参考にCookieを消してみたところ、解決。
https://github.com/cakephp/cakephp/issues/14471
https://github.com/cakephp/cakephp/pull/14504
未経験者がRailsでポートフォリオを作成し、AWSにデプロイしてみた

##はじめに
実務未経験者がRailsを使用し、Webアプリケーションを作成してみたのでアプリの紹介や開発時の苦労した点などをご紹介できればと思います。



##アプリ概要

本専用のタスク管理アプリ　「ブックたす」を作成しました

- 読もうと思っている本をリストに登録
- おすすめの本を他のユーザーにシェアできる
- 読んだ本を内容をアウトプットできる
![ezgif.com-gif-maker (3).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642425/bc142f47-f7ea-2705-8867-c53e94a21ce4.gif)



##作成背景
最近読書をするようになってきたんですがこれまでほぼ読書をしてこなかった人間なので毎日継続して読むことが難しく感じていました
また、読むだけで終わっていたので本の内容が抜けていることがあり、本の内容を簡単にアウトプットできたらいいなと思いました!

自分と同じような悩みを持っている人が他にもいるのではないかなと感じ、アプリを制作しようと考えました。


##機能一覧

|       | 　　　　　　        機能　    　　　　    　　 |  　Gem     |
|:-----------------|:----------------|:------------------:|
|①| ログイン機能           | [devise](https://github.com/heartcombo/devise)  |
|②| 本の登録(CRUD)        |       ×       |
|③| おすすめ機能(CRUD)     |       ×        |
|④| アウトプット機能   　     |       ×         |
|⑤| いいね機能(Ajax) 　    |       ×       |
|⑥| コメント機能(Ajax)      |       ×      |
|⑦| フォロー機能　　       　|       ×      |
|⑧| プロフィールページ機能　　 |       ×      |
|⑨| ゲストユーザーログイン機能 |       ×       |
|⑩| ページネーション機能      |       [kaminari](https://github.com/kaminari/kaminari)        |
|⑪| 検索機能              |      [ransack](https://github.com/activerecord-hackery/ransack)|
|⑫| 画像投稿機能           |       ×           |



##使用イメージ

#####本の登録
![ezgif.com-gif-maker (4).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642425/a5a4b7ac-842b-c14f-3803-d598fcf85642.gif)



#####おすすめ機能
![ezgif.com-gif-maker (5).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642425/d1808e26-2226-6141-056e-d2736c27a2e1.gif)


#####アウトプット機能
![ezgif.com-gif-maker (6).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642425/89f8691f-4dcd-0363-6b22-77e0d260176e.gif)




##使用技術

######フロントエンド
HTML/CSS(Sass)
Bootstrap 4.5.3
jQuery 3.5.1

######バックエンド
Ruby 2.6.5
Ruby on Rails 6.0.3.4

######インフラ
AWS(VPC、EC2、RDS、Route53、S3、ALB、ACM、IAM)
Nginx、puma
Capistrano3
PostgreSQL 11.5


######ER図

![全画面_2021_02_03_15_29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642425/bf6b26d0-6a33-9cd4-10ae-055bcdf773fc.png)


######インフラ構成図
![infra_dio_—_ruby_practice.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642425/bfb2cf65-518f-4ddb-8708-d95156f21041.png)



##苦労した点

#####非同期処理
コメントやいいねの部分を非同期で実装したのですがうまく値が渡ってこず苦労しました。
ドキュメントや技術ブログなどをみて進めていきました。

#####AWSへのデプロイ
AWSへの基礎理解やデプロイ時に何度もエラーが出て苦しみましたがエラーログを見たり、調べたりして進めていきました。
またわからない用語がたくさんあり、何がわからないのかがわからない状況になってしまっていたのですが1つずつ調べながら全体を理解していきました。




##今後やりたいこと

- レスポンシブ対応
- Vue.jsの導入
- DockerやCircleCIの導入
- 無限スクロール実装
- 外部APIとの連携
- おすすめランキング機能の実装

##感想
アプリ開発するのは楽しいなと改めて感じました。
もちろんエラーにはまり苦しいと感じる時もありますが、それを乗り越えた時は思わず声に出してしまいそうなぐらいの喜びを感じています！
また日々自分のできることが増えていくことにやりがいを感じます！
まだまだ改善点がたくさんあるのでどんどんアップデートしていきたいと思います！


ここまで読んでいただきありがとうございました！
良かったと思った方は`LGTM`していただけると嬉しいです
サイト集の作成【プログラミング日記~ポートフォリオ⑥~】#7

#サイト集を作ろう‼
今回はスライドの２枚目に当たるサイト集のページを作ります‼![スライド3.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1043307/df4cd74e-43fe-6fd7-4b8f-42f2b787b337.jpeg)

```html:index.html

<div class="container second">
        <div class="works">
          <h2 id="works" class="section-title">WORKS</h2>
          <div class="work">
            <a href="https://www.google.com/?hl=ja"><img src="image/work.png" height="200px" width="200px">
            <h3>○○のサイト</h3>
            <p>説明文</p></a>
          </div>
          <div class="work">
            <a href="https://www.yahoo.co.jp/"><img src="image/work.png" height="200px" width="200px">
            <h3>○○のサイト</h3>
            <p>説明文</p></a>
          </div>
          <div class="work">
            <a href="https://www.google.com/?hl=ja"><img src="image/work.png" height="200px" width="200px">
            <h3>○○のサイト</h3>
            <p>説明文</p></a>
          </div>
          <div class="work">
            <a href="https://www.yahoo.co.jp/"><img src="image/work.png" height="200px" width="200px">
            <h3>○○のサイト</h3>
            <p>説明文</p></a>
          </div>
        </div>
      </div>

```
```css:style.css

* サイト集 */
.second{
  background-color: rgb(251, 180, 47)
}
.work{
  float: left;
  width: 25%;
  text-align: center;
  padding-top: 40px;
}
.work img{
  border: 2px solid black;
}
.work p{
  font-size: 16px;
  padding: 0 30px;
}

```
#完成したモノがこちら！
![スクリーンショット (11).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1043307/d174fdac-0dd0-6a5e-1709-0d03ceaeb578.png)
シンプルだし孫悟空の左胸４つ並んでるみたいになっちゃったけど今後アニメーションとかつけれたらなぁって思ってます！早く自分のさいといれてぇ～

#おわりに

シンプルなサイトだからなのか慣れてきたからなのか一瞬で完成しちゃいました‼完成したモノ見た感じ完全に前者ですね:upside_down:
シンプルでもまず完成させることが大事‼って心に言い聞かせて頑張ります、、、
では、それでは～