OmniAICreator/Qiita-1.07M huggingface dataset:
【JavaScript】道路標識を簡単に、見つけることができるアプリを、作りました。



私は、家の近所を散歩をすることが趣味です。
そこで、とある疑問が出てきました。

道路の標識って、たくさんあるけど、
パッと見でなんとなくの、
感覚でしか意味わかってないよなと。

ということで、簡単に道路標識の意味を、
サッと理解できる、アプリを作りました。

アプリはこちら
https://orb.main.jp/app/roadsign/

GitHubはこちら
https://github.com/fujioka8700/roadsign

# このアプリを作って、解決したかったこと。

私が、このアプリで解決したかったことは、この2つです。

1.できるだけ、目当ての標識を、早く見つけたい。
2.アプリには、標識を大きく表示したい。

# なぜ、この2つのことを、解決したかったのか。
## 1.できるだけ、目当ての標識を、早く見つけたい。

みなさんもご存じの通り、
標識には似たものが、たくさんあります。
似たものがたくさんあるので、
「あれ？この意味であってたっけ？」となります。
かつ、誤った理解をしていると、非常に危険です。

![similar_signs.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/968572/fac9b7f7-f1f8-62d8-4a22-88246a5d03bd.png)


## 2.アプリには、標識を大きく表示したい。

インターネットで検索すれば、
標識一覧はたくさん、出てくるのですが、
どれも、画像一枚に、標識がびっしり。
ただでさえ、似たものが多い標識なのに、
びっしりある標識の中から、
目当ての標識を見つけるのは、大変だなと思いました。

![list_signs.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/968572/913d524f-e5ba-9e44-4948-32dace12b787.png)

# 標識の見た目の特徴で、まとめました。

目当ての標識を見つけるためには、
標識の見た目の特徴で、まとめた方が、
探しやすいよな、と思いました。
なので、赤の丸い標識や、青い四角と矢印の標識など、
見た目が、似ているものでまとめて、
できるだけ、探しやすくしました。

![feature_list.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/968572/05a678d6-8c52-4ada-dab1-02a8ddb6b88c.gif)

# 標識の表示が大きいから、すぐに見つけることができる。

先ほども言いましたが、一枚の画像にびっしり
書かれた標識から、目当ての標識を探すのは大変です。
なのでこのアプリでは、標識ひとつひとつを、
大きく表示し、標識を見やすくしました。
そして、見つけやすくしました。

![motion.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/968572/c2461ed9-3887-da1a-1be4-14c2f86525bd.gif)

# まとめ

実際に散歩中に、安全な場所に移動してから、
このアプリを使ってみました。
今までは、標識の特徴を文字で入力して、
検索して、探し回っていましたが、
このアプリを使うと、すぐに目当ての標識を
見つけることができました。

解決したいと思っていた2つの事は、
無事に解決することができました。

これからも、世の中の不満や、疑問など
少しでも解決できるようなアプリを、開発していきます。
List系APIの取得数上限とPaginator

# はじめに
「ファイル一覧、job一覧などを取得して何かしたい」というのはちょっとしたスクリプトからシステム開発までよく出くわす場面です。
そして、そういったもののためにweb serviceにはList系APIが実装されていることが一般的です。

そのようなList系APIはレスポンスが巨大になりがちなため、 **取得数に上限が設けられることが一般的** であり、 **この取得上限に注意しながら実装を進める必要があります。**
その一方で、ライブラリによってはPaginatorという、 **取得数上限を考慮せずに済むような仕組み** が準備されているものがあります。

本記事では、[aws s3 ListObjectsV2 API](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectsV2.html) を例にとり、 取得数上限を考慮した実装と、Paginatorの説明をします。

推奨の方法をいち早く確認したい場合は、 [Paginatorを利用する方法](#paginator%E3%82%92%E5%88%A9%E7%94%A8%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95) を参照ください。
また、本記事では python + boto3 を利用します。

# List APIの仕様と、取得数上限を考慮したコーディング
[aws s3 ListObjectsV2 API](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectsV2.html) の説明にはこのような記載があります：

> Returns some or all (up to 1,000) of the objects in a bucket with each request.
（バケット内のobjectの一部またはすべて（1,000個まで）を返します。）

このようなページ分割された（Paginated）情報を送ってくるAPIを利用してすべてのobjectを取得するには何らかの工夫が必要です。
そして、勿論この為の仕組みが準備されており、URI Request ParametersとResponse Elementsに以下のような記述を発見します：

> **URI Request Parameters::continuation-token**
> （意訳： `ContinuationToken` は、トークンを利用することでリストがまだ続いていることをAmazon S3に示します。 
> `ContinuationToken` は難読化されており、実際のキーではありません。）

<!-- -->

> **Response Elements::NextContinuationToken**
> （意訳： `NextContinuationToken` は、Response Elementsである `isTruncated` が `true` のときに送られます。これは、bucketにまだリストできるobjectが存在することを示しています。
> Amazon S3への次のリストのリクエストは、この `NextContinuationToken` で続行できます。
> `NextContinuationToken` は難読化されており、実際のキーではありません。）

...というわけで、 `NextContinuationToken` が得られた場合は再度 `continuation-token` に `NextContinuationToken` の値を仕込んでリクエストを投げればよい、ということになります。

## code

```python
import boto3

boto3.setup_default_session(profile_name='default')
client = boto3.client('s3')
bucket = 'some-bucket-name'

def paginate_list_objects_v2(**kwargs):
    payload = kwargs
    while 1:
        response = client.list_objects_v2(**payload)
        yield response
        if not response.get('IsTruncated'):
            return
        payload['ContinuationToken'] = response['NextContinuationToken']

payload = {
    'Bucket': bucket,
}
for response in paginate_list_objects_v2(**payload):
    print(response.get('Contents'))
```


# Paginatorを利用する方法
上記のようなコードを書けばすべてのobjectが取得できますが、面倒と言えば面倒ですよね。
そこで、boto3には[Paginator](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#id223)と呼ばれる仕組みが存在しています。
ページ分割周りを全部巻き取ってくれるため、コードがとても簡潔になります。

## code
```python
import boto3

boto3.setup_default_session(profile_name='default')
client = boto3.client('s3')
bucket = 'some-bucket-name'

payload = {
    'Bucket': bucket,
}
for response in client.get_paginator('list_objects_v2').paginate(**payload):
    print(response.get('Contents'))
```

`ContinuationToken` 周りを考慮せずに済み、とても簡潔に書くことができました。

# まとめ
ページ分割された（Paginated）情報を送ってくるAPIを利用してすべての情報を取得する方法を、コードベタ書きとPaginatorを利用した場合との2種類で説明しました。
Paginatorを利用すれば簡潔に書けるためおすすめですが、必ずしもライブラリにPaginatorが存在するとは限らないため、いつでもベタ書きで書けるように準備しておきましょう。
Dockerコンテナ内でホストと同じユーザで作業（sudoコマンド有り）

## 目的

ホストのUID/GIDで作業可能なsudo付きDockerコンテナを**Dockerfileを作成せず、かつ出来るだけ制約の少ない方法**で立ち上げる。

## 背景

Dockerコンテナを開発環境として使っていると、デフォルトがrootユーザなせいで、ファイルのownerの問題にぶち当たる。

よくあるパターンが、ディレクトリをマウントして作成したファイルのownerがrootになってて、がホスト側から編集出来ない、とかいうケース。

Dockerコンテナを開発環境に使ってると、よくこのパターンにハマり、ownerを変更するためだけにコンテナを起動したりすることも...。

回避方法として`-u $(id -u):$(id -g)`のオプションを付ける方法あるが、これだけではホスト側のユーザIDと一致しなかったり、`sudo`が使えなかったりと困ることも多い。

じゃあ、`sudo`インストールしたり`useradd`したりする`Dockerfile`を作るというのもあるが、いちいちpullしてきたイメージに対してそれをやるのも面倒。

というわけで、できるだけ簡単にホストユーザのsudo付きDockerコンテナを立ち上げるコマンドの紹介。

## 方法

UbuntuとCentOSで若干違うので分けて記載。

### Ubuntu

コンテナ名は適当に`test-user-with-sudo`とでもしときます。

```sh
CNAME=test-user-with-sudo
```

まずは、コンテナ起動。

```sh:ubuntu
docker run -it --name ${CNAME} \
    -u $(id -u):$(id -g) \
    -v /etc/group:/etc/group:ro -v /etc/passwd:/etc/passwd:ro \
    -v ${HOME}/src:${HOME}/src -w ${HOME} \
    ubuntu:20.04 bash
```
- `-u $(id -u):$(id -g)` : ユーザ：グループを指定
- `-v /etc/group:/etc/group:ro -v /etc/passwd:/etc/passwd:ro`：ホスト側との整合性(リードオンリー)
- `-v ${HOME}/src:${HOME}/src`：お好み。私の場合はソースコードとか大抵ホームディレクトリに置いてるので。 
- `-w ${HOME}`：お好み。コンテナ入る度にホームディレクトリに移動するのが面倒なので。

このままだと、

```sh
$ sudo apt update
bash: sudo: command not found
```

のように`sudo`が使えないため、使えるようにする。
コンテナ起動後、一旦`C-p C-q`で抜ける。

```sh:ubuntu
docker exec -it -u root ${CNAME} \
    bash -c "apt update && apt install sudo -y \
    && ( echo $(id -nu):$(id -nu) | /usr/sbin/chpasswd ) \
    && ( echo \"$(id -nu) ALL=(ALL:ALL) NOPASSWD: ALL\" | tee /etc/sudoers.d/$(id -nu) )"
```

- `apt install sudo -y`：`sudo`をインストール
- `echo $(id -nu):$(id -nu) | /usr/sbin/chpasswd`：パスワードを設定(パスワードにユーザ名を使用している)。
    - 一見すると`/etc/passwd`が`ro`なので実行できなそうに見えるが、実際パスワードは`/etc/shadow`に保存されており、こちらはマウントしていないため問題なく実行できる。
- `echo \"$(id -nu) ALL=(ALL:ALL) NOPASSWD: ALL\" | tee /etc/sudoers.d/$(id -nu) )`：`sudo`をパスワード無しで実行できるようにする。
    - パスワード無しはセキュリティ的に...と感じるかもしれないが、上記のコマンドから分かるように、そもそも横から簡単に`root`で実行できちゃうため、ここでは気にしない。
    - 今回はあくまで開発環境など性善説的な場面を想定しており、セキュリティ面を気にする場合は[rootlessモード](https://matsuand.github.io/docs.docker.jp.onthefly/engine/security/rootless/)を使うのが良さそう。

パスワード無し`sudo`なので「パスワードの設定」は不要そうだが、パスワード設定をしておかないと`sudo`コマンドが使えなかったため設定。

動作確認。

```sh
# ホスト
$ docker attach ${CNAME}
-----
# コンテナ内
$ sudo apt update
```

### CentOS

パスワードの設定方法が若干違うが、基本的に同じ。

```sh
CNAME=test-suer-with-sudo

docker run -it --name ${CNAME} \
    -u $(id -u):$(id -g) \
    -v /etc/group:/etc/group:ro -v /etc/passwd:/etc/passwd:ro \
    -v ${HOME}/src:${HOME}/src -w ${HOME} \
    centos:8 bash

# C-p C-q で抜ける

docker exec -it -u root ${CNAME} \
    bash -c "yum install sudo passwd -y \
    && ( echo $(id -nu) | passwd --stdin $(id -nu) ) \
    && ( echo \"$(id -nu) ALL=(ALL:ALL) NOPASSWD: ALL\" | tee /etc/sudoers.d/$(id -nu) )"
```

## 最後に

Dockerコンテナを開発環境として使うと、ツールのインストールやビルド済みのイメージが使えたりしていろいろ便利です。

マシンが自分しかログインしない場合には、`${HOME}`を丸ごとマウントして`ssh`の設定などを引き継ぐ、みたいな使い方もできます。ただし、コンテナにアタッチされるとホームディレクトリが丸見えなので、使用の際にはご注意を。
Googleスライド内のスプレッドシートにリンクしたグラフをGASで自動更新させる

# はじめに
こんにちは。PayPayのお買い物で抽選でキャッシュバックされるそうで、朝からスイカを買いに出かけました、筆者です:v:
ただ、外れましたwwww

さて、今回は以下記事で紹介しました、Googleスライドを自動更新する話の続編になります！

https://qiita.com/akitkat/items/0f7bd3101eaf3e612203

# Googleスライドにスプレッドシートからリンクしたグラフとか挿入してないですか？
スプレッドシートって数値を管理するの便利ですよね。
例えばQiitaの日別PV数など、こんな感じで管理しているとします。

![QiitaPVレポート-Google-スプレッドシート.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86984/026a1dba-7515-82d2-3d67-7f8790c2e9a7.png)

そうすると、スプレッドシート上で簡単に以下のようにグラフが作れます :+1:

![QiitaPVレポート-Google-スプレッドシート (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86984/fba5df18-f573-58fc-4282-ec00584ff10a.png)

そのグラフをGoogleスライド上で簡単に挿入できます。

![無題のプレゼンテーション-Google-スライド (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86984/101f9c61-3d7c-92c5-1a36-96dcaecceb7f.png)

**<font color="red">ただ、このグラフ、スプレッドシートの値が変わっても更新されないんです</font> :sob:**

# 自動更新したいケース
自動で更新されないのなら更新するまでだ :muscle: 

というわけで前回の記事をベースに以下のケースを想定して更新していこうと思います。

1. グラフの元になっているスプレッドシートの値は毎月1日に自動集計される.
1. 前回の記事をベースに、Googleスライドは毎月3日に自動作成処理が入る.


# Googleスライド内のスプレッドシートにリンクしたグラフをGASで自動更新させる
以下スクリプトを対象Googleスライドのスクリプトエディタに書くことで、スライド内のスプレッドシートにリンクしているすべてのグラフを更新できます :ok_hand: 
前回の記事同様にトリガーを毎月3日にセットすればOKです:+1:

```js
const main = () => {
  SlidesApp
    .getActivePresentation()
    .getSlides()
    .forEach(s => {
      s.getSheetsCharts().forEach(c => c.refresh())
    })
}
```

# おわりに
コードは少なめですが、地味に便利なものができたと思います。
スプレッドシート側の値をすべて自動で変わるようにしておけばグラフも自動で変わる、素敵ですね :smile: 

それでは！
Linux: 曜日情報を取得する方法

たまに必要となるのでメモ。

###### 実施環境：

```Linux:Linux
[testuser@testhost ~]$ uname -a
Linux testhost 4.18.0-147.8.1.el8_1.x86_64 #1 SMP Thu Apr 9 13:49:54 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
[testuser@testhost ~]$ echo $SHELL
/bin/bash
```

曜日によって実施する処理を変える等、曜日情報を取得したい場合はたまに存在します。
そのような場合は、dateコマンドのフォーマットに特定の文字列を指定することで取得できます。

%wを指定した場合、日曜日から0,1,2,3,4,5,6となる数値情報で取得できます。

```Linux:Linux
[testuser@testhost ~]$ date
Tue Jul 13 21:44:44 JST 2021
[testuser@testhost ~]$ date +"%w"
2
[testuser@testhost ~]$ date -d "sunday" +"%w"
0
[testuser@testhost ~]$ date -d "monday" +"%w"
1
[testuser@testhost ~]$ date -d "saturday" +"%w"
6
```

%uを指定した場合、月曜日から1,2,3,4,5,6,7となる数値情報で取得できます。

```Linux:Linux
[testuser@testhost ~]$ date
Tue Jul 13 21:48:25 JST 2021
[testuser@testhost ~]$ date +"%u"
2
[testuser@testhost ~]$ date -d "sunday" +"%u"
7
[testuser@testhost ~]$ date -d "monday" +"%u"
1
[testuser@testhost ~]$ date -d "saturday" +"%u"
6
```

文字列で取得したい場合は、%aまたは%Aを指定します。
ここで表示される文字列は、ロケール設定に依存します。

```Linux:Linux
[testuser@testhost ~]$ date
Tue Jul 13 21:51:34 JST 2021
[testuser@testhost ~]$ date +"%a"
Tue
[testuser@testhost ~]$ date +"%A"
Tuesday
```
【Kubernetes】イメージを更新するには (Declarativeアプローチで)　no.10

![名称未設定のデザイン (12).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/bd33b68d-bd0e-0036-c171-cc9e980181bc.png)


こんにちは。まゆみです。

Kubernetesについての記事をシリーズで書いています。

前回・前々回の記事で、yamlファイルにDeploymentやServiceオブジェクトの設定内容をどのように書くかを解説させていただきました。

今回の記事では、

<ul>
<li>Podの中のContainerのイメージを更新するにはどうしたら良いか</li>
<li>イメージを更新するときに水面下で行われていること</li>
</ul>

を解説していこうと思います

さっそく始めていきますね。

#イメージの更新の仕方

実はイメージを更新するのは　<font color="Red">(Declarative(宣言型)のアプローチを使えば)</font>　ものすごく簡単です。

deployment.yamlファイルの

spec > containers > image

に変更したいイメージ名を書くだけです。
![2021-07-25_11-11-15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/f41bf315-ac3c-8140-e77a-b011ded4b646.png)

Imperativeなアプローチの場合、イメージを更新するのは大変でした。([こちらの記事](https://qiita.com/Mayumi_Pythonista/items/dd5b183a89a4fdd47c7e)でImperativeな方法によるイメージの更新の仕方を紹介しています)

>①更新したイメージをdocker hubにpush して

>②kubectl set imageコマンドでイメージを更新する

というやや複雑なものでしたが、Declarativeな方法によれば、yamlファイルのimage名を書き換えるだけで良いのです。

#yamlファイルを更新するときに水面下で起こっていること

上で記したように、yamlファイルのimage: の項目を新しいイメージ名にして

```
kubectl apply -f=<yamlファイル名>
```
とすれば、イメージが更新されて新たなオブジェクトが作られます。

この時水面下で何が起こっているかというと

コンピュータはyamlファイルのなかに書かれたオブジェクトの

name:
 
kind: 

を見ます。


![2021-07-25_11-50-22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/42dfdae3-2889-fc87-a061-3aa0282c0c4c.png)


そして更新後もファイルが同じ

name: 
 
kind: 

を使っているのなら、そのファイルは前のファイルを更新したものだと認識するのです。

![configファイル.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/f958e40a-d762-f3c7-9d69-7cc8b7aff015.png)

もし、name: もしくは　kind: のどちらかを違うものにしてしまうと、

『既存のpodを更新するのではなく、新しいpodを作るんだ』

とコンピュータが認識してしまうので、注意です。


#まとめ

今回の記事は短いですが、ここで締めくくらせていただきます。

お役に立てれば幸いです。
エンジニアな僕が普段実践している英語の勉強法

普段のエンジニアの僕の英語の勉強法の一部を公開してみます。

laravelのグローバルスコープについて勉強していた時のこと、、、。

グローバルなスコープでユーザーを異性に絞り込む機能を実装しようと思った時に
ふと、異性って英語で何て言うんだろう、、、。と思った。

```
異性
↓（G翻訳）
the opposite sex
```

なるほど、、、。
英語で例文も作ってみる、、、。
こんなんでどうでしょう、、、！

```
This grobal scope extract the opposite sex.
↓（G翻訳）
このグローバルスコープは異性を抽出します。
```

ここでGrammarlyというChromeの拡張機能を入れておくと、
grobal→global
extract→extracts
に訂正でき、間違いに気づけます。（マジ便利）

うーん。抽出、、、ではなく
「絞り込む」という日本語にしたいので、、、

```
このグローバルスコープは異性に絞り込みます。
↓（G翻訳）
This global scope narrows down to the opposite sex.
```

と日→英で翻訳。
narrows downって初めてみたけどググってみると
よく使いそう？な表現にできました。

以上のようなことを何て表現したらわからない時に時折実行しています。
plunkerでvue その54

# 概要

plunkerでvueやってみた。
phinaでbox2dやってみた。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/ef7035fc-ee60-447b-a380-0ebaeb12d49e.png)


# サンプルコード

```

new Vue({
  el: '#app',
　data: {
  },
  beforeMount: function() {
		this.init()
	},
	methods: {
	  init() {
phina.globalize();
var SCREEN_WIDTH = 640;
var SCREEN_HEIGHT = 960;
phina.define("MainScene", {
  superClass: 'DisplayScene',
  init: function() {
    this.superInit();
    this.backgroundColor = 'aqua';
    var layer = Box2dLayer({
      width: SCREEN_WIDTH,
      height: SCREEN_HEIGHT,
    }).addChildTo(this);
    
    var ball0 = CircleShape().addChildTo(this);
    ball0.setPosition(this.gridX.span(3), this.gridY.span(3));
    ball0.alpha = 0.5;
    layer.createBody({
      type: 'dynamic', 
      shape: 'circle',
    }).attachTo(ball0);
    
    this.ball1 = CircleShape().addChildTo(this);
    this.ball1.setPosition(this.gridX.span(4), this.gridY.span(3));
    this.ball1.alpha = 0.5;
    this.ball = layer.createBody({
      type: 'dynamic', 
      shape: 'circle',
    }).attachTo(this.ball1);
    
    var ball2 = CircleShape().addChildTo(this);
    ball2.setPosition(this.gridX.span(5), this.gridY.span(3));
    ball2.alpha = 0.5;
    layer.createBody({
      type: 'dynamic', 
      shape: 'circle',
    }).attachTo(ball2);
    
    var floor0 = RectangleShape({
      width: 500,
      height: 32,
    }).addChildTo(this);
    floor0.setPosition(this.gridX.span(4), this.gridY.span(9));
    floor0.alpha = 0.5;
    layer.createBody({
      type: 'static',       
      shape: 'box',
    }).attachTo(floor0).body.SetAngle(Math.degToRad(10));
  
    var floor1 = RectangleShape({
      width: 500,
      height: 32,
    }).addChildTo(this);
    floor1.setPosition(this.gridX.span(13), this.gridY.span(13));
    floor1.alpha = 0.5;
    layer.createBody({
      type: 'static',       
      shape: 'box',
    }).attachTo(floor1).body.SetAngle(Math.degToRad(-15));
  
  },
  update: function() {
    if (this.ball1.y > 900)
    {
      //alert(this.ball.body)
      //this.ball1.body.setPosition(this.gridX.span(4), this.gridY.span(3));
			var p = new b2.Vec2(0, 0);
			this.ball.body.SetPosition(p);

    }
  },
});
phina.main(function() {
  var app = GameApp({
    startLabel: 'splash',
    title: 'box2d',
  });
  app.run();
});

    },
  }
});





```

# 成果物

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

以上。
AtCoderログ：0034 - ABC 211 に参加しました

この記事は 2021年07月24日(土)21:00-22:40 に開催された [AtCoder Beginner Contest 211 (ABC 211)](https://atcoder.jp/contests/abc211) に参加した記録です。

https://atcoder.jp/contests/abc211

# 結果
- 得点：600 (=100+200+300)
- 時間：52:46 (= 52:46 + 05:00 × 0)
- 順位：3722 / 8604
- パフォーマンス：701
- レーティング：182 → 251 (+69) Highest更新！
- 段級位：10級 → 9級

![2021-07-24_abc211.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1589302/abffa6fe-41f5-75c2-50dc-880cd6b62537.png)

# 詳細
|問題|得点|時間|提出コード|復習|
|:--:|:--:|:--:|:--:|:--:|
|[ABC 211 A](https://atcoder.jp/contests/abc211/tasks/abc211_a)|100|02:07|[○](https://atcoder.jp/contests/abc211/submissions/24481995)|[AtCoderログ：00**]()|
|[ABC 211 B](https://atcoder.jp/contests/abc211/tasks/abc211_b)|200|05:39|[○](https://atcoder.jp/contests/abc211/submissions/24487986)|[AtCoderログ：00**]()|
|[ABC 211 C](https://atcoder.jp/contests/abc211/tasks/abc211_c)|300|52:46|[○](https://atcoder.jp/contests/abc211/submissions/24507076)|[AtCoderログ：00**]()|
|[ABC 211 D](https://atcoder.jp/contests/abc211/tasks/abc211_d)|400|---|---|---|
|[ABC 211 E](https://atcoder.jp/contests/abc211/tasks/abc211_e)|500|---|---|---|
|[ABC 211 F](https://atcoder.jp/contests/abc211/tasks/abc211_f)|600|---|---|---|

# 感想
- A, B, C を完答、D 以降は手出しできなかったので、時間を余らせての終了となりました。
- A、B は素直に回答して正解。
- C は漸化式を用いることに気づいたのですが、コーディングに手間取ってしまいました。
- レーティングが伸びてくれるのはありがたいのですが、D の壁が見えてきた感じです。

# リンク
## 前後の記事
- 前の記事 → [AtCoderログ：0033 - ABC 095 B](https://qiita.com/RoadLynton/items/9f642ff0fcf345221c08)
- 次の記事 → [AtCoderログ：0035 - ABC 087 B](https://qiita.com/RoadLynton/items/338e306e579fb345969d)
AtCoderログ：0033 - ABC 095 B

# 問題

https://atcoder.jp/contests/abc095/tasks/abc095_b

## 問題文
> パティシエの赤木さんは、「お菓子の素」という粉のみを材料として $N$ 種類のドーナツを作ることができます。これらのドーナツはドーナツ $1$、ドーナツ $2$、$\dots$、ドーナツ $N$ と呼ばれます。ドーナツ $i~(1 \le i \le N)$ を $1$ 個作るには、お菓子の素 $m_i$ グラムを消費する必要があります。なお、$0.5$ 個など整数でない個数のドーナツを作ることはできません。
> いま、赤木さんはお菓子の素を $X$ グラム持っています。これを使って、今夜のパーティーに向けて可能な限りたくさんのドーナツを作ることにしました。ただし、来客の味の好みは様々なので、次の条件を守ることにしました。
> ・$N$ 種類のドーナツそれぞれを少なくとも $1$ 個は作る。
> このとき、最大で何個のドーナツを作ることができるでしょうか？お菓子の素を使い切る必要はありません。また、この問題の制約のもとでは、条件を守ることは必ず可能です。

## 制約
> ・$2 \le N \le 100$
> ・$1 \le m_i \le 1000$
> ・$m_1+m_2+\ldots+m_N \le X \le 10^5$
> ・入力中のすべての値は整数である。

## 収録されている問題セット
- [AtCoder に登録したら次にやること](https://qiita.com/drken/items/fd4e5e3630d0f5859067) ([第03問類題](https://qiita.com/drken/items/fd4e5e3630d0f5859067#%E7%AC%AC-3-%E5%95%8F--abc-081-b---shift-only-200-%E7%82%B9))

# 回答
## 回答1 (AC)
ドーナツの個数の個数を最大にするには、n 個のドーナツを 1 個ずつ作った後、ドーナツの素の消費量が最も少ないドーナツだけを作れば良いです。処理としては、ドーナツの種類 n とドーナツの素の量 x と各ドーナツを作るのに必要なドーナツの素の量を受け取り、各ドーナツを1個ずつ作るのに必要なドーナツの素の合計 sum と、ドーナツの素の消費量の最小値 dmin を求め、最後に合計で作ることのできるドーナツの個数 donut を計算します。コードは以下のようになりました。

```C++:abc095b-1.cpp
#include <bits/stdc++.h>
using namespace std;
 
int main() {
  int n, x;
  cin >> n >> x;
 
  vector<int> m(n);
  for ( int i=0; i<n; i++ ) {
    cin >> m.at(i);
  }
 
  int sum = 0, dmin = m.at(0);
  for ( int i=0; i<n; i++ ) {
    sum += m.at(i);
    dmin = min( dmin, m.at(i) );
  }
  
  int donut = n + (x-sum)/dmin;
 
  cout << donut << endl;
}
```

## 回答2 (AC)
回答1の無駄な処理を削っていきます。まず、各ドーナツは1個ずつは作るので、各ドーナツを作るのに必要なドーナツの素 m を受け取るたびに、所持しているドーナツの素の総量 x から m を引けば、変数 sum は不要です。また、m を受け取るたびに dmin を更新していくことで、各ドーナツを作るのに必要なドーナツの素を配列として所持する必要がなくなります。これらの改良を用いたコードは次のようになりました。回答1のコードに比べ、かなりコンパクトになっています。

```C++:abc095b-2.cpp
#include <bits/stdc++.h>
using namespace std;
 
int main() {
  int n, x;
  cin >> n >> x;
 
  int m, dmin = INT_MAX;
  for ( int i=0; i<n; i++ ) {
    cin >> m;
    x    -= m;
    dmin =  min( dmin, m );
  }
 
  cout << n + x/dmin << endl;
}
```

# 調べたこと
## [AtCoder の解説](https://atcoder.jp/contests/abc095/tasks/abc095_b/editorial) → [コンテスト全体の解説](https://img.atcoder.jp/arc096/editorial.pdf)
回答1,2と同じ方針でした。

# リンク
- 前の記事 → [AtCoderログ：0032 - 「AtCoder に登録したら次にやること」のまとめ](https://qiita.com/RoadLynton/items/be2bb98e5d0c0f30628b)
- 次の記事 → [AtCoderログ：0034 - ABC 211 に参加しました](https://qiita.com/RoadLynton/items/50b726125c1004d99b02)
【Rails 6】 テーブルへCSVファイルをインポートした際にNameErrorが出力された時の対処法

はじめに
----
CSVファイルをテーブルにインポートした際に、NameErrorが出力されて躓いたので、備忘録として残します。

開発環境
----
- Mac
- Ruby 2.7.2
- Rails 6.1.3.1
- PostgreSQL 13.2

前提
----

`rails db:seed`コマンドを実行後、以下の`seeds.rb`から`import_csv.rb`を呼び出して、テーブルにcsvファイルをインポートします。

```ruby:db/seeds.rb
ImportCsv.information_data
```

```ruby:lib/autoloads/import_csv.rb
class ImportCsv
  # CSVデータのパスを引数として受け取り、インポート処理を実行
  def self.import(path)
    list = []

    CSV.foreach(path, headers: true) do |row|
      list << row.to_h
    end

    list
  end

  def self.information_data
    list = import('db/csv_data/information.csv')

    puts "インポート処理を開始"
    Information.create!(list)
    puts "インポート完了!"
  end
end
```

エラーメッセージ
---

前提で記載した通り、`rails db:seed`を実行した結果、以下のエラーメッセージが出力されました。

```
% rails db:seed
rails aborted!
NameError: uninitialized constant ImportCsv
```

NameErrorのメッセージ内容を調べてみましたところ、以下の記事によると、NameErrorは定義されていない変数またはメソッドを使用したときに発生するとのことです。

https://diveintocode.jp/blogs/Technology/ErrorCollection

`seeds.rb`から`import_csv.rb`を上手く呼び出せていないのでは？と思いました。

対応方法
---
以下のように`application.rb`（すべての環境で共通の設定ファイル）の`config.autoload_paths`（オートロード対象）に`lib/autoloads`を指定することで、`import_csv.rb`を呼び出すようにしました。

```ruby:config/application.rb
module モジュール名
  class Application < Rails::Application
    # lib/autoloads ディレクトリ配下のファイルを読み込む
    config.autoload_paths << Rails.root.join('lib/autoloads')
  end
end
```

上記の設定後に`rails db:seed`を実行してみた結果、テーブルにCSVファイルを上手くインポートすることができました。

```
% rails db:seed
インポート処理を開始
インポート完了!
% 
```

参考記事
---
- [エラーメッセージから学ぶ](https://diveintocode.jp/blogs/Technology/ErrorCollection)
- [Railsドキュメント_設定ファイルについて](https://railsdoc.com/config)
- [Railsドキュメント_オートロード対象となるパスの追加](https://railsdoc.com/page/config_autoload_paths)
JNanoId で NanoID を生成する

# 概要
NanoID というものがあると以下の記事で知りました。

[Why is NanoID Replacing UUID?](https://blog.bitsrc.io/why-is-nanoid-replacing-uuid-1b5100e62ed2)

UUID よりもコンパクトで、また使う文字を生成時に制限できる点が特徴のようです。後者の特徴は、
例えばランダムなファイル名や URL のパスを生成したい時に役立ちそうです。

## Java での実装
Java の実装を探してみたところ、 [JNanoId](https://github.com/aventrix/jnanoid) というライブラリーがあったので試してみました。

https://github.com/aventrix/jnanoid

最新のバージョンは [2.0](https://github.com/aventrix/jnanoid/releases/tag/jnanoid-2.0.0) で、最終リリースが2018年11月と大分古いです。
ライセンスは [MIT License](https://github.com/aventrix/jnanoid/blob/jnanoid-2.0.0/LICENSE) です。

[130行ほどの小さなクラス1つ](https://github.com/aventrix/jnanoid/blob/jnanoid-2.0.0/src/main/java/com/aventrix/jnanoid/jnanoid/NanoIdUtils.java)です。[テストコード](https://github.com/aventrix/jnanoid/blob/jnanoid-2.0.0/src/test/java/com/aventrix/jnanoid/NanoIdUtilsTest.java)もあります。

### 特徴
- Secure……Java の SecureRandom を用いている
- Compact……長さが21なので UUID よりも短い
- URL-Friendly……出力される ID は (A-Za-z0-9_-) に限定されているので、URL に用いることができる
- Customizable……ID生成に用いる文字と、IDの長さを制限することができる

# 使用

## 依存の追加
build.gradle に依存を1行追加してください。

```kotlin
dependencies {
    implementation("com.aventrix.jnanoid:jnanoid:2.0.0")
}
```

## 基本的な使い方
`NanoIdUtils.randomNanoId()` をコールするだけで NanoID の文字列を生成してくれます。非常に簡単です。

```kotlin
import com.aventrix.jnanoid.jnanoid.NanoIdUtils

fun main() {
    repeat(10) { println(NanoIdUtils.randomNanoId()) }
}
```

```:出力例
MPKasmT5l0YxpnJe_Qfm1
594vTh1V5Y-cK4B-PgZzt
0vsaKgBxLbLrRnAA9c4lD
UL9GiWbUBKjOqqrST3o9k
OnfVWpbe2UJqpYawqkK_q
tv3sGbsEnDHHmMCgrHHfP
ai6qqzErVFWTUka6OO5Gw
FSmTiYVXyNYJwhPnYBM4-
```

## カスタムIDの生成
また、ID生成に使う文字を制限することもできます。

```kotlin
NanoIdUtils.randomNanoId(SecureRandom(), charArrayOf('a', 'x', '2', '$', '@'), 12)
```

こうすると、'a', 'x', '2', '$', '@' だけの組み合わせで長さ12のIDを生成してくれます。

```:出力例
$@$aa@@@$@@2
$2$aa$@@a@@2
@x@xa2xx$xxx
22$xax22axa2
```


# 他の実装
Clojure の実装もあるようです。

https://javalibs.com/artifact/nano-id/nano-id


# 終わりに
Java で NanoID を実装した [JNanoId](https://github.com/aventrix/jnanoid) について書きました。
Java で NanoID を使いたい時は、自分で実装しても良いでしょうが、
既に実装されていてテストコードもあるライブラリーを使っても良いのではと思います。
nodist でnodeを切り替えていると npx create-react app が動かなくてはまる

nodist で node のバージョン切り替えをしているとはまりました。

Windows環境です。

そのときのメモです。
解決策は、ありませんというか、nodist 使うのやめます。

## nodist で node を切り替えていました。

```powershell
> nodist -v
0.9.1
> nodist
  (x64)
  11.13.0  (global: 11.13.0)
> 15.13.0
```

この状態で、次のコマンドがエラーになりました。

```powershell
> npx create-react-app my-app
npm ERR! cb.apply is not a function

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\<UserName>\AppData\Roaming\npm-cache\_logs\2021-07-25T01_47_20_805Z-debug.log
Install for [ 'create-react-app@latest' ] failed with code 1
```

ネットでいろいろさぐって、Roaming内のキャッシュを消せやなんだかんだとあったのですがいろいろ試しても解決せず。

なんで変なことしてないのに npx create-react-app が動かないんだと探っていたら、nodist を使っていたことを思い出しました。

nodist で node 11.13.0 に切り替えると正常動作しました。

node の切り替えは純粋なインストーラーとかでやったほうがいいと思いました。

以上です。
Kaggleのnotebookでzipファイルを取り扱う時のTips

# 概要
Kaggleで定義されている訓練用・テストデータがzipに固められているものがある。
ローカルで開発している人は容易に解凍ができるが、notebook上だと「/kaggle/input」は配下はread権限しかないため、エラーが出てしまう。

▼下記のようなエラー

```
OSError: [Errno 30] Read-only file system: '/kaggle/input/~
```

やっていることはpythonのzip解凍・zip読み込み系ではあるのだが、kaggle内にある他の人が書いたコードを参考にする時に、zip解凍したファイルの読み込み周りで詰まったので、これで解決できたよという意味でまとめる。

※他に良い方法があれば教えて欲しいですmm

# 方法

## CSVの場合
CSVの場合は「pandas.read_csv([zip名])」を使用すれば読み込むことができる。

```
import pd as pandas
train = pd.read_csv('/kaggle/input/train.csv.zip')
```

CSV形式は以下でQAのやりとりがあり、他でもunzip方法が記載されている。

https://www.kaggle.com/questions-and-answers/56042

## 画像の場合

### ファイル出力

対象zip内のファイルを出力してしまう。

「/kaggle/input」配下に出力できないだけなので、作業用の「/kaggle/working」配下に出力する。

```
import zipfile
z = zipfile.ZipFile('/kaggle/input/street-view-getting-started-with-julia/train.zip')
z.namelist() # zip内のファイル名一覧を取得
extractall('/kaggle/working') # zip内容を出力
```

※ただし、画像が多い場合は対象DirがUI上は重すぎて開けなくなるので、UI上の操作はしないようにする。

imread関数を使用すれば対象画像を読み込むことができる。

画像が連番の場合はrangeなどで画像読み込みすれば楽に取得できる。

```
from skimage import io
train=[io.imread('/kaggle/working/train/'+str(i)+'.Bmp',as_gray=True) for i in range(1,[ラストの連番まで])]
```

namelist()を使用して、配列を回して画像として読み込むこともできると思う。(for文の回し方を変えるだけだと思うので割愛)

### ファイル名を元にアクティブで読み込んでいく

read関数でも取得することができる。

```
z = zipfile.ZipFile('/kaggle/input/xxxxx/test.zip', 'r')
z.namelist() # zip内のファイル名一覧を取得
img_data = z.read('test/xxxx.Bmp')
```

こちらも上記と同様にrangeなどで連番で画像情報を取得するか、namelistで取得する形になる。

# 参考リンク
https://www.kaggle.com/questions-and-answers/56042
https://www.it-swarm-ja.com/ja/python/python%EF%BC%9A%E4%B8%80%E6%99%82%E7%9A%84%E3%81%AB%E8%A7%A3%E5%87%8D%E3%81%9B%E3%81%9A%E3%81%ABzip%E3%81%8B%E3%82%89%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E9%96%8B%E3%81%8D%E3%81%BE%E3%81%99/1041517400/
fuel.php Fuel\Core\Database_Exception [ 42000 (1064) ]:エラー

fuel.phpのエラーはググっても古い記事が多く、苦戦しました。
本日は以下のエラーと格闘。


Fuel\Core\Database_Exception [ 42000 (1064) ]:
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'group, profile_fields, last_login, login_hash, created_at)

これはデフォルトで用意しなきゃいけないusersテーブルの中の「group」というテーブルが悪さをしてます。
これは予約語です。
なのでバッククウォートで囲ってあげる必要がありますね。

まずは
fuel>packages>auth>classes>auth>login>simpleauth.php
に入ります。

そこの260行目付近に以下の記述があります。
デフォルトだとgroupがシングルクオーテーションで囲われてるだけなのですが
その内側をバッククウォートで囲ってあげればOKですね。

```fuel.php

$user = array(
			'username'        => (string) $username,
			'password'        => $this->hash_password((string) $password),
			'email'           => $email,
　　　　　　　　　　　　　　　　　　　　　　　　　　//こいつです。このやろーーー
			'`group`'           => (int) $group,
			'profile_fields'  => serialize($profile_fields),
			'last_login'      => 0,
			'login_hash'      => '',
			'created_at'      => \Date::forge()->get_timestamp(),
		);
```

多分SELECTの時とかも悪さをしそうなのでエラー画面からファイル名を特定して書き換えてやる
必要がありそうですね。
【UiPath】ファイル／ディレクトリの別名保存（連番付き）

# はじめに

この投稿は、RPAツール「UiPath」での 実装例 について記事です。

UiPathのコミュニティ「UiPath Friends」が企画する「UiPathブログ発信チャレンジ2021サマー」の 25日目の投稿でもあります。

企画の内容は [**こちら**](https://note.com/shumpei_w/n/n651cbdbec4e8) 。カレンダーのURLは [**こちら**](http://u0u1.net/sUwZ) です。

https://twitter.com/ShumpeiWatanabe/status/1405168150736359427

# ファイル／ディレクトリがあれば、連番を付けて保存する

ファイルの貼り付けや移動時に、重複するファイル名／ディレクトリ名があった場合に「後ろに連番を付けて保存する」という何かと使えるコードです。内容は大したことありませんが、あると便利です。

連番・名前の付け方は「Windows標準」と同じく「コピー（X）」という形にしています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/117b3c37-ee22-d5c5-d4fb-fa9cfd1b86d7.png)

確認しやすいように、以下にxaml形式でアップしました。

https://github.com/miyag/UiPath.ReusableCode/blob/master/FileBackup/RenameFileIfExists.xaml

以下は「ディレクトリ」版です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/a62d7fbe-9920-5737-52c0-b430d391b977.png)

確認しやすいように、以下にxaml形式でアップしました。

https://github.com/miyag/UiPath.ReusableCode/blob/master/FileBackup/RenameDirectoryIfExists.xaml

# 終わりに

いかがでしたでしょうか。過去のファイルを取っておきたいときなどに使うと便利です。

この記事が参考になったら、 LGTMをお願いします。閲覧ありがとうございました。
触感デバイス開発モジュール“hapStak“ デジタル版＋M5 atom Lite/Matrixで好きな音を鳴らす(振動させる)

##はじめに
いろいろと電子工作に便利なキット/モジュールを販売しているビットトレードワン(https://bit-trade-one.co.jp/)
から新しく触感デバイス開発モジュール“hapStak“ デジタル版（型番：ADACHACY）が発売されました。
この触感デバイス開発モジュール“hapStak“ デジタル版はM5 atom Lite/Matrixを使って任意の振動波形を発生させることができます。中身は M5 atom echo の音声出力部とコンパチなので、M5 atom echo のサンプルプログラムを改造して今回はこれを用いて好きな音を鳴らせる(振動させる)ようにしてみます。

#####＜試した環境＞
OS：Windows 10
使用ソフトウェア：Arduino IDE
使用ハードウェア：M5 ATOM Matrix
##M5 atom echoのセットアップ
基本的にM5 atomのセットアップと同様です。
以下参考サイト
https://qiita.com/eeldog/private/4048234a3f134ed11723
##サンプルコードの音を出してみる

まずサンプルコードで音を鳴らしてみます。
下記のサイトにアクセスし、資料＞ Arduino サンプルコード >FactoryTestをクリックします。

https://www.switch-science.com/catalog/6347/?fbclid=IwAR18fW1mPV3ZcTXyAsG7JEDsGNjOt5VAvXFq91clWHRYLxX084cqlQJxlA8

クリック先は今回使用するサンプルが公開されているGitHubにつながります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1703667/effa494b-599f-ab25-9078-0e8d254100cc.png)

今回はこのサンプルコードを用います。
ダウンロードするために上流のディレクトリであるM5-ProductExampleCodeをクリックし、右上の↓codeをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1703667/4859486e-7f74-95e4-ebd7-43872d1ed540.png)
ダウンロードしたZIPファイルを展開し、Core>Atom>Atom Echo>Arduino>Factory_Test>Factory_test(Aruduinofile)を開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1703667/c336a946-7f3c-8cb0-e27c-f6a603944789.png)
COMやポートの確認し、書き込みをしてみると…
♪テテテテーテーテーテッテテー♪
どこか懐かしい音が聞こえました！
（振動スピーカーを段ボールなど硬いものに押し当てると押し当てたものがスピーカとなって音を鳴らします。）

##音を変えてみる
次にこのサンプルコードに指定されている音を好きなものに変えたいと思います。
M5 atom echoに音声ファイルを入力するためにはxxx.c形式に変換する必要があります。
今回は以下のファイルを使用します。
（サイトURL)
そこで今回は以下のURLに放課後マイコンクラブさんが公開しているツールを用います。

https://hello-world.blog.ss-blog.jp/2016-10-16?fbclhttps://hello-world.blog.ss-blog.jp/2016-10-16?fbclid=IwAR3BNtoigjntmdkIPFHHnUn2o5DzprDrevRvL4XDnappvvmmCe143f6ynZgid=IwAR3BNtoigjntmdkIPFHHnUn2o5DzprDrevRvL4XDnappvvmmCe143f6ynZg

変換したファイルはFactory_testの11-fanfare.cに書き換えます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1703667/f9300afc-e612-1365-ca2f-4bc7ba99f283.png)

そしてM5 stack echoに書き込むと・・・

無事、好きな音を鳴らすことができました。

##おわりに
触感デバイス開発モジュール“hapStak“ デジタル版はモバイルバッテリーなどに接続すればスタンドアロンで任意の振動を発生させることができます。M5 atomの GROVE端子にセンサなどを接続し連携することで簡単に触覚振動付きのメディアアート作品を作ることができると思います。
WSL (Windows Subsystem for Linux)からプロキシ環境下でインターネット通信する手順

# はじめに

プロキシ環境下においてUbuntu on WSLからインターネット通信ができずハマったのでメモしました．なお，WSL（バージョン2）では未だインターネット通信に成功していないので解決策をお持ちの方ご共有いただけると幸いです．

# TL;DR

* WSLバージョンが2の場合，バージョンを1に設定する．
* `/etc/environment`ファイルに環境変数`http_proxy`，`https_proxy`を追記する．

# 手順

ディストリビューションはUbuntu 18.04を使用しています．

## 1. WSLバージョンを2から1に設定する

自分がここでハマりました．WSLのバージョンによってネットワーク周りの仕様が異なるためか，WSLバージョンが2のときプロキシ環境下でインターネット通信できないという問題が起きていました．ここではWSLバージョンを2から1に設定する手順を載せます．

もしプロキシ環境下においてUbuntu on WSL（バージョン2）からインターネット通信に成功した方がいらっしゃれば，コメント等で共有していただけると幸いです．

まずインストールされているディストリビューションを確認します．

```powershell
> wsl --list --verbose
  NAME            STATE           VERSION
* Ubuntu-18.04    Stopped         2
```

WSLバージョンが2の場合は1に変更します．

```powershell
> wsl --set-version Ubuntu-18.04 1
> wsl --list --verbose
  NAME            STATE           VERSION
* Ubuntu-18.04    Stopped         1
```

## 2. `/etc/environment`ファイルにプロキシの環境変数を追記する

`/etc/environment`ファイルをスーパーユーザー権限で編集します．

```sh
$ sudo nano /etc/environment
```

以下をを追記します．プロキシサーバーのURLは`http://proxy.example.com:8080/`とします．ご自身の環境に合わせて変更してください．

```text:/etc/environment
http_proxy=http://proxy.example.com:8080/
https_proxy=http://proxy.example.com:8080/
```

認証が必要な場合は`http://username:password@proxy.example.com:8080`（ユーザー名: `username`，パスワード: `password`）のように書きます．

# おわりに

本稿ではプロキシ環境下においてUbuntu on WSLからインターネット通信するための手順について記載しました．

繰り返しになりますが，もしプロキシ環境下においてUbuntu on WSL2からインターネット通信に成功した方がいらっしゃれば，コメント等で共有していただけると幸いです．
SQL 超初心者向け スッキリわかるSQL 4章（検索結果の加工）

# はじめに
さて今回もやってきます！スッキリわかるSQL3章です！
本記事もこの家計簿テーブルを題材としています。
![スクリーンショット 2021-07-22 18.55.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1183228/d3564be4-9ab3-b2af-e443-bbbb598524e7.png)

# 検索結果の加工
実はSELECT文だけに可能な修飾があります。
抽出した検索文を加工(並び替えや重複削除など）できます。

### 検索結果を加工する主なキーワード

| 比較演算子 |  意味 | 
|---:|-------------|
|  DISTINCT  |  検索結果から重複行を除外する   |   
| ORDERBY  |  検索結果の順序を並び替える   |   
| LIMIT  |  検索結果から件数を限定して取得する   |   
| UNION  | 検索結果にほかの検索結果を足し合わせる   |   
| EXCEPT  | 検索結果からほかの検索結果を差し引く   |   
|  INTERSECT  | 検索結果とほかの検索結果で重複する部分を取得する   |   

いっぱいありますね！ さくっと書き方説明します。

## DISTINCT -重複行を除外する

```
SELECT DISTINCT 入金額 
  FROM 家計簿
```

これで抽出した結果は、重複されません！

## ORDERBY -検索結果を並び替える

ASCで昇順,DESCで降順の設定ができる。
ただし、デフォルトはASC（昇順）なので、ASCは書かなくてもいいです！

```
SELECT * 
  FROM 家計簿
ORDER BY 出金額
```
家計簿テーブルの出金額が低い順に並び変えられて出力されます。

```
SELECT * 
  FROM 家計簿
ORDER BY 出金額 DESC  ←DESCを追加
```

家計簿テーブルの出金額が高い順に並び変えられて出力されます。

####複数の列で並び替える
たとえば入金額の降順で並び替える。入金額が等しい行については
さらに出金額の降順に並び替えるという複数の列の並び替えができます

```
SELECT * 
  FROM 家計簿
ORDER BY 入金額 DESC, 出金額 DESC  ←複数の列
```
#### 列番号を指定した並び替え
ORDER BYでは、並び替えの基準とする列を列名ではなく列番号で指定ることも可能。

列番号とは、選択例リストにおける列の順番のことで、SELECT命令に記述した順に１から数えます。

```
SELECT * 
  FROM 家計簿
ORDER BY 4 DESC, 5 DESC
```
(ORDER BY 入金額 DESC, 出金額 DESC )この文と同じです。

## LIMIT -先頭から数行だけ取得する

LIMIT 取得行数 （OFFSET 先頭から除外する行数）

実際にやってみます。
出金額の高い順に３件取得する

```
SELECT 費目, 出金額 
FROM 家計簿
ORDER BY 出金額 DESC LIMIT 3
```

３番目に高い出金額だけを取得する

```
SELECT 費目, 出金額 
FROM 家計簿
ORDER BY 出金額 DESC LIMIT 1 OFFSET 2
```
#ここからは ２つのテーブルを扱う時に使う集合演算子の紹介
データ数が多くなって、テーブル２つに分ける際に、SELECT文を２つのテーブルにあてるのは面倒なので
一気にやっちゃおう！ができるもの

`※集合演算子は、選択列リストと列数のそれぞれのデータ型が一致していないといけない。`

## UNION -２つの結果を足し合わせたもの
家計簿テーブルと家計簿アーカイブテーブルが２つあった時。

```
SELECT 費目,入金額,出金額 FROM 家計簿
UNION
SELECT 費目,入金額,出金額 FROM 家計簿アーカイブ
ORDER BY 2,3,1
```
## EXCEPT(エクセプト） -最初の検索結果から次の検索結果と重複するものを取り除いたモノ

```
SELECT 費目 FROM 家計簿
EXCEPT
SELECT 費目 FROM 家計簿アーカイブ
```
##INTERSECT -２つの検索結果で重複するもの（共通する行を集める）
```
SELECT 費目 FROM 家計簿
INTERSECT
SELECT 費目 FROM 家計簿アーカイブ
```

##まとめ
・検索結果を加工し、取得データを色々加工できる。
・集合演算子を使って、２つのテーブルから簡単にデータを取得できる。


# 参考記事
- スッキリわかるSQL入門ドリル
fuel.phpのFuel\Core\Database_Exception [ 2014 (2014) ]:エラー

このエラーはfuel.phpのバージョンが18.1以降にDBの接続方法が
mysqliの時に起きました。
対処法は簡単

app>config>db.phpの中の以下の[active]の箇所をpdoに変更するだけ。

```fuel.php
return array(
  'active' => 'mysqli',

  'pdo' => array(
       //ここを変える
         'type' => 'pdo',
　　　　　　　　　　　　　　　　　　　//接続配列
         'connection' => array()
               //PDOの接続DSN（データソース名）
              'dsn' => 'mysql:host = localhost; dbname = db名',
               'username' => 'root',
               'password' => 'root',
　　　　　　　　　　　　　        //永続的に接続するかどうか
               'persistent'     => false,
　　　　　　　　　　　　　　　　　　　　　　　　　　　　　//MYSQL、MYSQLiを使用するときにクライアント圧縮するかどうか
               'compress'       => false,

         )
            //テーブル接頭辞(Wordpressのテーブルの前のwp_...みたいなやつ)
            'table_prefix' => '',
            'caching' => false,
            'profiling' => true,
),
  
　　'mysqli' => array(
        'type'           => 'mysqli',
        'connection'     => array(
            'hostname' => 'localhost',
            'database' => 'framework',
            'username'       => 'root',
            'password'       => 'root',
            'persistent'     => false,
            'compress'       => false,
        ),
        
        'table_prefix' => '',
        'charset'      => 'utf8',
        'caching'      => false,
        'profiling'    => true,
    ),
  );
Hapi.jsを使ったテストでauthの結果をモックする

Hapiは`server.inject`というメソッドでサーバーをシミュレートすることができます。その中で「あるAPIをテストしたいが、authの結果をモックして返したい」という場面があると思います。その場合は

```ts
const res = await server.inject({
          method: "POST",
          url: `${baseUrl}/users`,
          auth: { // authを指定
            strategy: "my-strategy",
            credentials: {},
            artifacts: {
              name: "Admin User",
              admin: true,
            },
          },
        });
```

こんな感じでauthを指定するとそのテストで欲しいデータを`request.auth`から取ることができました。
GitとGitHubを基本からまとめてみた【GitHub Issues】

## Issueとは?
GitHub上での課題を見える化して管理する機能である。

## Issueの使用の手順
##### (1) Issueを作成する
GitHubで、Issueを作成したいリポジトリにアクセスして『Issues』クリックする。
その後、右上の『New issue』をクリックする。
##### (2)Issueのタイトルと内容を入力する
Issueを作成する画面で、タイトルと内容を入力する。内容はMarkdown形式で入力でき、チェックボックス、画像、リンクなども挿入可能。※ 『Preview』のタブをクリックすると、プレビューを見ることができるのでチェックする。
##### (3)Issueに担当者を割り振る
もし、アサインしたい担当者が決まっている場合は、Assigneesの機能でIssueに担当者を割り振ることができる。右側の『Assignees』の歯車アイコンをクリックし、ユーザー名を検索、アサインしたいユーザーを選択する。
##### (4)Issueにラベルを付与する
また、ラベルを付与することで、Issueの種類を視覚的にわかりやすくすることができる。
右側の「Labels」の歯車アイコンをクリックし、対応するラベルを1つもしくは複数選択する。
##### (5) Issueの作成を完了する
全ての設定が完了したら、『Submit new issue』で、新しいIssueが作成される。
リポジトリの『Issues』をクリックすることで、作成されたIssueを一覧、または開くことができる。

## ソースコードの訂正（Git操作）
##### (1) Issueを作成する
GitHubで、Issueを作成したいリポジトリにアクセスして『Issues』クリックする。その後、右上の『New issue』をクリックする。

##### (2)Issueのタイトルと内容を入力する
Titleとcommentに発生した不具合などの状況を入力し、『Submit new issue』をクリックする。

##### (3)作業用のローカルブランチを作成する
```
git branch feature/# <issue番号><作業名>
```
feature：
各機能ごとに作るブランチ。
よくfutureと間違えて「フューチャー」と読む方がいるが、正しい読み方は「フィーチャー」。
複数切るブランチになるのため「feature/機能名」のようにする。

##### (4)カレントで見ているブランチを切り替える
```
git checkout  <feature/# <issue番号><作業名>>
//現在developブランチにいることを確認する。
git branch -l
```
##### (5) 実装したコードをaddする。
```
git add .
```
##### (6) コミットする。
```
git commit -m "コミットメッセージ"
```
##### (7)プッシュする。
```
git push 
```
##### (8)メッセージに表示されたコマンドを使用する。

##### (9)Pull requestsのタブを選んで『Compare&Pull request』を押す。

##### (10)『Create Pull request』を押す。

##### (11)プルリクエストと先ほど作ったIssueを関連付けをする。
※ 右にある『Development』を押し、Issueを選択する。

##### (12)レビューをしてもらう
①レビューをする人は、プルリクエストを確認する。
②File chagedから何処が変更されたか確認する。
③必要であれば、レビューを書き、『Finish your review』を押す。

##### (13)レビューした人は問題がなければ、『Merage pull request』を押す。

##### (14)最新を取得するための『git pull』をする
```
git checkout main
git pull
```



## 参考サイト
[GitHubプロジェクト管理入門 #01：Projectsのカンバン（KANBAN）方式でタスク管理しよう](https://www.youtube.com/watch?v=ZGq8eYECEH8)
[GitHubプロジェクト管理入門 #02：Issues（課題）機能で、バグを発見・修正しやすくしよう](https://www.youtube.com/watch?v=ZM7JRx6X2JA)
[GitHubで課題を管理する便利機能Issueとその作成方法](https://tonari-it.com/github-issue/)
[GitHubのissueを活用した、個人アプリの開発手順を書いてみた](https://qiita.com/tkmd35/items/9612c03dc60b1c516969)
[Github issue との付き合い方 作成編](https://qiita.com/janus_wel/items/ba47259f107b161c5727)
[VSCodeでSpringBoot開発 #03.ソースコードの訂正（Git操作）](https://www.youtube.com/watch?v=24zZNwSlzRc)
[小規模案件でのGit運用の個人的な最適解](https://bsblog.casareal.co.jp/archives/3864)
LinuxでMacのQuickLookをやりたければGNOME sushiを使えばよい

## はじめに

UbuntuでもMacのQuick Lookを使いたいという人は少なくないと思います。私がMacを使っていたのはOSX 10.04〜07ぐらいまでとかなり昔なのですが、それでもQuick Lookの使い心地は未だに記憶に残っており、しばしばUbuntuでもQuick Lookをしてしまうことがあります。


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/58330caa-e33e-9d92-20df-bfc08e398e86.gif" alt="Qiitan" width="10%"><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/58330caa-e33e-9d92-20df-bfc08e398e86.gif" alt="Qiitan" width="10%"><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/58330caa-e33e-9d92-20df-bfc08e398e86.gif" alt="Qiitan" width="10%">
 / Quick Lookが使えないとそわそわするなー \


## 結論 Gnome sushi を使えばよい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/0d50aedf-a9e7-1b9e-90b2-45f6a8c22bee.png)

https://gitlab.gnome.org/GNOME/sushi

## インストール

```
sudo apt install gnome-sushi
```

これでスペースキーを押すと即座に画像やPDFが表示されるようになります。GNOME系のツールはメンテナンス状況が気になるものが多いですが、こちらのツールに関しては、プロジェクト自体も若く、下のスクリーンショットのように最近までコミットが続いていますのでプロジェクトのLivenessは大丈夫でしょう。![Something went wrong]()

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/a6b61d2f-4198-f19e-45e7-d616fece5792.png)

それではみなさんごきげんよう！

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/58330caa-e33e-9d92-20df-bfc08e398e86.gif" alt="Qiitan">
Linuxまとめ

#用語一覧
|用語　　　　　　　　　　　　|意味　　　　　　　　　　　　　　　　　　　　　|
|---|---|---|
|CLI（Command Line Interface）|コマンドプロンプトやMacならターミナル（黒い画面）に文字を打ち、処理を行う|
|GUI（Graphical User Interface）|マウスでポチポチ操作|
|シェル|LinuxのCLIを提供するソフトウェア|
|シンボリックリンク|リンク先のパス名を記載しただけのファイル、ファイルを移動したり削除すると使えなくなる|
|テキストファイル|文字通りテキスト（文字列）が書かれたファイル|
|バイナリファイル|画像ファイルや音声ファイル、Linexコマンドの実行ファイル（/bin/catなど）|
|正規表現|条件に合う文字列集合体を表現するための記法、* {} $ などの記号（メタ文字）が使われる|
|メタ文字|本来の意味とは違う特別な意味を持たせた文字|
|シェルスクリプト|シェル（人間の入力をコンピュータに伝えるプログラム）に対する命令が書かれたファイル|
|パスを通す|複数ある場合はこっちを使ってね<br>シェルが起動した直後に参照するファイルをそれぞれのアプリケーションに対して記入すること|
|Homebrew|MacOS用のバージョン管理ツール|
|||
|||
|||


ターミナルとシェルの違い
ターミナル＝GUIの上でCUIの操作をしたいときに使用するアプリケーション　ex)iTerm
シェル＝Linux利用者とOSの中心部分カーネルなどに命令を伝えてくれるプログラムの一種

ターミナルの中はシェル？？
ターミナル>シェルかな



#コマンドの使い方を忘れたら
①--helpを使う
ex) rm --helpでオプションも確認することが出来る

②manコマンド（manual）を使う
ex) man bash

#コマンド読解

|コマンド|意味|
|--|--|
|export|環境変数やシェル変数を設定する|
|source|シェルの設定を即座に反応させる。.zshrcなどを編集した時にその変更をすぐに反映させるために使う<br>ex) source ~/.bashrc|
|eval|変数の２重展開が可能となる。$()がある時に使われている|
|grep|検索する時に条件を絞るために使う|
|||



#使うコマンド
|やりたい事　　　　　　　　　|コマンド　　　　　　　　　|
|--|--|
|sh ex) sh .env|
|環境変数を実行する|source ex)source .envで.envにはexport 〇〇=〇〇|
|シェルを再起動する| exec $SHELL -l|
|直前のコマンド引数を受け取る|$_|
|複数のフォルダを同時に作成する|mkdir {名前,名前}<br>スペースはいらん！|

#Vim（テキストエディタの一種）について
##テキストエディタとは
Windowsでいう「メモ帳」などのように文字列を編集するために使うソフトのこと
##２つのモードについて
ノーマルモード（コマンドを実行する）と
インサートモード（テキストの入力を行う）がある。

sudo vi ファイル名　でVimを起動した直後はノーマルモードで、

インサートモードに切り替えるにはa
ノーマルモードに切り替えるにはEscキー

##Vimでよく使うコマンド
|やりたい事　　　　　　　　　　　　|コマンド　　　　　　　　　　　　　　|
|---|---|---|
|ファイルを編集|sudo vi ファイル名|
|まとめて選択|shift vで上や下を押して選択範囲を決め、dでまとめて削除|
|右に移動|l|
|左に移動|h|
|上に移動|k|
|下に移動|j|
|保存せずに終了（編集した場合）|:q!|
|保存せずに終了（何も編集していない場合）|:q|
|保存する|:w|
|保存して終了|:wq|
|インサートモードに切り替え|a|
|ノーマルモードに切り替え|Escキー|

#シェルのコマンド

##シェルとは
ターミナル（黒い画面）に打ち込んだコマンドを実行するプログラムのこと

###パスを通すとは
シェルが起動した直後に参照するファイルにパスを記述することでそれが使われるようにすること

書き方

```
export PATH=""
```




|やりたいこと|コマンド|
|--|--|
|シェルの再起動|exec $SHELL -l（lはloginのl）|
|ディレクトリの中身を移動させる|mv 移動したいパス　場所<br>{\*,.\*}で全ての, .がついた全てのファイルという意味になる　<br>ex) mv front/app{*,.*} front|
|||
|||
|||
|||
Dockerでリモートデスクトップがubuntuに繋がらなくなった場合の対処法

Docker上でWindowsのリモートデスクトップでubuntuのデスクトップを表示し、終了して、
再起動して再びリモートデスクトップで繋ごうとしたら、繋がらなくなった。

繋がる場合は↓のようになる。

![スクリーンショット 2021-07-25 093717.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430586/3ee874cc-6c6f-df93-3c62-74523b1e11ae.png)

繋がらない場合は↓のようになる。

![スクリーンショット 2021-07-25 094100.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430586/60d8ee3c-fc58-e020-7574-3dedad8d7c94.png)

service xrdp start　でスタートさせると、下記のような表示になる。

```
service xrdp start
 * Starting Remote Desktop Protocol server                                                                              It looks like xrdp is allready running,
if not delete the xrdp.pid file and try again
sesman is already running.
if it's not running, try removing /var/run/xrdp/xrdp-sesman.pid

```
ここで、/var/run/xrdp/xrdp-sesman.pid　を削除しても繋がらない

rm /var/run/xrdp/*　

とし、(/var/run/xrdpフォルダ内をすべて削除)
service xrdp stop
service xrdp start

とすると、繋がる。



以上

これでもダメな場合下記記事を参照してください。
https://qiita.com/nihonmatsu/items/90a397b1286f7c31bf3a
特定の期間の投稿数表示：今日の投稿数、今週の投稿数　scope

<h2>やりたいこと</h2>
今日の投稿数、昨日の投稿数、前日比％
今週の投稿数、先週の投稿数、先週比を表示させたい。


<h3>モデルファイルの記述</h3>

```perl:book.rb
  scope :created_today, -> { where(created_at: Time.zone.now.all_day) } 
  scope :created_yesterday, -> { where(created_at: 1.day.ago.all_day) } 
  scope :created_this_week, -> { where(created_at: 6.day.ago.beginning_of_day..Time.zone.now.end_of_day) } 
  scope :created_last_week, -> { where(created_at: 2.week.ago.beginning_of_day..1.week.ago.end_of_day) } 
```

モデルファイルにスコープで記述します。こうやってモデルファイルで定義しておけば、
コントローラーもスッキリするのはわかります。

<h4>Scopeって何・・・・？</h4>

モデル側であらかじめ特定の条件式に対して名前をつけて定義し、
その名前でメソッドの様に条件式を呼び出すことが出来る仕組みのこと　だそう。

https://pikawaka.com/rails/scope

<h3>コントローラーの記述</h3>

```perl:users_controller.rb
    @books = @user.books.page(params[:page]).reverse_order
    @today_book =  @books.created_today
    @yesterday_book = @books.created_yesterday
    @this_week_book = @books.created_this_week
    @last_week_book = @books.created_last_week
```

bookモデルに記述した定義も、usersコントローラーで使用可能！

<h3>View</h3>

```
 <table class="table">
  <thead>
  <tr>
   <th>今日の投稿</th>
   <th>昨日の投稿</th>
   <th>前日比</th>
  </tr>
  </thead>
   <tbody>
    <tr>
     <td><%= @today_book.count %></td>
     <td><%= @yesterday_book.count %></td>
     <% if @yesterday_book.count == 0 %>
     <td>前日の投稿はなし</td>
     <% else %>
       　<td><% @the_day_before =   @today_book.count / @yesterday_book.count.to_f  %>
       　<%= (@the_day_before * 100).round %>%</td>
     <% end %>
     </tr>
   </tbody>
  </table>
  
  
  <table class="table">
  <thead>
  <tr>
   <th>今週の投稿</th>
   <th>先週の投稿</th>
   <th>比</th>
  </tr>
  </thead>
   <tbody>
    <tr>
     <td><%= @this_week_book.count %></td>
     <td><%= @last_week_book.count %></td>
     <% if @last_week_book.count == 0 %>
     <td>先週の投稿はなし</td>
     <% else %>
       　<td><% @the_week_before =   @this_week_book.count / @last_week_book.count.to_f  %>
       　<%= (@the_week_before * 100).round %>%</td>
     <% end %>
     </tr>
   </tbody>
  </table>
```

難しかったのは、前日比、先週比の出し方です。
```<td><% @the_week_before =   @this_week_book.count / @last_week_book.count.to_f  %>
       　<%= (@the_week_before * 100).round %>%</td>```
まず、```to_f```は少数点までの数値まで表示してくれるそうです。
それに１００をかけて％で表示されます。

<h2>終わりに</h2>
scope使いこなせるようになりたい！！！
linuxコマンド メモ

## 基本

```console:表示
ls [オプション]

-a　全部出力
-l　詳しく出力
```


```console:コピー
cp [オプション] コピー元 コピー先

-i　確認出す
-r　再帰
-p　元の情報そのまま
```

```comsole:移動、名前の変更
mv 移動元ファイル 移動先ファイル

-i　確認出す
```

```comsole:削除
rm ファイル名

-i　確認出す
-f　強制
-r　再帰
```

```comsole:ディレクトリ作成
mkdir ディレクトリ名

-p　階層で書くと一気に作る
```

```comsole:ディレクトリ削除
rmdir ディレクトリ名

-p　階層で書くと一気に削除
#ディレクトリ内が空の時しか削除できないので安全
```

```comsole:ファイルの中身を表示
cat ファイル名
-n　行番号を表示
```

```comsole:ファイルの中身を表示
less ファイル名
/単語　検索
q　抜ける
```

```comsole:ファイル検索
find パス -name ファイル名
```

```comsole:コマンドのパス表示
where コマンド名
```

```comsole:コマンドのヘルプ参照
コマンド --help
```

```comsole:コマンドのマニュアル参照
man コマンド
```

```comsole:リダイレクト
ls > ls-output-file
```

```comsole:エラー出力リダイレクト
ls sonzaisinai-file 2> ls-output-file
```

```comsole:grep
grep [オプション] 検索条件 [指定ファイル]
```

```comsole:ファイル内末尾参照
tail [オプション] ファイル名

-n　表示行数指定
-f　リアルタイムで更新
```

```comsole:テキストの中身をソート
sort [オプション] ファイル名

-r　逆ソート
-k n　n列目のデータをソート
-n　数値としてソート（デフォルトでは辞書順ソートのため）
```

```comsole:比較
diff [オプション] ファイル１ ファイル２

-u　詳しく表示
-c　詳しく表示
```

## 管理

```comsole:ユーザー
useradd ユーザー名
usermod ユーザー名
userdel ユーザー名
```

```comsole:グループ
groupadd グループ名
groupmod グループ名
groupdel グループ名
```

```comsole:パスワード登録・変更
passwd [ユーザー名]
```

```comsole:ユーザー変更
su - [ユーザー]
#指定しなかったらroot
```

```comsole:sudo
sudo コマンド
```

```comsole:所有者の変更
chown ユーザー ファイル
```

```comsole:アクセス権の変更
chmod モード ファイル
#モード：ユーザー グループ その他
```

##シェルスクリプト

```shell:おまじない
#!/bin/bash
コマンド
・
・
・
```
実行可能権限に変更すること

## ネットワーク
```comsole:ipの確認
ip a
```


```comsole:ping
ping [ホスト名] -c [回数]
```

```comsole:経路の確認
traceroute [ホスト名]
```

## プロセス

```comsole:プロセスの確認
ps [オプション]

-A　全部出力
l　詳しく出力
```

## ファイル

```comsole:ディスク空き確認
df [オプション]
-H　見やすくなる
```

```comsole:ディレクトリの容量確認
du 
```
npmとかyarnて結局何？

#本記事
本記事は初学者を対象とした記事です。
npmとかyarnをざっくり説明しています。


#npmとyarnとは
どちらも**Node.js**で動作するパッケージマネージャのこと。
それぞれ、**Node Package Manager**と**Yet-Resource-Negotiator**の略称。

#Node.jsとは
サーバーサイドで動かすことができるJavaScript。
※奇数が開発版で、偶数が安定板。

#JavaScriptにおけるパッケージマネージャ-とは
Nodeの開発に伴いフレームワークが開発されるなど、飛躍的な進歩を遂げることとなるが、同時に必要なものをインストールするのに工夫が必要となった。
（フレームワークを構成するのにプログラムのインストールが１０００個とかあると大変！もちろんバージョン管理もしないといけない！）
筆者は何も考えずにインストールしていたのですが、`npm list`を開発していたアプリで実行して軽く引きました（恥ずかしい話ですが、、、）。


#npm
Node.jsと同時にインストールされている。
2009年にNode.jsが開発されたのち、2010年1月にリリースされている。

#yarnって？
2016年にリリースされたnpmと互換性のある新しいパッケージマネージャー。
新しいぶん、使いやすい。以下のような特徴がある。
1.npmと互換性がある。
2.インストールが速い。
3.セキュリティが高い。
4.強固なバージョン管理が可能。

yarnでパッケージのインストールをした後、yarn.lockというファイルが生成される。中にはインストールしたパッケージが使用している別のパッケージのバージョンが明確に書き込まれる。

`yarn init`コマンドを実行すると、package.jasonファイル（プロジェクトの設定ファイル）が生成される(`npm init`も同じ)。


#参考文献

https://www.sejuku.net/blog/96866

https://qiita.com/Hai-dozo/items/90b852ac29b79a7ea02b

https://e-words.jp/w/Yarn.html

#最後に
書いてて気づいたのですが、既に多くの方が書かれている内容でした。
自身の知識定着も兼ねて書いたのですが、わかりにくい場合は参考文献にURLを貼っておりますので、そちらの記事を読まれることをお勧めします。
お付き合いいただきありがとうございました。