OmniAICreator/Qiita-1.07M huggingface dataset:
【nodejs】No 'Access-Control-Allow-Origin' header is present on the requested resourceを優しく解説

お疲れ様です、ラスカルです。

私は仕事でバックエンドもフロントエンドも担当しているのですが、実装した両者をGraphqlを使って繋ごうとしたときに次のエラーに遭遇しました。

```
Access to XMLHttpRequest at 'http://localhost:4000/graphql' 
from origin 'http://localhost:3000' has been blocked by CORS policy: 
Response to preflight request doesn't pass access control check: 
No 'Access-Control-Allow-Origin' header is present on the requested resource.
```

ふむ、どうやらフロント側のリクエストに対して、バックエンドが何やら**CORS**なる規約に則って、
**「おい、リクエストはちゃんと決まりを守って投げてこい🤬」**
とお怒りの様子です🤔

##状況説明

###バックエンド
バックエンドはNode.jsのExpressを使って、TypeScriptで実装しました。
自社AWSに繋がっていて、画像やらデータやらをリクエストに応じて返すことができます。
リクエストはGraphQLで受け取るように実装していて、実際ローカル環境でもちゃんとレスポンスが期待通りに返ってくることも確認できていました。

このとき、ポートは4000、つまり**localhost:4000/graphqlがバックエンド側のURI**でした。

###フロントエンド
フロントエンドはReactとTypeScriptで実装していて、最初の読み込みの際にGraphQLを使って、バックエンドにリクエストを投げ、受け取ったレスポンスの内容を表示するという至ってシンプルな実装です。


このとき、ポートは3000、つまり**localhost:3000/がフロントエンド側のURI**でした。


## エラーの原因

エラーメッセージにも書いてありますが、要はCORSという決まり的にNGなリクエストの投げ方をしてしまったために、エラーになっているだけです。

CORSの詳細は一旦置いといて、簡単にまとめると**違うドメインからのリクエストは、ブラウザを介して受け付けられませんよ**という決まりです。

確かに

- フロントエンドはlocalhost:3000/
- バックエンドはlocalhost:4000/

と異なるドメインになっているため、CORSに引っかかってしまったんですね。

まぁ考えれば当たり前ですが、違うドメインからのアクセスができてしまう方がセキュリティ的にはよろしくないですよね。
ありがとう、CORS🙏


## 解決策

前置き長くなりましたね。
結論としては、**cors**なるnode_moduleをインストールすれば解決です。

```
npm install --save cors
```

さらにTypeScriptを使っている方は、

```
npm install --save-dev @types/cors
```

をインストールしておきましょう。


終わったら、バックエンドの実装に入ります。
実装といっても、`app.use(cors())`を追加するだけ。

```
const app = express()

++ app.use(cors())

app.use('/graphql', graphqlHTTP({
  schema: schema,
  rootValue: root,
  graphiql: true
}))


app.listen(4000, () => {
  console.log('Start Express GraphQL Server. Listen to localhost:4000/graphql')
});
```

以上でエラーは解決すると思います。

ただこちらの実装だと、どのドメインからでもアクセスできてしまうため、（ローカルホストだからあんま影響ないとは思うけど、後々のために）特定のドメインからだけリクエストを受け付けられるように実装します。

```
const app = express()

++ const corsOptions = {
     origin: 'http://localhost:3000',
     optionsSuccessStatus: 200 
   }

++ app.use(cors(corsOptions))

-- app.use(cors())

app.use('/graphql', graphqlHTTP({
  schema: schema,
  rootValue: root,
  graphiql: true
}))


app.listen(4000, () => {
  console.log('Start Express GraphQL Server. Listen to localhost:4000/graphql')
});
```

許可するドメインと成功次のステータスコードが設定されているcorsOptionsなる変数を作成。
それをcors()の引数で渡してあげればOKです👏

## おまけ：解決しなかった対処法

CORS関連でいろいろ調べていると、corsモジュールをわざわざインストールせずとも、

```
const app = express()

app.use('/graphql', graphqlHTTP({
  schema: schema,
  rootValue: root,
  graphiql: true
}))

app.use(function(req, res, next) {
  res.header('Access-Control-Allow-Origin', 'http://localhost:3000');
  res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
  res.header('Access-Control-Allow-Methods', 'POST, GET, PUT, DELETE, OPTIONS');
  res.header('Access-Control-Max-Age', '86400');
  next();
});

app.listen(4000, () => {
  console.log('Start Express GraphQL Server. Listen to localhost:4000/graphql')
});
```

のようにヘッダーの上書きを施せばOK的なのを散見したのですが、私の環境ではうまく行きませんでした。
もう少し調べて、わかり次第追記したいと思います🖖
Flash Advent Calendar 6日目 - クロージャのスコープ問題 -

今日はちょっと小休憩的な感じで書きたいと思います。

FlashのActionScriptをエミュレーションする中で
クロージャーのスコープ問題にぶつかりました。

JavaScriptの実装になれていればすんなり解決していたと思うのですが・・・

# ActionScriptサンプル

```ActionScript

import flash.display.MovieClip;
import flash.events.Event;

public class Main extends MovieClip
{
    public function Main ()
    {
        super();
        this.addEventListener(Event.ENTER_FRAME, this._onEnterFrame);
    }

    private function _onEnterFrame ()
    {
        trace(this);
    }
}

```

`_onEnterFrame`で出力される情報は

```ActionScript
[object Main]
```

つまり、スコープはクラスに向いています。

これが、JavaScriptだと

```JavaScript
new Main(); // <= [Window]が出力される
```

と、globalのwindowクラスに向いてしまいます。

当時、ここが全然理解できず結構苦戦しました。。。
[JavaScript - MDN - Mozilla](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Function/bind)を徘徊して`bind`を見つけました。

```
bind() メソッドは、呼び出された際に this キーワードに指定された値が設定される新しい関数を生成します。
この値は新しい関数が呼び出されたとき、一連の引数の前に置かれます。
```

ActionScriptをエミュレートするには、JavaScript側で`this._onEnterFrame`関数に対して`bind(this)`をコールしてスコープを確約させる必要があります。

```JavaScript
this.addEventListener(Event.ENTER_FRAME, this._onEnterFrame.bind(this));
```

解決してしまえば、それほど大きな問題ではないのですが
当時は結構苦戦しました。。。

また、この後、ActionScriptの`addEventListener`の仕様で
同一のスコープで、同一の関数は追加しない。っという仕様にぶつかったのですが
きっとJavaScriptだけで実装していれば関わらない仕様だと思うのでサラッと書きます。

ドキュメントにあるように`bind`関数をコールすると`新しい関数`が生成されます。


```JavaScript
const method = this._onEnterFrame.bind(this);
console.log(method === this._onEnterFrame); // false
```

既存の関数から新たにスコープが確約された関数が生成されます。
なので、元の関数と生成された関数は別物として扱われます。

こういった、ActionScriptとJavaScriptの挙動の違いを詰めていく調査と検証に大きな時間がかかってしまいました。

ただ、その副産物でJavaScript特有の仕様や機能など知る事もできたので
言語を理解するという点ではとても勉強になり
今でも仕事で役に立っているので結果オーライですw

明日は、WebWorkerに関して書こうと思います！
データ基盤はイベントソーシング+CQRSで設計するとキレイになりやすいかもしれない

[データ基盤 Advent Calendar 2020](https://qiita.com/advent-calendar/2020/datainfrastructure)の16日目です。

データ基盤のアーキテクチャを考えるときに、イベントソーシング＋コマンドクエリ責務分離パターン(CQRS)で整理して考えたら割とキレイに考えられる気がするので、その紹介をします。
このパターン自体は数年前からすでに言われていたので、知ってる人にとってはそれほど新しい概念ではないかもしれない。


## イベントソーシング
詳細はMSのドキュメントがわかりやすかったので、それを見てもらうと良いかな。（余談ですが、MSのクラウド設計パターンのページがよくまとまってるので、設計考えるときにおすすめです）
https://docs.microsoft.com/ja-jp/azure/architecture/patterns/event-sourcing

簡単に説明すると、データの現在の状態ではなく、データの変更を引き起こすイベントの方を記録しましょう、という設計パターンです。ドメイン駆動設計の考え方らしいです。

例えばカートのDBを設計する場合、普通のDB場合はこんな感じで、現在の状態を保持します。

| User ID | Cart Item ID |
| --- | --- |
| A | item1 |
| A | item2 |
| A | item4 |
| B | item5 |

これがイベントソーシングだと、次のようなイベントの状態を保存することになります。

| User ID | Event | Cart Item ID |
| --- | --- | --- |
| A | add | item1 |
| A | add | item2 |
| B | add | item5 |
| A | add | item3 |
| A | add | item4 |
| A | delete | item3 |

イベントを保存しておいて、活用するとき（例えばカート商品一覧画面を表示する時など）にイベントから現在の状態を再現して使うことになります。

容易に想像できる通り、データの書き込みについては更新操作と比較して軽い追記操作というアトミックな処理で完結します。その代わり、データの読み込み時に大量のデータを読み込んで現在の状態を再現するという重い処理が必要となります。実際にはイベントソーシング単体だとあまり実用的ではないため、次のコマンドクエリ責務分離パターンと組み合わせて使われることが多いようです。

## コマンドクエリ責務分離パターン（CQRS）
これもMSの説明がとても分かりやすかったです。
https://docs.microsoft.com/ja-jp/azure/architecture/patterns/cqrs

ここでいうコマンドというのは書き込みリクエスト、クエリというのは読み込みリクエストを指します。下記図のように、データの書き込みの仕組みと読み取りの仕組みを分離して作る設計パターンになります。

![コマンドクエリ責務分離パターン](https://docs.microsoft.com/ja-jp/azure/architecture/patterns/_images/command-and-query-responsibility-segregation-cqrs-separate-stores.png)
[CQRS パターン - Azure Architecture Center | Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/architecture/patterns/cqrs) より引用

DBのprimaryとreplicationの関係と考えればわかりやすいかなと思います。多くの場合、書き込みリクエストと読み取りリクエストはそのリクエスト頻度や読み出しデータ量などが大きく違います。そのため、これらを分離することで、柔軟でパフォーマンスの高いシステムが作れます。


## で、何が新しいの

これを見て大して新しい発想じゃないな、と思った人も多いかなと思います。実際、以下のようなものもこのイベントソーシング+CQRSパターンと言って良さそうです。全く新しい概念のデータ基盤設計というより、今までの設計を整理し直した、と見るのが良さそうです。

- DataWarehouseとDataMart
- DataLakeと分析結果
- [kappaアーキテクチャ](https://tech.plaid.co.jp/realtime_stream_system/)のLog-structured data flow

データ基盤の場合、大量のデータを集めるため書き込みがネックになり、対して読み取りは分析時まで多少時間的猶予があるため、まさにこのパターンの強みが当てはまります。また、ストリーム処理・バッチ処理どちらの場合も適用できる考え方なので、使いやすい概念かなと思います。

概念として整理されていることで、”DataLakeなのにappend-onlyじゃない"とか、"DataMartに直接書き込んでしまってる"みたいなアンチパターンにも気付きやすくなるかなと思いって、紹介してみました。
javascript 問題集　No.12数値検査（Number型の禁止）

コマンド引数の3桁の数字の中に０～９以外のものが含まれていたらfalseする問を解きました。

初めはコマンド引数をfor文で回して０～９ならture
間違えていたらfalseにしようと考えていました。
けどコードが長くなり不満。。。

そこで考えたのは、初めからtureと定義して、もし０～９でなければfalseという考え方。

このやり方なら、for文とif文一つずつで解くことができます。
【SQL アンチパターン3選】

「SQLアンチパターン」を読んで必読と言われた章だけまとめる。

SQLにはさまざまなアンチパターンがあるが、その中でも基本的な3つのアンチパターンを知っておくことで最低限のアンチパターンを避けることができると思うので、それぞれ説明していこうと思う。
* * *
**【ジェイウォーク】**
これは、各データ内をカンマで区切ったりして複数の値を挿入してはいけないということ。

```jsx
id | name | account_id |
 1 |  ken |  11,22,33  |
```

【なぜか？】
・カンマで区切るように設定した場合、区切る目的ではないカンマとの見分けがつかない
・データを取得、検索する際にクエリを作るのが難しくなる。
・カンマで区切られたデータは、それぞれの長さが影響し合うことによって長さの上限値が変化してしまう。

【解決策】
きちんと一対多のテーブル関係を構築する。
多対多なら、中間テーブルを挟むようにする。


* * *
**【キーレスエントリ】**
これは、親テーブルに依存する子テーブルがある場合、外部キー制約を使用するべきだというもの。

【発生する状況】
この外部キー制約を設定することは、データの更新や削除を行う際の柔軟性が落ち、不便に感じることがあり、そういった時に外部キー制約を設定することを嫌うことがある。

【なぜダメなのか？】
・コードを書く時に完璧な手順でのコーディングをしなければ、参照整合性の保証ができない｡ （参照先に必要なデータがあることが保証されているということ）完璧なコードなどない前提で設計しなければならない。

【解決策】
外部キー制約を設定する。面倒なデータの更新や削除を簡単にするために、カスケード更新機能を使う。
`ON UPDATE CASCADE` → 参照先を更新すると参照元も更新される
`ON DELETE RESTRICT` → 参照先のレコードを削除できないようにする。
これら宣言は外部キー上で行うため子テーブル側で設定することになる
* * *
・**EAV  (entity attribute value)**
これは、属性(attribute)と値(value)を自由にセットできるTableのこと。この設計はいろいろ問題があるので原則やらないようにする。

```jsx
id | 属性名 | 値 | 親テーブルid
1  |  name | ken | 1234
2  | status| new | 1234
3  |  plan |  2  | 1234
```

【発生する状況】
変化しない固定の属性があるが場合によって、いくつか違う属性をレコードごとにセットしないといけないとする。どうすれば各データごとに属性を変えてそれぞれに値をセットできるだろうかと考える。「そうか、属性と値をセットにして親TableのIDにひもづければいいのか」と思いつく。
結果上のようなTable構造が出来上がる

【なぜだめなのか】
・属性を指定して情報を取得するクエリが冗長化する。
・EAV設計ではどんな値でも保存するために文字列型を使うため、DB側でデータ型の保証ができずアプリケーションコードによって保証しなければいけなくなる。
・特定のカラムに参照整合性制約を付与できない。（すべてのカラムに付与される）
・取得したデータは複数のレコードになっているため、レコードとして扱うには再構築する必要がある。

【解決策】
シングルテーブル継承、具象テーブル継承、クラステーブル継承、半構造化データのどれかを使う。
・シングルテーブル継承
関連するデータを全て一つにまとめて使わないカラムはNullなどにする方法。ポイントはどのタイプを使っているのかを明確化するtypeなどのカラムを設定すること。

・具象テーブル継承
関連するデータをすべて分けて、全部に共通属性をもたせる方法。使わない属性を持たせなくていいというメリットが有る。

・クラステーブル継承
共通属性のみのテーブルを一つ作り、対多の関係で変化する属性ごとに子テーブルを分けて外部キー制約によって継承を模倣する方法。個人的にオブジェクト指向に近いため、イメージしやすいなと思いました。

・半構造化データ
シングルテーブル継承のように一つにまとめるが、XMLやJSONで属性名と値を共に格納するカラムを作る方法。非常に拡張性が高いが、データ取得後にこのカラムを分解する手間がかかる。

* * *
「SQLアンチパターン」では25個ものアンチパターンが掲載されているので興味がある方は読んでみることをおすすめします。
AtCoderのRobot armsの問題を絵に描いて理解してみる（PHP）

区間スケジューリングというジャンルの問題らしいです。公式の解説だけでは、悲しいかな、僕には理解できなかったので、絵に書いて理解してみました。

問題は[こちら](https://atcoder.jp/contests/keyence2020/tasks/keyence2020_b)です。

#入力例

```html:入力例
4
2 4
4 3
9 3
100 5
```
#絵
こうやって絵に描いてみると「なんだそんなことか、確かにそりゃそうだよね」って感じになりました。
![IMG_4331.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645077/6b4fcc0b-8d32-851f-38fb-50f337e6aac3.jpeg)
１番目の一番右端と２番目の一番左端を比べていって、２番目の左端が１番目の右端よりも数字が小さければ、その２番目を取り除いていけばいいだけですね。

#コード
コードにするとこんな感じ。

```php:PHP
<?php
    fscanf(STDIN, "%d", $n);
    for ($i = 0; $i < $n; $i++) {
        fscanf(STDIN, "%d %d", $x, $l);
        $ss[] = max(0, $x - $l);
        $ts[] = $x + $l;
    }
    array_multisort($ts, SORT_ASC, $ss);
    $t = 0;
    $count = 0;
    
    for ($i = 0; $i < $n; $i++) {
        if ($ss[$i] >= $x) {
            $count++;
            $t = $ts[$i];
        }
    }
    echo $count . "\n";
```

時間に余裕ができたら随時更新していきたいです。
コメントあれば、ぜひよろしくお願い申し上げます！
ThingSpeakでInternet of Test

ThingSpeakにアクセスしてモジュールの安定度のテストをしています。無料のアカウントでのアクセスは15秒以上の間隔が必要で30秒のインターバルでアクセスして試しています。

![kani.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/a6a628df-7910-0a89-ea46-54491601dc07.png)

![thing.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/bfc75102-af8c-4880-d616-81884db56d7e.png)

データを送信しているmrubyスクリプトは以下のようにしています。

https://github.com/yamori813/rtlbm-mruby/blob/master/samples/thingspeak.rb

MATLAB Visualizationで直近1000個のアクセス間隔を集計してます。

```MATLAB
readChannelID = 0;

readAPIKey = 'abc';

t1 = thingSpeakRead(readChannelID, 'ReadKey', readAPIKey, 'NumPoints',1000, 'OutputFormat','table');

[m,n] = size(t1);
for c = 1:m - 1
    d = seconds(t1.Timestamps(c+1) - t1.Timestamps(c));
    s(c) = d(1); 
end

ma = max(s)
for c = 1:ma
    v(c) = 0;
end

for c = 1:m - 1
    v(s(c)) = v(s(c)) + 1;
end

plot(v, 'LineStyle','--','LineWidth',2,'Color','green','Marker','s');
```

![matlab4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/27273529-507c-2236-35a7-1f67df3fb182.png)

一行追加してX軸の範囲を指定してみます。

```MATLAB
xlim([30 ma+1])
```

![matlab5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/b26978fe-36c9-91f5-5bd7-132ed3fbe063.png)

棒グラフにしてみます。

```MATLAB
bar(v);
xlim([30 ma+1])
```

![matlab6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/98aafb11-0663-6cdb-3956-1b4854f02364.png)

配列を行列に変換してaccumarray関数で集計しても同じグラフになりました。

```MATLAB
readChannelID = 0;

readAPIKey = 'abc';

t1 = thingSpeakRead(readChannelID, 'ReadKey', readAPIKey, 'NumPoints',1000, 'OutputFormat','table');

[m,n] = size(t1);
for c = 1:m - 1
    d = seconds(t1.Timestamps(c+1) - t1.Timestamps(c));
    s(c) = d(1); 
end

B = reshape(s,[m-1,1])
A = accumarray(B,1);

bar(A);
xlim([30 ma+1])
```

無料アカウントでの使用はCPU利用時間に制限があり、データ量が多い場合は、できるだけ関数で処理するほうが有利なのかと思われます。

MATLABあまり良く分かってないので、よいこはまねしないでくださいね。
docker-composeの後につくbash,ashの違い

仕事で利用している開発環境では、、、

`docker-compose exec -it <container> bash`

なんだけど、自分が個人開発で使っているものは、

`docker-compose exec -it <contaienr> ash`

でした。
bashで使っている環境のコマンドはashにするとエラーになるし、もう一方も同じ。

これってどんな違いがあるのかな？と思い調べてみました。

### TL;DR
dockerコンテナ内部でシェルを使う時の参照元の違い

#### 詳細

言わずもがなではありますが、シェルはOS(Linux)を操作するCUIのことです。
開発を行うにあたってはdockerコンテナに入ってから色々コマンドを打つわけですが、そのコマンドを打つために`bash`を参照しています。

`bash`の中には「`pwd`というコマンドが送られてきたら現在のパスを表示する」みたいなコマンドが登録されていて、シェルが実行できるワケですね。

ただ、同じLinuxでもディストリービューションによってシェルの置き場所が`bash`ではない場合があります。

それを確認できるのが下記のコマンド。

```shell
echo $SHELL
// /bin/bash or /bin/ash
```
`bash`でコンテナに入れるdockerコンテナ内で打った時は`/bin/bash`、
`ash`で入れる場合は`/bin/ash`になります。

いわゆる「パスを通す」みたいなコトを`docker-compose`でもやっています。

LinuxやDockerのキホンを知らなかったコトをさらけ出しただけのような気もしますが、スッキリしました！

#### 参考資料
下記記事が分かりやすく、とても助かりました!

[dockerでalpine linux ベースのcontainerに入って、shellを使いたいとき。](https://qiita.com/yutachaos/items/56dd7ea09d7e2b0d9173)

[【Docker-Compose】コンテナ起動から入るまでを丁寧に](https://qiita.com/tsuboyataiki/items/90dbe94553d3dea39b19)
Android Studioが起動しない(Macユーザー)

#発端
業務でFlutter×Firebaseを使っています。
1週間程度私用のMacでAndroid Studioを起動しておらず、久しぶりに簡単に練習用アプリでもと思いAndroid Studioを起動しよう・・・できませんでした。

#解決までの道
エラーが出るわけでもなく、ただただ起動できない。

https://medium.com/@oikawa/solved-doesnt-start-android-studio-on-macos-8564d4f79ff8

ググるとこの方の内容に当てはまるっぽい。
>3.Applications/Android Studio/Contents/MacOS/studio ファイルを直接を起動

これで確かにエラーメッセージがターミナル上に表示された。
Android Studioフォルダを消して再度入れ直したら起動できるようになった。

詳細
1.FinderでApplicationフォルダを表示
2.Android Studioをダブルクリックして[パッケージの内容を表示]を選択
3.Applications/Android Studio/Contents/MacOS/studio をダブルクリックで実行
※1~3まではターミナルで実行でも問題ないと思います。僕は実際にみていた方が安心できるので上記で行いました。
4./Users/{your_name}を起動している状態で右クリック-[表示オプションを表示]を選択
5.["ライブラリ"フォルダを表示]を選択
6./Users/{your_name}/Library/Preferences/Android Studio3.1が見つからない
7.Android Studioを検索
8./Users/{your_name}/Library/Application Support/　内にAndroid Studioがいたので削除
9.Applicationフォルダ内のAndroid Studioも削除
10.再度Android Studioをインストール

#結果
起動すると正常に起動できることを確認できました。
何が原因だったのかはあまり分かっていないです。
Jinja2 templateを用いて listから indexを取得する

# はじめに
Ansible templateモジュールでファイルを作成する際にインプットとなるリスト型の変数に対してインデックス番号がほしい時があります
変数を書き換えて辞書型にすることでも対応できますが、その変数を使っていた処理に影響を及ぼしてしまします

困っていた所、Jinja2テンプレートの機能を使うことで、変数はリスト型のまま変更せずにインデックス番号が取得することができました(Pythonのenumerate関数的なことができます)

ちょっと救われたのでこれを記載します


# 何をしたいのか
たとえば以下のようなlistがあったとします。

```yaml
---
vars:
  team_member:
    - Alph
    - Brittany
    - Charlie
```

このlist(team_member)を元に、以下のようなファイルを作成することを目指します.

```py
{ID: 1, Name: Alph}
{ID: 2, Name: Brittany}
{ID: 3, Name: Charlie}
```

# どうやったのか

以下のようなtemplateを作成します。
ポイントは、`loop.index`という変数です。これが読み込んだlist変数に対してindexを割り当ててくれます。

```jinja
{% for member in team_member %}
{ID: {{ loop.index }}, Name: {{ member }}}
{% endfor %}
```

上記のtemplateを以下のplaybookを用いてファイルを生成します.

```yaml
---
- name: Enumerate in jinja2 template
  hosts: localhost
  gather_facts: false
  vars:
    team_member:
      - Alph
      - Brittany
      - Charlie

  tasks:
    - name: Create
      template:
        src: ./templates/demo.jinja2
        dest: ./work/demo.txt
```

実行すると以下のように、期待していたファイルができあがりました.

```
❯❯❯ cat ./work/demo.txt
{ID: 1, Name: Alph}
{ID: 2, Name: Brittany}
{ID: 3, Name: Charlie}
```

# その他
他にも便利な`loop.xxx`変数があるので利用する機会がありそうです
https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html#extended-loop-variables
HerokuでSeleniumを使いたいとき発生するValueError解決法

#はじめに
　HerokuでSleniumを使おうとしたときに「ValueError: Could not get version for Chrome with this command: google-chrome --version || google-chrome-stable --version heroku」というエラーで苦しめられたので対処法をメモします。

#対処法
　「Settings」から、
![setting.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537831/e570fbe9-ad68-554a-9522-0bf847e7a830.jpeg)

　以下の2つをBuildpacksに追加する。
・ https://github.com/heroku/heroku-buildpack-google-chrome.git
・ https://github.com/heroku/heroku-buildpack-chromedriver.git

![git.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537831/23911d12-5b8a-8c6e-c9cd-b542c88e3f77.jpeg)

#おわりに
　かなり悩みましたが無事に解決できてホッとしました。

#参考URL
https://qiita.com/7vvXi/items/0ba4f18dfae35bff6979
AWS Lambdaをローカル環境に用意する(AWS-SAMのインストール)

# 前書き
lambdaを実装する必要があり、ローカルでプログラムのテストができないか調べてたところ、AWS SAMを用いて検証するようなので設定方法を書いていきます。


###前提条件
Dockerが必要です。
+今回lambdaでgo言語を試すのでgoのインストールも必要です。

###検証環境
>OS:Windows 10 Pro 64bit ver 1909
>Docker version 19.03.12
>言語環境：go version go1.14.1
 
#SAMで構築する検証環境について
AWS-SAMをインストールすることで下記のような環境をローカルに作成できます。

![SAM.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436464/7759e3a7-7ba9-a623-6c4b-39d852144687.jpeg)

ローカルに仮想のAPI GaweWayを作りそこからLambda関数を実行する形です。
実行時にjsonを渡すことでevent発火時の動作も検証できます。

lambda関数の実行時にdockerコンテナが起動し関数が実行されます。そのため、dockerのインストールが必要になります。


### SAMのインストール
[AWS SAM CLI のインストール](https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html)
上記リンクからAWS-SAM CLIをダウンロードしインストールします。

### SAMをAPI GwateWay経由での実行する
[チュートリアル](https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/serverless-getting-started-hello-world.html)
公式のチュートリアルを参考にHello-wouldを実行します。
#####1.テンプレートからアプリケーションの作成
```
Which template source would you like to use?
        1 - AWS Quick Start Templates
        2 - Custom Template Location
Choice: 1
What package type would you like to use?
        1 - Zip (artifact is a zip uploaded to S3)
        2 - Image (artifact is an image uploaded to an ECR image repository)
Package type: 1
Which runtime would you like to use?
        4 - go1.x
Runtime: 4
Project name [sam-app]: Hello-Would
AWS quick start application templates:
        1 - Hello World Example
        2 - Step Functions Sample App (Stock Trader)
Template selection: 1
```

#####2.アプリケーションのビルド
```
cd .\Hello-Would\
sam build       //アプリケーションのビルド
```

#####3.アプリケーションの実行
まずローカル上のAPI Gatewayを起動しAPI叩くことでlamdaが実行されます。

```
sam local start-api   //Gatewayの起動
> C:\Windows\System32\curl.exe http://127.0.0.1:3000/hello
Hello, (IPアドレス)
```

##### (参考)Windows 10上でcurlの実行
windows10 ver 1803以降は標準のcurlツールがあるのでそちらを使ってテストします。

```
ディレクトリ
C:\Windows\System32
C:\Windows\System32\curl.exe http://127.0.0.1:3000/hello
```

上記で実行ができました。
lambdaが呼び出されたときにdocker imageが起動するので初回や環境によって時間がかかります。
GawteWayを起動せず直接実行する際は、プロジェクトフォルダで

```
sam local invoke
```

で実行できます。

## 感想
AWS-CLIもインストールすることで、作成した関数をデプロイできます。
実行時にはまったところとして、ローカルの別のコンテナに接続する際はdocker networkを指定する必要だったり、(コンテナ上のDBにアクセスする場合)
event時の環境変数をjsonで設定できます。
そちらも別記事にしようと思います。

lambda関数を作成するうえでローカルに実行環境があるほうが便利ですが、意外と記事がなかったので作成しました。

誰かの役に立てば幸いです。
ありがとうございました。
OpenCVplusUnity 画像フリップ処理について

#はじめに
この記事ではOpenCVplusUnity(無料)を使用しています。
Unityで画像を保存する際にフリップ処理したいなんて時があると思います。RendereTextreでこねくり回したり、ピクセル取り出して処理することもできるかと思いますが面倒です。大人しくそんな時はOpenCVを使いましょう。楽です。


今回はこの結果を目指します。Texture2DをX軸,Y軸,XY軸に対してフリップ処理します。
![スクリーンショット 2020-12-06 13.20.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508103/26b366b2-3755-13f8-b1f0-9b278458ec29.png)
といっても、することはPythonで使用する時と変わりません。
Texture2DをMatへ変換してFlip変換して再びTexture2Dへ返しているだけです。






#実装方法

```OpenCVManager.cs
using UnityEngine;
using OpenCvSharp;

public class OpenCVManager
{
　　 /// <summary>
    /// Texture2Dをフリップ回転処理
    /// </summary>
    public static Texture2D FlipToTex2D(Texture2D tex, int flipNum)
    {
        Mat origin = OpenCvSharp.Unity.TextureToMat(tex);
        if (flipNum == -1)
        {
            Cv2.Flip(origin, origin, FlipMode.XY);
        }
        else if (flipNum == 0)
        {
            Cv2.Flip(origin, origin, FlipMode.X);
        }
        else if (flipNum == 1)
        {
            Cv2.Flip(origin, origin, FlipMode.Y);
        }
        return OpenCvSharp.Unity.MatToTexture(origin);
    }
}

```

#まとめ
余談ですが、iOSアーカイブの予定のある方は最初からOpenCVforUnityを購入をお勧めします。bitcodeエラーから抜けれず、ビルドできてipaはできているのにアーカイブできない理由が分からず調べ続ける羽目になり、最終的に全移行することになります。

もちろんOpenCVをネイティブプラグインで全て自分で繋込めれば問題ないですが労力が見合ってません。外部ライブラリを使用した際は、アーカイブまで確認しろと教えられた良い教訓でした。


#エラー内容について
OpenCVPlusUnityではアーキテクチャarm64が含まれていないエラーでアーカイブができません。
iPhone5s以降はarm64なので必須です。
![スクリーンショット 2020-12-13 12.59.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508103/4f265fe5-d1d1-b0d2-65d2-d8c69427e752.png)


staticライブラリのビルド時の簡易な設定なので対応待ち？ということは考えにくいので無償版はここまでという認識です。


Appleのアーキテクチャ、bitcodeについてわかりやすくまとめてくださっている記事【@taki4227様】
https://qiita.com/taki4227/items/db9b503e56ab25a8a375
uglifyjsが圧縮時に格納するフォルダがないとエラーを吐く問題を追求してみた

# この記事の対象者

JSファイルを圧縮して、特定のフォルダに生成したいと思っている方


## 公式ではIssueが上がっていた

https://github.com/mishoo/UglifyJS/issues/1278

要約すると、uglifyjsはたくさんのタスクを処理しているからフォルダ生成はuglifyjsでは行うべきではないとのことでIssueがCloseされている。

## プルリク通りに圧縮前にフォルダを用意することにしてみた

```
"minify:js": "mkdir -p 'dist/js' && uglifyjs 'src/js/index.js' -c --output 'dist/js/index.min.js'"
```

## Brosersyncと組み合わせてみる

```
"minify:js": "mkdir -p dist/js && uglifyjs 'src/js/index.js' -c --output 'dist/js/index.min.js'",
"build:js": "yarn minify:js",
"watch:js": "onchange 'src/js/**/*.js' -- yarn build:js",
"server": "browser-sync start --server 'dist' --files 'dist'",
"dev": "yarn watch:js & yarn server"
```

## 最後に

Webpackを使う程でもない！！！
だけどJSファイルを修正したら特定のフォルダに圧縮した状態で生成したい時には使えると思いました。
ラビットチャレンジ - 深層学習 Day3 Section7 Attention Mechanism

# 0．概要
本記事は日本ディープラーニング協会認定の講座プログラムである「ラビット・チャレンジ」が提供している科目の1つである深層学習のレポートである。
記事タイトルに記載のとおり、Day3 Section7 Attention Mechanismについて以下にまとめる。

# 1．Attention
Seq2Seqは文章の単語数に関わらず常に固定次元ベクトルで入力しなければならないため、長い文章への対応が難しい。
デコーダの入力はエンコーダの最後の状態を入力とするため最初の方の情報がうまく埋め込まれない。

入力と出力のどの単語が関連しているか関連度を学習する仕組み。
関連度を学習することで関連度が高い部分を抽出して効率的に処理が行える。

入力
> 私 は ペン を 持って いる

出力
> I have a pen

上記のような翻訳の入力と出力があった場合、「私」と「I」、「ペン」と「pen」、「持って」と「have」の関連度が高いと言える。

Query(検索文)、Key(辞書のインデックス)、Value(辞書の本文)で構成され、Queryと近いKeyを探してValueを得るというイメージ。

参考：
https://qiita.com/ta2bonn/items/c645ecbcf9dabd0c4778#attentionsource-target-attention
https://ksksksks2.hatenadiary.jp/entry/20160430/1462028071

下記はE資格問題集にあったため超ざっくりした概要のみ記載したが十分な理解には遠い…

## 1.1．Soft Attention
ソフトマックス関数等で確率分布を得て重み付き平均を得る手法。

参考：https://qiita.com/ymym3412/items/c84e6254de89c9952c55#attentionメカニズム-2014

## 1.2．Hard Attention
Soft Attentionのように重み付け平均せず、重みが最大となるValueを取り出したり、重み行列を確率分布とみなして抽出する手法。

参考：http://yagami12.hatenablog.com/entry/2017/12/30/175113

# 2．確認テスト

## 2.1．確認テスト1
RNNとWord2vec、Seq2Seq、Seq2Seq+Attentionの違いを簡潔に述べよ。

回答：
RNNとWord2vec：
RNNはボキャブラリー×ボキャブラリー数だけの重みが必要だが、Word2vecはボキャブラリー数×単語ベクトルの次元数だけの重みのが必要。

Seq2SeqとSeq2Seq+Attention：
Seq2Seqは長い文章に対して対応が難しいが、Attentionを取り入れることで入力と出力の関連度に基づくため長い文章にも対応できる。

# 3．演習チャレンジ

## 3.1．トラバース

```Python:
def traverse(node):
  # node:再帰的な辞書{left: node, right: node} rootが最も外側の辞書
  # W:グローバル変数として定義されている重み
  # bグローバル変数として定義されているバイアス
  if not isinstance(node, dict):
    v = node
  else
    left = traverse(node['left'])
    right = traverse(node['right'])
    v = _activation(W.dot(np.concatenate([left, right])))

  return v
```

left, rightの隣接単語から内積を取って特徴量とする。

※トラバースはこういった木構造のような枝分かれの構造を全てもれなくたどっていくこと。

# X．ラビットチャレンジとは
ラビットチャレンジとは、日本ディープラーニング協会認定の講座プログラムの1つ。
E資格を受験するためにはこのラビットチャレンジ等、いずれかの講座プログラムを修了しなければならない。

ラビットチャレンジの特徴は「現場で潰しが効くディープラーニング講座」の通学講座録画ビデオを編集した教材を使用した自習スタイルであるという点。
サポートは他の講座より少なく、受け身ではなく自主的に学んでいく姿勢でなければ進められないが、その分、他の講座に比べると安価であり、手が出しやすい。
ある程度知識がある人、自力で頑張るぞというガッツのある人向けではないかと感じる。

![bnr_jdla.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/389699/bce66671-a2f5-a7f9-de6f-3f87e15c253b.png)
ODYSSEY X86のATSAMD21

最近、Intel Celeronを搭載したシングルボードコンピュータ（SBC）、ODYSSEY X86が日本販売店で見かけるようになりましたね。

<img width="600" alt="7564decc-25f1-eea7-55f0-22693e3943a8.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/7564decc-25f1-eea7-55f0-22693e3943a8.png">

現在、3ラインナップのボードが販売されています。

1.  SKU#102110479 ... 8GB RAMモデル(X86J4105800)
2.  SKU#102110477 ... 8GB RAM + 64GB eMMCモデル(X86J4105864)
3.  SKU#102110478 ... 8GB RAM + 64GB eMMCモデル(X86J4105864) + Win10Enterpriseライセンス

あと、8GB RAMモデル(X86J4105800)に外付け128GB SSDとケースをセットにした、SKU#110991465も販売されています。SSDは外付けとは書いてありますが、ケースに内蔵です。

<img width="600" alt="d56bb4e3-7ba2-ece0-98f7-00acbe6c81ad.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/d56bb4e3-7ba2-ece0-98f7-00acbe6c81ad.png">

ちょっと気づきにくいのですが、このODDYSEY X86にはATSAMD21も載っていて、Windows/Linuxとは独立して動かすことができるので、単純なI/O処理を正確に制御することが可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/260b2c45-3f33-886c-d1fd-4552d1200e2a.png)

このATSAMD21が、どのように使うことができるか調べました。

# Intel CeleronとATSAMD21のピンアウト

Seeed Wikiの[Pinout Diagram](https://wiki.seeedstudio.com/ODYSSEY-X86J4105/#pinout-diagram)を見ると、、、
40PinがIntel Celeron、28ピンがATSAMD21に繋がっているようです。
（細かいことを言えば、ATSAMD21は、さらにUART用？の4ピンと、SWD用の5ピンがある。）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/9922ea78-8425-fbc6-c3c9-319c74ed4dcf.png)

Intel CeleronとATSAMD21がどのように繋がっているかは謎。

# Intel CeleronとATSAMD21の接続

Seeed Wikiをじっくり見ると、[Arduino IDEのところ](https://wiki.seeedstudio.com/ODYSSEY-X86J4105/#using-the-arduino-core-atsamd21g18-in-linux-os)にヒントがありました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/18eb135a-8809-a4dc-29f5-f4df1c846413.png)


どうやら、Intel Celeronからは/dev/ttyACM0で繋がっているようです。

# /dev/ttyACM0

/dev/ttyACM0はキャラクタデバイス。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/4810a54b-b40f-1958-0b35-0e6545c455e8.png)

このデバイスは、USBバスにぶら下がっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/8cb483e0-f38a-ae4c-d77f-9ac7b74ef288.png)

使っているドライバはcdc_acmでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/df5fb4e1-e6a1-8767-854d-bbb81b6811a2.png)

# Seeeduino Zero

さらに、[Arduino IDEのところ](https://wiki.seeedstudio.com/ODYSSEY-X86J4105/#using-the-arduino-core-atsamd21g18-in-linux-os)に書いてある`Seeeduino Zero`をググってみたところ、こんな製品が出てきました。

[Seeed Wiki - Seeeduino Cortex M0](https://wiki.seeedstudio.com/Seeeduino-Cortex-M0/)
ArduinoフォームのATSAMD21ボード。
製品名は**Seeeduino Cortex-M0+**で、[SKU#102010248](https://www.seeedstudio.com/Seeeduino-Cortex-M0-p-4070.html)。
<img width="600" alt="b4333361-392a-f5f4-9e95-b105957951b4.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/b4333361-392a-f5f4-9e95-b105957951b4.png">


# Intel CeleronとATSAMD21の接続（改定）

こんな感じですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/dc147f97-3d78-47ba-a793-b457b2d55071.png)

4ピンのUARTは想像なので、、、後日、確認してみようと思う。
【待ってました】ラーメンにコショウをかけるためのアプリを作りました！

# よっ！待ってました

皆さんおまたせしました。ようやくラーメンにコショウをかけるアプリが誕生しました。

構想から18年、様々な難関を乗り越え、スマートフォンでコショウをかけることができるようになりました。本日はそんな画期的な新製品についてご紹介したいと思います。

# コショウのデジタルトランスフォーメーション(KDX)

弊社の製品は、これまでのすべての概念を覆します。

これまでラーメンにコショウをかけるためには、すべてのラーメン屋に設置されている青と銀のあれを使うしかありませんでした。しかと青と銀のあれを使ってコショウをかけることには様々な壁が存在します。
![スライド1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135663/91f77b7a-9457-2e7f-8275-a95826379a8f.png)


それらをすべて、弊社のアプリが解決します！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135663/ce6ba338-e925-6990-21d6-d8b5d151e3ba.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135663/baab6318-47c1-e22b-161a-3a4c29d75089.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135663/b6fa2b4d-ad0a-2e23-7c6a-32941de8d8b1.png)


# その名も「コショウかけすぎぃ！」

ラーメンにコショウを振りかけるアプリ、その名も「コショウかけすぎぃ！」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135663/fdcde079-784b-b7c4-483c-86616a47c73a.png)


## アプリでできること！

スマホ画面上のコショウをスワイプしまくり、10秒以内に何回コショウをかけることができるかを競うゲームです

その際、使うものはなんとスマホだけ。ラーメンもコショウも要りません！もちろん自宅でできます。

## プレイ画面

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">コショウをラーメンに振りかけるアプリを作りました <a href="https://t.co/EQTI835pv1">pic.twitter.com/EQTI835pv1</a></p>&mdash; fujitako (@fujitako03) <a href="https://twitter.com/fujitako03/status/1335453981494013952?ref_src=twsrc%5Etfw">December 6, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## 全国対戦

全国ランキング機能も充実、全国のコショウカケニストたちと競い合え！
<img width="200px" alt="ランキング" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135663/d48dd5f9-390b-6b51-bbfa-564c4c40b983.jpeg">

## 筋力アップ効果の声も！

既存のスマホアプリと比較し、瞬間スワイプ量は30倍～300倍！（独自調査）
つまり、これまでのスマホアプリでは成し遂げなかった筋肉増大効果も望めることでしょう。
![スライド2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135663/e2c1ee0b-2486-e816-ffb3-0fe7286d32a5.png)


# みんなもダウンロードしよう！

※なお、内容がショボいという理由でAppleから申請を却下されているため、ダウンロードすることはできません
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135663/78913633-f334-e3e4-da85-de86db7fbc06.png)
【NeosVR】3Dモデルを2点間の中点に移動させる

この記事は[「NeosVR reso Advent Calendar 2020」](https://qiita.com/advent-calendar/2020/neosvr_reso)の6日目です。

5日目は、@kmizuno0211 さんの[5GとNeosVRがもたらす未来の音楽の希望「Revolution No.10」](https://note.com/kmizuno0211/n/n3edd5e70798f)でした！

---

# はじめに

任意の3Dモデルを動的に生成するという目的でモデルの座標を弄っていましたが、いまいちよくわからんので初歩的なところから
始めました。お手柔らかにお願いします。

作るものは２つの3Dモデルの中間点に3Dモデルを移動させるLogixプログラムです。

# 必要知識

- [LogiXTip](https://neosvrjp.memo.wiki/d/LogixTip)
- [DevToolTip](https://neosvrjp.memo.wiki/d/DevToolTip)

# 準備

下記ノードを出しておきます。

- 「Operator」
  - 「+」１つ
  - 「÷」１つ

「3Dモデル」-「スフィア」を3つ用意します。

# 作成手順

1. 始点、終点、中点となる「スフィア」を決めて、各々「インターフェースノード」を出しておきます。
2. 始点、終点の「インターフェースノード」 - 「Postion」から「＋」ノードに繋げておきます。
    - LogiXの演算子は入力のデータ型に合わせて振舞が変わるようです。便利。
3. 「+」ノードの出力を「÷」につなげます。
4. 「÷」ノードのもう片方には「2」を入力します
5. 中点にしたい「スフィア」の「インターフェースノード」を出します。
5. 「÷」ノードの出力を中点スフィアの「インターフェースノード」の「Postion」につなげます

# 完成物

絵で見せれるので画像を張っておきます。
![20201205212141_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259874/cc9f628b-d537-d6d6-cb5f-02cdb082ca7f.jpeg)

## LogiXパック

LogiX込みで保存する場合は空オブジェクトに全部突っ込んでからパックしましょう。
一部だけを子オブジェクトにすると、グローバル座標とローカル座標が混ざって計算がおかしくなるので気をつけましょう。

![20201205220236_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259874/930d70ac-0991-0109-c795-d2c9ab8b576e.jpeg)

---

[「NeosVR reso Advent Calendar 2020」](https://qiita.com/advent-calendar/2020/neosvr_reso)の7日目は、@mikan3134さんです。
お楽しみに！
エンジニアの道を選んで1年4ヶ月たった話

# 初めに
初めまして来年からAndroidエンジニアとして働く予定のmessiです。
Twitter ->　https://twitter.com/175Atsu175
趣味でカメラやってるのでそのアカウントも是非
Twitter ->　https://twitter.com/messi0601


今回は自分がAndroidと出会ってエンジニアで働こうと決めてから1年4ヶ月たった今を振り返ってみたいと思います。
去年の夏まではAndroidなんてやったことないし、大学は経営学部なのでエンジニアとは疎遠です。（Pythonちょっと触ったぐらい）
エンジニアとしてもチュートリアルの本ぐらいしか行ったことがなかった人がなぜか来年からAndroidエンジニアとして働くことになった経緯やエンジニアの道を選んで今までどんなことしてたかを書いていきます。



# 2019年8月[Androidとの出会い]（0ヶ月目）

Androidに初めて出会ったのは2019年の8月でした。出会ったきっかけは8月に参加したAndroidのインターンでした。
申し込んだきっかけとしては、元々iosのチュートリアル本みたいなものを１週やったことがあったのですが、Androidユーザーだったこともあり、手元に端末がなく、実機で試すことが出来ませんでした。
そんなこともありAndroidやりたいなと思い申し込みました。

夏のインターンでは平日の２週間でQRを生成してプロフィール交換するアプリを作りました。


# 2019年9月[決意]（1ヶ月目）
2週間のインターンの後、自分はAndroidエンジニアとして就活していくことを決意しました。
元々エンジニアになるか総合職にするかかなり悩んでいました。エンジニアとして進もうと思った理由として、自分の将来像が関係してきます。
自分は将来的にエンジニアやビジネス、デザイナーなどのパイプのような存在になりたいと思っています。そのため、社会人になった時に仕事と技術の勉強を同時するのがかなり負担になりそうだと思ったのと、しっかり現場のエンジニアとしてエンジニア目線というものをしっかり体感する必要があると思い、エンジニアの道を選びました。

インターン後、本やネットなどを参考に１ヶ月ほど独学で学習しました。
ただ、独学の限界、自分の勉強の方向性とかが不安になり実務インターンを探し始めました。

# 2019年10~2020年8月[インターン]（2~12ヶ月目）
運もよく、10月からベンチャー企業Aでの実務インターンを行い始めました。
コードを読むことに慣れてないところから始まり、初めは小さなバグ修正を主に行っていました。
小さなバグを直そうとした際に他の部分にも影響が出てしまったり、条件に合わない挙動が起きたりかなり手こずりました。
12月の１ヶ月は別の企業のインターンにいっており、1月からまたベンチャーA企業に戻ってきてた際に新規の機能を任されその機能を１から作ることを任されました。なんとか作り終え無事にリリース出来ました。

最終的に約10ヶ月間お世話になりました。
ここでついた力というのはエンジニアとしての精神という物を鍛えられた気がしてます。


# 2019年12月[インターン2&内定]（4ヶ月目）
ベンチャー企業Aを1ヶ月間おやすみをいただいて、2019年12月は１ヶ月間別の会社でインターンを行ってました。
ここでは、まだ当時リリースされていなかったアプリをに携わらせてもらいました。
主にアプリの画面のUI部分を作らせてもらいました。

そしてその企業からAndroidエンジニアとして内定をいただきました🎉🎉🎉

# 5月~6月[個人アプリリリース]（10ヶ月目）
今まで実務ベースのチーム開発が主な開発でした。そのため一人でアプリを０から作ってリリースしたことがもちろんなく、一つの夢みたいな思いがあったのでそれを行ってみようを思い取り組んでみました。
その結果作ったアプリは「SkyCode」というアプリです。
画像からColourCodeを取得して表示するアプリになってます。
リンク -> https://play.google.com/store/apps/details?id=com.messi.skycode&hl=ja

このアプリの制作からリリースまで約2~3週間で行えました。（短期集中じゃないと飽きそうだったのでw）
詳しい記事はこちらに書いてあるので是非読んでみてください。
https://qiita.com/175atsu/items/66dec0f80b97f2da70ae


# 2020年9月〜現在[基礎固め]（1年~1年4ヶ月目）
ベンチャー企業Aを辞めて内定先バイトを行い始めました。
ここで大きな壁にぶつかりました。
**コードを雰囲気で書いていたということです。**
コードの本当の意味合いなどをしっかり理解した上で書いていなかったことに気付き、基礎をもっと定着させないと今後きつくなるとメンターさんに言われ、１から勉強し直し始めました。


# まとめ
絶賛まだ、基礎固め中です。

### エンジニアの道を選んで1年4ヶ月たった今思うこと
**色々遠回りしていたのかも知れないと最近になって思います。**
ただ、毎回その状況における自分の最適な行動をしてたと自分は思うので、今は今出来ることに取り組んでいきます。


### エンジニアの道を選んだことについて
今かなり、きついなーって思うことが多々あるのですが、後悔は一切してないです。（ただ、なぜエンジニアとして採用されたかは永遠の謎です）

漫画の言葉になってしまうのですが自分がかなり好きな名言があるので紹介させてもらいます。
**「正しい判断を下す事、下そうとする事は大切だ。でも、決してそれだけが全てじゃない。
判断が正しいか間違っているかなんて、その時には誰も判らない。
だから大切なのは
"判断の後"。
"下した判断を正解にする努力(こと)"。」**
*引用：約束のネバーランド第109話*


エンジニアの道を選んだのは自分なのでひたすらに努力して頑張って自分の目標とする姿を目指していきます。

では良いお年を。
オレオレ証明書をクライアントにインストールし、ブラウザ上の警告を消す

# オレオレ証明書をクライアントにインストールし、ブラウザ上の警告を消す
※あくまでオレオレ証明書を使ってHTTPSを利用する場合の対策です。

**ブラウザ:** Google Chrome

オレオレ証明書を利用してHTTPS通信を可能にすることはできますが、信頼された機関から発行されたものではないのでブラウザ上で警告が出ます。そのため、オレオレ証明書をクライアントにインストールして警告を出さないようにします。

**目的:** オレオレ証明書を利用したHTTPS通信でもブラウザ上の警告を出さないようにする
**方法:** オレオレ証明書をクライアントにインストールする

証明書を正しくインストールしたにもかかわらず、以下のエラーが表示される場合があります。

**問題:** 証明書を登録したのにnet::err_cert_common_name_invalidのエラーがでる
**原因:** 新しいブラウザはCommon Name(CN)ではなくSubject Alternative Name(SAN)とアクセスするドメインの一致を判定する
**解決法:** 証明書にCNのほかにSANを設定する

今回はSANの追加をしてから証明書のインストール作業を行います。

## SANを追加する
SANはCSR（証明書署名要求）から証明書を作成する際に追加します。
適当なテキストファイルを作成します。

```san.txt
subjectAltName = IP:xxx.xxx.xxx.xxx, DNS:example.com
```
IPを登録したいときはIP:、ドメイン名を登録したいときはDNS:と記述します。
複数の場合はコンマで区切ります。

### SANを含む証明書の作成
証明書発行のコマンドの最後に-extfile [sanが記述されたファイル]を付与します。

```
openssl x509 - req days 365 -in [CSR] -signkey [秘密鍵] -out [出力する証明書名] -extfile san.txt
```
参考: [SAN(Subject Alternative Name) のオレオレ証明書](https://qiita.com/nis_nagaid_1984/items/b8f87d41ea108d47af61)

##　証明書のインストール
1. エラーが発生しているサイトにGoogle Chromeでアクセスする
2. 左上の警告マークをクリック
3. 「証明書（無効）」の項目をクリック
4. 「詳細」タブをクリック->「ファイルにコピー」をクリック
5. エクスポートウィザードが表示されるので、証明書の種類はデフォルトのまま、任意の場所に証明書を保存
6. 証明書を「信頼されたルート証明機関」にインポートするためにcertmgr.mscを起動
7. 「信頼されたルート証明機関」を選択し、右クリック->すべてのタスク->インポートを選択
8. 手順5で保存した証明書を選択し、「信頼されたルート証明機関」にインポートする
9. Chromeをすべて閉じ、再度対象のサイトにアクセスしてエラーが出ないことを確認する
golangci-lintを使いこなしたい。

## 初めに
この記事はWanoグループ Advent Calendar 2020 の6日目の記事になります。

## golangci-lintって？

https://github.com/golangci/golangci-lint

Go言語には非常に多くのコード解析ツールがあります。例えば gofmt や goimports, govet などはgolangを書いている人なら知ってる人も多いと思います。
golangci-lintはGo言語のコード解析ツールを一つに集約したようなすごいやつです。

コードレビューをする時にまずこれを実行すると、機械的にまず直しておいたほうが良さそうな部分がわかって治安がよくなるかもしれないということですね。
そして解析結果はXMLだったりで出力することが出来るのでそこからさらにプログラムで使うのも簡単です。

インストールの方法などは上記リンクに記述してあるのでカットさせていただきます。


## configファイルを晒してみる
golangci-lintではconfigファイルを用いて
* どの解析ツールを使うか
* 解析ツールの条件(変数の出現回数など)

などを設定することが出来ます。

自分が実際に使っているものを晒してみたいと思います(結構適当に設定してますが)。

```

run :
  issues-exit-code: 0

issues:
  max-issues-per-linter: 1000
  max-same-issues: 1000

output :
  format : checkstyle

linters:
  disable-all: true
  enable:
    - deadcode
    - errcheck
    - gosimple
    - govet
    - ineffassign
    - staticcheck
    - structcheck
    - typecheck
    - unused
    - varcheck
    - bodyclose
    - depguard
    - dogsled
    - gochecknoglobals
    - gochecknoinits
    # - goconst
    - gocritic
    - gofmt
    - goimports
    # - golint
    - gosec
    - interfacer
    - misspell
    - nakedret
    - prealloc
    - scopelint
    # - stylecheck
    - unconvert
    - unparam
    # - whitespace
    # - wsl

linters-settings:
  errcheck:
    ignore: '[rR]ead|[w|W]rite|[c|C]lose|[c|C]ommit|[r|R]ollback|[p|P]rintln'

  goconst:
    min-len : 5

  golint:
    min-confidence : 1.0

```
使い方としては

1. まずgolangci-lint自体の設定を記述。
2. 使うlinterを選ぶ。
3. 各linterの設定を追加。

configファイルを呼んで解析する場合は

```
golangci-lint run -c .golang_review_config.yml <適当なpath>
```

とすれば良い感じに。なんでもかんでもぶち込むと「厳しすぎない？」となるので使うlinter類は各プロジェクトや開発者で選ぶと良いと思います。ちなみにymlファイルなのでコメントアウトも出来ます。


## おすすめ

個人的に入れとくと良いやつを紹介してみます。
各linterの細かいconfigはカットです。

### govet
これに関しては言うこともない気がします...が。
簡単に言うと「バグる可能性が高い部分を検知してくれる」やつです。なのでgovetでエラーが出る場合は「アウト」の認識だと良いと思います。例えばですが

```go
type A struct {
	Num  int
	Text string
}

a := A{
    1,
    "aaa",
}
```

では「構造体を使う時に変数だけしか書いてない」ということで怒られます。

```go
type A struct {
	Num  int
	Text string
}

a:=A{
    Num : 1,
    Text : "aaa",
}
```

こうしろということですね。

### errcheck
個人的にgovetと並ぶと思っている強いやつです。エラーハンドリングし忘れたやつを教えてくれるので、これに引っかかる場合もアウトにして良いかもしれません(ただしデフォルトで `Close()` などでも引っかかる)。

``` golang
func (db DB)insert(<hogehoge>)error

func main() {
	DB.insert(<hogehoge>) // エラー
	_ = DB.insert(<hogehoge>) // 明示するとlinterがスルーしてくれる
}

```

例えば「エラーを返す関数だけど確認してないよ！」というときに教えてくれます。もし確認する必要がなければ明示的に `_` で受けるとlinterが確認しなくなります(こういうことは開発ルールとして明記したほうが良いのかも)。



### 他にも...
* unconvert : 不要なキャストを知らせる
* unparam   : 不要な関数の引数を知らせる
* unused    : 使っていない変数を教えてくれる(自分の中でunparamと混じってるかも)

他にも不要な○○を教えてくれる、書き方が変または簡単に書ける(省略できる)、など色々なことを教えてくれます。


## まとめ
色々なlinterを使って開発者ごとのブレを少なく出来るといいですね()。
書き方などはともかく、バグになる可能性がある解析ツールをONにしてコミットやpushするときに解析すると事前に確認が出来て良いと思います。
setIntervalとsetTimeoutの違い

Javascriptで使用されるsetIntervalメソッドとsetTimeoutメソッドについてまとめてみます。

## setInterval
> setInterval()メソッドは、一定の遅延間隔を置いて関数やコードスニペットを繰り返し呼び出します。

（[MDN](https://developer.mozilla.org/ja/docs/Web/API/WindowOrWorkerGlobalScope/setInterval)より）

```javascript

setInterval(関数名, 実行間隔(ミリ秒で指定));
```

指定した間隔ごとに関数を実行してくれるメソッドです。
setIntervalを利用してコンソールに１秒間隔で時間を表示させる

```javascript

'use strict';

  function showTime() {
    console.log(new Date());
  }

  setInterval(showTime, 1000);
```

もし処理をとめたい場合は[clearIntervalメソッド](https://developer.mozilla.org/ja/docs/Web/API/WindowTimers/clearInterval)を使うことで止めることが可能です。

## setTimeout
> 時間切れになると関数または指定されたコードの断片を実行するタイマーを設定します。
（[MDN](https://developer.mozilla.org/ja/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout)より）

setIntervalとの違いはsetIntervalは指定間隔ごとに実行され続けるのに対して、setTimeoutは指定した関数が１回のみ実行されます。

```javascript

setTimeout(関数名, 実行時間(ミリ秒で指定));
```

1秒後に１回だけコンソールに時間を表示する

```javascript

'use strict';

  let i = 0;

  function showTime() {
    console.log(new Date());
   
  }
  setTimeout(showTime, 1000);
  
```

setTimeoutを使用してsetIntervalのように繰り返し関数を実行することも可能です。

```javascript

'use strict';

  function showTime() {
    console.log(new Date());
    setTimeout(showTime, 1000);
    }
  }

  showTime();
```

関数の中にsetTimeoutを含めることでsetIntervalと同じく繰り返し関数が実行されます。
こちらも[clearIntervalメソッド](https://developer.mozilla.org/ja/docs/Web/API/WindowTimers/clearInterval)を使うことで止めることが可能です。


## 関数を繰り返し実行したい時には、どちらのメソッドを使えばいいのか

繰り返し処理を実行したい時にはどちらのメソッドを使えばいいのでしょうか？
上記で登場した２つのメソッドには繰り返し処理における開始のタイミングに違いがあります。

- setIntervalでの繰り返し処理
処理にかかる時間に関係なく指定した秒数ごとに関数が実行される。

- setTimeoutでの繰り返し処理
関数が終了してから指定した秒数後に関数が実行される。

具体的に例を出してみてみます。（ミリ秒だと頭がこんがらがるので秒で例を出します。）
例えば処理に1.2秒かかると仮定して、実行間隔を1秒にするとします。
この場合、setIntervalで指定をすると0.2秒分の処理が終わっていない段階で次の関数が実行されてしまうことになります。
ですが、setTimeoutにした場合は1.2秒かかる処理が全て終わってから1秒後に次の関数が実行されます。

処理の量が増えると、負担もその分大きくなってしまう可能性があるため、うまく使い分けることが大切ではないでしょうか。

以上、setIntervalとsetTimeoutの違いでした！！
golangでテーブル駆動テスト（テーブルドリブンテスト）を並列実行で書く際の注意点

なぜかテストが正しく動作しないことがあり、調べたら以下が原因でした

https://gist.github.com/posener/92a55c4cd441fc5e5e85f27bca008721

なぜ上記のようなことが起こるかというと、
https://play.golang.org/p/QIjYezj9RzR
を見たら分かる通り、for loopでloop毎に新しく変数を作っているのではなく、同じ変数を使いまわしているからですね
plotlyで貸借対照表(BalanceSheet)を描画する

#Plotlyで貸借対照表(BS)を描画する
　先日某オンラインウェビナーで[plotlyのハンズオン](https://fin-py.connpass.com/event/196299/)に参加して、Plotlyを使ったデータビジュアライゼーションの創作意欲が高まってきたので、練習がてら、以下のブログの記事を参考に、企業決算の貸借対照表(BS、いわゆるBalanceSheet)をplotlyでグラフ描画してみた。

**Stacked and Grouped Bar Charts Using Plotly (Python)** 
https://dev.to/fronkan/stacked-and-grouped-bar-charts-using-plotly-python-a4p
※スウェーデン在住のフレデリク・ベングトソンさんのブログ記事

　企業決算のBSは、右側にある借方の純資産と負債は「Stacked Bar chart(積み上げ棒グラフ)」の要素を持っていて、また左側の貸方の総資産と右側の借方の部分がくっついていて「Grouped bar chart」の要素も持っていて、いわばStacked-BarとGrouped-barの両方を組み合わせた複合的な「Stacked and Grouped Bar chart」といったグラフを描画するイメージになるのだが、これをPlotlyでどのように指定して描画するのか？というのが今回のイシュー。

#script
```python:asahi_bs.py
from plotly import graph_objects as go

#朝日新聞社のBSの数値をサンプルのデータとして利用
# (子会社の朝日放送HDもしくはテレビ朝日HDが適時開示に「親会社の決算」を発表している)
data = {
    "総資産":[ 594628,605226,611502 ,607605 ,614114 ,599162,554408],
    "負債": [256320,288806, 278072,234054,231745,223782,217897],
    "純資産": [338307,316419,333429 ,373551 ,382368 ,375380,336511],
    "labels": [
        "2015/03本",
        "2016/03本",
        "2017/03本",
        "2018/03本",
        "2019/03本",
        "2020/03本",
        "2020/09中"
    ]
}

# グラフ描画
fig1 = go.Figure(
   # データの指定
   data=[
        go.Bar(
            name="総資産",
            x=data["labels"],
            y=data["総資産"],
            offsetgroup=0,
        ),
        go.Bar(
            name="負債",
            x=data["labels"],
            y=data["負債"],
            offsetgroup=1,
            base=data["純資産"],
        ),
        go.Bar(
            name="純資産",
            x=data["labels"],
            y=data["純資産"],
            offsetgroup=1,
        )
    ],
   # レイアウトの指定
    layout=go.Layout(
        title="朝日新聞社_貸借対照表(BS)",
        xaxis_title="決算期",
        yaxis_title="JPY(単位:百万円)"
    )
)
fig1.show()
```
　上記のスクリプトでは、 `go.Figure()` のDataの指定の箇所で、`go.Bar()`を３つ、総資産と負債と純資産の３種類の棒グラフを指定するのだが、ポイントはこの時に、`offsetgroup`句で右側借方と左側貸方の２グループに分類する記述をする点である。
　つまり左側の総資産は単一でグルーピングする`offsetgroup=0`とし、また右側の負債と純資産の借方を１つのグループ`offsetgroup=1`と記述する。
　あとはoffsetgroup=1の右側(借方)の負債Barの記述だが、純資産Barの上に負債Barを積み上げるイメージでグラフを描画するので、負債の`go.Bar()`の箇所で、`base=data["純資産"]`というように、どのデータの上に載せるのかという記述すればよろしい。

#描画結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91974/8d7bf8b7-018f-c00e-12ea-2ee48fa83cd6.png)
※上図は、Google Colaboratory上でplotlyでグラフ描画した結果

2020/9月時点で、総資産を500億円も減らしているようだ...
(とは言っても、総資産5500億円の巨大企業...優良有価証券ないし優良不動産物件を数多く保有していて、リストラする原資は過分にあるものと思われ)

#補足
今回サンプルにした朝日新聞社(未上場)の決算だが、朝日新聞社は金融庁のEDINETに有価証券報告書を毎年提出しており、また朝日新聞社の子会社、朝日放送ホールディングス(SIC:9405)もしくは、テレビ朝日ホールディングス(SIC:9409)が、「親会社の決算の状況」をJPX適時開示情報に本決算(3月決算)と中間決算(9月決算)の概況を開示しているので、その開示資料等から朝日新聞社の決算の数値は取得可能である。

参考URL:
・IRbank(朝日放送HD):https://irbank.net/E04380/tdnet
・IRbank(テレビ朝日HD):https://irbank.net/E04414/tdnet
typescript環境にJestを導入する

# はじめに
Next.js環境に`typescript`+`jest`のテスト環境を入れたかったため、インストール内容の覚書として記載

# 前提条件
- `typescript`がインストールされていること

# 導入手順
`jest`を`typescript`で認識させるためには[Babel](https://babeljs.io/)による方法と[ts-jest](https://kulshekhar.github.io/ts-jest/)を使う方法が存在するが、ここでは`ts-jest`を使った構築方法を記載する
## インストール
`jest`と`typescript`環境を一括でインストールする

```console:yarn
yarn add --dev jest @types/jest ts-jest
```
```console:npm
npm install --save-dev jest @types/jest ts-jest
```
## 初期化
以下コマンドで初期化を行うことで、`jest.config.js`が生成され、jestに対して`ts-jest`をpresetとして使用するように設定される。

```console:yarn
yarn ts-jest config:init
```
```console:npm
npx ts-jest config:init
```
```jest.config.js
module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
};
```
また、`package.json`にて`yarn test`もしくは`npm test`のコマンドでテストが実行できるように以下設定を追加する

```json
 "scripts": {
...
    "test": "jest",
...
  },
```
## テストコードの記述と実行
テスト対象の`ts`ファイルと、テストコードが記載された`test.ts`を用意する。

```ts:sum.ts
export function sum(a, b) {
    return a + b;
}
```
```ts:sum.test.ts
import {sum} from './sum'

test('adds 1 + 2 to equal 3', () => {
    expect(sum(1, 2)).toBe(3);
});
```
最後にテストを実行する

```console:yarn
yarn test
```
```console:npm
npm test
```
VSCodeの場合は[Jest Runner](https://marketplace.visualstudio.com/items?itemName=firsttris.vscode-jest-runner)の拡張機能を入れることでエディタ上から実行・デバッグすることができる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200228/5b8cd910-3f12-867e-20ac-7a8f4b3b5a54.png)

# 参考
- [Jest公式](https://jestjs.io/docs/ja/getting-started)
- [ts-jest公式](https://kulshekhar.github.io/ts-jest/)
- [Jest Runner](https://marketplace.visualstudio.com/items?itemName=firsttris.vscode-jest-runner)
openpyxlで縦軸の項目の順序を揃える

デフォルトの設定のまま、openpyxlを使ってグラフありのExcelファイルを出力すると、下図のようにテーブルとグラフで縦軸の項目の順序が逆順になってしまい見づらくなってしまいます。

![修正前.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76958/8d7d2158-cfd5-05d4-cd4c-43f369fb4f05.png)

以下のリンクのようにExcelで操作すればテーブルとグラフで縦軸の項目の順序を同じにできますが、今回はプログラムで順序が同じになるよう設定します。

まず、項目の順序を同じにするためには

```:python
chart.x_axis.scaling.orientation = 'maxMin'
```

の設定を追加すると、項目の順序を同じにできます。

![修正後-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76958/b427f588-db79-0103-7e73-e7864e6d35da.png)

項目の順序が同じになったのは良いですが、横軸まで上部に移動してしまいました。

横軸は下部のままにしたいので、

```:python
chart.y_axis.crosses = 'max'
```

の設定を追加します。

![修正後-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76958/b570d915-560e-5fef-31aa-69137c83323c.png)

縦軸の項目の順序だけをテーブルとグラフで同じにすることができました。
【jQuery】jQueryでアコーディオンパネルを作る

最近jQueryを勉強しています。覚えた内容を少しずつ書き出していきたいと思います。
最初は、タイトルをクリックするとその下に内容がぬるっと出てくる、アコーディオンパネルの作り方。
#1 準備
まずはHTMLを準備。

```html
<dl>
    <dt>メニュー1</dt>
    <dd><p>メニュー1の内容</p></dd>
    <dt>メニュー2</dt>
    <dd><p>メニュー2の内容</p></dd>
    <dt>メニュー3</dt>
    <dd><p>メニュー3の内容</p></dd>
</dl>
```
次にCSSを準備。色とサイズを適当に決めているだけです。

```CSS
dl {
    width: 400px;
}
dt {
    height: 30px;
    background-color: gray;
}
dd {
    margin: 0;
    height: 100px;
    background-color: darkgray;
}
dd p {
    margin: 0;
}
```
ブラウザで表示するとこんな感じになります。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/912003/502c8413-7600-f61b-8c55-ad273dec5e4a.png" width=50%>
メニューが全部開いている状態ですね。
これを、クリックしたらメニューの内容が開いたり閉じたりするようにしていくわけです。
#2 JavaScriptの記述
JavaScriptを記述して、機能を実装していきましょう。
まず、2個目以降のメニューは初期表示されないようにしましょう。

```javascript
$(function(){
    $("dd:not(:first)").css("display","none");
});
```
ここでは、`$("dd:not(:first)")`で、「dd要素のうち、最初の要素でないもの」を指定しています。
さらに、`.css("display","none")`で、CSSのdisplayプロパティをnoneに変更しています。
これにより、2個目以降のメニュー(dd要素の中身)が表示されなくなりました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/912003/93901e0a-2093-cff8-1ecd-122c043c3062.png" width="50%">
#3 完成
クリックしたら開いたり閉じたりする機能を追加します。

```javascript
$(function(){
    $("dd:not(:first)").css("display","none");
    $("dl dt").click(function(){
        //ここにクリックしたときの動きを書く
    });
});
```
`$("dl dt")`で、dl要素の中のdt要素を指定します。つまり、メニューのタイトル部分ですね。
ここをクリックしたときの動きを追記していきます。

```javascript
$(function(){
    $("dd:not(:first)").css("display","none");
    $("dl dt").click(function(){
        if($("+dd",this).css("display")=="none"){
            $("dd").slideUp("slow");
            $("+dd",this).slideDown("slow");
        }
    });
});
```
`$("+dd",this)`で、クリックされたdt要素(メニュータイトル部分)と隣接するdd要素(メニューの内容)を指定します。
そのdd要素のdisplayプロパティがnone、つまり表示されていなければ、`$("dd").slideUp("slow")`で、一旦すべてのdd要素を非表示にします。
そして`$("+dd",this).slideDown("slow")`でクリックされたdt要素と隣接するdd要素だけを表示します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/912003/899a9c2c-5435-06c8-775f-5ad92c4fa07b.png" width="50%">
できた。
#4 終わり
jQueryは`getElementsByClass`とか`setAttribute`とかをスッキリ書けるのがいいですね。
でも短い記述がメソッドチェーンとやらでたくさんつながっていくので、文の途中で何をしているのか見失うことが多い・・・。
また、カッコ(){}を大量に使うので、余分に書いたり閉じ忘れたりというミスも、よくやってしまいます。
まだまだ勉強し始めたばかりで簡単な内容しか書けませんが、今後もできるだけ記事を書いていきたいと思います。
[2020/12/06確認済み]UbuntuでFlutterの開発環境を構築してみた

# 本記事のゴール
Android Studioを用いてFlutterのサンプルをエミュレータで動かしてみる。

# バージョン

|ツール名|バージョン|
|:---:|:---:|
|Flutter|1.22.4|
|Dart|2.10.4|
|Android Studio|4.1.1|

# Flutter SDKの導入

- 公式サイトよりダウンロードして適当な場所に解凍

[公式サイト](https://flutter.dev/docs/get-started/install/linux)

```
$ cd ~/
$ mkdir Development && cd Development
$ tar xf ~/Downloads/flutter_linux_v1.22.4-stable.tar.xz
$ rm -rf ~/Downloads/flutter_linux_v1.22.4-stable.tar.xz
```

- パスを通す

```
$ sudo vim ~/.bashrc

#　ここから追加
export PATH="$PATH:$HOME/development/flutter/bin"
#　ここまで
```

# Android Studioのインストール

- 公式サイトよりダウンロードして適当な場所に解凍

[公式サイト](https://developer.android.com/studio)

```
$ cd ~/Download
$ tar -zxvf ./android-studio-ide-201.6953283-linux.tar.gz
$ sudo mv ./android-studio /opt/
$ rm -rf android-studio-ide-201.6953283-linux.tar.gz 
```

- スクリプトを叩いて起動するか確認

```
$ cd /opt/android-studio/bin
$ ./studio.sh 
```

- ウィザードが起動するため以下のサイトに従って進める

[参考サイト](https://www.virment.com/install-android-studio-ubuntu18-04/)

- Flutter/Dartプラグインを追加する

Configure -> Plugins -> Marketplace -> Flutter か Dart を入力してインストールを押下

- ショートカットをデスクトップに作成

```
$ cd ~/Desktop
$ vim android-studio.desktop

#　ここから
[Desktop Entry]
Type=Application
Encoding=UTF-8
Name=Android Studio
Comment=Android Studio
Exec=/opt/android-studio/bin/studio.sh
Icon=/opt/android-studio/bin/studio.png
#　ここまで

```

- 実行権限を付与しておく

```
$ chmod 773 ./android-studio.desktop
```

# 諸設定

- 必要なツールをインストール

```
sudo apt-get install -y libc6:i386 libncurses5:i386 libstdc++6:i386 lib32z1 libbz2-1.0:i386
```

- 依存関係を解決する

```
flutter doctor
flutter doctor --android-licenses
```

# サンプルアプリを作成してみる

- プロジェクトを作成する

New Flutter Project -> Flutter Application　を選択する

なお、Flutter SDK pathは以下のように設定する

```
/home/[user]/development/flutter
```

- エミュレータを起動する

公式サイトに従ってエミュレータを起動する

[公式サイト](https://developer.android.com/studio/run/managing-avds?hl=ja#emulator)
 
- Runを押して実行！

# 参考

[Flutter公式が提供している環境構築手順](https://flutter.dev/docs/get-started/install/linux)
[Android Studioのショートカットの作成方法](https://qiita.com/kaleidot725/items/dc1eccc9064ab6b8cd4a)
[記事執筆時点で解決不能なエラーについて](https://twitter.com/kosuke_mtm/status/1323662380727898113?ref_src=twsrc%5Etfw%7Ctwcamp%5Etweetembed%7Ctwterm%5E1323662380727898113%7Ctwgr%5E%7Ctwcon%5Es1_&ref_url=https%3A%2F%2Fqiita.com%2Fmkosuke%2Fitems%2F7957e71968aefc6558be)