OmniAICreator/Qiita-1.07M huggingface dataset:
[ハンズオン] ５分でAWS S3で静的ホスティングする

## 経緯
現在のプロジェクトで静的ファイルをS３にホスティングして運用しているので、勉強がてら記録を残します。

## AWS S3とは
基本的にストレージを提供するサービスになっています。
画像、動画、ファイルなど様々なデータを保存するサービスで、
例えば、icloudは写真や書類（メモアプリ、pdfなど）を保存するストレージサービスです。

S3は、他のAWSサービスと連帯して使うことができ、
EC2のスナップショット（バックアップ）の保存先、
ファイルアップロード時をイベントトリガーとして、Lambda関数を呼び出しをしたりと、
一般的なストレージサービスより多くの機能を兼ね備えています。

今回は、静的ホスティング機能について記載していこうと思います。

>参照：[S3ユースケース](https://michimani.net/post/aws-about-amazon-s3/#https://michimani.net/post/aws-about-amazon-s3/#amazon-s3-%E3%81%AE%E3%83%A6%E3%83%BC%E3%82%B9%E3%82%B1%E3%83%BC%E3%82%B9)

## 静的ホスティングとは
静的なwebサイトをホスティング（一般公開）すること。

静的なwebサイトとはhtmlファイルをサーバにアップロードしておき、
リクエストに対してそのままそのファイルをレスポンスするサイトのこと。

例えば、PHPやJavaはアプリケーションサーバで動作させることにより、
ログイン情報によって処理を行うことができるためリクエストごとに
異なったレスポンスをするので、動的なwebサイトになります。

## S3でホスティングする理由
１番の理由は*コストが低い*です。
料金は、**S3 Standard**のストレージクラスですと、
ストレージあたり0.025USD/GB、1000リクエストあたり0.00037USD
とレンタルサーバを借りてLPなどを運用するよりはるかに安いです。
また、 フルマネージドサービスなのでサーバのメンテナンス等は考えなくても良いです

>参照：[料金 - AWS S3](https://aws.amazon.com/jp/s3/pricing/?nc=sn&loc=4)


## 手順
### 1.index.htmlを作成
公開するhtmlファイルを準備

```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>S3静的ホスティング</title>
</head>
<body>
  <h1>S3静的ホスティング</h1>
</body>
</html>
```

### 2.バケットを作成
AWSにログイン後、Amazon S3サービスに移動**バケットを作成する**を押下し、バケット名を入力してバケットを作成
![s3-static-hosting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536932/4bec1d59-3ba5-acb1-95bb-fd79a7cfa542.png)

### 3.バケットにindex.htmlをアップロード
作成したバケットに移動し**アップロード**を押下して、先程のhtmlファイルをアップロード
![O 774LOER.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536932/7bfe28e2-a0f0-3562-b97f-f3c89d339c05.png)

### 4.静的ホスティングを有効化
アップロードしたindex.htmlをクリックし、 「プロパティ」タブの「Static website hosting」項目の
 「このバケットを使用してウェブサイトをホストする」を選択
インデックスドキュメントに静的ホスティングするindex.htmlを入力して保存
![Static website hosting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536932/c0826cb3-8d16-33a2-3f97-293b6e75e0b5.png)

### 5.index.htmlを公開
バケットに戻り、index.htmlを選択してからアクションボタンを押下し、**公開する**をクリック
![s3-static-hosting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536932/577e133f-30c7-1f8d-2d05-6d1efb42d535.png)

 *※バケット作成時に「パブリックアクセスをすべてブロック」を選択していた場合、
「公開」ボタンが非活性になっているので、その場合は「アクセス権限」タブの「ブロックパブリックアクセス」項目の
「パブリックアクセスをすべてブロック」のチェックを外す*
![T. ENGORERIONT FEROTHUAMSHEOAdRE3. AWHIL7 THURSD  ALTS⅝ULUIFlNThMSOD.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536932/adb9bb1f-8b9c-e9c2-ffe6-2088b152c1c1.png)

### 6.静的ホスティングを確認
「プロパティ」タブの「Static website hosting」項目のエンドポイントからアクセス可能
![Static website hosting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536932/a145d240-2512-7be6-1e36-a6aee22288af.png)

表示を確認できました！
![bianTlNGE s3-static-hosting.s3-website-ap-northeast-1.amazonaws.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536932/38d0b7bf-19ec-9c62-cc0f-e97444da4d0c.png)

## まとめ
公開するソースコードさえ準備していれば、簡単にホスティングできます。

Route53のサービスを使えば、独自ドメインも使うので近いうちに試してみたいと思います。

自己紹介ページやLPページを公開したい方はぜひお試しください！！
失敗したrspecのテストをgithubのcheck annotationsでみられるようにする

# 序

GithubActionsでCICDフローを回せて便利！
でもrspecがこけたときに、エラー箇所をしらべるのに難儀する。
Github Checksでみられたらよさそう。

# 破

reviewdogでアップロードしようと思ったけれど、サポートされているエラーフォーマットはなかった。
https://github.com/reviewdog/reviewdog#available-pre-defined-errorformat

サポートするためのPRつくれるかなとおもってソースをみていたら、 `Reviewdog Diagnostic Format` というものが提案されている。
https://github.com/reviewdog/reviewdog/tree/master/proto/rdf

パーサーを書くより、こっちのフォーマットに合わせて、rspecの出力を加工するほうが良さそう。
でもまだ正式版じゃないみたい。SARIF良さそう。
なのでRDFormatではなく、既存の入力フォーマットに合わせてrspecのフォーマッタを作ることにする。
https://github.com/reviewdog/reviewdog#input-format

- `errorformat`
- `checkstyle XML format`

を試作してみて、動作確認がしやすかった checkstyle にする。

XMLがなつかしい。

# 急

https://github.com/astronoka/rspec-checkstyle_formatter
フォーマッタをつくってgemにしました。

実装中、mysqlかなにかのエラーで出力される asciiのカラーコード `\e[0;34m` 的なやつでXMLのビルダー/パーサーがエラーになったりして
そういえばこういうことでエラーになったことあったなと、ますます懐かしい気持ちになる。

GithubActionsでの記述例

```yaml

name: CI

on: push

jobs:
  test:
    name: Test
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2

    - name: Set up Ruby
      uses: ruby/setup-ruby@v1
      with:
        ruby-version: 2.7.1

    - name: Restore gems
      uses: actions/cache@v2
      with:
        path: vendor/bundle
        key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
        restore-keys: |
          ${{ runner.os }}-gems-

    - name: Run rspec
      run: |
        bundle config path vendor/bundle
        bundle install --jobs 4 --retry 3
        bundle exec rspec \
          --no-fail-fast \
          --format RSpec::CheckstyleFormatter \
          --out /tmp/rspec_result.xml

    - name: Upload rspec result
      if: always()
      uses: actions/upload-artifact@v2
      with:
        name: rspec_result.xml
        path: /tmp/rspec_result.xml

    - name: Install reviewdog
      if: always()
      uses: reviewdog/action-setup@v1
      with:
        reviewdog_version: latest

    - name: Report rspec error
      if: always()
      env:
        REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      run: |
        cat /tmp/rspec_result.xml | reviewdog -name=rspec -f=checkstyle -reporter=github-check -filter-mode=nofilter

```

こんなかんじ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/53551/36449408-3260-17da-7f5c-94bc7154630f.png)

reviewdog素晴らしい :sparkles: 


linter向けのフォーマットで渡すのはどうなのだろうと思いつつ
了。
Redmineのトップメニューに言語の切り替えリンクを追加（個人設定画面に遷移しないで言語を切り替える）

Redmineの言語を切り替える際に、わざわざ個人設定画面に遷移するのは面倒なので、View Customize Pluginを使って、トップメニューに言語切り替えリンクを追加してみました。

Redmine 4.1で追加された、MyAccountのAPIを使用します。

make /my/account endpoint accessible through API
https://redmine.org/issues/31399

Redmine Rest API（MyAccount）
https://www.redmine.org/projects/redmine/wiki/Rest_MyAccount

```javascript
/*
パスのパターン:.*^(?!/login).*$
挿入位置:全てのページのヘッダ
種別:JavaScript
*/

$(function() {
    const apiKey = ViewCustomize.context.user.apiKey;
    const current_language = document.documentElement.lang.toLowerCase();
    if (current_language === "ja") {
        lang = "en";
        menutitle = "英語";
    } else if (current_language === "en") {
        lang = "ja";
        menutitle = "Japanese";
    }

    //トップメニューに言語切り替えリンクを追加
    if (!location.href.match('/my/account')) { //個人設定画面以外
        $('#loggedas').prepend('<li><a href="javascript:void(0)" id="languagechange">' + menutitle + '</a></li>');
    };

    //クリックしたら言語を切り替え
    $('#languagechange').click(function() {
        $.ajax({
            type: "PUT",
            url: '/my/account.json',
            headers: {
                'X-Redmine-API-Key': apiKey
            },
            dataType: "text",
            contentType: 'application/json',
            data: JSON.stringify({
                'user': {
                    "language": lang
                }
            })
        }).done(function() {
            window.location = location.href;
        })
    })
})
```
/app/views/my/account.api.rsb に1行（api.language   @user.language）を追加します。

```ruby
  api.api_key    @user.api_key
+ api.language   @user.language

  render_api_custom_values @user.visible_custom_field_values, api
```

![言語切り替えメニュー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/761560/9a6f9d86-8a66-9a69-f735-84462ed717da.png)
cronを使ってみた

##基本事項のざっとした説明

※細かいことは他にも色々あるので必要な人は調べてください

- cron --- 定期実行するデーモン
- crontab --- cronのスケジュール設定する



実行環境　Linux Mint(19.1 Tessa) ,EC2(Amazon Linux2)

以下のコマンドで現在の設定内容を表示できる

```
$crontab -l
```
上記コマンドをdockerの中とMacで実行したが、コマンドが存在しなかったので(※後で確認したらMacにはありました。。。表示が少し違っていたので見間違いと思われます)
とりあえずLinux Mint(19.1 Tessa)のPCで試してみた。crontabが使えてかつ未設定の場合は以下のように表示される。
![corabtab_-l.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664188/817b4f96-7e9a-423e-add6-e1ed54bfb3a7.png)
以下のコマンドで設定の編集ができるようになる、最初はエディタの指定を求められる。（今回はVimに設定した。nanoがおすすめされていた）

```
$crontab -e
```
![crontab_-e.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664188/8bca22af-7e04-5c6c-aedf-2834dd1ca72f.png)

コマンドは　分、時、日 、月、曜日、コマンド
の順番で記載し、半角スペースを空ける。
以下は１０分毎にシェルを実行する設定

```
*/10 * * * * /home/user/test.sh
```

cronの実行ログを確認するコマンド

- Linux Mintの場合

```
grep CRON /var/log/syslog
```
- EC2の場合

```
sudo grep CRON /var/log/cron
```
# 今回遭遇したトラブルと対応方法

###トラブル①　エラー　No MTA installed, discarding output

設定してもまったくなにも起きなかったので実行ログを確認したところ以下のような表示が出ていた。
![cron_log_err.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664188/335d9610-750f-cc50-be28-88b3571d17d5.png)
調べたところ、UbuntuとUbuntuがベースのLinux Mintで起きる事象であるとのこと。

postfixをインストールすると上記のエラーは解消された。

```
sudo aptitude install postfix
```
###トラブル②　シェルのパーミッション
トラブル①を解消するも全くシェルが動かなかった。
ふとファイルのパーミッションを```ls -l```コマンドで確認してみると```-rw-rw-r--```だった。

実行権限を付与した。（とりえず動かすための権限付与なので必要に応じて変えてください）

```
chmod +x test.sh
```

正常にシェルは動作した。

##補足
ちなみにcronの動作確認をしたかっただけなので確認用のコマンドは以下のように簡単なものを使用した。

```
echo "test cron1" >> /home/owner/aaa.txt
```
AWSにEC2上でdockerを使用したlaravelをデプロイ②（Elastic IP取得〜紐付け）

##概要##
・自分が詰まったポイントと同じポイントで詰まった方向けにAWSにlaravel/dockerをデプロイするまでの過程を書いていきます。

前回の記事
[AWSにdockerを使用したlaravelをデプロイ①]
(https://qiita.com/JXnj8uVrUkiBh90/items/463fe4a122a0c4e5d03f)

##Elastic IP取得##
**1:Elastic IPを開く**
EC2ダッシュボードの左側のメニューの「Elastic IP」を選択。
「Elastic IPの割り当て」をクリック。
![スクリーンショット 2020-10-10 22.05.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/778706/10247ef7-4d81-04f7-7524-f6e57089dec0.png)

**2:「割り当て」をクリック**
![スクリーンショット 2020-10-10 22.05.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/778706/896d23ef-d86b-b9f2-0963-4db893e48499.png)

**3:割り当てられたIPをクリック**
![スクリーンショット 2020-10-10 22.06.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/778706/c4195bf8-0947-6a4c-4a35-c95b077270f7.png)

**4:EC2インスタンスに紐づける**
「Elastic IP アドレスの関連付け」をクリック
![スクリーンショット 2020-10-11 11.45.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/778706/b726a2f3-2edc-4c38-b461-d9974199b3a0.png)

**5:インスタンスを選択**
「インスタンス」に先ほど作成したEC2インスタンスを選択する。
「関連付ける」をクリック。
![スクリーンショット 2020-10-10 22.06.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/778706/fd37d0d1-821a-e171-6973-de3915c0c247.png)

これで作成したインスタンスにElastic IPが紐付けられました。

**前回の記事**
[AWSにEC2上にdockerを使用したlaravelをデプロイ①]
(https://qiita.com/JXnj8uVrUkiBh90/items/463fe4a122a0c4e5d03f)

**続きはこちら**
[AWSにEC2上にdockerを使用したlaravelをデプロイ③](https://qiita.com/JXnj8uVrUkiBh90/items/374868750adc36179148)

＊＊間違い等ございましたらご指摘お願い致します＊＊
AndroidアプリをGooglePlayConsoleで好きなタイミングで公開する

Androidアプリの公開タイミングについて
審査後すぐ公開ではなく、自分の好きなタイミングで公開する手順を試したので
書き記しておく

公式のヘルプ
https://support.google.com/googleplay/android-developer/answer/9859654?hl=ja

# 前情報
- 新しいUI（2020/11/2〜）を使用


# 手順
1. GooglePlayConsoleにログイン > アプリ指定
2. 左メニュー > 公開の概要
3. 管理対象の公開のステータスを「オン」にする ![スクリーンショット 2020-10-10 11.26.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6568/944f3363-35fe-c5bd-0404-cedad48a8e38.png) ![スクリーンショット 2020-10-10 11.26.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6568/0ac3be95-44d1-62e2-1350-06f8bf170913.png)
4. 左メニュー > リリース > 製品版 > 新しいリリースを作成
5. 新しいバージョンのAPKファイルをアップロード > リリースのレビュー > 製品版としての公開を開始
6. 審査中となる
7. 「公開の概要」画面でも「審査中の変更」として表示される ![スクリーンショット 2020-10-10 11.40.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6568/a6ae8ea9-d3b0-9a1b-a726-1eeef97e529e.png)
8. ストアページの内容変更も同様に「審査中の変更」になる
9. 審査が終了し、「公開の概要」画面で「変更の公開準備完了」として表示される。 ![スクリーンショット 2020-10-11 11.34.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6568/c3513e07-227c-5de7-c78e-bf4bd34d26ce.png)
この時点では、アプリもページの変更もまだ公開されていない
10. 自分の公開したいタイミングで「公開して確認」ボタン押下 ![000.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6568/77845c56-ac0a-34fe-e801-3fc17136a424.png) ![スクリーンショット 2020-10-11 11.46.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6568/25563ba3-41a5-e7bc-1ef6-a43f906bf072.png)
11. ボタンを押してすぐに公開されました

# 感想
時間指定ではなく、ボタンを押すと公開。
また、管理対象の公開機能で保留されない変更もあるので注意が必要
【Thymeleaf】ステータス変数


# ステータス変数
`th:each`を利用する場合、繰り返し処理中のステータスを知るためのステータス変数というものが用意されている。ステータス変数を利用する場合、th:each 属性の中で、繰り返し変数の後ろにカンマで区切ってステータス変数を定義する。以下の例ではstatを追加。


```Controller.java
List<Player> players = new ArrayList<Player>();
players.add(new Player(1 , "Miura", "Kazuyoshi"));
players.add(new Player(2 , "Nakamura", "Shunsuke"));
players.add(new Player(3 , "Matsui", "Daisuke"));
model.addAttribute("players", players);
```

```list.html
<tr th:each="player, stat : ${players}" th:object="${player}">
	<td th:text="*{id}"></td>
	<td th:text="*{lastName}"></td>
	<td th:text="*{firstName}"></td>
	<td th:text="${stat.index}"></td>
</tr>
```
index以外にも様々なステータス変数が用意されている。

|ステータス変数|内容|
|:--|:--|
|index|0始まりの現在の「繰り返しインデックス」|
|count|1始まりの現在の「繰り返しインデックス」|
|size|繰り返し変数の全要素数|
|current|現在の要素オブジェクト|
|even|現在の繰り返し位置が偶数の場合true|
|odd|現在の繰り返し位置が奇数の場合true|
|first|現在の繰り返し処理が最初の場合はtrue|
|last|現在の繰り返し処理が最後の場合はtrue|

# 参照
[Tutorial: Using Thymeleaf (ja)　6.2 繰り返しステータスの保持](https://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf_ja.html#%E7%B9%B0%E3%82%8A%E8%BF%94%E3%81%97%E3%82%B9%E3%83%86%E3%83%BC%E3%82%BF%E3%82%B9%E3%81%AE%E4%BF%9D%E6%8C%81)
Firebaseを使ってみた　〜第三章 Firestoreからデータを取得する 〜

React Hooksを使いチャットボットアプリを作成しています。

この章ではFirestoreに保存した中から初期データを取得するまでを行います。

<a href="https://qiita.com/iiizoo/items/a31726966c1a42f37809">第一章　サービスをデプロイする</a>
<a href="https://qiita.com/iiizoo/items/a946be93d2475647dfec">第二章　Firestoreにデータを保存する</a>
第三章　Firestoreからデータを取得する

<h2>Firestoreを使う準備の流れ</h2>
[1. config.jsファイルを作成する](#menu1)
[2. エントリポイントを作成する](#menu2)
[3. 初期データを取得する](#menu3)
[4. まとめ](#menu4)



<h2 id="menu1">1. config.jsファイルを作成する</h2>
srcディレクトリ配下に「firebase」ディレクトリを作成し、その中に「config.js」ファイルを作成します。
Firebaseのページに移り、「プロジェクトを設定」画面へ遷移します。
![スクリーンショット 2020-10-11 10.43.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578913/76085cc3-1c47-d3c1-788e-78fee668a2a1.png)

の下部にあるFirebase SDK snippetの構成にチェックを入れ、下に記載してあるコードをコピーしconfig.jsファイルに貼り付けます。
![スクリーンショット 2020-10-11 10.44.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578913/518b5d46-f07a-2425-38d8-74a11993150a.png)

貼り付けた内容を他の画面で使うので、exportしておきます。

```firebase/config.js
const firebaseConfig = {
  apiKey: "******",
  authDomain: "******",
  databaseURL:"******",
  projectId: "******",
  storageBucket: "******",
  messagingSenderId: "******",
  appId: "******",
  measurementId: "******"
};

export default firebaseConfig
```
こちらの内容はGitHubなどに公開して問題ない内容のようですが、firestoreのセキュリティ設定をしておかないと簡単に書き込みをされてしまうので注意してください。（セキュリティ設定に関しては<a href="https://firebase.google.com/docs/firestore/security/rules-conditions?hl=ja">こちら</a>）

<h2 id="menu2">2. エントリポイントを作成する</h2>
firebaseディレクトリ配下に「index.js」ファイルを作成し以下記述をします。

```firebase/index.js
import firebase from 'firebase/app'        //firebaseを読み込み
import 'firebase/firestore'                //firebaseの中のfirestoreを読み込み
import firestoreConfig from './congfig'    //先ほど作成したconfigファイルを読み込み

firebase.initializeApp(firesbaseConfig);   //firebaseを初期化
export const db = firebase.firestore();    //初期化したfirebaseのfirestoreを使う
```


<h2 id="menu3">3. Firestoreからデータを取得する</h2>
Firestoreからデータを取得していきます。まず、先ほど作成したdbをインポートします。

```src/App.jsx
import { db } from './firebase/index'
```

useEffectを使い、ページ読み込み時に全データを取得するようにします。
async,await付きの即時関数で記述していきます。（即時関数について<a href="https://qiita.com/katsukii/items/cfe9fd968ba0db603b1e">参考記事</a>）

```src/App.jsx
import React, {useState, useEffect} from 'react'
import { db } from './firebase/index'

const App = () => {
 const [dataset, setDataset] = useState({});

  useEffect(() => {
    (async () => {
      const initDataset = {};
      await db.collection('[チャットボットのjsonファイルで設定したキー]').get().then(snapshots => {
        snapshots.forEach(doc => {
          const id = doc.id
          const data = doc.data()
          initDataset[id] = data
        })
        setDataset(initDataset)
      })
    })()
  },[])
```
ここで行っていることは以下です。

- collectionにアクセスし、データ(doc)を取得（データはsnapshotsに全て格納される）
- snapshotsの中身をforEachで回し、id,dataを取り出す
- 取り出したidをキーにinitDatasetの中にデータを格納する

あとは任意の場所でinitDatasetからidをキーにデータを取り出して使います。


<h2 id="menu4">4. まとめ</h2>
この章ではエントリポイントを作成し、Firestoreに格納したデータを取得しました。

今回初めて使ったみたのですが、記述すべき内容が把握できればとても簡単にできることがわかりました。手軽にバックエンド環境を用意したい方にはお勧めです！
Docker-composeコマンド　メモ

##dockerコマンドとの比較(docker-compose.ymlを書いている前提）
```
$ docker build <buildするファイルのパス> ↔︎　$ docker-compose build
$ docker run <docker image> ↔︎ $ docker-compose up //buildされていなければbuildもしてくれる
$ docker exec <コンテナ><command> ↔︎ $ docker-compose exec <service><command>

$ docker-compose down //  : stopしてrm
```
Typescript ジェネリクス

Typescriptでは予め型を決めておく必要がありますが、ジェネリクスを使うと使用直前まで型を定義しなくて良くなります。
型が違う同じような機能をいくつも定義しなくて良くなるので、ソースコードの再利用性や保守性が増します。

以下では、ジェネリクスを使はない場合はstringとnumberの両方のクラスを用意しないといけないですが、ジェネリクスを使う場合は1つのクラスだけで機能提供できていることがわかります。

```typescript:ジェネリクスを使わない場合
class useString {
  constructor(public arrays: string[]) {}
  print(value: string): void {
    for(const array of this.arrays) {
      if(array === value) {
        console.log(`Yes you have ${value}`)
      }
    }
  }
}

class useNumber {
  constructor(public arrays: number[]) {}
  print(value: number): void {
    for(const array of this.arrays) {
      if(array === value) {
        console.log(`Yes you have ${value}`)
      }
    }
  }
}

new useString(['a', 'b', 'c']).print('b')
new useNumber([1, 2, 3]).print(2)
```

```typescript:ジェネリクスを使う場合
class useAnyting<T> {
  constructor(public arrays: T[]) {}
  print(value: T): void {
    for(const array of this.arrays) {
      if(array === value) {
        console.log(`Yes you have ${value}`)
      }
    }
  }
}

new useAnyting<string>(['a', 'b', 'c']).print('b')
new useAnyting<number>([1, 2, 3]).print(2)
```

# 必ず存在するかわからないメソッドを使う場合

ジェネリクスで使うことで、型ごとに同じような機能を作る必要がない例は見ていただいたと思いますが、もし未来に定義する型にメソッドがあるかどうかわからない例だとエラーになってしまいます。

```typescript
class Student {
  print(): void {
    console.log('This is Student')
  }
}

class Teacher {
  print(): void {
    console.log('This is Teacher')
  }
}

interface People {
  print(): void
}

function print<T>(arr: T[]) {
  for(let i = 0; i < arr.length; i++) {
    // arrが必ずprintメソッドを持つ訳ではないので、エラーになる
    console.log(arr[i].print) 
  }
}

print([new Student(), new Teacher])
```

ジェネリクスの引数をprintメソッドを持つインターフェイスで継承すれば、引数に渡る値はインターフェイスを満たす必要があり、必ずprintメソッドを持つことが確約されるためエラーにはなりません。

```typescript
class Student {
  print(): void {
    console.log('This is Student')
  }
}

class Teacher {
  print(): void {
    console.log('This is Teacher')
  }
}

interface People {
  print(): void
}

// Peopleインターフェイスを継承する
// 引数にprintメソッドを持っている値が渡される限りエラーにならない
function print<T extends People>(arr: T[]) {
  for(let i = 0; i < arr.length; i++) {
    console.log(arr[i].print)
  }
}

print([new Student(), new Teacher])
```
Dart の assertion テスト

Class のインスタンス生成時における assert のテスト

- テスト対象は、ブロックで渡す
- 実行結果は、エラーオブジェクトのクラスを検証する

---
- 環境
  - Dart SDK version: 2.10.1 (stable) (Tue Oct 6 10:54:20 2020 +0200) on "macos_x64"
- 参考資料
    - [Cannot test for assertion errors · Issue \#39305 · dart\-lang/sdk](https://github.com/dart-lang/sdk/issues/39305)

## テスト対象

```dart
class Article {
  Article({this.title})
      : assert(title != null);

  String title;
}
```


### assert テスト

```dart
test('Case null member', () {
  expect(() {
    Article(title: null);
  }, throwsA(isA<AssertionError>()));
});
```

### 間違った記述例

```dart
test('Case null member', () {
  var article = Article(title: null);

  expect(article, AssertionError);
});


test('Case null member', () {
  var article = Article(title: null);

  expect(() {
    article;
  }, throwsA(isA<AssertionError>()));
});
```
28歳地方公務員がプログラミングを始めて8.5ヶ月でweb系自社開発企業に転職成功した話

# 私について
1992年生まれ28歳
地方公務員5年目
早大卒のド文系
プログラミング経験は特にありませんでした
数学はじめ理数系も全くの未経験

# 誰に向けて書いた？
未経験からweb系エンジニアにジョブチェンジされようとしている方

# 学習内容
## おおよそのタイムライン
2019年12月　Progate
2020年1月　Railsチュートリアル・インスタクローン作成
2020年2月　現場で使えるRuby on Rails5速習実践ガイド
2020年3月　ポートフォリオ作成
2020年4月　ポートフォリオ作成
2020年5月　ポートフォリオ作成
2020年6月　面接
2020年7月　内定

## 勉強しているときの生活リズム
平日：出勤前後に各1時間
休日：8時間

## 実際にやったこととかけた時間
[Progate　Ruby on Rails][link-1] 　3周　 40時間
[link-1]:https://prog-8.com/languages/rails5

〜環境構築〜　3時間

[小学生でも分かるRuby on Rails入門][link-2]　5時間
[link-2]:https://openbook4.me/projects/92/

[Railsチュートリアル][link-3]
[link-3]:https://railstutorial.jp/

一周目：ざっと流し読み　10時間
二周目：テスト、デプロイ、演習除く　20.5時間
三周目：省略なし（11章の途中でエラーが発生し、直せなかった・・・ので、そこからはコーディング及びデプロイはしていません）　25時間

インスタクローン作成　52.5時間

[現場で使えるRuby on Rails5速習実践ガイド][link-4]　一周　17時間
[link-4]:https://www.amazon.co.jp/%E7%8F%BE%E5%A0%B4%E3%81%A7%E4%BD%BF%E3%81%88%E3%82%8B-Ruby-Rails-5%E9%80%9F%E7%BF%92%E5%AE%9F%E8%B7%B5%E3%82%AC%E3%82%A4%E3%83%89-%E5%A4%A7%E5%A0%B4%E5%AF%A7%E5%AD%90/dp/4839962227

ポートフォリオ作成　185.5時間

# プログラミングスクールについて
某キャンプさんにお世話になりました。
スクールについては自走できる人については必要ないと考えています。
自分の勉強スタイルや、スクールで何を得たいか、外からの強制力が必要かどうかを考えて使うかを決めていきましょう。

# いざ、転職活動
## 100数十社にエントリー、しかし・・・度重なるお祈り、そして内定
転職活動は6月〜7月でした。
ちょうどコロナで各企業が採用を絞っている時期でした。

今は求人プラットフォームが様々ありますが、私はwantedly一択でした。
GREENやエージェントも使いましたが、ピンと来る企業がなかったため途中からは使っていません。
エージェントは、未経験だとSIerやSESの企業ばかり勧めてきます。

上記にもあるように100数十社にエントリーした私ですが、書類を通過したのはわずか10社程度でした。
未経験からの転職は厳しいと聞いていましたが、まさかこれほどまでとは・・・。

最終的には、トントン拍子に選考が進んだ企業様から内定をいただくことになりました。
自社開発を行っているベンチャー企業でした。

# 勉強開始からこれまでを振り返って
僭越ながら二点ほど。

・勉強は短期集中
長くなってしまうとどうしてもモチベーションが下がってしまいますし、知識の定着も悪くなります。
「◯月◯日までにこれをやる！」といったように目標期日を（厳しめに）設けて進めていきましょう。

・未経験からのエントリーはとにかく量
未経験からの転職は想像を超える大変さでした。
質の高いポートフォリオを作りきり、面接準備も整ったらどんどんエントリーしていきましょう。
どうしても入りたい企業があれば話は別ですが、基本的に企業は選ばずにエントリーしていきます（そのうち選んでいられなくなるかと思います・・・）。
「実務未経験！」と書いてあった求人はもちろん、大々的に謳っていない企業にもガンガンエントリーしました。
お祈りが大量に来ると思いますが、めげずにエントリーしてください！

最後までお読みいただきありがとうございます。
皆さんにもいいご縁がありますように！
【業務書まとめ】『文系出身者が2時間で製造業がわかる本』を読んだまとめ

## 第1章 代表的な製造業の業務内容と経営の特徴

### 注目点

- ヒト、モノ（設備）、カネ、コト（経営）に注目する
- 業種や取引先によって経営が大きく変わる
- ヒトに依存する部分が多い
    - つくりかたの勘所
    - 育成に時間がかかる
- モノ
    - 耐用年数が短くなってきている
- カネ
    - 利益がわからない
        - 原価計算システムが高価で導入できないなど
        - 原価計算が複雑
- コト
    - どこと取引しているか
    - 中小企業の弱点は営業機能
        - 新しい取引先を開拓したいが営業力がない
        - 多くの会社と取引したい
    - 大手メーカー
        - 取引先をしぼっている
            - 購買の人員を削減できる
        - 多社購買化
            - ひとつの部品の製造を複数の会社で行なう

### 中小企業の業種

- 機械加工
    - 切削加工（加工屋）
    - 精密部品の製造に使われる
        - 旋盤（丸物加工）
        - NC旋盤
            - プログラムをつくる
                - 自動でプログラムを作成してくれるのがCAM
        - フライス盤（角物加工）
            - 刃物代は最大のランニングコスト
                - 1本数千円〜数万円
                - 1ヶ月数百万円も
        - マシニングセンタ
            - NCフライス盤に刃物自動交換装置とストッカーをつけたもの
                - 大きいものから小さいものまである
                    - 大は小を兼ねない
        - 研削加工
            - 作業者の技量次第
        - 放電加工
            - 溶かして加工する
                - ワイヤーカット
                - カタボリ放電加工
    - 刃物と温度で精度が変わる
    - 難加工材
        - HRC（ロックウェル硬さCスケール）
            - 切削できるのはHRC40まで
- プレス加工
    - 量産できる
        - 加工精度は機械加工には劣る
        - 板金加工よりは高い
    - 単発プレス
        - １個ずつやる
    - トランスファープレス
        - プレス機の間をつないだもの
    - 順走プレス
        - 鉄板をコイルから供給する
    - 段取替え
        - 金型交換
    - 歩留まりに注意
    - 応用技術
        - ファインブランキング
- 板金加工
    - 多品種少量の製品に向いている
    - 大型の製品
    - 工程
        - 切断
            - タレパンやレーザー
        - 曲げ
            - 作業者が操作
        - 溶接
            - スポット溶接、アーク溶接、レーザー溶接
        - 仕上げ
            - サンダーで
- 樹脂成形加工
    - 金型は複雑なものなら新車一台程度の値段
    - ヒケとバリ
    - シルバーストリーク
        - ガスでできる
    - ウェルドライン
        - 境界が見える


### 工場の課題

- 機械加工
    - 設備では強みにならなくなってきた
    - 中国との競争
- ブレス加工
    - 品質は金型メーカー次第
    - 原価の把握ができていない
- 板金加工
    - 人材確保の問題
- 樹脂成形加工
    - 細かいキズも不良となる時代
        - メーカーの技術力低下もある
            - 製造工程に配慮しない設計
                - 顧客とのアジャイル的な連携が必要
- 多品種大量生産の工場の課題
    - 案件管理の手間
        - 見積もり作成コスト
            - 「見積もりばかり増えて儲からない」
        - 納期管理コスト
    - 人材育成の問題


## 第2章 ものづくり技術の知識を習得して、できる製造業支援

- 今までは事業計画を立てなくても伸びる企業は多くあった
- QCD改善の方法を4Mで考える
- 4M
    - 作業者(Man）
    - 機械設備（Machine）
    - 原材料（Material）
    - 方法（Method）
- QCD
    - 品質（Quality）
    - コスト（Cost）
    - 納期（Delivery）
よく使うCSSのカラーコードについて

## ■ はじめに

普段、何気なく使っているCSSのカラーコードについて、記事にしましたのでご覧下さい。
この記事について得られる事は以下の通りです。

・カラーコードの構成・仕組み
・カラーコードの記述（短縮方法）


## ■ 16進数のカラーコード構成

```
.test {
  color: ＃112233;
}

最初の2桁(11):赤
次の2桁(22):青
最後の2桁(33):緑
で構成し、16進数で表現されている

16進数 → 0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f
```

### ・何故、10進数ではないのか
→ １０進数では色の情報量が不足し色を表現しきれない為。

10進数 → 10*10*10*10*10*10 = 1,000,000
16進数 → 16*16*16*16*16*16 = 16,777,216


## ■ 色の指定方法について
```
- 16進数
#112233

→ 最も使用頻度が高い

- 16進数の短縮した書き方
#ffffff　→　#fff
#112233　→　#123
#ff0000　→　#f00

→ 赤青緑の2桁が同じであれば短縮できる


- キーワードで指定する
red

→ 要素に色をつけて分かりやすくする等。一時的に使用する

```

コードを短縮することで、素早くスッキリした形で書けて修正も簡単。
但し、会社やチーム等で指定がある場合は指示に従う。

ただ、16進数とキーワードは混同させず、どちらを使うか事前に決めておいた方が良い。
チーム開発で書いたコードを後から見直すと、ごっちゃになっていました。

他にもRGBやHSLといった、色の他に透過度も指定した方法もありますが、ここでは割愛します。
rails db:migrateでエラーが出た（（StandardError: An error has occurred, this and all later migrations canceled:）時の対処法

rails db:migrate でエラーが出ることがあります。私の場合は何故かちょいちょい何かしらのエラーが出るので対処法を調べてみました。（私自身ruby,rails共に初学者です。この記事は初学者の方の参考になればという思いと、私の学習のために執筆しています。）

```
== 20201011010946 CreatePosts: migrating ======================================
-- create_table(:posts)
rails aborted!
StandardError: An error has occurred, this and all later migrations canceled:

PG::DuplicateTable: ERROR:  relation "posts" already exists

(つづく）
```

##rails db:migrateでエラーが出る原因は？
今回のStandardErrorに関しては、migrateを実行したが実行中に何らかの原因でエラーが起きてしまい、テーブルは作成されているけどmigtate事態は未実行扱いとなっている状態。

つまり、システム側のちょっとしたエラーで中断された状態って感じだと思います。

しかし、エラー文には/post_bootstrap_app/db/migrate/20201011010946_create_posts.rb:3:in `change'などと、あたかもそこにミスがあるかのように書かれていて「俺、そんなとこいじってへんのやけど？」状態となり、一瞬混乱します。

##rails db:migrateでエラー（StandardError）が出た時の対処方法
```
rails db:migrate:reset
※migrateの実行を一旦リセット

rails db:migrate
※改めてrails db:migrateを実行
```
対処方法を私なりに少し調べてみたのですが、中断されたmigrateを一旦リセットでなかったことにして、再度migrateでやり直せば上手くいくとのことで、この方法を実際に実行してみました。

その結果、、、何事もなかったかのようにdb:migrateに成功しました！


##今回のまとめ
しょっぱなのデータベース作成時にエラーが出たら「まだ大して何も記述していないのに何故にエラー！？」と混乱するのは初学者あるあるだと思います。

しかし、この簡単な方法１つで解決されることもあるのでお困りの方は試してみてください。少しでも参考になれば幸いです。
vite でビルドしたアプリケーションを github pages にデプロイすると _assets 以下がロードされない

## 問題

vite でアプリケーションをビルドして、github pages にデプロイしたい。

以下みたいな感じでビルド時にアセットのパスは変更できてるけど、アクセスするとアセットが 404 になる。

```sh
npm run build -- --base=/<repo-name>
```

## 原因

jekyll はアンダースコアスタートのディレクトリは無視するらしい。

デフォルトでアセットが入っているディレクトリは `_assets` なので、それが原因

## 解決方法

`public` ディレクトリに `.nojekyll` を置いてあげる。

## 参考

https://github.com/vitejs/vite/issues/238
アセンブラーを作る。

#概要

アセンブラーを作る。
俺cpuで動く。

#ソース

九九

```
  push  1
  set  a
  push  1
  set  b
label30:
  get  a
  get  b
  *
  set  c
  get  c
  push  10
  /
  push  48
  +
  out
  get  c
  push  10
  %
  push  48
  +
  out
  push  32
  out
  push  ','
  out
  push  32
  out
  get  a
  push  1
  +
  set  a
  get  a
  push  10
  <
  jz  label30
  push  10
  out
  get  b
  push  1
  +
  set  b
  push  1
  set  a
  get  b
  push  10
  <
  jz  label30
bye:
  jmp  bye
a:
  0x0000
b:
  0x0000
c:
  0x0000
    
```

#コンパイル結果

```
mem[12'h000] = 16'h1001;//       push  1
mem[12'h001] = 16'h302f;//       set  a
mem[12'h002] = 16'h1001;//       push  1
mem[12'h003] = 16'h3030;//       set  b
mem[12'h004] = 16'h202f;//label30:  get  a
mem[12'h005] = 16'h2030;//       get  b
mem[12'h006] = 16'hf004;//       *
mem[12'h007] = 16'h3031;//       set  c
mem[12'h008] = 16'h2031;//       get  c
mem[12'h009] = 16'h100a;//       push  10
mem[12'h00a] = 16'hf005;//       /
mem[12'h00b] = 16'h1030;//       push  48
mem[12'h00c] = 16'hf000;//       +
mem[12'h00d] = 16'he000;//       out
mem[12'h00e] = 16'h2031;//       get  c
mem[12'h00f] = 16'h100a;//       push  10
mem[12'h010] = 16'hf006;//       %
mem[12'h011] = 16'h1030;//       push  48
mem[12'h012] = 16'hf000;//       +
mem[12'h013] = 16'he000;//       out
mem[12'h014] = 16'h1020;//       push  32
mem[12'h015] = 16'he000;//       out
mem[12'h016] = 16'h102c;//       push  ','
mem[12'h017] = 16'he000;//       out
mem[12'h018] = 16'h1020;//       push  32
mem[12'h019] = 16'he000;//       out
mem[12'h01a] = 16'h202f;//       get  a
mem[12'h01b] = 16'h1001;//       push  1
mem[12'h01c] = 16'hf000;//       +
mem[12'h01d] = 16'h302f;//       set  a
mem[12'h01e] = 16'h202f;//       get  a
mem[12'h01f] = 16'h100a;//       push  10
mem[12'h020] = 16'hf001;//       <
mem[12'h021] = 16'h5004;//       jz  label30
mem[12'h022] = 16'h100a;//       push  10
mem[12'h023] = 16'he000;//       out
mem[12'h024] = 16'h2030;//       get  b
mem[12'h025] = 16'h1001;//       push  1
mem[12'h026] = 16'hf000;//       +
mem[12'h027] = 16'h3030;//       set  b
mem[12'h028] = 16'h1001;//       push  1
mem[12'h029] = 16'h302f;//       set  a
mem[12'h02a] = 16'h2030;//       get  b
mem[12'h02b] = 16'h100a;//       push  10
mem[12'h02c] = 16'hf001;//       <
mem[12'h02d] = 16'h5004;//       jz  label30
mem[12'h02e] = 16'h402e;//bye:  jmp  bye
mem[12'h02f] = 16'h0000;//a:  0x0000
mem[12'h030] = 16'h0000;//b:  0x0000
mem[12'h031] = 16'h0000;//c:  0x0000


```

#成果物

https://embed.plnkr.co/plunk/4YJOIgQeQftpIkhb

以上。
Laravelで画像をリサイズ＆勝手に回転しないようにする【EXIF情報も削除】

# はじめに
Laravelで画像投稿機能を作ったは良いけど、

　`「投稿される画像が大きかったり小さかったりする..」`
　`「アップロード後に画像が勝手に回転してしまう..」`
　`「画像に埋め込まれた隠し情報が危険って聞いたけど..」`

そんな問題を解消していきます。

画像の大きさの問題はCSSで縮尺などを指定すれば表示は小さくできますが、
それだと表示を変えるだけで保存される画像は大きいままです。
これではストレージや通信に負荷がかかってしまいます。

また画像には`EXIF情報`というものが埋め込まれていて、撮影したスマートフォンの情報だったり画像の向き、さらには撮影した場所などが記録されているものもあります。
少し怖いですね。

今回はこれらを同時に最適化する方法をシェアしていきます。

# やること
以下の手順で行います。
　① 現状のEXIF情報をみてみる
　② InterventionImageをインストールする(Composerを使用)
　③ InterventionImageを使えるようにする(Configをいじる)
　④ Controllerで実際に画像処理を行う

# 実際にやってみる
## ① まず現状の画像のEXIF情報をみてみる
これは別にやらなくても良いのですが、
現在画像処理を行っているControllerにおいてdd()メソッドを実行してみます。

```〇〇Controller.php
dd($image->exif()); // $imageが画像データです
```

これでブラウザにEXIF情報が表示できます。
ずらっと配列で表示されて、撮影した機種など色々な情報が格納されているのがわかると思います。。

ちなみにdd()は「dump and die」の略なんですね。(知らないで使ってた)
<br>

## ② InterventionImageをインストールする
この~~余計な~~EXIFの削除とリサイズ処理と回転(画像の向き)の最適化処理を同時に簡単にできるのが`InterventionImage`というものです。
PHPの画像処理ライブラリであるGDとImagickをサポートするパッケージで、
Laravelで画像処理をするならこれ一択、という位置付けのものですね。
GDやImagickを簡単に扱うことができます。

公式はこちら
http://image.intervention.io/getting_started/installation#laravel

以下のコマンドを実行してインストールします。

```zsh
$php composer.phar require intervention/image
```
<br>

## ③ InterventionImageを使えるようにする
`Config/app.php`に以下の記述を追加します。
追加するのは`providers`と`aliases`の2箇所です。
プロバイダとエイリアスの設定ですね。

```Config/app.php
'providers' => [
    Intervention\Image\ImageServiceProvider::class,
],

~中略~

'aliases' => [
    'Image' => Intervention\Image\Facades\Image::class,
],
```
<br>
さらにdriver設定の追加を行います。(以下のコマンドを実行)

```zsh
$php artisan vendor:publish --provider="Intervention\Image\ImageServiceProviderLaravelRecent"
```
<br>
最後に、Configで設定をいじったのでキャッシュをクリアします。(以下のコマンドを実行)

```zsh
$php artisan config:clear
```
<br>


## ③ Controllerで実際に処理を行う
### ファサードを使う宣言をする
まずは画像処理を行うControllerにおいて以下を記述します。

```〇〇Controller.php
use Intervention\Image\Facades\Image; // Imageファサードを使う
use Illuminate\Support\Facades\Storage; // Storageファサードを使う
```

### 画像処理を行う
InterventionImageでは本当に色々なことができるのですが、
ここでは実際によく使うであろう縦横比を維持したリサイズと、
ファイルをjpg形式に変換する例を示します。

```〇〇Controller.php
$resized_image = Image::make($posted_image)->fit(640, 360)->encode('jpg');
```
<br>
`$posted_image`が加工前の画像で、`make()`でInterventionImageに加工前の画像を読み込んでいます。
`fit()`は幅と高さを指定しつつ、縦横比が合わない場合はトリミングしてくれるメソッドです。

単純なリサイズなら`resize()`でも良いのですが、画像がゆがんでしまうのでこの`fit()`が便利だと思います。

※InterventionImageでの網羅的な画像処理はこちらのサイトが参考になります。
https://blog.capilano-fw.com/?p=1574#_resize

### 画像の回転とEXIF情報の処理
最後に本題(?)の画像が勝手に回転する問題とEXIF情報の処理です。
これには`orientate()`を使います。

```〇〇Controller.php
$resized_image->orientate()->save();
```
これで自動回転しつつEXIF情報を削除してくれます。
`->save()`がないと処理が反映されないので注意です。

### ファイル保存する
ファイル保存は`store`メソッドが使えない(GDがサポートしていないというエラーになる)ので
Laravelの機能(ファサード)の`Storage::put`を使います。

```〇〇Controller.php
Storage::put('public/image/' . $image_name, $resized_image); 
```
<br>
これで良い感じの大きさになり、画像の向きも正しい向きになり、不要な埋め込み情報も削除された画像が投稿できるようになったはずです！
おつかれさまでした〜。
インタープリタを作る その7

#概要

インタープリタを作ってみた。
俺cpuのアセンブラが動く。

#ソース

九九

```
  push  1
  set  a
  push  1
  set  b
label30:
  get  a
  get  b
  *
  set  c
  get  c
  push  10
  /
  push  48
  +
  out
  get  c
  push  10
  %
  push  48
  +
  out
  push  32
  out
  push  ','
  out
  push  32
  out
  get  a
  push  1
  +
  set  a
  get  a
  push  10
  <
  jz  label30
  push  10
  out
  get  b
  push  1
  +
  set  b
  push  1
  set  a
  get  b
  push  10
  <
  jz  label30
label255:
  end  


```

#実行結果

```
01 , 02 , 03 , 04 , 05 , 06 , 07 , 08 , 09 , 
02 , 04 , 06 , 08 , 10 , 12 , 14 , 16 , 18 , 
03 , 06 , 09 , 12 , 15 , 18 , 21 , 24 , 27 , 
04 , 08 , 12 , 16 , 20 , 24 , 28 , 32 , 36 , 
05 , 10 , 15 , 20 , 25 , 30 , 35 , 40 , 45 , 
06 , 12 , 18 , 24 , 30 , 36 , 42 , 48 , 54 , 
07 , 14 , 21 , 28 , 35 , 42 , 49 , 56 , 63 , 
08 , 16 , 24 , 32 , 40 , 48 , 56 , 64 , 72 , 
09 , 18 , 27 , 36 , 45 , 54 , 63 , 72 , 81 , 
end

```

#成果物

https://embed.plnkr.co/plunk/2pNgQVLUwuznRBLP

以上。
ファイルの変更時刻に基づいて名前変更 (Linux)

# ファイルの変更時刻に基づいて名前変更

## コマンド

`LOGFILE` にファイル名を変更したいファイル名が入っているとして

```
if [ -e $LOGFILE ]; then
   TIMESTAMP=$(date -r $LOGFILE "+%Y-%m-%d_%H_%M_%S")
   mv $LOGFILE $LOGFILE.$TIMESTAMP
fi
```

とすればよい。

## 説明

`date -r ファイル名` で `ファイル名` で指定したファイルの変更時刻を取得できる。
`"+%Y-%m-%d_%H_%M_%S"` で `date -r` で返す形式をしているしている。

`$(コマンド)` を使うことにより `コマンド` の実行結果を変数に代入できる。

`mv` で実際の名前変更を実行する。

## 参考

https://stackoverflow.com/questions/16391208/print-a-files-last-modified-date-in-bash/16391221
PowerPointのプレゼンテーションモードをウィンドウ表示する

PowerPointで作者の意図通りアニメーションを含めた表示で閲覧する場合、フルスクリーン表示だと占有されてしまいます。
ウィンドウ表示でプレゼンテーションモードのスライドを閲覧することができます。

ウィンドウ表示を利用すれば、Web会議など、手元で参照しながらmeeting画面を表示したり場合や、ホストとしてもメモを同時にデスクトップに表示したい場合に便利です。



1. [スライド ショー] > [スライド ショーの設定]ボタン
2. [スライド ショーの設定] ダイアログの [種類] > [出席者として閲覧する (ウィンドウ表示)]を選択

![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399204/c4c6112c-7df5-8ade-d958-f3775de28f5d.png)

できあがり。
Note:ウィンドウ最大化ボタン(□)で、フルスクリーンに切り替わります。
![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399204/e1b33cf4-97ec-1ef7-195a-23a685b06ec1.png)
コンパイラを作る。 その4



概要

コンパイラを作る。
俺言語を俺cpuのアセンブラに変換するコンパイラを作る。
下記に、ソースとコンパイル結果を載せる。

#ソース

九九

```
10 a=1
20 b=1
30 c=a*b
40 ?=c
50 ?=","
60 a=a+1
70 #=a<10*30
80 ?=;
90 b=b+1
100 a=1
110 #=b<10*30
```

#コンパイル結果

```
  push  1
  set  a
  push  1
  set  b
label30:
  get  a
  get  b
  *
  set  c
  get  c
  push  10
  /
  push  48
  +
  out
  get  c
  push  10
  %
  push  48
  +
  out
  push  32
  out
  push  ','
  out
  push  32
  out
  get  a
  push  1
  +
  set  a
  get  a
  push  10
  <
  jz  label30
  push  10
  out
  get  b
  push  1
  +
  set  b
  push  1
  set  a
  get  b
  push  10
  <
  jz  label30
label255:
  jmp  label255

```

#成果物

https://embed.plnkr.co/plunk/z4zR4ipmrnLh9JmH

以上。
Laravel ベースレイアウトにDBから取得したデータを表示する

# 目的

- ベースレイアウトにテーブル内に格納されているデータを表示する方法をまとめる

# 実施環境

- ハードウェア環境

| 項目 | 情報 |
| --- | --- |
| OS | macOS Catalina(10.15.5) |
| ハードウェア | MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports) |
| プロセッサ | 2 GHz クアッドコアIntel Core i5 |
| メモリ | 32 GB 3733 MHz LPDDR4 |
| グラフィックス | Intel Iris Plus Graphics 1536 MB |

- ソフトウェア環境

| 項目 | 情報 | 備考 |
| --- | --- | --- |
| PHP バージョン | 7.4.8 | Homebrewを用いてこちらの方法で導入→[Mac HomebrewでPHPをインストールする](https://qiita.com/miriwo/items/cd54077aad7e139cf518) |
| Laravel バージョン | 8.6.0 | commposerを用いてこちらの方法で導入→[Mac Laravelの環境構築を行う](https://qiita.com/miriwo/items/adaaaeecae69d6392e08) |
| MySQLバージョン | 8.0.19 for osx10.13 on x86_64 | Homwbrewを用いてこちらの方法で導入→[Mac HomebrewでMySQLをインストールする](https://qiita.com/miriwo/items/ef6a064bc545fbea29d9) |


# 前提情報

- 本記事は`@inject`ディレクティブの使用方法を簡単にまとめるものである。
- `@inject`ディレクティブはサービスやリポジトリインターフェースを呼び出す事のできるディレクティブである。
- 本記事は若干抽象的な説明が多くわかりにくいと思うので具体例を別途記事にする予定である

# 詳細

1. ベースレイアウトへのディレクティブの記載
    1. 下記の記載方法でベースレイアウトにディレクティブを記載する。

        ```php
        @inject(サービスからの戻り値を格納する変数, サービス)
        ```
    1. 例えば変数`$str`に`アプリ名ディレクトリ/app/Services/TestService`に記載されているとあるメソッドの戻り値を格納したい場合は下記のように記載する。

        ```php
        @inject('str', 'App\Services\TestService)
        ```
1. 得た値の出力
    1. ディレクティブを記載したベースレイアウトファイル内で下記のように記載する事により値を出力する事ができる。

        ```php
        {{ 戻り値を格納した変数名->サービスファイルに書かれたデータ取得メソッド名()}}
        ```
    1. 例えば変数`$str`に格納されている`アプリ名ディレクトリ/app/Services/TestService`に記載されているとあるgetStr()メソッドの戻り値を表示したい場合は下記のように記載する。

        ```php
        {{ $str->getStr() }}
        ```

# 参考文献

- [Laravel 8.x Bladeテンプレート](https://readouble.com/laravel/8.x/ja/blade.html)
なぜAPIをHTTPSで呼び出したのにMixed Contentになるのか

先日、Google Cloud Runに自作のAPIをデプロイして利用していたときのこと。

axiosで`https://dummy.a.run.app/hoge`にPOSTすると、なぜかMixed-Content扱いになって通信が失敗してしまいました。

## 理由

リダイレクトが問題でした。具体的には、

1. https://dummy.a.run.app/hoge
2. **http**://dummy.a.run.app/hoge/
3. https://dummy.a.run.app/hoge/

という順にリダイレクトが進んでいて、このうち2番目がHTTPだったためエラー扱いになってしまいました。

そのため最初から`https://dummy.a.run.app/hoge/`を指定していればよかった。というのが結論になります。

## 備考

このような「末尾のスラッシュ」を**トレイリングスラッシュ(trailing slash)**と呼ぶようです。
【Flutter】アプリリリースに向けて、アイコンをオリジナル画像に変更してみた

Flutterで開発中の個人アプリがそろそろリリースできそうなので、アイコンを設定してみた。
パッケージを使う事で簡単にできるのだが、少し詰まった部分もあるので、ここにまとめておく。

## まずアイコンを用意する
Flutter側の設定をする前に、アイコン画像がないと話にならない。
サイズを適当にすると、うまく表示されないので要注意。

私は、以下のサイトを使って、512×512のpng画像を作成した。
作成は無料でできるが、ダウンロードするには月額1000円程度のプランに登録する必要があるので、あくまで参考までに。
https://www.youidraw.com/

サイズを整えることを押さえておけばOK。

## flutter_launcher_iconsを導入する
画像が用意できたら、アイコンの設定をしてくれるパッケージを用意する。
公式↓の内容に沿って進めればOK。
https://pub.dev/packages/flutter_launcher_icons

```pubspec.yaml
dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_launcher_icons: ^0.8.0   # ←追加
```

現時点で最新のバージョンは`0.8.1`だが、最新にするとエラーが出たため、一つ前の`0.8.0`にした。
`pubspec.yaml`に追記できたら、お決まりの↓

```
$ flutter pub get
```

続いて、再び`pubspec.yaml`に↓を追記する。

```pubspec.yaml
flutter_icons:
  android: true
  ios: true
  image_path: "assets/sket_logo.png"   # ここは画像のパスを記述
```
`image_path`には、冒頭で用意したアイコン画像の配置先を記述する。
ドキュメントの例では`assets/画像ファイル`としていたため、そのまま真似した。

↑の記述ができたら、以下のコマンドを実行。
これにより、アイコンの設定ができる。

```
$ flutter pub run flutter_launcher_icons:main
```

## ビルドして確認
私の場合、iPhoneの実機にビルドしながら開発を進めているので、いつも通りビルドして確認。
すると・・・、アイコンは変わったが、`lost connection`みたいなのエラー？が出て、すぐにフリーズしてしまった。

そこで、先ほど記述した↓を全てコメントアウトしてみた。

```pubspec.yaml
# flutter_icons:
  # android: true
  # ios: true
  # image_path: "assets/sket_logo.png" 
```
この状態で再度ビルドすると、問題なく動いた。

```
$ flutter pub run flutter_launcher_icons:main
```
詳細は不明だが、↑コマンドの時点でアイコンの設定はされているため、その後はコメントアウトしても大丈夫そう。

## まとめ
日本語の情報が少ないので、単純に見落としているだけかもしれないが、
`flutter pub run flutter_launcher_icons:main`を実行した後は、↓をコメントアウトする
というのが個人的にハマりポイントだった。

```pubspec.yaml
flutter_icons:
  android: true
  ios: true
  image_path: "assets/sket_logo.png"
```

この辺り詳しい方がいれば、教えていただけると嬉しい・・・
Firebaseを使ってみた　〜第二章 Firestoreにデータを保存する 〜

React Hooksを使いチャットボットアプリを作成しています。

この章ではAPIを使いFirestoreにチャットボットアプリで使うデータを保存していきます。



<a href="https://qiita.com/iiizoo/items/a31726966c1a42f37809">第一章　サービスをデプロイする </a>
第二章　Firestoreにデータを保存する
<a href="https://qiita.com/iiizoo/items/4afa65a3a79820a2b78b">第三章　Firestoreからデータを取得する</a>　

<h2>Firestoreにデータを保存する までの流れ</h2>
[1. データファイルを作成する](#menu1)
[2. Cloud Functionsをインポートして初期化する](#menu2)
[3. https関数を作成する](#menu3)
[4. デプロイ する](#menu4)
[5. APIを叩く](#menu5)
[6. まとめ](#menu6)



<h2 id="menu1">1. データファイルを作成する</h2>
json型のデータファイルを生成します。
(jsonファイルの書き方が分からない・・・という場合は<a href="https://super-yusuke.gitbook.io/udemy-course/fei-tong-qi-chu-li-promise-ajax/json-woshisonoworendaringusuru-react-app-no">こちら</a>参考にしてみてください)

私はチャットボットで使う応答内容やユーザーの選択肢などをjson型で作成しました。

<h2 id="menu2">2. Cloud Functionsをインポートして初期化する</h2>

Cloud Functionsをインポートし、Firebase Admin SDK を初期化します。
<a href="https://firebase.google.com/docs/functions/config-env?hl=ja">こちら</a>を参考にしました。（jsの場合の書き方もありました）

```functions/src/index.ts
import * as functions from 'firebase-functions'; 
import * as admin from "firebase-admin"; 
admin.initializeApp(); 
const db = admin.firestore();
```

<h2 id="menu3">3. https関数を作成する</h2>

APIからのレスポンスを返すための関数を作成します。
response、statusCode、bodyを受け取ります。

```functions/src/index.ts
const sendResponse = (response: functions.Response, statusCode: number, body: any) => {
  response.send({
    statusCode,
    body: JSON.stringify(body)
  })
}
```

外部から関数を呼び出すため「export」をつけます。
今回はすべて「POST」を使うので、POST以外はエラーになるよう記述します。

```functions/src/index.ts
export const addDataset = functions.https.onRequest(async(req: any, res:any) => {
  if(req.method !== 'POST') {
    sendResponse(res, 405, {error: 'Invalid Request'})
  } else {
    const dataset = req.body
    for(const key of Object.keys(dataset)) {
      const data = dataset[key]
      await db.collection('contents').doc(key).set(data)  
      //'contents'の部分は任意のcollection名でOKです
    }
    sendResponse(res, 200, {message: 'Successfully added dataset!'})
  }
})
```

参考：https://firebase.google.com/docs/functions/http-events?hl=ja


余談ですが、collection、document、dataについて曖昧な場合は<a href="https://firebase.google.com/docs/firestore/data-model?hl=ja">こちら</a>のページに図で解説があるので見てみてください。


<h2 id="menu4">4. デプロイ する</h2>
デプロイ コマンドを実行します。

```
$ firebase deploy
```

デプロイ 完了後、FirebaseのFunctionsに先ほど作成した関数名でデータが生成されます。

![スクリーンショット 2020-10-06 19.40.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578913/e9739e61-076f-794c-cfd9-fbee71c2f955.png)

「リクエスト」の下に記述されているURLをコピーしておきましょう。（次で使います）


<h2 id="menu5">5. APIを叩く</h2>
1.で作成したデータファイルがあるディレクトリまで移動します。
移動したら、以下のcurlコマンドでAPIを叩きます。

```
curl -X POST -H "Content-Type:application/json" -d @[作成したデータファイル名].json [先ほどコピーしたURL]
```

ステータスコード200が返ってくれば成功です。


Cloud Firestoreにデータが格納されていることを確認します。
![スクリーンショット 2020-10-06 19.54.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578913/0ddbeefa-7923-8d4a-2a4d-c780e57611e6.png)


<h2 id="menu6">6. まとめ</h2>
この章ではFirebaseでプロジェクトを作成し、FirestoreにAPIを使ってデータを格納するところまで行いました。

続いてFirestoreに格納したデータを取得して使っていきます。（<a href="https://qiita.com/iiizoo/items/4afa65a3a79820a2b78b">第三章へ</a>・・・）
石川県の Go To EATの加盟店舗のPDFをCSVに変換

[石川県 Go To Eat キャンペーン](https://ishikawa-gotoeat-cpn.com)の加盟店舗のPDFをCSVに変換

10/28現在PDFがダウンロードできません

```shell
pip install tabula-py
pip install pandas
pip install beautifulsoup4
pip install requests
```

```python
from urllib.parse import urljoin

import requests
from bs4 import BeautifulSoup

import pandas as pd
from tabula import read_pdf

url = "https://ishikawa-gotoeat-cpn.com/member_store/"

r = requests.get(url)
r.raise_for_status()

soup = BeautifulSoup(r.content, "html.parser")

dfs = [
    tbl
    for tag in soup.select("p.btn.btn_red.btn_pdf > a")
    for tbl in read_pdf(urljoin(url, tag.get("href")), pages="all", lattice=True)
]

df = pd.concat(dfs).set_axis(["市町村名", "店舗名"], axis=1).reset_index(drop=True)

df.to_csv("ishikawa.csv", encoding="utf_8_sig")
```
【物体検出】SNIP : Scaleに対してロバストに

<h1> Image Pyramid </h1>
trainとtestで違うresolutionを使った時の精度に物体検出の精度が落ちる問題について。

じゃあ入力画像のを解像度を複数の解像度で物体検出すれば精度があがるんじゃね？MST(Multi Scale Training)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/a0698ec8-b191-526a-1aaf-e8a156d55467.png)

今回は入力画像を複数の解像度で検出を行う(a)の方法について考察して改善案を考えてみる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/24937005-70e2-f9e8-10d9-992a9d64a1ff.png)


 Image PyramidでTrainingとTestで別の解像度がきてもある程度大丈夫になった！
しかし！、Scaleを小さくしたことで、小さすぎる物体の情報量が減り見つけるのが困難になる。逆に高解像度の画像で大きすぎる物もReceptive Fieldが大きくないと検出できないやんけ。

じゃあどうすればいいわけ？

<h1> Scale Normalization for Image Pyramids (SNIP) </h1>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/3cbce812-1d45-e213-c024-38403c1b263f.png)

MediamサイズのBounding Boxだけ検出すれば良いんじゃね？(=Normalize Scale)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/130351a3-706d-e277-0caf-1750bee68d8d.png)

上のFig2でもあるように
小さい物体は高解像度であると検出しやすいですね。低解像度だったらグリッドに対して物体が小さすぎて検出が難しい
大きい物体は低解像度であると検出しやすいですね。高解像度だったらグリッドに対して物体が大きすぎて検出が難しい


<h1>結論</h1>

Image Pyramidを使いTrainとTestで別の解像度にも対応出来るようになり、さらにScaleした事による小さすぎる物体や大きすぎる物体の検出精度低下を中くらいのBouding Boxのみを使う事で精度の向上をする事が出来た！

かなりざっくりとしてるので、概要だけでも伝わればなと




<h1>参考文献</h1>

An Analysis of Scale Invariance in Object Detection – SNIP
https://arxiv.org/pdf/1711.08189v2.pdf
SNIPER: Efficient Multi-Scale Training
https://papers.nips.cc/paper/8143-sniper-efficient-multi-scale-training.pdf#search='Multi+Scale+Training'
PR-199: SNIPER:Efficient Multi Scale Training
https://www.slideshare.net/jaewonlee79/pr199-sniperefficient-multi-scale-training
git のブランチ名を bash のコマンドプロンプトに表示する

# git のブランチ名を bash のコマンドプロンプトに表示する

git のブランチ名を bash のコマンドプロンプトに表示する方法です。(Ubuntu 20.04.1 で確認しました)

## 設定方法

```
if [ -e /etc/bash_completion.d/git-prompt ]; then
    source /etc/bash_completion.d/git-prompt
    PS1='\[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\] $(__git_ps1 " (%s)") \$ '
fi
```

* `/etc/bash_completion.d/git-prompt` は `sudo apt install -y git` で git をインストールすると作成されます。
* Ubuntu ではデフォルトで以下のように定義されているので、最後に ` $(__git_ps1 " (%s)") \$ ` を追加します。

変更前:
`PS1='\[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$'`

変更後:
`PS1='\[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\] $(__git_ps1 " (%s)") \$ `

## コメント

`/etc/bash_completion.d/git-prompt` の中身を確認すると以下のようになっています。

```
if [[ -e /usr/lib/git-core/git-sh-prompt ]]; then
	. /usr/lib/git-core/git-sh-prompt
fi
```

`/usr/lib/git-core/git-sh-prompt` の先頭にコメントがあります。
https://github.com/git/git/blob/master/contrib/completion/git-prompt.sh でも参照できます。
(GPL のようです)


```
#    3a) Change your PS1 to call __git_ps1 as
#        command-substitution:
#        Bash: PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
#        ZSH:  setopt PROMPT_SUBST ; PS1='[%n@%m %c$(__git_ps1 " (%s)")]\$ '
#        the optional argument will be used as format string.
```

https://github.com/git/git/blob/d4a392452e292ff924e79ec8458611c0f679d6d4/contrib/completion/git-prompt.sh#L13-L17
docker 

compose構成
https://note.com/koushikagawa/n/nc63a8ae2e810
https://qiita.com/nemui_/items/f911be7ffa4f29293fd5
https://carametal.hatenablog.com/entry/2020/01/15/225637

version: '3' # docker-composeのバージョンを指定
services: 
  nginx: # サービス名
    container_name: "nginx" # コンテナ名
    image: nginx:1.14 # image名を指定。ここではDockerHub上のnginxイメージを指定している。
    links: # ここで指定したサービス名とのリンクを作成する
      - php # サービス名”php”と”nginx”を関連付ける
  php:
    container_name: "php"
    image: php:7.2-apache
    ports:
      - '80:80'
    volumes:
      - ./html:/var/www/html

https://techplay.jp/column/613

同期
http://mashiroyuya.hatenablog.com/entry/dockerphp

僕たちのさくら
https://knowledge.sakura.ad.jp/13265/
std::move(T&&) しただけではムーブコンストラクタもムーブオペレータも呼び出しされない

c++でムーブコンストラクタを特定の条件下で呼び出したいことがあり、`std::move(T&&)`を呼び出すコードを書いた。

しかし、デバッグしてみると対象のムーブコンストラクタが呼び出しされなかった。

暫く悩んだのですが、
この時書いたコードが`std::move(obj)`というコードであり、`Obj obj = std::move(obj)`の様に
rvalueの受け入れ先になる変数が存在していないのが原因でした。

`std::move(T&&)`は受け入れ先の変数の
ムーブコンストラクタやムーブオペレーターを呼び出すために
特定の変数をrvalueにするための操作でしかないという基本的な理解が抜けていました。

`std::move(T&&)`の効果についてはcppreference.comにも書かれています。

[std::move \- cppreference\.com](https://ja.cppreference.com/w/cpp/utility/move):

> std::move は、オブジェクト t からムーブしても構わない、つまり、 t から別のオブジェクトへのリソースの効率的な転送を許可する、ということを示すために使用されます。
>
> 特に、 std::move はその引数 t を表す xvalue 式を生成します。 これは右辺値参照型への static_cast と正確に同等です。