OmniAICreator/Qiita-1.07M huggingface dataset:
BOX SDK（java）で同名ファイルの上書きアップロード

# BoxFolder.uploadFileだと既に同名のファイルが存在する場合にエラーになる
上書きオプションとかあればいいんですが・・・。

```
// ファイルをルートフォルダにアップロード
BoxFile.Info newFileInfo = null;
try (FileInputStream stream = new FileInputStream("C:\\hoge\\updload_sample.txt")) {
  newFileInfo = rootFolder.uploadFile(stream, fileName);
} catch (BoxAPIResponseException e) {
  System.out.println("LocalizedMessage : " + e.getLocalizedMessage());
  // 既に同名ファイルが存在する場合
  if (e.getLocalizedMessage().contains("409")) {
　  // 該当ファイルを捜索
    Iterator<Info> ite = rootFolder.getChildren().iterator();
    while (ite.hasNext()) {
      Info boxInfo = (Info)ite.next();
      String objectName = boxInfo.getName();
      if(objectName.equals(fileName)) {
        String fileId = boxInfo.getID();
        BoxFile file = new BoxFile(api, fileId);
　　　  // アップロード
        try (FileInputStream stream = new FileInputStream("C:\\hoge\\updload_sample.txt")) {
          file.uploadVersion(stream);
        }
      }
    }
  }
}
```

# 課題
BoxFile.uploadVersion は非推奨になっているんですが他に代替手段を見つけられなかった。。
Sonar for BitbucketでSonarを全社導入してみた

## はじめに
こんにちは。
ナビタイムジャパンで社内JiraやBitbucketの運用をしている TAKE です.
社内のコード品質向上について,全社向けに『Sonar for Bitbucket』を導入した際に大変だった点をお伝えします.

### Sonar for Bitbucket とは
『SonarQube』の解析結果をBitbucket上に表示するためのBitbucketのアドオンです.
![sonar.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315364/d9b29b1a-9677-b221-6107-fd79f6ef6841.png)

https://marketplace.atlassian.com/apps/1212735/sonar-for-bitbucket-server?hosting=server&tab=overview


## 問題と解決のみちのり

#### 数百のリポジトリ
一番大きかった問題は解析用CIツールのJOBについてです.
SonarQubeの公式ドキュメントを参考に実装すると**リポジトリの数**だけ解析用CIツールのJOBが必要になってきます.(弊社ではJenkinsを利用)
つまりJOBを数百個作成する必要がありました...

#### JOBの共通化
BitbucketからJenkinsにリポジトリ名などの情報を渡せばJOBは一つで済むと考えました！
![diagram.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315364/cfdf685e-d36d-1ad1-98b1-5b226991f498.png)




#### BitbucketとJekinsの連携の問題
BitbucketからJenkinsのJOBをパラメータ付きで起動したい場合,多くの場合で『[Webhook to Jenkins for Bitbucket](https://marketplace.atlassian.com/apps/1211284/webhook-to-jenkins-for-bitbucket?hosting=server&tab=overview)』というプラグインが利用されています.公式でもこちらがおすすめされていました.

(参考)
https://mohamicorp.atlassian.net/wiki/spaces/DOC/pages/210305025/Sending+URL+Parameters+to+Jenkins#SendingURLParameterstoJenkins-BitbucketServer

実際に実装しようとしたところJenkinsのプラグインの設定を行うと,共通化したJOBにパラメータを渡すことができませんでした.
どうにかできないか色々試しましたが、深みにハマりつつあったのでAWS API GWとAWS Lambdaを用いて自作しました.
<img width="988" alt="lambda.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315364/3168051f-c6b5-2bb3-b6c4-8be3ea8bac00.png">


Lambdaの処理については,Bitbucketから送られてきたパラメータをもとにJenkinsのAPIを叩くようなものになっています.
Bitbucketからのパラメータも[公式ドキュメント](https://confluence.atlassian.com/bitbucketserver0513/event-payload-957493824.html?utm_campaign=in-app-help&utm_medium=in-app-help&locale=ja_JP%2Cja&utm_source=stash#Eventpayload-repositoryevents)を確認すると詳細に情報が記載されています.

これによりユーザはAWS APIGatewayのURLをwebhookに設定するだけで解析ができます.
詳細は下記のような3ステップで,数分しか必要としません.
1. Bitbucketのリポジトリ毎のwebフック設定に、上記で作成したLambdaへのリクエストURLを設定
2. 「テスト接続」で解析実行
3. BitbucketでSonar表示の設定を行う
<img width="1119" alt="webhook.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315364/4cd4611d-25fb-5ed2-c439-6d97f7fd48ed.png">

## 結果
導入ができました!
更に2つのメリットがありました

* 導入が楽
* 全社で同じ基準のルールを適用できる

特に1つ目については,各組織毎に導入を行うとDBの構築からJobの設定,Bitbucketの設定まで非常に多くの工数が発生しますが,全社向けに導入した成果として,数分で導入可能になりました!


## 今後の課題
### テスト結果が確認できない
今回のSonarの導入にはAWSのEC2を用いていますが,社内の各リポジトリの動作環境を用意することができず(現実的じゃなかった)テストのためのビルドを実行することができませんでした.
テストカバレッジなどは品質を管理する上で非常に重要な指標のため現在改善に向けて活動しております.

## まとめ
* 各リポジトリ毎に解析用JOBを作成したくなかった
* Lambdaで自作した
* 各リポジトリにかんたんに導入できるようになった
GitHubのパスワードを変更して、pushしたらエラーが出た話

# エラー詳細
GitHubのパスワードを変更後に、作業ブランチをpushしたら下記エラーが発生

```
remote: Invalid username or password.
```

# 解決方法
下記コマンドでGitHubユーザ名を入力

```
git config --global user.name ユーザ名
```

その後、通常通りpushを実施するとユーザ名とパスワードを聞かれるので入力する。

```
git push origin ブランチ名
Username for 'https://github.com': ユーザ名
Password for 'https://hogehoge@github.com': 新しいパスワード 
```

# 参考
[GitHubでパスワード変更後、pushしたら「remote: Invalid username or password.」が出たときの対処法](https://reasonable-code.com/github-invalid-error/)
webpackのバージョン上げて、HMRに失敗した時の備忘録

vue-cliでサーブしている場合。
webpackのバージョンを上げたらHotModuleReloadが失敗するようになった時のメモ。

```
TypeError: compilation.getPathWithInfo is not a function
```

webpackの中でやり方が変わったっぽい。


```
npm uninstall webpack
```

package.jsonを確認して、動いていた時のバージョンを入れ直す。

```
npm install webpack@4.28.4 --save-dev
```

参考リンク
https://github.com/gatsbyjs/gatsby/issues/19081
※全然違うissueですが、webpackのバージョンを上げすぎ。と言ってる。
割引率のメモ

雑なメモです．

#割引率(discount factor)

強化学習では，累積割引報酬

```math
\sum_{t=0}^{T} \gamma^{t} R_t
```

を最大化する．ここで，$R_t$は各時刻$t$に貰える報酬，$\gamma$が割引率（discount factor）である．割引率とは，「将来に貰える報酬をどれだけ割り引いて考えるか」を表すパラメータで，範囲は$0 \leq \gamma < 1$．通常0.9あたりに設定する．割引率が大きいときは遠い未来の報酬まで考える方策を，小さいときには直近の報酬しか考えない方策を学習する．

## 割引率のグラフ
$y=\gamma^{t}$のグラフを示す．横軸が$t$，縦軸が$y$．
![gamma.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459984/ed4af0db-2f95-51a5-e097-29d9aeee2ab8.png)

よく使われる$\gamma=0.95$は，およそ$t=100$付近でほぼ$0$になっている．たとえば，OpenAI Gym環境の[CartPole-v0](https://github.com/openai/gym/wiki/CartPole-v0)は最長ステップ数が200であるが，200ステップ先の報酬に掛かる割引率は$\gamma^{200}=0.95^{200} \fallingdotseq 0.000035$であり，非常に小さい．

## 割引率が特定のしきい値を下回るステップ数
```math
y= \gamma^{t} \\
\ln y = t \ln \gamma \\
t = \frac{\ln y}{\ln \gamma}
```

と変形すると，割引率$\gamma^t$が特定の値$y$になるようなステップ数$t$を求めることができる．
割引率$\gamma^{t}$が特定の値より小さくなるステップ数を示す．

| 割引率$\gamma$ | $<0.5$ | $<0.1$ | $<0.01$ | $<1.0 \times 10^{-100}$|
|:-----------|------------:|------------:|------------:|------------:|
| 0.999 | 693 | 2302 | 4603 | 230143 |
| 0.99 | 69 | 230 | 459 | 22911 |
| 0.95 | 14 | 45 | 90 | 4490 |
| 0.9 | 7 | 22 | 44 | 2186 |
| 0.8 | 4 | 11 | 21 | 1032 | 
| 0.5 | 2 | 4 | 7 | 333 |
| 0.1 | 1 | 2 | 3 | 101 |

## 割引率の逆算
こういうやり方がよいかは微妙だが，逆に，あるステップ数$t$で特定の値$y$になるような割引率$\gamma$を求めたい時．

```math
y= \gamma^{t} \\
\ln y = t \ln \gamma \\
\frac{\ln y}{t} = \ln \gamma \\
 \gamma = \exp (\frac{\ln y}{t})
```

たとえば，先述したCartPole-v0で，最長ステップ数$t=200$のとき$y=0.01$になる$\gamma$は，$\exp(\frac{\ln 0.01}{200}) \fallingdotseq 0.977$である．
【vue.js】【css】element-ui el-dialogのheaderをカスタマイズしたい時


下記の書き方ならok!

ポイント1：　lang="scss"  を　必須！
ポイント2：  /deep/ or >>> を　どちらか　必須！

方法1

```
<style lang="scss" scoped>
  /deep/ .el-dialog__header{
         background-image: linear-gradient( to right, #5cbb7a, rgba(255, 0, 0, 0) );
  }
</style>
```


方法2

```
<style lang="scss" scoped>
  >>> .el-dialog__header{
         background-image: linear-gradient( to right, #5cbb7a, rgba(255, 0, 0, 0) );
  }
</style>
```
私のbigquery備忘録

BigQueryを扱うことになったが、ここ数年はsqlserverぐらいしか触って来なかったので、よく使う関数やらを備忘録程度に書き留める

1. とりあえず使った関数を書き連ねる　←いまここ
2. カテゴリーとかで分ける

# 使った・しらべた

## 現在時刻
* `CURRENT_DATE()`
 * 戻りデータの型 DATE  
sqlserverで言うところの`getdate()`

* `CURRENT_DATETIME()`
  * 戻りデータの型 DATE  
* `CURRENT_TIMESTAMP()`
  * 戻りデータの型 CURRENT_TIMESTAMP  
使い分けがいるみたい

# TIMESTAMP型のUTCからJST変換
 `FORMAT_TIMESTAMP('%Y-%m-%d %H:%M:%S', created_at, 'Asia/Tokyo')`


## 日付がついたテーブルの指定方法
```
select *
from `tabel_*`
where _TABLE_SUFFIX = FORMAT_DATE("%Y%m%d",CURRENT_DATE())`
```
`_TABLE_SUFFIX`がポイント
``

## 文字列検索
* `STRPOS(string, substring)`
 * 戻りデータの型 int64  
sqlserverで言うところの`CHARINDEX`

## NULL置換
* `IFNULL`
    * `ISNULL`じゃない
RDSについて特徴,構成,作り方

#RDS
MySQL,postgressに慣れた人なら一番とっつきやすい．
トランザクション処理が必要な業務データベースです．


##構成
###Multi-AZ
![az.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543591/b3d2d948-70ba-c04f-89c4-0f75e337ee61.png)

異なるアベイラビリティゾーンでデータを複製しています．
複製に常に最新情報を更新させています．
すなわち，メンテナンスやバックアップに対応しております．

###リードレプリカ
![リードレプリカ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543591/37fcc7c8-d241-7470-9df3-2c33fc5d78c4.png)
ざっくり言うと，読み込みと書き込みを別のDBで行なってるんです．

マスター(プライマリDBともいう)に書き込みをし，
リードレプリカから読み込みをしてます．

さらに，複数のリードレプリカを作っているので，アクセスの分散も出来てしまいます．

###ストレージのタイプ
他の記事では長ったらしく書いてますが，

凡用SSD ... 無課金　普通性能 普通にこれで良い

プロビジョンドIOPS ... 課金有り　高性能　I/O多いならこれ

Magnetix ... いらん　上記の下位互換

でおけ．

注意は，プロビジョンドで思ったよりもデータ数が少なくて，容量を下げたい場合はRDSを停止する必要がある．

容量上げはRDS起動時も可能．




##作り方
マネジメントコンソールからRDSを開く
![スクリーンショット 2019-12-10 15.24.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543591/71ee2043-4a14-e911-c221-19c418e1b07f.png)

mysql勢はチェック

![スクリーンショット 2019-12-10 15.24.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543591/5ab2ed7a-a7bf-1425-b737-2dd7a08e32bf.png)
バージョンと用途選択

![スクリーンショット 2019-12-10 15.24.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543591/b6146c56-a793-b558-b3ab-9ea95e153252.png)

DBのインスタンス名を決めて，
よくある奴を打ち込んで，

![スクリーンショット 2019-12-10 15.24.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543591/c80bb766-a7ab-a272-972a-aa48dbb47dbd.png)



使いたいメモリクラス決めて

![スクリーンショット 2019-12-10 15.25.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543591/3b607eb9-17a4-fafc-5f49-99544a6385bd.png)

タイプは凡用でok
ストレージは各々決めてください．
最初は小さめに設定するのがオススメ．
自動スケーリングをONにすれば最適な容量でコスパ良いからね

![スクリーンショット 2019-12-10 15.25.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543591/16bc0b62-69ad-d894-ce9e-35e2e61bf842.png)



マルチAZは配置すべき別のアベイラビリティゾーンに複製してくれる．
VPCは繋げたいappの環境に合わせてください．
多分デフォでいけるはず．

![スクリーンショット 2019-12-10 15.25.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543591/4397015b-cc3a-0b15-2083-e189f75670fb.png)

めんどうなのでパスワード認証のみでok
料金は見積もってみて，自分の財布と相談してAZ外したり，可用性落としたりで．ok

![スクリーンショット 2019-12-10 15.26.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543591/5ec7b74e-570d-6c8c-6b12-b50db84c417a.png)

はい完成

DB削除したい場合は，![スクリーンショット 2019-12-10 15.27.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543591/3d707326-a920-4b8f-ccd7-6e815b777d0a.png)
削除保護無効にしてから，
![スクリーンショット 2019-12-10 15.27.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543591/3153c370-1a31-4d38-606c-30db4bdca994.png)
ここで削除．


出来そうでしょ??

sql派の人はクラウドベースの作業時RDSは必須なんで手を動かしてやってみると良いですよ~
LINE WORKSのAPIを使ってノンプログラミング連携してみた体験談 


# はじめに
こんにちは、セゾン情報システムズのよろず相談担当 すぎもん :yum:です。

先日、以下の記事をQiitaにて掲載させていただきました。
「DataSpiderで人事DBとLINE WORKSをノンプログラミングで繋いでみた」
https://qiita.com/sugimon/items/7ec6a87c3438574b3ef1

その流れで、"LINEWORKS Advent Calendar 2019”にお誘いを受けましたので、
今回はLINE WORKSの周辺システム開発を行う立場と想定して、記事掲載時に体験した事を書かせていただこうと思います。

# そもそもDataSpiderって何？
前提として、「DataSpider」が何者かを少しだけ。

DataSpiderは異なるシステムのデータやアプリケーションをノンプログラミングで「つなぐ」ことで開発が行える開発ツールになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458288/518dc449-5916-225a-9b67-01877e4ea532.png)

細かい事は興味がありましたら以下をご覧いただければと思います。
https://www.hulft.com/software/dataspider/product

# 実施概要
詳しい事は別途記事をご覧いただければと思いますが、ざっくりと以下のユースケースを満たす仕組みを構築しました。
「人事DBの更新情報を自動でLINE WORKSのユーザ情報に反映させたい」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458288/aff683ee-bdaf-f7c2-b02f-95c715cb49e5.png)

この仕組はLINEWORKS の組織連携 APIを使用して構築しています。
https://developers.worksmobile.com/jp/document/100300101?lang=ja

また、構築時はsandbox環境にてテストを行いました。

# 構築体験談
ここからは、実際に構築を行っていく上で体験したことを記載していきます。

### 「External Key」が空だった
一番初めにハマったことは、「External Key」が空でどうしていいか分からなかった事です。

画面からユーザを追加した後、設定を変更してAPI連携できるようにしたところ発生しました。

APIの仕様を見るに、「externalKey」の項目がキーとして必須の項目であるのですが
それが空という状態が一体どういう状態なのか分からず困っていました。

最終的にはコミュニティの以下のやり取りを見る事で解決しました。
https://forum.worksmobile.com/jp/posts/149

画面操作で登録したユーザは「externalKey」が空欄で登録されてしまうらしく、
別途コミュニティ掲載の手段で「externalKey」を追加することで解決しました。

一度運用に乗ってしまえは問題にはならないかと思いますが、一番始めの構築時に注意が必要かなと感じました。

### sandboxはやはり便利
一連のテストはsandbox環境を利用してテストしましたが、やはり本番環境とは別にテスト環境があるのは便利ですね。
今回のテストでは幾人もの「セゾン太郎」さんや「セゾン次郎」さんを入社させたり退職させたり休職させたりしたのですが、もし本番環境でミスして既存のユーザに影響が出たら恐ろしいですからね……

ただ、メンバー即時削除APIの設定が有効になるのに1日かかるのを知らなかったため、実作業が1日ペンディングになるという珍事がありました。そこはsandbox環境では即時有効できると嬉しいなと思いました。

また、ユースケース「処理に失敗した場合、メールで管理者へ通知する」をテストしようとしたのですが、メール機能はsandboxの機能対象外だったため諦めました。
ここは実際の運用ではメールではなくLINE通知などになるのではないかと考えており、あまり拘っていなかったので今回は問題にならなかったです。

### コミュニティでのサポート
処理を構築していく上で、いくつか仕様や動作がわからない点がありましたが、コミュニティにてサポートしていただけました。
ドキュメントに記載のない細かい動作仕様があるようですが、それらもきちんとコミュニティにて回答頂けたため作業に詰まることなく無事に構築することが出来ました。

#最後に
LINE WORKSのAPI連携機能を用いて構築を行った上での体験を記載させて頂きましたがいかがでしたでしょうか？
いくつか詰まったポイントはありましたが、総じて開発、テストが行いやすいと感じました。

今後はBotを使ったシステム連携の仕組みをノンプログラミングで作ってみたいと考えているので、また機会があれば記事にして公開していければと考えています。
また、社内システムのこういったものとLINE WORKSを連携させたいなどのアイディアがありましたら、実践してみたいのでぜひお声がけ下さい。
スクレイピングで画像を取得してみた

## 初めまして！ 
　プログラミングの勉強をしている**Shun**です。最近Pythonに興味があったので、こちら「**スラスラわかるPython**」を読ませて頂きました。この本ではPythonの基本的な構文を学んだり、Webスクレイピングのやり方が書いてあります。
![](https://images-na.ssl-images-amazon.com/images/I/41cNLS3Aa9L._SX354_BO1,204,203,200_.jpg)
[**スラスラわかるPython 単行本**]
(https://www.amazon.co.jp/%E3%82%B9%E3%83%A9%E3%82%B9%E3%83%A9%E3%82%8F%E3%81%8B%E3%82%8BPython-%E5%B2%A9%E5%B4%8E-%E5%9C%AD/dp/4798151092/ref=asc_df_4798151092/?tag=jpgo-22&linkCode=df0&hvadid=295686767484&hvpos=1o1&hvnetw=g&hvrand=17010285472902510266&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1009343&hvtargid=pla-526272651553&psc=1&th=1&psc=1/)

　
## そもそもWebスクレイピングって何？？
簡単に言うと、Webサイトで自分が欲しい情報を抜き出す技術です。

## 実際に画像を取得してみようと思う
せっかくWebスクレイピングを学んだので実際にやってみようと思います。今回スクレイピングを行うサイトはバンドリの公式サイト(https://bang-dream.com/)
なぜこのサイトにしようとしたのかというと．．．下の画像が欲しかったからです。
![キャプチャ02.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541905/21227127-5367-e1da-ccb2-2b9a12c417d0.jpeg)


###  準備

VScodeでQiitaというフォルダを作ってみました。このQiitaというフォルダの中に保存していきたいと思います。次にコマンドプロンプトを開いて以下のコマンドを実行してください。インストールが始まります。

``` 
$ > pip install requests --user
```



```  
$ > pip install BeautifulSoup4 --user 
```

インストールが完了したら今度はターミナルを開いて、インストールが成功しているかチェックしたいと思います。

``` 
$ >>> import requests 
  >>>
```

``` 
$ >>>  from bs4 import BeautifulSoup
  >>>                 
```
この時点で何もメッセージが出ていなければインストール成功です。もしここで以下のようなエラーメッセージが出てしまう場合はインストールに失敗しています。このような場合は、パソコンがインターネットに接続できてきているか確認をして、もう一度pipコマンドでインストールしてください。


``` 
$　>>> import requests 
 Traceback (most recent call last ) : 
    File  "<stdin>" ,  line  1 , in  <module>
ModuleNotFoundError : No module named " requests "
      >>>　　
```



### コード

以下の内容をQiitaフォルダの中にQiita01.pyという名前で保存してみました。解説も載せてあります。

```python:Qiita01.py

import requests 
from bs4 import BeautifulSoup 

result = requests.get("https://bang-dream.com/")
soup = BeautifulSoup(result.text, "html.parser")
img = soup.find_all('img')
print(img)
```

``` import requests ``` requestsライブラリを利用するための宣言
``` from bs4 import BeautifulSoup ``` 外部ライブラリBeautifulSoupのインポートを行っている
``` result = requests.get("https://bang-dream.com/") ``` ここでスクレイピングしたいURLを入れる
``` soup = BeautifulSoup(result.text, "html.parser") ``` BeautifulSoupの処理に解析したい文字列と実際に解析するための処理の種類を指定
``` img = soup.find_all('img') ``` findメゾットに[img]という文字を指定


| メゾット | 機能 |
|:--------|------|
| find_all()  | 引用で指定されたタグを検索して、一致したものすべてを格納したリストに返す    |

``` print(img) ``` 出力

### 出力結果

![キャプチャ03_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541905/797a1cf9-34e4-e62a-2cba-6396c4dedbed.jpeg)


ターミナルで見てみると、このようなのが出てきます。赤線で引かれてるところのリンクを開いてみましょう。以下のような画像が出てきたら、スクレイピング成功です。

![579de894-5bc4-4371-a0a0-da781af22bfa.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541905/68492ed6-94b2-a5ca-f52b-055d71f3eef5.jpeg)




## 感想
なんで初歩的なことを記事にしたんですか？？　って思う人もいるかもしれません。答えは簡単です、これくらいしかかける記事がありませんでした... これからもっとPythonを深めていきたいです。
jquery（javascript)でクリップボードにコピーする

# サンプルコード
※2019/12のサンプルコードになります。
ボタン押下などで動作するようにはしています。
サンプルコード内にコメントを記載したので、注釈的な記述はとりあえず省略。


```javascript:clipboardCopy.js
/**
* @string text:コピーするテキスト
*
**/
function clipboardCopy(text) {
    // コピーするテキストが空の時は放置民
    if(text != ""){
        // 閲覧中のブラウザの情報を取得
        var userAgent = window.navigator.userAgent.toLowerCase();
        
        // ブラウザで処理を分岐
        if(
            userAgent.indexOf('msie') != -1// IE10以下
            || userAgent.indexOf('trident') != -1// IE11
        ) {
            // クリップボードにコピー
            window.clipboardData.setData("text",text);
        } else if(
            userAgent.indexOf('edge') != -1// Edge
            || userAgent.indexOf('chrome') != -1// Chrome
            || userAgent.indexOf('safari') != -1// Safari
            || userAgent.indexOf('firefox') != -1 //FireFox
            || userAgent.indexOf('opera') != -1// Opera
        ) {
            var listener = function(e){
                e.clipboardData.setData("text/plain" , text);
                // 本来のイベントをキャンセル
                e.preventDefault();
                // 終わったら一応削除
                document.removeEventListener("copy", listener);
            }
            // コピーのイベントが発生したときに、クリップボードに書き込むようにしておく
            document.addEventListener("copy" , listener);
        
            // コピー
            document.execCommand("copy");
        }
    }else{
        // 空の時はalertでもやっとく？
    }
};
```
## 注釈（後日）

## 最後
もう少し調査したかったけど、一端糸冬了。
IE11のせいで調査に時間かかりすぎる。
GCE上でRancherOSを立ち上げDockerの管理をしてみる

プロジェクトやgcloudの設定など、本記事と本質的に関係の無い所は除外します。

また、序盤の環境構築は[公式のチュートリアル](https://rancher.com/docs/os/v1.x/en/installation/running-rancheros/cloud/gce/)を基にしています。

## 環境の構築

では早速GCEインスタンスの立ち上げまでを進めていきましょう。

RancherOSはイメージとして`.tar.gz`ファイルとして提供されています。

まずはそのイメージをローカルマシンに持ってきましょう。

以下のReleasesから、`rancheros-gce.tar.gz`をダウンロードするか、その下にあるコマンドを任意のディレクトリで実行します。

[Releaces Artifact](https://github.com/rancher/os/releases)

```zsh:local
$ curl -OL https://github.com/rancher/os/releases/download/v1.5.4/rancheros-gce.tar.gz
```
上記コマンドを実行する場合は、バージョンを指定しているので最新バージョンを確認し、置換してください。

ダウンロードしたら、次はGCSバケット作成します。

まずgcloudのconfigが正しいかをしっかり確認しましょう。

```zsh:local
$ gcloud config list
```

GCPではリソースはプロジェクト毎に管理されるので、間違ったプロジェクトで作業しないようしっかり確認してください。

```zsh:local
$ gsutil mb gs://rancher-image4qiita
```

今回は`rancher-image4qiita`という名前でバケットを作成しています。

バケットを作成したら、先程ダウンロードしたイメージをGCSバケットにアップロードします。

```zsh:local
$ gsutil cp ./rancheros-gce.tar.gz gs://rancher-image4qiita
```

イメージをアップロードできたので、このイメージからGCEで利用可能なカスタムイメージを生成します。

```zsh:local
$ gcloud compute images create my-rancher --source-uri gs://rancher-image4qiita/rancheros-gce.tar.gz
```

イメージ名は`my-rancher`にしています。`--source-uri`オプションには先程アップロードしたイメージのURIを指定します。また、こちらのコマンドは多少時間がかかります。

カスタムイメージが作成できたら、そのイメージでインスタンスを準備します。

まずはファイアーウォールのルールを作りましょう。

```zsh:local
$ gcloud compute firewall-rules create allow-rancher --allow tcp:22,tcp:80,tcp:443 --source-ranges 0.0.0.0/0
```

それをタグとして追加したインスタンスを立ち上げます。

```zsh:local
$ gcloud compute instances create rancher-instance --machine-type n1-standard-1 --image my-rancher --tags allow-rancher
```

RancherOSのメモリ要件として1GB以上となっています。n1-standard-1を選んでおけば問題ないです。

インスタンスが立ち上がったらSSHで接続しましょう。

```zsh:local
$ ssh rancher@IP_ADDR -i SSHKEY_PATH
```

ログインできたら準備完了です。 dockerのバージョンでも確認しておきましょう。

```zsh:ranchger-insrance
$ docker -v
```


---

RancherServerのGUIでコンテナ管理はあとから書きます
nextronを使ってNext.jsでMacアプリを作る話

この記事はNext.jsアドベントカレンダーの10日目の記事です。

どうも！ハムカツおじさんという名前でtwitterやってます([@hmktsu](https://twitter.com/hmktsu))🤘
自分でだったり弊社でだったりなどNext.jsを使ってサービスを作っています。

## はじめに

現在作っているサービスの管理画面は自分たちでしか使わない + ffmpegで動画をエンコードしたりなど諸々作業をしないといけないという理由からElectronで作ろうと思いました。
もちろん普通にReactでというのも全然問題ないのですが、正直Next.jsに慣れているとReactのライブラリを色々と導入して…というのが面倒に感じてしまいます。

そこでElectronでどうにかNext.js使うことできないかな〜と思いつつ色々と探していたら、Next.jsを内包したnextronというパッケージがあったのでそちらを使うことにしました。
メンテナンスもしっかりと行われてたり、issueも活発に返答いただいたりと丁寧な感じなのでおすすめです。

[saltyshiomix/nextron](https://github.com/saltyshiomix/nextron)

ということでnextronを使うと便利だよ的な紹介をしたいと思います。

## インストール
```
# npx create-nextron-app <MY-APP>

# templateを使う場合
$ npx create-nextron-app <MY-APP> --example with-typescript-material-ui
```
Nextと同じくこういうコマンドが用意されています。
[examples](https://github.com/saltyshiomix/nextron/tree/master/examples)に色々とテンプレートが用意されているので使うと良いのではないかと。

```
.
├── README.md
├── electron-builder.yml
├── main
│   ├── background.js
│   └── helpers
│       ├── create-window.js
│       └── index.js
├── package.json
├── renderer
│   ├── next.config.js
│   ├── pages
│   │   ├── home.jsx
│   │   └── next.jsx
│   └── public
│       └── static
│           └── logo.png
└── resources
    ├── icon.icns
    └── icon.ico
```
これはテンプレートを使わないでインストールをしたものとなっています。
`main`でElectronの初期化、`renderer`に通常のNext部分が入っています。

## ビルド
```
{
  "scripts": {
    "build": "nextron build",
    "build:all": "nextron build --all",
    "build:win32": "nextron build --win --ia32",
    "build:win64": "nextron build --win --x64",
    "build:mac": "nextron build --mac --x64",
    "build:linux": "nextron build --linux"
  }
}
```
`package.json`の`scripts`にすでにビルドコマンドを用意してくれています。
さらに`electron-builder.yml`を編集するなりすればもう少し細かいオプションの設定もすることができます。

```
$ nextron build --mac --x64 --config electron-builder.development.yml
$ nextron build --mac --x64 --config electron-builder.production.yml
```
またこのように`--config`オプションを指定することでymlの変更を行うこともできます。
こちらの機能を欲していたのでissueでお願いしたところすぐに作ってくれたので感謝です🙏

ビルドが完了すると`dist`フォルダ内に諸々出てくるのでそれを使うなりなんなりと。

## 注意点
* サーバーレスモードとして扱われる
* `dev`環境ではNextサーバが内部で動くが、ビルドしたものでは動かない
* ファイルを置いてある環境(自分の場合はfirebase storage)によってはCORS制限にどうやっても引っかかるので、リバースプロキシを`main`部分で定義して内部でサーバを立てる必要がある

その他もろもろありますが、Electronで出てくるようなものでもありますので割愛します。

## まとめ
とりあえず単純な紹介記事になってしまって申し訳ないですが、Next.jsでMacアプリを作りたいというときはnextronを使うことをおすすめします。
通常のElectronは諸々設定なりも多いのでビルドすることも面倒だったりはしますが、ほぼほぼ何も気にする必要なく、しかも便利なscriptを内包してくれているのでビルドもすごく簡単にできます。
ぜひとも使ってみてください。
Library not loaded: /usr/local/opt/openssl/lib/libssl.1.0.0.dylib (LoadError)

# opensslが読み込めない
別アプリでrubyのバージョンアップしたら全然関係ないアプリが見事に死んだよ。
備忘録に残すので誰かのザオリクとして使えますように。

## bundlerをインストールしようとするとコケる
ruby入れ直して

```
gem install bundler
```
でインストールしようとしたところ

```
ERROR:  Loading command: install (LoadError)
	dlopen(/Users/~~/.rbenv/versions/2.5.3/lib/ruby/2.5.0/x86_64-darwin18/openssl.bundle, 9): Library not loaded: /usr/local/opt/openssl/lib/libssl.1.0.0.dylib
  Referenced from: /Users/~~/.rbenv/versions/2.5.3/lib/ruby/2.5.0/x86_64-darwin18/openssl.bundle
  Reason: image not found - /Users/~~/.rbenv/versions/2.5.3/lib/ruby/2.5.0/x86_64-darwin18/openssl.bundle
ERROR:  While executing gem ... (NoMethodError)
    undefined method `invoke_with_build_args' for nil:NilClass
```
**は？**
opensslが読み込めてないと怒られてる。
```brew link openssl --force```とかなんかいろいろしたけどあかん。

```
openssl version
```
でバージョン確認

```
OpenSSL 1.1.1d  10 Sep 2019
```
………

**使おうとしてるやつとバージョンちゃうやんけ**

## openssl再インストール
```
brew reinstall openssl@1.1
```
んで```gem install bundler```

```
ERROR:  Loading command: install (LoadError)
	dlopen(/Users/~~/.rbenv/versions/2.5.3/lib/ruby/2.5.0/x86_64-darwin18/openssl.bundle, 9): Library not loaded: /usr/local/opt/openssl/lib/libssl.1.0.0.dylib
  Referenced from: /Users/~~/.rbenv/versions/2.5.3/lib/ruby/2.5.0/x86_64-darwin18/openssl.bundle
  Reason: image not found - /Users/~~/.rbenv/versions/2.5.3/lib/ruby/2.5.0/x86_64-darwin18/openssl.bundle
ERROR:  While executing gem ... (NoMethodError)
    undefined method `invoke_with_build_args' for nil:NilClass
```
はい、エラーは変わりません。

## ruby再インストール
あれこれしましたがopensslがうまいことインストールされてなさげなので

```
rbenv install 2.5.3
```
でrubyごと再インストール。
ここはご自身のバージョンに合わせてくだせぇ。

```
ruby -v
```
でバージョン確認。
変わってなかったら

```
rbenv local 2.5.3
```
で変更忘れずに。
そして

```
brew update && brew upgrade
```
んで

```
gem install bundler
```
私はこれで無事復活しました。
原因はおそらく使おうとしてたopensslのバージョンは`1.0.0`でインストールされてるのは`1.1.1d`だったことかなと。
ただremoveしてインストールし直してもコケたのでrubyインストール時に何かが失敗してたのかな…
rubyのバージョンアップはやだね…
Expoでオリジナルのベクターアイコンを使う

Expo、およびReact Nativeでベクターアイコンを使うためには、このようなパッケージが用意されています。

https://github.com/expo/vector-icons
https://github.com/oblador/react-native-vector-icons

```jsx
import React from 'react';
import { Ionicons } from '@expo/vector-icons'; // アイコンセットをimport

export default class IconExample extends React.Component {
  render() {
    return <Ionicons name="md-checkmark-circle" size={32} color="green" />;
  }
}
```

好みのアイコンセットをimportし、アイコンの名前などをpropsで指定します。

デフォルトで多くのアイコンが使用でき、一覧はこちらから確認できます。
https://oblador.github.io/react-native-vector-icons/
ただし気に入るアイコンが無い場合や、必要なアイコンのみ読み込みたい場合、あるいはデザイナーに指定されたものがある場合など、オリジナルでアイコンセットを作成したいシチュエーションもあるかと思います。
上記のパッケージでは内部的にはアイコンフォント化されたttfファイルを使用しているので、オリジナルのアイコンを使いたい場合はフォントファイルを用意すればWebと同じように使用できます。

# iconfontの生成

[icomoon](https://icomoon.io/)等をつかってもよいですが、SVGファイルから動的に作成できるようにしてみましょう。

### SVGファイルの用意

ディレクトリを作り、SVGファイルをまとめます。

```
.
└── icons
    ├── close.svg
    ├── arrow.svg
    ├── left-arrow.svg
    └── ...
```

SVGファイルの注意点として、

* アートボードのサイズはそこそこに（だいたい100 x 100くらい以上）  
  小さいと小数点以下が切り捨てられて歪なアイコンになってしまう場合があります。
* パスはアウトライン化し、交差の無い単純なパスにする
* 全てのアイコンがアートボードの縦サイズで合わせれるのを考慮してアイコンを配置  
  デザイン次第ですが、あらかじめソース側でサイズの指定が楽になるように考えておきましょう。

等。Webのナレッジと同様です。

### SVGからアイコンフォントファイルを生成

Expo/RNで使用するためにはアイコン名と文字コードを紐付けるデータが必要です。
フォントファイルと一緒に、お手軽にJSONファイルも出力してくれる`icon-font-generator`というパッケージを使用します。

```
$ npm install --dev icon-font-generator
```

コマンドラインから使用できるので、package.jsonにこのようにスクリプトを追加します。

```package.json
  "scripts": {
    "iconfont": "icon-font-generator icons/*.svg -o assets/fonts --jsonpath js/constants/iconfonts.json --css false --html false --types ttf",
  }
```

`assets/fonts`ディレクトリにアイコンフォントファイルが、
`js/constants`ディレクトリにアイコン名と文字コードを紐付けるJSONファイルが出力されるようにしました。
好みで場所を変更し、あらかじめディレクトリを作成した状態でコマンドを叩けばファイルが作成されるはずです。
アイコンを追加したタイミングで`npm run iconfont`でもいいと思いますが、使いやすいタイミングでrunするように設定します。

# Expoから使用する

`Icon`コンポーネントを作成します。

```javascript:js/components/Icon.js
import React from "react";
import { createIconSet } from "@expo/vector-icons";
import map from "../constants/iconfonts"; // 生成されたJSONファイル

// icon-font-generatorで生成されたJSONファイルをcreateIconSetに渡すために変換
const glyphMap = {};
Object.keys(map).forEach(key => {
  glyphMap[key] = parseInt(map[key].substring(1), 16);
});

const expoAssetId = require("../../assets/fonts/icons.ttf"); // アイコンファイルをExpoで読み込み

const Icon = createIconSet(glyphMap, "iconfont", expoAssetId);

export default Icon;
```

`icon-font-generator`で生成されたTTFファイルとJSONファイルとを読み込み、`@expo/vector-icons`の`createIconSet`に渡してReactコンポーネントを作成します。
生成されたJSONファイルはそのままではなく、文字コードの部分を数値に変換して使用します。

### 使ってみる

`name`には元のSVG画像のファイル名を指定し、あとは通常のアイコンセットと同じように使用できます。

```jsx:js/components/HeaderBackButton.jsx
import React from "react";
import Icon from "./Icon";
import { StyleSheet, TouchableWithoutFeedback } from "react-native";

const styles = StyleSheet.create({
  icon: {
    flex: 1,
    padding: 10,
    marginLeft: 6
  }
});

/**
 * 戻るボタン
 * @param {object} props
 * @returns {JSX}
 */
export default props => (
  <TouchableWithoutFeedback onPressIn={props.onBack}>
    <Icon
      name="left-arrow"
      style={styles.icon}
      color="#fff"
      size={24}
    />
  </TouchableWithoutFeedback>
);
```
Anypoint Studioで複数のアプリを同時に動かす

# はじめに
極小ネタです。
さっきAnypoint Studioを触っていてふと見つけたのですが、小ネタ感がなかなか良い感じなんじゃないかと思い、（仕事中ではありますが）さくっと書いてみました。
こんなもん一瞬で解決できるわ！仕事中に遊んでんじゃねえぞ！大事なアドベント１日分無駄にすんな！などといった素敵な反応が頂ければ幸いです。

#では
以下のような感じで、複数のアプリケーションを同時に開発している時に、例えば「demo_publisher」アプリを起動している状態で、「demo_subscriber1」を起動すると、警告ダイアログが出たのち、「demo_publisher」アプリを停止して「demo_subscriber1」が起動されます。

![コメント 2019-12-10 143414.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367531/d73f66e3-ab32-d09d-dde6-e00e917edc31.png)

![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367531/234fcb39-e372-afd7-75e3-d396f37ed3b9.jpeg)

つまり、普通に動かすとMuleアプリケーションは1つしか起動しないのです。でも、アプリケーションを同時に動かしたい時もあります。パブしたものはそのままサブしてもらいたいものです。いちいち「demo_publisher」アプリを停止して、「demo_subscriber1」アプリを起動するなんてやってられません。

**今回は、これを解決します。( ｀ー´)ノ**

1. メニューからRun > Run Configurations...を選択し、起動設定のダイアログを表示します。
![キャプチャ2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367531/7a25326b-c0e5-b4d4-7c3c-3285050a6aad.jpeg)

2. 起動設定ダイアログの左のツリーでMule Applicationsを右クリック > Newを選択します。
![キャプチャ3.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367531/356ebec9-8eb3-2c34-17da-42624cab5908.jpeg)

3. Nameに「all_mule_application」などと指定し、「Mule project to launch」で同時に起動したいアプリケーションをすべて選択し「Apply」します。
![キャプチャ4.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367531/f5cb20b2-3dca-9c17-e5d3-fd2023e69855.jpeg)

4. 「Run」ボタンで起動してみます。
![キャプチャ5.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367531/4c6167f1-4057-c38e-21b5-c7e902027f93.jpeg)

という感じで、複数のアプリケーションが同時に起動することができます。(^O^)／
【Django】 個人的よく使うコマンド、コードテンプレート、TDD 【メモ】

タイトル通り。
調べるよりメモしたほうが早いと思ったものを追加していく

# メモ(コマンド)

|コマンド|内容|
|:-:|:--:|
|python manage.py inspectdb [Table name]|既存DBのモデルを作成|


# メモ(プログラムテンプレート)

## url
ファイルの構造が
> prj
　-app
　　-views
　　　＿init＿.py
　　　sample1.py
　　　sample2.py

みたいになってる場合のコードなので注意(一応コメントアウトで追記してます)

```python:urls.py
from django.urls import path
# from . import views
from .views import  sample1, sample2

app_name = 'app'

urlpatterns = [
    # path('sample1', views.sample1, name='sample1'),
    # path('sample2', views.sample2, name='sample2')
    path('sample1', sample1.method_name, name='sample1'),
    path('sample2', sample2.method_name, name='sample2')
]
```


## Form

```python:forms.py
import re
from django import forms
from django.forms import RadioSelect
from django.core.exceptions import ValidationError


class DocumentForm(forms.Form):
    # ただの文字フィールド
    text_Field = forms.CharField()
    # 50文字以下
    # 必須項目でない(初期値は必須)
    # 必須項目でない(TextArea形式)
    text_Area = forms.CharField(max_length=50, required=False, widget=forms.Textarea)
    # 選択のタプル。(実際の値,表示の値)
    # ラジオボタンにする(もともとはプルダウン)
    # 初期の値(実際の値を指定する)
    radio_button= forms.fields.ChoiceField(
                        choices = (('1','value1'),('2','value2')),
                        widget=RadioSelect,
                        initial=2
                    )
    # ファイルフィールド
    file_field = forms.FileField()

    # ここで要素にクラスを追加したりする。HTMLの<input name="aaa" value=... />の部分に相当
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # text_Fieldのクラスにadd_classを追加する
        self.fields["text_Field"].widget.attrs['class']='add_class'

    # カスタムバリデーションを作る
    # clean_[フィールド名]で特定のフィールドのバリデーションを作成できる
    # バリデーションが通らなかったらraise ValidationErrorでエラーを出すといい。
    def clean_text_Field(self):
        text_Field = self.cleaned_data['text_Field']
        if re.fullmatch(r'^[a-z0-9-]+$',text_Field) == None:
            raise ValidationError("利用できない文字が使用されています")
        return text_Field


```


## Test

```python:tests.py
from django.contrib.auth.models import User
from django.test import TestCase, Client
from django.test.utils import override_settings

# クラス名はtestから始める必要がある。
# override_settings はテスト中、一時的にsettingsを上書きしてくれるデコレータ？ってやつらしい。
@override_settings(TEST=True)
class Test_example_View(TestCase):
    # クラス内のテストを行う関数すべての実行前に実行してくれる関数。
    # データを作ったり、同じ動作が必要な時はここに書くといい。
    def setUp(self):
        User.objects.create_user(username='tdd', email='test_account@aaa.bbb', password='test_pass') 
        self.client = Client()

    # テストを行う関数。最初にtestを入れる必要はない
    def test_redirect(self):
        response = self.client.get('/')
        # 正しい動作化を確認してくれる関数たち。いろいろあるので少しだけ載せる
        # 右辺が左辺と等しくなかった場合、右のエラーメッセージを表示する
        self.assertEqual(response.status_code, 302, "リダイレクトしませんでした。")
        # 右辺が左辺に含まれていない場合、右のエラーメッセージを表示する
        self.assertIn('data', response.context, "データが入っていません。")
        # 左辺がTrueでない場合、右のエラーメッセージを表示する
        self.assertTrue(response.context['flag'], "flagが正しくありません。")
```
PHPStan 0.12 でGenericsが使えるようになった

PHPStan 0.12 がリリースされていた。
https://medium.com/@ondrejmirtes/phpstan-0-12-released-f1a88036535d
和訳 https://www.phper.ninja/entry/2019/12/06/032456

ただし、ここで気軽にcomposer updateしてしまうと、大量のエラーに遭遇することになる。（設定レベルにもよるが）
PHPStan 0.12 ではレベルが一つ増えているが、以前の最大値7の次の8が追加されたのではなく、6が追加されて 6 と 7 が 7 と 8 にずれた。
つまり以前の「nullable型のメソッド呼び出しとプロパティアクセスを報告」のレベルを保持するためには 新しく追加された「6: 欠落した型ヒント」を先に全て満たす必要がある。

今までタイプヒント無しで逃げていた部分や`array`、`stdClass`でお茶を濁していた部分も正確に指定する必要があるようだ。

それを乗り越えると（別に乗り越えなくてもGenericsは使えるが）、例えば[以前書いた](https://qiita.com/nishimura/items/42ecba8f90c12b13e721#プロパティをインターフェースとメソッドに置き換える)プログラムは


```php:Type/HasValue.php
<?php
namespace MyProject\Type;
/**
 * @template T
 */
interface HasValue {
    /** @return ?T */
    public function getValue();
}
```

```php:Input/Value.php
<?php
namespace MyProject\Input;
use MyProject\Type;

/**
 * @template T
 * @implements Type\HasValue<T>
 */
abstract class Value implements Type\HasValue {
    /** @var string */
    public $name;
    /** @var ?string */
    public $input;
    /** @var ?T */
    protected $value;

    public function __construct(string $name)
    {
        $this->name = $name;
        $this->input = $_REQUEST[$name] ?: null;

        if ($this->input !== null)
            $this->convert($this->input);
    }
    /** @return void */
    abstract protected function convert(string $input);
    /** @return ?T */
    public function getValue(){ return $this->value; }
}
```

```php:Input/IntValue.php
<?php
namespace MyProject\Input;

/**
 * @extends Value<int>
 */
class IntValue extends Value {
    protected function convert(string $input){
        if (preg_match('/[0-9]+$/', $input))
            $this->value = (int)$input;
    }

    public function getValue(): ?int { return $this->value; }
}
```

こんな感じで正しく型コメントを書ける。
前は型を書くために`protected`にも関わらずスーパークラスとサブクラスの両方に

```php
class IntValue extends Value {
    /** @var ?int */
    protected $value;
```

と書いていた不要なプロパティが無くなって型と構造が正しくなった。


PHP7.4も出たし、しっかり書く派のPHPプログラムは作り方が全然変わってくるのかもしれないな。
[HTMLでの変数にも型が欲しい](https://qiita.com/nishimura/items/bfabfb137abe42e62c39)し、何かもうあと一歩という感じがする。



（追記: 2019-12-11）
試しに、4万行ほどの使いたいプロジェクトで 0.12 にバージョンアップしてみると、エラーが 0 件から 1613 件に…。
ちょっと心折れそうではある。
DBから取得したデータとか、`json_decode`とか、テンプレートで使う変数のひとまとまりだとか、フォームリクエスト変数とか、IO境界がつらい。
特に`json_decode`で取得した`stdClass`がつらい。`mixed`で逃げてもいいけど、せっかくなので全ての型を書きたいところ…。
備忘録 仕事用MACのWi-Fi設定に登録してあるSSID

仕事用MACのWi-Fiで接続するSSID
![スクリーンショット 2019-12-10 14.49.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373685/513a04a6-8482-b56a-16f9-add82229eada.png)
vue-cli+TypeScriptな環境でTSLintからESLintに移行する方法

この記事は [ZOZOテクノロジーズ #5 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/zozo_tech5) 11日目の記事です。
昨日は @gold-kou さんによる [NLB配下でgRPC通信するときに考えるALPN対応状況](https://qiita.com/gold-kou/items/6aa87c1c09d38b79881a)でした。

# 背景
プロジェクトで使っていたTSLintはロードマップに基づき年内でセキュリティパッチ以外の更新は終了し、今後は `@typescript-eslint/parser` を推奨！とのことで隙を見て移行してみました。 

TSLintの開発ロードマップ：https://github.com/palantir/tslint/issues/4534
typescript-eslintの今後：https://eslint.org/blog/2019/01/future-typescript-eslint

# 環境
関連するPackageは以下の通りです。formatterにprettierを使っていました。

```json:package.json（一部抜粋）
{
...
  "dependencies": {
    "vue": "^2.6.10",
    ...
  },
  "devDependencies": {
    ...
    "@vue/cli-service": "^3.8.0",
    "prettier": "^1.19.1",
    "tslint-config-prettier": "^1.18.0",
    "tslint-plugin-prettier": "^2.0.1",
    "typescript": "^3.4.3",
    ...
  }
}
```

# やったこと

## ESLintの追加
まずはESLintのvue-cil用プラグインを追加。
起動時にオプション指定で色々できるようですが今回は指定なしでインストール。
https://www.npmjs.com/package/@vue/cli-plugin-eslint

```
vue add @vue/cli-plugin-eslint
```
インストール後のコンフィグ設定。元々使っていた `Prettier` を継続利用。

```
? Pick an ESLint config: 
  Error prevention only 
  Airbnb 
  Standard 
❯ Prettier 
```

Lintの実行タイミングを設定します。

```
? Pick additional lint features: (Press <space> to select, <a> to toggle all, <i> to invert selection)
❯◉ Lint on save
 ◯ Lint and fix on commit
```

これで `@vue/cli-plugin-eslint` の追加は完了です。
`npm run lint` を実行するとESLintが走ります。

## .eslintrc.ymlの追加
`@vue/cli-plugin-eslint` を追加すると、 `.eslintrc.js`が自動作成されます。デフォルトのままでも使えますがプロジェクトの事情に応じた`rules`等を設定していきます。この辺の手順は他の記事にも詳しいものが色々あるので詳細は割愛します。それとこれは好みの問題ですが、ymlの方がメンテナンスしやすいと考えているためjsで生成されたものをymlに書き換えました。

```yml:.eslintrc.yml
env:
  browser: true
  es6: true
extends:
  - 'eslint:recommended'
  - 'plugin:vue/essential'
  - 'plugin:@typescript-eslint/eslint-recommended'
  - "plugin:prettier/recommended"
globals:
  Atomics: readonly
  SharedArrayBuffer: readonly
parserOptions:
  ecmaVersion: 2018
  parser: '@typescript-eslint/parser'
  sourceType: module
plugins:
  - vue
  - '@typescript-eslint'
  - 'prettier'
rules:
  no-unused-vars: 0
  no-case-declarations: 0
```

## .eslintignoreの追加
お好みで `/.eslintignore`ファイルを作成し、Lintを無視するファイルを定義しておくと便利かもしれません。例えば今回は `openapi` を用いたプロジェクトだったので `openapi-generator` で生成されたコードは無視するよう設定しました。

```:.eslintignore
src/adapters/backendAPI/openapi-generated/**
```

##TSLintの削除
不要なパッケージ、ファイルを削除していきましょう。

- `/tslint.json` を削除。お疲れっした！
-  `/package.json` からtslint関連のパッケージを削除。

```json:この辺を削除する
{
    "tslint-config-prettier": "^1.18.0", 
    "tslint-plugin-prettier": "^2.0.1",
}
```
以上で設定は完了です！これで安心して年が越せますね！

明日は @saitoryuji さんが記事を書いてくれます！乞うご期待！
pythonしぐさを学ぶ

前回の記事でVisual StudioやFortranを使ったことがあると書いたが、rufiyaaはこれまでにもちょっとだけプログラミングをかじっている。仕事でもVBAを使うのが結構好きで、手の込んだ自動化を組んでは軽微な変更で使い物にならなくなるといったことを繰り返したりしている。

つまり、プログラムやアルゴリズムといった基本的な部分はおおよそ理解している。そうなると、pythonの世界を自由に歩き回るためにあと必要なのは、pythonでの表現方法＝pythonしぐさである。
このpythonしぐさを学ぶために、とびきり簡単な問題を解けばいい。ということに気づいた。

今回用いたのは[paiza](https://paiza.jp/)。paizaは転職サービスらしく、転職勧誘が若干うるさいが、「スキルチェック」というコーナーに大量の問題がレベル別に用意されている。

paizaの問題は、標準入力で与えられる数字や文字列を使った処理を記載し、求められたスタイルの回答をprint()関数を使って表示することができれば合格となる。pythonでの文字列や数値の扱い、プロパティ？とかそういった部分をバリバリ検索しながら問題を解いていった。

なお標準入力をうまく変数に落とし込む部分が難しいが、このへんを使いながら練習を進めた。
[python3 での標準入力 まとめ　(競プロ用)](https://qiita.com/pyu666/items/6b8cfefc1ea994639683)

Dランクの問題は本当に簡単な問題で、基本の文字列操作や計算といった感じ。Cランクの問題でも数行の記述で何とかなった。Bランクともなると制限時間も1～3時間の問題が出てくるようになり、アルゴリズムの能力という点でうまく解けない問題が出てきたので、pythonしぐさが十分に身についたと判断し、paizaによる練習を終えた（自動車教習所が完全な運転能力を身に着ける場所ではなく、一人で運転を練習できるレベルにする場所という話に似ている）


今日はここまで。
非破壊編集でなるべく手間を減らしたい話

こんにちは、プログラミングのことはわからないk_azmです。
紆余曲折あり、webデザイナーをしています。

業務としてデザインをしている上で必ず発生するのが、「クライアントからの修正要望」です。
出来るだけ工数をかけずに修正作業を行うために使っているphotoshopの機能を少しご紹介します。
もう知っている方が大多数だとは思いますが……

##「非破壊編集」について
非破壊編集とは、元の画像データの上書きをせずに画像を変更することです。
つまり…　修正を繰り返したデータも、すぐに元に戻すことができるものです。

「やっぱり前の画像の色味に戻して」「小さくした写真、やっぱり大きくして」クライアントからの要望で意外とよくあるものです。
非破壊編集を行っていないと、元の画像データをローカルから探してきて、再度色調補正をやり直したり…画像を縮小し直したり…ととても手間になります。いくつも過去のpsdを残しておくと、だんだんPCのストレージを圧迫していきます。
「非破壊編集」を意識してデータを作成しておけば、その手間が格段に少なくなります。


ではこの「非破壊編集」ですが、具体的にどのような方法があるのかというと…

###①スマートオブジェクト
本来、画像は小さくしたものを、再度大きくするとボケて汚くなってしまいます。
![img01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533082/f03e1197-82b6-fa45-c90d-88ac0befdf29.png)
**「レイヤーをスマートオブジェクト化」**
こちらを行うと、元の画像のデータは保たれたまま、psd上で何度も拡大縮小したり、変形できます！
![img02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533082/783bed26-e67c-3ec4-aac9-d0688cc7bc47.png)
方法は、スマートオブジェクト化したいレイヤーを右クリックして「スマートオブジェクト化」するだけです。
スマートオブジェクトになったレイヤーを直接編集したい場合は、サムネイル部分をダブルクリックすると別ウィンドウで編集画面が現れます。


###②色調補正フィルター
色調補正フィルターは、画像の色味や明るさなどを調整することができます。
![img03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533082/3a9fbc8a-29f5-c997-57f1-18f3bc7338ad.png)

Ctrl（MacはCommand）＋Alt＋Gでクリッピングすることで、直下のレイヤーにだけ適用することができます。
写真やイラストの微妙な色調整はリテイクが発生しやすい箇所なので、調整だけ出来ると便利です。
![img04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533082/18c0db30-e691-e8b4-913b-79fde3f49e80.png)
イエベのサンタになってしまいました


###③フレーム
いわゆる「マスク」のようなものですが、より使いやすいと思います。
図形ツールのようにドラッグで作成し、その範囲に入れたい画像をドラッグ＆ドロップします。
（または、フレームをつけたい画像レイヤー上でドラッグをします）
![img05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533082/a7d43f10-ca7c-fd7e-8a71-6045ecd3f27d.png)
フレーム（枠）はそのままで、中に入れる画像を何度も差替えできます。
特に気に入っているところが、新しい画像をドラッグ＆ドロップした時に、自動的にリサイズされてピタッ…とはまるところです。もちろん画像のみを拡大縮小して見える範囲の調整をすることも可能です。


フレーム自体のサイズを属性パネルで微調整できるのも便利です。
![img06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533082/31e4da26-30fc-d588-15dc-d92b895c968e.png)

元となる図形ツールに画像をクリッピングしていくよりも、よりレイヤーとしての役割がわかりやすいのかなと思います。
![img07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533082/ec65a93e-04ae-a235-04c8-9cb964ef05a2.png)
※従来のイメージ
別にこれがダメとかではないとは思うのですが:thinking:


##どんな時に「非破壊編集」だと便利か
###PCサイトデザインを元にスマートフォン用のデザインを作るとき
一般的にスマホ版デザインのほうがPC版デザインよりも画像サイズが大きいので、バナーやメインビジュアル等をあらかじめスマートオブジェクト化しておくと、再度作り直す手間が少なくなります。


###レイヤー内検索機能
「画像レイヤー」「調整フィルター」「フォント」「シェイプレイヤー」「スマートオブジェクト」で絞り込んで検索するため、調整フィルターやスマートオブジェクト化しておくことで目的のレイヤーを探しやすくなります。
少し話は逸れますが、レイヤーはその役割がわかりやすいほど、データを第三者に受け渡す時などにトラブルも生じにくいと思います。


##「非破壊編集」の弱点
なんでもかんでも元に戻せるようにスマートオブジェクト化していると、
**ファイルサイズが肥大化します。**
気づけば数百MBのpsdが出来上がっていることも……。
やりすぎには注意しましょう。

##まとめ
もちろん、「非破壊編集」の機能は他にもあります！良ければ調べてみてください。
デザイン業務は、構想や要素の組立てに重きを置いて作業したいものです。
テクニックで時短できるものは、なるべくしていきたいなと思います。
まだまだ勉強中です。

##明日は
「North Detail Advent Calendar」 13日目は @_shun_sato_ さんです！:clap:
API Connectの開発者ツールキットでAPI情報を取得

## はじめに
API管理とAPI作成から公開までのチームが分かれている・権限をそれぞれ分けたいなどといった背景を元に、ローカル環境で作成したAPI製品を、開発者ツールキット経由でカタログに対してAPI製品を公開することがあります。開発者ツールキットについては[こちら](https://qiita.com/rinaxsumomo/items/48836a9633d2f79efab5)にも書いています。

このときAPI Manager上のAPI製品ドラフト一覧には開発者ツールキットからステージングしたAPIがリストされません。が、その開発者ツールキットが入ったローカル環境が壊れたーとか、開発者メンバーが消えたーとか、、そんな状況で（APIとして公開はされてるけど）APIの元ネタであるyamlファイル自体が消えてしまった、なんて状況も実はありえます（そもそもyamlをgitなどで管理すべきというのは勿論なのですが、それをしてないところもあるのです・・・）。そんなときにも開発者ツールキットを使うとAPI Manager上に公開されているAPI製品を再度ダウンロードすることができます。プロバイダ組織所有者権限ユーザーが必要です。

今回はAPI情報を取得・ダウンロードする前にCLIでAPI Connectにログインする必要があるのですが、そこでつまづいたので備忘録です。

## 前提条件
- IBM CloudでAPI Connectのインスタンス作成済み
- apiconnectコマンド（開発者ツールキット）がローカル環境に導入済み
  - 前提条件とか導入方法の参考は[こちら](https://qiita.com/Naomi_Tanaka/items/4853e220e8e99197dbed)
- IBM CloudのIAMでAPI Keyを作成済み
- 私の環境の場合
  - Node.js: v10.17.0
  - apiconnect: v5.0.8.7 (apiconnect: v5.0.25)

## 手順
1. IBM Cloudにログインして、自分のAPI Connectインスタンスのカタログを確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129662/9cc31231-450b-b9af-00ee-7db991003413.png)


2. カタログのリンクマーク![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129662/61ad2949-936a-c94d-f97a-9bb44eb9ff99.png)
をクリック
3. コマンドやURLなど記載を確認

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129662/b545065c-9e7a-7a71-e751-a1cceac9bb3e.png)


４. apicコマンドを実行

  コマンドラインでログインする前に、IBM Cloud上にあるAPI Connectの組織やカタログ情報をローカルにセットします。上記のカタログのリンクの文字列をそのまま実行できます。

  ```
  apic config:set catalog=apic-catalog://us.apiconnect.ibmcloud.com/orgs/自分の組織名/catalogs/自分のカタログ名
  ```
  上記の構成設定が終わったら、IAMのAPIKEYを使ってログインできます。試してないですが、シングルサインオン・オプション（--sso)など他のログイン方法でも可能と思います。

  ```
  apic login -k APIKEY

  us.apiconnect.ibmcloud.com に正常にログインしました
  ```
  API情報が以下のように取得できます。API Connectのサーバー名や組織やカタログ情報はすでにローカルに構成されているので、オプションには不要でした。

  ```
  apic apis:get API名:バージョン

  例：
  apic apis:get backend:1.0.0

  名前: backend
　バージョン: 1.0.0
　タイトル: Backend
　基本パス: /backend
　状況: オンライン
　実動エンドポイント: "https://api.us-south.apiconnect.appdomain.cloud/自分の組織名/カタログ名/backend"
　開発エンドポイント: "https://api.us-south.apiconnect.appdomain.cloud/自分の組織名/カタログ名/backend"
　製品: 自分の製品名:1.0.0
　カタログ: カタログ名
　組織: 自分の組織名
  ```
  APIをダウンロードするには以下のコマンドを実行すると、apicコマンドを実行したディレクトリにyamlファイルがダウンロードされています。

  ```
  apic apis:pull API名:バージョン

  例：
  apic apis:pull backend:1.0.0

  backend:1.0.0 API 定義が 自分の組織名:カタログ名 [backend_1.0.0.yaml] からプルされました
  ```

## 終わりに
上記のように開発者ツールキットのコマンドを使うと、API Connect上に公開されているAPI情報の取得、yamlファイルのダウンロードができることがわかりました。今回はクラウド版nAPI Connectで実行していますが、オンプレでも同様に可能です。オンプレはAPIKEYによるログインではなく、従来のユーザー・パスワードで認証することになると思われます。
またAPI Connect v2018だと方法が変わる可能性があるので、今回の検証はV5ベースのクラウド版が対象であることにご留意ください。

## 参考情報
- https://www.ibm.com/support/knowledgecenter/en/SSFS6T/com.ibm.apic.toolkit.doc/tutorial_cli_project_stage_command.html
ファイル整理してたらログインできなくなった話　Ubuntu18.04.3（ログインループ）


#パソコンを再起動したらログインできなくなった

Ubuntu 18.04でログインループにハマったときの話です。
仮定の原因しか突き止めることができなかったんですが一応ここで書いておきたいと思います。


#原因
そもそも何が原因だったのか考えていきたいと思います。

多く見られるログインループの原因では以下のようなものが考えられます。

- カーネルのアップデートに失敗していろいろなバージョンが混ざってしまった
- NVIDIAのドライバのバージョン不整合
- ディスクの容量不足でGUIが立ち上がらない
- 重要なファイルを削除してしまってGUIにログインできない

などでした。

とりあえずログインループの問題で出てきた解決策を片っ端から試しました。

結果的にたどり着いたので重要なファイルを消してしまったことが原因だったと思っています。

#試した解決方法

まずなにが原因なのかを突き止めるために色々検索して調べました。
そこでドライバーのバージョンを更新してないなど情報が多くありました。

しかし、今回の場合はドライバをいじってもいないし、バージョンも古くなかったのでこれではありませんでした。

次に考えたのは容量の圧迫が原因でGUIが開かなかったことです。

そこで容量を開けるためにログイン画面からCUIを使って容量を調べました。

```
Ctrl+Alt+f1
```
これでCUIを使いました。

ログイン画面に戻りたいときは

```
Ctrl+Alt+f7
```

OSによって違いますが基本的にF1-F7を押せば終了できるかと思います。

そして以下のコマンドで状況を参照しました。

```
df -m
```

しかし。何を意味しているのか全くわからずどのファイルを消せば容量に余裕が出るかわからず。。。
とりあえずどのデータが圧迫していたかも確認しました。

```
du -h --max-depth=1 /
```

その結果、自分がいらないと思ったデータを消していきました。
例えばダウンロードしたインストーラーやその他の不要な画像から資料などです。

消し方はrmコマンドを使いました。
僕が使ったのは

```
rm -r
rm -rf
```
です。

しかしこれでも直らず完全に詰んだなーっと思っていました。

他にも色々な記事を見ながら試しましたが原因がその時わからなかったためどれも解決には至りませんでした。

そして最後に試したのがGUIのアップデートで失敗して解決した記事を見つけてそれを参考にコマンドを実行したら解決しました。


>
リカバリーモードでログイン
"root" でコマンドラインを開く
Xorgの再インストール

の一連のコマンドを実行しました。


uninstall

```
apt-get purge xorg "xserver-*"
apt-get purge lightdm plymouth
rm -rf /etc/X11/xorg
apt-get autoremove
```
install

```
apt-get install xauth xorg openbox lightdm plymouth
apt-get install ubuntu-desktop
reboot
```

https://qiita.com/irna_k4t/items/62cf37c9edcdfd62633a

ここに書いてあることを参考にそのまま実行したら解決しました。


#反省点
そもそもHDDの容量が圧迫しており更新なども滞っていたのが良くなかったんです。。。

容量を開けるために自分の見たことがあり不要なファイルを片っ端から消すことで容量を空けようとしました。

それでどこかの設定ファイルを消してしまったのかもしれません。。。

日頃からパソコンの中は整理しておいたほうがトラブルに合った時に対処しやすいです。



#参考

http://learnprogra.com/2019/07/17/ubuntu-login/
https://qiita.com/irna_k4t/items/62cf37c9edcdfd62633a
async/awaitで非同期処理させた結果を返り値としてreturnしたい

# async/awaitで非同期処理させた結果を返り値としてreturnしたい

※全力で省略して書きます

↓↓↓ こんな感じでできる ↓↓↓

```javascript
// 呼び出し元関数
async doUpdate() {
   const res = await this.apiSubmit()
   console.log(res) // 非同期処理の結果が欲しい
}
// 非同期側
async apiSubmit() {
  return await axios.post(url, data)
    .then(response => {
      // 成功時の処理etc
      return response
    })
    .catch(error => {
      // 失敗時の処理etc
      return error
    })
}
```

### ことのはじまり
Vuexのactionsでaxiosの返り値をコンポーネントの呼び出し元メソッドに返却して処理をしたかった。
しかし、呼び出し元メソッドにasync/awaitを指定しなかったためにPromisだけ返却されて困った。

更に、then/catchを使いたかったが
`await axios.post(url, data).then(response =>{return response})`
としても`undefined`が返却されてしまった。

## 要点
- async/awaitは呼び出し元の親関数も指定しないと非同期処理よりも先に親関数が終了してしまう
- thenやcatchを使った場合はthenの中でもreturnしないとundefinedになる（あたりまえ）
WordPressでビジュアルエディタに切り替えができない

WordPressを5.3にしたのですが、
記事エディタが大きく変わりました。
とっつきツラい上に、なぜかHTML記述しか受付けてくれいない状況になって、
困っていたのですが、ビジュアルエディタへの変更ボタンの出し方が分かりました。

## CloudFront の設定を修正する必要がある

WordPressは、ビジュアルエディタが使用可能な環境かの判定を
HTTP ヘッダの User-Agent を元に行っています。
しかし、CloudFront は設定をしておかないと User-Agent を削除してしまうらしいです。

それでは、CloudFrontを使っていても、User-Agentが削除されないように設定をしていきましょう！

CloudFrontを開き、今回修正したいサイトに設定されているDistributionsを選択します。

タブを **Behaviors** に切り替えたら、
path-Pattern : /wp-admin/* の設定で、
「Forward Headers：whitelist」にして、
「Whitelist Headers」に「User-agent」を登録します。

Whitelist Headersの候補欄には、User-agentは元からは入っていないため、
テキストボックスに、**User-agent** と入れて、「Add Custom >>」ボタンをクリックして、追加します。

<img width="939" alt="スクリーンショット_2019-12-10_14_14_32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8222/7f37dda1-6467-4b58-7d94-c84ff1416173.png">

登録が出来たら、保存をします。
保存をしたら、しばらく更新中の状態になりますので、待ちます…

更新が終わったら、編集ページを再読み込みして、縦の点々ボタンをタップしてメニューを表示すると、ビジュアルエディタが出ていました！
<img width="424" alt="スクリーンショット_2019-12-08_19_23_45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8222/45b6863b-42cd-a85a-a02c-9451d53e57ee.png">


参考サイト：
https://jyo-to.okinawa/20170520/1092/
PythonでCSVファイル触ってみた

## はじめに

今まで業務でPythonを扱ったことは無かったのですが、Pythonを使うことで色々と業務を効率化できると聞いたので、とても簡単ではありますが試しにどんなもんか触ってみました。
今回は特に実業務でもよく扱うCSVファイルの操作に絞って試してみました。
（異常系の考慮等は省いています）


今回用いたCSVファイルはこちら。

```
Apple,100,1
Orange,120,4
Banana,80,2
Apple,100,2
```
左から、商品、金額、個数の順となっています。

## CSVファイルの読み込み

それでは早速CSVファイルを読み込んでみます。

```
import csv

with open('purchase.csv') as f:
    print(f.read())
    
# Apple,100,1
# Orange,120,4
# Banana,80,2
# Apple,100,2
```

たった2行で書けました。
結果はファイルの中身がそのまま出力されています。

#### CSVモジュール

csvモジュールはPythonの標準ライブラリに含まれているため、インポートを追加すれば使えるようになります。

#### with構文

with構文はファイル操作に便利です。close処理が省略できます。


## forループさせてみる

とりあえず回してみる。

```
import csv

with open('purchase.csv') as f:
    reader = csv.reader(f)
    for row in reader:
        print(row)
        
# ['Apple', '100', '1']
# ['Orange', '120', '4']
# ['Banana', '80', '2']
# ['Apple', '100', '2']
```

行ごとの要素がリストとして出力されました。

#### csv.reader

CSVを読み込む際は`reader`を使う。`reader`を回すことでリストが取得できる。

## 要素の中身を取り出してみる
要素を取り出す場合は`row`のindexを指定してやれば良さそう。

```
import csv

with open('purchase.csv') as f:
    reader = csv.reader(f)
    for row in reader:
        print('商品:' + row[0] + ' ' + '値段:' + row[1] + ' ' + '個数:' + row[2])
        
# 商品:Apple 値段:100 個数:1
# 商品:Orange 値段:120 個数:4
# 商品:Banana 値段:80 個数:2
# 商品:Apple 値段:100 個数:2
```

各要素毎の出力できました。

## 合計金額を計算してみる
forループの中で金額の計算を行い、最後に合計金額を出力するように変えてみました。

```
import csv

with open('purchase.csv') as f:
    reader = csv.reader(f)
    amount = 0
    for row in reader:
        amount += int(row[1]) * int(row[2])
        print(amount)
print(amount)

# 100
# 580
# 740
# 940
# 合計金額：940円
```
ちゃんと合計金額が出力されました。

※ 最初の`print(amount)`は動作確認用です。

## CSVファイルへの書き込み
今度は逆にCSVファイルに対して書き込みを行なってみたいと思います。

```
import csv

with open('purchase.csv', 'w', newline='') as f:
    writer = csv.writer(f)
    writer.writerow(['Grape',150,1])
    
# Grape,150,1
```

無事書き込めました・・・って全部消えてしまってる！？
既存ファイルに追記する場合は引数に`w`ではなく`a`を指定するようです。

```
import csv

with open('purchase.csv', 'a', newline='') as f: #追加
    writer = csv.writer(f)
    writer.writerow(['Grape',150,1])
    
# Apple,100,1
# Orange,120,4
# Banana,80,2
# Apple,100,2
# Grape,150,1
```

これで追加することが出来ました。

#### csv.writer
csvに書き込む際は`writer`を使う。書き込みには上書きと追加がある。

#### newline
改行コードが`\r\n`である環境では`open()`の引数`newline`を`''`として明記しておいた方が安全らしい。

## 最後に
今回は簡単ではありますが、CSVファイルの基本的な読み書きについて触れてみました。Pythonで出来ることは他にも山ほどあるので、これを機に色々試してみたいなと思いました。
Django Admin フォームの並び替えを行う

# 前提
* DJango 2.2 (ドキュメントではDjango1.1からサポート)
* Python3.6

# コード
変更先はアプリケーション内のadmin.py。
*ModelAdmin.fields* に対してオーダリングを記述すればよい。

```python:admin.py
@admin.register(Samples)
class SamplesAdmin(admin.ModelAdmin):
    form = froms.SamplesForm
    fields = (
        'name',
        'age',
        'qiita_urls',
        'memo',
    )
        
```

# 参考
[The Django admin site](https://docs.djangoproject.com/en/2.2/ref/contrib/admin/)