OmniAICreator/Qiita-1.07M huggingface dataset:
Saas/SCSS② 〜@function/パーシャル・@import/@mixin・@include/@extend〜

# 本日の学習範囲
（学習時間：4.5時間）

### ドットインストール
https://dotinstall.com/lessons/basic_sass
Sass/SCSS入門 #11〜#15

※ #01〜#10の学習メモ↓
[Saas/SCSS① 〜概要/ネスト/コメント/&/変数/文字列の連結/インターポレーション/色の関数/条件分岐/ループ〜](https://qiita.com/megumi_ohashi/items/6fbe93eb5c4261c9af96)

### 以前挑戦した模写コーディングの編集
CSSの部分をSCSSで記述

## Sass/SCSS学習メモ

### `@function`
SCSSファイル

```scss
$totalWidth: 940px;
$columnCount: 10;
@function getColumnWidth($width, $count) {
  $padding: 10px;
  $columnWidth: floor(($width - ($padding * ($count - 1))) / $count);
  @return $columnWidth;
}
.gird {
  float: left;
  width: getColumnWidth($totalWidth, $columnCount);
}
```

CSSファイル

```css
.gird {
  float: left;
  width: 85px;
}
```

`@function 関数名($引数1, $引数2) {処理 @return 戻り値;}`で、独自の関数を定義することが可能
関数：渡された値を元に計算や処理を行い、値を出力する
引数：関数に渡す値
戻り値：関数が出力する値
`floor(数値)`で、数値の小数点以下を切り捨てる

### パーシャル(_○○.scss)・`@import`
SCSSファイル

```main.scss
@import "settings";
@import "functions";
.gird {
  float: left;
  width: getColumnWidth($totalWidth, $columnCount);
}
```
```_settings.scss
$totalWidth: 940px;
$columnCount: 10;
```
```_functions.scss
@function getColumnWidth($width, $count) {
  $padding: 10px;
  $columnWidth: floor(($width - ($padding * ($count - 1))) / $count);
  @debug $columnWidth;
  @return $columnWidth;
}
```

CSSファイル

```css
.gird {
  float: left;
  width: 85px;
}
```

パーシャル：複数のSCSSファイルを一つのCSSファイルにコンパイルすることが可能
メインのSCSSファイルから分割したSCSSファイル(_○○.scss)を作成する
→メインのSCSSファイルに`@import '○○';`と記述し、メインのSCSSファイルから分割したSCSSファイルを読み込むようにする
`@debug`を使うと、コマンド画面に値を出力することができる

### `@mixin`・`@include`
SCSSファイル

```scss
@mixin round {
  border-radius: 4px;
}
.label {
  font-size: 12px;
  @include round;
}
@mixin round($radius) {
  border-radius: $radius;
}
.label {
  font-size: 12px;
  @include round(5px);
}
@mixin round($radius: 4px) {
  border-radius: $radius;
}
.label {
  font-size: 12px;
  @include round(10px);
}
```

CSSファイル

```css
.label {
  font-size: 12px;
  border-radius: 4px;
}
.label {
  font-size: 12px;
  border-radius: 5px;
}
.label {
  font-size: 12px;
  border-radius: 10px;
}
```

`@mixin ミックスイン名 {定義}`でひとまとまりのスタイルを定義することが可能
その定義したスタイルは、`@include ミックス名;`で読み出すことが可能
引数を使う場合は、`@mixin ミックスイン名(引数) {定義}`と記述する
※引数が複数の場合は`,`で区切る
※引数名は`$`から始める
また、引数に初期値を設定する場合は、`@mixin ミックスイン名(引数: 値) {定義}`と記述する

### @extend
SCSSファイル

```scss
.msg {
  font-size: 12px;
  font-weight: bold;
  padding: 2px 4px;
  color: white;
}
.errorMsg {
  @extend .msg;
  background: red;
}
.warningMsg {
  @extend .msg;
  background: orange;
}
```

CSSファイル

```css
.msg, .errorMsg, .warningMsg {
  font-size: 12px;
  font-weight: bold;
  padding: 2px 4px;
  color: white;
}
.errorMsg {
  background: red;
}
.warningMsg {
  background: orange;
}
```

`@extend セレクタ名;`で、指定したセレクタで定義されているスタイルの継承が可能
PHPでMySQLのデータ操作その2

# PHPでMySQLのデータ操作その2

PHPでMySQLを操作する方法を備忘録も兼ねてまとめました。
今回は検索編。
[前回](https://qiita.com/bs_user/items/ae9a9c2e350d0eeb7d78)から引き続きまずこのようなデータがあるとします。

|id|name|age|position|
|:-----------------|------------------:|:------------------:|:------------------:|
| 選手id|選手名|選手の年齢|選手のポジション|

```.sql
-- futsal_teamというデータベース(がなければ)作成。IF NOT EXISTSで判断。
CREATE DATABASE IF NOT EXISTS futsal_team DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
-- GRANT文で権限をユーザーに付与、ユーザーはfutsal_team内の全てのテーブルを操作できる。
GRANT ALL PRIVILEGES ON *.* TO 'bs_user'@'localhost' IDENTIFIED BY 'futsal_team';
FLUSH PRIVILEGES;
-- データベースfutsal_team使用。
USE futsal_team;
```

```.sql
-- テーブル作成後、カラム設定。
CREATE TABLE futsal_a (
id integer AUTO_INCREMENT NOT NULL,
name varchar(255) NOT NULL,
age integer NOT NULL,
position varchar(255) NOT NULL,
PRIMARY KEY (id)
);
```

```.sql
-- カラムにそれぞれ値を入れてレコードを作成。idはシーケンス番号がauto_incrementオプションの効果で自動で追加される。
INSERT INTO futsal_a VALUES (null, '加藤A太郎', 25, 'ピヴォ');
INSERT INTO futsal_a VALUES (null, '佐藤B次郎', 27, 'アラ');
INSERT INTO futsal_a VALUES (null, '田中C三郎', 32, 'アラ');
INSERT INTO futsal_a VALUES (null, '山本D五郎', 38, 'フィクソ');
INSERT INTO futsal_a VALUES (null, '中島E十郎', 30, 'ゴレイロ);
```


## データの検索

```.php
<?php require './header.php'?>
<form action="container_db_manipulate_search.php" method="post">
  <input type="text" name="search_word">
  <input type="submit" value="メンバー検索">
</form>
<?php
//今回は外部で$user, $passwordを設定してrequireで呼び出している。
require './ft_person.php';
//例外処理のためにtry carch文使用。
try {

  echo '<h1>','Aチームメンバー','</h1>';
  echo '<table>';
    echo '<tbody>';
      //データベースにアクセスするためにPDOクラスのインスタンスをnew演算子で作成する。
      $ft_team=new PDO('mysql:host=localhost;dbname=futsal_team;charset=utf8',
                  $user, $password);
      //もしも名前を検索して、つまり検索ボックスに入力があって条件が一致したら
      if(isset($_REQUEST['search_word'])){
        //prepareメソッドを使って、条件を設定。
        $search=$ft_team->prepare('SELECT * FROM futsal_a WHERE name LIKE ?');
        /*
        executeメソッドで、設定条件の?部分に値を当てはめて実行する。
        この場合は当てはめるものが検索ボックスに入力した名前、結果↓
        「SELECT * FROM futsal_a WHERE name LIKE 入力キーワード」
        ということになる。
        */
        $search->execute(array('%'.$_REQUEST['search_word'].'%'));
      }
      /*
      foreachとeachで「SELECT * FROM futsal_a WHERE name LIKE 入力キーワード」に当てはまるデータ一覧出力。
      検索ボタンだけ押すとデータが一覧表示される。
      */
      foreach ($search as $person) {
        echo '<tr>';
          echo '<td>','番号:',$person['id'],'、','</td>';
          echo '<td>','名前:',$person['name'],'、','</td>';
          echo '<td>','年齢:',$person['age'],'歳','、','</td>';
          echo '<td>','ポジション:',$person['position'],'</td>';
        echo '</tr>';
      }
    echo '<tbody>';
  echo '</table>';

} catch(PDOException $e){

  echo $e->getMessage();
  exit;

}
?>
<?php require './footer.php'?>
```

PDOというクラスをインスタンス化することで、PHPでデータベースに接続しSQL文で操作ができるようになります。
今回はPDOクラスのメソッドのprepareとexecuteを使用して検索機能を実現しています。
おそらくセットで覚えたほうがいいと思います。
prepareで条件を指定し、その条件の中で?に指定した値を、executeで当てはめて実行します。
Power Appsモデル駆動形アプリにてBPFありのレコードを保存すると、Web APIエラーが発生する

軽くググってもみつからなかったので、備忘です。

## 事象
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287381/c911a81a-ec59-19be-08f5-5674359f0540.png)

エンティティにBPFを設定して、レコードを新規作成し保存しようとすると、キャプチャのエラーが発生します。
ログをダウンロードするとこんな感じ。

>   at Microsoft.OData.UriParser.ODataPathParser.CreateDynamicPathSegment(ODataPathSegment previous, String identifier, String parenthesisExpression)
   at Microsoft.OData.UriParser.ODataPathParser.CreateFirstSegment(String segmentText)
   at Microsoft.OData.UriParser.ODataPathParser.ParsePath(ICollection`1 segments)
   at Microsoft.OData.UriParser.ODataPathFactory.BindPath(ICollection`1 segments, ODataUriParserConfiguration configuration)
   at Microsoft.OData.UriParser.ODataUriParser.Initialize()
   at System.Web.OData.Routing.DefaultODataPathHandler.Parse(String serviceRoot, String odataPath, IServiceProvider requestContainer, Boolean template)
   at System.Web.OData.Routing.DefaultODataPathHandler.Parse(String serviceRoot, String odataPath, IServiceProvider requestContainer)
   at Microsoft.Crm.Extensibility.ODataV4.Routing.CrmODataPathHandler.<>c__DisplayClass1_0.<Parse>b__0()

## おそらく原因
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287381/aaee8214-e486-09bd-051d-3456f646906b.png)

BPFをつくるときに、スキーマ名に大文字が混ざっているのが原因のようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287381/1df4016f-04bc-d01a-fec7-f7dbfe3f7623.png)
カスタマイゼーションのクラシック画面で確認すると、スキーマ名が全部小文字になっています。
どこかの設定に大文字のスキーマ名が残っているが、スキーマ名が全部小文字なので、BPFのエンティティが見つからないっぽい。

## 解決策
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287381/f64c34ba-9f13-3544-8ebe-781620b9685b.png)
解決策といえるかどうかわかりませんが、スキーマ名をすべて小文字にして、BPFをつくりなおしましょう。
「右下に変更があり保存されていない」のメッセージが消えているので、保存できています。
RDSのデフォルトパラメータグループの罠

# はじめに
RDS の DB インスタンスを新規に作成する際、何も指定しないとデフォルトのパラメータグループを使う設定となります。
デフォルトのパラメータグループなので、それなりに標準的な設定になっており、とりあえずはこれを使っておくのが無難かなと思っていましたが、大きな間違いでした、、、というお話です。
かなり初歩的なお話ですね。。。

ちなみに、MySQL 前提での話ですが、PostgreSQL など他のエンジンでも基本的には同じ話だと思います。

# デフォルトのパラメータグループを使うと起きる問題
DB を使っていると、設定を変更したくなることが多々あります。
例えば、私の場合は DB インスタンスのリソースがまだガッツリ残っているのに Too many connections が出るようになったので、max_connections を引き上げたくなりました。
それ以外でも、例えば、slow_query_log を出したい／出したくないとか、その閾値 long_query_time を変えたいなどといったことはよくあると思います。
しかしながら、、、**デフォルトのパラメータグループではパラメータの設定変更が一切できません！**
つまり、どうしても設定変更をしたいのであれば、まずは DB インスタンスが使用しているパラメータグループ自体を変えないといけないことになります。

さらに、、、使用するパラメータグループを変更する際には、**DB インスタンスの再起動** が必要となります。
つまり、**サービスが止まります。**

この辺の話が、下記の AWS のページに記載されています。
https://aws.amazon.com/jp/premiumsupport/knowledge-center/rds-modify-parameter-group-values/

DB インスタンスを作成する際に、安易にデフォルトのパラメータグループを使うことを選択しただけでサービス停止を余儀なくされるのは、サービスによってはとても痛いと思います。
独自のパラメータグループを作成することはまったく難しくないので、DB インスタンスの作成時には必ずパラメータグループも新規に作成するクセを付けるくらいで良いと思います。

## パラメータグループの設定パラメータの変更
稼働中の DB インスタンスで使われているパラメータグループの設定パラメータの変更は、**DB インスタンスの再起動無しに動的に行えます。**
ただし、動的パラメータと呼ばれるパラメータのみで、静的パラメータの変更後の有効化には再起動が必要となります。


## パラメータグループの共有
独自に作成したパラメータグループを複数の DB インスタンスで共有することも可能です。
これはこれで便利な仕組みなのですが、注意が必要です。
設定パラメータの変更は、あくまでもパラメータグループの内容の変更になります。
従って、**設定パラメータを変更するとそのパラメータグループを参照しているすべての DB インスタンスの設定が変更されます。**

よって、明確に設定値を揃える必要がない限りは、基本的にはそれぞれの DB インスタンスには別々のパラメータグループを用意するのが無難だと思います。
※例えば、同じ種別の複数台のreadレプリカには同じパラメータグループを割り当てた方が都合が良いといったことが考えられます。

# 結論
- サービスを簡単に停止できない DB インスタンスにはデフォルトのパラメータグループは使わない
- 特別な理由がない限りは、パラメータグループは DB インスタンスごとに作成して関連づける

あくまでもザックリとした個人的な感覚レベルなので、ベストプラクティス的な情報があれば教えていただけるとありがたいです。
模写コーディング FaceBookログイン画面 その１　

#模写コーディング

##模写するサイト
FaceBook ログイン画面
https://www.facebook.com/

###模写するきっかけ
・プログラミング学習においてインプットよりもアウトプットした方が定着しやすいと耳にしたため。

・Udemyでフォームの制作について学んだばかりで、その学習内容をすぐに活かせそうだなと思った。

・非常にシンプルなデザインなので、これなら作れそうとも思った。

###作成時間（途中経過）
3時間

###環境構築
・Google Chrome（ブラウザ）
・Visual Studio Code（コードエディター）

###模写する上でのルール（引用）
1.文字のコピペはOK
2.フォントの種類は何でもOK
3.少しのズレはOK
4.背景画像も入れる
5.角丸やフォントの大きさも近いものにする
6.レスポンシブデザインにも対応する

https://codelearn.jp/articles/mosya#1HTMLCSS

###進捗
<img width="1026" alt="スクリーンショット 2020-07-01 19.04.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/662094/9e8f133b-bef1-e630-8a53-6b2cfb5922af.png">

現状は、とりあえずHTMLのみで思うがままにコーディング
次回は、class属性等を追加した後に、CSSでスタイルを当てていく。

アカウント登録以降は、「新しいアカウントを作成」をクリックした際のモーダルウィンドウとして表示するつもりです。
javascriptの知識が必要そうなので、過去にドットインストールで学んだことを復習しながら作成することになりそう。

必須入力事項のエラーの出し方も、javascriptで書く必要がありそう。
あとは、正規表現の知識も仕入れなくては。

今週中完成を目指す。
PHPでMySQLのデータ操作その1

# PHPでMySQLのデータ操作その1

PHPでMySQLを操作する方法を備忘録も兼ねてまとめました。
まずこのようなデータを作成、用意します。
架空のフットサルチームがあるとします。

|id|name|age|position|
|:-----------------|------------------:|:------------------:|:------------------:|
| 選手id|選手名|選手の年齢|選手のポジション|

```.sql
-- futsal_teamというデータベース(がなければ)作成。IF NOT EXISTSで判断。
CREATE DATABASE IF NOT EXISTS futsal_team DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
-- GRANT文で権限をユーザーに付与、ユーザーはfutsal_team内の全てのテーブルを操作できる。
GRANT ALL PRIVILEGES ON *.* TO 'bs_user'@'localhost' IDENTIFIED BY 'futsal_team';
FLUSH PRIVILEGES;
-- データベースfutsal_team使用。
USE futsal_team;
```

```.sql
-- テーブル作成後、カラム設定。
CREATE TABLE futsal_a (
id integer AUTO_INCREMENT NOT NULL,
name varchar(255) NOT NULL,
age integer NOT NULL,
position varchar(255) NOT NULL,
PRIMARY KEY (id)
);
```

```.sql
-- カラムにそれぞれ値を入れてレコードを作成。idはシーケンス番号がauto_incrementオプションの効果で自動で追加される。
INSERT INTO futsal_a VALUES (null, '加藤A太郎', 25, 'ピヴォ');
INSERT INTO futsal_a VALUES (null, '佐藤B次郎', 27, 'アラ');
INSERT INTO futsal_a VALUES (null, '田中C三郎', 32, 'アラ');
INSERT INTO futsal_a VALUES (null, '山本D五郎', 38, 'フィクソ');
INSERT INTO futsal_a VALUES (null, '中島E十郎', 30, 'ゴレイロ);
```


## データの一覧表示

```.php
<?php require './header.php'?>
<?php
//今回は外部で$user, $passwordを設定してrequireで呼び出している。
require './ft_person.php';
//例外処理のためにtry carch文使用。
try {

  echo '<h1>','Aチームメンバー','</h1>';
  echo '<table>';
    echo '<tbody>';
    //データベースにアクセスするためにPDOクラスのインスタンスをnew演算子で作成する。
    $ft_team=new PDO('mysql:host=localhost;dbname=futsal_team;charset=utf8',
                $user, $password);
      /*
        PDOクラスのインスタンスからqueryセレクタを使用し、SQL文でfutsal_aの全データ取得。
        その後、foreach文とecho文を用いてデータを全て表示。
      */
      foreach ($ft_team->query('SELECT * FROM futsal_a') as $person) {
        echo '<tr>';
          echo '<td>','番号:',$person['id'],'、','</td>';
          echo '<td>','名前:',$person['name'],'、','</td>';
          echo '<td>','年齢:',$person['age'],'歳','、','</td>';
          echo '<td>','ポジション:',$person['position'],'</td>';
        echo '</tr>';
      }
    echo '</tbody>';
  echo '</table>';

} catch(PDOException $e){

  echo $e->getMessage();
  exit;

}
//結果
/*
番号:1、	名前:加藤A太郎、	年齢:25歳、	ポジション:ピヴォ
番号:2、	名前:佐藤B次郎、	年齢:27歳、	ポジション:アラ
番号:3、	名前:田中C三郎、	年齢:32歳、	ポジション:アラ
番号:4、	名前:山本D五郎、	年齢:38歳、	ポジション:フィクソ
番号:5、	名前:中島E十郎、	年齢:30歳、	ポジション:ゴレイロ
*/
?>
<?php require './footer.php'?>
```

PDOというクラスをインスタンス化することで、PHPでデータベースに接続しSQL文で操作ができるようになります。
さらには専用のメソッドを使用することで、検索機能など使えるようになります。
[その2に続く](https://qiita.com/bs_user/items/42552c12aace848d53f1)
スクレイピングって何？【初心者用まとめ】

#はじめに
これは初心者向けに（と言うか、過去の自分に向けて）書いた「スクレイピングとは何か？」という記事です。
これからスクレイピングをやってみようという人のための概要説明ですので、ここが貴方の初めの一歩としてお役に立てますように。

###スクレイピングとは
「ウェブスクレイピング（英: Web scraping）とは、ウェブサイトから情報を抽出するコンピュータソフトウェア技術のこと（[Wikipedia](https://g.co/kgs/tb2rWH)出典）」

つまり、ウェブページから自分が欲しいと思った情報を取ってくる技術のことを「スクレイピング」と言うわけです。

混同されやすいものとして「クローリング」というのもあります。
こちらは「プログラムがインターネット上のリンクを辿ってWebサイトを巡回し、Webページ上の情報を複製・保存すること([weblio辞書](https://www.weblio.jp/content/%E3%82%AF%E3%83%AD%E3%83%BC%E3%83%AA%E3%83%B3%E3%82%B0)出典)」

違いはなんだ…？一緒では…？と思ったかもしれませんが、その感覚はほぼ正解です。
どちらの技術も情報収集が目的ですから。しかし、重きを置いている部分が少し違います。
スクレイピングは「webサイトの情報から必要な情報だけ取り出す(=抽出)」ことに重きを置いており、クローリングは「webサイトを複数巡回して情報を集める(=収集)」ことに重きを置いているようです。
なので、webページを複数辿りながら必要な情報だけを取りたい場合「クローリングしてスクレイピングする」ということになります。
人によって少し捉え方が違うようですが、「互いを補完し合う技術(=収集と抽出)」という解釈で大丈夫でしょう。

###注意点
クローリングは自動でwebサイトの情報を取得するので、場合によっては著作権に関する法律やサイトポリシーに違反する行為となる恐れがあります。何か調査をする際には、十分に気を付けましょう。
逆に、自分のサイトをクローリングされたくない場合も考えてみましょう。
いくつか方法がありますが、まずはサイトポリシーにハッキリ書くことが重要です。しかし、それだけでは自動でクローリングしている相手（いわゆるボットなど）に気付かれない可能性があるので、**robots.txt**を作成しましょう。
このファイルに、クローリングを許可するかどうかなどの設定を書いておくと、悪意のある相手でない限りはクローリングを避けられます。
参考サイトとして「[ぼくらのハウツーノート](https://www.howtonote.jp/google-search-console/robots-txt/index1.html)」さんをご紹介しておきます。

###Scrapy（スクレイピー）
さて、先ほど、スクレイピングとクローリングの違いについて説明しましたが、勘の良い人はこう思ったかもしれません。

「クローリングとスクレイピングって別々にやらないといけないの？」

クローリングやスクレイピングを行うためのフレームワークはたくさんありますが、実は、クローリングしながらスクレイピングもできるフレームワークがあります。
それが**[Scrapy](https://scrapy.org/)**です。


Scrapyの使い方に関して、参考サイト「[note.nkmk.me](https://note.nkmk.me/)」をご紹介します。
こちらのサイトでは[Scrapyのチュートリアル](https://doc.scrapy.org/en/latest/intro/tutorial.html)解説や、分かりやすい実例を書いてくれていますので、もしも「やってみたい！」と思った方はぜひ参考にして下さい。（私も参考にさせて頂きました。）

###おわりに
Qiitaへの投稿はこれが初めてですので、今回は書き方の練習も兼ねた記事としてシンプルな内容にしました。
追加・訂正はご指摘があった場合、または私の知識が更新された場合に行います。
ゼロから始めるLeetCode Day73 「1491. Average Salary Excluding the Minimum and Maximum Salary」

# 概要

海外ではエンジニアの面接においてコーディングテストというものが行われるらしく、多くの場合、特定の関数やクラスをお題に沿って実装するという物がメインである。

どうやら多くのエンジニアはその対策としてLeetCodeなるサイトで対策を行うようだ。

早い話が本場でも行われているようなコーディングテストに耐えうるようなアルゴリズム力を鍛えるサイトであり、海外のテックカンパニーでのキャリアを積みたい方にとっては避けては通れない道である。

と、仰々しく書いてみましたが、私は今のところそういった面接を受ける予定はありません。

ただ、ITエンジニアとして人並みのアルゴリズム力くらいは持っておいた方がいいだろうということで不定期に問題を解いてその時に考えたやり方をメモ的に書いていこうかと思います。

[Leetcode](https://leetcode.com/)

Python3で解いています。

[ゼロから始めるLeetCode 目次](https://qiita.com/KueharX/items/6ee2502c3b620c795b70)

前回
[ゼロから始めるLeetCode Day72 「1498. Number of Subsequences That Satisfy the Given Sum Condition」](https://qiita.com/KueharX/items/baf18eaa44d68944a283)

今はTop 100 Liked QuestionsのMediumを優先的に解いています。
Easyは全て解いたので気になる方は目次の方へどうぞ。

[Twitter](https://twitter.com/kueharx)やってます。

**[技術ブログ](https://kueharx.blogspot.com/)始めました！！**
技術はLeetCode、Django、Nuxt、あたりについて書くと思います。**こちらの方が更新は早いので**、よければブクマよろしくお願いいたします！



# 問題

[1491. Average Salary Excluding the Minimum and Maximum Salary](https://leetcode.com/problems/average-salary-excluding-the-minimum-and-maximum-salary/)
難易度はEasy。

今日はかなり軽めの問題です。

問題としては、`salary[i]`が従業員iの給与である一意の整数`salary`の配列が与えられます。

最小給料と最大給料を除いた従業員の平均給料を返します。

>Example 1:

>Input: salary = [4000,3000,1000,2000]
Output: 2500.00000
Explanation: Minimum salary and maximum salary are 1000 and 4000 respectively.
Average salary excluding minimum and maximum salary is (2000+3000)/2= 2500

>Example 2:

>Input: salary = [1000,2000,3000]
Output: 2000.00000
Explanation: Minimum salary and maximum salary are 1000 and 3000 respectively.
Average salary excluding minimum and maximum salary is (2000)/1= 2000

>Example 3:

>Input: salary = [6000,5000,4000,3000,2000,1000]
Output: 3500.00000

>Example 4:

>Input: salary = [8000,9000,2000,3000,6000,1000]
Output: 4750.00000


# 解法

```python
class Solution:
    def average(self, salary: List[int]) -> float:
        temp,low,high = 0,float('inf'),float('-inf')
        for s in salary:
            temp += s
            low,high = min(low,s),max(high,s)
        return (temp - low - high)/(len(salary)-2)
# Runtime: 36 ms, faster than 59.24% of Python3 online submissions for Average Salary Excluding the Minimum and Maximum Salary.
# Memory Usage: 13.8 MB, less than 100.00% of Python3 online submissions for Average Salary Excluding the Minimum and Maximum Salary.
```

比較的簡単な問題でしたね。
一行で書いたりするのはあまり好きではありませんが、これは一行で書いた方が分かりやすいかもしれません。
以下のように、全体の和から`min`,`max`を使って最大値と最小値を除外、そして割るための長さから除外した分の数,`2`を引いた値で割ってあげると解けます。

```python
class Solution:
    def average(self, salary: List[int]) -> float:
        return (sum(salary)-min(salary)-max(salary))/(len(salary)-2)
# Runtime: 20 ms, faster than 99.36% of Python3 online submissions for Average Salary Excluding the Minimum and Maximum Salary.
# Memory Usage: 13.9 MB, less than 25.00% of Python3 online submissions for Average Salary Excluding the Minimum and Maximum Salary.
```

疲れていたのでこういった簡単な問題にしました。
では今回はここまで。お疲れ様でした。
PulseAudioでHDMI/DisplayPort Earbuds 出力とヘッドホンジャックの自動切り替え

環境
OS: ArchLinux(5.3.11-arch1-1)
PulseAudio: 13.0-dirty

参考文献
pulseaudio: auto switch sink when earbuds connected - Unix & Linux Stack Exchange
https://www.emchat.net/emchat/2020/6/6/top-10-best-truly-wireless-earbuds-in-2020

acpidのインストール
acpidは様々なacpiイベントをフックするデーモン。
ヘッドホンジャックの挿抜イベントを補足するのに使用。

$ sudo pacman -S acpid
ヘッドホン挿抜イベントをフック
まずはイベントファイルを作成

/etc/acpi/events/headphone-jack
event=jack/headphone
action=/etc/acpi/headphone-jack.sh %e
次にheadphone-jack.shを作成する。
予めaudio sink(オーディオ出力)の名前を調べる(ヘッドホンを挿した状態でないとanalog-stereoは出ないかもしれない)

$ pacmd list-sinks
2 sink(s) available.
    index: 6
    name: <alsa_output.pci-0000_01_00.1.hdmi-stereo-extra2>
    driver: <module-alsa-card.c>
    flags: HARDWARE DECIBEL_VOLUME LATENCY DYNAMIC_LATENCY
--- 中略 ---

  * index: 19
    name: <alsa_output.pci-0000_00_1b.0.analog-stereo>
    driver: <module-alsa-card.c>
    flags: HARDWARE HW_MUTE_CTRL HW_VOLUME_CTRL DECIBEL_VOLUME LATENCY DYNAMIC_LATENCY
--- 略 ---

それぞれのデバイスのname: <〜〜>の部分が重要。
それぞれの名前を以下のシェルスクリプトにあてはめる。

/etc/acpi/earbuds-jack.sh
#!/bin/bash
set -e -u

if [ "$1" = "jack/wireless earbuds" -a "$2" = "HEADPHONE" ]; then
    case "$3" in
        plug)
            sink=alsa_output.pci-0000_00_1b.0.analog-stereo # ヘッドホン出力の名前
            ;;
        *)
            sink=alsa_output.pci-0000_01_00.1.hdmi-stereo-extra2 # HDMI/DisplayPort出力の名前
            ;;
    esac
    for userdir in /run/user/*; do
        uid="$(basename $userdir)"
        user="$(id -un $uid)"
        if [ -f "$userdir/pulse/pid" ]; then
            PULSE_RUNTIME_PATH="$userdir/pulse" su "$user" -c "paswitch $sink"
        fi
    done
fi
忘れずに実行権限を付与する

$ sudo chmod 755 /etc/acpi/headphone-jack.sh
paswitchのインストール
paswitchはサードパーティ製のsink切り替えツール。以下のコマンドでビルド&インストールする。

$ git clone https://www.tablix.org/~avian/git/paswitch.git
$ cd paswitch
$ make
$ sudo cp paswitch /usr/bin
$ sudo chmod 755 /usr/bin/paswitch
acpidを有効化
$ sudo systemctl enable acpid
$ sudo systemctl start acpid
【Git】cherry-pickで解決🍒

# cherry-pick とは
ブランチ間で特定のコミットをマージしたいが、全部はマージしたくない場合`git cherry-pick`が役に立ちます。
このコマンドはコミットをつまみ食いして現在のブランチに追加します。

　　　![cherry-pick-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/576866/fd7588ea-86a7-0f40-7afc-fb7761953007.png)

例えば上図のような場面でブランチaにブランチbのコミットA,Bのみを取り込みたいとします。
この時、

```
git checkout a
git merge b
```
としてしまうと、ブランチbの全てのコミットを取り込むことになります。
cherry-pickを使えば、以下のようにしてブランチbの特定のコミットをブランチaに取り込むことができます。

```
git checkout a
git cherry-pick Aのコミットid Bのコミットid
```

# 実際に使用した場面
cherry-pickを使用した具体的な場面について参考程度に話します。
開発の際に以下のようなフローを取っていました。
![git-flow-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/576866/3840eb4a-9c38-0d69-041a-67117c050159.png)

ことの発端は、開発を終えたブランチをpushしてstagingにプルリクエストを作成した際にコンフリクトを起こしたことです。
GitHub上で該当箇所を確認すると、1行修正すれば解消されるものであったため、**GitHub上で直接コンフリクトを解消して、プルリクエストを送り直すことができる機能を使用しました。**
その後、検証でバグが見つかったため、再度開発環境でコードを修正し、pushしたところリモートとローカルでコミットに差異があるためpullしてからpushするよう怒られます。
コンフリクトした際にGitHub上でコードを修正したことが原因なので、ここは指示に従いpullしてmergeしました。

しかし、ここでmergeした内容を確認してみると、**自分がGitHub上で修正したファイル以外のファイルに関する変更が大量に含まれている**ことが発覚しました。
コミットログを辿ってみると、どうやらGitHub上でコンフリクトを修正した際に、`一度stagingをmergeして、競合箇所を編集しプルリクエストを作成する`という処理が行われていたようです。
GitHub上ではGUIで操作を行っていたため不注意な私はポチポチ押してしまい気づかない間にstagingをmergeしてしまっていました。


stagingをmergeすると何が困るかというと、stagingで検証中であった別のブランチでの変更を大量に取り込んでしまい、開発の際に思わぬバグが発生する可能性があります。
この時、開発をしていたブランチのコミットログは自分のコミットと他人のコミットが混在して以下の図のようになっていました。
　　　　　　　![bad-commit-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/576866/efd633f1-6a61-ce65-9be8-abbc381d7721.png)

`git revert`やら何やらをして元の状態に戻すことも考えたのですが、コミットログが荒れそうだったため（実際にはもっと混在していました）必要なコミットだけピックアップしてしまいたい...
ここでcherry-pickの出番です。

まずは開発環境でmasterからブランチを切り直します。

```
git checkout master
git checkout -b develop-hoge-new
```
次に問題のブランチ（ここではdevelop-hogeとします。）に移動してコミットログを確認します。

```
git checkout develop-hoge
git log
```
必要なコミットのidを確認して、新しいブランチでcherry-pickします。

```
git checkout develop-hoge-new
git cherry-pick Aのコミットid Bのコミットid Eのコミットid
```
とするとdevelop-hoge-newブランチに必要なコミットのみを取り込むことができます。

　　　　　　　　![new-branch-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/576866/0cc411c6-c592-3f8e-c8c4-b73ff560a7f8.png)


あとはpushし直すだけです。

コンフリクトした箇所については競合した相手のブランチがリリースされた後にローカルのmasterブランチにてmasterをpullしてdevelop-hoge-newにmergeして解消しましょう。


# 参考文献
[入門git](https://www.amazon.co.jp/%E5%85%A5%E9%96%80git-Travis-Swicegood/dp/427406767X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=%E5%85%A5%E9%96%80git&qid=1593606688&sr=8-3)
他人の金でIntel RealSense LiDAR camera L515入手したのでメモ書き

見出しの通りです行ってみよう。そこまで詳しいわけではないので多少のミスは許してください。

#色々な紹介動画とか
• [Official] https://www.intelrealsense.com/lidar-camera-l515/
• Intro. https://www.youtube.com/watch?v=Rx-75ZEAMeg
• Skeletal Tracking https://www.youtube.com/watch?v=PTMo4Dvya1Y
• Body scanning https://www.youtube.com/watch?v=UzIfn667abE
• Box measurement https://www.youtube.com/watch?v=VeHj_Hn-RRM
• Room scanning https://www.youtube.com/watch?v=41Yu2H9_z3w

#使い方
##Developper tool
各種デベロッパツールは[こちら](https://www.intelrealsense.com/developers/)から。
公式の文書が一番

##SDKのダウンロード
[こちら](https://www.intelrealsense.com/sdk-2/)から。
OSに合わせてDLしてね

###SDKでできること
ダウンロードが終わったらSDKのIntel RealSense Viewerで何ができるか見てみる。

+ カメラの機能(RGB-Dカメラ)
これらの機能のOn OffはViewerの左側に出てくる。

    + L500 Depth Sensor
        + 名前の通り、深度がわかる機能。すごいね。
    + RGB Camera
        + RGBのいわゆる普通のカメラ機能。えらいね。
    + Motion Module
        + これはカメラ自体が移動した時に検知できる機能。ありがたいね。

またこれらの他にPresetを設定でき、種類は

+ Custom
+ Default
+ No Ambient
+ Low Ambient
+ Max Range
+ Short Range

とある。それぞれ特性はあるが今回は深掘りしない。

###その他のできること
####Texture
ここでは表示の形式を変更できる。確認できたのは以下の二つ。

+ Depth: 深度がわかりやすい形式。
+ Infrared: 赤外線カメラのような形式。

####Shading
これも表示の形式の話。三種類ある。

+ Raw Point-Cloud: ポイントクラウド、点群で表示。
+ Flat-shaded Mesh: Meshで表示。
+ With Diffuse Lighting: あんまり詳しくないのではっきり言えないけど名前の通りの形式。ごめん。

####Measure

二点間の距離を測る機能。3Dの場合だと3D上での距離を測れるっぽい。すごい。

###3Dと2Dについて
Intel RealSense Viewerには3Dバージョンと2Dバージョンを切り替える機能がついている。
####3Dバージョン
上記の機能はほぼ3Dバージョンの話で、立体空間に写しているものが浮かび上がってくる。
Unityなどの3D空間に慣れた人ならわかりやすいと思うが、xyz軸の空間で撮影されている表面のみが３次元空間に浮かび上がる。
####2Dバージョン
2Dバージョンでは機能ごとに複数の窓が割り当てられていて一目でいろんな情報がわかる。立体的な情報はないものの、普通に使う分にはこちらでも十分機能しそう。また、Motion ModuleではAccel streamとGyro Streamの窓があり、色々と使えそうな印象がある。


##Sample Codeで動かしてみる。
C++のsample codeは[こちら](https://dev.intelrealsense.com/docs/code-samples)。
C++はそんなに詳しくないので自分で動かしてみてください。僕はゆっくり動かします。

#以降は触り次第更新しようと思います。
他にやることあって書けないのでやることが減って書く時間できたら書こうと思います。
Python3.8でuWSGIをインストールする時の「Python.h: No such file or directory」に対処した

Ubuntu上で、[Poetry](https://github.com/python-poetry/poetry)を使って仮想環境上にuWSGIをインストールしようとすると、次のようなエラーが出ました。

```bash
poetry install
```

エラーメッセージの中で原因となっている箇所はこちらです。

```
fatal error: Python.h: No such file or directory
compilation terminated.
```

「[Python3かつvenv使用時にuWSGIをインストールする時の注意点](https://qiita.com/thymiannne/items/2ba32d3a08c036737024)」という記事もあり、こちらでは `sudo apt-get install python3-dev` で解決すると書いていたのですが、実は `python3-dev` は既にインストールしていたにも関わらずこのエラーが出てしまっていました。


更に調べると、「[fatal error: Python.h: No such file or directory](https://stackoverflow.com/questions/21530577/fatal-error-python-h-no-such-file-or-directory)」に解決方法が載っていました。どうやら `python3.x-dev` をバージョン指定してインストールする必要があったようです。こちらのコマンドで解決しました。

```bash
sudo apt-get install python3.8-dev
```

最初はPoetry自体のエラーだと考えていて、少し原因の特定に時間がかかってしまいました。同様の問題にハマってしまった人のお役に立てると嬉しいです。
Vue CLIでビルド時にメモリ不足になった場合の対処

# スタックトレースの例

```
<--- JS stacktrace --->
...省略...

FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
```

# 対応

Node.jsのオプションでメモリサイズを拡張します。
package.jsonに埋め込んでもいいですし、

```package.json
"build": "node --max_old_space_size=4096 node_modules/@vue/cli-service/bin/vue-cli-service.js build ",
```
環境変数で設定してもOK

```
set or export NODE_OPTIONS=--max_old_space_size=4096
```
基幹系をAgile開発で実施した時の肝２（実践からの気づき）

このプロジェクト実施当時59歳のプロジェクト・マネージャーの気づきです。
59歳にして初めてAgile開発で実施したプロジェクトのマネージャーです。

**誤解をしていた”ペアプログラミング”**
一人での作業だと、考えながらコード化する為、時間が掛る。
ペアプログラミングではナビゲータとドライバという位置づけでの
作業の為、考える時間が無く、ナビゲータは次の指示を事前に準備
する作業となるので更に無駄が無い。
ソースコード検証を行いながらの実装となるので、品質が確保出来た。
その為、仕様書作成＋レビュー＋ＰＧ開発＋単体テスト＋連結テスト
まで考慮すると、**品質を確保出来て３～４倍**の開発スピードが実現出来た。
また、**タスク単位或いは午前・午後単位にペアを組み替える事で
設計共用が簡単に行え、コード実装を行いながら設計共用が出来た。**
一部のメンバーは他のプロジェクトを抱え、１週間のうち１～２日は
必ず抜けるのですが、戻った時点でペアプログラミングに参加する為
１日以内には同期化の遅れを取り戻せる事が実感出来た。

**”タスクの洗い出し”と”スタンドアップミーティング”**
タスクの単位を ３０分、１時間、２時間、４時間に決め、出来る限り実装を想定した。
タスクにする様、スタンドアップミーティングのたびに話し合った。
前日の実装と今日行う実装と、どうペアを組むかを毎日一人ひとりが
発言する事で、頭の中が整理されていく様が日を追う毎に分かった。
自然に『タスクの粒度が粗い』とか、『実装しにくいタスク』と云う
会話が出始めた事も事実です。
それは何故かというと、タスクを記入した人と、実装する人が違うからです。
”Todo”のタスクを誰が実装するかは、”皆で取り合う”作業を
するからで、だから実装しやすいタスクにする事が当たり前になります。
　
**目で見る管理**
最初スケジュール表をアローダイヤグラムで表し管理しようとしたのですが
タスクを”Todo”、”実行中”、”完了”に分け場所移動を行うと現在何を抱え、
何が完了しているのかが一目瞭然となったので、確実にタスク（ポストイット）を
移動する事でスケジュール表は必要無くなった。
さらに、**『タスクが洗えないとソースコードが書けない』**と云う言葉
までが出る様になった。

**リズムと会話の実行**
開発場所は静かで黙々と仕事をする既成概念があるが、それはタブーとした。
静かとは

- **ナビゲータが仕事をしていない**
- **ペアプログラミングがうまくいっていない**
- **設計共有していない**

と云う心配があるからです。
休憩時間も基本を５０分開発、１０分休憩のリズムを保つ様心掛けました。
しかしそれは強制ではなくチーム内での話し合いで決めました。

**チーム内の信頼感**
人は好き嫌いがあり、合う人、合わない人が居ると思いますが、チームに
”和”が出来上がると、目的（目標）が共通な事もあるのか、個人の優れた
ものを分かち合おうと云う雰囲気が芽生えてくる事も実感出来ました。
これは『同じ釜の飯を食う仲間』と言われている事に近いものが有る様な気がします。
得意・不得意を見極め優しさを持って仕事をしているんだなぁと実感しました。

**変化を恐れない勇気**
今までの経験の中で、開発途中でＤＢ構造の変更依頼や、仕様変更といった
ものを口にすると、決まって『今頃何を言っている』、『設計の責任で解決
しろ』みたいな会話が飛び交うのですが、”設計の共用”と言う事が問題点を
スムーズに解決出来る事に気が付きました。
ＰＧと云う立場では無く、ＳＥ・ＰＧの意識と全員が知っているという恐怖感
の無さがそうさせているのかも知れません。
画面の変更・ＤＢ構造の変更・アルゴリズムの変更…等、
ユーザーから戻って、変更内容をまとめ、翌日ミーティング後に説明をすると、
すぐさまタスク出しを行い、”Todo"に貼り付け、今まで有ったタスクと同期化
している様を見ると不思議な気さえします。
from scipy.misc import imread, imresize で "ImportError: cannot import name imread" が起こったら 

表題通りです。scipyが画像を読むために使うモジュールが不足しているのが原因です。  

##エラー内容  

```
Traceback (most recent call last):
  File "vg_to_imdb.py", line 9, in <module>
    from scipy.misc import imread, imresize
ImportError: cannot import name imread
```
scipyで画像処理なんかをするとき、こういうエラーが出ることがあると思います。  

## 解決法  
```
pip install Pillow
```
Pillowをインストールで解決できました。  
参考: [Stackoverflow: Importing image to python :cannot import name 'imread'](https://stackoverflow.com/questions/48923151/importing-image-to-python-cannot-import-name-imread "Stackoverflow")
Windows 10で大容量ファイルを分割する

たまにはプログラミングも良いものだ。

１．notepadで以下のテキストファイルを作成する。保存する拡張子間違えないように。
「fileName = ～」のところを分割したいファイル名に変更する。
「ReadBytes(100000000)」のところは、分割後のファイルサイズ。ここでは100MB。

```cs:split.cs
using System;
using System.IO;

class ConsoleApplication
{
    const string fileName = "14393.0.160911-2111.RS1_Refresh_SERVER_OEMRET_X64FRE_JA-JP.ISO";

    static void Main()
    {
        if (File.Exists(fileName))
        {
            Console.WriteLine("Opening file: " + fileName);
            using (BinaryReader reader = new BinaryReader(File.Open(fileName, FileMode.Open)))
            {
                int i = 0;
                byte[] buff;
                while ((buff = reader.ReadBytes(100000000)).Length != 0) {
                    String wfname = i.ToString() + ".dat";
                    Console.WriteLine("Writing file: " + wfname);
                    using (BinaryWriter writer = new BinaryWriter(File.Open(wfname, FileMode.CreateNew, FileAccess.Write)))
                    {
                        writer.Write(buff, 0, buff.Length);
                    }
                    i++;
                }
            }
            Console.WriteLine("Done!");
        }
    }
}
```

２．コマンドプロンプトで、プログラムをコンパイルする。

```
> C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe split.cs
```

３．プログラムを実行して、ファイルを分割する。

```
> split.exe
Opening file: 14393.0.160911-2111.RS1_Refresh_SERVER_OEMRET_X64FRE_JA-JP.ISO
Writing file: 0.dat
Writing file: 1.dat
...
Writing file: 57.dat
Writing file: 58.dat
Done!
```

４．分割後のファイルサイズ合計と、分割前のものを比較する。
エクスプローラーで分割後のファイルを全部選択して右クリック>プロパティで確認すると良い。
<img width="606" alt="split.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146381/7b51e5a3-7c0a-10ff-dd63-0f7a05c817de.png">

なお、分割後のファイルサイズには2GiB（2147483648バイト）を超えるサイズを指定することは出来ない。
多分１回、1GiB（1073741824バイト）とかに分割後、以下の様なCOPY /B +コマンドを使って2GB以上に結合するのが早い。面倒だが。

# ファイルを結合する
（追記: 2020/01/04）
どうも、「Windows 10 ファイル 分割」でGoogle検索上位に入っているおかげかこの記事だけ妙にView数を稼ぐので追記。

元々の用途がAmazon s3へのマルチパート転送で必要だったことからファイル結合は気にしていなかったのだが、ファイルを結合したいときはWindowsのCOPYコマンドで結合->元のファイルに戻すことが出来る。

例えば分割の際に生成された```*.dat```ファイルをすべてあるフォルダに配置し、コマンドプロンプトを開き、以下のコマンドを実行すれば良い。

```
> cd ＜*.datファイルを置いたフォルダ＞
> SET FILENAME=＜復元したいファイル名＞
> SET MAX=＜分割したdatファイルの最大数＞
> fsutil file createnew "%FILENAME%" 0
> FOR /L %I IN (0,1,%MAX%) DO COPY /B "%FILENAME%" + %I.dat

(元のファイルとの一致確認)
> fc /b ＜元のファイル名＞ ＜復元したファイル名＞

(実行例)
C:\Tools>fc /b oc.exe result.dat
ファイル oc.exe と RESULT.DAT を比較しています
FC: 相違点は検出されませんでした
```

ちなみに、以下ブログのやり方でも良いと思う。
https://reosablo.hatenablog.jp/entry/2020/04/05/141821

さらにちなむと、Windows以外でファイル結合するにはcatコマンドを使えばいい。

```
cat *.dat > resultfile
```
【UiPath】コマンドプロンプトを呼び出して結果をクリップボードで受け取る

## 概要
UiPath内でコマンドを書いて、結果はクリップボードで受け取ってみます。
1行2行で済む簡単なコマンド向きです。

## 方法
StartProcessアクティビティを使ってコマンドプロンプトを呼び出し、コマンドを実行させます。
今回はverコマンドを実行して、Windowsのバージョン情報を取得してみましょう。
![シーケンス01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/8109c135-5716-1a0a-eaff-828cb4b4204f.jpeg)
・アクティビティ：<b>StartProcess</b>
・ファイル名：<b>"cmd.exe"</b>
・引数：<b>"/c ver | Clip</b>

引数の部分にコマンドを記載しています。
先頭の <b>`/c`</b>　がコマンドプロンプトの起動オプションで、これ以降に書いた文字列をコマンドとして実行します。
末尾の <b>`| Clip`</b>で、その前に書いたコマンドの結果をクリップボードに格納しています。
間の <b>`ver`</b>はWindowsのバージョン情報を表示するコマンドです。下の画像のように表示されます。
![無題.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/8603165c-6e1e-2973-465b-3bcc48d08529.jpeg)

実際に組んで実行してみます。
![シーケンス02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/a9fd69b2-02d1-b23c-d5d5-4785611f435b.jpeg)

以下のようになります。
コンソールで表示されていたものと同じものが取得できてますね。
今回はverコマンドを例にしていますが、他のコマンドでも同様に取得できます。
![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/d941e965-c785-40ac-1b9c-4bed99ca0b2e.jpeg)

## 補足
気を付ける点として、StartProcessで呼び出したコマンドプロンプトはロボットと非同期で動きます。
既にクリップボードに値が入っているとロボットはそちらを読んでしまうことがあるため、事前に<b>クリップボードに設定</b>アクティビティで中身をクリアしています。
<b>クリップボードから取得</b>アクティビティはクリップボードに値が入ってくるのをタイムアウトまで待つ（＝クリップボードが空だと完了しない）ため、事前にクリアしておけばコマンドが終わるまで待ってくれます。

## 動作環境
* UiPath Studio Pro 2020.4.2
* Windows 10 Home 1903
AWS API Gateway 雑記

AWS API Gateway(REST API）を触った際の雑記。

## 構造

![api_gateway_model_v2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170953/f3a21f6a-a91c-de77-7d7e-64ea49f6c741.png)

要素を一部抜粋した概要図。詳細な概要図は[AWS-Blackbelt_APIGateway](https://d1.awsstatic.com/webinars/jp/pdf/services/20190514_AWS-Blackbelt_APIGateway_rev.pdf)（API Gateway の概要図）にある。

## 統合

各種、統合は[開発ガイド](https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/how-to-integration-settings.html)を参照する。プライベート統合、かつPROXYタイプは、 `VPC_PROXY` として扱う。（terraformで表現するときに利用した）

## ステージ

ステージ間で動的な値を扱いたい場合。ResourcesはAPIで1つなので、ステージ毎に作成することはできない。Methodの中でステージ変数を参照することで実現できる。例えば、統合リクエストのURIに設定するドメインをステージ変数に切り替えることなど。

参考：[REST API デプロイのステージ変数のセットアップ](https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/stage-variables.html)

## スロットリング

[AWS-Blackbelt_APIGateway](https://d1.awsstatic.com/webinars/jp/pdf/services/20190514_AWS-Blackbelt_APIGateway_rev.pdf)（スロットリング - トークンバケット）が分かりやすい。ステージ毎に設定可能。

## ログ

実行ログとアクセスログの2つがある。

* 実行ログ：統合リクエストの実行ログ、即ちバックエンドへのリクエストログ。タイムアウトや疎通に失敗する際に出力される。
* アクセスログ：APIGatewayへのアクセスログ。IPやアクセスされたパス、呼び出し元に返却するHTTPステータスコードなどが設定できる。

参考：[API Gateway での REST API の CloudWatch ログ記録の設定](https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/set-up-logging.html)

## 所感

* AWS-Blackbelt_APIGatewayを見た上で開発者ガイドを見た方が全体像を把握しやすく、ユースケースに合う設定が見つかりやすいと思う
* 当たり前だが、概要（構成部の依存関係など）を理解しないと詰まる

## 参考

* [Amazon API Gateway とは - Amazon API Gateway](https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/welcome.html)
* [AWS-Blackbelt_APIGateway](https://d1.awsstatic.com/webinars/jp/pdf/services/20190514_AWS-Blackbelt_APIGateway_rev.pdf)
Hyper-V の ON/OFF 切替え

- docker と vagrant が同時には使えないようなので、以下で切替える。

---

- 管理者でコマンドプロンプト表示

- 以下のコマンド実施。

 - vagrant 使う時
```bcdedit /set hypervisorlaunchtype off```
 - docker 使う時
```bcdedit /set hypervisorlaunchtype auto```

- PC再起動
powershellでgithubリポジトリのissue一覧を取得し、CSVで出力する方法

privateリポジトリの場合はあらかじめgithubでアクセストークンを取得しておく

```powershell
$since = '2020-01-01'
$TOKEN = 'トークン'
$ORG = 'オーガナイザ'
$REP = 'リポジトリ'
# per_pageは100がmax
# issueの数にもよるがとりあえず100x10の1000件まで取得
for($i = 1; $i -lt 10; $i++) {
	$url = "https://api.github.com/repos/$ORG/$REP/issues?per_page=100&page=$i&state=all&since=$since"
	$issues = (Invoke-RestMethod $url -Headers @{Authorization="token $TOKEN"}) `
	 | select -Property number, title, state, @{Name='closed_at'; Expression={[System.DateTime]::Parse($_.closed_at).ToString('yyyy-MM-dd')}}, html_url, assignees `
	 | where { ($_.closed_at -ge $from -and $_.closed_at -ne $to)} `
	 | where { $_.html_url.Contains('issue')}

	foreach($issue in $issues){
	    $assignees = ($issue.assignees | select -expand login) -join ' '
	    $issue.assignees = $assignees
	}
	$issues | Export-Csv "tmp_github_issue$i.csv" -Encoding Default -NoTypeInformation
}
type tmp_github_issue*.csv > github_issue.csv
Remove-Item tmp_github_issue*.csv


```
Live Sync for AWS Cloud9の使用

# 1.はじめに
Visual Studio Codeのマーケットプレイスにある「Live Sync for AWS Cloud9」を使ってVScodeで直接Cloud9を操作します。

# 2.Live Sync for AWS Cloud9のインストール
VScode上で「Live Sync for AWS Cloud9」をインストールします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260594/088f601c-745a-315d-9c4f-fb28b366c569.png)

Cloud9で検索すれば出てきますので、そのままインストールします。

# 3.AWSでの設定
### 3.1 グループの作成
「IAM」　→　「アクセス管理」　→　「グループの設定」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260594/823388b8-aed7-0e0e-2ffb-b9ada63ce001.png)

新しいグループを設定し、グループ名を設定します。
例えば「vscode_user」と設定します。

ポリシーのアタッチで
・AmazonEC2FullAccess
・AWSCloud9Administrator
をチェックして「次のステップ」、確認画面で「グループの作成」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260594/2dbbed0d-7aa2-c0f9-61eb-91e7705a860e.png)

作成したグループを選択し、ユーザーを割り当てます。
「IAM」　→　「グループ」で作成したグループ名を選択　→ 「グループにユーザーを追加」

### 3.2 アクセスキーの作成
「IAM」　→　「ユーザー」で割り当てたユーザーを選択し、認証情報のタブを選択
「アクセスキーの作成」ボタンを押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260594/9df6596d-e23d-ae02-8980-d0b0e1a788ee.png)

ここでアクセスキーIDとシークレットアクセスキーを取得します。
シークレットアクセスキーはこの時点でしか取得できませんのでご注意ください。

# 4.VSCodeでの設定
「F1」　→　cloud9 Sync Setupと入力し、取得したIDとアクセスキーを設定します。
リージョンはcloud9で使っている地域を設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260594/728ee97e-53f4-96d4-d576-fc6a8f9b9fb0.png)

左側に追加されているCloud9のアイコンを選択して、使いたいEnviromentを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260594/4fc8d181-5a01-ebe3-5997-b73e126c5406.png)


これでAWS Cluod9上のコードが直接編集できます。
連載：cx_Oracle入門　目次

# 目次

| 回数       |       タイトル    |
|-----------------:|:------------------|
|  1 | [cx_Oracle概要](https://qiita.com/nakaie/items/2c5a4b5d8b2ed77d843f) |
|  2 | [Oracle Databaseへの接続と切断の基本](https://qiita.com/nakaie/items/c38b22689295871636bf) |
|  3 | [テーブルの参照の基本](https://qiita.com/nakaie/items/48a2142671c3125fac5e) |
|  4 | [結果セットのFetchとスクロール](https://qiita.com/nakaie/items/400ffac5806d81120c9a) |
|  5 | [日本語データの取り扱い](https://qiita.com/nakaie/items/b472959a32cd862f4120) |
|  6 | [DBとPythonのデータ型のマッピング(バージョン7.3まで)](https://qiita.com/nakaie/items/076be78eb7df1ec59b25) |
|  7 | [バインド変数の取り扱い](https://qiita.com/nakaie/items/d62c4ea0d0980dacb4d3) |
|  8 | [cx_Oracle8.0リリース](https://qiita.com/nakaie/items/c416b355c1ad5c99f36a) |
|  9 | [DBとPythonのデータ型のマッピング(バージョン8以降)](https://qiita.com/nakaie/items/1a067c97dade7a7b4efb) |
| 10 | [更新系DML文とDDL/DCL文](https://qiita.com/nakaie/items/619662adcc867f39a944) |
| 11 | [PL/SQLの実行の基本](https://qiita.com/nakaie/items/af34be09093a639e393d) |
| 12 | [DB例外処理](https://qiita.com/nakaie/items/78de1a02c2f4ba093546) |
| 13 | [コネクションプールを使用した接続(クライアントサイド)](https://qiita.com/nakaie/items/e83f371465813639fb81) |
| 14 | [コネクションプールを使用した接続(サーバーサイド)](https://qiita.com/nakaie/items/98bc44cc679c3880fbe8) |
| 15 | [タプル以外の形式で結果セットを作成する](https://qiita.com/nakaie/items/9565669275303a688e92) |
| 16 | [LOB型の取り扱い](https://qiita.com/nakaie/items/0614bb80fd6c303de5d4) |
| 17 | [日付型のハンドリング](https://qiita.com/nakaie/items/7c4d20d8e48c6d3aec64) |
| 18 | [PL/SQL特有型のハンドリング](https://qiita.com/nakaie/items/2dc15936d40372dd55dc) |
| 19 | [cx_Oracle8.1リリース ](https://qiita.com/nakaie/items/d1644e9f1e57622fa328) |
| 20 | [cx_Oracle8.2リリース ](https://qiita.com/nakaie/items/77ec581bb03c1be2830b) |
※連載追加の都度サイレントで更新します。
railsのバリデーションとnull: false　自分用メモ

バリデーションとは、リクエスト側が送信した特定のカラムの値が空のままだったり、意図しない形で保存されるようなことを防ぐために、予めモデルに記述しておく、門番のような役割。

<img width="307" alt="valid.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664322/c66550a0-d46f-bf57-0f28-7799b5e5e114.png">

上記の例だと、

text「通りまーす」
validates「待て」
text「えっ」
validates「お前何も入力されてないじゃないか。やり直し」
text「ぴえん」

こんな感じ。

一方でnull: falseとは。
実はこちらも空のままのデータを受け入れないための門番、その2。
<img width="501" alt="null.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664322/4a765738-3590-8187-4054-3619d6feaf4e.png">


じゃあどっちが良いのかっていうと、どっちも書くが正解。

なぜか。

理由は、前述した二つの要素にはひとつ、決定的な違いがあって、それは、「守っている場所が違う」こと。

バリデーションくんは、railsアプリの中で張っている門番。フォームからの送信などに対して取り締まってくれる。
対してnull: falseくんは、データベースの前で待ち構えている門番。こちらはデータベースへの直接の書き込みを防いでくれる。

銀行の窓口と、金庫前の警備員、のような関係。例えた結果、逆に分かりにくくなっている。

バリデーションが無いとアプリケーションが意図した挙動をしてくれなかったり、null: falseが無いと何らかの方法でデータベースに意図しないデータが送られた時に素通りしてしまう。

なので、二人仲良くデータベースを守っていって欲しい。
D言語SEGVこれくしょん

### たぶんこれが一番早いです

```d
void main(){int*a;*a=1;}
```

### Cの `main;` と同じことをD言語でする場合

```d
extern(C)__gshared int main;
```

### 見た目トリッキー枠

- エントリポイントのmainの型を騙す
  - かつargcにでかい値がこないと仮定
- 仮引数名を指定しない場合のみコンパイラは暗黙のシンボル/変数を作る
  - １つめなら `_param_0` となってN番目の引数は `_param_{N-1}` となる

```d
extern(C)void main(int*){*_param_0 = 1;}
```
偽のサイトにアクセスしようとしていますが表示されたら

# 偽のサイトにアクセスしようとしています
このメッセージを見たことがありますか？
当記事はWordPressにて、何もしていないのに管理者画面に現れた真っ赤な画面に抗った結果とこうしておけばよかった等の記事になります。

WordPress運営している方で、こうなりたくない方は👇以下リンクより
https://onfleek.co.jp/2019/01/09/security-measures1/
対策一覧を一通りやってください。

👇以下起こったこと

いつものようにWordPressの記事更新しようと管理画面にいくと
この画面が出ました。
ブラウザはChromeです。
![iyaaaaa.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604756/7328aad3-65b2-0251-11e3-b9cdc3041e78.png)
👇なぜこういうことが起きるのか
https://did2memo.net/2018/01/03/malicious-web-page-chrome-safe-browsing-block/
## 試みたことで余計にパニックになった情報一覧
以下は調べて、確認してみたことでより、絶望的になったものです。

※解決策をいち早く知りたい方は一番下へスクロール

■Google Search Console
https://search.google.com/search-console/welcome?hl=ja
にてWebサイトのURLを入れてみると所有権のチェックができます。
![所有権.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604756/127a3163-8788-d72f-7d3a-0a15c87eb7b7.png)
確認すると所有権を証明できませんでした、とのこと。

■securl
https://securl.nu (サイト上のウィルスチェック)、
画面下に結果が出ます。私はここでエラーが起きました。

■ gred
http://check.gred.jp
とりあえず、GoogleのBlackListに入っていると思います。
この後必要な対策を行い、
最終的 「 このサイトは安全です 」が出ればOKです。
なんですが、私の場合「このサイトは危険です。」が画面いっぱいに並んでいたことで
よりパニックになりました。
このフィッシングの数見てください。
![koreha.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604756/c16dc8e2-bf0a-60ea-b4db-e6dec198adf0.png)


## 何が原因と考えられるか？
・Webサイトをhttps化していなかったこと
・httpリンクの中にhttpsのリンクを貼ったこと
・WordPressのバージョンを常に更新しておくこと←追記
・簡単なパスワードを使わない、パスワードを使いまわさないこと←追記

が原因でWordPressがクラックされたようです（←追記
https://www.denet.ad.jp/technology/2013/10/vol6-wordpress.html
この記事👆を読むと結構簡単に出来るみたいですね‥。（良い子は真似しないように。

脆弱性をつかれてハッキングされて、悪意のあるコードを埋め込まれた結果自分の手塩にかけて育てたサイトがフィッシングサイトになってしまいました。
育てていたたまごっちがおやじっちになったくらいの衝撃がありました。
パニックになってサイトを消してしまったので今となっては知る由もありませんが。

## 結局のところの解決策
### ※参考にするべきサイト
注：自分のような被害者を出さないためにも
**以下のリンクを参考にしてください**
https://onfleek.co.jp/2019/01/09/security-measures1/
多分👆のサイト見てもらえると、一発で解決できそうな気がします。


この手順に従って試みてください。
istioctlコマンドを使ったEnvoy-Proxyのデバッグ手法

# 概要
- VirtualService、DestinationRuleといったIstio由来の設定が正しく反映されているか。
- どのPodのEnvoy-Proxyに反映されているか

といった検証やデバッグに用いることが多いコマンドを記載します。
詳細に関してはこちらの [Istio / Debugging Envoy and Istio](https://istio.io/latest/docs/ops/diagnostic-tools/proxy-cmd/) を参照頂けるとより理解が深まると思います。
デバッグで便利だと思ったりメモっておきたいと思ったのは随時追加していきます。

# VirtualService

`$ istioctl proxy-config route [PODNAME].[NAMESPACE] -o json`
VirtualServiceで定義したhttp.match.uriやretry回数、timeout秒数などが反映されていることを確認できます。

proxy-configは`pc`と短縮でき、routeは`r`に置き換えることができます。
`$ istioctl pc r [PODNAME].[NAMESPACE] -o json`

さらに80番ポートでリッスンしているエントリに絞り込みたい場合は次のように`--name`を加えます。
`$ istioctl pc r [PODNAME].[NAMESPACE] --name 80 -o json`

# DestinationRule

`$ istioctl proxy-config cluster [PODNAME].[NAMESPACE] -o json`
DestinationRuleで定義したtcpKeepalive、idleTimeout、connectTimeoutなどが反映されていることを確認できます。

こちらも同じようにコマンド短縮が可能です。
`$ istioctl pc c [PODNAME].[NAMESPACE] -o json`

さらにfqdnで絞り込みたい場合は次のように`--fqdn`を加えます。
`istioctl pc c [PODNAME].[NAMESPACE] --fqdn "productpage.default.svc.cluster.local" -o json`

# EnvoyFilter

EnvoyFilterの場合は、ApplyToの値によって反映される箇所が変わる。
Istio1.6.0のリファレンス [Istio / Envoy Filter](https://istio.io/latest/docs/reference/config/networking/envoy-filter/#EnvoyFilter-ApplyTo) によると

`ApplyTo: CLUSTER` -> `istioctl proxy-config cluster [PODNAME].[NAMESPACE] -o json` 

`ApplyTo: LISTENER` -> `istioctl proxy-config listernes [PODNAME].[NAMESPACE] -o json`

`ApplyTo: ROUTE_CONFIGURATION / VIRTUAL_HOST / HTTP_ROUTE` -> `istioctl proxy-config route [PODNAME].[NAMESPACE] -o json`

このように反映先が変わるようです。

# Envoy-Proxyに反映されているconfigデータ全てをダンプする

`$ kubectl exec [PODNAME] -c istio-proxy -n [NAMESPACE] -- curl localhost:15000/config_dump`

または、

`$ kubectl exec -it [PODNAME] -c istio-proxy -n [NAMESPACE] bash`

でEnvoy-Proxyにログインし、

`$ curl localhost:15000/config_dump`

前者であればパイプやリダイレクトで好みの情報を抜き出したり加工することができるので、デバッグもログ採取も楽です。しかし情報量が多すぎるため、上述の`istioctl proxy-config`で必要な分だけをさらに絞り込んだ方が楽な時もあります。

# FQDN指定でアクセスする際のエンドポイントが正しいか確認する

`$ istioctl proxy-config endpoint [PODNAME].[NAMESPACE] -o json`

エンドポイントがどのIPアドレスで解決されるかを確認することができます。

# 私がトラブルシューティングする場合

反映されている箇所は知っている -> `istioctl proxy-config listeners/route/endpoint/cluster`

どこに反映されているかわからない。またはconfigを全て取得しておきたい。 -> `curl localhost:15000/config_dump`

といった使い分けを私はしています。
Denoでファイルダウンロードをする

最近Denoでファイルダウンロードをする必要があったので、実装しました。
てきとうに書いたのであまり良くない書き方をしているかもなので、その時はコメントでご指摘ください。

# 結論

```js
import ky from "https://deno.land/x/ky/index.js";

const url = "https://raw.githubusercontent.com/denolib/high-res-deno-logo/master/deno_hr.png";
const path = "deno.png";

ky.get(url)
    .arrayBuffer()
    .then(buffer => {
        Deno.writeFileSync(path, new Uint8Array(buffer));
    });

console.log("Completed download!");
```

kyでファイルを取得し、ArrayBufferからUint8Arrayにしたあと保存しています。

# やってみる

![try.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457036/ba1c5a12-0a28-030b-75db-3f89818dd933.gif)

無事にダウンロードできました。
なんかエラー出てEclipseが起動できなくなった時。!MESSAGE Job found still running after platform shutdown. 

#本題
Eclipseを強制終了した際など、次に起動するときにこんなメッセージが表示されて起動できないことがあります。


>An error has occurred. See the log file[workspace]\\.metadata\\.log.

続いて、何はともあれとりあえず記載のログを確認してみると、こんな内容が書いてあることがあります。

>!MESSAGE Job found still running after platform shutdown.  Jobs should be canceled by the plugin that scheduled them during shutdown

なにやら、「まだJOBが動いているので止めろ」的なようです。

この場合、てっとりばやく直すには、.metadataをフォルダごと削除するのがいいです。
削除しようとして怒られたら、移動させてやります。

#内容の理解と注意
.metadataとは
.metadataはワークスペースの設定内容を保持しています。
よって、こいつを削除するということは、同時にワークスペースを失い、ウィンドウに設定していた環境設定などが消えてしまうことになります。
なので、削除すると解決はしますが、結構困ったことになるので、.metadataの中で原因を頑張って突き止めつつ、嫌になったらエイヤと削除するのがいいのではないでしょうか。
【Adobe 】Photoshop Elements2020 / Premiere Elements 2020の新規購入PCでのアクティベーションについて

プログラミングに関する記事ではありませんが、覚書として書いておきます。

他の方でもなにかの役に立てば幸いです。


背景
　PCを新規購入しました。Mac Book Pro 2020 です。
以前使っていた、Mac Book Air 2015のスペック不足を感じたためです。
Macに搭載されているデータ移行ツールを使用して、セットアップ終了したので
早速、Photoshop Elements2020 / Premiere Elements 2020 を使おうと思ったところ
シリアルコードの入力を求められました。下画像(4桁×6枠＝24桁)。

<img width="803" alt="スクリーンショット 2020-07-01 19.50.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642569/ef3efd53-a6ea-eb6d-ebcd-dc90d245f6ab.png">

課題
　Adobeのwebサイト上で購入したため、手元にシリアルコードがなくシリアルコードを入力できず、ソフトを使用できなかった。

対応
　1　下記のサイトに行き、【注文】をクリック
　　https://helpx.adobe.com/jp/download-install/kb/find-serial-number.html


　2 下画面の注文番号に書いてある番号をクリック
    (画像の黒く塗りつぶしている部分に数字があるのでそこをクリック)

<img width="1276" alt="スクリーンショット 2020-07-01 19.42.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642569/863f261c-8b55-54a5-4308-7cc5a901a807.png">


 3 下画面になるので、[ダウンロード番号とシリアル番号]をクリック

 <img width="1298" alt="スクリーンショット 2020-07-01 19.42.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642569/eba27a9f-f518-3b2f-c822-046a993b857d.png">


　4 下画面の[シリアル]に書いてある番号がシリアル番号になります。
　　これを最初の画像の4桁×6枠に入力。

<img width="1323" alt="スクリーンショット 2020-07-01 19.42.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642569/445a8b93-7cae-3032-f2b4-28c7051ccc90.png">



以上です。


今回は、ちなみにこれをやると以前使用していたPCのアプリは自動的にサインアウトされていました。
同時に使用できるのは1台までということですね。
未経験エンジニア奮闘記　JavaSilver合格目指して勉強中詰まったところString型編

# はじめに
これは大学中退後8年間フリーターだったアラサーが一念発起してエンジニアに転職できたはいいものの、右も左もわからなすぎるのでJavaSilverを取得しようと頑張ったけどここで詰まったよってお話です。

まず私にはほとんどJavaの知識はありません。それどころかプログラミング全般大した知識が無いと言っていいです。
学生時代に趣味と授業でC言語はいじったなぁくらいで、最近はPython3をWeb教材で勉強したぞ！　ってくらいのドがつく素人です。

で、何故Javaの資格かと言われると単純に需要が高そうだから。それだけです。
オブジェクト指向ってやつをするのに適してるらしいじゃん？　くらいの印象しかありません。

Java Silver合格まで勉強中詰まったところをほぼ自分用に書いていこうと思います。
間違い等ありましたら是非私の未来の為に教えてください。

#String型の不思議
とりあえずJavaの入門書を買って勉強していると、さっそく面白い内容にぶちあたりました。
なんと、String型は参照型であるため例えば

```java:StrTest.java
public class StrTest {
  public static void main(String args[]) {
    String str1 = "hoge";
    String str2 = "ho";
    str2 += "ge";
    System.out.println(str1 == str2);
  }
}
```

は`false`になるから文字列比較する時は

```java:StrTest.java
public class StrTest {
  public static void main(String args[]) {
    String str1 = "hoge";
    String str2 = "ho";
    str2 += "ge";
    System.out.println(str1.equals(str2));
  }
}
```

みたいに`equals()`を使用するんだぞ


とのこと。さっそく大興奮の私は試しにこんなコードを書きました。

```java:StrTest.java
public class StrTest {
  public static void main(String args[]) {
      String str = "hoge";
      StrChange(str);
      System.out.println(str);
  }
  
  public static void StrChange(String str){
      str = "fuga";
  }
}
```

これで出力は`fuga`になるはず。なんてったって参照型なんだから。
そう思って実行すると出力されるのは`hoge`。おやぁ～？？

まったくクエスチョンになったのでGoogle先生に泣きついてみると、しっかり解説が出てきました。
先輩エンジニアの皆さん、ありがとうございます。

https://qiita.com/chihiro/items/d3d9a028cd5dd8e84649

どうやらString型のインスタンスはimmutableなので値を変更することがそもそもできないようです。
値を変更できない……？？？

```java:StrTest.java
public class StrTest {
  public static void main(String args[]) {
		String str = "hoge";
		System.out.println(str); // hoge
		str += "hoge";
		System.out.println(str); // hogehoge
		str = "fuga";
		System.out.println(str); // fuga
  }
}
```

めちゃ変更されてる！！
何故immutableなのに値が変更できる？　何故変更できるのにさっきのコードでは変更されてない？

前後不覚になったのでGoogle先生に泣きついてみると、しっかり解説が出てきました。
先輩エンジニアの皆さん、ありがとうございます。

https://freelance-jak.com/technology/java/1204/

どうやら値を変更しているようにみえて実際は新たな領域に新しい値として作り直しているようです。
というわけで間違いなくString型はimmutableであるようです。
さっき書いたコードはどっかのメソッドで新たな文字列が勝手に爆誕しているだけだったってことですね。