OmniAICreator/Qiita-1.07M huggingface dataset:
Unknown action  ,The action 'create' could not be found for MessagesControllerエラーの解決例

#1.どんなエラー
MessagesControllerにcreateが定義されていませんよという内容です。
ちなみに筆者は下記の通りcreateは定義していました。

＜エラー文＞

<img width="1280" alt="スクリーンショット 2020-01-14 21.03.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555157/cefdf2a8-df14-cfbc-53ea-b07ca7db24d9.png">

＜エラーに該当するファイル＞

```ruby:messages_controller.rb
class MessagesController < ApplicationController
  before_action :set_group

  def index
    @message = Message.new
    @messages = @group.messages.includes(:user)
  end
end

  def create
    @message = @group.messages.new(message_params)
    if @message.save
      redirect_to group_messages_path(@group), notice: 'メッセージが送信されました'
    else
      @messages = @group.messages.includes(:user)
      flash.now[:alert] = 'メッセージを入力してください。'
      render :index
    end
  end

  private

  def message_params
    params.require(:message).permit(:content, :image).merge(user_id: current_user.id)
  end

  def set_group
    @group = Group.find(params[:group_id])
  end

```

#2.原因
今回の場合は'class MessagesController'の'end'の位置が'create'の定義の前で記入してしまっていたため、定義されていないという状態となっていました。
なので八行目の'end'を一番下にカットアンドペーストすることで解決します。
2段階 ssh で入ったサーバーの中をVSCodeで開く

~/.ssh/config に以下のように設定を書きます。

gateway が踏み台サーバーで、RemoteHost-out がアクセスしたいサーバーです。

```
Host gateway
   HostName sshgate.hoge
   User hoge

Host RemoteHost-out
  HostName RemoteHost
  User fuga
  ProxyCommand ssh -W %h:%p gateway
```

`ssgate.hoge`, `hoge`, `RemoteHost`, `fuga`を適当なものに置き換えてください。

## VSCode: remote-ssh

VSCode で remote-ssh という拡張機能をインストールします。
そのあとエディタの左下にある

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/385573/21b0b155-963e-ff33-1f57-d1dfce371b95.png)

この緑のマークをクリックします。すると自分の環境の~/.ssh/config に書かれている Hostが一覧で出てくるのでアクセスしたいやつにクリックします。
これでアクセスすることができます。ここでパスワードが必要な場合は要求されるのでパスワードに答えましょう。

### 開くフォルダを決める

エディタの右上にある

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/385573/30ff079c-51e7-000f-7b61-b173537dd7e0.png)


このファイルのアイコンをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/385573/ecb0a846-0fa7-66a0-e1a2-07c7885fbb75.png)



するとこのようにOpen Folder というボタンがでるのでここをクリックします。

ディレクトリ一覧が出てくるので開くディレクトリを選択します。

これで多段ssh でも VSCode で開くことができます！
GitLab CIで連続pushしたときに先行ジョブを中断する

コードベース＆開発チームが大きくなると、ビルドにかかる時間も、ビルドが始まるまでの待ち時間もどんどん長くなっていきます。お金を積んでGitLab Runnerを増強してしまえれば一番早いですが、この文書では小手先のテクニックでビルドキューに少しでも空きを作る方法を紹介します。

### 確認環境

* GitLab.com (12.7.0-pre 94b8fd8d152)

### 背景

次のように自動テストを実行する test ステージと、デプロイを実行する deploy ステージからなるビルドパイプラインを構築しているとします。

```yml:.gitlab-ci.yml
image: busybox:latest

stages:
  - test
  - deploy

frontend-test:
  stage: test
  script:
    - echo "frontend-test ..."
    - sleep 10

backend-test:
  stage: test
  script:
    - echo "backend-test ..."
    - sleep 10

deploy:
  stage: deploy
  script: "echo deploying..."
```

この作業ブランチを GitLab に push すると、自動的にビルドが開始されます。ここまでは期待通りですが、ここで修正ミスに気付くなどして、まだビルドが終わっていない状態で再度コードを push するとします。すると、1回目の push に対するビルドとは別に、もう1つ新たにビルドパイプラインが開始されてしまいます（下図参照）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33668/5a692ce8-4def-a099-64c0-341330c69323.png)

一般に、静的解析や自動テストは最新のコミットに対する実行結果だけがあれば十分なケースが多く、連続して push した場合には先行ジョブのビルドを続ける意味がありません。そのための GitLab Runner のリソースを別のジョブに割り当てた方が有意義といえます。

### 解決策

GitLab には、中断可能（interruptible）なジョブを指定する機能があるため、これを使います。デフォルトでは、interruptible = false です。

```diff:.gitlab-ci.yml
image: busybox:latest

stages:
  - test
  - deploy

frontend-test:
  stage: test
  script:
    - echo "frontend-test ..."
    - sleep 10
+ interruptible: true

backend-test:
  stage: test
  script:
    - echo "backend-test ..."
    - sleep 10
+ interruptible: true

deploy:
  stage: deploy
  script: "echo deploying..."
```

interruptible = true を指定した状態でコードを連続 push すると、下図のように先行するパイプラインのジョブが自動的に中断され、canceled ステータスになるのが分かります。ただし、ドキュメントにも記載がある通り、1つでも interruptible = false なジョブの実行が開始されてしまうと、そのパイプラインはもう中断できません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33668/773e2c54-1154-eec8-9a30-ff91df397fdf.png)

なお、先行ジョブを中断するかどうかはブランチ単位で管理されるため、下図のように異なるブランチで並行 push してもどちらかのパイプラインが中断されるわけではありません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33668/62eeeb35-ffb9-05f0-54a1-3c2a9d2587a0.png)

### 参考

* [GitLab CI/CD Pipeline Configuration Reference | GitLab](https://docs.gitlab.com/ee/ci/yaml/#interruptible)
npmの-gオプションでインストールするモジュールの格納先の変更

##UbuntuにNodeJSをインストールしたらまさかの不便さに遭遇

先日UbuntuにNodeJSやらNPMをインストールしたところ
グローバルにモジュールをインストールしようとしたら失敗しました。

**sudo**で実行すればインストールできたのですが[Gatsby.jsのチュートリアル](https://scotch.io/tutorials/zero-to-deploy-a-practical-guide-to-static-sites-with-gatsbyjs)をやっていたときにGatsbyのプロジェクトを作成しようとしてエラーが発生しました

以下遭遇したエラーの一部

```
gyp ERR! stack Error: EACCES: permission denied, mkdir '/home/【ユーザー名】/scotch-blog/node_modules/sharp/build'
```

このエラーが発生したときに
***NodeJSをまたインストールしないといけないのかな***と暗い気持ちになっていましたが、***以下の方法で***npmパッケージをインストールするディレクトリを指定することで事なきを得ました

以下はそのやり方を共有します

## グローバルなモジュールをインストールするディレクトリは指定できる!!

[元ネタのリンク](https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally)

以下にエラー回避をマニュアルでやる方法をお伝えします

### 1. $HOMEのディレクトリにnpmのモジュール格納用ディレクトリを追加する

```
 mkdir ~/.npm-global
```

### 2. npm set configで今作ったディレクトリを指定する

```
 npm config set prefix '~/.npm-global'
``` 

### 3. ~/.profileで環境変数を追加する

``` .profile
 export PATH=~/.npm-global/bin:$PATH
```

### 4.$PATHを更新する

```
 source ~/.profile
```

以上です。お疲れさまでした。元ネタのリンクではそのほかにも***nvm***を使った方法などを紹介しています。NodeJSのバージョン管理ができる代物なので時間があればそちらにも挑戦したいところです。

##更新履歴

- 2020/1/14 新規作成
DynamoDBのテーブルデータをNodejsでS3にBackupする

## はじめに

DynamoDBに大量にあるテーブルのデータを一括でS3にバックアップしたい。。みたいな状況があったので、メモとして書いておきます。

ちなみにテーブルが少量であれば、Data Pipelineを使って簡単に出来ます！！
`aws-sdk`ではData Pipelineの細かいオプションは設定出来なかったようなので、nodejsでData Pipelineを操作することはしていません。

## 環境

* Nodejs v11.1.0
* DynamoDB


## 事前準備

バックアップを行うためにS3に専用のバケットを作成しておいてください。
この記事では`backups`というバケットを作成したという例で進めます。

## プロジェクトを作成

適当ですが、`dynamodb-backuper`みたいなディレクトリを作成して進めていきます。

```sh
$ mkdir dynamodb-backuper

$ cd dynamodb-backuper

$ npm init

$ npm install aws-sdk dynamodb-backup-restore --save

$ touch export.js restore.js
```

## export.js

`export.js`はその名通りDynamoDBから全テーブルのbackupを行うファイルです。

```javascript
'use strict'

const AWS = require('aws-sdk')
const DynamoDB = new AWS.DynamoDB({region: 'ap-northeast-1'})

async function main(){
    let tables = await getAllTableLists()
    tables.forEach((v) => {
        exportToS3(v)
    })
}

// 実行
main()

// Get all table names from DynamoDB
async function getAllTableLists() {
    let params = {}
    let tables = []

    while(true) {
        let response = await DynamoDB.listTables(params).promise()
        tables = tables.concat(response.TableNames)

        if (!response.LastEvaluatedTableName) {
            break
        } else {
            params.ExclusiveStartTableName = response.LastEvaluatedTableName
        }
    }
    return tables
}

// Function to perform backup
function exportToS3(tableName){
    const Backup = require('dynamodb-backup-restore').Backup
    let config = {
        S3Bucket:     'backups', // 必須 - バケット名 
        S3Prefix:     tableName, // 任意 - 保存するS3のサブフォルダ名
        S3Encryption: 'AES256', // 任意 - 暗号化
        S3Region:     'ap-northeast-1', // 必須 - リージョン
        DbTable:      tableName // 必須 - エクスポートするテーブル名
    }

    let backup = new Backup(config)
    backup.full()
}
```

以下でエクスポートを実行出来ます。

```sh
$ node export.js
```


## restore.js

`restore.js`もそのままですが、export.jsでS3にエクスポートしたデータを今度はDynamoDBの指定のテーブルにインポートします。

リストアを行う前に事前にインポートするテーブルを作成しておく必要があります。
今回は`newTest1`というテーブルを作ったとして進めます。
この時に注意が必要なのが、データ量によっては無料枠ではキャパシティーレベルが超えてしまうため、データサイズに応じてオンデマンドに変更してください。


以下のコードでは、`execRestore`関数の第一引数にS3にバックアップをとった`test1`というサブフォルダを指定し、インポート用に作成した`newTest1`というテーブル名を第二引数に設定します。

```javascript
'use strict'

function execRestore(bucketName, tableName){
    const Restore = require('dynamodb-backup-restore').Restore
    let config = {
        S3Bucket:   'backups', // 必須
        S3Prefix:   bucketName, // 任意
        S3Region:   'ap-northeast-1', // 必須
        DbTable:    tableName, // 必須
        DbRegion:   'ap-northeast-1', // 必須
    }

    Restore(config)
}

// 実行
execRestore('test1', 'newTest1')
```

以下でリストアを実行出来ます。

```sh
$ node restore.js
```
Laravel5.5 にmdbootstrapをインストールする方法【How to install mdbootstrap on Laravel 5.5】

Laravel mixを使ってmdbootstrapをインストールします

#install mdb

```
npm i mdbootstrap
npm i @fortawesome/fontawesome-free
```

無駄なのはいってますが、package.json

```json:package.json
{
  "private": true,
  "scripts": {
    "dev": "npm run development",
    "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "watch-poll": "npm run watch -- --watch-poll",
    "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
    "prod": "npm run production",
    "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
  },
  "devDependencies": {
    "cross-env": "^5.0.1",
    "jquery": "^3.2",
    "laravel-mix": "^4.0.7",
    "lodash": "^4.17.4",
    "resolve-url-loader": "^2.3.1",
    "sass": "^1.15.2",
    "sass-loader": "^7.1.0",
    "vue-template-compiler": "^2.6.11"
  },
  "dependencies": {
    "@fortawesome/fontawesome-free": "^5.12.0",
    "axios": "^0.19.1",
    "bootstrap": "^4.4.1",
    "chart.js": "^2.9.3",
    "mdbootstrap": "^4.11.0",
    "popper.js": "^1.14.3"
  }
}
```


#setting bootstrap.js

```js:resourece/asset/js/bootstrap.js
try {
    window.Popper = require('mdbootstrap/js/popper').default;
    window.$ = window.jQuery = require('mdbootstrap/js/jquery');
    require('mdbootstrap/js/bootstrap');
    require('mdbootstrap');
} catch (e) { }

```

#import app.scss

```css:app.scss
@import "~@fortawesome/fontawesome-free/css/all";

// Bootstrap
@import "../../../node_modules/mdbootstrap/css/style.css";
@import "~mdbootstrap/scss/mdb-free";
@import "../../../node_modules/mdbootstrap/css/bootstrap.min.css";
```

#fin

```
npm run dev
```
JavaScriptでif文の条件式に変数だけを記述するやつ

よく忘れるのでメモ

## JavaScriptでは 0, "", undefined, null は false になる
以下のようなよくあるif文。存在チェックなどに使われています。
この場合、例えばhogeがundefinedだとif文の中に入ります。

```javascript
if(!hoge) {
  ・・・
}
```

**JavaScriptでは以下の値はfalseとみなされます。**
- 空文字("")
- 数値の0
- NaN
- null
- undefined
旧リポジトリの資源を新規リポジトリへクローンしたい

## はじめに
未経験からプログラマー転職して２年目になります。

今回は、元リポジトリの資源をそっくりそのまま、新しいリポジトリでバージョン管理するための手順を初めてやってみたのですが、少し手間取りました。
そのため、今回学んだことを自分なりにまとめてみました。
どなたかの役に立てれば幸いです。

もし間違いやご意見等ありましたら、学びになるのでぜひご教授ください。

## 参考URL
- [gitリポジトリの複製](https://qiita.com/syuji-higa/items/e380289502c7896daf0f)
- [Github公式（Adding a remote）](https://help.github.com/en/github/using-git/adding-a-remote)

## 1.旧リポジトリから資源をクローンする
`git clone 旧リモート先（URLの場合：https:～.git）`
`git clone 旧リモート先（SSHの場合：〇〇@github.com:～.git）`
こちらはお好みで。
## 2. 「.git」ディレクトリを削除する 
`git rm -r .git`
「.git」の中には、リモート先のURL情報やコミット履歴などの情報が入っています。
ここでは旧リポジトリの履歴を一旦きれいにするため、削除します。
## 3. 新しく「.git」ディレクトリを作成する
`git init`
## 4. リモート先を追加する
` git remote add 新リモート先（URLの場合：https:～.git）`
` git remote add 新リモート先（SSHの場合：〇〇@github.com:～.git）`
「.git」ディレクトリを新規に作成しただけなので、当然リモート先の情報がありません。
したがって、新しくリモート先を指定する必要があります。
## 5. 新リモート先になっているか確認する
`git remote -v`
## 6. 旧リポジトリでクローンした資源をadd&commit
`git add .`
`git commit -m "first commit"`
## 7. 新リポジトリに資源をpushする
`git push 新リモート先（URLの場合：https:～.git）`
`git push 新リモート先（SSHの場合：〇〇@github.com:～.git）`
## 最後に
リポジトリを変更することはこれまで経験がなかったので、Gitをより理解するいい機会となりました。
よくつかう dockerコマンドまとめ

## よくつかうdocker(-compose含む)コマンドを書きなぐる

- 滅びの呪文と復活の呪文

```
docker-compose pull && docker-compose down && docker-compose up -d
```

- dockerイメージの確認

```
docker images
```

- docker(-compose)内のログをみる

```
docker-compose logs (-f: ログを表示し続ける) サービス名(api, db)
```

- dockerサービスの起動

```
docker-compose up (-d: バックグラウンド)(--build: ビルドしてから実行)(サービス名: サービス名を指定すると指定サービスだけ起動)
```

- dockerサービスの停止

```
docker-compose stop
```

- dockerサービスの停止と削除

```
docker-compose down (--rmi all: docker imageも一緒に削除する)
```

- dockerの更新(最新イメージの取得)

```
docker-compose pull
```


### おわり

基礎的なコマンドですがよく忘れるので備忘録。

### Tips

Aliasに `docker-compose=dc` すると効率Up!!
[React/state更新]inputタグなどの入力フォームにおけるvalue値を更新

inputタグなど、入力値を変える場合はonChangeイベントでstateを更新する必要がある

空で設定した初期値を更新し、下記のように
name:タスク名,
content:炊事
というようにvalue値を更新できるようにする方法を備忘録として残しておく。

![入力フォーム.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378609/3d1db92b-1171-e3f5-617f-016a0e40e2ae.png)



## コンポーネント内でStateを定義する

初期値は空文字のため、{name:'', content:''}で設定

```js
    const [newData, setNewData] = useState({name:'', content:''});
```

先程のnewDataを使用し、value値に使用する
そして後ほど定義するinputChangeをonChangeイベントに設定

```html

        <form>
            <TextField  label="タスク名" name="name" value={newData.name} onChange={inputChange} />
            <TextField label="内容" name="content" value={newData.content} onChange={inputChange} />
            <Button color="primary" variant="contained">登録</Button>
        </form>

```


## コンポーネント内にonChangeイベントのfunctionを定義

keyとvalueを設定し、newDataのkeyと入力フォームのname値が一致している場合にvalueに更新し、新しく作り直したオブジェクトに代入して、setNewDataで、stateの更新を行う。

```js


    function inputChange(e){
        const key = e.target.name;
        const value = e.target.value;
        newData[key] = value;
        let data = Object.assign({}, newData);
        setNewData(data);
     }

```

以上、let data = Object.assign({}, newData);でオブジェクトを作り直さないとstateが更新されず、再レンダーもされません。
少し詰まりました。

他にもっといいやり方があるかも。。
【Django】urls.pyのurlpatternsのr'^$'とr''って何が違うの？

結論から言うと「**なんで君そんな質問するの？**」ってくらい違うんですが、最初見た時挙動がイメージできなかったのと、特殊文字のせいでググっても全然ヒットしなかったこともあって記事にしておきます。

#事の発端
最近Djangoの開発案件にアサインされたのでソースコード見ながら勉強していたんですが、Railsで言うところのルータである`urls.py`（ルートURLconf）にこんな感じでルーティングが定義されていました。

```urls.py
(...)

urlpatterns = [
    url(r'^$', views.hoge),
    url(r'', include(fuga)),
    (...)
]

(...)
```

1行目はわかるんですよ。パス指定なしでルートディレクトリにアクセスした時のルートなんだな～と。

2行目はなんですか・・・。空文字・・・？　ルートディレクトリの後に空文字だから、1行目と同じでは・・・？？？

頑張ってGoogleで「urlpatterns 空文字」とか調べてみたんですが、それらしい解説には出会えず・・・。

#解決編
困り果てて社用Slackで「わからん～！」と喚いていたら、優しい先輩方が助けてくれました。

空文字にマッチする`r''`という正規表現は、どうやら**すべての文字列にマッチするワイルドカード**的な書き方のようです。

そう言われて「なるほど」と思い、自分でも検証してみると、

```sample.py
import re
if(re.match(r'', "abcde")):
    print("match") # -> "match"
if(re.match(r'', "     　　　　")):
    print("match") # -> "match"
```

確かに、何にでもマッチしています。

つまり、上の`urlpatterns`の書き方は、「**ルートディレクトリ以外へのアクセスはとにかく全部`include(fuga)`してね**」という意味だったんですね。いやはや勉強になりました。

#もうちょっと詳しく
とりあえず当初の疑問は解消したわけですが、どうにもモヤモヤします。というのも、検証している過程で

```sample.py
import re
m = re.findall(r'', "abcde")
print(m) # -> ['', '', '', '', '', '']
```

・・・どゆこと？　という疑問が生じたためです。

再び考え込んでいるうちに、「**正規表現はオートマトン**」ということを思い出しました。オートマトンについてはまだ人にちゃんと説明できるほど勉強できていないんですが、ざっくり言うと「入力によって状態が遷移する機構（なんともそれっぽい）」だと思ってます。

つまり、`r''`という正規表現は、「**「何も入力がない[^1]」が入力されたら「マッチした」という状態に遷移するオートマトン**」を意味していたわけです。

![スクリーンショット (45).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/507842/6d5f191b-62d9-e0ce-bfa7-98c008c77bc8.png)

（お粗末な図で恐縮です）

なので、文字列`abcde`を`r''`で判定する際には、行頭・文字と文字の間・行末において「**何も入力がない**」が発生するため、`m`の長さは6になったというわけです。

先輩が「**`r'.*'`は最後まで読み込まないといけないけど、`r''`は1文字も読み込まなくてもマッチするから速い**」と言っていた意味も半分理解できました（もう半分は最長一致がどうとかいう話だと思いますが、おいおい勉強しようと思います）。

#まとめ
正規表現のグーグラビリティの低さには困ったものですね・・・。

#参考文献
『[オートマトン 言語理論 計算論 I [第2版]](https://www.saiensu.co.jp/search/?isbn=978-4-7819-1026-0&y=2003)』サイエンス社 2003年

[^1]: オートマトンではこれを`ε`で表すらしいです。
AWS Solutions Architect Associate (SAA) にギリギリ合格した

Qiitaには初めて投稿します。本当にだいぶギリギリで合格したので、Qiitaへの投稿テストも兼ねて勉学の記録など残せればと思い書いてみます。
#受験勉強前のスキルセットなど
##AWS経験
皆無。「クラウド is 何？」状態。
##エンジニア経験
これも全く無し。

##保有資格
- 基本情報技術者（2019年春合格）
    - エンジニア経験皆無だけど何とか取った試験。

#受験勉強内容
##学習期間
正味約2ヶ月といったところか。

##学習題材
1. [この１冊で合格！　AWS認定ソリューションアーキテクト - アソシエイト テキスト&問題集](https://www.kadokawa.co.jp/product/321811001165/)
    - ざっと読んで全体感を掴んだ。薄くて読みやすい本であった。
2. [AWS Web問題集で学習しよう](https://aws.koiwaclub.com/)
    - 上の本読んだ後、ゴールドプラン契約してひたすらこれを解きまくった。とはいえ割けられた時間が少なく、結局受験までにこなせた問題は#85くらいまでで、当該サービスの提供問題数の約6割程度だった。それでもまあ600問くらい解いたし、頑張った。
3. 自力でハンズオン
    - AWS上で色々と遊んだ！EC2建てたしRDS建てたし、参考記事読んでELBも建てた。ここで培ったものはとても大きかった。
4. [AWS SAA公式模擬試験](https://aws.amazon.com/jp/certification/certified-solutions-architect-associate/)
    - 本番受験2週間前くらいに受けて、**落ちた。だいぶ焦った。**

#受験結果
739/1000で合格。720が合格点だったので、相当にギリギリだった。

#雑感など
答案を埋めた時点では全く合格した感触がなかったし、ギリギリとはいえ合格できて本当によかった。あとテストセンターのあの画面、本当になんの前触れもなくしれっといきなり合否が表示されて非常に心臓に悪かった。もう少しドキドキしてから表示されてほしかった笑
合格点ギリギリだったしそんなに両手を上げて喜べないところでもあるのだが、まあ必要最低限の努力で受かることができたのかなと思えばここに書く意味もあったのかなと。

#次への抱負
Solutions Architect Professional? さぞ難しいのだろうねえ。。。。。
Power Automateで交通機関の遅延情報取得からノンストップで遅刻連絡

[2020/1/16追記] 改良版はこちら→https://qiita.com/h-nagao/items/920ede52a38cf99b1cca

きっかけは朝のタイムライン。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/4ce354e9-3561-eb78-4ab6-78db9c90e691.png)
たしかに。今日は自分の乗っている路線もすごい遅延とダイヤ乱れが発生していました。
あまり自分からその日の運行情報とか見に行かないし、テレビもEテレ一択なので、あまりニュースを見ない私が考えたソリューションがこちら！

###Power Automateでトリガーして通知送ればいいんじゃない？？

だいたいどの路線にも最近は運行情報をつぶやくTwitterアカウントがあります。下図は東西線の例です。
<img width="375" alt="EC8CF47E-814D-4E24-B795-652642FFB5D8.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/cb543d2e-0dd9-75c5-68be-17fb6d71138f.jpeg">


Power Automateには『Twitterで新しいツイートがあったとき』というトリガーがあるので、これを利用します。
条件には
``` from:@ここにツイッターアカウント```
を指定します。
これだけだと毎回通知が飛んでしまうので、そのあとに分岐を入れます。
『TweetのTextに "平常どおり" が **含まれていなかったら** 』という条件です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/e6b2ee9b-9d6f-1093-5763-1b398f0371b2.png)
東京メトロの場合はおおよそ朝の7時と夕方5時に定期ツイートがあります。
運行状況が正常なら、「mm月dd日hh時mm分現在　ご利用ありがとうございます。東西線は平常どおり運転しています。」という文面でつぶやかれるので、これ以外なら何らかの異常だと簡単に判定します。

※異常のパターンは結構いろいろです。ダイヤ乱れ、遅延、運行を中止している などなど

おおよそツイートが出てから5分程度でスマートフォンに通知が届きますので、家を出る前の危機回避にぜひ使ってみてください！

※複数路線の場合には複数のFlowを作成する必要があるので、通知の先頭にXXX線と入れておくと判別しやすいです

**[2020/01/15追記]**
###さらに遅延のため遅刻する旨を会社に連絡しちゃいましょう！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/d2bfbbe6-ad07-8fb4-be22-572d322e56f8.png)

遅延情報は数十分おきに発生するので、モバイルへの通知を行ったあとに適当なデータソースに、すでに遅延ツイートがあったかを見に行きます。
この場合はSharePointに、日付と路線だけ入れておきます。
アイテムを日付と路線で指定し、アイテムが0件ならメール送信＆SharePointにアイテム登録。
1件以上あったら、メールも送らない という分岐にしました。

あとはツイートでうまく遅延かダイヤ乱れかを抽出して連絡すればさらに信ぴょう性が(以下略
Rocket.Chatでユーザのパスワードを設定／リセットする機能が消えた

# はじめに
Rocket.Chatバージョン2.3.0から、管理者がユーザーのパスワードを設定したり、パスワードをリセットしたりする機能が無くなったようです。ユーザーごとに設定されたメールアドレスにパスワードが送られてくる仕様になりました。セキュリティの観点（管理者がパスワードを知っている必要は無いと言う理由）ことと、運用側の負荷低減（問い合わせを無くすとか？）の目的がある様ですが、フォーラムでも揉めており、他のOSSのチャットツールに移行する人も出てきている様です。とは言え、現状バージョン2.2.0で特に機能的に困っていないので、このまま放置しておく予定だった。
https://github.com/RocketChat/Rocket.Chat/issues/15880


#### ・2.2.0のユーザ登録画面

<img width="390" alt="スクリーンショット 2020-01-14 22.04.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317297/561e69a8-195b-2e74-aebd-704da51ffc2e.png">

#### ・2.3.0のユーザ登録画面
<img width="389" alt="スクリーンショット 2020-01-14 22.13.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317297/5821c98d-e540-db7a-ccaa-16885fbfab26.png">

# 元に戻すことにしたみたい
でもユーザから沢山のクレーム？があったようで元の通りに戻すことにしたみたい。バージョン2.3.3および2.4.1で修正されているのでアップデートしてみた。

# 環境

・Rocket.Chat
　社員（約５０名）のコミュニケーションツール。
　バージョンアップ前：0.70.0
　バージョンアップ後：2.2.0

・OS
　Amazon Linux 4.14.104-95.84.amzn2.x86_64

・その他
　Docker and Docker-Compose はインストール済み。

# アップデート方法

[公式](https://rocket.chat/docs/installation/docker-containers/docker-compose/)の手順を参考にした。

docker pull rocketchat/rocket.chat:latest
docker-compose stop rocketchat
docker-compose rm rocketchat
docker-compose up -d rocketchat

#### ・2.3.3のユーザ登録画面
<img width="390" alt="スクリーンショット 2020-01-14 22.16.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317297/8b471f33-095a-1618-b67a-94923ea7c5d4.png">

# まとめ
アップデート自体は簡単にできた。でも殆ど（管理者以外全員）のプロフィールの写真（アバター）がデフォルトに戻っていた。環境に依存する問題かもしれませんが、社内向けのチャット用途なのでことなきを得た。
トランザクションとは

IT用語トランザクションについて

複数の処理を1つにまとめたもの。
ただし、これら「複数の処理」は分離させることはできないこと。


具体例

1. Aさんの口座から100円分差し引き、残高1,000 - 100 = 900円にする。
2. Bさんの口座へ100円分プラスし、残高2,000 + 100 = 2100円にする。


1．の処理がうまくいって、2．の処理が何らかの原因で失敗したとする。そうなると、
Aさんの口座残高は5,000円になっているいる一方で、Bさんの口座残高は20,000円のままで、5000円が「消失」してしまうことになる。

まとめ

トランザクションは成功か失敗かの二択
【Bundle】Catalina にアップデートしたらbundle exec pod installが失敗した話

# 概要
Mac OSX Catalinaにアップデートした後に

```shell
$ bundle exec pod install
```

を叩くと

```shell
Failed to execute process '/usr/local/bin/bundle'. Reason:
The file '/usr/local/bin/bundle' specified the interpreter '/System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/bin/ruby', which is not an executable command.
```

と出てしまう。

どうやら使っているインストールされているRubyのバージョンは2.6だけど、
コマンドが参照しているのが2.3で端末に存在していないので実行出来ないという事だと思います。

# 解決方法
bundleの再インストールで解決しました！

```shell
# bundleの削除
$ sudo rm -rf /usr/local/bin/bundle
```

```shell
# bundle, bundlerの再インストール
$ gem install bundle
$ gem install bundler
```

```
# 再度実行してみる
$ bundle exec pod install
```

出来ました！

## 備考

これの解決の前に

```shell
xcode-select --install
```

も実行しました。

これだけでは解決しなかったのですが、これも必要なのかもしれません。
上記の再インストールで出来なかった人はやってみても良いかも。

誰かのお役に立てば。
macOS 10.15 Catalinaでwebpackをインストールしようとしてエラーになった

# 環境
- macOS 10.5
- node 8.5.0
- npm 5.3.0

# 手順
プロジェクトディレクトリでwebpackをインストールします。

```
npm i -D webpack
```

下記のエラーが出ます。

```
xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance
No receipt for 'com.apple.pkg.CLTools_Executables' found at '/'.
No receipt for 'com.apple.pkg.DeveloperToolsCLILeo' found at '/'.
No receipt for 'com.apple.pkg.DeveloperToolsCLI' found at '/'.

gyp: No Xcode or CLT version detected!
gyp ERR! configure error
gyp ERR! stack Error: `gyp` failed with exit code: 1
gyp ERR! stack     at ChildProcess.onCpExit 
gyp ERR! stack     at emitTwo (events.js:125:13)
gyp ERR! stack     at ChildProcess.emit (events.js:213:7)
gyp ERR! stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
gyp ERR! System Darwin 19.2.0
gyp ERR! command "/Users/hiro/.nodebrew/node/v8.5.0/bin/node" "/Users/xxxx/.nodebrew/node/v8.5.0/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
gyp ERR! node -v v8.5.0
gyp ERR! node-gyp -v v3.6.2
gyp ERR! not ok
npm WARN webpack-test@1.0.0 No description
npm WARN webpack-test@1.0.0 No repository field.
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.11 (node_modules/fsevents):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.11 install: `node-gyp rebuild`
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: Exit status 1```
```
node-gyp.jsのインストールでエラーが出てるようです。

# 対策
Xcodeが入ってなかったので、AppStoreからXcodeをインストール。
が、それでも同じエラーが出るためCommand Line ToolsをXcode同梱版を使うように指定します。

```
sudo xcode-select --switch /Applications/Xcode.app
```

これで、node-gyp.jsがインストールされて、webpackもインストールされました。
IQOSのパックコード入力をできるだけ省力化

# IQOSのパックコード入力がめんどくさい
先日まで使用していたiPhone7。カメラの調子が悪かったのでQRコードではなくアルファベットで入力していました。めんどくさい。
iPhone11proに買い替えたことをきっかけに、IQOSのパックコード入力を省力化できないか試してみました。

ところで、`iPhone ショートカット LINE`で検索するとLINEで帰るコールするショートカットがたくさん出てきますが世の中の皆さんは、そんなに帰るコールを自動化したいものなんですか。

# さっそくつまずく
`書類　＞　QR/バーコードをスキャン`
`共有　＞　クリップボードにコピー`
`App　＞　LINE　＞　メッセージをIQOSに送信`
の順に追加。

いざ実行。

標準カメラが起動し、QRコードを読み込んだら。。。LINEが起動。
うん。起動はしました。
手動でIQOSのトークルームを探して開いて、TXTボックスにペーストし送信。
登録できました。

違う。そうじゃない。

# メッセージをIQOSに送信
検索してみると皆さん、同様に
`App ＞　LINE　＞　メッセージをIQOSに送信`
でトークルームが開かないみたい。
開きそうなのに。
さらに[検索](https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q14214309194)してみると
`お使いのAppからショートカット　＞　全て表示　＞　メッセージを{ユーザー名}に送信`
でショートカットを作成し呼び出すと良いらしい。

`メッセージをIQOSに送信`を作って呼び出すことにしました。

# 動け
`書類　＞　QR/バーコードをスキャン`
`共有　＞　クリップボードにコピー`
に続けて
`App　＞　ショートカット　＞　ショートカットを実行`
を追加し、実行するショートカットに先ほど作った`メッセージをIQOSに送信`を指定します。

いざ実行。

標準カメラが起動し、QRコードを読み込みLINEが起動。
IQOSのトークルームが開いたのでTXTボックスを触ってペースト。
送信！！

# 動いた
動きました。動いたけど、もうちょっと何とかならないのかと。
アルファベットを入力するよりも、写真AppにQRコードの写真が溜まっていかないし、手間が減った気がします。
いや、気がついていないだけで、もっと簡単な方法があったのかもしれません。

TXTボックスにクリップボードの内容がペーストされてるとなお良いし、送信までしてくれるととても嬉しいんです。
今後、ショートカットAppがもっとできることが増えて、便利になることを祈ります。
INSERT文作成マクロ

```vb:insert.vba
Option Explicit

Sub MakeInsert()

Dim sqlstring As String
Dim colindex As Integer

Dim sqlcolumns As String
Dim maxcol As Integer

Const Phrase1 As String = "INSERT INTO "
Const Phrase2 As String = " ("
Const Phrase3 As String = ") VALUES ("
Const Phrase4 As String = ");"

'SQLシートをクリア
SQL.Cells.Clear

'テーブル名を取得
sqlstring = Phrase1 + DATA.Range("B3") + Phrase2

'カラム行の終わりを取得
maxcol = Range("B6").End(xlToRight).Column

'1カラムだけだと16384が返ってくるので2を無理やり代入
If maxcol = 16384 Then

  maxcol = 2
  
End If

'カラム数だけ回してカラム定義部分を作成
'カラムが入っているのが2列目なので2からmaxcolまで
For colindex = 2 To maxcol

  sqlcolumns = sqlcolumns + DATA.Cells(6, colindex)
  
  If colindex <> maxcol Then
    sqlcolumns = sqlcolumns + ", "
  Else
  ' カラム定義の最後尾の処理
    sqlcolumns = sqlcolumns + Phrase3
  End If
Next

'INSERT文のカラム部分をVALUEの手前まで作成する
sqlstring = sqlstring + sqlcolumns


Dim maxrow As Integer
'値が入っている最後の行数を取得
maxrow = Range("B6").End(xlDown).row

Dim rows As Integer
Dim cols As Integer
Dim valuestring As String
'値を入れてSQLを作成
'行数分だけ回す。値の入っているのが7行目からなので7からmaxrowまで
For rows = 7 To maxrow
  'カラムの数だけ回す
  For cols = 2 To maxcol
  
    If IsEmpty(DATA.Cells(rows, cols)) = True Then
      '空白の時はnull扱い
      valuestring = valuestring + "null"
    Else
      '文字列の時はシングルクォーテーションで囲む
      If TypeName(DATA.Cells(rows, cols).Value) = "String" Then
        valuestring = valuestring + "'" + DATA.Cells(rows, cols) + "'"
      Else
      'それ以外は文字列に変換
        valuestring = valuestring + CStr(DATA.Cells(rows, cols))
      End If
    End If
    
    If cols <> maxcol Then
      valuestring = valuestring + ","
    End If
    
  Next
  
  SQL.Cells(rows, 2) = sqlstring + valuestring + Phrase4
  valuestring = ""
Next

End Sub


```
- [Excel VBAでIndexもシート名も使わず、シートオブジェクトをダイレクトに指定する方法](https://thom.hateblo.jp/entry/2015/02/02/061313)
- [空白セルを正しく判定する方法](https://excel-ubara.com/excelvba4/EXCEL237.html)
- [Excel VBAでシート全体をクリアする方法](http://www.koikikukan.com/archives/2016/10/04-003333.php)
不具合管理で管理するべき内容

# 不具合管理で管理するべき内容

用途ごとにバグ管理する項目を作成してみました。
用途に合わせ、記載粒度やかける工数を決めると、なお効率が良くなります。

## バグ修正を効率的に回す

バグ修正をチームで効率的に修正するためには、以下の管理項目が有効です。

| 項目       | 説明                                                 |
| ---------- | ---------------------------------------------------- |
| 題名 | バグ一覧に表示される項目。将来的に検索しやすいように名は体を表すようにする |
|説明|・バグの内容説明<br>・再現手順<br>期待する動作<br>ログ など|
|ステータス|新規、再現待ち、解析中、解析済み、修正中、承認待ち、終了|
|優先度|高、中、低|
|担当者|不具合修正におけるアクションアイテムを持っている人|
|対象バージョン|リリースしたプログロムの版|
|期日|修正の期日(クリティカルパスまでのフロート）|
|試験項番|試験項目の番号|
|直接的原因|不具合発生の具体的な原因|


## ナレッジの蓄積

１年たつと当時何をおもってそうしたのかわからなくなります。コードは具体的な動作は明確に示しますが、何を目的としているかは表現できないからです。当時の思い・狙いを蓄積しておくことで将来的に安心して修正することができます

| 項目       | 説明                                                 |
| ---------- | ---------------------------------------------------- |
| 概要       | どんなバグか。                                       |
| 直接的原因 | 本当に具体的な原因                                   |
| 処置内容   | どんな処置をしたのか、なぜそのような手段をとったのか |
|水平展開・影響範囲確認 観点|水平展開を行った観点|

## プロセス改善の評価

プロセスの改善評価では以下の項目が使用できます。

| 項目                   | 説明                                                         |
| ---------------------- | ------------------------------------------------------------ |
|工程|発見工程|
|バグ種別|自責（新規）、自責（修正不十分）、自責（デグレ）、自責（潜在）、他責（別PJ）、その他（非バグ）|
|作りこみ工程|PJで計画した理想的な開発計画に沿って設計を行うことができなかった工程。どの工程に改善余地があるのかがわかります。|
|作りこみ原因|PJで計画した理想的な開発計画に沿って設計を行うことができなかった原因。開発プロセスで問題のある観点がわかります。|
| 本質的原因（作りこみ） | 不具合をなぜ作りこんだのか？を考えます。開発プロセスの設計工程の問題点を判断することができます |
|見落とし工程|PJで計画した理想的な開発計画に沿って検出を行うことができなかった工程。どの工程に改善余地があるのかがわかります。|
|見落とし原因|PJで計画した理想的な開発計画に沿って検出を行うことができなかった原因。開発プロセスで問題のある観点がわかります。|
| 本質的原因（見落とし） | どのレビュー・テストで見つけるべきだったのに見つけられなかったのかを考えます。開発プロセスのテスト工程の問題点を判断することができます |
| 不具合発生個所         | 機能・モジュール・　などを記載しておくと、品質が悪い機能やモジュールが浮き彫りになり、技術的負債がどこにあるかが判断しやすくなります |
|バグ混入バージョン|どのバージョンでバグが作り込まれたか。品質の悪い版が判明します。|

## 代表的な作りこみ原因

設計漏れ:インプット情報の確認不足
設計漏れ：インプット情報不良
設計漏れ:影響範囲確認不足
設計漏れ:流用元の確認不足
設計漏れ:検討不足
設計誤り:インプット情報の確認不足
設計誤り:インプット情報不良
設計誤り:影響範囲確認不足
設計誤り:検討不足
設計誤り:流用元の確認不足
ケアレスミス：単純な人為的ミス
作業ミス：PJルール違反
作業ミス：レビュー指摘事項反映漏れ
作業ミス：情報共有のミス
スキル不足
業務（ユーザー運用）の理解不足
前回開発時からの潜在不良
流用元からの潜在不良
該当なし

## 代表的な見落とし原因

項目漏れ（正常系・準正常）
項目漏れ（異常系）
項目漏れ（境界値）
項目漏れ（競合）
項目漏れ（連続・負荷）
項目漏れ（設定組み合わせ）
項目漏れ（リグレッション）
項目漏れ（その他観点）
項目誤り（判定結果）
項目誤り（実施手順）
試験実施誤り（結果判定）
試験実施誤り（実施手順）
レビュワーのスキル不足
レビュー未実施（全部）
レビュー未実施（一部）
レビュー観点不足
レビューメンバの不足
該当なし（本質的原因欄に記載）
見落としではない（本質的原因欄に理由）
Ubuntu 18.04.3 LTS でOpenVPNを使う方法

個人メモです。
UbuntuのGUI環境でOpenVPNを使用するときの手順です。

## openvpnをインストール

```bash
sudo apt install network-manager-openvpn-gnome
```

## *.ovpnファイルを指定して読み込む
ネットワーク設定を開き、VPNの`+`ボタンを押して、ファイルからインポートで自分のovpnファイルを選択する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66178/9ed4bc35-eac6-a33a-7838-bbd9d6bf17d3.png)

## ネットワークメニューからVPNを有効する
VPNのメニューが表示されるので、それを有効にする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66178/6ebf1149-f84c-0fbf-f56c-7940da8c2744.png)
Laravel 6.0 開始-1

6.0 LTSもうできたから、とりあえず使ってみましょう。
Laragonでプロジェクトを新規します。

### installer 更新
```
λ composer global upgrade "laravel/installer"
Changed current directory to C:/Users/tiefb/AppData/Roaming/Composer
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 0 installs, 1 update, 0 removals
  - Updating laravel/installer (v2.1.0 => v2.3.0): Downloading (100%)
Writing lock file
Generating autoload files
```

### create-project
```
λ composer create-project laravel/laravel Lemuria-6 --prefer-dist "6.0.*"
Installing laravel/laravel (v6.0.2)
  - Installing laravel/laravel (v6.0.2): Downloading (100%)
Created project in Lemuria-6
> @php -r "file_exists('.env') || copy('.env.example', '.env');"
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 86 installs, 0 updates, 0 removals
  - Installing symfony/polyfill-ctype (v1.13.1): Downloading (100%)
  - Installing phpoption/phpoption (1.7.2): Downloading (100%)
  - Installing vlucas/phpdotenv (v3.6.0): Downloading (100%)
  - Installing symfony/css-selector (v5.0.2): Downloading (100%)
  - Installing tijsverkoyen/css-to-inline-styles (2.2.2): Downloading (100%)
  - Installing symfony/polyfill-php72 (v1.13.1): Downloading (100%)
  - Installing symfony/polyfill-mbstring (v1.13.1): Downloading (100%)
...
Package manifest generated successfully.
> @php artisan key:generate --ansi
Application key set successfully.
```

新規完了！

ページを開いてみて～OK

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567121/db9c67d9-1576-317a-f86b-aebd187e3650.png)
HTMLImageElementインターフェースについてまとめ

###はじめに
JSを勉強している中で、**「HTMLImageElementインターフェース」**というモノを知り、最初は何を言っているのかさっぱりわからなかったところから少しづつ理解したこととまとめてみます。

###HTMLImageElementとは
>HTMLImageElement インターフェースは、<IMG> タグに相当します。
>エレメントの一種です。
>画像を読み込んで表示するための機能がまとまっています。

つまり、JS上で `<img>タグ` に相当するモノ(オブジェクト)を作成し、htmlに反映できるだと理解しました。

こちらのサイトがわかりやすかったので引用させていただきました。
>https://hakuhin.jp/js/image.html

###どんな感じに使うのか
####使い方：Image() コンストラクタを使用する
```js:コンストラクタを使用
// HTMLImageElement オブジェクトを作成する
var image = new Image();
```
簡単にボタンクリックで画像切り替え処理を作成しました。

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

###まとめ
簡単な処理を作成してみましたが、まだまだ理解仕切れてないことが多いなと痛感しました。
もっと画像をJSで扱う動作を勉強してもっと臨機応変なコードを描けるようにしたいと改めて思いました！
勉強をしていく上でもっと良い方法や内容があれば更新していきます。
自己紹介

#自己紹介
勉強しようと思ったらXcodeのアプデが必要で結構時間かかりそうだったのとカレー2杯食べて腹一杯なので今日は自己紹介をします。


##高校時代
高校までは四国のある県で過ごしてました。自転車であちこち行ってました。
割とうるさいやつでしたね。

##大学時代
大学は情報系でC言語を学習して実習でマイコンを動かしたりしてました。
研究は半導体の研究室だったのでプログラミングはほとんど使いませんでしたね。

##社会人
新卒で半導体の会社に入社しました。
配属が明るくてちゃんとコミュニケーションが取れるからと生産管理配属になり、業務を行っておりました。
しかし、土日の出勤や1年目から毎月40時間付近まで残業があったりで休日が欲しいなと思って2年目で転職しましたね。
今の会社も最初は生産管理で入社したんですが、1年後に物流課に配属が変わり現在となります。
今はフォークリフト乗って、製品の入出庫作業やピッキングしたりたまに物流のスキーム構築のプロジェクト参加したりとルーティンワーク多めです。

##きっかけ
今の部署で、資料作成の時に過去1年間のデータを他のエクセルから引っ張ってこなければならない時があり、その時に自動でしてくれたら楽なのにと思ったのがプログラミングをまた勉強しようと思った理由です。

##感想
pythonはC言語に比べるとまだ学びやすいような気がします。引き続き勉強していき1,2月で基礎を固めます。
【Unity】 角速度(ジャイロ)センサーの使い方

#注意
**スマホから取得する方法になります。PC本体のセンサー情報を取得にはこの方法だと無理です。**

#UnityリファレンスのURL
リファレンスを読めば分かる人はコチラ
- https://docs.unity3d.com/ja/2019.3/ScriptReference/Gyroscope-rotationRate.html
- https://docs.unity3d.com/ja/2019.3/ScriptReference/Gyroscope-rotationRateUnbiased.html

<br>
以降は私の記事から情報を得る人向けです(忘れやすい私でも分かるように書いています)

#1. 角速度の取得方法(Part1)
最初にジャイロセンサーを有効化します

``` C#
// Start is called before the first frame update
void Start()
{
  Input.gyro.enabled = true;
}
```
<br>
有効化後に角速度を取得します - 単位 : Rad/Sec
(念のためロール・ピッチ・ヨー方向が合っているかは実機で確認した方が良いです。)

``` C#
private void UpdateGyroData()
{
  double pitch = Input.gyro.rotationRate.x;
  double yaw = Input.gyro.rotationRate.y;
  double roll = Input.gyro.rotationRate.z;
}
```
**rotationRate**は角速度センサーから取得した生のデータです。
なぜ説明しているのかを理解したい方はPart2を読みましょう。

#2. 角速度の取得方法(Part2)
Part2では**rotationRateUnbiased**を説明します。
より正確な値を取得する人向けに使用が推奨されます。
rotationRateで取得すると自動車がドリフトしている時の値が正しくないケースがあります。
ドリフト時の様に誤差が生まれやすい環境で使用する場合に使用が推奨されています。
(ハードウエアがそれらを考慮した設計をされていればrotationRateで取得しても問題ありません)

<br>
最初にジャイロセンサーを有効化します

``` C#
// Start is called before the first frame update
void Start()
{
  Input.gyro.enabled = true;
}
```
<br>
有効化後に角速度を取得します - 単位 : rad/sec

``` C#
private void UpdateGyroData()
{
  double pitch = Input.gyro.rotationRateUnbiased.x;
  double yaw = Input.gyro.rotationRateUnbiased.y;
  double roll = Input.gyro.rotationRateUnbiased.z;
}
```

#3. Rad/Sec から Deg/Sec に変換する
ラジアンより度の方が一般的なので変換する事が多いと思います。
メモ程度で記載します。参考になる資料は[参考]欄に記載しておきます。

``` C#
private void UpdateGyroData()
{
  double pitch = (Input.gyro.rotationRate.x * 180) / Mathf.PI;
  double yaw = (Input.gyro.rotationRate.y * 180) / Mathf.PI;
  double roll = (Input.gyro.rotationRate.z * 180) / Mathf.PI;
}
```
<br>
Unityの関数を使用して変換する事も出来ます。
今回はdouble型ですがfloat型の時に使用するといいと思います。

``` C#
private void UpdateGyroData()
{
  double pitch = Input.gyro.rotationRate.x * Mathf.Rad2Deg;
  double yaw = Input.gyro.rotationRate.y * Mathf.Rad2Deg;
  double roll = Input.gyro.rotationRate.z * Mathf.Rad2Deg;
}
```
#<br>
もっといい方法(アドバイス)や感想があったらコメントしてください。
おいしいと思うお店の情報もお待ちしております。

[参考] 
Unity専用関数を使用: https://docs.unity3d.com/ja/current/ScriptReference/Mathf.Rad2Deg.html
ラジアンと度の概念 : https://juken-mikata.net/how-to/mathematics/radian.html
Rails エラーメッセージの表示と日本語化

## エラーメッセージの表示
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520383/94cf4e9e-6676-5e5e-2728-0e12fda15a79.png)

上記の画像のようにタイトルとブログ本文が空だった場合はエラー表示される様に実装する事。

## モデルにバリデーションを設定
バリデーションを付けたいモデル（今回はpost.rb）に記載。


```ruby:post.rb
class Post < ApplicationRecord
  validates :title, :content, presence: true
end
```

titleカラムとcontentカラムが空を防ぐ。

## エラーメッセージのファイルの作成
エラーメッセージはエラーが発生すると、_error_messages.html.erb内に格納される。

```ruby:layouts/_error_messages.html.erb
% if model.errors.any? %>
  <div class="alert alert-warning">
    <ul>
      <% model.errors.full_messages.each do |message| %>
        <li><%= message %></li> 
      <% end %>
    </ul>
  </div>
<% end %>
```
## フォーム（form_with）の中にrenderで挿入

```ruby:posts/new.html.erb
<%= form_with model: @post, class: :form, local: true do |form| %>
　#renderメソッドで_error_messages.html.erbを呼び出す。
  <%= render 'layouts/error_messages', model: form.object %> 
  <%= form.text_field :title, placeholder: :タイトル, class: :form__title %>
  <%= form.text_area :content, placeholder: :ブログ本文, class: :form__text %>
  <%= form.submit '投稿する', class: :form__btn %>
<% end %>
```

これで表示は完了。
次は日本語化実装へ。

## エラーメッセージの日本語化

```ruby:Gemfile
gem 'rails-i18n'
```
Gemfileに以下の一文を追加して、bundle install。

##  日本語化の基となるファイルを作成する
Railsの多言語化対応は、ymlファイルで管理。
config/locales ディレクトリ直下に、ja.ymlを作成。

```ruby:ターミナル
$ touch config/locales/ja.yml
```

## カラム名の日本語化
```ruby:config/locales/models/ja.yml
ja:
  activerecord:
    attributes:
      post:
        title: 名前
        content: ブログ本文
```

## ja.ymlの注意点
Railsはymlファイルの改行とインデントで日本語化のパスを参照している為、
attributes: => モデル名 => カラム名 の順に改行とインデントを入れる必要がある。


```ruby:config/locales/models/ja.yml
attributes:  　　　　　　　# attributes:の直下に
  post:  　　　　　　　　　 # モデル名を指定し
    title: 名前   　　　　　# カラム名を指定する。
　　 content:ブログ本文　　　　# カラム名を指定する。

```
[Flutter]高さが動的なリストのセルの内側に縦線を描画する方法

Google Mapの以下のようなルート検索結果画面をつくることを想定します。
![device-2020-01-14-200922.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202533/908d265a-a3b3-6fde-ebdc-7ddd22c2deba.png)
今回はその中で、ルート検索結果のリストのパーツを作ることにフォーカスします。
![device-2020-01-14-200922.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202533/0bb24446-4c3d-7929-1298-b5cbabfb368c.png)
これですね。

## Rowを組み合わせて実現しようとした場合（失敗）

素直に実装しようとすると、下記のようにRowで縦線部分と子要素を横に並べるようになると思います。
![Android.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202533/b8ef084e-d73f-6905-f540-4afac3568c28.png)
ここで、子要素は要素の内容によって高さは動的に変わります。（Androidでいう`wrap_content`）
そして縦線部分の高さは親の高さに合わせる（`match_parent`）ようにしたいのですが、この部分がどうしてもうまく実現できませんでした。
当初はContainerのheightを`double.infinity`にすればいけるかな？とも思っていたのですが、この場合Rowの高さが不定になってしまい、どうしてもうまく描画できませんでした。（親Widgetも高さが`double.infinity`扱いになっていそう）

他にもRowの`CrossAxisAlignment.stretch`を試してみたりしましたが、できませんでした。

…うまいやり方があったら教えてください…

## 解決方法

`Stack`と`Positioned`を組み合わせて実現しました。

```dart
Widget _buildLinedCell(Color color, Widget widget) {
  return Stack(
    children: <Widget>[
      Positioned(
        child: Container(
          color: color,
        ),
        left: 48, // 左から48の位置に幅8の線を描画。
        width: 8,
        top: 0,   // topとbottomは0を指定することで高さを親に合わせます
        bottom: 0,
      ),
      Padding(
        // 左端から十分なマージン(left: 72)をとってwidgetを配置
        padding: EdgeInsets.only(left: 72, top: 16, bottom: 16, right: 16),
        // widgetのサイズは動的に変わる
        child: widget,
      ),
    ],
  );
}
```

上記コードでの完成形はこのとおりです。
こうすると、右側のWidgetのサイズに合わせて縦線をうまく描画できるようになりました。

![device-2020-01-14-202536.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202533/858b7978-a575-6630-8838-49eb06c15f38.png)

サンプルコードも合わせてこちらにおいておきます。
https://github.com/shcahill/LinedCell
備忘録 - NIST 800-90Aで規定されている CTR-DRBG を読み解く（途中）

組み込み向け案件で、セキュリティ周りでCTR-DRBGを使う場面がでてきたので、調べがてらメモを残してみる。

# 想定読者

CTR-DRBGを使う場面に直面しているが、原文読むのがつらい人向け（要は自分という・・・）。

前提知識と心構えをざっくりと：

+ 情報工学の基礎知識がある（ビット演算とか）
+ 真性乱数と疑似乱数の違いが説明できる
+ AES(Advanced Encryption Standard)を知っている
+ セキュリティに対するアレルギーがない（Web系のセキュリティ知識は不要）

# この記事の使いかた
原文を読む際の手助けとしての利用を想定しています。（本記事だけでは情報が不足していますので原文を合わせて読んでください。）
※間違っていても責任はとれません。

参考文献を頭から読まずに、さらに斜め読みしているので色々抜けてるかもです。

間違いがありましたら指摘いただけると助かります！

# 参考文献（原文）

+ [NIST SP 800-38A (Recommendation for Block Cipher Modes of Operation Methods and Techniques)](https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf)<br>本記事では2001年版の内容に沿います。

+ [NIST SP 800-90A (Recommendation for Random Number Generation Using Deterministic Random Bit Generators)](https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-90a.pdf)<br>本記事ではJan-2012版の内容に沿います。

# 概要

CTR-DRBG - 要はカウンタ(CTR)とブロック暗号(AESなど)を使って疑似乱数を作るアルゴリズム。

# NIST文書中の略語

|略語|非省略形|説明|
|---|---|---|
|CTR|Counter|カウンターモード。ブロック暗号(AESなど)をどういう風に利用するかを示す分類と捉えておけば、とりあえず おｋ|
|DRGB|Deterministic Random Bit Generator|疑似乱数だと捉えておけば、とりあえず おｋ|

# NIST SP 800-38Aに記載されているCTRを読み解く

DRBGに入る前に、NIST SP 800-38Aに記載されている、ブロック暗号を使ったCTRの推奨例について調べた。
(NIST SP 800-90Aから同-38Aを参照しているため。)

なお、38AのほうはRecommendation(推奨)であり、仕様規定ではないようである。（違ってたらすみません。指摘ください。）

## CTRでの入力データの区切り方

NIST SP 800-38A 2001 Editionの5.2章Representation of the Plaintext and the Ciphertextを解釈した結果を記載する。

|記号|説明|
|---|----|
|<i>b</i>|Blockのbit長。AES128を使う場合は128|
|<i>n</i>|Blockの個数|
|<i>u</i>|最後のBlockのbit数。|

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438183/77ddb283-b45c-abd8-5d8d-83c009e9f0a7.png)


CTRモードではPadding(38AのAppendix Aに書いてある)は使わない。

## CTRのデータの流れ

NIST SP 800-38A 2001 Editionの6.5章The Counter Modeを解釈した結果を記載する。

<b>下図はAES128を使用した場合の例</b>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438183/147aadc9-f26b-d946-f45c-269f426bb3f4.png)


+ AES128のところは、使用するブロック暗号アルゴリズムにより異なる。
+ bit数も使用するアルゴリズムやパラメータにより異なる。
+ `+1`は例。

## カウンターの初期値(counter1)の選び方

NIST SP 800-38A 2001 EditionのB.2 Choosing Initial Counter Blocksを解釈した結果を記載する。

B.2章の冒頭の文章[^1]：
> 指定されたキーで暗号化される各メッセージの初期カウンターブロックT1は、すべてのメッセージにわたってすべてのカウンターブロックの一意性を保証する方法で選択する必要があります。このセクションでは、初期カウンターブロックを選択するアプローチの2つの例を示します。

### カウンターの初期値(counter1)の選び方のアプローチ(例として記載されている)

【1つ目のアプローチ】
単純なインクリメントカウンタっぽい。本文中の<i>m</i>はカウンタのbit長。

【2つ目のアプローチ】
ブロックサイズ(b bit)の半分(AES128なら64bit)のNonce(1回だけ生成する乱数)をインプットとして使う。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438183/3494e4cd-de7f-860c-c542-031ac8095cff.png)


# NIST SP 800-90Aに記載されているCTR-DRBGを読み解く

10.2.1章CTR_DRBG

疑似乱数を一定数生成したら、真性乱数を使用してReseed[^2]するステップを踏むようである。

読解中・・

10.2.1.5章Generating Pseudorandom Bits Using CTR_DRBG が本体

[^1]: Google翻訳した結果をそのまま記載した。内容は合っていそうだがよく分からん。。コーディングしてTest Vector流せばすっきり分かるような予感。

[^2]: 疑似乱数は決められた計算で生成するため、一般的に、初期状態を真性乱数で作り出す必要がある（乱数列を再現したい場合は固定値にしたりすることもある）。その初期状態をつくるデータをシードと呼ぶ（自分の理解はこれ）。定義はどこに書かれているかわからないですが、シードの意義は https://www.jpcert.or.jp/sc-rules/c-msc32-c.html などを参照してください。
AtCoderで緑になるまでにやったこと、必要な知識

## はじめに

タイトル通りですが緑になりました。これから目指す人の参考になればと思い、この記事を書きます。

<img width="685" alt="スクリーンショット 2020-01-14 20.17.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115524/efa980f8-8442-9310-f673-0f6c9f7950ee.png">
https://atcoder.jp/users/mokrai

## やったこと
### 1. 『プログラミングコンテスト攻略のためのアルゴリズムとデータ構造』(https://book.mynavi.jp/ec/products/detail/id=35408)

書籍です。緑になるために必要でない情報も含まれているので、最速で緑になるために必要かと言われたら微妙ですが、これまで学校等でアルゴリズムを学んだことが無い自分にとっては大変勉強になりました。体系的に学べたのが良かったです。

### 2. ひたすら過去問を解く
私の実績はこんな感じです。（緑になってから１週間後くらい）

<img width="1154" alt="スクリーンショット 2020-01-14 20.35.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115524/a4f4fc36-1992-22b3-97e5-799f635720d1.png">

まず、ABCのC問題を埋めていきました。[AtCoder Problems](https://kenkoooo.com/atcoder#/table/)で各問題のdifficultyを見て、簡単な問題から解いていきました。水色以上の問題は、適度な難易度では無いと判断して解いていません。

その後は、ARCのA問題を埋めました。こちらもdifficultyが緑のものまでです。

さらにその後は、ABCのD問題を解きました。こちらもdifficultyを見て、簡単な問題からです。10問くらい解いたところで、緑になりました。

最近では（2020年1月現在）、緑パフォを出すためにはABCのコンテストで3完（ABC）は必須で、4完（ABCD）が必要な場合もあります。
したがって、「C問題は確実に解ける。D問題も頑張れば解けるかも」くらいになっておく必要があります。

### 3. たくさんコンテストに出る
ratedのコンテストは、特別な予定がない限り出るようにしていました。
コンテストに慣れるため、集中して問題を解く時間を作るため、コンテストへの参加回数が少ないとレーティングにマイナスの補正がかかるためです。

コンテスト後は必ず解説動画を見て復習をしました。解けた問題は自分の実装が想定回答かと別解がないかを確認し、解けなかった問題は動画を見ながらACしました。
緑が見えてくるまではC問題まで、緑に近づいてからはD問題までについてです。

解説PDFにも目を通していましたが、こちらは動画よりも内容が難しかったので、参考程度に見ていました。（すべて理解できなくてもOK）

## やっていないこと
### 1. 蟻本
内容が難しそうで、緑になるためには不要そうだったのでやりませんでした。

### 2. AtCoder以外のコンテスト
AtCoderで十分な問題量があり、やっていません。


## 緑になる上で必要な知識、アルゴリズム
* 全探索
* bit全探索
* 二分探索
* 必要に応じて優先度付きキューが使える
* 簡単なDFSとBFS
* 簡単なDP
* 素数判定
* 素因数分解
* 累積和
* しゃくとり法
* GCD（最大公約数）とLCM（最小公倍数）が求められる

## 最後に
緑になるためには、センスやひらめきは（あまり）必要ないと思います。
基本的なアルゴリズムを身につけた上で、問題文を理解し、適切なアルゴリズムをバグなく実装することが重要です。

多くの良問（つまりAtCoderの過去問）に触れ、一つずつ知識を増やしていくのが近道だと思います。

以上です。
TypeError: argument of type xxxxxx is not iterableが出る場合

#1. 概要

Pythonコード実施時、try：の範囲でエラーが発生すれば、exceptに処理が移る。
下記のコードでは、エラーコードが"sqlite3.IntegrityError"であれば、except以下の
コードを実施する流れになっている。

```python:test.py(関係あるコードのみを掲載)

if __name__=='__main__':
    
    try:
       (略)

    except sqlite3.IntegrityError as ex:
               
        if "UNIQUE constraint failed: STOCK_INFO.STOCK_NUM" in ex:
            print("ERROR:{}".format(ex))
```

上記のコードを実施するとエラーが発生する。


```console
root@2a1627805ea9:/home/stock# python3 sqltest.py 13
7
UNIQUE constraint failed: STOCK_INFO.STOCK_NUM
Traceback (most recent call last):
  File "sqltest.py", line 103, in <module>
    cur.execute(insert_sql,STOCK_INFO)
sqlite3.IntegrityError: UNIQUE constraint failed: STOCK_INFO.STOCK_NUM

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "sqltest.py", line 127, in <module>
    if "UNIQUE constraint failed: STOCK_INFO.STOCK_NUM" in ex:
TypeError: argument of type 'IntegrityError' is not iterable
```

#2. 解決法

エラーの原因は[こちら](http://hakomiyo.hatenablog.com/entry/2017/10/16/164535)に分かりやすく書かれてあり、この情報に従い

ex → str(ex)を書き換えれば正常に動作するようになりました。

```python:test.py(修正後)
if __name__=='__main__':
    
    try:
       (略)

    except sqlite3.IntegrityError as str(ex):  # ex → str(ex)を書き換える。
               
        if "UNIQUE constraint failed: STOCK_INFO.STOCK_NUM" in ex:
            print("ERROR:{}".format(ex))
```
リスト内包表記

```py:1
t = (1, 2, 3, 4, 5)
l = []

for i in t:
    l.append(i)

print(l)
```

```:1の実行結果
[1, 2, 3, 4, 5]
```
これをリスト内包表記で書くと

```py:1をリスト内包表記で
t = (1, 2, 3, 4, 5)
l = [i for i in t]
print(l)
```

```:1をリスト内包表記での実行結果
[1, 2, 3, 4, 5]
```

3で割った余りが0の数字だけリストに入れる場合を考える。

```py:2
t = (1, 2, 3, 4, 5, 6)
l = []

for i in t:
    if i % 3 == 0:
        l.append(i)

print(l)
```

```:2の実行結果
[3, 6]
```
これをリスト内包表記で書くと

```py:2をリスト内包表記で
t = (1, 2, 3, 4, 5, 6)
l = [i for i in t if i % 3 == 0]
print(l)
```

```:2をリスト内包表記での実行結果
[3, 6]
```

二つのタプルがあり、
それらを操作した数をリストに入れる場合

```py:3
t = (1, 2, 3)
t2 = (4, 5, 6, 7, 8, 9)
l = []

for i in t:
    for j in t2:
        l.append(i * j)

print(l)
```

```:3の実行結果
[4, 5, 6, 7, 8, 9, 8, 10, 12, 14, 16, 18, 12, 15, 18, 21, 24, 27]
```

これをリスト内包表記で書くと

```py:3をリスト内包表記で
t = (1, 2, 3)
t2 = (4, 5, 6, 7, 8, 9)

l = [i * j for i in t for j in t2]
print(l)
```

```:3をリスト内包表記での実行結果
[4, 5, 6, 7, 8, 9, 8, 10, 12, 14, 16, 18, 12, 15, 18, 21, 24, 27]
```

リスト内包表記で書けるからといって、
forループを2つも3つも内包させたりして、
長くなるとコードが読みにくくなるので避けるべき。

上記の「2をリスト内包表記で」位までにする事が好ましい。
UnicodeEncodeError: 'ascii' codec can't encode characters in position 5-12: ordinal not in range(128)が出る場合

#1 問題点

Python3にて、データをcsvに書き込み実施時にエラーが発生する。


```python:test.py(関係あるコードのみを掲載)

def db_dump(c):
    sql_com='SELECT * FROM STOCK_INFO ORDER BY STOCK_NUM ASC'
    tmp=c.execute(sql_com)   
    with open(setting.CSV_DB_PATH,'w') as f:
        writer=csv.writer(f)
        writer.writerows(tmp)

```

上記のコードを使い、データをcsvファイルに書き込みを行う時にエラーが発生する。

```console:
root@2a1627805ea9:/home/stock# python3 sqltest.py 9
7
Traceback (most recent call last):
  File "sqltest.py", line 105, in <module>
    db_dump(cur)
  File "sqltest.py", line 56, in db_dump
    writer.writerows(tmp)
UnicodeEncodeError: 'ascii' codec can't encode characters in position 5-12: ordinal not in range(128)

```
デフォルトではasciiでエンコードされるが、扱っている文字列はasciiでは扱えないためエラーが発生しています。自分の環境では、扱っている文字はutf-8で扱えるようです。



#2 解決策

csvファイルをオープンするときに、encoding='utf-8'を記載することで、扱う文字コードをutf-8に指定できます。

with open(setting.CSV_DB_PATH,'w',encoding='utf-8') as f:

```python:test.py(修正版)

def db_dump(c):
    sql_com='SELECT * FROM STOCK_INFO ORDER BY STOCK_NUM ASC'
    tmp=c.execute(sql_com)   
    with open(setting.CSV_DB_PATH,'w',encoding='utf-8') as f:
        writer=csv.writer(f)
        writer.writerows(tmp)

```

上記を実施すると無事にcsvファイルにデータを書き込むことができました。
【超初心者向け】『メイドイン「俺」』から学ぶゲーム作り③アニメーション編

#はじめに
この記事は[『メイドイン「俺」』から学ぶゲーム作り②台本(スクリプト)の書き方編](https://qiita.com/khjcsm/items/d96132c4f9d3c15918f3 "『メイドイン「俺」』から学ぶゲーム作り②台本(スクリプト)の書き方編")
の続きです。
この記事は超初心者向けなのでアニメーションの作り方ではなく、**アニメーションの構造**について説明したいと思います。
#アニメーションについて

みなさんはパラパラ漫画を描いたことはありますか？
パラパラ漫画とは少し違った複数枚の絵を高速でめくることで実際動いてるように見せるものです。
![IMG_9854.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550954/2f6c3f12-c090-6fcc-067d-61584bae494e.png)


実はアニメーションとはその**パラパラ漫画**のようなものなのです。
実際には動いていないけど、複数枚のイラストを交互に見せることによって動いてるように見えています。

ではこれが実際どのような感じなのか、例を追って見ていきましょう。

##(例)風船が浮いているように見せたい時

まず風船の画像を用意します。
![IMG_9855.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550954/ea92f072-71c0-d7ea-249b-a51f2fea67ca.jpeg)

これだけだとただの風船ですよね。

####では少し位置の違った風船の画像二枚を用意します。
![IMG_9857.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550954/9f3f57d1-ca28-7cc0-f838-60941570cf18.jpeg)
![IMG_9856.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550954/22a2f738-4454-1cf8-0821-eb65e9f324e0.jpeg)

####この二枚を交互に表示すると、、

![IMG_9858.GIF](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550954/e5213b70-0af5-6830-b8e1-1c7e87be7a5a.gif)

こんな感じに！少しぎこちないですが画像の位置が変わっていないにも関わらずプカプカ浮いているように見えます。

このように、画像を重ねることで実際にその動きをしているように見せるのがアニメーションという機能です。
もしマリオに歩くアニメーションがなかったら、マリオがただ平行移動しているだけに見えます。

#動きを付け加えたい場合

例えばプカプカ浮いている風船に、割れるという動きを付け加えたいとします。
その場合、**プカプカ浮いている**アニメーションと、**風船が割れる**アニメーションの二つを用意しなければなりません。その場合

『もし風船に物が当たったら、プカプカのアニメーションから割れるアニメーションに移行する』という台本を書けば思い通りの動きになるかと思います。

マリオでも、『Aを押したらジャンプ』の動作になりますよね。この場合のアニメーションも
『Aを押したら、歩くアニメーションからジャンプのアニメーションに変更』という台本が実行されているわけですね！
![IMG_9863.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550954/cfc32a03-1d25-47ee-9218-af241941e23a.jpeg)

#終わりに
アニメーション編いかがでしたでしょうか？
次回は何を書こうか悩み中です、、

**『メイドイン「俺」』**についてのサイトは[こちら](https://www.nintendo.co.jp/ds/uorj/index.html "こちら")から。