OmniAICreator/Qiita-1.07M huggingface dataset:
CodeSignal - firstNotRepeatingCharacterにチャレンジ

コーディングしなさすぎてコーディングを忘れたエンジニアがコーディングを思い出すためにコーティングします。
今回は、アメリカのコーデイング練習サイトCodeSignalの問題「firstNotRepeatingCharacter」を解いていきます。
サイトによると、この問題はAmazonの面接で出されたことがあるようです。

##問題
"abacabaed"のような文字列sが渡されるので、最初に出てくる重複していない文字を探します。
上の例だと、重複していないし最初に出てくるのでcが答えです。

もし重複している文字がない場合は、'_'を返します。

##考え方・解説
最初は単純に、文字を一つずつループして、もう一つループを回して他の文字と比較し、重複がない文字を探す方法が浮かびました。
しかしこの方法で回答すると、実行時間超過でテストが一部通りませんでした。

そこで、この解き方の無駄を探すと、それぞれのループで全ての文字をチェックしていたので、重複した文字を何度も比較してしまっていることに気づきました。
たとえば、文字列の中にaが1000回あれば、2回目のaでその文字は重複しているため答えではないのがわかるのに、その後の997個のaも比較をしている、という具合です。

そこで、ループで重複が検知できたらループを即座に抜け、次の確認する文字に移るという回答に書き換えたところ、テストに通ることができました。

Javaで書くとこんな感じです。

```Java
char firstNotRepeatingCharacter(String s) {
    boolean unique;
    for (int i = 0; i < s.length(); i++) {
        unique = true;
        for (int j = 0; j < s.length(); j++) {
            if (i != j && s.charAt(i) == s.charAt(j)) {
                unique = false;
                break;
            }
        }
        if (unique) {
            return s.charAt(i);
        }
    }
    return '_';
}
```
コードの説明
2つのforは文字列の各文字を一つづつループしています。
1つめのifで2つのループそれぞれの文字を比較し、同じであればその文字は重複あり、つまり答えではないので、uniqueフラグをfalseにします。
と同時に、breakでループを抜け次の文字に移ります。

各文字がループし終わるたびに、2つめのifの部分で変数uniqueの結果を確認し、trueのままの文字があればそれは重複していなかったことを意味するので、答えとして返却します。

最後まで何も返却されなければ、重複なしのため'_'を返します。

##感想
2つのループどちらもすべての文字をチェックするのは無駄かなとなにか改善しようと試みましたが、重複があればすぐにループがbreakされるので、結局問題ないようでした。

回答後、他の人の回答を見るともっと上手いやり方があって勉強になりました。
そのコードを載せるのは微妙なので仕組みだけ書くと、ループは一つで、各文字について文字列sの中で出現する位置を確認し、最初のインデックス（s.indexOf）と最後のインデックス（s.lastIndexOf）を取得します。
それらのインデックスが同じ値であれば、文字列の中に1個しか存在しないので、重複なし（＝答え）。
インデックスが異なれば、複数存在しているので重複あり（＝答えではない）、という感じでした。

自分にはまったく思い浮かびませんでした。
ネステッドループを無くすというアイデアをしつこく考えれば、もしかしたら思い付けたかもしれません。
折返しのある系列を巻き戻す

# 折返しのある系列を巻き戻す

こんな感じで直線（的なもの）が折り返されているときに、折返しを巻き戻したい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219428/52a18236-9dde-a211-a2ac-b6a851ed0282.png)

最終的に完全な直線に乗るとは限らないので、最小二乗法で直線近似をする。基本的な考え方としては、数の系列$x_{k}$と、折返し何周目なのかを表す系列$y_{k}$を使い、折返しを元に戻したときにできるだけ直線に近くなるようにする。図では連続的に点があるが、途中の点が抜けてもいいように考慮する。

系列$x_{1},x_{2},\ldots,x_{N}$について、非減少系列$y_{1},y_{1},\ldots,y_{N}(y_{k} \leq y_{k + 1},\ y_{k} \in Z)$があったとき、重み$w_{1},\ldots,w_{N} \in \left\\{ 0,1\right\\}$を既知として

$$w_{n}(x_{n} + \alpha y_{n})$$

ができるだけ等差数列に近くなるように$\alpha$を決めたい。

最終目標となる等差数列を

$$a + bn$$

とおく。この時の二乗誤差は

$$e^{2} = \sum_{i = 1}^{n}{w_{n}\left( x_{n} + \alpha y_{n} - a - bn \right)}^{2}\quad　(1)$$

$$\frac{\partial e^{2}}{\partial\alpha} = \sum_{n = 1}^{N}{2w_{n}y_{n}(x_{n} + \alpha y_{n} - a - bn)} = 0\quad　(2)$$

$$\frac{\partial e^{2}}{\partial a} = - \sum_{n = 1}^{N}{2w_{n}(x_{n} + \alpha y_{n} - a - bn)} = 0\quad　(3)$$

$$\frac{\partial e^{2}}{\partial b} = - \sum_{n = 1}^{N}{2nw_{n}(x_{n} + \alpha y_{n} - a - bn)} = 0\quad　(4)$$

ここで次のような数を考える。

$$\sum_{n = 1}^{N}{w_{n}x_{n}} = S_{X}$$

$$\sum_{n = 1}^{N}{w_{n}y_{n}} = S_{Y}$$

$$\sum_{n = 1}^{N}{w_{n}x_{n}y_{n}} = S_{\text{XY}}$$

$$\sum_{n = 1}^{N}{w_{n}y_{n}^{2}} = S_{YY}$$

$$\sum_{n = 1}^{N}{w_{n}nx_{n}} = M_{X}$$

$$\sum_{n = 1}^{N}{w_{n}ny_{n}} = M_{Y}$$

$$\sum_{n = 1}^{N}w_{n} = W$$

$$\sum_{n = 1}^{N}{w_{n}n} = \Sigma$$

$$\sum_{n = 1}^{N}{w_{n}n^{2}} = \Sigma_{2}$$

(3)より、

$$S_{X} + \alpha S_{Y} - a W - b\Sigma = 0 \quad(5)$$

(2)より

$$S_{XY} + \alpha S_{YY} - a S_{Y} - b M_{Y} = 0\quad　(6)$$

*(4)より*

$$M_{X} + \alpha M_{Y} - a\Sigma - b\Sigma_{2} = 0\quad　(7)$$


以上より


$$
\begin{pmatrix}S_{XY} \\\\ S_{X} \\\\ M_{X}\end{pmatrix} + 
\begin{pmatrix}
S_{YY} & - S_{Y} & - M_{Y} \\\\
S_{Y} & - W & - \Sigma \\\\
M_{Y} & - \Sigma & - \Sigma_{2}
\end{pmatrix}\begin{pmatrix}
\alpha \\\\
a \\\\
b 
\end{pmatrix} = 0$$

これを解いて$\alpha$を求めるとよい。プログラムで書けばこんな感じ。

```{R}
findlinear <- function(pos,x,y) {
  if (max(y) == 0) {
    # only one segment
    model <- lm(x~pos,data=data.frame(x=x,pos=pos))
    return(c(0,model$coefficients))
  }
  sx <- sum(x)
  sy <- sum(y)
  sxy <- sum(x*y)
  syy <- sum(y^2)
  mx <- sum(pos*x)
  my <- sum(pos*y)
  v <- -c(sxy,sx,mx)
  n <- length(pos)  
  sn <- sum(pos)
  sn2 <- sum(pos^2)
  m <- matrix(c(syy,-sy,-my,sy,-n,-sn,my,-sn,-sn2),
              nrow=3,ncol=3,byrow=TRUE)
  solve(m,v)
}
```

やってみるとこんな感じ

```{R}
> x
 [1]   0   3   6   9  12 -14 -11  -8  -5  -2   1   4   7  10  13 -13 -10  -7  -4
[20]  -1   2   5   8  11  14 -12  -9  -6  -3   0   3   6   9  12
> y
 [1] 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3
> n
 [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
[26] 26 27 28 29 30 31 32 33 34
> findlinear(n,x,y)
[1] 29 -3  3
> plot(x+29*y)

```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219428/6c9688a8-e05d-7462-8e02-08a636e0461b.png)

[その2](https://qiita.com/akinori-ito/items/ecd62a90651822acb184)に続く。
【Java】新卒が初めてのコードレビューで受けた指摘５選

## はじめに

新卒でSIerのJavaプログラマとして働き始めて２ヶ月が経ちました。
忙しい中、自分の拙いコードを見てくださる先輩方には感謝しかありません。

今後同じ指摘を受けないように、コードレビューでの指摘をまとめようと思います。

## ①Nullぽを起こさないようにチェックを入れる。

```Java
    Customer customer = getCustomer(request);
    System.out.println("ようこそ、" + customer.getName() + "さん");
```

もしgetCustomerで顧客情報が取得できなかった場合、customerはnullとなり、getNameメソッドを呼び出す時点でヌルポが発生します。

Nullチェックするときは、CollectionUtils.isEmptyとか、StringUtils.isEmptyとかを使いましょう。

https://qiita.com/mtanabe/items/fdfd304e461fd50e10ff



https://qiita.com/mtanabe/items/80423ae4a0147b40245c


## ②Stringのequalsメソッドで比較する際は、定数を左に持ってきてヌルポを回避する

```Java
    String answer = getAnswer();
    
    if(answer.equals("A")) return "正解です";  // (1)
    if("A".equals(answer)) return "正解です";  // (2)
```
(1)の場合は、仮にgetAnswerで答えを取得できずanswerにNullが入ったらヌルポが起こります。
(2)の場合は、左側に定数があるためヌルポは起こりません。


https://loglog.xyz/programming/javaconstleft


## ③マジックナンバーは使わない

数値とか、”01”みたいな文字列は、後々何を表すか分からなくなります。
以下のコードは、なんとなく”01”と”02”が春夏で、”03”と”04”が秋冬であると察せますが分かりにくいです。また、別の箇所で”01”が、全然違った意味で使われた場合、確実に混乱します。

```Java
    String seasonNo = clothes.getSaleSeasonNo();
    
    if("01".equals(seasonNo) || "02".equals(seasonNo)) return getThisYear() + "SS";
    if("03".equals(seasonNo) || "04".equals(seasonNo) ) return getThisYear() + "AW";
 ```   

マジックナンバーには名前をつけてあげましょう。

```Java
    private final String SPRING = "01";
    private final String SUMMER = "02";
    private final String AUTUMN = "03";
    private final String WINTER = "04";
```

https://vertys.net/java-magic-number/


## ④定数を作る

プログラム内で変わらない値がある場合は、定数として定義します。
必要であれば、どんな定数かコメントアウトをつけましょう。
また、変数名は大文字にします。

```Java
    public class Sample {
      private static final String GREETING_MESSAGE = "Hello, world!";
      System.out.println(GREETING_MESSAGE);
    }
```

また、様々な場所で使われる定数の場合は、切り出しましょう。

https://qiita.com/cabab/items/ed669e36097861fb00e7


constsパッケージ内のConstクラスに書けばいいかなと思っていましたが、Enumクラスというものを初めて知りました。


https://engineer-club.jp/java-enum


### ※余談 private static finalについて目に止まった記事

https://qiita.com/Qiitaman/items/743013921e3ed31d948f

https://sakuramochi702.hatenablog.com/entry/2013/07/10/143255




## ⑤いらないelseを書かない

シンプルにこちらの記事がとても分かりやすかったです。
https://refactoring-brique.info/logic/else/
Javaで経過日数を計算したい

Javaで経過日数を計算したい場合、もっともシンプルなのは`LocalDate`と`ChronoUnit`を利用するものです。

```java
public static long diff(LocalDate localDate1, LocalDate localDate2) {
    return ChronoUnit.DAYS.between(localDate1, localDate2);
}
```

しかしライブラリや開発環境の都合上、`Date`や`Calendar`を利用せねばならないということもあります。この場合、`Date`や`Calendar`を`LocalDate`に変換してしまうのがもっともわかりやすいと思います。

```java
public static long diff(Date date1, Date date2) {
    LocalDate localDate1 = date1.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
    LocalDate localDate2 = date2.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
    return ChronoUnit.DAYS.between(localDate1, localDate2);
}
    
public static long diff(Calendar calendar1, Calendar calendar2) {
    LocalDate localDate1 = calendar1.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
    LocalDate localDate2 = calendar2.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
    return ChronoUnit.DAYS.between(localDate1, localDate2);
}
```

利用しているJavaのバージョンやコーディングルールなどにより、そもそも`LocalDate`の利用ができない場合は、おとなしく秒数から計算しましょう(´・ω・`)

```java
public static long diff(Date date1, Date date2) {
    long time1 = date1.getTime();
    long time2 = date2.getTime();
    return Math.abs(time1-time2) / (1000*60*60*24);
}

public static long diff(Calendar calendar1, Calendar calendar2) {
    long time1 = calendar1.getTimeInMillis();
    long time2 = calendar2.getTimeInMillis();
    return Math.abs(time1-time2) / (1000*60*60*24);
}
```

__環境情報__

```
D:\>javac --version
javac 11.0.10

D:\>java --version
openjdk 11.0.10 2021-01-19
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.10+9)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.10+9, mixed mode)
```
gulpでSass環境構築とエラー紹介

## 前提
Nodeはインストール済とします。
## 作業
プロジェクトのホームディレクトリから下記のコマンドを叩いて、package.jsonを作成します。

```
$ npm init -y
```
gulpを使用してsassの環境を構築していくので、下記のコマンドを叩いてインストールを行う。

```
$ npm install --save-dev gulp
$ npm install --save-dev gulp-sass
```
次に同じ階層にgulpfile.jsを作成して以下のように記述。

```gulpfile.js
var sass = require('gulp-sass')(require('sass'));
var gulp = require('gulp'); 
 
gulp.task("sass", function(done){
    gulp.src("./sass/**/*.scss")
    .pipe(sass({outputStyle: "expanded"}))
    .pipe(gulp.dest("./css"));
    done();
});
// 下記の設定で自動コンパイルをすることができる。
gulp.task("watch", function(){
  gulp.watch("./sass/**/*.scss", gulp.series(["sass"]))
});
```
sassのディレクトリを作成して、中にscssなどのファイルを作成した後に下記のコマンドでコンパイル。

```
$ npx gulp sass
```
自動コンパイルはこちら

```
$ npx gulp watch
```

## 遭遇したエラー
其の１

```
gulp-sass 5 does not have a default Sass compiler; please set one yourself.
Both the `sass` and `node-sass` packages are permitted.
For example, in your gulpfile:

  var sass = require('gulp-sass')(require('sass'));

[21:46:51] The following tasks did not complete: sass
[21:46:51] Did you forget to signal async completion?
```
gulpfile.jsのvar sass部分の記述方法をエラー文の通りに変更すれば解決しました。

其の２

```
Error: Cannot find module 'sass'
Require stack:
- /Users/***/practice/error_gulp/gulpfile.js
- /Users/***/practice/error_gulp/node_modules/gulp-cli/lib/shared/require-or-import.js
- /Users/***/practice/error_gulp/node_modules/gulp-cli/lib/versioned/^4.0.0/index.js
- /Users/***/practice/error_gulp/node_modules/gulp-cli/index.js
- /Users/***/practice/error_gulp/node_modules/gulp/bin/gulp.js
    at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15)
```
gulpのsassをおとなしくインストールしたら、解消しました。

```
$ npx gulp sass
```

【備考】
Nodeとgulpのバージョンの相性が悪いと、エラーが出てしまう事があるようです。
【Next.js】ChunkLoadError: Loading chunk node_modules_next_dist_client_dev_noop_js failedへの対処

## はじめに
Next.jsで開発をしていると、下記エラーが出現しました。
（画像はとり忘れてしまったので、次に出た時に更新します。）

## エラー内容

```
Unhandled Runtime Error
ChunkLoadError: Loading chunk node_modules_next_dist_client_dev_noop_js failed.
(error: http://localhost:3000/_next/static/chunks/fallback/node_modules_next_dist_client_dev_noop_js.js)
```

## 解決策
一番上にある「.next」フォルダを削除する。
（コンパイルする度に生成されます。）
削除したらエラーは出なくなりました。

<img width="300px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626568/594fa815-4006-8997-7d31-a47537e07fe7.png">

## 原因
詳しい原因はわかりません。すみません。
ただ、stackoverflowによると、キャッシュが原因なのではないかとのことでした。

### 参考

- [ChunkLoadError: Loading chunk node_modules_next_dist_client_dev_noop_js failed](https://stackoverflow.com/questions/67652612/chunkloaderror-loading-chunk-node-modules-next-dist-client-dev-noop-js-failed)
- [Teamsで「Loading chunk failed」のエラーが出た時の解決方法](https://windows777.com/1190)（Next.jsとは関係ないですが、似たようなエラーがTeamsでもあり、キャッシュが原因とのことで参考として載せておきます。）
CentOSでライブラリ(yumコマンド)をインストールしようとしたらTimeOutしてしまってできなかった

# はじめに

インフラ系って何度やっても難しく感じますよね
私は普段からDockerを利用していまして、kubernetesがどんなものなのかよくわからなかったのでDevOpsの勉強がてら「[たった1日で基本が身に付く! Docker/Kubernetes超入門](https://amzn.to/3ffInJR)」というのを休日を使ってやることにしました。

内容はある程度Dockerを使っている人ならスムーズにできるのですが、途中から仮想マシンの上でDockerを使う必要があり、Docker for Desktopではなく、`Hyper-V`に仮想環境を作成して書籍を進める必要があります。

この仮想環境作成がかなり苦戦したので、今回はつまずいた点をまとめたいと思います。

# 環境

- Hyper-V
- CentOS7
- Docker

# 問題

まずは書籍通りに、CentOS7の環境を作成しました。

そして、dockerをインストールするため以下のコマンドを入力します。

```
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://download docker.com/linux/centos/docker-ce.repo
(以下省略)
```

すると、2行目で以下のようなエラーが発生します。

```
Loaded plugins: fastestmirror
adding repo from: https://download.docker.com/linux/centos/docker-ce.repo
grabbing file https://download.docker.com/linux/centos/docker-ce.repo to /etc/yum.repos.d/docker-ce.repo
Could not fetch/save url https://download.docker.com/linux/centos/docker-ce.repo to file /etc/yum.repos.d/docker-ce.repo: [Errno 12] Timeout on https://download.docker.com/linux/centos/docker-ce.repo: (28, 'Operation timed out after 30000 milliseconds with 0 out of 0 bytes received')
```

タイムアウトしてダウンロードできていないようです。
ネットワークの関係か私の環境ではダウンロードができませんでした。(最近ネット環境がひどいのもあります)

(メモ: CentOSでコマンドを打つときにUS配列になっていました。「:」はShift + ;で入力できました。「=」は「^」です)

# 解決方法

タイムアウトまでの時間を長くすることで解決しました。

```
sudo vi /etc/yum.conf
```

と入力して、

```
# 好きなところに以下の行を追加。viはESCキー→「:q」で終了。ただしUS配列は「:」のキーが違う
timeout=1000
```

と追加することでダウンロードができました。
私の環境がかなり遅かったので`1000`にしました。

# メモ

CentOSの環境作成の時に1つ間違えて、それが原因でダウンロードできなかったのも起きたのでメモしておきます。

CentOSのインストール時に、ネットワークの設定を「ON」にする必要があります。

![3-3-4-1-hostname.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/ce3fc4c3-e260-9ed2-3768-4f43ee641147.png)
[引用: CentOS 7 をインストール Linuxを始めるにはインストールからがお勧め](https://www.rem-system.com/centos-install/)

この「ON」と「OFF」のスイッチを勘違いして、うまく設定できていませんでした。
いま、「OFF」とみえるので、状態は「OFF」になります。「ON」にするにはスイッチをクリックする必要があります。

以前、このボダンをおすと「OFF」になるよみたいなのがあったせいで勘違いしました。

以下のような状態にしましょう。

![3-3-4-2-ipaddress.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/77e6a54c-94ea-5d92-5a7f-a28846e3e4f0.png)


(引用元から借りさせていただきました)

# おわりに

1日で身につくという趣旨の本でしたが、2章やるのに1日を使ってしまいました。(5時間くらい)
なぜか私のネットワークではインストールがかなり遅く、それにも多くの時間がかかりました。

インフラ系はとにかく躓いて、あきらめずに頑張るという感じではあるので今後も頑張っていきたいです。

とりあえず読了まではなんとかしたいですが、次はどんなエラーが起きるのでしょうか、、、、

# 参考
- [CentOS 7 をインストール Linuxを始めるにはインストールからがお勧め](https://www.rem-system.com/centos-install/)
SASSについて

#SASSとは
結論、CSSプリプロセッサー技術の一つ。
cssをより使いやすくした技術のこと。

##SASSのできること
- ネスト（入れ子構造）を使ってCSSが書ける
- 変数が使えて効率的な管理ができる
- よく使うCSSをパーツ化して使い回すことができる。

>同じことを何度も書かなくていいので、効率的かつとても見やすくなる。

##Sass(SCSS)の具体的な使い方
- ネスト

```scss
.container {
  h1 {
    color: red;
    font-size: 21px;
  }

  p {
    color: blue;
    font-size: 50px;
  }
}
```

- 変数

```scss
$main-color:red;
```

- mixin
mixinは引数を渡すことができる。

```scss
$main-color:red;
@mixin name($bgColor) {       //パーツ化
  background-color: $bgColor;
  padding: 10px;
  color: blue;
}

.container {
  h1 {
    color: $main-color;
    font-size: 21px;
  }

  p {
    @include name(#000);      //@includeで呼び出し
  }
}
```
- & （アンパサンド）

```
    <ul>
      <li class="work">仕事</li>
      <li class="private">プライベート</li>
    </ul>
```

```
  ul {
    li {
      &.work{              //ワークのみが白で表示される
        color: white;
      }
    }
  }
```
- 四則演算

```
width: 100px * 2;       //四則演算も使える
```
- import 

```
@import "ファイル名.scss";
```
よくあるファイルを読み込んで使う形式。


##SCSSをコンパイル
ブラウザはSASSやSCSSを読み解くことができないため、CSSに変換(コンパイル)する必要がある。

コンパイルについては方法の選定や実際の設定がまだよく理解できていないので、別の機会にします。
文字列の出現回数を数えたい

特定の文字列の出現回数を数えたい場合、たとえばPythonだと

```
$ python3
Python 3.8.5 (default, Jul 28 2020, 12:59:40)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> "AABABAAAB".count("AB")
3
```

というように、非常に簡単に書けるのですが、Javaでは一工夫が必要になります。

```java
public static int count(String string, String target) {
    int i = -1;
    int c = 0;
    while ((i = string.indexOf(target, i+1))!=-1) c++;
    return c;
}
```

実際に使ってみると、次のようになります。

```java
System.out.println(count("AABABAAAB", "A"));    //=> 6
System.out.println(count("AABABAAAB", "AB"));   //=> 3
System.out.println(count("AABABAAAB", "ABA"));  //=> 2
System.out.println(count("AABABAAAB", "AAAA")); //=> 0
```

想定通りに動いていそうですね(´・ω・｀)

___環境情報___

```
D:\>javac --version
javac 11.0.10

D:\>java --version
openjdk 11.0.10 2021-01-19
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.10+9)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.10+9, mixed mode)
```

__2021/08/01 22:45追記__

上記のロジックは「文字列の出現回数を**重複あり**で数える」もので、Python3と同じように「文字列の出現回数を**重複なし**で数える」場合は以下のようにすべきでした。

```java
public static int count(String string, String target) {
    int c = 0;
    int i = 0;
    int len = target.length();
    while ((i=string.indexOf(target, i))!=-1) {
        c++;
        i += len;
    }
    return c;
}
```
自分と同じLAN内にある機器のMACアドレスを取得する

# はじめに
自分のPCと同じLAN内にある機器（192.168.0.0/24）のMACアドレスを調べたい。そこでpingコマンドを用いてarpテーブルに192.168.0.0/24の機器のMACアドレスを記録し、それをarpコマンドで取得。

# pingコマンドを用いてarpテーブルにMACアドレスを記録
```shell
echo 192.168.207.{0..254} | xargs -P256 -n1 ping -s1 -c1 -W1
```
これで自分のPCと同じLAN内にある機器（192.168.0.0/24）のMACアドレスがarpテーブルに記録される。
`|`はUnix系オペレーティングシステムのパイプ(pipe)である。複数のプログラムの入出力をつなぐための仕組みで、今回は`echo`コマンドで標準出力に出力したipアドレスへ`xargs`と`ping`コマンドを使ってpingを飛ばす。

https://ja.wikipedia.org/wiki/%E3%83%91%E3%82%A4%E3%83%97_(%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF)#:~:text=Unix%E7%B3%BB%E3%82%AA%E3%83%9A%E3%83%AC%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E3%81%AE,%E5%AE%9F%E8%A1%8C%E3%81%A7%E3%81%8D%E3%82%8B%E5%88%A9%E7%82%B9%E3%81%8C%E3%81%82%E3%82%8B%E3%80%82

```shell
echo 192.168.0.{0..254}
```
192.168.0.0から192.168.0.254までのipアドレスを標準出力に出力する。

https://kazmax.zpp.jp/linux/bash_tips.html

```shell
xargs -P256 -n1 ping -s1 -c1 -W1
```

`xargs`のオプション

- `-P256`: 同時に実行するプロセス数の上限が256という意味
- `-n1`: 1回のコマンドラインで使用する引数の上限が1という意味（この指定によって各ipアドレスへpingが飛ばされる）


`ping`のオプション

- `-s1`: pingの試験するパケットサイズを1に設定する
- `-c1`: pingの回数を1に設定する
- `-W1`: 送信した各パケットの返信を10ミリ秒待つ時間（どれくらいの時間をとればいいのかはよくわからないのでちょっと長めにした、大体は1ms以内に返信が返ってくる）


https://www.atmarkit.co.jp/ait/articles/1801/19/news014.html

https://eng-entrance.com/linux-command-ping


# arpコマンドを用いてarpテーブルの内容を取得（ついでに保存）
```
$ arp -a > arp.log
```
arpテーブルの内容を`arp.log`に保存
`-a`は現在のARPエントリーのすべてを表示する

# 最後に
自分の備忘録として書きました。情報系の人にとっては何をいまさらという内容だったかもしれません。
【JS】チェーンメソッドのTips

# チェーンメソッド's Tips
いくつもメソッドを連続で実行するためには、一工夫するだけで実行できます。
それは、メソッド末尾に`return this;`と返すだけです。
以下の例では、最後にthisを返すことで、`Person`オブジェクトを返すことになるので、チェーンにしてもエラーが発生せずに実行出来ます。

```js
class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  hello(person) {
    console.log(`hello ${person.name}`);
    return this;
  }

  bye(person) {
    console.log(`Goodbye, ${person.name}.`);
    return this;
  }
}

// インスタンスを生成
const bob = new Person('Bob', 23);

// チェーンメソッドで実行する
bob.hello(bob).bye(bob);
// => 'hello bob' 'Goodbye, bob'
```
21 最小と最大 Dif:483 ABC195 B：「AtCoder　凡人が『緑』になるための精選50問詳細解説」サンプル

**この記事は拙著「AtCoder　凡人が『緑』になるための精選50問詳細解説」のサンプルです**
価格：100円
kindle：https://www.amazon.co.jp/dp/B09C3TPQYV
booth(pdf)：https://sano192.booth.pm/items/3179185

前：https://qiita.com/sano192/items/a86795c3851db8a897b9
次：https://qiita.com/sano192/items/780e1c4751b60cb0c8ed

https://atcoder.jp/contests/abc195/tasks/abc195_b

**【目標】**
・条件を満たす中での最小、または最大を求める問題を解けるようになる

**【概要】**
いつもはなんなくB問題を解けるという人でもこの問題に苦戦した人は多かったと思う。この手の問題の解法を自分で思いつくのは難しい。しかし「条件を満たす中での最小、または最大を求める問題」というのは解き方が決まっているのでそれを知っていれば簡単。この問題でやり方を身に着けよう。

**【方針】**
条件を満たす中での最小、または最大を求める問題では、答えの候補となる数について条件を満たすか順に確かめる、という方法を使う。

具体的に言うとこの問題では1個、2個、...が問題の条件を満たすか？ということを順に計算する。

X個が条件を満たすか？をどう判定するか。
1個あたりの重さはAグラム~Bグラム
ゆえに
X個の当たりの重さはAXグラム~BXグラム
ということになる。
よってXが以下の条件を満たせば良い。
AX<=1000W<=BX
(Wキログラムをグラムに直すために1000倍している)

次に考えるのはXの探索範囲、つまり条件を満たしうる最大の個数。
条件を満たしうる最大の個数はみかん1個あたりの重さが最小かつ重さの合計が最大、つまり
B=1かつW=1000
この場合条件を満たす最大の個数は10^6個。
よってX=1,２,...,10^6まで順に条件を満たすか計算して確認すればよい。

**【実装】**
入力を受け取る。

```python:
A,B,W=map(int, input().split())
```

Wはキログラムだが1000倍してグラムに直す。

```python:
W_g=W*1000
```

答えの最小値、最大値を格納する変数を作っておく。
最小値の初期値はバカでかい数(=10^15)
最大値の初期値はとてつもなく小さい数(=-10^15)
にしておく。
この問題に限らず最小値、最大値を求める問題の初期値はいつもそのように決めると覚えておこう。

```python:
min_ans=10**15
max_ans=-10**15
```

X=1、2、...が条件を満たすか順に確かめる。【方針】で説明したとおり、Xは最大10^6で十分だがてきとうにそれより少し大きな数として10^6+9まで探索している。

```python:
for X in range(1,10**6+10):
    if A*X<=W_g<=B*X:
        min_ans=min(min_ans,X)
        max_ans=max(max_ans,X)
```

後は答えの出力。
もし最小値=min_ansが一度も更新されていなければ条件を満たすXは存在しなかったということなので"UNSATISFIABLE"を出力する。

```python:
if min_ans==10**15:
    print("UNSATISFIABLE")

else:
    print(min_ans,max_ans)
```

この問題のようにB問題がやたら難しいということはたまに起きる。コンテスト中にB問題が解けないと焦るだろうが、さっさと諦めてC問題に移ろう。解ける問題を全て終わらせてから解けない問題を考えたほうがよい。
実際このコンテストはB問題よりC問題の方が簡単だったため、早めにB問題を捨ててC問題に取り掛かった人のほうが順位が高くなった。

**【コード全文】**

```python:
A,B,W=map(int, input().split())

W_g=W*1000

min_ans=10**15
max_ans=-10**15

for X in range(1,10**6+10):
    if A*X<=W_g<=B*X:
        min_ans=min(min_ans,X)
        max_ans=max(max_ans,X)

if min_ans==10**15:
    print("UNSATISFIABLE")

else:
    print(min_ans,max_ans)
```

**この記事は拙著「AtCoder　凡人が『緑』になるための精選50問詳細解説」のサンプルです**
価格：100円
kindle：https://www.amazon.co.jp/dp/B09C3TPQYV
booth(pdf)：https://sano192.booth.pm/items/3179185

前：https://qiita.com/sano192/items/a86795c3851db8a897b9
次：https://qiita.com/sano192/items/780e1c4751b60cb0c8ed
Node.js実行環境構築

#目的
Node.jsを用いて簡易なWebシステムを構築することを目的に、まずは動作環境の構築を行う。

#環境条件
- Node.jsサーバ
    - EC2：t2.micro
    - OS：Red Hat Enterprise Linux 8 (HVM), SSD Volume Type
    - Disk：汎用SSD（GP2） 10GB

セキュリティグループの設定等はいい感じに。

#構築手順

ec2-userでログイン

```
# rootユーザにスイッチ
sudo su - 
```

```
# Node.js用ディレクトリの作成
mkdir -p /opt/nodejs
```

```
# 作成したディレクトリへ移動
cd /opt/nodejs
```

```
# Node.jsのモジュールインストール
yum module install nodejs:14
```

```
# nodeの配置先の確認
which node
```

/usr/bin/node

```
# Node.jsのバージョン確認
node -v
```
v14.16.0

```
# NPMのバージョン確認
npm -v
```
6.14.11

この後のアプリケーション開発のために、同サーバにmysqlをインストールしたが、手順については割愛。
8.0.21をインストールし、rootアカウントのパスワードを設定。
ラズパイのUSBブート検証中

# はじめに
ラズパイはmicroSDカードの代わりにUSBメモリから起動することもできるが、その利点がよく分からない。高寿命を求めるなら、産業用microSDカードを使用すればいい気がする。

そこで実際に試してみようと考え、まずは、ブラウザの表示速度が変わるかどうかを検証した。
結論：変化なし

# 検証に使用したmicroSDカードおよびUSBメモリ
microSDカード：東芝 microSDHC 32GB EXCERIA 48MB/s UHS-I Class10
USBメモリ：‎Sandisk ULTRA FIT USB 3.0 16GB

# 検証に使用したOS

```
$ lsb_release -a
No LSB modules are available.
Distributor ID: Raspbian
Description:    Raspbian GNU/Linux 10 (buster)
Release:        10
Codename:       buster
```
```
$ uname -a
Linux raspberrypi 5.10.52-v7+ #1440 SMP Tue Jul 27 09:54:13 BST 2021 armv7l GNU/Linux
```

# 検証内容と結果
ラズパイのブラウザで「aaa」を検索し、Ctrl+F5で再読み込みをする。
再読み込みの時間を、開発者ツールのネットワークタブにあるFinishの値で確認する。

| 種類 | 1回目 | 2回目 | 3回目 | 4回目 | 5回目 | 6回目 |
|:-|:-|:-|:-|:-|:-|:-|
| microSDカード | 15.26s | 7.60s | 7.04s | 9.61s | 7.97s | 7.46s |
| USBメモリ | 7.11s | 7.39s | 7.24s | 7.14s | 7.36s | 9.26s |
JavaScriptでクラスを使ってみる。

# はじめに
JSでもクラスが使えるようになってとても便利だなと感じていますが、まだES5の名残りがあるコードはたくさんあるので、使ったことがない人もいるかと思います。これからは主流の書き方になると思うので、確実に押さえておきましょう！
これまでの使い方を復習した上で、クラスの使い方を見ていこうと思います。

# コンストラクタとは
コンストラクタとは、インスタンス(実体)を作成する関数のことです。

```js
function Person(name, age) {
  // プロパティを設定
  this.name = name;
  this.age = age;

  // メソッドを設定
  this.setName = function(name) {
      this.name = name;
  }
}

// コンストラクタからインスタンスを作成
let person1 = new Person('tanaka', 22);
```

## プロトタイプについて
メソッド定義の方法のことで、インスタンスが生成されるたびにコピーされることはないのでメモリの節約になります。

```js
Person.prototype.setName = function(name) {
    this.name = name;
}
```

# クラスの使い方

```js
class Person {
  // コンストラクタを設定
  constructor(name, age) {
      this.name = name;
      this.age = age;
  }

  // メソッドを設定
  hello(someone) {
    console.log('Hello ' + someone.name, ', I am ' + this.name + '.');
  }
}

let tanaka = new Person('Tanaka', 22);
let kato = new Person('Kato', 30);
kato.hello(tanaka);  // Hello Tanaka , I am Kato.
tanaka.hello(kato);  // Hello Kato , I am Tanaka.
```

## クラスの継承
クラスを継承することで無駄の無いコードを実装出来ます。継承には、`extends句`を使います。

```js
class Person {
  // コンストラクタを設定
  constructor(name, age) {
      this.name = name;
      this.age = age;
  }
}

// Personクラスを継承
class ChildPerson extends Person {
  // コンストラクタを設定
  constructor(name, age, person) {
    super(name, age) // Personクラスのプロパティを継承
    this.person = person
  }
}
```

# 終わりに
一部のブラウザではまだ機能できない事がありますが、これから調整されて利用できると思うので今から身につけておきましょう！

# 参考
[【JavaScript入門】コンストラクタの使い方]
(https://www.sejuku.net/blog/25328)

[JavaScriptのクラス（class）を理解する]
(https://techplay.jp/column/482)
[SwiftUI] NavigationBar の背景色を変える方法

こんな感じです：

**large**
![スクリーンショット 2021-08-01 午後11.36.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178570/2a2c1bf1-28d3-b576-ea67-8b1f1763af9a.png)

**inline**
![スクリーンショット 2021-08-01 午後11.36.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178570/4b223c77-f76e-1285-6b26-7ef4a37184af.png)

↓Backボタンを表示するために NavigationLink 先を preview しています

```swift
import SwiftUI

struct LargeTitleView: View {
    init() {
        UINavigationBar.appearance().backgroundColor = .blue // 背景色
        UINavigationBar.appearance().largeTitleTextAttributes = [ .foregroundColor: UIColor.white] // タイトル色
        UINavigationBar.appearance().tintColor = .white // backボタン色
    }
    var body: some View {
        VStack {
            Text("Hello, world!")
                .navigationTitle("title")
        }
    }
}

struct InlineTitleView: View {
    init() {
        UINavigationBar.appearance().barTintColor = UIColor.blue // 背景色
        UINavigationBar.appearance().titleTextAttributes = [ .foregroundColor: UIColor.white] // タイトル色
        UINavigationBar.appearance().tintColor = .white // backボタン色
    }
    var body: some View {
        VStack {
            Text("Hello, world!")
                .navigationTitle("title")
                .navigationBarTitleDisplayMode(.inline)
        }
    }
}

struct TitleView_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            NavigationView {
                NavigationLink(destination: LargeTitleView(), isActive: .constant(true)) { EmptyView() }
            }
            NavigationView {
                NavigationLink(destination: InlineTitleView(), isActive: .constant(true)) { EmptyView() }
            }
        }
    }
}
```

---

**バージョン**
Swift 5.4
作業申請用のメモ

実際に動いている本番機に対して、本番作業を行う際に必要な情報を記載します。
■本番作業名
--作業名　：○○移行
--作業概要：
--想定作業日時　：20〇〇
■体制
○○株式会社
--作業責任者：
--作業者：
--再鑑者：
--作業サポート（切り戻し手順等）：
--作業サポートその他担当：

○○株式会社（関係会社がいる場合）
--連絡窓口（承認者）：
--その他担当：

■作業対象
--作業対象（環境名/サーバ名等）：
--作業対象のOS再起動の有無：
--作業対象のサービス再起動の有無：

■作業リスクと影響範囲
--リスクNo/影響度/リスク内容/リスクが発現した場合の影響/影響範囲/対策・復旧方法

■作業項目/タイムチャート
--No　/大項目/中項目/作業者/再鑑者/リスクの有無/作業実施サーバ/タイムチャート
■作業承認
--体制確保/作業リスクの洗い出しと影響範囲の精査/切り戻し作業準備
graldeのSpring BootアプリケーションをHerokuへdeployしてみる

# 概要
Spring Boot(gradle)をHerokuへデプロイ時に意外と躓いたのでメモとして。
他にも困っている人の参考になればうれしいです。


# 環境
- windows 10 Home
- java 11
- spring-boot 2.3.5
- gradle 7.1.1  (gradlew)

#目次
<!-- タイトルとアンカー名を編集 -->
1. [前準備](#前準備)
1. [デモアプリ作成](#デモアプリ作成)
1. [デプロイ](#デプロイ)

#前準備
①Herokuのアカウントを作成
②Heroku Cliをインストール
>公式：https://devcenter.heroku.com/ja/articles/heroku-cli
 参考：[初心者向けherokuをデプロイしよう](https://qiita.com/DogK0625/items/12178fdc3dd607088ff0)

#デモアプリ作成
<a id="#Chapter2"></a>
とりあえず動きが見たいので、helloを返すだけのデモアプリを作成

一応githubに置いてあります。
https://github.com/Takeuchi713/spring-boot-gradle-heroku

```gradle:build.gradle
plugins {
	id 'org.springframework.boot' version '2.5.3'
	id 'io.spring.dependency-management' version '1.0.11.RELEASE'
	id 'java'
}

group = 'com.takeuchi'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-web'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

test {
	useJUnitPlatform()
}

```

```java:HelloController.java
@RestController
@RequestMapping("/api")
public class HelloController {

	@GetMapping("/hello")
	public ResponseEntity<String> hello(){
		return new ResponseEntity<String>("hello", new HttpHeaders(), HttpStatus.OK);
	}
}
```

# デプロイ
<a id="#Chapter3"></a>
ログイン、herokuのapp作成、、gitの設定、deployの設定などすべてコンソールで行う。

色々設定ファイルを追加するがすべてプロジェクトのrootへ追加が必要。
参考⇓
![heroku-project.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1295610/6a6c5378-22bf-2a26-4d80-dccb4c478c13.png)

### Heroku ～ gitの初期設定
```
gitレポジトリ化
>git init

Herokuへログイン
>~\deploy-heroku-maven\heroku login

アプリの作成。名前をしていしないとherokuが適当に作ってくれる
>heroku create

アプリ名を変更 (still-harbo-16072はherokuが適当につけた名前)
>heroku apps:rename --app still-harbor-16072 spring-gradle-deploy

Herokuをremoteへ追加
>heroku git:remote -a spring-gradle-deploy
```

### 設定ファイルを追加
```
デプロイ時のJavaバージョンを指定する設定ファイルを作成
>echo java.runtime.version=11 > system.properties

buildパスとdeploy時のportを一致させるための設定ファイルを作成
>echo web: java -Dserver.port=$PORT $JAVA_OPTS build/libs/heroku-demo-gradle-0.0.1-SNAPSHOT.jar > Procfile

※heroku-demo-gradleは自分のアプリ名
```

### デプロイ
```
全てコミット
>git add .
>git commit -am "first commit"

デプロイ
>git push heroku main
```

### 動作確認
![hello-gradle.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1295610/8580a05e-f740-7e5e-f94c-7ebbce62eb6f.png)


# 終わりに
とりあえず、最低限？の設定でHerokuへデプロイできることを確認。
次はpostgres込みのデプロイを試したい。

- [herokuでspring-bootをgradleを使ってデプロイするときのコツ](https://qiita.com/gosshys/items/fa02b390b60ee3001dae)
ubuntu20.04LTSにROS Noeticをインストールする


# 概要
ROS Noeticのインストール方法が変わっていたのでここに最新のインストール手順を書いておく


公式のインストールページ
http://wiki.ros.org/noetic/Installation/Ubuntu



# source.listの設定

```bash
$ sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'
```

ここは今までと同様


# キーの設定

```bash
$ sudo apt install curl
$ curl -s https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | sudo apt-key add -
```

# インストール

```bash
$ sudo apt update
$ sudo apt install ros-noetic-desktop-full
```

または

```bash
$ sudo apt install ros-noetic-desktop
```



# 環境設定

```bash
$ echo "source /opt/ros/noetic/setup.bash" >> ~/.bashrc
$ source ~/.bashrc
```

```bash
$ sudo apt install python3-rosdep python3-rosinstall python3-rosinstall-generator python3-wstool build-essential
```


rosdepの初期化

```bash
$ sudo rosdep init
$ rosdep update
```


# ワークスペースを作成
```bash
$ mkdir -p ~/catkin_ws/src
$ cd ~/catkin_ws/
$ catkin_make
```

catkin_makeで失敗したらこちらを実行

```bash
$ sudo apt install catkin
```


.bashrcに記述（必要なら）

```bash
$ echo "source ~/catkin_ws/devel/setup.bash" >> ~/.bashrc
$ source ~/.bashrc
```




# 参考

https://discourse.ros.org/t/ros-gpg-key-expiration-incident/20669


https://qiita.com/take4eng/items/70f167320ede46e4139c

https://qiita.com/oguashiii/items/f23f2d25531c9311e614
負荷試験実施ツール JMeterについて part3

[前回](https://qiita.com/fy406/items/826058fd3fcb9281586a)の続きです。

#ログ表示
前回はGUIからテストを実行しましたが、コマンドプロンプトで実行するとJMeterのレポートファイル(.jtl)も吐き出されます。
コマンドプロンプトで実行する方法は、テストの設定ファイル(.jmx)を、`jmeter-n.cmd`ファイルへドラッグドロップします。
するとコマンドプロンプトが起動され、設定の内容に応じたテストが実行されます。
しばらく待つと同じフォルダ内にJMeterのレポートファイル(.jtl)が生成されます。

このレポートファイルからさらにテスト結果を閲覧できるようにするためには、htmlを生成する必要があります。
「Tools」 > 「Generate HTML report」をクリックします。
![jm03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/858317/85df0d4e-6363-bfc7-6bc7-21dfda5fe692.png)
その後、以下の画面にてそれぞれ設定をしてから「Generate report」をクリックします。
①Results fileには先程のレポートファイル(.jtl)を指定します。
②user.properties fileには「reportgenerator.properties」ファイルを指定します。
③Output directoryには抽出先の空のフォルダを指定します。※空フォルダを指定しないとエラーとなります。
![jm04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/858317/28aa5a88-e3c4-5ce9-5fc0-69c1fe1e80c7.png)
しばらくまち、③で指定した空フォルダの中を見てみますと以下のようになっています。
「index.html」ファイルを開いてみます。
![jm05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/858317/3f5f39b3-c0ac-5fc6-296d-fecb3cab92ff.png)
すると以下のようにwebブラウザでテスト結果の統計を確認することができます。
![jm06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/858317/40c161b0-0a2b-c82a-4b15-8d0d7563cf9e.png)

#補足
前回JMeterの実行後に特に通知はないと言いましたが、以下の設定を入れると簡易的なログが表示できるようになります。
![jm01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/858317/4bda665b-6de2-d2c6-81ca-37b1d135d9d9.png)
上記にチェックを入れると以下のようにログが表示されるようになります。
![jm02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/858317/b3166fb6-baa6-3631-ebda-5a705902fd19.png)

今回は以上です。
【簡単】nodejsがインストール済のlinuxのコンテナを作成する【備忘録】

# Dockerfile作成
```dockerfile:Dockerfile
FROM node:12

ENTRYPOINT /bin/bash
```
あとはDockerfileのあるディレクトリで

```
docker build -t image_name .
```
でイメージをビルドし、

```
docker run -it image_name
```
でnodejsがインストール済みのlinuxのシェルにアクセスできます。

ちなみにlinuxのディストリビューションはdebainです。
チームワークがよくなる！私の周りにいる人たちの素敵な習慣【打ち合わせ・チームワーク編】

こんにちは！GxPの清水です。

今回は、私がチーム開発を行う上でチームワークがよくなり、とてもありがたいな、助かるなと感じている「私の周りにいる人たちの素敵な習慣」をご紹介します！
書き起こしてみるとたくさん見つかったので、この記事では「打ち合わせ系」「チームワーク系」に絞りました。
もしご自身が実践していることがあれば、周りの人はとても助かっているんだなと自信を持っていただければ幸いです:blush:

**【追記】**
続編として[チームワークがよくなる！私の周りにいる人たちの素敵な習慣【リモートワーク編】](https://qiita.com/nshimizu-gxp/items/3bdf47de2e5ddbb6674c)を書きましたので、よかったらこちらも見て頂けると嬉しいです✨


# 打ち合わせ系

## 打ち合わせが決まったらカレンダーアプリに全員分の予定を登録してくれる
予定を迅速に全員分登録してくれる方です。
打ち合わせの中で次の打ち合わせ予定が決まった場合、その打ち合わせが終わってカレンダーを開くとだいたい既に予定が登録されていることがほとんどです。
出社時には適切な会議室の予約も行ってくれるので、**直前で会議室がない…！**なんてことにもならず本当に助かっています。

## 打ち合わせをした方がいい流れになったら、すぐに予定を具体化してくれる
「これは打ち合わせで話したほうがいいね」と言う流れになった時に、「そうだね」と同意するだけでなく「では予定を決めちゃいましょう！○日の○時とかどうですか？」などと具体的に提案してくれる方です。
その場の議論で場が盛り上がっているとついつい次の予定決めは後回しになってしまいがちですが、**忘れないうちに決めておきましょうと冷静に促してくれる**のでありがたいです。

## zoomのURL発行が必要な場面でサッと作ってくれる
固定のzoomURLがない打ち合わせで、誰に言われるでもなくさっとURLを発行してくれる方です。
自分は「誰かが出すのかな…それとも出したほうがいいかな…」と相手の出方を伺ってしまうタイプなので、**先陣を切って発行してくれる**人にはいつも感謝しています。
（そして毎回URLにありがとうございますスタンプを貼るのでした）

## 打ち合わせの5分くらい前にzoomURLを発行・共有してくれる
打ち合わせの開始時間より少し早い時間にzoomURLを発行したり、既に発行されているURLをSlackに貼って共有してくれる方です。
打ち合わせは参加者全員の時間を消費するアクションであり、集まるのに時間がかかってしまうと非常に勿体ないものです。
早めの共有を行うことで、**URLのありかを探してもたついたり、うっかり会議があることを忘れて会議になかなか来なかったり…と貴重な時間を浪費することを防いでくれています。**
きっと昔から「○分前行動」が習慣になっているのだろうなと思います。時間にルーズな私は頭が上がりません…。

# チームワーク系

## Slackに必ずリアクションしてくれる
質問など返答を明確に返して欲しいもの以外の発言に対しても、必ず何かしらのリアクションをしてくださる方です。
例えば全体共有事項などにも「はい！」「対応済み」などのスタンプでリアクションを付けてくれるため、「この文章で伝わったんだな」と安心することができます。
なにより、孤独を感じやすいリモートワークの環境において**「反応をくれる」こと自体が純粋に嬉しい**です。
時にはリアクションスタンプで盛り上がることもあり、リモートでもわいわいやってる感が出て楽しいなと感じています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/890856/0c414686-dd65-ee77-d96b-04dbda96265b.png)
▲とある機能の実装が終わりPRが出されたときのお祭りムードなリアクションです

##「一緒にやりましょう！」と言ってくれる
何か経験のない作業を行う時に「一緒にやりましょう！」と声をかけてサポートしてくださる方です。
自身の時間を使ってでも **チームの中で作業ができる人が確実に増えることに価値がある**と考えていらっしゃるのだと思います。
私の場合は自分の慣れた作業だとつい「私がやっておきます！」と引き取ってしまいがちなので、目先の時間だけにとらわれず、本人の意思やチームの成長を考えてサポートを申し出られるようになりたいなと思っています。


## 決まったことを全員が見えるところに共有してくれる
朝会やちょっとした打ち合わせなど、議事録もないような場で決まったことをSlackなどの見える場に書いて共有してくださる方です。
その場では全員で合意して決めたことでも記録に残らないと忘れてしまったり正確な意味が失われたりしてしまうので、記憶が新しいうちに全員宛にアウトプットしてくださり本当に助かっています。
実践してくださる方にお礼を言うと、謙遜なのか「自分が忘れっぽいので…」とおっしゃる方が多いのですが、**自分のためだけでなく全員が助かる場に共有してくれる**ところがやっぱり素敵だなと思います。

# さいごに
以上が私の日々ありがたく感じている「私の周りにいる人たちの素敵な習慣」でした！

こちらで紹介したようなアクションを習慣的に実践できている方に共通するのは
「 **チームで取り組んでいることを意識し、自分以外のメンバーも快く働けることを大切にする**」精神があることだと思います。
チーム開発はチーム全員が一つの目標に対して向かっていく活動であり、メンバー同士の協力、チームワークが不可欠です。
この精神を持って取り組むことで、今回ご紹介したアクション以外にもステキなアクションが生まれ、それが習慣化することでよりよいチーム開発ができるようになるのではないかと記事を書きながら感じました:blush:

上記をいつも実践してくださる方に、この場を借りてお礼を言いたいと思います。いつもありがとうございます！
今後も日頃から感謝の気持ちを伝えていくとともに、どんどん見習って自分の習慣にしていきたいなと思います！
Linux: 画面が文字化けしてしまった時にはRESETコマンド

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

###### 実施環境：

```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
```

うっかりバイナリファイルをテキスト表示コマンドで開いてしまうと、画面が文字化けして戻らなくなります。

```Linux:Linux
[testuser@testhost ~]$ head -1 /var/log/wtmp
■tty1tty1■■■■`E
[|es||ser@|es|■os| -]$
```

このような場合は、resetコマンドを使用することで直すことが可能です。
画面表示上はresetコマンド自体も文字化けしていますが、問題なく実行できます。

```Linux:Linux
[|es||ser@|es|■os| -]$ rese|
[testuser@testhost ~]$
```

もっとも、一番良いのはそもそも文字化けさせないことです。
例えば、fileコマンドで開きたいファイルがテキストファイルか事前に確認することで、バイナリファイルをテキスト表示コマンドで開いてしまうことを防げます。

```Linux:Linux
[testuser@testhost ~]$ file /var/log/README
/var/log/README: ASCII text
[testuser@testhost ~]$ file /var/log/wtmp
/var/log/wtmp: dBase III DBT, version number 0, next free block index 0
```

lessコマンドのような、テキストファイルかどうかの確認機能が備わっているテキスト表示コマンドを使用することも有効です。

```Linux:Linux
[testuser@testhost ~]$ less /var/log/wtmp
"/var/log/wtmp" may be a binary file. See it anyway?
```
開発環境の構築を自動化するシェルスクリプト[Xcode, Homebrew, Ruby, MySQL]

## この記事の目的

今週の初めに以下の手順通り、Homebrewのインストールから、Rubyのセットアップまで、開発環境の構築を行いました。
そして今週の終わりに、この手順を自動化するシェルスクリプトを作成しました。初めて作成して、自動化の有益性を実感したのでここに記します。

https://qiita.com/koki0527/items/5eb8d8c1ac56dcd05466

## App/construct_dev.sh

以下がシェルするクリプトです。

```bash
#!/bin/bash

# 環境変数
RUBY_VERSION=2.7.1
MYSQL_VERSION=5.7
RAILS_VERSION=6.0.3
DATABASE_HOST=127.0.0.1
LDFLAGS="-L/usr/local/opt/openssl@1.1/lib"

# 必要なパッケージのインストール
sudo curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh | bash
git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core fetch --unshallow
git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask fetch --unshallow
brew update
brew install ruby rbenv ruby-build mysql@$MYSQL_VERSION shared-mime-info gnu-sed

# プロジェクト配下に移動
cd ~/App

# Rubyのセットアップ
rbenv install -s $RUBY_VERSION
rbenv local $RUBY_VERSION
rbenv rehash

# rubyとmysqlそれぞれにパスを通す
echo 'eval "$(rbenv init -)"' >> ~/.zshrc
echo 'export PATH="/usr/local/opt/mysql@'$MYSQL_VERSION'/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc

# 環境変数の設定
cp .env.example .env
gsed -i 's/DATABASE_HOST="0.0.0.0"/DATABASE_HOST="'$DATABASE_HOST'"/' .env

# 外部ライブラリのバージョン管理
bundle config --local build.mysql2 --with-ldflags=$LDFLAGS

# ローカルのRailsをセットアップ
gem install rails -v $RAILS_VERSION

# DBの起動
brew services start mysql@$MYSQL_VERSION

# Railsアプリケーションのセットアップ
bundle install
rails db:create
rails db:migrate
rails db:seed
```

## スクリプトの説明

ここではスクリプトの実行条件と実行手順などを説明します。

### スクリプトの実行条件

1. ローカルでgit cloneができる状態であること
2. clone先にこのスクリプトファイルが存在すること
3. リモートリポジトリに環境変数を管理する`.env.example`ファイルが存在すること

### スクリプトの実行手順

①　プロジェクトのクローン

```bash
$ git clone git@github.com:user_name/repogitory_name.git ~/App
```

②　スクリプトの実行

この時、XcodeとHomebrewそれぞれのインストールのために、パスワードの入力が2回求められます。

```bash
$ bash ~/App/construct_dev.sh
```

③　Railsアプリの起動

```bash
$ rails s
```

④　ローカルホストにアクセス

### スクリプトのこだわりポイント

1. 環境構築の手順を極限まで省略していること
git clone以外の作業をほぼ自動化していること（素晴らしい！w

2. バージョン管理を環境変数を用いて管理していること
これはまさにスクリプトで環境構築をする利点で、開発環境をコードで管理できるようになります

3. Mac環境に合わせて、ファイル内の文字の置換に`gsed`を用いていること

```bash
gsed -i 's/DATABASE_HOST="0.0.0.0"/DATABASE_HOST="'$DATABASE_HOST'"/' .env
```

## 参考記事

gsedコマンドについて

https://qiita.com/akameco/items/804970cd6655e69cc537

mysql2がbundle installできないエラーについて

https://qiita.com/fukuda_fu/items/463a39406ce713396403

<br>

この記事は以上です！シェルスクリプトは初めて記述しましたが、とても便利で個人的に他にも作成してみたいと思いました！最後までお読み頂きありがとうございました！
Spresense環境設定

最近Spresense　SDKに始めたましたが、すんなりできなかったので投稿したいと思います。
公式サイトは、３大OSを紹介していますが、わかりにくいので
大きなシェアをもつWindows環境開発にしぼって説明します。
Windowsでは、MSYS２を必要とします。MSYS２のバージョンが新しいとうまく動きませんでした。
SDKコンフィングでエラーがでます。
そこで、Spresense SDKリリースが２０２１年５月なのでMSYS２は２０２１年４月を使用しました。
Visual Studio CodeのIDEを使用します。数年前はEclipseを使っていたようですが、VSに鞍替えしたようです。

MSYS２がインストール完了したら、MSYS２を起動しpacmanコマンドで

```
$cd ~
```

更新します。

```
$pacman -Syu
```

Git,unzipコマンドを使えるようにします。

```
$pacman -S git
$pacman -S unzip
```
をインストールします。

開発に必要なパッケージをインストールします。

```
$curl -L https://raw.githubusercontent.com/sonydevworld/spresense/master/install-tools.sh > install-tools.sh
```

```
$bash install-tools.sh
```

/home/user/にspresenseenvというディレクトリができあがり、有効にします。

```
$source ~/spresenseenv/setup
```

SpresenseSDKをインストールします。（サンプルコードが含まれています。）

```
$git clone --recursive https://github.com/sonydevworld/spresense.git
```

クローンが完了すると/home/user/にspresenseディレクトリが出来上がります。
service workerを使ったアプリでworkboxのログを表示しないようにする

next.jsのプロジェクトを触っていて、consoleでworkboxのログが非常に邪魔（filterかけれない・・・）だったのでdisableにする方法を探す。

![5f70628da13d2f73a4a43db096002326.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66957/c2fd3af1-9707-1733-ea0e-b69a30fba275.png)


ここに書いてあった
[Configure Workbox - Disable Logging](https://developers.google.com/web/tools/workbox/guides/configure-workbox#disable_logging)

というわけでやってみる。

プロジェクトのルートディレクトリで以下のコマンド

```
mkdir worker
echo "self.__WB_DISABLE_DEV_LOGS=true" > worker/index.js
```

service workerをunregisterして再登録されるようにするか、起動し直せば反映🥱
【Laravel】よく使うリダイレクトのやり方２種類


>**HTTPリダイレクト**

>リダイレクトレスポンスは、Illuminate\Http\RedirectResponseクラスのインスタンスで、ユーザーを他のURLへリダイレクトするために必要なしっかりとしたヘッダを含んでいる必要があります。RedirectResponseインスタンスを生成する方法はいくつかあります。

引用：[HTTPリダイレクト
](https://readouble.com/laravel/6.x/ja/redirects.html?header=%25E3%2583%25AA%25E3%2583%2580%25E3%2582%25A4%25E3%2583%25AC%25E3%2582%25AF%25E3%2583%2588%25E3%2581%25AE%25E4%25BD%259C%25E6%2588%2590)

#結論
通常のリダイレクト：`redirect`ヘルパを使用する
前のページに戻るリダイレクト：`back`ヘルパを使用する

#1. redirectヘルパを使用する
Laravelでは`redirect`ヘルパ関数がグローバルに定義されており、アプリケーションのどこからでも使用できます。

```php
// URLへのリダイレクト
return redirect('home/dashboard');

//名前付きルートへのリダイレクト
return redirect()->route('login');

//名前付きルートへのリダイレクト（パラメータ付き）
return redirect()->route('profile', ['id' => 1]);

// コントローラアクションへのリダイレクト
return redirect()->action('LoginController@login');

// コントローラアクションへのリダイレクト(パラメータ付き)
return redirect()->action('LoginController@login', ['id' => 1]);

// URLでへのリダイレクト(フラッシュメッセージ付き)
return redirect('home')->with('status', 'ログインしました！');

// bladeでこんな感じに描けばフラッシュメッセージを表示できる
@if (session('status'))
    <div class="alert alert-success">
        {{ session('status') }}
    </div>
@endif
```

#2. backヘルパを使用する
`back`ヘルパ関数もグローバルに定義されており、アプリケーションのどこからでも使用できます。

```php
// 前の画面に戻る
return back();

// 前の画面に戻る（入力された値は保持する）
return back()->withInput();

// 前の画面に戻る（エラーを設定する）
return back()->withInput()->withErrors([
    'email' => '入力必須です。'
]);

// こんな書き方も見たことあるけど、古い書き方で現在は上記のbackヘルパを使う模様
return redirect()->back();
```

#まとめ
2種類のヘルパを使って簡単にリダイレクトができました。

内部的にはどちらもreturnの後のヘルパで`Illuminate\Http\RedirectResponse`クラスのインスタンスを作成して返しています。

`Illuminate\Http\RedirectResponse`クラスのインスタンスはリダイレクト先のURLやHTTPのステータスコードを保持します。

`redirect`ヘルパでは引数で指定したURLを、`back`ヘルパでは前画面のURLをそれぞれ設定しているようなイメージでしょうか。

`return back()`について内部的に何が起こっているか確認する記事も投稿しているので、よろしければこちらも併せて確認いただければと思います。

https://qiita.com/kondo0602/items/562b915e3e2f2734db96
create react appでyarn startでコケたときの解決法

## 記事の定義

`yarn start` をすると下記のエラーが出てきました。
この記事では上記の解決法を記載する。

```
error An unexpected error occurred: "/Users/hoge/hogehoge/package.json: Unexpected string in JSON at position 185".
```

## 起きたこと&状況

- ソースコード

```JSON:pakege.json
{
  "name": "hoge",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-scripts": "4.0.3"
  }
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
}

```

- バージョン

```
node -v
v14.17.4
```


```
yarn -v
1.22.10
```


## 解決方法

`Scripts` の前の　`}` の後ろに `,` を追加する。
そして`Scripts` の　`}` の `,` を削除する。


```JSON:pakege.json
{
  "name": "hoge",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-scripts": "4.0.3"
  }, 
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  }
}
```

## 余談
おそらく文字列("hoge")が続く場合は `,` で接続する必要性がある
テンプレート



#目次
[1.前回](#1-前回)
[2.概要](#2-概要)
[3.内容](#2-内容)
[4.用語のまとめ](#3-用語のまとめ)
[5.感想](#4-感想)
[6.おわりに](#5-おわりに)

#1. はじめに
#2. 概要
#3. 内容
#4. 用語のまとめ
#5. 感想
#6. おわりに



以下コピー用

```
#目次
[1.前回](#1-前回)
[2.概要](#2-概要)
[3.内容](#2-内容)
[4.用語のまとめ](#3-用語のまとめ)
[5.感想](#4-感想)
[6.おわりに](#5-おわりに)

#1. 前回
前章を貼り付ける

#2. 概要
今章の概要を記載

#3. 内容

### 節(section)
#### 項(subsection)
##### 目（演習）(subsubsection)


#4. 用語のまとめ

|用語|意味|
|-|-|
|Qitta(キータ)|エンジニアに関する知識を記録・共有するためのサービスです。|

#5. 感想
- 節の感想

#6. おわりに

章を改めて振り返っての感想
次の目標

```
18 数列の和 Dif:386 ABC177 C：「AtCoder　凡人が『緑』になるための精選50問詳細解説」サンプル

**この記事は拙著「AtCoder　凡人が『緑』になるための精選50問詳細解説」のサンプルです**
価格：100円
kindle：https://www.amazon.co.jp/dp/B09C3TPQYV
booth(pdf)：https://sano192.booth.pm/items/3179185

前：https://qiita.com/sano192/items/d6d2397f5f1bde156631
次：https://qiita.com/sano192/items/b301698295e6b6721b35

https://atcoder.jp/contests/abc177/tasks/abc177_c

**【目標】**
・数列の和を求める問題は具体例で考えるということを覚える
・計算量を減らせるように数式を変形する方法を身につける

**【概要】**
数列が与えられ、その組に対してなにかしら処理したものの和を出すというのは頻出の問題である。本問のように愚直に全ての組み合わせを計算すると計算量が大きすぎてTLE(実行時間制限超過)する、というのもお決まりのパターンだ。そしてこの手の問題は解説を見てもシグマをやたら並び替えたり変換したりしていて何をしているのか、まったくわからない・・・。
この問題で数列の和問題はどのように解くのかを学ぼう。

**【方針】**
数列が与えられ、その組に対してなにかしら処理したものの和を出す、という問題が出てきた場合、まず最初に入力例を見る。たいてい入力例1には具体的に何を計算するのか丁寧に書いてくれているからだ。

次に紙とペンを用意し、入力例1に書いている計算の内容をそのまま紙に写す。

ここまでを必ず行うこと。AiだのAjだののまま、頭の中でΣをこねくり回して解こうとしても絶対に解けない。
とにかく具体例、そして紙とペンだ。

ではこの問題の入力例1をみよう。
「入力例1」
3
1 2 3

N=3
A：1 2 3

計算方法も丁寧に記載がある。

まず紙に計算式をそのまま写す。
1*2+1*3+2*3

紙に写したら次に考えるのは「どこをかっこでくくれるか」。
最初の2項について1(=A1)が重複しているからこれでくくれそうだ。
1*(2+3)+2*3
(2+3)=A2+A3だから、ここをうまくやれれば計算量を減らせそう。しかしまだよくわからない。

入力例を見てもよくわからない、というときは自分でもっと大きなサンプルを作る。
A：1 2 3 4
ならどうなるか。

1*2+1*3+1*4+2*3+2*4+3*4
1、2を使ってかっこでくくろう。
=1*(2+3+4)+2*(3+4)+3*4
(2+3+4)=A2+A3+A4
(3+4)=A3+A4
となっている。どうやら
A1*(A2~ANの和)+A2*(A3～ANの和)+...
と計算できそうだ。
A2~ANの和
A3~ANの和
...
はそれぞれ
A1～ANの和-A1
A2～ANの和-A2
…
となるからこれなら逐一sum関数で和を計算せずに済む。この方針でTLE(実行時間制限超過)せずに解ける。

この変形が一般の場合において正しいかどうかの証明はコンテスト中にしなくてもよい。とりあえずこの方針でコードを作ってみて入力例を試し、出力が合っていれば提出する。
証明はコンテストの後にゆっくり考えよう。考えてわからなくても無理に証明まで理解する必要はない。

**【実装】**
入力を受け取り、ついでにmod=10^9+7を定義しておく。

```python:
N=int(input())
A=list(map(int, input().split()))
mod=10**9+7
```

次に
A1*(A2~ANの和)+A2*(A3～ANの和)+...
すなわち
A[0]*(A[1]~A[N-1]の和)+A[1]*(A[2]~A[N-1]の和)+...
を計算する。(リストAは0インデックスなのでA1→A[0]、A2→A[1]、...とずれる)

(A[1]~A[N-1]の和)=sum(A)-A[0]　
(A[2]~A[N-1]の和)=(A[1]~A[N-1]の和)-A[1]　
(A[3]~A[N-1]の和)=(A[2]~A[N-1]の和)-A[2]　
…
であるからまずAの合計を計算し、A[1]、A[2]、...を順に引いていけば(A[1]~A[N-1]の和)、(A[2]~A[N-1]の和)、...をO(1)で求めることができる。
足し算しながら10^9+7で余りを取ることを忘れずに。

```python:
A_sum=sum(A)

ans=0

for i in range(N):
    A_sum-=A[i]
    ans+=A[i]*(A_sum)
    ans%=mod
```

最後に答えを出力して終わり。

```python:
print(ans)
```

**【コード全文】**

```python:
N=int(input())
A=list(map(int, input().split()))
mod=10**9+7

A_sum=sum(A)

ans=0

for i in range(N):
    A_sum-=A[i]
    ans+=A[i]*(A_sum)
    ans%=mod

print(ans)
```

**この記事は拙著「AtCoder　凡人が『緑』になるための精選50問詳細解説」のサンプルです**
価格：100円
kindle：https://www.amazon.co.jp/dp/B09C3TPQYV
booth(pdf)：https://sano192.booth.pm/items/3179185

前：https://qiita.com/sano192/items/d6d2397f5f1bde156631
次：https://qiita.com/sano192/items/b301698295e6b6721b35
1周目ーrailsチュートリアル第2章

#目次
[1.はじめに](#1-はじめに)
[2.大まかな流れ](#2-大まかな流れ)
[3.用語のまとめ](#3-用語のまとめ)
[4.疑問・感想](#4-疑問・感想)
[5.おわりに](#5-おわりに)

#1. はじめに
本日は第2章

今日もある程度、第2章を読み進めるもののどうやって記事をまとめようか迷走中、
目次をつけて、ある程度自分が見直したときにわかりやすそうにまとめてみる。
各用語をまとめ、後ほどその章の感想なりを書いて次回に触れるような流れにしようかと考えている。

前回の第1章

https://qiita.com/ak-matsu/items/78f809644c1b870b4052

#2. 大まかな流れ

 - toyアプリケーションの作成
 - scaffoldの自動生成について説明
 - RESTアーキテクチャの考察
 - モデルとMVCの説明
 - 継承の説明
 - validation（制限）
 - 異なるデータモデル同士の関連付け（アソシエーション）

#3. 用語のまとめ
##Active Record
Active Recordとは、MVCで言うところのM、つまりモデルに相当するものであり、ビジネスデータとビジネスロジックを表すシステムの階層です。
一部抜粋

https://railsguides.jp/active_record_basics.html


##scaffoldジェネレータ
素早くwebアプリケーションに必要なスクリプトを呼び出して
サーバーを作成することができるもの、MVC（モデル、ビュー、コントローラ）を全て自動生成してくれるコマンド。

##RESTアーキテクチャ(習熟度浅いので後ほどまとめる）
4つのHTTPリクエストをrailsによって更に深めたものだったか？
index,new,create,edit,show,update,destroy
忘れている。

##HTTPリクエスト
GET,POST,PUT,DELETEの4つのHTTPメソッド、webページ全体のひとかたまりの情報を指す。
RailsのRESTful構造を身体に叩きこむには、繰り返し学ぶのが一番。

- HTTPリクエスト

|メソッド|役割|
|-----------|------------|:
|GET|リソースの取得。GETでのアクセスはリソースの内容に影響を与えない。|
|POST|リソースの新規作成|
|PUT|既存のリソースのアップデート|
|DELETE|リソースの削除|


##MVCの挙動
![qiita用のMVC (1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459220/2c8eef41-0fc1-d209-cb51-3509fe6fc6ae.jpeg)

##validation（制限をかける）
|lengthを使い、140字以上を制限|:「カラム名」, length: { maximum: 140 },|
|-|-|
|空白を入れさせないように制限|presence: true|

```ruby
class Micropost < ApplicationRecord
  validates :content, length: { maximum: 140 },
                      presence: true
end
```
##association
###has_many
Userモデルの視点で考えると、あるユーザーの作成した投稿は複数個ある状態。
つまり、1人のユーザーは複数の投稿を所有している。
<b>1:n</b>

###belong_to
1つの投稿は、1人のユーザーが投稿したもの。
つまり1つの投稿を複数人が投稿できないため、投稿は必ず1人のユーザーに所属する。
<b>1:1</b>

#4. 感想

2章から情報量がとても多くなる。
そして相変わらず、このqiitaにはどのように記事を段階的に書いていけばいいのか悩む。
やはりチュートリアルと解説動画がワンセットな取り組みなため必要な気がしてきた。
まだ解説がなくても復習程度であるのでもう少し進めてみて
それでも不明点や解消できない部分が出てきたら1周待たずに購入するかもしれない。

#5. おわりに

次回

https://qiita.com/ak-matsu/items/283f94a4c74127609e51

第3章

https://qiita.com/ak-matsu/items/b30a4d16f5ce1ef4c0ab
TypeScriptで配列の中身のデータ型を指定する方法

TypeScriptで配列の中身の数やそのデータ型を指定したかったのですが、ググり方がダメなのかわかるまで大変でしたので記事にします:eyes:

# 結論

```typescript
const food: [string, string, string, number] = [
    "吉野家", "牛丼", "並盛", 352
];
```

数が多くても少なくてもダメですし、型を間違えればもちろんエラーが出ます。

# エラーを出してみる

型を変えてみる

```typescript
const food: [string, string, string, number] = [
    "吉野家", "牛丼", "並盛", "352円"
];

// TS2322: Type 'string' is not assignable to type 'number'.
```

中身を減らしてみる

```typescript
const food: [string, string, string, number] = [
    "吉野家", "牛丼", 352
];

// TS2322: Type '[string, string, string, number]' is not assignable to type '[string, string, number]'.  Source has 3 element(s) but target requires 4.
```

# 活用方法

普通の配列指定

```typescript
const food: Array<any> = [
    "吉野家", "牛丼", "並盛", 352
];
```
これでも指定できるんですけど混在していて厳密に型指定しておきたい場合は不便ですよね。
例えば以下のようなループで使うことを前提とした配列。

```typescript
const food: Array<[string, string, string, number]> = [
    ["吉野家", "牛丼", "並盛", 352],
    ["松屋", "牛めし", "並盛", 320],
    ["すき家", "とろ〜り3種のチーズ牛丼", "大盛", 630],
];
```

こういう厳密性が大切な配列を定義したいときなんかは非常に頼りがいがあります。

※2021/08/01時点での牛丼情報なので時期によっては価格が違う可能性があります。

お付き合いいただきありがとうございました！
この記事が何かお力になれたらうれしいです。