OmniAICreator/Qiita-1.07M huggingface dataset:
Node.js環境でgrpc-webを動かす

`@improbable-eng/grpc-web`はNode.jsサポートしている。

https://github.com/improbable-eng/grpc-web#nodejs-support

前回のgrpcエンドポイントにアクセスできるnode.jsプロジェクトを作ることを目標とする。

https://qiita.com/gp333/items/3ed426626b63578ae71b

# 最終的なプロジェクト構成

![スクリーンショット 2021-08-28 22.34.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88357/e88782c2-5fe7-05d8-571c-90315a2971cd.png)


# 必要なパッケージのinstall

`@improbable-eng/grpc-web-node-http-transport`が必要。

https://www.npmjs.com/package/@improbable-eng/grpc-web-node-http-transport

```
npm install @improbable-eng/grpc-web @improbable-eng/grpc-web-node-http-transport ts-protoc-gen
```

# .protoファイルの設置

`proto/cat.proto`を作成

```proto:cat.proto
syntax = "proto3";

// option go_package = "cat/;pb";

option go_package = "./;pb";

package cat;

service Cat {
    rpc GetMyCat (GetMyCatMessage) returns (MyCatResponse) {}
}

message GetMyCatMessage {
    string target_cat = 1;
}

message MyCatResponse {
    string name = 1;
    string kind = 2;
}
```

# コードの自動生成

`protoc.sh`を用意し実行する。

```sh:protoc.sh
protoc -I. \
    --plugin="protoc-gen-ts=./node_modules/.bin/protoc-gen-ts" \
    --js_out="import_style=commonjs,binary:./" \
    --ts_out="service=grpc-web:./" \
    ./proto/cat.proto
```

# クライアントコード作成


```js:index.js
const { GetMyCatMessage } = require("./proto/cat_pb");
const { CatClient } = require("./proto/cat_pb_service");
const {
  NodeHttpTransport,
} = require("@improbable-eng/grpc-web-node-http-transport");

const client = new CatClient("http://127.0.0.1:9000", {
  transport: NodeHttpTransport(), // これが必須
});

const request = new GetMyCatMessage();
request.setTargetCat("tama");
client.getMyCat(request, {}, (err, response) => {
  if (response == null) {
    console.log(err);
  } else {
    console.log(response);
  }
});
```

第二引数の`metadata`はなくてもいい。

```js
client.getMyCat(request, (err, response) => {
  if (response == null) {
    console.log(err);
  } else {
    console.log(response);
  }
});
```

# 実行

```
$ node index.js 
{
  wrappers_: null,
  messageId_: undefined,
  arrayIndexOffset_: -1,
  array: [ 'tama', 'mainecoon' ],
  pivot_: 1.7976931348623157e+308,
  convertedPrimitiveFields_: {}
}
```
VFXGraphでインタラクティブなエフェクトを作る

#やりたいこと
VRコンテンツを想定した、手で触ると反応してくれるエフェクトをVFXGraphで作成する。
#参考文献
https://github.com/Unity-Technologies/SpaceshipDemo
#Gif
![sample1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1947827/8afcd2b4-5e71-7e71-c0f6-d500e4c4ac0a.gif)
#グラフの中身
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1947827/b5039542-2659-3b0e-d9c4-0b3f71ed2fd3.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1947827/cab58134-ff07-a83c-5559-7dd2b63b1e99.png)

#軽く解説
このエフェクトはActiveというBoolパラメータをオンオフすることで上のgifのように色、位置、回転を変化出来ます。
UpdateParticle内のNewGroupNodeではActiveの状態に応じてActivateというカスタムアトリビュートを増減させています。InOutSpeedというパラメータはこのActivateの増減のスピードをそれぞれ調整できます。今回は(0.8,0.5）に設定しています。
その後、増減させたActivateをSaturateに入れることで値を0から１に制限しています。

OutputParticleQuadではUpdateで変化させたActivateを用いて色等を変化させています。

VRコンテンツ等で使うにはSetBoolからActivateの状態を切り替えればOK（例えばOnTriggerEnter内などで)

魔法陣テクスチャは以下のところからお借りしました。
あやえも研究所：http://ayaemo.skr.jp/

以上
Cookie にSession 情報保存されない？そう、デフォの api.php ならね。

#はじめに

Laravel 6で開発してて詰まったことあったので備忘録で残しておきます。


# やりたかったこと

## Session 情報をcookie に保存したかった。

下記のようなコードを書いた。


```php:api.php
Route::post("set_token", "Controller@setToken");
Route::get("fetch_token", "Controller@getToken");
```

```php:Controller
public function setToken(Request $request){
   session()->put('token', $token);
}

public function getToken(){
    $token = session()->get('token');
    return response()->json(['token' => $token]);       
}
```


シンプルなセッション情報の保存と、別リクエストでのその情報の利用です。

でもなぜかできない。セッション情報が保存されていない。

リクエスト内で保存直後に確認してみるとちゃんと入っている。そのリクエストが終了するとセッション情報もリセットされてしまう。


もちろんセッションドライバーは下記の通りcookieになっていることは確認した。


```:.env
SESSION_DRIVER=cookie
```

# api.phpに書かれたルーティングのリクエストではcookieの使用ができない。


これがわかったので、先程のルーティングの記述をweb.phpに移動させれば完了なのだが、web.phpではCSRFトークンの認証が必要となるため、それだと諸事情があって都合が悪かった。


# 解決策
当たり前ですが、デフォルトの web.php と api.php では、処理が違います。

https://qiita.com/pyon141/items/b3a2d2865c70b6a73ae2

\App\Http\Kernel.php にそれが記述されているので、そこを変更してやれば解決します。


## App Http Kernel.phpへの追記

### Kernel


デフォルト

```php:\App\Http\Kernel.php
protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class, // <--
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, // <--
            \Illuminate\Session\Middleware\StartSession::class, // <-- web.php内に記述されたルーティングのリクエストは、これらのミドルウェアによりCookie が使用できる
            \Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

        'api' => [
            'throttle:api',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
    ];

```



変更後

```php:\App\Http\Kernel.php
protected $middlewareGroups = [

        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            \Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

        'api' => [
            // この3行の追記
     +      \App\Http\Middleware\EncryptCookies::class,
     +      \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
     +      \Illuminate\Session\Middleware\StartSession::class,
            'throttle:api',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
    ];
```

これでapi.php 内のリクエストでもSession情報をcookie に保存できます。

#おわりに

本来は、api.php は外部からのリクエストをルーティングするためのファイルです。

なので、もしかしたら session や cookie が使えるようになることで、セキュリティ上の不都合ありそうな気はします。

その辺はちゃんと調べきれてないので、もし詳しい方いらっしゃいましたらコメントいただけますと幸いです。

## 参考記事

https://mseeeen.msen.jp/laravel-api-get-enabled-session/
spring-cloud-openfeignを使ってみた

# spring-cloud-openfeignとは？

ざっくり、
「最低限の実装でRestTemplateをもつClientクラスを提供してくれる」ライブラリです！

---

# 使い方

1. 依存に`spring-cloud-starter-openfeign`を追加する
2. FeignClientを有効化する
3. FeignClientを実装する

---

## 1. 依存に`spring-cloud-starter-openfeign`を追加する

gradleの場合、`build.gradle`に以下のように記述します

```groovy
...

ext {
    set('springCloudVersion', "2020.0.3")
}

dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
    }
}

dependencies {
    ...
    implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
    ...
}
```

---

## 2. FeignClientを有効化する

mainクラスに`@EnableFeignClients`を付与します

```java
@SpringBootApplication
@EnableFeignClients
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class);
    }
}
```

---


## 3. FeignClientを実装する

`@FeignClient`を付与したinterfaceを作成します

```java
@FeignClient(name = "sample", url = "http://localhost:8080")
public interface SampleClient {
    @GetMapping("/server/hello")
    String hello();
}
```

---

以上！！

これで、以下のような実装をしたのと同じです！

```java
public SampleClient {
    private final RestTemplate restTemplate = new RestTemplateBuilder()
            .rootUri("http://localhost:8080")
            .build();
    
    public String hello() {
        return restTemplate.getForObject("/server/hello", String.class);
    }
}
```

ここからは、FeignClientについて踏み込んで見ていきます。

---

# IFへの対応

`@FeignClient`を付与したinterfaceでは、RestControllerと同じようにIFを記述できます。

---

なので例えばパラメータを載せたい場合は`@RequestParam`を使えば良いし

```java
    @GetMapping("/server/hello")
    String hello(@RequestParam String greeting);
```

ヘッダを載せたい場合は`@RequestHeader`を使えば良い

```java
    @GetMapping("/server/hello")
    String hello(@RequestHeader(value = "SAMPLE-HEADER") String header);
```

> ヘッダを載せたいときはRestTemplateだと記述量が増えるのでありがたい…！

---

# 設定値の変更

propertyを記述することで実現できます。

ありがちなread timeoutとconnection timeoutだと、以下のような記述で設定ができます

```yaml:application.yaml
feign:
  client:
    config:
      sample: # @FeignClient name
        connect-timeout: 1000 # milli seconds
        read-timeout:    5000 # milli seconds
```

---

# interceptorの反映

`RequestInterceptor`(RestTemplateでいう`ClientHttpRequestInterceptor`)を反映したい場合は、Bean登録しておくだけでOK！

ただ、Clientごとに適用するinterceptorを変えたいようなケースでは
専用のConfigurationクラスを作成してあげる方法もあります！

---

```java:専用Configurationクラス
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.context.annotation.Bean;

//@Configuration // Configurationは不要
public class SampleConfig {
    @Bean
    public RequestInterceptor sampleRequestInterceptor() {
        return new RequestInterceptor() {
            @Override
            public void apply(RequestTemplate template) {
                // 実装する
            }
        };
    }
}
```

---

作成したらFeignClientでConfigurationクラスを以下のように指定してあげればOK！

```java
@FeignClient(name = "sample", url = "http://localhost:8080", configuration = SampleConfig.class)
public interface SampleClient {
    ...
}
```

> 他にもapplication.yamlでクラス指定をしてあげる方法もありますが、個人的にはConfigurationクラスを作るのがいいかなと
【初心者向け】Dockerのはじめかた

#はじめに#
Dockerをインストールするところまで実践しましたので備忘録として残していきます。

・Dockerとは何か
・Dockerのメリット
・Dockerのインストール方法

以上の項目についてまとめていきます。

誤り等ありましたらご指摘いただけると幸いです。


#Dockerとは#
　Dockerとは、一言で言うと仮想環境を作り出すことができるソフトウェアのことです。仮想環境とは、**自分のパソコン上に、開発に必要なツールを擬似的に再現した環境**のことです。もう少し具体的に見ていきましょう。
　実はプログラミング言語を使って開発するにはいくつかのツールが必要です。必要なツールを構成することを環境構築と言ったりします。例えば、PHPの代表的な構成にLAMP環境というものがあります。

####LAMP環境とは####
・Linux
・Apache
・MySQL
・PHP
以上の頭文字をとってLAMPと言います。
　ちなみにLinuxはOS（オペレーティングシステム）、ApacheはWebサーバー（ミドルウェア）、MySQLはデータベース、PHPはプログラミング言語になります。それぞれの用語については機会があれば別の記事で書いていきます。
　PHPで開発をするにはこのような環境を構築する必要があります。

　話を戻しますが、Dockerを使うことで自分のパソコン上にこれらの仮想環境を作り上げることが出来ます。


#Dockerのメリット#
　Dockerのメリットを理解するには、コンテナと言う概念を理解する必要があります。コンテナとは、物流に使われる箱のことです。船の上とかに乗ってるアレですね。あの中に、ApacheやMySQLやPHPが入っているとイメージしてください。そのコンテナをそのまま本番環境に持っていくことで、開発環境と同じ環境で動かすことが出来ます。これにより、開発環境では動いたけど本番環境で動かなくなった・・・みたいなことを防ぐことが出来ます。


#Dockerのインストール#
　Dockerのインストール方法にはいくつか種類がありますが、今回はDocker Desktopというものを使っていきたいと思います。

![スクリーンショット 2021-08-28 21.29.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1558223/2582098a-d364-8d22-a867-194f47f8a265.png)

　Docker Desktopで検索すると上記のような画面のページが出てきます。今回はMacの画面ですが、Mac with intel ChipまたはMac with Apple Chipどちらか自分のパソコンに該当する方を選んでクリックしていきましょう。するとdmgファイルがインストールされます。次にダウンロードされたdmgファイルを実行することでインストールが開始されます。
　これでインストールは完了です。簡単ですね。


#まとめ#
　Dockerとは何か、Dockerのメリット、インストール方法について学んできました。さらに理解を深めて、現場で使えるレベルにしていきたいと思います。:punch:
SQLの自己結合を用いて数学の順列や組み合わせを表現する

## はじめに

SQLにおいて、自分はあまり聞き慣れなかった自己結合の今後役立つかもしれないテクニックを紹介していきます。

実行結果はこちらで確認できます。

https://www.db-fiddle.com/

## 基本となるデータ

何かのメンバー一覧だと思ってください。

```sql
CREATE TABLE members (
  id INT NOT NULL PRIMARY KEY auto_increment,
  name TEXT
);

INSERT INTO members VALUES
    (1, 'tanaka'),
    (2, 'okada'),
    (3, 'hiranuma');
```

## 自己結合を用いて重複順列を作る

重複順列とは...異なるn個のものから、重複を許し、r個とる順列

```math
n^r
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/a3136284-ffc6-36ce-5af0-9168b240516f.png)

http://www.it-passport.org/category/technology-calculation/IPH242T078.html

Query

```sql
    SELECT
      M1.name,
      M2.name
    FROM members M1 CROSS JOIN members M2;

```

Results

| name1     | name2     |
| -------- | -------- |
| tanaka   | tanaka   |
| okada    | tanaka   |
| hiranuma | tanaka   |
| tanaka   | okada    |
| okada    | okada    |
| hiranuma | okada    |
| tanaka   | hiranuma |
| okada    | hiranuma |
| hiranuma | hiranuma |

これはいわゆる総当たり戦で全ての組み合わせを列挙してるだけです。

## 自己結合を用いて順列を作る（重複を許さない）

では、テーブル `members` を使って、SQLで順列を表現します。

順列は、並び順を区別し、当然ながら重複ありません。

今回であれば、3つのメンバーの2人で並べる方法なので、式にすると。

```math
_{3}P_{2}
```

3×2=6パターンの並べ方があります。

これをSQLの自己結合を用いて表現すると以下のようになります。

Query

```sql
    SELECT
      M1.name AS name1,
      M2.name AS name2
    FROM members M1
    INNER JOIN members M2 ON M1.name <> M2.name;
```

Results

| name1    | name2    |
| -------- | -------- |
| okada    | tanaka   |
| hiranuma | tanaka   |
| tanaka   | okada    |
| hiranuma | okada    |
| tanaka   | hiranuma |
| okada    | hiranuma |


## 自己結合を用いて組み合わせを作る

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/3fd23fd5-5a21-e8bc-2f20-020daf110261.png)

https://juken-mikata.net/how-to/mathematics/permutation.html

今回のケースを計算すると

```math
_{3}C_{2} \\
= \frac{3\times2}{2} \\
= 3 \\
```

パターンの並べ方があります。

これをSQLの自己結合を用いて表現すると以下のようになります。後でもいい。

Query

```sql
    SELECT
      M1.name AS name1,
      M2.name AS name2
    FROM members M1
    INNER JOIN members M2 ON M1.name > M2.name;
```

文字コードの順にソートして、自分よりも前に来るようにしています。

Results

| name1  | name2    |
| ------ | -------- |
| tanaka | okada    |
| tanaka | hiranuma |
| okada  | hiranuma |

## 参照

https://www.amazon.co.jp/dp/4798157821/

44 - 48p 

## アウトプット100本ノック実施中

https://qiita.com/ryosuketter/items/713474dbd009870e4103
Flutter Appを実機で動かす (M1 Mac, iOS)

# 環境

- MacBook Air (M1, 2020)
- MacOS 11.4
- Flutter (stable, 2.2.3)

# Homebrew Cask

次のコマンドをターミナルで実行し、Flutterをダウンロード、インストールする。

```
brew install --cask flutter
flutter doctor
```

出力される指示に従って環境構築を進める。

## Rosetta 2

FlutterとDartはM1チップのMacに適応している最中であるため、
M1 MacではFlutter SDKのインストール後に下記のエラーが出ることがある。

```
Bad CPU Type in executable
```

その場合、Rosetta 2をインストールし、M1が解釈できるバイナリに翻訳する必要がある。

```
softwareupdate --install-rosetta
```

M1 MacでFlutterを使うことについての補足は、公式がこのページにまとめている。
https://github.com/flutter/flutter/wiki/Developing-with-Flutter-on-Apple-Silicon

# iOSプラットフォームのセットアップ

iOS用のFlutterアプリを開発するにはXcodeが必要なので、
[Apple Developerのページ](https://developer.apple.com/xcode/)からダウンロードするか、[App Store](https://apps.apple.com/us/app/xcode/id497799835)から入手する。

## 実機にデプロイする

### Cocoapods

HomebrewでCocoapodsをインストールする。

```
brew install cocoapods
```

### MacにiPhoneを接続

双方でデバイスを信頼するかどうかのダイアログが表示されるので、
次に進むには「信頼」を選択する。

### Xcode

プロジェクトのディレクトリに移動し、下記コマンドでXcodeを開く。

```
cd my_app
open ios/Runner.xcworkspace
```

1. プルダウンから接続したデバイス名を選択する

1. TARGETS > Runnerを選択する

1. Signing & Capabilitiesタブを開く

1. Add Account…ボタンを押下する<br/>

    ![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1749115/473e04fa-aadb-31cd-8ca2-f51b870b0b5e.png)

1. ポップアップウィンドウが表示されるので、Apple IDでログインする

1. 元の画面に戻る

1. Teamプルダウンメニューから手順5.でログインしたチームを選択する

    ![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1749115/4cbaa0f3-5093-5f4a-a63c-9c71a062f4d7.png)

1. Bundle Identifierについてのエラーが出るので、一意の値となるよう変更する。<br/>これは実際にApp Storeで発表する際には重要な値となるが個人で使用する分にはあまり神経質になる必要は無い。

    ![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1749115/6521b327-19b1-fa10-779e-66d917e4a5cd.png)

### デペロッパを信頼する

画面左上の実行ボタンをクリックするとビルドが開始される。
途中で何度かパスワードを求められるので、Macのユーザーパスワードを入力する。
ビルド成功後、接続したiPhoneにアプリがインストールされる。
しかし、**デベロッパを信頼**していないので、iPhoneでアプリを実行することはできない。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1749115/09e7f629-a26c-2dce-f826-223cc2058682.jpeg)

設定画面 > 一般 > プロファイルとデバイス管理から、デペロッパを信頼する。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1749115/a3842bfe-ab2d-b427-150c-2087c20446c1.jpeg)
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1749115/8988dc21-d062-634c-e5c7-c7daed9058ea.jpeg)
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1749115/909bc29b-00f1-ef4b-b95c-7012f1395361.jpeg)

再度Macからアプリを起動すると、今度はiPhoneで実行できる。
リアルタイムの時刻と干支を表示（魔歴・悪魔干支）

#目次
[1.前回投稿](#1-前回)
[2.概要](#2-概要)
[3.内容](#2-内容)
[4.おわりに](#5-おわりに)

#1. 前回投稿

https://qiita.com/ak-matsu/items/ba79cfc46793e5432561


#2. 概要
htmlファイルだけでリアルタイムに時刻と干支を表示させるプログラミングを作成。
この時刻表示は普通ではありません。

### 作成理由

箸休め的にrailsチュートリアル以外でやってみたことを投稿
html単体で時刻と干支を表示させてみました。
きっかけは聖飢魔IIが好きな知り合いのユーチューブライブを見ていた際、
時刻をhtmlファイルを使ってライブ画面に時刻を表示させてみたい
という一言から作ってみました。
聖飢魔IIは魔歴表示でカウントされるので
ただの時刻表示ではなく、知り合いの好みに合わせた時刻表示にさせてみました。

https://ja.wikipedia.org/wiki/%E9%AD%94%E6%9A%A6

#3. 内容

作成したもの
![時刻表示.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459220/b8979621-18e7-0514-f71c-5d0846975fae.gif)

悪魔干支は13種類なんですね。
そのため、var eto = now.getFullYear()%13　こちらを13で余を計算。
普通の干支にしたい場合は配列内容とgetFullYearの割る数字を変更すれば表示できます。
文字化けする場合は　meta charset="UTF-8"　の　UTF-8 を
Shift_JIS、EUC-JP などに変更してください。

```html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title></title>
</head>
<body>
  <font size="100%"><b>
<span id="view_clock"></span>

<script type="text/javascript">
timerID = setInterval('clock()',500); //0.5秒毎にclock()を実行

function clock() {
	document.getElementById("view_clock").innerHTML = getNow();
}

function getNow() {
	var now = new Date();
	var year = now.getFullYear();
	var mon = now.getMonth()+1; //１を足すこと
	var day = now.getDate();
	var hour = ("0" + (now.getHours())) .slice(-2);
	var min = ("0" + (now.getMinutes())) .slice(-2);
	var sec = ("0" + (now.getSeconds())) .slice(-2);
	var you = now.getDay(); //曜日(0～6=日～土)
    var eto = now.getFullYear()%13
  
	//曜日の選択肢
	var youbi = new Array("日","月","火","水","木","金","土");
  
    //干支の選択肢
    var etomareki = new Array("妖精","河童","つちのこ","三ツ首竜","鵺","一角獣","モグラザメ","化猫","蝦蟇","火の鳥","怪奇植物","人魚","夜叉");

	//出力用
	var s = "D.C."+(year-1998)+ "(" + year + ")" + "年" + mon + "月" + day +  "日 (" + youbi[you] + ")" + hour + "時" + min + "分" + sec + "秒" + "<br>" + "悪魔干支 "+etomareki[eto];
	return s;
}
</script>
    </b></font>
</body>
</html>
````

#4. おわりに
以下の参考URLを見て作成してみました。
検索力が前より向上したのではないかと思う。


参考URL

http://www.shurey.com/js/samples/2_msg10.html
[シリーズ 全3回] Vagrant を使って VM を構築する


# 概要

仮想PC (以降「VM」) が 1台 あるいは 2台必要になった場合に、
Vagrant + VirtualBox を使って VM を立てるための手順である.

VM の OS は Linux 「Centos-7-v7.4-Minimal-CLI」を使う.

|コンテンツ|
|:--|
|[[01] Vagrant を使って VM「192.168.101.1」を立てる](https://qiita.com/robozushi10/items/9b580af05646eb81c50b)|
|[[02] Vagrant を使って VM「192.168.101.1」を立てる際のトラブル事例とその対策方法](https://qiita.com/robozushi10/items/0d956169514fc18f0bdf)|
|[[03] Vagrant を使って VM「192.168.101.1」と「192.168.101.2」を立てる](https://qiita.com/robozushi10/items/dc9e74a50a051f8f7d67)|
PrettierでApexを自動フォーマットできるように

package.jsonに記述には
バージョンペアは下になっていると、ロードエラーを発生する

``` 
    "prettier": "^2.0.5",
    "prettier-plugin-apex": "^1.6.0",
```

下のバージョンペアに変更して、VSCodeを再起動するとエラーが消し去れた![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/356407/464e18be-fa35-e063-d35d-bd5d085f6274.png)



``` 
    "prettier": "2.3.2",
    "prettier-plugin-apex": "1.10.0"
```

後に、先のエラーを出るバージョンペアに戻ってVSCode再起動してもエラーが再発生されない
【Prepros】「Write any browsers query (for instance, 'defaults') before 'not dead'」とエラーが出た場合の対処法

## 環境
+ Microsoft Windows 10.0.22000.978
+ Prepros 7.3.48

## エラーの内容
一番上に「Failed to Process (file path)」、その下に「Write any browsers query (for instance, 'defaults') before 'not dead'」と書かれている。
![スクリーンショット (156).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1946472/0e8b09bb-5bd3-b9a6-bd3f-0c8250fc85b7.png)

## 対処法
このようなエラーが表示される場合、Autoprefixerの設定でTarget Browsersのリストの一番上に「not dead」があるはずである。エラーを消すためには、not deadの上に1つ以上条件を追加する必要がある。

### 設定画面
Preprosでプロジェクト名を右クリック --> Project Settings --> CSS Tools --> Autoprefixer --> Target Browsers
![スクリーンショット (157).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1946472/1bfc678e-33de-9909-9fdf-81ea73dc3992.png)

### 設定変更
「not dead」を一番下にする。
![スクリーンショット (158).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1946472/1f1a192f-5f2a-8652-9306-88d63ec90fd2.png)

### 設定後
設定後に実行すると「Success」と表示される。
![スクリーンショット (159).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1946472/fba78fcb-e9f0-dad4-2468-ec636d923f7e.png)
pycharmの例外ブレークポイント

PyCharm で pythonプログラムを実行中に何らかの例外が発生した場合に「例外ブレークポイント」を設定しておけば、デバッグで実行すると、例外発生時の変数等が見られるので、超便利。
設定方法をよく忘れるので備忘録として。
画像のバージョンは「PyCharm 2021.2.1(Community Edition)」です。
![2021-08-28 20_47_22-Window.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566633/741e3dd7-6f2a-dd45-e783-1a0a35653d33.png)
以上。
ラムダ式をコピーしたときの挙動

# はじめに

こんなミスするの僕だけだと思いますが忘れないように記事にしておきます

# 本文

こういうコードを書いたとすると、

```c++
#include <iostream>
#include <functional>

struct Hoge{
  int x;
  std::function<int()> f;

  Hoge(int x): x(x), f{[&](){ return this->x; }} {}
};

int main() {
  
  Hoge hoge(0);
  std::cout << hoge.f() << "\n";

  hoge.x = 1;
  std::cout << hoge.f() << "\n";
}
```

出力はこうなりますね

```
0
1
```

書き方がよろしくないとかは今は許してください

<br><br>


ではこうしてみると

```c++
#include <iostream>
#include <functional>

struct Hoge{
  int x;
  std::function<int()> f;

  Hoge(int x): x(x), f{[&](){ return this->x; }} {}
};

int main() {
  
  Hoge hoge(0);

  Hoge fuga = hoge;
  std::cout << fuga.f() << "\n";

  fuga.x = 1;
  std::cout << fuga.f() << "\n";
}
```

出力はこうなります

```
0
0
```

つまり、ラムダ式がキャプチャしている変数は hoge のほうの x のままということです

そのため、こうすれば

```c++
#include <iostream>
#include <functional>

struct Hoge{
  int x;
  std::function<int()> f;

  Hoge(int x): x(x), f{[&](){ return this->x; }} {}
};

int main() {
  
  Hoge hoge(0);

  Hoge fuga = hoge;
  std::cout << fuga.f() << "\n";

  fuga.x = 1;
  std::cout << fuga.f() << "\n";

  hoge.x = 2;
  std::cout << fuga.f() << "\n";
}
```

ちゃんと書き換わります

```
0
0
2
```

# おわりに

こうなることに全く気付かなくて一時間無駄にしました
40 代おっさん Laravel 環境の構築してみた

## 本記事について

本記事は AWS 初学者の私が学習していく中でわからない単語や概要をなるべくわかりやすい様にまとめたものです。
もし誤りなどありましたらコメントにてお知らせいただけるとありがたいです。

## 構築環境

・EC2:Amazon Linux2
・PHP7.3
・Composer
・Laravel Framework8

## 初期設定

<https://qiita.com/kou1121/items/42a863971d2d7d270b2c>

## Apacheインストール

インストール

```shell
$ sudo yum install httpd
```

Apache起動

```shell
$ sudo systemctl start httpd
```

動作確認

```shell
$ sudo systemctl status httpd
```

![動作確認.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641940/c0f40dde-2261-5af8-b17f-7c3aa4f4220c.png)

緑の文字
active (running)
となっていれば大丈夫

システム起動時に起動する設定

```shell
$ sudo systemctl enable httpd
```

上記設定の確認

```shell
$ sudo systemctl is-enabled httpd
```

enabled って出れば大丈夫

## PHPインストール

インストール

```shell
$ sudo amazon-linux-extras install php7.3
```

バージョンの確認

```shell
$ php -v
```

インストールされたモジュールの確認

```shell
$ sudo yum list php* | grep php7.3
```

次のどれかがなかったらインストール
ないとLaravelのインストール時やプロジェクト作成時にコケるらしい

php-xml
php-mbstring
php-dom
php-zip

関連モジュールのインストール

```shell
$ sudo yum install php-xml php-mbstring php-dom php-zip
```

## PHPの設定

設定ファイルを開く

```shell
$ sudo nano /etc/php.ini
```

開いたら修正

```shell
# HTTPヘッダにPHPのバージョンを記載しない(セキュリティ的に)
# expose_php = On
expose_php = Off

# メモリ上限を引き上げる(結構デフォルトのメモリは少なめ)
# memory_limit = 128M
memory_limit = 256M


# POST送信の許容サイズを引き上げる
# post_max_size = 8M
post_max_size = 16M

# アップロードファイルの許容サイズを引き上げる
# upload_max_filesize = 2M
upload_max_filesize = 16M

# timezoneの設定
# date.timezone =
date.timezone = Asia/Tokyo
```

php-fpmの再起動（php.iniの設定を反映させるため

```shell
$ sudo systemctl restart php-fpm
```

## Laravelプロジェクトの作成

composerインストール

```shell
$ curl -sS https://getcomposer.org/installer | php
```

Pathの通っている/usr/binに移動させる

```shell
$ sudo mv composer.phar /usr/bin/composer
```

composerの準備が出来ました。

/var/www/htmlにプロジェクト作ったほうが良いのですが
今回は参考資料のとおりにやってみます（怖いので・・・）

```shell
$ mkdir ~/html
$ cd ~/html
```

laravelプロジェクトの作成

```shell
$ composer create-project --prefer-dist laravel/laravel blog
```

プロジェクトの更新

```shell
$ cd ~/html/blog
$ composer update
```

権限周りの変更

```shell
$ cd ~
$ sudo chmod -R 775 ~
$ sudo chmod -R 775 ~/html
$ sudo chmod -R 777 ~/html/blog/bootstrap/cache
$ sudo chmod -R 777 ~/html/blog/storage
```
## Laravel のバージョン確認

プロジェクトフォルダで次のコマンド

```shell
$ cd ~/html/blog/
$ php artisan -V
```

## Apacheの設定

conf作成

```shell
sudo nano /etc/httpd/conf/httpd.conf
```

httpd.conf

```shell
DocumentRoot /home/ec2-user/html/blog/public
<Directory /home/ec2-user/html/blog/public>
    #.htaccessを利用可能にする
    AllowOverride All

    #アクセス許可
    Require all granted
</Directory>
```

上記で書き換え
※nanoエディター日本語が文字化けしました・・・
わからないので＃のところは消しました

## Apacheの再起動

```shell
sudo systemctl restart httpd
```

これで表示されるはずです・・・

![laravel.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641940/c0cd620a-af9b-5926-3881-491ca062da49.png)

ふ～～疲れた～～
これでWEB開発ができるようになりました＞＜
頑張ります。

##　参考資料

<https://qiita.com/thfree0119/items/da37eaa85d529955aa90>
<https://qiita.com/yoriblog/items/05e53fa005f4dc223ca3>
Kubernetes入門 ~概念編~

## Kubernetes概念図

Kubernetesのアーキテクチャは**マスター(コントロール プレーン)**と**ノード**で構成される。

![Untitled Diagram.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355263/427a8eaf-2702-1069-9890-8339ff34e89d.png)

## k8sクラスタコンポーネント　用語説明

### マスター(コントロール　プレーン)
|コンポーネント|概要|
|:--|:--|
|kubectl|k8sクラスタ操作用のCLI|
|kube-apiserver|APIサーバ　<br>kubectlなどのクライアントからのRESTリクエストを受け付け、操作を提供する。|
|etcd|クラスタの全ての管理データが保存される。|
|kube-scheduler|ワークロード専用のスケジューラ機能<br>アプリケーションをスケーリングするきに、どのノードがワークロードを実行して開始できるかを判断する。|
|kube-controller-manager|Podのレプリケートやノード調整などのアクションを実行する。|

### マスター
|コンポーネント|概要|
|:--|:--|
|kubelet|Kubernetesエージェント<br>マスターからのオーケストレーション要求やポッド・コンテナの実行をする、|
|kube-proxy|各ノードで動作しロードバランシングを提供する。|
|コンテナーランタイム|コンテナ実行基盤<br>DockerとContainerdが有名。<br>各クラウドが提供してるマネージドK8sではだいたいContainerdが利用されている。|
|coredns|ポッドがサービス名からIPアドレスを得るために利用されるDNS|

## 役割

マスター

* K8sクラスタのコントロール
* ポッドのスケジュール

[GKE](https://cloud.google.com/kubernetes-engine)、[AKS](https://azure.microsoft.com/ja-jp/services/kubernetes-service/)、[AWS EKS](https://aws.amazon.com/jp/eks/?whats-new-cards.sort-by=item.additionalFields.postDateTime&whats-new-cards.sort-order=desc&eks-blogs.sort-by=item.additionalFields.createdDate&eks-blogs.sort-order=desc)などのマネージドK8sサービスではマスターの管理はクラウドベンダー側の責任となっている。

ノード

* コンテナ実行


## 【参考文献】

* https://kubernetes.io/ja/docs/concepts/overview/components/
* https://docs.microsoft.com/ja-jp/azure/aks/concepts-clusters-workloads
Jetson Nanoと Jetson Xavier NXで YOLOv5を動かす

## 最新版をご覧ください。
https://qiita.com/ez_tera/items/e62987c66113c2e9d85e

* Jetson Nano 4GB
* Jetson Xavier NX
* logicool C270N
* JetPack 4.6

参考：https://qiita.com/ryryry/items/d95c2207b9608243340e

## パッケージの更新
sudo apt update
sudo apt upgrade
（Configuring docker.io -> Yes）

## OpenCVのインストール
「apt install python3-opencv」ではweb camをソースとした時にSegmentation faultエラーとなったため、ソースコードからインストールしました。

### スワップ領域の設定（Xavier NXでは不要です）
sudo apt install dphys-swapfile
sudo nano /etc/dphys-swapfile

```:/etc/dphys-swapfile
CONF_SWAPSIZE=4096
CONF_MAXSWAP=4096
```

reboot

### OpenCVのインストール
wget https://github.com/Qengineering/Install-OpenCV-Jetson-Nano/raw/main/OpenCV-4-5-0.sh
sudo chmod 755 ./OpenCV-4-5-0.sh
./OpenCV-4-5-0.sh
rm OpenCV-4-5-0.sh


参考：https://qengineering.eu/install-opencv-4.5-on-jetson-nano.html

### こちらもご参照ください
https://qiita.com/ez_tera/items/aa964ae489e1be57cedb

## torchのインストール
* torch（PyTorch）は、Facebookが開発を主導したPython向けの機械学習ライブラリです。

wget https://nvidia.box.com/shared/static/cs3xn3td6sfgtene6jdvsxlr366m2dhq.whl -O torch-1.7.0-cp36-cp36m-linux_aarch64.whl
sudo apt install python3-pip libopenblas-base libopenmpi-dev
pip3 install Cython
pip3 install numpy torch-1.7.0-cp36-cp36m-linux_aarch64.whl

## torchvisionのインストール
* tourchvisionは、画像処理におけるデータセット（MNIST、COCO）、モデルアーキテクチャ、画像変換処理から構成されたパッケージです。

git clone --branch v0.8.1 https://github.com/pytorch/vision torchvision
cd torchvision
export BUILD_VERSION=0.x.0
sudo python3 setup.py install
cd


## YOLOv5のインストール
pip3 install -U pip
pip3 install -U setuptools

git clone https://github.com/ultralytics/yolov5.git

インストール済みのパッケージは事前に無効にしておきます。

```:requirements.txt
#opencv-python>=4.1.2
#torch>=1.7.0
#tensorboard>=2.2
#torchvision>=0.8.1
```
pip3 install -r requirements.txt

## YOLOv5の動作確認
* detect.pyの実行

python3 detect.py

:::note info
初回起動時はウェイトファイル「yolov5s.pt」がダウンロードされます。
:::

:::note info
検出結果は「yolov5/runs/detect/exp」内に保存されます（bus.jpg、zidane.jpg）。
:::

* webカメラから動画を入力して認識を実行（yolov5s.ptを使用)

python3 detect.py --source 0 --imgsz=256 --nosave

:::note info
Jetson Nano：1 frame：0.063s（15.8fps）
:::

:::note info
Jetson Xavier NX（MODE 20W 6CORE）：1 frame：0.029-0.033s（30.3fps）
:::

## この後は
https://qiita.com/ez_tera/items/169afe7da8d570c79bc7
Logファイルの権限エラーの解決方法（Laravel）

プログラミング初心者です
##環境
Laravel 5.8
PHP 7.3.29
AWS EC2 にてデプロイ

##問題
データ処理送信を行う際、loggerメソッドでlogを記載しようとしたが、当日のLogファイルのPermision Deniedつまり権限エラーが出てしまいました。
```$ php artisan```実行時も同様のエラーが出ました。
以下エラー例文です。

```
UnexpectedValueException : The stream or file
“/test/laravel/storage/logs/laravel-2021-01-01.log” could not be opened: failed 
to open stream: Permission denied
```



##やってみたこと
ターミナルで以下を入力します。
storageディレクトリの権限を777に変更します。
chmodの権限について[こちら](https://qiita.com/ntkgcj/items/6450e25c5564ccaa1b95)の記事が詳しいです。


```
$ sudo chmod 777 -R storage/
```
####別問題発生
上記のコマンドは、当日のみのLogファイル権限が変更されます。
例：当日が1/1なら、laravel-2021-01-01.logの権限が変更。
つまり日付が変わってしまうと、またコマンド入力して権限変更させないといけないのです。

##解決方法
```config/logging.php``` ファイルの中の daily の部分を以下のように変更します。

```config/logging.php
'daily' => [
            'driver' => 'daily',
            'path' => storage_path('logs/laravel-'.php_sapi_name().'.log'),
            'level' => 'debug',
            'days' => 14,
        ],
```
php_sapi_name()を追加します。
以降Logファイル名は laravel-cli-2021-01-01.log のようになり、cliがつくようになりましたが、自分はこれで日を跨いでも無事に動き解決できました。
参考記事は[こちら](https://conocode.com/troubleshooting/laravel-log-permission-php-artisan-fail/)
[C++] 色んな型の上限・下限を取得する

# はじめに
C++でアルゴリズム勉強している過程で得た知識の備忘録です。

# 色んな型の ~~無限大~~ 上限値
`<limit>`パッケージを読み込むことで、いろんな型の ~~無限大~~ 上限値・下限値を取得できます。

```cpp
 double max_double = numeric_limits<double>::max();
 float max_float = numeric_limits<float>::max();
 int max_int = numeric_limits<int>::max();
 unsigned int max_unsigned_int = numeric_limits<unsigned int>::max();
 
 cout << "max double = " << max_double << endl;
 cout << "max_float = " << max_float << endl;
 cout << "max_int = " << max_int << endl;
 cout << "max_unsigned_int = " << max_unsigned_int << endl;
```

結果

```
max double = 1.79769e+308
max_float = 3.40282e+38
max_int = 2147483647
max_unsigned_int = 4294967295
```
Microsoft Azureを使って、最小構成でWebサーバー(Ubuntu)を構成してみる -リソースグループの作成

#はじめに
[参考書籍や目次はこちら](https://qiita.com/y_kai_acc/items/f5bc3abd063ac2ab76d8#当記事の利点)

前記事 [Microsoft Azureのアカウントの開設はこちら](https://qiita.com/y_kai_acc/items/de1a79c161fca54f439e)

#目的
##### リソースグループの作成
Microsoft Azure上でリソースを管理するために設定しておくと便利

#準備するもの
特になし。強いて言えば、自分のリソースグループにしたい英文文字列のアイディア。

#手順 リソースグループの作成 

####① Azure Portalにアクセスする。
[Azure Portal](https://portal.azure.com/)

####② Azure Portal画面の左側にあるAzure Portalメニューから、「すべてのサービス （All Serveices）」をクリックする。
画面が分からない場合は以下のDocs参照
[Azure Portal の概要](https://docs.microsoft.com/ja-jp/azure/azure-portal/azure-portal-overview)

####③ サービスのフィルターで「リソース」と検索して、「リソースグループ」をクリックする。
リソースグループは比較的使用度が高いため、星マークをクリックしてお気に入り登録することをおすすめする。
お気に入り登録すると、Azure Portalメニューから簡単にアクセスできるようになる。

####④ リソースグループを新規作成する。
新規作成からリソースグループを新規作成する。

####⑤ 設定項目を入力する。
以下の項目を入力していく。

| 項目名 | 入力値 |
|:-----------|:------------|
|サブスクリプション| （デフォルト）無料サブスクリプション|
|リソースグループ|（任意の英語文字列)|
|リージョン|（日本で作るなら）西日本|

リソースグループの名称は任意と書いたが、例えば以下のような命名規則を作っておくとリソースの管理が便利。
**(任意の英語文字列)+'-'+'(西日本リージョン)w'+'-'+'（リソースグループの略）rg'**
例えば、'test'というリソースグループを作る予定の場合、'test-w-rg'とする。
東日本リージョンへ拡張する場合や、他のリソースを展開する場合も、命名ミスが発生しにくい。

このテクニックは、**作りながら覚えるMicrosoftAzure入門講座（IaaS編)**で紹介されてました。

ちなみに、無料サブスクリプションだと、西日本リージョンにしか展開できない。
東日本リージョンは、従量課金サブスクリプションにアップグレードすると使えるようになる。
取りあえずAzureでサーバーを作って見たい人はあまり気にしなくて問題ない。

####⑥ 各項目を設定し終えたら、「確認および作成」ボタンをクリックして、リソースグループをデプロイする。
デプロイが完了したら、この記事の内容は完了。

#おまけ
リソースグループを設定すると、リソースグループ全体に適用するポリシーの設定が出来るようになる。
業務利用する場合は、データセンターの設計に規制がかかる場合があるので、ポリシーを利用することで、ポリシー違反したリソース展開に警告を発することが出来るようになる。

#次の記事
[仮想ネットワークの作成はこちら](https://qiita.com/y_kai_acc/items/d602a0ac95221e8c0d65)
Microsoft Azureを使って、最小構成でWebサーバー(Ubuntu)を構成してみる -仮想ネットワークの作成

#はじめに
[参考書籍や目次はこちら](https://qiita.com/y_kai_acc/items/f5bc3abd063ac2ab76d8)
前記事 [リソースグループの作成はこちら](https://qiita.com/y_kai_acc/items/31f156c7c1450fd20ded)

#目的
##### 仮想ネットワークの作成
様々なリソースを展開するための準備として、仮想ネットワークを作成する。
とりあえずルータとLANケーブルを買ってくるイメージ。

#準備するもの
特になし。

#手順 仮想ネットワークの作成

####① Azure Portalメニューから仮想ネットワークを検索し、クリック。
Azure Portalの操作が分からない方は、[前記事]の手順①、②参照。

####② 仮想ネットワークを新規作成する。
新規作成から仮想ネットワークを新規作成する。

####③ 設定項目を入力する。
以下の項目を入力していく。

| 項目名 | 入力値 |
|:-----------|:------------|
|サブスクリプション| （デフォルト）無料サブスクリプション|
|リソースグループ|(前記事で作成したリソースグループ名)|
|名前|(任意の仮想ネットワーク名)|
|地域|（日本で作るなら）西日本|

前記事の命名規則に則るのなら、**(任意の英語文字列)+'-'+'(西日本リージョン)w'+'-'+'（リソースグループの略）vnet'**
例えば、'test'という仮想ネットワークを作る予定の場合、'test-w-vnet'とする。

####④ 各項目を設定し終えたら、「確認および作成」ボタンをクリックして、仮想ネットワークをデプロイする。

ちなみに、アドレス空間や、サブネットマスクも作成時に編集することができるが、今回は変更しない。
セキュリティに関しては、とりあえずAzureの標準セキュリティと、次記事のネットワークセキュリティグループの設定で対応する。

デプロイが完了したら、この記事の内容は完了。

#次の記事
[ネットワークセキュリティグループの作成はこちら](https://qiita.com/y_kai_acc/items/d596026637092e210d4a)
Microsoft Azureを使って、最小構成でWebサーバー(Ubuntu)を構成してみる -ネットワークセキュリティグループの作成

#はじめに
[参考書籍や目次はこちら](https://qiita.com/y_kai_acc/items/f5bc3abd063ac2ab76d8)
前記事 [仮想ネットワークの作成はこちら](https://qiita.com/y_kai_acc/items/d602a0ac95221e8c0d65)

#目的
##### ネットワークセキュリティグループの作成
VMを作成した際に、想定していない接続をさせないため。またVMをネットワーク外から管理するため。

#準備するもの
特になし。

#手順 ネットワークセキュリティグループ(NSG)の作成

####① Azure Portalメニューからネットワークセキュリティグループ(NSG)を検索し、クリック。

####② ネットワークセキュリティグループ(NSG)新規作成する。
新規作成からネットワークセキュリティグループ(NSG)を新規作成する。

####③ 設定項目を入力する。
以下の項目を入力していく。

| 項目名 | 入力値 |
|:-----------|:------------|
|サブスクリプション| （デフォルト）無料サブスクリプション|
|リソースグループ|(前記事で作成したリソースグループ名)|
|仮想マシン名|(任意のNSG名)|
|地域|（日本で作るなら）西日本|
|可用性オプション|(デフォルト)|
|イメージ|(任意のNSG名)|
|Azure Spotインスタンス|(デフォルト)|


前記事の命名規則に則るのなら、**(任意の英語文字列)+'-'+'(西日本リージョン)w'+'-'+'vm'**
例えば、'test'というvmを作る予定の場合、'test-w-vm'とする。

####④ 各項目を設定し終えたら、「確認および作成」ボタンをクリックして、仮想ネットワークをデプロイする。

####⑤ NSGのデプロイが完了したら、リソースに移動する。

####⑥ 受信セキュリティ規則を作成する。
今回作成するのはUbuntuベースのWebサーバーであるため、Azure外からのHttp,Httpsプロトコル及び、SSH通信を許可する設定にする。

メニューから、受信セキュリティ規則を選択し、追加をクリックする。

以下のルールを追加する。
まずは、Http, Httpsの許可。

| 項目名 | 入力値 |
|:-----------|:------------|
|ソース| Any|
|ソースポート範囲|*|
|宛先|Any|
|サービス| Custom|
|宛先ポート範囲|80,443|
|プロトコル|TCP|
|アクション|許可|
|優先度| 100(お好きにどうぞ)|
|名前|AllowHttpAndHttps（分かりやすいルール名）|
|説明| AllowHttpAndHttps|

次にSSH通信の許可。

| 項目名 | 入力値 |
|:-----------|:------------|
|ソース| Any|
|ソースポート範囲|*|
|宛先|Any|
|サービス| SSH|
|宛先ポート範囲|22(自動入力)|
|プロトコル|TCP(自動入力)|
|アクション|許可|
|優先度| 200(お好きにどうぞ)|
|名前|AllowSSH（分かりやすいルール名）|
|説明| AllowSSH|

ここの設定は、ホームルータの設定をしたことあるなら、似ているかもしれない。

####⑦ サブネットへのNSGの関連漬け
[前記事]で作成した仮想ネットワークのサブネットにネットワークセキュリティグループを紐付ける。

メニューからサブネットを選択して、関連付けボタンをクリック。
プルダウンメニューから、前記事で作成した仮想ネットワークを選択し、再度出てきたサブネットプルダウンから、Defaultのサブネットを選択して、OKをクリックする。


ちなみにNSGはVMに直接紐付けることも可能。
ただ、道楽用途の最小構成であれば、仮想ネットワーク内のサブネットに紐付けておけば、サブネットに紐付けたVM全てに同じル-ルが適用されるので、セキュリティの設定漏れのリスクが少ない気がする。

紐付けが完了したら、この記事の内容は完了。

#次の記事
[VMの作成はこちら](https://qiita.com/y_kai_acc/items/cff29b991c18510f00c8)
Microsoft Azureを使って、最小構成でWebサーバー(Ubuntu)を構成してみる（参考書籍・目次）

#はじめに
Microsoft AzureとUbuntuについて勉強するための環境を構築をしてみました。
レンタルサーバー(PaaS)では何か満足できないけれど、オンプレミスにサーバーを建てるほどでもない方用。
あと、道楽。
このページは参考書籍と目次掲載用なので、中身は各ページに分けてあります。

# 当記事の利点
#####クラウドの仕組みやネットワークの仕組み、Ubuntuの仕組みについて横断的に勉強できる。
#####自宅に複数台のPCを保有しなくて済む。
#####Azure Fundamentalの試験勉強になる。

# 当記事の利点
#####従量課金なので、少なからず出費がある。何もかもゼロコストで済ませたい人には向かない。
#####業務レベルのサーバーを構築できるほどの内容ではない。


# 参考とした教材

####@m-oka-system 氏が公開しているUdemy講座

#####作りながら覚えるMicrosoftAzure入門講座（IaaS編）

#####作りながら覚えるMicrosoftAzure入門講座（PaaS編）

windows serverベースで解説されていますが、Azure上での実際の操作は大変勉強になりました。

# 参考書籍

#####徹底攻略 Microsoft Azure Fundamentals 教科書[AZ-900]
（Microsoft Azureの認定資格の教本）

#####Azure テクノロジ入門2019

#####Ubuntuサーバー徹底構築

# 参考サイト
[Microsoft Docs](https://docs.microsoft.com/ja-jp/)
Microsoftの公式ドキュメントサイト。

[Microsoft サポート](https://support.microsoft.com/ja-jp/)



#目次
- [Microsoft Azureのアカウントの開設](https://qiita.com/y_kai_acc/items/de1a79c161fca54f439e)

- [リソースグループの作成](https://qiita.com/y_kai_acc/items/31f156c7c1450fd20ded)

- [仮想ネットワークの作成](https://qiita.com/y_kai_acc/items/d602a0ac95221e8c0d65)

- [ネットワークセキュリティグループの作成](https://qiita.com/y_kai_acc/items/d596026637092e210d4a)

- [VMの作成](https://qiita.com/y_kai_acc/items/cff29b991c18510f00c8)

- Automationの作成(作成中)

- webサーバーのインストール（作成中）

- （おまけ）独自ドメインの設定(作成中）
Azureを使って、最小構成でWebサーバー(Ubuntu)を構成してみる -VMの作成

#はじめに
参考書籍や目次は[こちら](https://qiita.com/y_kai_acc/items/f5bc3abd063ac2ab76d8)
前記事 [ネットワークセキュリティグループの作成の作成はこちら](https://qiita.com/y_kai_acc/items/d596026637092e210d4a)

#目的
##### VMの作成
IaaSの最も基本的なリソースであるVirtual Machineを作成する。

#準備するもの
特になし。初めてのVirtual Machineがデプロイされるまでのワクワク感だけ持っていれば問題ない。
あと、管理者IDの

#手順 VMの作成

####① Azure PortalメニューからVirtual Machinesを検索し、クリック。

####② Virtual Machinesを新規作成する。
作成、仮想マシンからVirtual Machinesを新規作成する。

####③ 設定項目を入力する。
以下の項目を入力していく。

#####まずは仮想マシンの作成：基本

| 項目名 | 入力値 |
|:-----------|:------------|
|サブスクリプション| （デフォルト）無料サブスクリプション|
|リソースグループ|(前記事で作成したリソースグループ名)|
|名前|(任意のNSG名)|
|地域|（日本で作るなら）西日本|
|可用性オプション| （デフォルト）インフラストラクチャ冗長はありません|
|リソースグループ|(前記事で作成したリソースグループ名)|
|イメージ|(作成したいUbuntuのバージョン)Ubuntu Server18.04 LTS|
|Azure スポット インスタンス|選択しない|
|サイズ|（任意。道楽ならStandard B1s-1で十分。）|
|認証の種類|SSH公開キー|
|ユーザ名|（管理者IDに設定したい文字列)|
|SSH公開キーのソース|新しいキーの組の生成|
|キーの組名|(任意。忘れない名前)|
|パブリック受信ポート|選択したポートを許可する|
|受信ポートを選択|SSH(22)|

#####仮想マシンの作成：ディスク

| 項目名 | 入力値 |
|:-----------|:------------|
|OSディスクの種類|Standard HDD|
|リソースグループ|(前記事で作成したリソースグループ名)|
|暗号化の種類|（デフォルト）既定|

データディスクは特に作成する必要なし。

#####仮想マシンの作成：ネットワーク

| 項目名 | 入力値 |
|:-----------|:------------|
|仮想ネットワーク| (前記事で作成した仮想ネットワーク)|
|サブネット| (前記事で作成したサブネット)|
|パブリックIP|（デフォルト）新規作成|
|NIC ネットワーク セキュリティ グループ|なし（NSGが設定されている）|
|負荷分散|設定しない|

#####仮想マシンの作成：管理

| 項目名 | 入力値 |
|:-----------|:------------|
|ブート診断| マネージド ストレージ アカウントで有効にする (推奨)|
|サブネット| (前記事で作成したサブネット)|
|パブリックIP|（デフォルト）新規作成|
|NIC ネットワーク セキュリティ グループ|なし（NSGが設定されている）|
|負荷分散|設定しない|
|その他の設定|デフォルト|

ここまで設定したら、確認および作成をクリックし暫く待つ。

####【重要】[新しいキー ペアの生成] ウィンドウが開いたら、 必ず「秘密キーをダウンロードし、リソースを作成する」を選択する。

秘密鍵をDLしないと、作成したVMにSSHでアクセス出来ない。

####④ リソースに移動し、「接続」、「SSH」の順に選択する。

この画面に入ると、SSH接続するために必要なコマンドを生成する機能を使用できる。

VMにSSH接続できるようになったら、この記事の内容は完了。

####参考
[Azure Docs:クイック スタート:Azure portal で Linux 仮想マシンを作成する](https://docs.microsoft.com/ja-jp/azure/virtual-machines/linux/quick-create-portal)
CNN-LSTMモデルを用いた株式相場予想

# はじめに

深層強化学習モデルIMPALAを開発する前段階として、CNN-LSTMモデルの実装を行なった。

ソースコードはこちら

https://github.com/sugiyama404/forecast_sp500/blob/main/cnn_lstm.ipynb


## 使用データについて

トレンド傾向の掴みやすさから、yahoo financeからGSPCの日足を使用した。

訓練データの期間：2015/1/1 - 2017/6/30
テストデータの期間：2017/7/1 - 2021/1/1

以下ソースコード

https://github.com/sugiyama404/ReinfoceLearningForTrading/blob/main/get_csv.ipynb

# 時系列におけるCNN

## 一般的なCNN

　CNN(Convolutional Neural Networks)は、畳み込み層を含んだニューラルネットワークで、画像データから意味のあるデータを抽出し、画像認識などを行えるようにする。

![cnn_info.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/731268/b058954a-e407-38a9-0f54-9299e56b53e9.png)


畳み込み層・・・入力データから特徴量を抽出する層
プーリング層・・・入力データを圧縮する層
全結合層・・・全てのニューロンが繋がった層

## 時系列におけるCNN

　CNNは、時系列データに置いて、1次元の入力データを2次元の行列に変換することで、特徴量の抽出に用いる。[^1]

![cnn.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/731268/59bfbd27-8a3b-fc48-2b8c-678059c4f91c.png)

# LSTM[^2]

　LSTM(Long Short-Term Memory)は，勾配の爆発と勾配の消失を解決するため、1997年にJ.Schmidhuberらによって提案されたネットワークモデルである。[^2]今現在、音声認識，感情分析，テキスト分析、時系列分析の分野で用いられている。LSTM は、長期記憶、短期記憶、忘却の３つの機能がある。このことから、過去の状態が今現在に影響を与える時系列データを取り扱うのに適している。

# CNN-LSTM[^3]

　CNN-LSTMを組み合わせることにより、波形のパターンを時系列的に処理することができる。
　モデルの構造図を示す。主な構造は入力層、一次畳み込み層、プーリング層、LSTM隠れ層、完全結合層を持つ。



![Screen Shot 2021-08-18 at 13.09.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/731268/702bb408-7760-3d2f-565d-b37633443b64.png)

[^3]より引用

以下の構造図より、LSTMの入力形式（サンプル数、ルックバック数、変数量）を踏襲している。

![Screen Shot 2021-08-18 at 13.13.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/731268/aff40a7a-9bf0-1ace-3bf8-738e048e7fef.png)

[^3]より引用

# モデル構築[^3]

![cnn_lstm_model_flow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/731268/96cc8775-2a16-bc8d-e859-930c8ed43c8a.png)


```python
conv_filter = 4
units = 8
batch_size = 8
look_back = 10

opt = Adam(learning_rate=0.001)

model = Sequential()

model.add(Conv1D(filters=conv_filter, kernel_size=1, padding="same", activation="tanh",batch_input_shape=(None, look_back, 1)))
model.add(MaxPool1D(pool_size=1, padding='same'))
model.add(Activation("relu"))
model.add(LSTM(units, return_sequences=True))
model.add(Dense(1, kernel_initializer='random_uniform'))
model.compile(loss = "mean_absolute_error", optimizer=opt)
print(model.summary())
```

# 損失関数

![Unknown.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/731268/83fece2a-4369-a13d-d908-ff1b5a5191e9.png)


# 学習結果

![Unknown-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/731268/920d8aa6-8ced-8fff-1117-d0ba53f5ab8b.png)

![Unknown-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/731268/0ab51761-f73d-4c1a-1200-0de0395d83b5.png)



[^1]: S. Chen and H. He, 'Stock Prediction Using Convolutional Neural Network' (2018),Materials Science and Engineering443

[^2]: S. Hochreiter and J. Schmidhuber, 'Long Short Term Memory' (1997),Neural Computation 9,p.1735-1780

[^3]: W. Lu,J. Li,Y. Li, A. Sun, and J. Wang, 'A CNN-LSTM-Based Model to Forecast Stock Prices', (2020), Hindawi Complexity Volume 2020,p.10
Microsoft Azureを使って、最小構成でWebサーバー(Ubuntu)を構成してみる - Microsoft Azureのアカウントの開設

#はじめに
[参考書籍や目次はこちら](https://qiita.com/y_kai_acc/items/f5bc3abd063ac2ab76d8#当記事の利点)

#目的
##### Microsoft Azureのアカウントの開設
Microsoft Azureを使うために必要

#準備するもの
#####有効なクレジットカード番号
Microsoft Azureのアカウントの開設に必要

#手順① Microsoftアカウントの開設（必要に応じて）
Microsoftアカウントを持っていない人はまずMicrosoftアカウントを作成する必要がある。持っている方は特段新たに開設する必要はない。

[Microsoft アカウント](https://account.microsoft.com)

[サポート 新しい-microsoft-アカウントを作成する方法](https://support.microsoft.com/ja-jp/account-billing/新しい-microsoft-アカウントを作成する方法-a84675c3-3e9e-17cf-2911-3d56b15c0aaf)

公式サポートページの指示に従い、Microsoft アカウントを作成する。

#手順② Microsoft Azureアカウントの開設
初めてMicrosoft Azureを使用する場合は、無料アカウントの作成がおすすめ。
30日間使用出来る22,500円のクレジットと、12ヶ月間の無料枠が付与される。
[Azureアカウントの作成](https://azure.microsoft.com/ja-jp/free/)

画面の指示に従って、アカウントを作成していく。途中、クレジットカード番号の情報を入力する必要があるので、自身のクレジットカード情報を入力する。
クレジットカードなしではアカウントを開設できない。

ちなみにAzure Fundamentals試験においても、上記の設例が出題されたりする。

Microsoft Azureアカウントが作成されると、サブスクリプションが有効化される。
Microsoft Azureはサブスクリプションという単位で、契約を管理している。
無料アカウントを作成すると、無料枠が設定されたサブスクリプションが作成される。

Azure Portal画面が表示できれば、Microsoft Azureアカウントは正常に作成されている。
[Azure Portal](https://portal.azure.com/)

#次の記事
[リソースグループの作成はこちら](https://qiita.com/y_kai_acc/items/31f156c7c1450fd20ded)
BlazorとFluxorでTodoを作った話

# 概要
C#でWebページが作れる[Blazor](https://dotnet.microsoft.com/apps/aspnet/web-apps/blazor)で使ってみた時に詰まったところをまとめた記事です。状態管理のために[Fluxor](https://github.com/mrpmorris/Fluxor)を使用しています。

作成したリポジトリは[こちら](https://github.com/suger-131997/TodosBlazorFluxor)です。Webページは[こちら](https://suger-131997.github.io/TodosBlazorFluxor/)。

[Redux Todos Example](https://github.com/reduxjs/redux/tree/master/examples/todos)を参考にしています。

# 使用したバージョンなど
- .NET 5.0.9
- AspNetCore.Components.WebAssembly 5.0.9
- Fluxor.Blazor.Web 4.1.0

# 詰まったところ

## FluxorでStateを更新しても画面が更新されない
`@inherits Fluxor.Blazor.Web.Components.FluxorComponent`を更新してほしいコンポーネントのrazorファイルの先頭に追加する。

```html:VisibleTodoList.razor
@inherits Fluxor.Blazor.Web.Components.FluxorComponent

<TodoList Todos="@VisibleTodos()" OnClickMethod="@ToggleTodo"/>
```

## メソッドを子コンポーネントに渡したい
[EventCallback](https://docs.microsoft.com/ja-jp/aspnet/core/blazor/components/event-handling?view=aspnetcore-5.0#eventcallback)を使用する。

```html:VisibleTodoList.razor
@inherits Fluxor.Blazor.Web.Components.FluxorComponent

<TodoList Todos="@VisibleTodos()" OnClickMethod="@ToggleTodo"/>
```
```c#:TodoList.razor.cs
using Microsoft.AspNetCore.Components;
using System.Collections.Generic;
using Todos.Models;

namespace Todos.Components
{
    public partial class TodoList
    {

        [Parameter]
        public IEnumerable<TodoItem> Todos { get; set; }

        [Parameter]
        public EventCallback<int> OnClickMethod { get; set; }
    }
}
```

引数に値を渡したい場合は`InvokeAsync`を使用する。

```html:TodoList.razor
<ul>
    @foreach (var todo in Todos)
    {
        <Todo Text=@todo.Text Completed=@todo.Compleated OnClickMethod="@(() => OnClickMethod.InvokeAsync(todo.Id))" />
    }
</ul>
```

## コンポーネントを親コンポーネントから受け取る
[RenderFragment](https://docs.microsoft.com/ja-jp/aspnet/core/blazor/components/templated-components?view=aspnetcore-5.0)を子コンポーネントのパラメータとして定義する。

```c#:Link.razor.cs
using Microsoft.AspNetCore.Components;

namespace Todos.Components
{
    public partial class Link
    {

        [Parameter]
        public RenderFragment ChildContent { get; set; }

        [Parameter]
        public bool Active { get; set; }

        [Parameter]
        public EventCallback OnClickMethod { get; set; }
    }
}
```
```html:Footer.razor
<div>
    <span>Show: </span>
    <FilterLink FilterType="@VisibilityFilterType.ShowAll">
        All
    </FilterLink>
    <FilterLink FilterType="@VisibilityFilterType.ShowActive">
        Active
    </FilterLink>
    <FilterLink FilterType="@VisibilityFilterType.ShowCompleted">
        Completed
    </FilterLink>
</div>
```

# 使ってみての感想
### 良かった点
- C#であるため、型があり補完等がきく
- 開発の環境構築が容易である
- 詰まったところはだいたいドキュメントに書いてあった

### 微妙だった点
- VisualStadioの警告が間違っている場合がある
    - 再起動で直るものの、わりと高頻度で起きる
- あんまりネットに使用例がない

# 参考にしたリンク集
- Fluxor Toutorials
    - https://github.com/mrpmorris/Fluxor/tree/master/Tutorials/02-Blazor
- ASP.NET Core Blazor の概要
    - https://docs.microsoft.com/ja-jp/aspnet/core/blazor/?view=aspnetcore-5.0
[Ruby] AtCoder 過去問　B- Booby Prize

##はじめに
AtCoder過去問のB問題、Booby PrizeをRubyでといて見ました。
問題文はこちらから確認してください↓

https://atcoder.jp/contests/abc213/tasks/abc213_b

よろしくお願いします！！

##B-Booby Prize
まずは入力受け取りですね。
人数を受け取るのと、スコアの受け取りですね。

```ruby
N = gets.to_i
A = gets.split.map(&:to_i)
```

正直Nの人数に関してはAの配列の要素の数=人数になるので必要ありませんでした。

ブービー賞は最下位から二番目のスコアになるので、配列の中身を降順に並び替えて、二番目のスコア、つまりインデックス数の1がブービーのスコアになります。変数booby_scoreに値を代入します。

配列の中身を降順に並び替えるには```.sort.reverse```で並び替えることができます。

```ruby
N = gets.to_i
A = gets.split.map(&:to_i)

booby_score =  A.sort.reverse[1]
```

これでbooby_scoreには最下位から二番目の値が入っています。
次に配列Aの中にbooby_scoreが何番目かを調べます。

これにはインデックス数を利用します。
index()メソッドを配列に対して使えば、渡した引数と同じ値が配列の何番目に存在するのかをインデックス数で返してくれます。

インデックス数で返ってくるので+1した数字が選手番号になります。

```ruby
N = gets.to_i
A = gets.split.map(&:to_i)
 
booby_score =  A.sort.reverse[1]
puts A.index(booby_score) + 1
```

##最後に
他の解き方などあれば教えてください！
また便利なメソッドなどもあればご教授いただけると幸いです！
複数台のraspberry piのバックアップについて考えてみる

raspberry pi（以下ラズパイ）のバックアップについて考えたのでメモ。
※複数台で運用する場合を想定しています。
#MicroSDは壊れやすい
ラズパイのストレージとしては主にMicroSDを使うのが主流ですが、**すぐ壊れます**。
用途にもよりますが持っても1年程度で唐突に壊れます。

なのでバックアップは割と重要になってきます。
##MicroSDを使わない選択肢
一応ラズパイにはUSBブートやネットワークブートなど、それ以外のところから起動することも可能です。

USBブートでHDDやSSDを繋げばすぐ壊れるという点も回避でき、SSDであれば高速化も期待できます。
**ただ高い**。とてもではないですがラズパイにそこまで駆けるお金なんてないです。
あとHDDの場合電源供給をどうするか問題も出てきます。

ただラズパイが1台のみなら全然ありです（自分みたいに台数が増えるとその分必要になるので）。

ネットワークブートは別途それ用の鯖がいることと、技術的な難易度が高いです。

#外部ストレージへバックアップ
結局無難に外部ストレージに保存するのが手っ取り早いんですよね。
とはいえラズパイに直差しすると電力問題や複数台でどうするの問題が起きます。

##NASを使う選択肢
そこで活躍してくれるのがNASですね。こうすることでどのサーバーからでもサクッと保存できてパソコンとかで管理も楽にできます。

ただどのみちNASが必要になるわけです。一応ラズパイをNAS化することも可能ですがそうなると結局ストレージを買うことになります。

#じゃあどうするんだよ
結局お金を出さないことにはよくある手法は使えないわけですよ。
で、仕方なくMicroSDにバックアップしてたわけですがある日思い立ちます。
**「proxmoxのCephみたいにすればよくね？」**

proxmoxのCephについて簡単に説明すると、各サーバーに同じデータを保存して、どれか死んでも残りでデータを保持できる機能です。（他にもあるけど割愛）

そして各サーバーの1ディレクトリをNAS化し、バックアップ終了後に他サーバーのNASと同期する仕組みを構築しました。

#総括
結果、1円もかけずデータ破損にそこそこ強いバックアップ環境を構築できました。
ただしデメリットとして、

- 容量を逼迫する
- 結局MicroSDが壊れた際には買い替えが必要

などが挙げられます。結局の所上2つが無難になるのでそれまでの一時しのぎがいいでしょう。

他にも有効な手段等あればご指摘してくださるとありがたいです。
MVCモデルを会社内部で例えてみる　初心者

<h2>初めに</h2>
プログラミングスクールで学習を始めて、最初にぶつかった壁が「MVCモデル」だったような気がします。
何をどこに書くかなんか、最初の頃は全然わかりませんでしたが、
今は何となくイメージは掴めるようになったかなと思いますので、まとめていきます。
何かと擬人化して理解しようとしてしまうので？、
MVCモデルについても会社内部でイメージしてみました。

<h2>Model・・・モデル</h2>
何かこんなイメージです。（ちょっとお堅い、えらいイメージ）
<img width="200" alt="deta_man_color.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633266/c0170c68-3e1c-a7cd-a601-f00f7f2bb485.png">


データベースに片足突っ込んでいて、データの登録業務や、取得、削除をおこなているようなところ。
会社で言うと管理部みたいな。

<h2>Controller・・・コントローラー</h2>
こんなイメージですかね。
<img width="150" alt="operator_man_color.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633266/8dce2bf8-d756-9fa7-d141-1211da402cfb.png">

モデルやビューを統合的に制御する部分です。
ユーザーの命令を受けて、モデルを呼んだり、ビューに値を渡したり、そういったことをやっています。
会社で言うと、上司（チーム長？課長？）のイメージです。
ここが優秀だと、ViewもModelも楽と言うか、働きやすい。
ここがグチャグチャだと地獄（激務、無駄なことさせられる）みたいな。

<h2>View・・・ビュー</h2>
こんなイメージです。（元気いっぱい！働きもの！）

<img width="150" alt="counton_suit_woman_color.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633266/0dace0bd-be77-8cf8-0663-ffc5df9d69a6.png">

ユーザーのために結果をどんどん出力してくれます。
コントローラー（上司）の指示がおかしいと、こっちもおかしくなります。


<h2>終わりに</h2>
Ruby on railsの勉強を開始して３ヶ月ほどの初学者のイメージ、理解になります。
今後、勉強していくうちにもっと理解が深まって、やっぱり違ったなぁとなるかもしれないし、
変わらずこのイメージかもしれません。