OmniAICreator/Qiita-1.07M huggingface dataset:
Intune管理iOSでは、Managed Browser ではなくEdgeを使うべき3つの理由

注）ポエムな要素を多分に含んでいます。


iOSデバイスでIntune入れてる会社は、結構な頻度でEMSいれてるんじゃないか思う。そうなると、結構な頻度でアプリ保護ポリシー適用したくなって、セキュアブラウザ使ってるんじゃなかろうか。（アプリ保護ポリシーについては[ここ参照](https://qiita.com/hisssa0102/items/289fdacde42351fc44da#%E3%82%A2%E3%83%97%E3%83%AA%E4%BF%9D%E8%AD%B7%E3%83%9D%E3%83%AA%E3%82%B7%E3%83%BC)。）


Intuneで色々適用できるセキュアブラウザといえば、Managed Browser と、Edge なんだけど、声を大にして言いたい。

**Edgeにしよう**

だって、便利だもん。

というわけで、Edgeにすべき3つの理由を個人的な主観でまとめてみました。


#速い

速いことは正義。待つの嫌だもん。IEとChrome、どっち使いますか？早いChrome使ってますよね。Managed BrowserとEdge(iOS)だと、IEとChromeぐらい違う。

たった数秒かもしれない。でも、パワーは正義。

速いほうがいいっしょ？


#パスワード記憶させられる

セキュアブラウザは組織の情報残しちゃダメ。とはいえ、ユーザーからすればパスワード記憶してくれたらやっぱり便利。Managed Browser だと残せないけど、Edgeだと保存できる。しかも、組織アカウントの範囲で保持するので、iOSに渡すわけではないので、管理者目線でも安心。

想像してほしい。毎回パスワードを入れなくていい世界を。みんな、今日も~~生きてる~~業務してる。

楽に使えるほうがいいっしょ？

#複数のデバイス間とリンク

マルチデバイスで、ブックマークとか閲覧履歴か、見直しできれば便利。Officeファイルなら別デバイスで扱ったら、ほかのデバイスからでも「最近使ったファイル」で一発で開ける。おんなじことが、Edgeならできる。履歴も、ブックマークもリンクしてる。
Chromium Edgeとの同期はまだこれからっぽいけどな。

プライベートのデバイスでできる便利な機能なら、業務のツールでできてたっていいじゃないか！（もちろん、全部が全部、いいとはいいませんが）

#ついでに、管理者目線で
Managed Browser だと、SharePoint のモダン表示が一部動かない。ってことで問い合わせ来たりする。面倒。
Edgeだと、こんな問い合わせは、来ない。

それと、アプリ構成ポリシー作る画面も、Edgeだと簡単に作れる。ブックマーク追加や、アクセス禁止URL入れるのも簡単。Edgeの設定は、ManagedBrowserと共有してるし。
参考：[保護ブラウザー アプリの構成を作成する](https://docs.microsoft.com/ja-jp/intune/manage-microsoft-edge#create-a-protected-browser-app-configuration)


ユーザーもラクで、管理者もラクなら、どっちをとるか自ずと同じ答えになるんじゃないのかな。



##最後に
ただね。オフィシャルにはEdge推奨、などという案内出てない。オフィシャルな案内だしてくれたら、たとえ文句言う人いたとしても「いや～、仕様変更らしくて、どうしようもないんすよ。てへぺろ。」って言えるのだけどな。まだかな～まだかな～。
SQL  結合編

#結合

結合も集合演算子と同じようにテーブル同士をくっつけます。

集合演算子が行を足し合わせる（テーブル同士を上下にくっつける）に対し、

結合は列をくっつけます（テーブル同士を横にくっつける）。

 

結合の種類：

・内部結合　　INNER JOIN

・左外部結合    LEFT OUTER JOIN

・右内部結合    RIGHT OUTER JOIN

・完全外部結合   FULL OUTER JOIN

＋

・自己結合


基本の形：

```sql
SELECT　選択列
FROM　テーブル
JOIN 結合するテーブル ON
結合条件 = 結合条件
```
 

#内部結合  INNER JOIN

両方のテーブルの結合条件に一致する行だけ取得します。

```sql
SELECT TS.tenpo_id, TS.tenpo_mei, TS.shohin_id, S.shohin_mei, s.hanbai_tanka
FROM TenpoShohin AS TS INNER JOIN Shohin AS S 
ON TS.shohin_id = S.shohin_id;
```

訳：

TenpoShohin（TSと呼ぶことにし）とShohin（Sと呼ぶことにし）を結合する。
そのため、結合条件としてTSのshohin_idとSのshohin_idを紐づける。
内部結合に関わらず、どの結合方法も基本的には流れは同じです。
INNER JOINにするか OUTER JOINにするかという違いです。

 

#外部結合 OUTER JOIN

内部とは反対に、外部は全行を取得します。

左外部結合は左のテーブルを基準とし、結合されるもう一方のテーブルは左テーブルと一致するレコードのみ取得されます。

右外部結合はその逆となります。

書き方は基本、内部結合と変わりませんし、左か右かもLEFTかRIGHTにするだけです。

```sql
SELECT TS.tenpo_id, TS.tenpo_mei, TS.shohin_id, S.shohin_mei, s.hanbai_tanka
FROM TenpoShohin AS TS LEFT OUTER JOIN Shohin AS S 
ON TS.shohin_id = S.shohin_id;
```
 

#完全外部結合　FULL OUTER JOIN

両方のテーブルどちらも優先で、結合条件で一致するレコード、一致しないレコード全てを取得します。

 
```sql
SELECT TS.tenpo_id, TS.tenpo_mei, TS.shohin_id, S.shohin_mei, s.hanbai_tanka
FROM TenpoShohin AS TS FULL OUTER JOIN Shohin AS S 
ON TS.shohin_id = S.shohin_id;
```
 

 

#自己結合

上記では結合は２つのテーブルを結合してましたが、内部結合では１つのテーブルの中で結合します。検索したいものを、１つのテーブル内の情報を組み合わせて探し出します。

```sql
SELECT　選択列
FROM テーブル AS テーブル１
JOIN テーブル AS テーブル 2 ON
(テーブル1.項目 = テーブル2.項目）
```

```sql
SELECT staff.id AS id, 
 staff.name AS 名前, 
 boss.name AS 上司名
FROM staff 
JOIN staff AS boss ON
(staff.boss = boss.id)
```
 

会社の組織のなかで、自分の上司は会社内の人ですし、同じく自分の部下も会社内の人です。つまりテーブルに全メンバーがいれば、もう一つ同じテーブルを用意し、メンバー同士の関係性を組み合わせれば上司は誰かということが導き出されます。プロセス上もう一つのテーブルを作りますが、実態は、一つのテーブル内の情報で検索が完結できるということです。
自分のためのLINE Bot用npmパッケージをつくった

# はじめに
Messaging APIを使ってLINE Botを何回か作っていると、同じようなコードを書くのが面倒になるので自分用のnpmパッケージを作ってみようと思いました。

# つくったもの
今回はnpmパッケージ公開の練習を兼ねているので簡単なものを作りました。[ここ](https://www.npmjs.com/package/line-message-builder)で公開しています。
内容として、[LINE Bot用のNode SDK](https://github.com/line/line-bot-sdk-nodejs)でのreplyMessageの

```javascript
{
  type: 'text',
  text: 'Hello'
}
```

というテキストメッセージのためのオブジェクトを入力したテキストのみから作成する関数をつくりました。機能としては、

1. 単機能でのテキストメッセージ作成
2. 配列形式での複数メッセージ作成
3. 配列形式で渡されたテキストからどれか一つをランダムで選んでメッセージ作成

この３つをサポートしています。特に大した内容ではありませんが、一々オブジェクト組み上げるの面倒だったのと、複数メッセージ作るのがだるかったので少し快適になりました。ちなみに複数メッセージについては[こちら](https://qiita.com/ufoo68/items/ea923025e7989ff5af3d)を参照してください。

## 単体でのメッセージ作成
単純に入力したテキストデータを適切なオブジェクトに変換します。

```javascript
buildReplyText('test')
/*
return
{
  type: 'text',
  text: 'test'
}
*/
```

## 複数のメッセージ作成
配列を受け取った場合は配列形式のオブジェクトで返します。順番は配列の0のインデックスからになります。

```javascript
buildReplyText(['test1', 'test2'])
/*
return
[{
  type: 'text',
  text: 'test1'
},
{
  type: 'text',
  text: 'test2'
}]
*/
```

## ランダムなメッセージを作成
配列を受け取ったときにどれか一つをランダムで返す関数もサポートしました。

```javascript
buildReplyRandomText(['test1', 'test2', 'test3'])
/*
return
{
  type: 'text',
  text: 'test2'
}
*/
```

# 参考にしたサイト
少し古いですが、[このサイト](https://codeburst.io/https-chidume-nnamdi-com-npm-module-in-typescript-12b3b22f0724)がとてもわかり易かったです。

# これからやりたいこと
今のところは以下の機能を自分のためにアップデートしていきたいです。

- 特定のワードが含まれていた場合の返信用メッセージの作成
- テキスト以外のタイプのメッセージ作成

# さいごに
npmパッケージ作成は思ったより楽でした。自分のライブラリを[npmjs](https://www.npmjs.com/)が管理してくれるのでほしいときにすぐに取ってこれますね！
SQL  集合演算子編

#集合演算子


構造が似たテーブルを合算させることができるのが集合演算子。

構造が似たというのは、列数、列名が同じテーブルのことです。

例えば、家計簿データベースで行数が増えてきたので、アーカイブテーブルに古いデータを写した場合、構造が同じテーブルが２つできることになりますので、それらをもう一度がっちゃんこできるということです。

集合演算子には、いくつかの演算子がありますので、それぞれまとめます。

 

#和集合を求める　UNION

 ２つのSERECT文の検索結果を足し合わせます。

イメージとしてはテーブルの足し算（行の足し算）です。

なおUNIONでは重複行があった場合、１つにまとめます。

```sql
SELECT shohin_id, shohin_mei　　--式１
FROM shohin
UNION
SELECT shohin_id, shohin_mei　　--式２
FROM shohin2;
```
 

###UNION ALL

は重複行があった場合も全て含めます。

```sql
SELECT shohin_id, shohin_mei　　--式１
FROM shohin
UNION　ALL
SELECT shohin_id, shohin_mei　　--式２
FROM shohin2;
```
 

#差集合を求める　EXCEPT

レコードの引き算です。

式１EXCEPT 式２は式１から式２を引く、つまり式１にはあって式２にはないものが最後残ります。下記で言えば、shohinテーブルにはあるけど、shohin2テーブルにはないものが選ばれます。

```sql
SELECT shohin_id, shohin_mei　　--式１
FROM shohin
EXCEPT
SELECT shohin_id, shohin_mei　　--式２
FROM shohin2;
```
 

#積集合を求める　INTERSECT

両方のテーブルにある共通のものが選ばれます。

```sql
SELECT shohin_id, shohin_mei　　--式１
FROM shohin
INTERSECT
SELECT shohin_id, shohin_mei　　--式２
FROM shohin2;
```
 

集合演算子の注意点：

・集合対象となるレコードの数は同じであるべし

・足し算の対象となるレコードの列のデータ型は一致しているべし

・SELECT文はどんなものを指定してもいいが、ORDER BYは最後に一つだけ
SQL  述語・CASE文編


#述語とCASE文

述語は戻り値が真理値になる関数のこと

目次：

述語

・LIKE述語
・BETWEEN述語
・IS NULL,  IS NOT NULL

CASE文

 

##文字列の部分一致検索　LIKE述語　

文字を検索する際、文の一部分だけを指定して、それが含まれる文字を探してくれる便利なLIKE述語。

###・前方一致

下記の例では、「dddなんとか〜」という文字を探してきます。

```sql
SELECT *
FROM SampleLike
WHERE 'ddd%';
```

###・中間一致

これは、どこかの位置にdddが含まれる文字を探します。

〜dddやddd~、また〜ddd〜などなど

```sql
SELECT *
FROM SampleLike
WHERE '%ddd%';
```

###・後方一致

これは、「なんとか〜ddd」という文字を探します。

```sql
SELECT *
FROM SampleLike
WHERE '%ddd';
```
 

#範囲検索　BETWEEN述語

対象 BETWEEN 下限 AND 上限

1下記、単価を取得する際、「100円から1000円までの」と範囲を絞れます。

```sql
SELECT shohin_mei, hanbai_tanka
FROM Shohin
WHERE hanbai_tanka BETWEEN 100 AND 1000;
```
 

反対に含みたくないときは

```sql
SELECT shohin_mei, hanbai_tanka
FROM Shohin
WHERE hanbai_tanka > 100
AND hanbai＿tanka < 1000;
```
 

###NULLかどうかの判定　IS NULL  /  IS NOT NULL

NULLは　＝　NULLということができません。

NULLを指定する場合はIS NULL

NULLを排除したいときは　IS NOT NULLです。

```sql
SELECT shohin_mei, shiire_tanka
FROM Shohin
WHERE shiire_tanka IS NULL;
```
 

 
#場合分けを記述する　CASE文

 

###単純CASE式

```sql
CASE ＜式＞
WHEN ＜式＞ THEN ＜式＞
WHEN ＜式＞ THEN ＜式＞
ELSE ＜式＞
END
```
 
 
```sql
CASE hanbai_tanka
WHEN 100 THEN '100円'
WHEN 200 THEN '200円'
ELSE 'その他'
END
```
 

例２

```sql
SELECT 費目, 出金額,
CASE 費目 WHEN '居住費' THEN '固定費'
WHEN '教育費' THEN '固定費'
ELSE '固定費'
END AS 出費の分類
FROM 家計簿 WHERE 出金額 > 0
```
 

###検索CASE式
```sql
WHEN ＜評価式＞THEN＜式＞
WHEN ＜評価式＞THEN＜式＞
ELSE  ＜評価式＞
```

```sql
SELECT SUM(CASE WHEN shohin_bunrui = '衣服'
THEN hanbai_tanka ELSE 0 END) AS sum_tanka_ihuku,
SUM(CASE WHEN shohin_bunrui = 'キッチン用品'
THEN hanbai_tanka ELSE 0 END) AS sum_tanka_kitchin
FROM Shohin;
```
 

例２

```sql
SELECT メールアドレス
CASE WHEN 年齢 >= 20 AND 年齢 < 30 THEN '20代'
WHEN 年齢 >= 30 AND 年齢 < 40 THEN '40代'
END
```
MacでChromeをアップデートしようとすると毎回エラー：１２が表示される

# １，はじめに
Macbook AirにインストールしたGoogle Chromeを更新しようとすると、エラーが表示された。
筆者のサイトにも[記載している](https://sysrigar.com/2019/09/14/mac%e3%81%aechrome%e3%81%8c%e6%9b%b4%e6%96%b0%e3%81%a7%e3%81%8d%e3%81%aa%e3%81%84%e3%81%ae%e3%81%a7%e5%af%be%e5%87%a6%e3%81%97%e3%81%9f/)が、Qiitaにも転記する。

発生環境
* Chrome 76.0.3809.132（Official Build） （64 ビット）
* Mac OS 10.14.6 (18G95)

エラーログは、下記の通りである。

```
更新できませんでした（エラー: 12）
 エラーの詳細:
 KSInstallAction install script failure. Exit code: 12. Standard error output: "goobspatch: old hash mismatch: 22c8125f41577ff4f34dc33bf3f4e25793decdba != 933911d0cf53f90320b51d10b512965d03a8eb8c\ndirpatcher.sh: couldn't create /Applications/Google Chrome.app/Contents/Frameworks/Google Chrome Framework.framework/Versions/77.0.3865.75/Helpers/Google Chrome Helper (GPU).app/Contents/CodeResources by applying /tmp/KSInstallAction.F5XyNdrTX7/m/.patch/framework_76.0.3809.132_77.0.3865.75.dirpatch/Helpers/Google Chrome Helper (GPU).app/Contents/CodeResources$gbs to /Applications/Google Chrome.app/Contents/Frameworks/Google Chrome Framework.framework/Versions/76.0.3809.132/Helpers/Google Chrome Helper (GPU).app/Contents/CodeResources\n.keystone_install: dirpatcher of versioned directory failed, status 13\n".
```

# ２，原因調査
今回、サポートサイトと開発コミュニティの２つを中心に調査を行なった。

## (1) サポートサイト
まず、サポートサイトで類似事例がないか調査を行なった。
その結果、以下のケースが本件と類似する事例として発見できた。

[chrome giving me an error when updating had issue before last month - Google Chrome Help](https://support.google.com/chrome/thread/9379810)

## (2) 開発コミュニティ
また、Chromeの基幹部分を開発しているコミュニティのメーリングリストからも、
類似事例の記載を発見できた。

[Issue 991570 - chromium - An open-source project to help move the web forward. -  Monorail](https://bugs.chromium.org/p/chromium/issues/detail?id=991570)

# 3，根本原因と思われるもの

開発コミュニティのメーリングリストに、以下の記述があった。

## (1) 原文

```
In comment 3, the reporter suggests that this may have happened after upgrading from 10.14.5 or 10.14.6.
If something on the system is rewriting stapled notarization tickets, it would be unexpected and could cause this breakage.
This would be the first report of that happening, though, and unless we catch something in the act (seeing a copy of the modified file would help), it’s hard to come up with a plan of action.
```
引用元：[Issue 991570: macOS: Updating Chrome always fails](https://bugs.chromium.org/p/chromium/issues/detail?id=991570#c6)

## (2) 和訳
(注)筆者の拙い語学力での意訳(筆者の読みが入っています)のため、誤りがある可能性があります。

```
指摘事項３の報告者が言うように、Mac OSをアップデートしたことが本件事象の原因かもしれません（確定ではない）。
もしかしたら、アップデートに伴い、Chromeの認証用に作成した情報が、書き換えられたのかもしれません（確定ではない）。
あとこれ、初耳なので、対応するの大変(わかる。お仕事、お疲れ様です)。
```

## (3) 考察
Mac OSはApp Store以外からインストールしたソフトウェアについて、
認証を行うところ、PC内部に保存されていたキー情報がMac OSの更新に伴い、変更された。

上記が原因として仮定できる。

# 4，対応
Chromeの再インストールを行う。

# 5，参考資料
* [macOS の App Notarization について - Qiita](https://qiita.com/noby111/items/89840a8ef46185863ace)
* [Issue 991570 - chromium - An open-source project to help move the web forward. -  Monorail](https://bugs.chromium.org/p/chromium/issues/detail?id=991570)
SQL  サブクエリ編

#サブクエリ

サブクエリは副問い合わせともいい、SELECT文をネストして欲しいデータを探します。

下記では、FROMの後に、さらにSELECT文を使っています。

順番としてはまず（）内のサブクエリが実行され、その後１行目のSELECT文が実行されます。FROMで参照したいテーブル内容をさらにSELECT文で探してきているということです。

例１

```sql
SELECT shohin_bunrui, cnt_shohin
FROM (SELECT shohin_bunrui, COUNT(*) AS cnt_shohin
FROM Shohin
GROUP BY shohin_bunrui) AS Shohinsum;
```
 

例２

サブクエリを使わない場合、「一度SELECT文で出金額を出して、それをもう一回SELECT文書いて使う」と二度手間になってしまいます。

```sql
SELECT MAX(出金額)
FROM 家計簿;
```

```sql
SELECT 費目, 出金額
FROM 家計簿
WHERE 出金額 = [メモしておいた金額]
```

↓

サブクエリ使うと、以下のように１つのSQL文で済みます。出金額については（）で

MAX額を計算して「出金額」を取得しています。

```sql
SELECT 費目, 出金額
FROM 出金額 = (SELECT MAX(出金額)
　 FROM 家計簿)　AS 出金額
```
 

サブクエリの３つのパターン

１、単一の値の代わりとして、サブクエリの検索結果を用いる

２、複数の値の代わりとして、サブクエリの検索結果を用いる

３、表のの値の代わりとして、サブクエリの検索結果を用いる

 

###１、単一行サブクエリ

・検索結果が１行１列の値になる。

・SELECT文の選択リストやFROM句、UPDATEのSET句、また１つの値との判定を行うWHERE句の条件式などに使える

 

SET句

```sql
UPDATE 家計簿集計
SET 平均 = (SELECT AVG(出金額)
FROM 家計簿アーカイブ
WHERE 出金額 > 0
AND 費目 = '食費')
WHERE 費目 = '食費';
```
 

選択リスト

```sql
SELECT 日付, メモ, 出金額,
 (SELECT 合計 
FROM 家計簿集計
WHERE 費目 = '食費') AS 過去の合計額
FROM 家計簿アーカイブ
WHERE 費目 = '食費'
```
 

###２、複数行サブクエリ

・検索結果がn行1列の複数の値となる（nは１以上）

・複数の値との判定を行うWHERE句の条件式や、SELECT文のFROM句に記述できる

 

INを利用

```sql
SELECT *
FROM 家計簿
WHERE 費目 IN ('食費', '水道光熱費', '給料');
```

または以下のようにすることも可能

```sql
SELECT *
FROM 家計簿
WHERE 費目 IN (SELECT DISTINCT 費目 FROM 家計簿);
```
 

###ANYを利用

```sql
SELECT *
FROM 費目 = '食費'
AND 出金額 < ANY (SELECT 出金額 
FROM 家計簿アーカイブ
WHERE 費目 = '食費');
```
 

###NULLを除外したい

```sql
SELECT *
FROM 家計簿アーカイブ
WHERE 費目 (SELECT 費目 FROM 家計簿
WHERE 費目 IS NOT NULL);
```
 

###３、表形式

・検索結果がn行n列の表となる（n、mは１以上）

・SELECT文のFROM句やINSERT文などに記述できる

```sql
SELECT SUM(SUB, 出金額) AS 出金額合計
FROM (SELECT 日付, 費目, 出金額
FROM 家計簿
UNION
SELECT 日付, 費目, 出金額
FROM 家計簿アーカイブ
WHERE 日付 >= '2018-01-01'
AND 日付 <= '2018-01-31') AS SUB;
```
SQL  集約と並び替え編

#集約と並べ替え

 

#集約関数

 

###行数を数える　COUNT関数

```sql
SELECT COUNT(引数）
FROM テーブル名
```

全行数えるなら(＊）を利用。

```sql
SELECT COUNT(*)
FROM shohin;
```

NULLの行を除外したい場合、対象とする列を限定して引数に書く。

```sql
SELECT COUNT(shiire_tanka)
FROM Shohin;
```
 

###合計を求める　SUM関数

NULLがあった場合、無視されますので影響ありません。

```sql
SELECT SUM(hanbai_tanka), SUM(shiire_tanka)
FROM Shohin;
```
 

###平均値を求める　AVG関数

SUM関数と同様、NULLは含まれません。

300, 500, NULLの場合、（300 + 500) / 2 = 400となります。

```sql
SELECT AVG(hanbai_tanka)
FROM Shohin;
```
 

###最大値・最小値を求める　MAX関数・MIN関数

```sql
SELECT MAX(hanbai_tanka), MIN(shiire_tanka)
FROM Shohin;
```
 

###グループ分けする　GROUP BY句

SELECT 列名１, 列名２, 列名３
FROM テーブル名
GROU BY 列名１, 列名２, 列名３

グループ分けして、そのグループごとに計算して表示することができます。

下記、shohin_bunruiごとに行数を数えます。

```sql
SELECT shohin_bunrui, COUNT(*)
FROM Shohin
GROUP BY shohin_bunrui;
```

例えば、shohin_bunruiに衣服、事務用品、キッチン用品があった場合、それぞれ何行あるかを計算して表示できます。

 
```sql
shohin_bunrui   　　count
衣服　　　　　　　２
事務用品　　　　　４
キッチン用品　　　 ５
```
 

WHERE句で条件を指定できます。

```sql
SELECT shiire_tanka, COUNT(*)
FROM Shohin
WHERE shohin_bunrui = '衣服'
GROUP BY shiire_tanka;
```
 

NULLがあった場合、NULLとして１つのグループに分類されます。

 

注意１：

GROUP BYでSELECT分に書けるのは、

・定数

・集約関数

・GROUP BY句で指定した列名（つまり集約キー）

 

注意２：

GROUP BY句に列の別名（AS)はつけれない

 

注意３：

GROUP BY句を使って結果を選択した時、表示される結果の順番はランダム

 

注意４：

GROUP BY句のGROUP BYリストに使用される式内では集計、またはサブクエリは使えない

 

集約した結果に条件を指定する　HAVING句


GROUP BYを使って集約した際、更に条件を指定して絞り込みたい時はHAVING句を使います。

```sql
SELECT 列名１, 列名２, 列名３
FROM テーブル名
GROU BY 列名１, 列名２, 列名３
HAVING グループの値に対する条件
```
 

shohin_bunruiごとに集約をし、集約された値に対し更に2500（円）以上のもののみ取得するという条件をつけると

```sql
SELECT shohin_bunrui, AVG(hanbai_tanka)
FROM Shohin
GROUP BY shohin_bunrui
HAVING AVG(hanbai_tanka) >= 2500;
```
 

WHERE　と　HAVINGについて

「集約キーに対する条件」は WHERE句、HAVING句それぞれに書くことはできますが、その違いは何なのか。取得できる結果は同じですが、集約キーに対する条件はソートに掛かる時間の関係上WHERE句に書く方がいいそうです。

WHERE句

```sql
SELECT shohin_bunrui, COUNT(*)
FROM Shohin
WHERE shohin_bunrui = '衣服'
GROUP BY shohin_bunrui;
HAVING句

--△ ソートに時間がかかり処理が遅くなる

```sql
SELECT shohin_bunrui, COUNT(*)
FROM Shohin
GROUP BY shohin_bunrui
HAVING shohin_bunrui = '衣服';
```
 

注意：

集計がHAVING句または選択リスト内にある場合、及び集計する列が外部参照の場合にだけWHERE句に集計を含めることができる。

 

検索結果を並べ替える　ORDER BY句

ASC: 昇順（小さい順）

DESC: 降順（大きい順）

※指定しなければ自動的にASCになる

ORDER BY句は最後に書きます。

```sql
SELECT shohin_id, shohin_mei, hanbai_tanka, shiire_tanka
FROM shohin
ORDER BY hanbai_tanka;
```

--何も指定しなければASC(昇順：小さい順）

 

・NULLを含む列は先頭または末尾にまとめられて表示されます。

・GROUP BYと違い列の別名が使える

（処理の順番的にGROUP BYの時はまだ別名が認識されていないがORDER BY句は最後なので認識される）
決定木のハイパーパラメータをOptunaで最適化する

機械学習をする際に自身で決めなければならないパラメータを、ハイパーパラメータと言います。

Optunaは機械学習のために設計されたハイパーパラメータ最適化フレームワークです。

https://optuna.org/

今回はsickit-learnのDecisionTreeClassifierのハイパーパラメータチューニングを試みます。

以下の公式ドキュメントに各ハイパーパラメータの詳細があります。

https://scikit-learn.org/stable/modules/generated/sklearn.tree.DecisionTreeClassifier.html

irisデータセットでrandome_state以外何も指定せずに実行してみます。

```python:
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier

clf = DecisionTreeClassifier(random_state=0)
iris = load_iris()
X = iris.data
y = iris.target
(X_train, X_test,
 y_train, y_test) = train_test_split(
    X, y, test_size=0.3, random_state=0,
)
clf.fit(X_train, y_train)
```


```
DecisionTreeClassifier(class_weight=None, criterion='gini', max_depth=None,
                       max_features=None, max_leaf_nodes=None,
                       min_impurity_decrease=0.0, min_impurity_split=None,
                       min_samples_leaf=1, min_samples_split=2,
                       min_weight_fraction_leaf=0.0, presort=False,
                       random_state=0, splitter='best')
```

```python
print(clf.score(X_train, y_train))
print(clf.score(X_test, y_test))
```

```
1.0
0.9777777777777777
```

ここからがOptunaを用いたハイパーパラメータ最適化の部分です。

```python
from sklearn.metrics import accuracy_score
def objective(trial):
    max_depth = trial.suggest_int("max_depth", 2, 612)
    min_samples_split = trial.suggest_int("min_samples_split", 2, 612)
    max_leaf_nodes = int(trial.suggest_int("max_leaf_nodes", 2, 612))
    criterion = trial.suggest_categorical("criterion", ["gini", "entropy"])
    
    DTC = DecisionTreeClassifier(min_samples_split = min_samples_split, 
                                max_leaf_nodes = max_leaf_nodes,
                                criterion = criterion)
    DTC.fit(iris.data, iris.target)
    return 1.0 - accuracy_score(y_test, DTC.predict(X_test))
```

```
!pip install optuna
```

```python
import optuna
study = optuna.create_study()
study.optimize(objective, n_trials = 500)
```

```python
print(study.best_params)
print(1.0 - study.best_value)
```

```
{'max_depth': 78, 'min_samples_split': 2, 'max_leaf_nodes': 539, 'criterion': 'gini'}
1.0
```

最適なパラメータは
{'max_depth': 78, 'min_samples_split': 2, 'max_leaf_nodes': 539, 'criterion': 'gini'}
であることがわかりました。

ソースコードはgithubでも公開しております。

https://github.com/lystahi/qiita/blob/master/Optuna_DecisionTreeClassifier.ipynb
[memo]ML.線形回帰(式)

## 単回帰
- 線形モデル

>```math
\hat{y}=w_1x + w_0
```

- 残差（residual）

>```math
\hat{y_i}-y_i
```

- コスト関数(二乗誤差)

>```math
J(w_0, w_1)=\frac{\sum_{i=1}^{m}{(\hat{y_i}-y_i})^2}{{2m}}\\
・斜面の傾きを計算する偏微分
```
 
- 最急降下法
    - 最適化アルゴリズム
        - コストを最も低くする$w_0$,$w_1$を導き出す
        - 最急降下法(Gradient Decent)が一般的
            - $w_0$,$w_1$の最適化
            - $J$の最小化

>```math
w_0=:w_0 - \alpha \frac{\partial}{\partial w_0}J(w_0, w_1)=w_0 - \alpha\frac{1}{m}\sum_{i=0}^{m}(\hat{y} - y_i)\\
w_1=:w_1 - \alpha \frac{\partial}{\partial w_1}J(w_0, w_1)=w_1 - \alpha\frac{1}{m}\sum_{i=0}^{m}(\hat{y} - y_i)x_i\\
=:は値を更新する\\
\alphaは学習率(learning\hspace{5pt}rate)\\
```

## 重回帰
- 線形モデル

>```math
Y = XW
```

- コスト関数

>```math
J(W) = \frac{1}{2m}\sum_{i=0}^n(\hat{y}-y_i)^2 \\
= \frac{1}{2m}(XW-y)^T(XW-y)\\
```

- 最急降下法

>```math
W=:W - \alpha\frac{1}{m}X^T(XW-y)\\
```

- 正規化（feature scaling/normalization）

1) zero score normalization

>```math
x_1 = \frac{x_1-\bar{x}}{\sigma}
```

2) min-max normalization

>```math
x_1 = \frac{x_1-x_{min}}{x_{max}-x_{min}}
```


疑問：
学習率が高すぎると最小値を通り過ぎて、だんだん離れていく？？？

ref:
- [Qiitaの数式チートシート](https://qiita.com/PlanetMeron/items/63ac58898541cbe81ada)
- [線形回帰 入門](https://student.codexa.net/contents/view/72)
- [Introduction to residuals and least-squares regression](https://www.khanacademy.org/math/ap-statistics/bivariate-data-ap/least-squares-regression/v/regression-residual-intro)
SQL  検索の基本編

#SQL　検索編
 

・基本の形

```sql
SELECT
選択列
FROM テーブル名
```
 

SELECTの後に選択したい列（カラム名）を書きます。AS　〜　とすることで別名にすることができます。ASを付けた場合、AS以下の名前が列名として表示されます。

FROMのあとは、データを取ってきたいテーブル名を書きます。

```sql
SELECT shohin_id AS "商品ID",
 shohin_mei AS "商品名",
 shiire_tanka AS "仕入れ単価"
FROM Shohin;
```
 

##重複行を一つにまとめる　DISTINCT

SELECT DISTINCT 列名

FROM テーブル名

同じ値が入っている行については２つ表示するのではなく、１行でまとめます。

```sql
SELECT DISTINCT shohin_bunrui
FROM Shohin;
```
 

##行を指定する　WHERE
```sql
SELECT 列名
FROM テーブル名
WHERE 取得したい条件
```

下記では、Shohinテーブルからshohin_meiとshohin_bunruiを取得する。条件としてshohin_bunruiが"衣服"のもの。つまりWHERE抜きだと単純にshohin_meishohin_bunruiの列を全行取得しますが、WHEREに続けて条件を書けば、それに合致した行のみ取得できます。

```sql
SELECT shohin_mei, shohin_bunrui
FROM Shohin
WHERE shohin_bunrui = "衣服";
```
 

##算術演算子

SQL文の中では四則演算（＋　ー　＊　/ )も使えます。 

```sql
SELECT shouhin_mei, hanbai_tanka,
 hanbai_tanka * 2 AS '販売単価の２倍'
FROM Shohin;
```

注意１：

NULLが入っている式は答えが全てNULLになります。

```sql
5 + NULL → NULL
10 - NULL → NULL
2 * NULL → NULL
```

注意２：

データ型が違うものは+ で連結できません。

どちらかデータ型を変換して合わせましょう。

文字型　→　数字型  へ変換 （できない）

数字型　→　文字型  へ変換（できる）

 

注意：

WHERE句の後ろに四則演算は使えません（条件式は書ける）。

WHERE句に書けるもの、書けないものは別途ブログに書きます。

 

##比較演算子

= 　  等しい

<> 　等しくない

>=    以上

>      より大きい

<=    以下

<     より小さい

 

hanbai_tankaが1000(円)以上のものを条件にする

```sql
SELECT shohin_mei, shohin_bunrui, hanbai_tanka
FROM Shohin
WHERE hanabi_tanka >= 1000;
```

日付に使うと、以降、以前など指定できます。

もしCHAR型(文字型）の'3'に指定すると辞書式順序になります。

 

##論理演算子

 

〜でないもの　AND演算子

hanbai_tankaが1000(円)以下のもの

 
```sql
SELECT shohin_mei, shohin_bunrui, hanbai_tanka
FROM Shohin
WHERE NOT hanabi_tanka >= 1000;
```
 

または　OR演算子

shohin_bunruiが事務用品または衣服

```sql
SELECT shohin_mei, shohin_bunrui, torokubi
FROM Shohin
WHERE shohin_bunrui = '事務用品'
OR shohin_bunrui = '衣服';
```

ANDとORの組み合わせに注意：

( )で分けないと意図しないデータが取得されます。

( )の中から処理されるので取得したい条件を整理して書きましょう。

以下 、「shohin_bunruiが事務用品」と「登録日が9/11または9/20」となります。

事務用品は必ず取得できます。が（）の入れ子を誤ると取得できなくなる可能性も。

```sql
SELECT shohin_mei, shohin_bunrui, torokubi
FROM Shohin
WHERE shohin_bunrui = '事務用品'
AND ( torokubi = '2009-09-11'
OR torokubi = '2009-09-20');
```
 

論理演算子の優先度は

１、NOT

２、AND

３、OR

（）をつければ優先順位を引き上げる事ができます。

取得したい情報は何か整理してうまく（）を使おう！
#VsCode の Rest Client で Bearer 認証でのリクエストを投げる例

```
GET https://example.com/
Authorization: Bearer some-token
```

コマンドパレットに Rest Client とか入力するなどして実行

![image](https://user-images.githubusercontent.com/13635059/64907337-e65e0e00-d72b-11e9-8e11-4b9655b19b18.png)


![image](https://user-images.githubusercontent.com/13635059/64907334-e0682d00-d72b-11e9-9d48-e4e630554d40.png)


# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/2438








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
Unity2019.2にあげたらC#スクリプトをダブルクリックしてもvscodeがファイルを開いてくれない

## Unity2019.2にあげたらC#スクリプトをダブルクリックしてもvscodeがファイルを開いてくれない
正確にはC#スクリプトをダブルクリックするとvscodeは正常に起動するが、ダブルクリックしたファイルを開いてくれない。

# 解決策
PackageManagerからVisualStudioCode Editorの1.1.2をインストールする
<img width="707" alt="スクリーンショット 2019-09-14 22.34.30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278474/25096e37-8a2d-a0c4-c5f3-aefe7752ca39.png">
SQL  テーブルの作成・編集編

#データベース、テーブルの作成、編集

 

SQLはデータベースに指令を出して得たい情報などを取得できる言語なので、

まずはデータベースありきです。

データベース内では様々なテーブルがあり、それら各々のテーブルから、またテーブル同士を結合させるなどして情報を取得します。

データベース、テーブルを作ることもSQLではできるので、まずはそこからまとめていきます。

 

なお、コードの内容については今読んでる参考書のものを引用させて頂きます。

使用するRDBMSはSQL serverを想定しています。

 

#データベースを作る

```sql
CREATE DATABASE データベース名;
```

下記ではshopというデータベースを作りました。

```sql
CREATE DATABASE shop; 
```
 

#テーブルを作る

```sql
CREATE TABLE テーブル名
(カラム名　データ型  　制約の設定);
```

下記、shohinというテーブルを作りました。

その下は、例えばshohin_idカラムで、データ型はCHAR型、さらにNOT NULL制約をつけています。制約については付けなくてもOK。付ければデータの整合性は高められます。反面、制約をかけるのでデータの使い勝手が悪くなるということも。

一番下のPRIMARY KEYは主キーです。今回はshohin_idを主キーにしました。

```sql
CREATE TABLE shohin
(shohin_id CHAR(4) NOT NULL,
shohin_mei VARCHAR(100) NOT NULL,
shohin_bunrui VARCHAR(32) NOT NULL,
hanbai_tanka INTEGER ,
shiire_tanka INTEGER ,
torokubi DATE ,
PRIMARY KEY (shohin_id)
);
```
 

 

#テーブルの削除

```sql
DROP TABLE テーブル名;
```

```sql
DROP TABLE Shohin;
```
 

#テーブルの更新

カラムの追加

```sql
ALTER TABLE テーブル名 ADD カラム名 データ型
```

```sql
ALTER TABLE Shohin ADD shihin_mei_kana VARCHAR(100);
```
 

#カラムの削除

ALTER TABLE テーブル名 DROP COLUM カラム名

※追加の時は新規なのでデータ型も指定しますが、削除する時はすでにデータ型はわかっているので指定は不要。

```sql
ALTER TABLE Shohin DROP COLUMN shohin_mei_kana;
```
 

#テーブルにデータを登録

先ほどまではカラムでしたが、１つのデータ、つまりレコードを追加します。

INSERT INTO テーブル名 VALUES(カラムに対応する値、カラムに対応する値・・・);

下記の（）の中の値は、上記「テーブルを作る」で作ったshohinテーブルのカラム（shohin_id, shohin_mei, shohin_bunrui, hanbai_tanka, shiire_tanka, tourokubi)にそれぞれ対応します。順番はカラム通りに追加されるので、このように全てのカラムに値を入れる際、特に順番やカラム名を指定する必要はありません。

```sql
INSERT INTO Shohin VALUES('0001', 'Tシャツ', '衣服', 
1000, 500, '2009-09-20');
```
 

もし、一部のみデータを登録したい場合は、下記のように、どのカラムにどういう値を入れたいという指定をすることができます。逆に、これが基本です。もちろん、全部登録したい時にもカラム名も全部書いても同じですが、上記コードのように省略もできます。一部だけの時はちゃんと指定しないとどのカラムに入れたらいいのか分からないので登録できません。

```sql
INSERT INTO Shohin 
 (shohin_id, shohin_mei)
VALUES('0001', 'Tシャツ)
```
Project Euler 015を解いてみる。「格子経路」

# Project Euler 015
[015](http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%2015)
>
2×2 のマス目の左上からスタートした場合, 引き返しなしで右下にいくルートは 6 つある.
![p_15.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346690/9722c20a-24c4-1429-a120-7ec94a41269a.gif)
>では, 20×20 のマス目ではいくつのルートがあるか.

->[次の問題](https://qiita.com/radiol/items/1b51e533d61d3fd7be0a)

## 考え方
中学か高校の数学でやったことのある問題ですね。
どんなルートを通るにしても右に20回、下に20回の計40回の移動をすることは確定しているので、
`40個の動作の中から「下へ行く」をする20箇所を選ぶ組み合わせ問題`と考えられます。

```math
{}_{40} C_{20} = \frac{40!}{20!20!}
```

## コード
```Python:euler015.py
def main():
    """
    go downが20回、go rightが20回の計40回の動作がある。
    40個の動作の中からgo downをする20箇所を選ぶ組み合わせ問題と考えられる。
    40C20 = (40*39* ・・・ *22*21) / (20*19* ・・・ *3*2)
    :return:
    """
    n = 20
    ans = 1
    for i in range(n + 1, n * 2 + 1):
        ans *= i
    for i in range(2, n+1):
        ans //= i
    print(ans)


if __name__ == '__main__':
    from time import time as t
    start = t()
    main()
    print(t() - start, 'sec')

```
[paiza](https://paiza.io/projects/new)にて実行
`結果
137846528820
9.775161743164062e-06 sec
`
計算量も大したことはないので、とくにひねりもなくそのまま計算しました。
【UiPath】Directory.GetFilesでもっと細かい条件でファイル取得したい場合

UiPathで特定のフォルダ内のファイルを一括取得したいときに`System.IO.Directory.GetFiles("ファイル名")`という構文を使う人は多いのではないでしょうか！

しかし、特定のフォルダ内の特定の条件に当てはまるファイルだけとりたいんだー！！というときもあります。

今回はそれの対応策についてお話します。

# とりあえずよく使うあるあるのやり方たち

もしかしたらご存知の方も多いかもしれませんが、少々お付き合いください...！

## サブフォルダに入っているファイルも全部取得したいとき

普通に`System.IO.Directory.GetFiles("フォルダ名")`を使うと、サブフォルダのファイルは取得できません。指定したディレクトリ内のファイルしか取れません。

サブフォルダに入っているファイルも全部取得したいときは、このように使います。

```vb
System.IO.Directory.GetFiles("フォルダ名", "*", System.IO.SearchOption.AllDirectories)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238739/47a985bd-9e45-5c16-a7cd-6824ee00f05e.png)


## 特定の拡張子のファイルだけ取得したいとき

例えばExcelのファイルだけ取得したい場合は、`.xlsx`の拡張子のファイルだけ取得すればいいですよね！

というわけで、例えば`.xlsx`の拡張子のファイルだけ取得するには以下の構文が使えます。

もちろん、`.txt`でも`.doc`でも同じようにすればできます！

```vb
System.IO.Directory.GetFiles("フォルダ名", "*.xlsx")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238739/193306db-f0b9-977b-6754-7bb1fbbe87e8.png)


また、先ほどのサブフォルダも全部ファイル取得するコードと組み合わせて以下のようにすることもできます。

```vb

System.IO.Directory.GetFiles("フォルダ名", "*.xlsx", System.IO.SearchOption.AllDirectories)
```

# もっと柔軟に条件つけてファイル取得したい！！

そうですよね、特定の拡張子だけ取得したい場合や、サブフォルダも全てファイルを取得したい場合もあると思いますが、もっと柔軟に条件つけてファイルしたいときもありますよね。

例えば、"qiita"という文字が入っているファイルだけ取得したい場合は、`where`を使ってこのように表現できるんです

```vb

System.IO.Directory.GetFiles("フォルダ名").Where(function(file) file.Contains("qiita")).ToArray
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238739/37fd676b-a77b-4dc4-7aa3-5a107148f84e.png)

この`function(file)`の`file`には、直前の`System.IO.Directory.GetFiles("フォルダ名")`で取得したファイルが1つずつ格納されています。そして、`file.Contains("qiita")`で、ファイル名に`qiita`と入っているものだけを取得しています。


先程の「特定の拡張子のみ取得」「サブフォルダも含めて取得」と合わせることもできます。合わせるとこんな感じになります↓

```vb

System.IO.Directory.GetFiles("フォルダ名", "*.xlsx", System.IO.SearchOption.AllDirectories).Where(function(file) file.Contains("qiita")).ToArray
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238739/c59a4ef0-b635-4e21-06a9-26425e1d3a32.png)


# 終わりに

Directory.GetFilesでもっと細かい条件でファイルを取得できるようになれば、もう少し融通の利くファイル操作が出来そうですね！

ぜひ使ってみてください！
SQL　基本編

#第一回　基本編

SQLを勉強中なので、学んだ内容を何回かに分けてまとめていきます。

目次：
１、SQLを書くにあたって、自分なりに重要だと思ったこと

２、SQLの流れ（順番）

３、型

 

１、SQLを書くにあたって、自分なりに重要だと思ったこと

###・読みやすいように改行や、インデントをつける（所属する組織、チームのコーディング規約に従う）

 

###・テーブル名に別名をつける

　AS  T1やAS  T2など別名をつければ見た目もスッキリし見やすくなる。また書く手間も省ける

 

###・関数を全て覚える必要はない

関数は多く、またRDBMSによって使える、使えないがあり統一されていないので、今やりたい処理は何か整理し、リファレンスなどで都度調べればOK。もちろんよく使う関数は覚えておけば便利。

 

###・文が長くなる場合、処理ごとにパーツに切り出して考えると整理しやすい

例えば、サブクエリなど、別途その部分だけSQL文を書き取得したい情報がちゃんと取れるか確認してみるなど。

 

##２、SQLの流れ（順番）

###処理実行の順番

```sql
FROM
↓
JOIN
↓
WHERE
↓
GROUP BY
↓
SUM, AVGなど
↓
HAVING
↓
SELECT
↓
DISTINCT
↓
ORDER BY
↓
LIMIT
```
 

###記述の順番

```sql
SELECT
↓
FROM
↓
WHERE
↓
GROUP BY
↓
HAVING
↓
ORDER BY
```
 

##３、型

INTEGER  整数

DECIMAL　固定小数点数

FLOAT　浮動小数点数

CHAR　固定長文字列（文字数が最大長になるまで空きを半角スペースで埋める）

VARCHAR　可変長文字列

DATE　日付

DATETIME　日付・時間
など
railsを5.2.3から6.0,rubyを2.5.1から2.6.4にあげてみた

bundle installをしたら、下記のエラー

```
Bundler could not find compatible versions for gem "railties":
  In Gemfile:
    railties (>= 6.0.0)

    rails (~> 6.0.0) was resolved to 6.0.0, which depends on
      railties (= 6.0.0)
```
railtiesのバージョンアップが必要だったので、Gemfileに下記を追加。

```
gem 'railties', '>= 6.0.0
```

```
$ rails s
```
起動してみると、ワーニングがでた。

```
/Users/ユーザー名/.rbenv/versions/2.6.4/lib/ruby/2.6.0/fileutils/version.rb:4: warning: already initialized constant FileUtils::VERSION
```

```
$ gem uninstall fileutils
$ gem update --default
```

上記コマンドで解消。
リーダブルコード　要約

プログラマの間ではかなり有名で、一人一冊持っておくべきということも聞いた「リーダブルコード」。

１回目さらっと読んで、２回目に要点をまとめたので、自習用のメモをブログにまとめます。


#はじめに
コードは他の人（未来の自分）が最短時間で理解できるように書かなければならない。

行数は必ずしも短ければいいわけではなく、複雑な１行より分割されて整理された２行の方がいい。理解しやすいかがポイント。

#表面上の改善

##１、名前に情報を詰め込む

1-1 明確な単語を選ぶ

get   →　どこからget ?

size  →　何のsize ?

stop  →　取り消し可能？完全消去

いずれも意味が曖昧

代替案：

例：start → launch,   create,   begin,   open

 

###1-2 汎用的な名前を避ける

例：

retval（戻り値） →　sum_squares

こちらの方が具体的で分かりやすい。またバグも発見しやすい。

ただ、一時的な保管だけのためであれば、retvalでも十分。

 

###1-3 名前に情報を追加する

・変数＋単位（例：start_ms）

・危険や注意を喚起する情報など

 

###1-4 名前の長さを決める

名前は短い方が良いが、変数の使い方によって適切な長さは変わる。

・スコープが小さい　→　短い名前でもOK（全ての情報が見えているので）

・省略形はプロジェクト内など短な人にしか分からないものは避けるべき。新しいチームメイトが加わった際に、見て分からないため。

・不要な単語は捨てる　→　ConvertToString(  )　→　ToString(  ) これでもできることは一緒だから

 

###1-5 名前のフォーマットで情報を伝える

アンダースコアやダッシュ、大文字を使おう

 

##２、誤解されない名前

例：filter(  )

filter( "year" <= "2011")

→　選択するのか、除外するのか分からない

→　select(  ),  exclude(  )を使おう

  

例：length

max_length

→　バイト数？文字数？単語数？

→　max_charsとかにしよう

 

例：limit

→　以下か未満か分からない

→　限界値を明確にするにはmax_,  min_ を使おう

 

範囲の指定：firstとlast

first = 2,  last = 4　→　2~4

包含/排他的範囲：beginとend

begin = 2,  end = 4　→　2~3

 

・ブール値

read_password = true　→　これから読む？ OR すでに読んでいる？

→　need_passwordなどにする

ブール値の変数名は頭にis, has, can, shouldなどを使って分かりやすくしよう。

 

##３、書くべきでないコメント、書くべきコメント

書くべきでない：

・新しい情報を提供するわけでもなく、ただコードの意味を書いているだけ。

・曖昧な言葉を使っている

 

書くべき：

自分の考えを記録するもの

・〜だと〜％速かった、〜だと〜なので難しい、〜よりも〜の方がコストは高いようだ

　など　→　無意味なテストや無駄な確認処理などをしなくて済んだり、バグだと思われなくて済む。

・コードの欠陥にコメントをつける（〜を修正中　など）

・定数の値に対する背景

・全体像を要約するコメントや実例を書くと他人が見ても分かりやすい

 

#ループとロジックの単純化

##１、制御フローを読みやすくする

1-1条件式の並び順

左：調査対象の式（変化する）　右：比較対象の式（あまり変化しない）

if (length >= 10 )   　良い

if (10 <= length )   　あまり良くない

 

###1-2 if elseブロックの並び順

肯定系、単純、目立つものを先に書くべし

良い：
if ( a == b ) {

} else {

}

あまり良くない：
if ( a != b ) {

} else {

}

 

###1-3 三項演算子、do/whileループ、gotoなどを使うと読みにくくなることも。なるべく使わないようにする

 

##２、巨大な式を分割する

式を簡単に分割するには、式を表す変数を使えば良い。式を変数に代入しておくと何かと便利。また、ド・モルガンの法則を使ってロジックを操作しよう。


 

##３、変数と読みやすさ

変数を適当に使うと？

１、変数が多いと変数を追跡するのが難しくなる

　　→　コードが読みやすくならない変数を削除

２、変数のスコープが大きいとスコープを把握するのが難しくなる

　　→　変数のスコープを縮める＝グローバル変数を避ける

３、変数が頻繁に変更されると現在の値を把握するのが難しくなる

　　→　一度だけ書き込む変数を使う

 

コードの再構築

１、無関係の下位問題を抽出する

エンジニアリングとは、大きな問題を小さな問題に分割してそれぞれの解決策を組み立てること。

例：

高レベルな目標「与えられた地点から最も近い店舗を見つける」

下位問題「２つの地点（緯度経度）の球面距離を算出する」

→この処理だけで自己完結しているので、新しい関数として抽出する。

思考プロセス：

１、高レベルの目標は何か

２、各行を見て、高レベルの目標に直接的に効果があるのかOR無関係の下位問題を解決しているのか

３、それらが相当量あれば、それらを抽出して別の関数にする

 

・汎用コードをたくさん作っておけば、複数のプロジェクトで再利用できる

 

##２、１度に１つのことを

・コードは１つずつタスクを行うようにしなければならない。

コードが行なっているタスクを全て列挙する

→　タスクをできるだけ異なる関数に分割する。少なくとも異なる領域に分割する。
git push origin HEADを知らない人は時間を無駄にしています！

## はじめに

Gitでカレントブランチ（現在いるブランチ）をリモートの同名ブランチにプッシュする時、今まで次のコマンドを入力してきました。

```
$ git push origin 現在のカレントブランチ名
```
ブランチ名が長い時は、直接入力が面倒くさいし、間違えないように`git branch`でブランチ名を確認して、それをコピーして貼り付けるとかやっていたのですが、これは時間の無駄だったことに気づいたので記しておきます。

## 解決法
このコマンドで全て解決！

```
git push origin HEAD
```

Gitのコマンドを検索していると、よく`HEAD`というワードは目にしていたのですが、ややこしい処理になるのではないかと思い避けていました。
`HEAD`は、現在のブランチの先頭、つまりコミットの一番新しいものを指しており、 gitはそこからブランチ名を取得できるので、カレントブランチ名を入力することと同じになります。

##参考
```公式ドキュメント.
git push origin HEAD
A handy way to push the current branch to the same name on the remote.
 ```
 https://git-scm.com/docs/git-push
配列中の最大値のindexを複数取得する方法

#記事の概要
　配列が最大値を複数持つ場合にその全てのindexを取得する方法です。
　以下の配列を例に話を進めます。

~~~
a=[2,2,1]
~~~

この配列から最大値２を持つインデックス０、１を取得するのがゴールです。

#Array#indexメソッド
配列から条件に合うindexを取得するメソッドですが....

~~~
a.index(a.max)
=> 0
~~~

最初に引数に合致するindexしか取得できません。

#each_indexとselectを組み合わせる
結論から言うとこうするとできました。

~~~
a.each_index.select{|i|a[i]==a.max}
=> [0, 1]
~~~

each_indexは配列からindexだけ取り出して渡します。渡されたindexを元にselectメソッドで最大値に合う要素を探し出し取得します。

もっとスマートな方法がある場合は教えていただけると嬉しいです。
Neo4jでグラフアルゴリズム：深さ優先探索

## この記事について

Neo4jを使ったグラフアルゴリズムの実装を紹介してみようという計画[「グラフアルゴリズム入門 - javaとNeo4jで学ぶ -」](https://qiita.com/ggszk/items/4884f764936686d740e1)の一部です（どこまで続くか・・・）

サンプルコードは[こちら](https://github.com/ggszk/neo4j-extension-sample)においた。

## 深さ優先探索

グラフの探索と幅優先探索については、[こちら](https://qiita.com/ggszk/items/f50a0705e45764f13107#グラフの探索)。次に深さ優先探索のサンプルプログラムを示す。これは、Neo4jのプロシージャとして書かれている。プロシージャの作り方については、[この記事](https://qiita.com/ggszk/items/c15e6e346aef5e19f8ed)に解説した。入力としてはノードのidをもらい、出力には、到達したノードと、そのノードに至るパスを入れている。到達したノードは探索で訪れた順番ですべて出力される。パスを得る関数と出力のクラスについては幅優先探索の記事にある。

深さ優先探索には、スタックを使うとシンプルに書くことができる。下のプログラムは、幅優先探索でキューを使ったところをスタックに書き換えただけである。Javaのスタックは、ArrayDequeクラスを使えば良い。これはキューにもスタックにも使える双方向に出し入れできる配列である。

```java:深さ優先探索のサンプル
    // sample6_2: DFS
    @Procedure(value = "example.sample6_2")
    @Description("sample6_2: DFS")
    public Stream<Output> sample6_2( @Name("id") Long id )
    {
    	// start node
    	Node start_nd = db.getNodeById(id);
    	// map for keeping Node id and parent relationship
    	Map<Node, Relationship> parent = new HashMap<>();
		// to avoid coming back to start node
		parent.put(start_nd, null);
    	// array for checking whether the node was visited 
    	List<Node> visited = new ArrayList<>(); 
    	// queue
    	Deque<Node> queue = new ArrayDeque<>();
		// current node
		Node c_nd = start_nd;
		// list for result
		List<Output> o_l = new ArrayList<>();
		// end if queue is empty
		while(c_nd != null) {
			Iterable<Relationship> rels = c_nd.getRelationships();
			if(!(visited.contains(c_nd))) {
				for(Relationship rel: rels){
					// if not visited add next node
					Node n_nd = rel.getOtherNode(c_nd);
					if(!parent.containsKey(n_nd)) {
						queue.push(n_nd);
						parent.put(n_nd, rel);
					}
				}			
				visited.add(c_nd);
			}
	    	Output o = new Output();
	    	o.node = c_nd;
	    	// get path from start_nd to c_nd
	    	o.path = getPath(start_nd, c_nd, parent);
	    	o_l.add(o);
	    	// get next node from queue
	    	c_nd = queue.poll();
		}
    	return o_l.stream();
    }
```
幅優先探索のときと同じサンプルでこのプログラムを実行してみよう。以下のサンプルである。
<img width="741" alt="スクリーンショット 2019-09-14 21.16.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219248/70b9c0e2-b7e7-33d9-04bb-ab57f2da6118.png">
A（idが0）からスタートした実行結果は、
<img width="741" alt="スクリーンショット 2019-09-14 21.17.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219248/77d11852-accc-1901-5e2c-ee733b062d31.png">
となる。確かに深さ優先でノードが得られている。この結果を表すツリー（木）は、幅優先のときと同様に深さ優先探索木と呼ばれるものである（この表示を得るためには、Neo4j BrowserのオプションをOFFにする必要がある。説明は幅優先の記事を参照）。
JavaScript Objectの省略記法について

###オブジェクトを簡潔に書く

JavaScript(ECMAScript2015以降)のオブジェクトは値とキーが一致しているときは簡潔に書くことができます。

例えばreduxのaction creatorを書くときは以下のような書き方をします。

```JavaScript
let nextTodoId = 0;
export const addTodo = text => ({
  type: ADD_TODO,
  id: nextTodoId++,
  text
});
```

注目して欲しいのは最後のtextの部分なのですが、キーがありません。

上記はショートハンドを使わなければ以下のように書くことになります。

```JavaScript
let nextTodoId = 0;
export const addTodo = text => ({
  type: ADD_TODO,
  id: nextTodoId++,
  text: text
});
```

以上です。
【PowerApps Tip's】改行で文字列分割

「ブラウザーによって異なる可能性」ってのがいやらしい・・・。

# はじめに
アプリケーションを作成していると、文字列を指定した文字で分割したいタイミングが発生します。はい、そんな時には「Split関数」ですね。

[PowerApps の Split 関数
](https://docs.microsoft.com/ja-jp/powerapps/maker/canvas-apps/functions/function-split)

> Split 関数はテキスト文字列を部分文字列のテーブルに分割します。

例えば、”2019/09/14”という文字列を年、月、日の各々に分割したい場合などに利用します。

```
Split( "2019/09/14" , "/" )
```

結果は下記になります。

| Result |
|--------|
| 2019   |
| 09     |
| 14     |

# 改行でSplitしたい
業務アプリなどを考えている際に「改行コードで分割する」という必要に迫られる場合があります。プログラミング経験者は、おそらくピンときたことでしょう。そう、改行コードはOSなどの環境によって異なるんですよね。

[改行コード(Wikipedia)](https://ja.wikipedia.org/wiki/改行コード)


## 改行コードとブラウザー
嫌な予感がして調べてみたら、ブラウザーのVerによっても改行コードが異なるようです。例えば、Windowsは標準では「改行コード＝CRLF」のハズです。しかしながら、ブラウザーのVerによっては「改行コード＝LF」になるとのこと。メンドクサイですね・・・。

http://shimax.cocolog-nifty.com/search/2006/09/post_b296.html
https://blog.dreamarts.co.jp/creator/cr20160921/

古い記事ですが、可能性として「CRLF」と「LF」のパターンが存在する可能性を考慮したほうがよい、と結論づけました。

「CR」のみは古いMac OS でしょうし、無視しちゃって大丈夫でしょう。おそらくｗ

# PowerApps 改行コードでSplit
ブラウザーでも改行コードが異なる可能性があるのですが「CRのみ」は発生しない（またはサポートしない）と考えると「LF」で分割すれば良い、と判断できます。

## 改行で分割する関数

```
Split(Substitute([分割ターゲットの文字列],Char(13),""),Char(10))
```

Char(13) ＝ CR
Char(10) ＝ LF

です。

Substitute 関数で Char(13) ＝ CR を削除して、その後で Char(10) ＝ LF で Split 関数による分割をしています。これであれば、LFをターゲットに分割が可能です。

[PowerApps の Replace および Substitute 関数](https://docs.microsoft.com/ja-jp/powerapps/maker/canvas-apps/functions/function-replace-substitute)

## 動作イメージ

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr"><a href="https://twitter.com/hashtag/PowerApps?src=hash&amp;ref_src=twsrc%5Etfw">#PowerApps</a> 改行コード 分割 <a href="https://t.co/S6sMTbMwnx">pic.twitter.com/S6sMTbMwnx</a></p>&mdash; やま (@yamad365) <a href="https://twitter.com/yamad365/status/1172848725187682304?ref_src=twsrc%5Etfw">September 14, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

左側：TextInput コントロール、MultiLineモード
右側：ListBox コントロール、Itemsに下記を指定

``` ListBox.Items
Split(Substitute(TextInput.Text,Char(13),""),Char(10))
```

# まとめ
おそらく、上記の動作イメージのような簡単な表示で利用するケースは少ないと思います。改行コードで分割した結果をもとに、データソースを検索したり、1行ずつ更新したり、が発生するのではないでしょうか。

その場合、Split 関数の戻り値”テーブル”（といっても、1列なので、配列と思っても差し支えはないと思うけども・・・）をうまく活用することを考える必要があります。検索する場合、そこらへん意識したキーワードで実施されると幸せになれるかもしれません。

それでは、皆さま。素晴らしい Power Platform Life を！
Callbackから定期的に受け取る位置情報をKotlin Coroutines Flowを使って監視する方法

Callbackから定期的に受け取る位置情報を `Kotlin Coroutines Flow` を使って監視する方法です。

```build.gradle
dependencies {
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.1"
}

// AndroidStudio上のFlowの警告を抑止
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
    kotlinOptions {
        freeCompilerArgs = [
            '-Xuse-experimental=kotlinx.coroutines.ExperimentalCoroutinesApi',
            '-Xuse-experimental=kotlinx.coroutines.FlowPreview'
        ]
    }
}
```

位置情報の取得は `FusedLocationProviderClient` を使いました。
`FusedLocationProviderClient` の位置情報はCallback形式で返ってくるため、取得後に `Flow` に渡しています。

```LocationDatasource.kt
class LocationDatasource(private val fusedLocationProviderClient: FusedLocationProviderClient) {

    fun observeLocationUpdate(): Flow<Location> = callbackFlow {
        val request = LocationRequest().also {
            it.interval = 60000
            it.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
        }
        val callback = object : LocationCallback() {
            override fun onLocationResult(locationResult: LocationResult?) {
                super.onLocationResult(locationResult)
                val location = locationResult?.lastLocation ?: return
                offer(Location(lat = location.latitude, lng = location.longitude))
            }
        }
        fusedLocationProviderClient.requestLocationUpdates(request, callback, null)
        awaitClose {
            fusedLolationProviderClient.removeLocationUpdates(callback)
        }
    }
}
```
`callbackFlow` で全体を囲い、`requestLocationUpdates` で位置情報の取得を開始します。ここでは、1分毎に位置情報を取得しています。

利用側で、Corotuinesが破棄されると、 `awaitClose` が呼ばれるため、 `removeLocationUpdates` を呼ぶことで位置情報の取得が停止します。

続いて、利用側のコードです。


```HogeActionCreator.kt
fun startLocationUpdate() {
    launch(exceptionHandler) {
        val flow = locationRepository.observeLocationUpdate()
        flow.collect {
        	Timber.d("lat : ${it.lat}, lng : ${it.lng}")
        }
    }
}
```

`coroutineScope` の `launch` 内で `collect` を呼びます。

ここでは、LocationReopository というRepository経由で位置情報を取得する実装にしています。

```LocationReopository.kt
interface LocationRepository {
    fun observeLocationUpdate(): Flow<Location>
}
```

```LocationReopositoryImpl.kt
class LocationRepositoryImpl(
    private val locationDatasource: LocationDatasource
) : LocationRepository {

    override fun observeLocationUpdate(): Flow<Location> {
        return locationDatasource.observeLocationUpdate()
    }
}
```

```AppModule.kt
@Module
class AppModule {
    @Provides
    fun provideFusedLocationProviderClient(context: Context): FusedLocationProviderClient {
        return LocationServices.getFusedLocationProviderClient(context)
    }

    @Provides
    fun provideLocationDatasource(fusedLocationProviderClient: FusedLocationProviderClient): LocationDatasource {
        return LocationDatasource(fusedLocationProviderClient)
    }
}
```

以上です。
繰り返し呼ばれるCallbackを継続的に監視できるため、これから利用する機会が増えそうです。
`awaitClose` を使ってシンプルにCallbackを止める仕組みが備わっているのも嬉しいですね。
脱JQuery　理由

#脱JQueryの理由

## 標準仕様の浸透
- JQueryが登場した2006年ごろには、各ブラウザごとに実装しているJSの関数や、描き方が異なっており、各ブラウザごとに対応するのが難しかった。JQueryを使えば、一つのコードでまとめて動作させることができた。
- しかし、現在は標準仕様が浸透し、一つのコードですべてのブラウザ(ie11を除く)に対応させることができるため。

## 代替可能なネイティブメソッドの登場
- セレクタメソッドなどの登場でほとんどのJQueryのメソッドを賄えるようになった。

## ファイルサイズと速度 (理由 ×)
- ネットワークの高速化・圧縮とキャッシュ活用を適切に行えば、そこまで気にならないと思われる。
- これは理由としては弱い

## 他のJSフレームワークの登場
- Angular・React・Vue などの新しいフレームワークの登場も理由の一つである
RN（expo）でグラデーション。カード風エリアを作る。


##　やりたいこと

* カード風エリアを作りたい
* 背景をグラデーションにしたい
* クリッカブルにしたい

## 完成品

グラーデーションつけて、ちょっと影落として（難あり）、クリッカブルにする。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55188/7842e322-21bf-1c77-76d3-4a35279451f2.png" style="width:300px"/>


## 準備

グラデーションは標準では難しいらしいので専用のモジュールを利用します。
私はexpoを利用しているのですが、[そのまま使えるモジュール](https://github.com/expo/expo/tree/master/packages/expo-linear-gradient)があるようなので、それを利用してみます。



```bash
npm install --save expo-linear-gradient
```

## 実装

```js:App.js
import React from 'react';
import { View, Button, Text, TouchableHighlight } from 'react-native';
import { LinearGradient } from 'expo-linear-gradient';

export default class BlackFade extends React.Component {
    render() {
        return (
            <View style={{ flex: 1, alignItems: 'center', paddingTop: 60 }}>
                <TouchableHighlight
                    onPress={() => console.log("hoge")}
                    underlayColor="#fff"
                    activeOpacity={0.7}
                    style={{
                        shadowColor: "#000",
                        shadowOffset: { width: 1, height: 1 },
                        shadowRadius: 1,
                        shadowOpacity:0.3 //影は無くてもいいかな・・・
                    }}
                >
                    <LinearGradient
                        colors={['#393FFF', '#44A5FF']}
                        start={{ x: 0, y: 0 }}
                        end={{ x: 1, y: 1 }}
                        style={{
                            height: 200,
                            width: 320,
                            borderRadius: 10,
                        }}
                    >
                        <Text
                            style={{
                                color: "#fff",
                                position: "absolute",
                                top: 40,
                                left: 50,
                                fontSize: 20,
                            }}
                        >
                            1234-5678-9012-3456
                        </Text>
                    </LinearGradient>
                </TouchableHighlight>
            </View>
        );
    }
}
```
生産現場で役に立つかもしれない最適化手法3【表計算ソフトのソルバー】(工数の平準化)

[<--目次へ](https://qiita.com/ki073/items/508b3c20eb03078703dd)
## はじめに
表計算ソフトのソルバーを使った方法です。
やっていることは「生産現場で役に立つかもしれない最適化手法2」とほぼ同じですが、小さなロットに分割し複数の日に生産を分けられるようにしています。

## 最適化の条件
* 製品ごとに必要な工数が与えられており、日ごとの最大総工数以内になるように生産計画を立てたい。
* 各製品の生産はロットに分割できる
* 製品の製造できる期間は決まっているが、生産する順は任意


## ソルバーで
LibreOffice Calcのソルバーでやってみました。
EXCELでも同じようにできるはずです。
まず文字や数値を次のように書き込みます。
![t1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171895/8a61d2e8-58bc-3fca-5a14-3738e4bc1ab0.png)

セルG2に下図の式を入れ、下方向にG6までコピーします。ロット数の合計を計算しています。
![t2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171895/2bc8ffb5-61d5-2dca-e77a-20897a020adb.png)

セルD7に下図の式を入れ、右方向にF7までコピーします。工数の合計を計算しています。
![t3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171895/afa45f3f-aff3-33ed-bc79-a96884a56dcc.png)

G9に生産できない日に相当するセル(工数が0になる)の合計の計算式を入れます。
![t4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171895/623360f9-1985-f310-638e-f19b78f051dd.png)

ソルバーへの入力です。
![t5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171895/c5f8c7dc-2908-3124-05e2-401c6bc89bc4.png)

「変更させるセル」で変数領域のセルを指定します。ロット数が入りますので、
制約条件で、その領域のセルが整数でかつ0以上になるように制約します。

制約条件3行目はロット数の合計が一致するように
制約条件4行目で各日の工数の上限を超えないように制限しています。

どうも「ターゲットセル」を指定しないと動かないみたいなので、苦し紛れに入れています。
かなり遅くなっています。
できればG9は制約条件として=0にすればすっきにするのですが。
「ターゲットセル」を指定する必要がなければ、そのようにしてください。

これで実行すれば「変更させるセル」に数値（ロット数）が入ります。

## GLPKプログラム
GLPKで動くプログラムも載せていきます。
同じことができます。

```GLPK:manufacuring31.mod
# version 0.2
set WorkingDay; # 工場稼働日付を読み込む
set ProductName; # 製品名を読み込む
param manHourPerLot{ProductName}; # 1ロットの工数
param nLotByProduct{ProductName}; # 製品ごとのロット数
set ManufacturablePeriod  dimen 2; # 生産可能日を読み込む
param manHourByDay{WorkingDay} default 100; # 1日の標準的な工数上限

var assignLot{ManufacturablePeriod} integer, >=0 ; # 生産可能な日のロット数
# 各製品のロット数の合計を合わす
s.t. product1{p in ProductName}: sum{(d,p) in ManufacturablePeriod}assignLot[d,p]==nLotByProduct[p];
# 1日の総工数を超えない
s.t. limitWorkerHour{d in WorkingDay}: sum{(d,p) in ManufacturablePeriod}assignLot[d,p]*manHourPerLot[p]<=manHourByDay[d];

solve;

# 結果を出力
for{d in WorkingDay}{
    printf "%s   総工数 %10.2f\n", d, sum{(d,p) in ManufacturablePeriod}assignLot[d,p]*manHourPerLot[p];
    printf "  製品名　ロット数*ロット当たりの工数\n";
    printf{(d,p) in ManufacturablePeriod: assignLot[d,p]>0} "  %s   %d * %d\n", p, assignLot[d,p], manHourPerLot[p];
}

data;
# 工場稼働日付
set WorkingDay := 1 2 4;
# 製品名と1ロットの工数
param : ProductName : manHourPerLot:=
"製品1"   25
"製品2"   25
"製品3"   20
"製品4"   40
"製品5"   20
;
# 製品ごとのロット数
param : nLotByProduct:=
"製品1"  4
"製品2"  2
"製品3"  1
"製品4"  2
"製品5"  2
;
# 製品名と生産可能日
set ManufacturablePeriod :=
(*, "製品1") 1 2  # 製品1を1 2 日に限定
(*, "製品2") 2 4
(*, "製品3") 1 2
(*, "製品4") 2 4
(*, "製品5") 1 2 4
;
# 1日の工数上限を特別に変えたい場合
param manHourByDay[2] := 110;
end;
```
coeureさんを引用　３カラムの作り方

お恥ずかしながら一通り勉強した後に、３カラムが出来ないままであることを忘れておりまして、これから次に書いてあるプログラムを書いて、動作確認をしてみます。汗　恥ずかしい。

```HTML5:base-3column.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>はじめてのホームページ</title>

    <link rel="stylesheet" href="style.css">

  </head>
  <body>

    <div class="header">
      ここにはヘッダーが入ります
    </div>

    <div class="main">
    	<div class="main-contents">
        メインコンテンツ
      </div>
    	<div class="right-navi">
        右側のカラム
      </div>
      </div>
        <div class="left-navi">
        左側のカラム
      </div>

    <div class="footer">
      ここにはフッターメニューが入ります
    </div>

  </body>
</html>
```


```CSS3:3column.css
body{
  background-color: lightyellow;
}
.header {
  height: 150px;
  background-color: yellow;
}
.footer{
  height: 200px;
  background: black;
  color: #fff;
  clear: both;
}
.main-contents, .left-navi, .right-navi {
  height: 400px;
}
.main-contents {
  background-color: red;
  color: #fff;
  float: left;
  width: 80%;
}
.left-navi {
  background-color: blue;
  color: #fff;
  width: 20%;
  float: right;
}
.right-navi {
  background-color: green;
  color: #fff;
  float: right;
  width: 20%;
}
.main{
  width: 80%;
  float: right;
}
```

やっと出来た！
![Screenshot from 2019-09-14 21-29-48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442057/b1c35f41-a10c-67e6-e44c-c21bac7100f2.png)