OmniAICreator/Qiita-1.07M huggingface dataset:
IS_LEAP_YEAR 閏年チェック

Oracle18C

```
CREATE OR REPLACE FUNCTION IS_LEAP_YEAR
    (
    IN_YEAR IN DATE  -- 調査年
    )
    RETURN VARCHAR2 -- 'OK' : 閏年 or 'NG' : 閏年ではない
--
-- 閏年チェック
--
IS
    L_DATE  DATE ;
BEGIN
    -- 閏年か否かはその年の2月29日がTO_DATEで例外にならないかで判断できる。
    L_DATE := TO_DATE(TO_CHAR(IN_YEAR, 'YYYY') || '0229', 'YYYYMMDD') ;
    RETURN('OK') ;
EXCEPTION
    WHEN OTHERS THEN
        RETURN('NG') ;
END IS_LEAP_YEAR ;
/
```

```結果
SQL> COLUMN IS_LEAP_YEAR FORMAT A2
SQL> SELECT B.YEARS
  2       , IS_LEAP_YEAR(TO_DATE(TO_CHAR(B.YEARS, 'FM0000'), 'YYYY')) AS IS_LEAP_YEAR
  3  FROM(
  4      -- NUMBER FROM ～ TO
  5      SELECT A.YEAR_FROM + ROWNUM - 1 AS YEARS
  6           , A.YEAR_TO
  7      FROM(
  8          SELECT 1990 AS YEAR_FROM  -- 開始年
  9               , 2100 AS YEAR_TO    -- 最終年
 10          FROM DUAL
 11          ) A
 12      CONNECT BY LEVEL <= A.YEAR_TO - A.YEAR_FROM + 1  -- 階層問合せ
 13      ) B ;

        YEARS IS
------------- --
         1990 NG
         1991 NG
         1992 OK
         1993 NG
         1994 NG
         1995 NG
         1996 OK
         1997 NG
         1998 NG
         1999 NG
         2000 OK
         2001 NG
         2002 NG
         2003 NG
         2004 OK
         2005 NG
         2006 NG
         2007 NG
         2008 OK
         2009 NG
         2010 NG
         2011 NG
         2012 OK
         2013 NG
         2014 NG
         2015 NG
         2016 OK
         2017 NG
         2018 NG
         2019 NG
         2020 OK
         2021 NG
         2022 NG
         2023 NG
         2024 OK
         2025 NG
         2026 NG
         2027 NG
         2028 OK
         2029 NG
         2030 NG
         2031 NG
         2032 OK
         2033 NG
         2034 NG
         2035 NG
         2036 OK
         2037 NG
         2038 NG
         2039 NG
         2040 OK
         2041 NG
         2042 NG
         2043 NG
         2044 OK
         2045 NG
         2046 NG
         2047 NG
         2048 OK
         2049 NG
         2050 NG
         2051 NG
         2052 OK
         2053 NG
         2054 NG
         2055 NG
         2056 OK
         2057 NG
         2058 NG
         2059 NG
         2060 OK
         2061 NG
         2062 NG
         2063 NG
         2064 OK
         2065 NG
         2066 NG
         2067 NG
         2068 OK
         2069 NG
         2070 NG
         2071 NG
         2072 OK
         2073 NG
         2074 NG
         2075 NG
         2076 OK
         2077 NG
         2078 NG
         2079 NG
         2080 OK
         2081 NG
         2082 NG
         2083 NG
         2084 OK
         2085 NG
         2086 NG
         2087 NG
         2088 OK
         2089 NG
         2090 NG
         2091 NG
         2092 OK
         2093 NG
         2094 NG
         2095 NG
         2096 OK
         2097 NG
         2098 NG
         2099 NG
         2100 NG

111行が選択されました。

SQL> COLUMN IS_LEAP_YEAR CLEAR
SQL>
```
YouTubeの配信・動画のコメント(トップレベルコメントのみ)を取得するnode.jsのツールを作成

## 概要
- 気になる事があったので、配信のコメントを取得するツールを作成した。
- トップレベルコメントのみ(コメントへの返信は取得していない)
- APIキーは伏字。log4jsでログ出力しているので(いないとは思いますが)流用する場合は各々の出力方法に変換してください。

## 引数
- 動画ID(watch?v=XXXXXXXXXXXのXXXXXXXXXXX部分)

## 実行結果
以下を出力する。
- 投稿者表示名(items.snippet.topLevelComment.snippet.authorDisplayName)
- 投稿者チャンネルID(items.snippet.topLevelComment.snippet.authorChannelId.value)
- 表示メッセージ(items.snippet.topLevelComment.snippet.textDisplay)
- いいね数(items.snippet.topLevelComment.snippet.likeCount)
- 投稿日(items.snippet.topLevelComment.snippet.publishedAt)
- 詳細は[APIドキュメント](https://developers.google.com/youtube/v3/docs/commentThreads/list)を参照

## 備考
[YouTubeの利用規約](https://www.youtube.com/static?template=terms&hl=ja&gl=JP)としては、個人を特定する情報を収集・取得するのは駄目、とありますが、
APIで取得できる情報が規約的に駄目ならAPIを使っては駄目なのでは、という話になりかねないので
とりあえず取得できるものは見ていい(DBには保存しない)というスタンスで扱います。

## ソース
~~~ javascript
const ApiKey = "key=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
const UrlCommentThreads = "https://www.googleapis.com/youtube/v3/commentThreads?" + ApiKey + "&part=snippet&maxResults=100&videoId="

var logger  = require('../modules/logger');

var axios = require("axios");

let targetVideoId = getTargetVideoId(process.argv);
if ( targetVideoId == undefined || targetVideoId.length == 0 ) {
  logger.info("video comment require arg... video id.")
  return;
}

// call main
main(targetVideoId);

function getTargetVideoId(argv) {
  if ( argv.length <= 2 ) {
    return "";
  }
  return argv[2];
}

// main
async function main(videoId) {
  logger.info("video comment start");
  var itemArray = new Array();
  logger.info("get video comment, videoId[" + videoId + "]");
  await outVideoComment(itemArray, videoId, "");
  logger.info("video comment end");
};

// out video comment
async function outVideoComment(itemArray, videoId, pageToken) {
  var nextPageToken = "";
  var docs = undefined;
  let requestUrl = UrlCommentThreads + videoId + "&pageToken=" + pageToken;
  logger.debug(requestUrl)
  await axios.get(requestUrl)
        .then(function(res) {
          nextPageToken = res.data.nextPageToken;
          docs = res.data.items;
        })
        .catch(function(err) {
          docs = undefined;
          logger.error("axios error!");
          logger.error(err);
        });

  if ( docs != undefined && docs.length > 0 ) {
    for ( let key in docs ) {
      let topLevelCommentSnippet = docs[key].snippet.topLevelComment.snippet;
      let comment = {
        authorDisplayName: topLevelCommentSnippet.authorDisplayName,
        authorChannelId: topLevelCommentSnippet.authorChannelId.value,
        textDisplay: topLevelCommentSnippet.textDisplay,
        likeCount: topLevelCommentSnippet.likeCount,
        publishedAt: topLevelCommentSnippet.publishedAt
      }
      logger.info(comment);
    }
  } else {
    logger.debug("no docs");
  }
  if ( nextPageToken == undefined || nextPageToken == "" || nextPageToken.length == 0 ) {
    logger.debug("no next page");
    return;
  }
  await outVideoComment(itemArray, videoId, nextPageToken);
}
~~~
ITIL Foundationをいい感じに突破したのでまとめてみる

#最初に
![aaa.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219000/e376ae65-732f-ce2e-758c-acc03363dc9b.jpeg)

本情報は2020/11に受験していい感じに突破したときのお話です。
正解39/全40問
合格ラインは65%（26問）ですから、まぁ過剰といえば過剰

#ざっくりいうと
- 黄色本しかない
- 問題はping-tがいい
- 受かるだけなら難しくはない

#ネット情報ありがとう
とはいえPMPと違って少ない。
なんででしょう…というわけで事前情報がほとんどなかったので
まぁ雰囲気はPMPと同じかな？と思っていました。

#コロナ禍の試験
共用ロッカーに荷物をあずけるのかな…と思ったら、持ち込んで足元に置けと。
PMPのときみたいに休憩のときに食事とりだすなんてできないだろうな…

#さて試験
６０分で４０問。合格ラインは６５％（２６問）
PMPは２４０分で２００問。合格ラインは不明だけど７割ぐらいか？
というわけで、PMPよりはとっつきやすいと思う。

チュートリアルが終わるとすぐ試験。
終わると合否だけはすぐわかります。
詳細なレポートもほどなく届くでしょう。

#どう攻略するの？
もっとも聞きたいと思われる攻略である。

受かるだけなら講習を受ければ受かりやすいらしい。
確かにそのような気がする。

次の作戦は「問題に沢山こなす」
結果してitil foundationだと「知識」だけで正解が出せる。
そしてその「知識」は問題を沢山こなすとついてくる。
たぶんそれでも受かるとは思う。

私はPMPのときとほぼ同じで
itilライフサイクルが全部乗った表を手に入れ
そこに学んだことを書き足していく
という「白地図を埋めていく」スタイルでINPUTをした後、
[ping-t](https://mondai.ping-t.com/question_subjects/45)
で問題をひたすらといて、レベル４０（MAX）にした。

その結果の結晶が上記のパーセンテージである。
ちなみに最初の15分で全部回答し、その後３回見直して「もういいや」と最後は途中で「終了」した。

受かるだけなら問題をとけばいいのだと思うけど…
やっぱりINPUTすべきはしたほうがいいかな
と思う。
「サービスポートフォリオ管理」と「サービスカタログ管理」が曖昧なままでも合格はできると思われる。
でもせっかく受験するならちゃんとどっちがどのライフサイクルに属し、なぜ別れているのかまで理解できたほうがいいと思う。

問題は上記にも書いたが
[ping-t](https://mondai.ping-t.com/question_subjects/45)
がよい。一番本番に近い。
黄色本についている模擬試験はちっとも「模擬」してない。
○✗試験の組み合わせを回答する形になっているのだが、本番はping-tのスタイルである。

#その他
##本番の問題でも「…でないのはどれか」「すべて正しい」がある
PMPのときは「実際にはなかった！」のだが、itilのは本番でも「…ではないのは」とかいうのがありひっかけくさい。


#最後に
PMP同様白地図を埋めていくような勉強でもいいと思う。
ただ受かるだけでいいなら効率悪いと思うが、私はPMPのときと同様に白地図を埋めて、演習するスタイルで良かったと思う。
いろいろ見え方が変わったから。

以上でえーす
Rails 7つのアクション以外のアクション設定

#はじめに
Railsでオリジナルアプリを作成し、いよいよ大詰めとなりました。これまでindexアクションに登録データの一覧表示以外の記述をしていました。コードの役割を分離しようと考え、7つのアクション<sup>※</sup>以外のアクションを活用しましたので、記します。

※7つのアクション：index,show,edit,update,new,create,destroy

#目次
1.ルーティングへの記述
2.memberとcollection

#1.ルーティングへの記述
今回はsuggestionsコントローラーで設定する。定義するアクション名はfinishとcleanの2つ。finishはあるカラムの値を更新するアクションであり、updateと似ている。したがってHTTPメソッドはpatch(一部書き換え)となる。もう一つのcleanアクションはある条件を満たす情報を表示するアクションであり、indexと似ている。そのため、HTTPメソッドはgetとなる。

```ruby:config/routes.rb
resources :suggestions do
    member do
      patch 'finish'
    end
    collection do
      get 'clean'
    end
end
```

#2.memberとcollection

上記コードにおけるmemberとcollectionを説明する。これにより、生成されるルーティングのURLと実行されるコントローラーを任意にカスタムできる。違いはidが紐づくかどうかである。下記のようにターミナルからルーティングを確認た。memberで設定したアクションにはidが紐づき、collectionの場合はidが紐づかない。

```bash:ターミナル
finish_suggestion PATCH  /suggestions/:id/finish(.:format) -中略- suggestions#finish
clean_suggestions GET    /suggestions/clean(.:format) -中略- suggestions#clean
```

以上
SIer向けProxy環境下のもろもろ

# 想定環境
Windows 10
Proxy ＋ Basic認証

# Postman
| version |
|:-:|
| 7.36  |

Setting > Proxyから設定可能。

# Java
環境変数`JAVA_TOOL_OPTIONS`に以下をまとめて書くのが吉。
設定をローカル環境のみ限定できる。

```
-Dhttp.proxyHost=? -Dhttp.proxyPort=? -Dhttp.proxyUser=? -Dhttp.proxyPassword=? -Dhttps.proxyHost=? -Dhttps.proxyPort=? -Dhttps.proxyUser=? -Dhttps.proxyPassword=? -Djdk.http.auth.tunneling.diabledSchemes="" -Djdk.http.auth.proxying.diabledSchemes="" 
```
## Java認証プロキシ
[Java認証Proxy対応方法](https://qiita.com/SierSetup/items/f29e84f27273d1bea7f5)

# Maven
# Gradle
# Git
# npm
# Spring RestTemplate
# Spring WebClient
# ssh
# Teraterm
# a5m2


## 暇があったら追記していく。
Elixirで進捗表示したい！

# はじめに
- @kuroitu さんの[Pythonで進捗表示したい！](https://qiita.com/kuroitu/items/f18acf87269f4267e8c1)を拝見しまして、私は[Elixir](https://elixir-lang.org/)でやってみようとおもいます
- 上記記事中の[プログレスバーを作ってみる](https://qiita.com/kuroitu/items/f18acf87269f4267e8c1#%E3%83%97%E3%83%AD%E3%82%B0%E3%83%AC%E3%82%B9%E3%83%90%E3%83%BC%E3%82%92%E4%BD%9C%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%8B)をやってみます

# 0. 準備
- [Elixir](https://elixir-lang.org/)をインストールしましょう
- 手前味噌の記事ですが、[インストール](https://qiita.com/torifukukaiou/items/d04d0273749c41eb50af#0-%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)等ご参考にしてください

# ソースコードを書く
- 今回は`progress.exs`ファイルをそのへんにつくるだけにします

```elixir:progress.exs
f = fn
  n when is_integer(n) -> Process.sleep(n)
  s -> IO.write("\r[#{s}]")
end

1..50
|> Enum.map(&String.duplicate("#", &1))
|> Enum.intersperse(100)
|> Enum.each(&f.(&1))
```

- `f`に束縛した無名関数は引数が整数の時には[Process.sleep/1](https://hexdocs.pm/elixir/Process.html#sleep/1)を実行してスリープします
- 整数ではない場合には[IO.write/1](https://hexdocs.pm/elixir/IO.html#write/2)を呼び出して出力をしています
- 元の記事にありますように`\r`が出力する文字列の先頭にあることがポイントです
- `1..50`ではじまる行からは以下の関数や、Pipe operator [|>](https://hexdocs.pm/elixir/Kernel.html#%7C%3E/2)を使って気持ちよく書いています
    - [Enum.map/2](https://hexdocs.pm/elixir/Enum.html#map/2)
    - [String.duplicate/2](https://hexdocs.pm/elixir/String.html#duplicate/2)
    - [Enum.intersperse/2](https://hexdocs.pm/elixir/Enum.html#intersperse/2)
    - [Enum.each/2](https://hexdocs.pm/elixir/Enum.html#each/2)
- `Enum.intersperse(100)`を実行した時点で下記のようなリストができています

``` elixir
["#", 100, "##", 100, "###", 100, "####", 100, "#####", 100, "######", 100,
 "#######", 100, "########", 100, "#########", 100, "##########", 100,
 "###########", 100, "############", 100, "#############", 100,
 "##############", 100, "###############", 100, "################", 100,
 "#################", 100, "##################", 100, "###################",
 100, "####################", 100, "#####################", 100,
 "######################", 100, "#######################", 100,
 "########################", 100, "#########################", 100, ...]
```
- 文字列と`100`が交互に入っているリストになっています
 
```elixir:progress.exs
1..50
|> Enum.map(&String.duplicate("#", &1))
|> Enum.intersperse(100)
|> IO.inspect()
|> Enum.each(&f.(&1))
```

- ってな感じで途中がどうなっているのかを[IO.inspect/1](https://hexdocs.pm/elixir/IO.html#inspect/2)で出力して確認するのはよくやることです

# 実行する

```
$ elixir progress.exs
```

![output.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131808/9c58efdc-0104-ebdd-6465-1963f58f02d1.gif)

:tada::tada::tada:

# Wrapping Up :lgtm: :qiita-fabicon: :lgtm: 
- Enjoy [Elixir](https://elixir-lang.org/) !!! :fire: :rocket::rocket::rocket:
【firebase authentication】永続化された認証情報の参照にAuth.currentUserは使ってはいけない

## firebase.auth().currentUserとは
現在のユーザー認証情報を所持するプロパティです。

firebaseでは認証情報をクライアントに永続化が可能となっているので、永続化された認証情報が存在すれば
> 現在のユーザー認証情報

の対象となります。[公式ドキュメント](https://firebase.google.com/docs/reference/js/firebase.auth.Auth?hl=ja#currentuser)

リロードしようがブラウザ閉じようが認証状態は継続しているということですね、firebaseさまさまです。

## 本題

意気揚々Reactでこんなコードを書きます。

``` ts
firebase.initializeApp({....})

const App = () => {
    retutn <Router>
        <LoginPage />
        <HogePage />
        <HugaPage />
    <Router />
}

if (firebase.auth().currentUser !== null) {
    console.log("前の認証情報が残っているよ！")
} else {
    console.log("認証情報は残っていないよ！")
}

ReactDOM.render(<App />, document.getElementById("root"))
```

実行してみましょう、LoginPageで何かしら認証を行いリロード！
ですが表示されるのは

> 認証情報は残っていないよ！

無慈悲.....

調査するところ認証情報の永続化はデフォルトでsessionモードと言われるものとなっており、今回の意図通りの挙動をしてくれる様子です。[公式ドキュメント](https://firebase.google.com/docs/auth/web/auth-state-persistence?hl=ja)

もう少し調べると、認証し→リロード→HogePageを動かしている際にはcurrentUserが参照できる

ここから推測するにcurrentUserにデータが入ってくるのはfirebaseSDKのモジュールが生成されるタイミングではないようで少しラグがあるようのでは。。。。。？

ですがcurrentUserに入ってくるタイミングなんてものはもちろん検知できません。
そこでAuth.onAuthStateChangedを発見、signin,signoutが発生した際にコールバックを処理してくれるようです。
使えそうなので書き換えてみましょう。


``` ts

const getStoredFirebaseAuthenticatedUser = () => 
    new Promise<firebase.User | null>(
        (resolve, reject) => firebase.auth().onAuthStateChanged(resolve, reject)
    );
 
firebase.initializeApp({....})

const App = () => {
    return <Router>
        <LoginPage />
        <HogePage />
        <HugaPage />
    <Router />
}

getStoredFirebaseAuthenticatedUser().then(user => {
    if (firebase.auth().currentUser !== null) {
        console.log("前の認証情報が残っているよ！")
    } else {
        console.log("認証情報は残っていないよ！")
    }
})

ReactDOM.render(<App />, document.getElementById("root"))
```

同じく、LoginPageで何かしら認証を行いリロードしてみます。

少し待ち

> 前の認証情報が残っているよ！

勝利！

## まとめ

* 永続化された認証情報の参照でcurrentUserを使うとnullになるケースがある
* たぶんfirebaseSDKの初期化が終わってからcurrentUserに入るまでに時間がかかる
* 初期化終了の検知はできないからOnChangeAuthStateでフックしてあげようね

(ならcurrentUserの定義```() => Promsie```にしろよ........)

ということでした、ハマったので皆さんお気をつけください。
Python学習 基礎編　~文字列を出力(表示)するには？~


こちらではPython学習の備忘録と、Ruby、JavaScriptとの比較も含め記載していきたいと思います。
プログラミング初心者や他の言語にも興味、関心をお持ちの方の参考になれば幸いです。

###文字を出力(表示)するには？
####共通部分
文字列は、必ず半角の「''」シングルクォーテーション、または「""」ダブルクォーテーションのどちらかで囲む必要がある。
記述がない場合はエラーになるので注意！
###Python

```py:script.py

print('Hello World')
```


###Ruby

```ruby:index.rb
puts 'Hello World'
```
putsの後ろには「半角スペース」が必要。
###JavaScript


```javascript:script.js
console.log('Hello World');
```
文の最後は「；」セミコロンで終わりにする。
* * *
###Pythonにてクォーテーションの記述がなかった場合
```
SyntaxError: invalid syntax
```
「構文エラー：無効な構文」というエラーが発生します。

そして、 今後、記述が多くなると上記エラーが発生する確率も高くなるのでその際は下記をチェックしてみましょう。

- Pythonのコマンドや関数の名前を打ち間違えていないか？
- カッコを閉じ忘れていないか？
- 半角スペースのところが全角になっていないか？
- for文, if文, 関数などの「:」を書き忘れていないか？
- 「''」シングルクォーテーション、または「""」ダブルクォーテーションを忘れていないか？

* * *
####おわりに
私自身「Python」の学習を始めたばかりなので、これからよろしくお願い致します！
また間違いがあれば遠慮なくご指摘願います！！
* * *
参考記事
[SyntaxError: invalid syntaxとは何ですか？](https://blog.pyq.jp/entry/Python_kaiketsu_200310 )
Joget DXの始め方

# Joget DXの始め方

## はじめに

`macOS環境の記事ですが、Windows環境も同じ手順になります。環境依存の部分は読み替えてお試しください。`

### 目的

この記事を最後まで読むと、次のことができるようになります。

| No.  | 概要                   | 備考 |
| :--- | :--------------------- | :--- |
| 1    | Joget DXとは           |      |
| 2    | Joget DXのインストール |      |
| 3    | Joget DXの学び方       |      |

### 実行環境

| 環境           | Ver.     |
| :------------- | :------- |
| macOS Catalina | 10.15.6  |
| Docker         | 19.03.13 |

### 関連する記事

- [Joget](https://www.joget.org/)

## Joget DXとは

- オープンソース
- ローコード開発プラットフォーム
- クラウドやモバイルで動作するWEBアプリの構築が可能
- ワークフローの自動化が可能
- 既存アプリのテンプレートを使用して独自アプリの構築が可能
- JogetMarketplaceから新しいアプリやプラグインをダウンロードし拡張することが可能

## Joget DXのインストール

- [Get Started](https://www.joget.org/get-started/)
- [Joget on Docker](https://dev.joget.org/community/display/DX7/Joget+on+Docker)

### Dockerデータのクリア

```command.sh
docker stop $(docker ps -q)
docker rm $(docker ps -q -a)
docker rmi $(docker images -q) -f
```

### Community版(無料)のインストール

- [jogetworkflow/joget-community](https://hub.docker.com/r/jogetworkflow/joget-community)

#### Docker Pull Command

```command.sh
docker pull jogetworkflow/joget-community
```

#### Case1: Run Joget with Embedded MySQL

```command.sh
docker run -d -p 8080:8080 -v /var/lib/mysql --name joget jogetworkflow/joget-community
```

#### Case2: Run Joget with Linked MySQL and Container Mounted Volume

```command.sh
docker volume create jogetdata
docker run -d --name jogetdb -p 3306:3306 -e MYSQL_ROOT_PASSWORD=jwdb -e MYSQL_USER=joget -e MYSQL_PASSWORD=joget -e MYSQL_DATABASE=jwdb mysql:5.7
docker run -d --link jogetdb:jwdb --name joget -p 8080:8080 -e MYSQL_HOST=jwdb -e MYSQL_DATABASE=jwdb -e MYSQL_PORT=3306 -e MYSQL_USER=joget -e MYSQL_PASSWORD=joget --mount source=jogetdata,target=/opt/joget/wflow jogetworkflow/joget-community
```

### Joget DXの起動

- [http://localhost:8080/jw](http://localhost:8080/jw)

### Joget DXのログイン

1. Login > Username:, Password: 入力 > Submit

| Username: | Password: |
| :-------- | :-------- |
| admin     | admin     |

## Joget DXの学び方

### Joget Knowledge Base

- [Joget Knowledge Base](https://dev.joget.org/community/)

### Joget Academy

- [Joget Academy](https://academy.joget.org/lms/courses)
Windows10でも利用できるwebdavコンテナの作成

* 5mbの[jgeusebroek/webdav](https://hub.docker.com/r/jgeusebroek/webdav)
* 一番注目されている[bytemark/webdav](https://hub.docker.com/r/bytemark/webdav/) も気になる

## 参考

[Dockerで簡易WebDAVサーバを作る - Qiita](https://qiita.com/kxn4t/items/dd20bc65aff0ff9b0f2c)

[kxn4t/webdav-docker - Docker Hub](https://hub.docker.com/r/kxn4t/webdav-docker/)
[Dockerfile](https://hub.docker.com/r/kxn4t/webdav-docker/dockerfile)

* windows10 でwebdav接続をするにはhttpsである必要がある。
    * [レジストリ値を変更すればhttpでもいけます。](https://kb.seeck.jp/archives/16018)

## server.crt, server.key の生成

```sh
openssl req \
 -x509 -sha256 -nodes \
 -days 3650 \
 -newkey rsa:2048 \
 -subj /CN=localhost \
 -keyout server.key \
 -out server.crt
```

### Dockerfile

```Dockerfile:Dockerfile
FROM httpd:2.4
RUN sed -i \
        -e 's/^#\(Include .*httpd-dav.conf\)/\1/' \
        -e 's/^#\(LoadModule .*mod_auth_digest.so\)/\1/' \
        -e 's/^#\(LoadModule .*mod_dav.so\)/\1/' \
        -e 's/^#\(LoadModule .*mod_dav_fs.so\)/\1/' \
        -e 's/^#\(LoadModule .*mod_dav_lock.so\)/\1/' \
        conf/httpd.conf \
    && mkdir -m 700 /usr/local/apache2/var \
    && chown daemon. /usr/local/apache2/var/ \
    && mkdir -m 700 /usr/local/apache2/uploads \
    && chown daemon. /usr/local/apache2/uploads/ \
    && sed -i \
        -e 's/POST OPTIONS/POST OPTIONS LOCK/g' \
        -e 's/Require user admin/Require user admin/g' \
        conf/extra/httpd-dav.conf \
    && apt-get -y update \
    && apt-get -y install vim

RUN sed -i \
    -e 's/^#\(Include .*httpd-ssl.conf\)/\1/' \
    -e 's/^#\(LoadModule .*mod_ssl.so\)/\1/' \
    -e 's/^#\(LoadModule .*mod_socache_shmcb.so\)/\1/' \
    conf/httpd.conf

ADD ./user.passwd /usr/local/apache2/
EXPOSE 80
EXPOSE 443
CMD ["httpd-foreground"]
```

### 認証

user.passwdファイルを用意

* admin
* test1234

```go:user.passwd
admin:DAV-upload:ed5f558bff713caae6aa7e89c8c45259
```

### build

```sh:build.sh
docker build . -t tukiyo3/webdav
```

### run

```sh:run.sh
docker run --rm -it -d \
 --name=webdav \
 -p 443:443 \
 -v "$(pwd)/server.crt:/usr/local/apache2/conf/server.crt" \
 -v "$(pwd)/server.key:/usr/local/apache2/conf/server.key" \
 tukiyo3/webdav
```

### 動作確認

windowsのexplorerのアドレスバーに以下を入力

`https://localhost/uploads`

* id : pass
    * admin : test1234

`/usr/local/apache2/uploads/` にupされたことを確認。
create-react-app(typescript)が動かんくなった

突然create-react-app (typescript)で作成したプロジェクトが動作しなくなった模様
(この不具合は11/24に対応され、現在は問題は解消されている模様）
https://github.com/facebook/create-react-app/issues/10112

いつものようにプロジェクトを作成

```
npx create-react-app myapp --template typescript
```

作成したアプリを起動

```
cd myapp
yarn start
```

以下エラーが出る。なぜ？

```
/Users/hoge/react/myapp/node_modules/react-scripts/scripts/utils/verifyTypeScriptSetup.js:239
      appTsConfig.compilerOptions[option] = value;
                                          ^

TypeError: Cannot assign to read only property 'jsx' of object '#<Object>'
    at verifyTypeScriptSetup (/Users/hoge/react/myapp/node_modules/react-scripts/scripts/utils/verifyTypeScriptSetup.js:239:43)
    at Object.<anonymous> (/Users/hoge/react/myapp/node_modules/react-scripts/scripts/start.js:31:1)
    at Module._compile (internal/modules/cjs/loader.js:778:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
    at Module.load (internal/modules/cjs/loader.js:653:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
    at Function.Module._load (internal/modules/cjs/loader.js:585:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:831:12)
    at startup (internal/bootstrap/node.js:283:19)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:623:3)
error Command failed with exit code 1.
```


##解消方法

### package.json変更

typescriptを^4.0.3から~4.0.3に変更

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415206/520be385-f911-23bf-c98f-f6f0baa2ba6f.png)

### tsconfig.json変更

jsxをreact-jsxからreactに変更
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415206/b89b1a52-1fbf-6b92-ad82-ac50256c3c18.png)

あとは、yarn.lock削除してからyarn startを実行

とりあえず、これで解消しました。どうしたんだ一体。。。
RailsのDocker化 〜その2〜

## とりあえず、Railsアプリケーションを動かしてみる 
まずは、どういうところに環境依存があるのか、また何がめんどくさかったのか思い出すために、
Railsアプリケーションをcloneしてlocal環境で動かすところまでやってみましょう。

■sample project
`https://github.com/k-tetsuhiro/rails_docker_sample`

こちらは`ruby 2.7.2`と　`Rails 6.0.3.4` で作成されたsampleアプリです。
これを好きなところにgit cloneしてみてください。
これを `bundle exec rails s` で動かせるところまで持っていってみてください！
動かすまでに様々な問題点が出てくると思います。


## 出てくる問題点

まずはlocalのRubyのバージョンに2.7.2が入っているでしょうか？
rbenvを使用してる場合 `rbenv versions` で確認できます。

```
$ rbenv versions
  system
  2.3.8
  2.6.3
  2.6.5
  2.6.6
  2.7.0
  2.7.1
* 2.7.2 (set by /Users/kakuno/.rbenv/version)
```

どうでしょうか？
2.7.2が入ってない場合、まず**local環境にruby2.7.2のインストールが必要**になります。

**さっそく環境依存が出てきてしまいました！！**

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/174291/8a0a2ee2-c943-3800-8fdb-0da628098e1d.png" width=20%>

## この先も同じような環境依存が出てくる

起動するまでにlocalのこのような環境依存にこまるかと思います
・rubyのversion
・Railsのversion
・MySQLのversion
・yarnのversion
etc...


## その環境依存 dockerで解決しよう！

というわけでここで出てくるのがdockerです！
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/174291/024d7f0c-69f1-4c7e-58bf-74caafe448c4.png"  width=50%>


誰かが環境を整えたRailsアプリケーション
**それをimageとして保存しちゃおう！！**

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/174291/b534fec5-20fd-0258-a3b4-5866b72fa489.png" width=20%>



すべての環境(Ruby, Rails, MySQL, etc...)を込み込みでimageにしてしまえば、そもそも環境依存はおきないよね！
というイメージです！

更に利点として、local環境がMacだろうがWindowsだろうが、**実際にRubyやRailsが入っているのはdockerのimage**なので、どのマシンでも関係なく動きます！


## dockerで動かしてみる
dockerで動かすことにすごいメリットを感じますね！
では次回はどうしたら今のRailsアプリケーションをdockerで動かすことができるのか？
ここを説明していきます。
Djangoのget_object_or_404()とModel.objects.filter()の違い

get_object_or_404()は一つだけ。idかonetoonefieldsに便利。

```
chat = get_object_or_404(Chat, id=id)
```

Model.objects.filter()は複数ゲット

```
chat = Chat.objects.filter(user='papa')
```
初学者の為のプロキシってなに？

##プロキシって？


一言で言うと、代理になってくれるサーバーのこと


もう少し砕けて言うと、ホームページを見る時に使うWebブラウザの身代わりになってアクセスしてくれるサーバのこと。


なんとなく意味はわかったけど、それをする必要性が？な感じです。



##プロキシを深堀り
プロキシは「proxy」代理という意味。
代用のサーバを使うことで、セキュリティが上がるイメージ。
「プロキシサーバー」＝「代用のサーバー」と言う意味になる。



####プロキシを設置する目的は？
①セキュリティを確保。
悪意を持ったサーバー管理者からのパソコンへの攻撃を防ぐことが出来る。

②IPアドレスを隠す
Webサイトにアクセスすると、パソコンを識別する番号（IPアドレス）が足跡として残ります。プロキシを使用することでIPアドレスを匿名化したアクセスが可能になり悪意を持った相手に渡ることを防ぐ。

③フィルタリング
ユーザーがアクセス出来るWebサーバーを限定する機能。パソコンに入っている情報を守ることに繋がる。

④通信速度の高速化
プロキシサーバーには、過去にアクセスしたWebページのデータを保存されます。
そこから、素早く表示することが出来る。
使用するユーザーが多い時に、効果がありそうですね。

会社で、どのサイトを見たかわかるやつがこれですね。
あー、あの仕組みはこれかと納得！


###デメリット
・海外にサーバーがあると物理的に距離があるので、通信速度が落ちる。
・複数のユーザーが使用した場合は、読み込みまで数十秒かかることもある。
・通信負荷が強よくないサーバーは、ダウンしてしまう可能性もある。

プロキシサーバーは安定しないことが多い
代理という形を取っているため、通信が安定しないので注意が必要。


##どうやって設定？
Google chrome
https://www.waseda.jp/navi/network/doc/proxy_chrome.pdf
①画面右上のメニュー「設定」
②ウィンドウ下の「詳細設定を表示」
③ネットワーク「プロキシ設定の変更」
④「接続」
⑤「LANの設定」
⑥「LANプロキシサーバーを使用する」チェック
⑦プロキシサーバーのアドレス、ポート番号入力
⑧「OK」


プロキシアドレス
IPアドレスの代わりに足跡を残すプロキシサーバーを通した際のアドレス。
プロキシサーバのアドレスがこれ！

下記記事を参照
https://chewy.jp/businessmanner/5395/



##まとめ
自宅で使用するくらいであれば必要性はそこまでないが、外出先などで公共のネットワークを活用する時は、プロキシを使用したほうがいいですね。
form_withについての周辺知識

#はじめに
脱初心者にむけてアウトプットをしていこうと思って記事を書いております。
間違ったことがありましたら、ぜひコメントいただけると幸いです。

##form_withとは何か
form_withとはブラウザにデータのリソースの入力や
編集を行うフォームを生成するために使用される。
（Railsで何かしらに情報を送信したい時に使うメソッド）という理解で大丈夫だと思います。

```
<%= form_with(モデル or URLベース,[スコープ],[オプション]) do |f| %>
  フォームの内容
<% end %>
```


##form_forとform_tagについて
これらのヘルパーメソッドはRails5.1で導入されたform_withが導入されたことによって非推奨となりました。
（form_withはこれらの機能をまとめたもの）という理解で大丈夫です。
form_withを理解するためにはこれらのヘルパーメソッドを理解するにはこれらを知ることでさらに理解を深めることができます。

## form_for
```
<%= form_for(モデル,[オプション]) do |f| %>
    フォームの内容
<% end %>
```
form_forは入力されたデータをモデルなどに保存する時に使われていた

##form_tag
```
<%= form_tag(URL,[オプション]) do |f| %>
  フォームの内容
<% end %>
```
form_tagは入力されたデータを保存する必要がない時に使用されていた



##form_withはこれらの機能を併せ持ったヘルパーメソッドだと覚えておきましょう。
form_withには様々なオプションがあり、今まで、分けられていた機能がまとまったメソッドなので、少しわかりづらいこともありますが、なれるととても便利な機能(らしい)なので、どんどん使って慣れていこうと思います。
AWS cliでECRにpushするときに再認証を求められる＆loginが400 bad requestで弾かれる

# エラー内容

```
docker push ********.dkr.ecr.region.amazonaws.com/****:TAG
```
ECRにpushしようとすると


```
denied: Your authorization token has expired. Reauthenticate and try again.
```
トークンが期限切れと言われた。再度ログインします。

## ログインする
```
aws ecr get-login-password --region <region> | docker login --username AWS --password-stdin https://<id>.dkr.ecr.<region>.amazonaws.com
```
ちょっとハマってしまったポイントがあります。

- get-login-passwordには明示的にregionが必要
- get-login-passwordとdocker loginのregionが一致していなければいけない

さもないと400 bad requestが返ってきます。
【自己用メモ】（javascript）「.innerHTML」と「Math.floor()」について

例えば
addTaxDom.innerHTML = Math.floor(inputValue * 0.1);
この場合、
addTaxDomは、ブラウザ上の金額を表示する「場所」を示しているにすぎず、
あくまでそこに計算結果(inputValue * 0.1)が「表示」されているだけ。
addTaxDomに数値が「定義」されているわけではない！←:fast_parrot:

これをprofitDom.innerHTML = Math.floor(●●)で、●●を引き算の形にしたいのであれば、
const tax = Math.floor(inputValue * 0.1);で、計算式を一旦適当なconst○○に入れて、
消費税：addTaxDom.innerHTML = tax
儲け　：profitDom.innerHTML = Math.floor(inputValue - tax);
とする。
Rubyの代入感覚で考えていると、ミスしてしまう落とし穴だー:thinking:
Windows 10 でsshfsを使ってみた (billziss-gh/sshfs-win)

## 参考

* [SSHFS-Win が便利そうだった - ngyukiの日記](https://ngyuki.hatenablog.com/entry/2020/08/29/164525)

## インストール

[billziss-gh/winfsp](https://github.com/billziss-gh/winfsp/releases) と [billziss-gh/sshfs-win](https://github.com/billziss-gh/sshfs-win/releases)をインストールする。


### winfsp

![fa1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/873f488c-d235-b56b-4b88-a3c3a8279235.png)
![fa2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/eaa52017-c01a-51cc-2288-7c45d824c1f3.png)
![fa3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/c8e9cf74-8de7-046a-7b23-c71b584bf39a.png)
![fa4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/d2b7e0ff-a5d2-76ef-9a0b-316a3e02c0dd.png)
![fa5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/32b23f94-e3cf-39ed-75bd-0a44d5608c44.png)



### sshfs-win

![fs1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/549f6e54-86c6-c943-99b9-a22bc0957e51.png)
![fs2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/89471314-e604-db4d-a320-e934a163943e.png)
![fs3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/55322596-dd6c-3347-2b87-e028be5916b8.png)
「はい」
![fs4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/3a0a89a7-9a34-b0bb-a41e-8362abc99252.png)
完了
![fs5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/0c3774eb-8312-ae00-99ad-6bb2570e3c25.png)


## 利用

公開鍵認証は今のところ成功しませんでした。
パスワード認証の場合は確認できました。

```vb
net use X: \\sshfs\user@server
```

```vb
\\sshfs\[LOCUSER=]REMUSER@HOST[!PORT][\PATH]
\\sshfs.r\[LOCUSER=]REMUSER@HOST[!PORT][\PATH]
\\sshfs.k\[LOCUSER=]REMUSER@HOST[!PORT][\PATH]
\\sshfs.kr\[LOCUSER=]REMUSER@HOST[!PORT][\PATH]
```
JScriptでCSVファイルをSQLで検索してみた(64bit)

#はじめに
[OLE DB接続に利用できるプロバイダを調べる方法。 - Tihiroのストレスフリーな生活]
(https://tihiro.hatenablog.com/entry/2018/09/13/162238)
を参考にさせて頂きました。圧倒的感謝……！
CSVファイル用のOLE DBプロバイダが64bit版の環境を想定する。

#環境
- Windows 10 Home (64bit)

#手順
##OLE DBプロバイダの確認
テキストファイルを作り名前を`test.udl`としてダブルクリックする。
データ リンク プロパティの[プロバイダー]タブを選択し、一覧の中に
`Microsoft Office 16.0 Access Database Engine OLE DB Provider`
があることを確認する。

[Microsoft Access データベース エンジン 2016 再頒布可能コンポーネント]
(https://www.microsoft.com/ja-JP/download/details.aspx?id=54920)
で入手可能。

##ソースの用意

```ado_sample.js
{
	var cn = WScript.CreateObject("ADODB.Connection");
	var str = "Provider=Microsoft.ACE.OLEDB.16.0; ";
	str += "Data Source=.\; ";
	str += "Extended Properties='Text;HDR=Yes;FMT=Delimited'";
	cn.Open(str);

	var rs = cn.Execute("select name from [test.csv] where id=2");
	for ( ; !rs.Eof; rs.MoveNext()) {
		WScript.Echo(rs.Fields("name").Value);
	}
	rs.Close();

	cn.Close();
}
```

##データの用意

```test.csv
id,name
1,tako
2,ika
3,manbo
2,geso
```

##実行
コマンドプロンプトから以下のコマンドを実行する。
`cscript ado_sample.js`
[Power BI Tips] 折れ線グラフって色を条件によって変えられないんですけど、偶然変える方法を見つけました🥳

#今回は本当に裏技的 Tips です
いや、いつも書いてるのも Tips ではあるのですが、今回はついさっき（2020.11.20 18:30 頃）見つけた裏技的 Tips です

#今回説明に使ってるレポートはこちらで参照できます
東京都の新型コロナウイルスの感染者数に関するオープンデータをソースにした Power BI Report です。
レポートへのアクセス: https://bit.ly/PBI-Tokyo-Covid19
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152946/981b5d67-7bd0-8e97-7b4b-dab923de2bee.png)

このレポートの最初に表示されるページの左側の赤枠で囲った **[移動平均増加率推移]** というボタンをクリックすると、以下で説明している画面に遷移できます。

さて、ここからが本題です。

#Power BI の折れ線グラフは色が条件によって変えられない
**折れ線グラフ**、よく使いますよね。英語だと **Line Chart** っていいます。**棒グラフ**と双璧をなす BI のレポートではなくてはならないグラフのひとつです。

Power BI ではこんな感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152946/91cd90ce-c97e-0da0-5419-1534a7996e23.png)
上部にいるのが折れ線グラフ。で、右側の **[書式]** のところでいろいろとプロパティをいじることで、色やオプションを設定するのですが、**[データの色]** を見ると、ドロップダウンに色が表示されています。

これを例えば赤にすると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152946/d3a9a34c-0936-0289-7983-23ea5ab4d91b.png)
こんな風に折れ線の色を変更できます。

が、例えば
**「値が 100 以上になったら、赤にしたい」**
ということ、ありますよね

これ、標準だとできないんです。僕も **2020.11.20 18:30** 以前までそう思ってましたし、そう説明してきたこともあります。
でも、できましたwww

どうやってやるか？
説明するには、棒グラフの例をからお見せします。

#棒グラフはもともと条件によって色が変えられます (条件付き書式)
棒グラフで同じプロパティ **[データの色]** 見てみると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152946/b237875a-4c76-a8b1-e764-bb193678d596.png)
**[既定色]** の右に **[fx]** というボタンがあります。これは Function を表しており、つまりメジャーが指定できるのです。
**条件付き書式** の一種です。
なので、以下の様なメジャーを指定します。

```:DAX
Alert = 
SWITCH(
    TRUE(),
    [7日間移動平均 増加率 対前週比] <= 1, "#0F80E7",
    [7日間移動平均 増加率 対前週比] <= 1.5, "#FFB300",
    [7日間移動平均 増加率 対前週比] > 1.5, "#FF0006",
    "#9F00FF"
)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152946/2b1c5795-5983-5ddd-5a0e-9852016f52ba.png)
**[fx]** をクリックして、

- [書式設定基準]: フィールド値
- [フィールドに基づく]: (作成したメジャー）

を指定すると、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152946/8af7270a-e107-f7cb-7447-977cdf6772a1.png)
こんな風に条件に応じて指定した色が適用されます。

#さてここからが偶然見つけた方法🥳
はい、しつこいですが 2020 年 11 月 20 日 18:30 頃、この状態から折れ線グラフに変えたのです、ワタクシ。
ちなみに Power BI ではグラフの種類を選びなおすと瞬時にグラフを変えることが可能です。途中まで作成した棒グラフを選択した状態で、折れ線グラフのボタンを押すと、折れ線グラフになります。

つまりは偶然、これをやったのです、ワタクシ😇
そうするとどうなるのか？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152946/9d192324-4591-33dc-e81d-5fb91e0279e9.png)
そうすると...
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152946/1436fbf0-98d5-85e1-d30f-8b8f42391df0.png)

**こうなるわけです！！！！！！！！！！！！！！！！！！！！！！！！！！**
注目は **[データの色]** を見ると **[fx]** ボタンはないわけです。なぜなら **折れ線グラフ** では条件付き書式は設定できないからw

#まとめ
はい、ということで今回は以上です。
ね？本当に **裏技的Tips** だったでしょ？

なお、標準の機能じゃなくて、裏技的なので、いつ使えなくなるかはわかりません。そこだけは **ご注意** をお願いします。

最後まで読んでいただきありがとうございました。また気が向いたら、**Power BI Tips** シリーズを書きます。
皆様からのリクエスト、お待ちしております。

何かリクエストがあれば、以下までー🤗
Twitter: https://twitter.com/yugoes1021
Facebook: https://www.facebook.com/yugoes1021
LinkedIn: https://www.linkedin.com/in/yugoes1021/
jQueryを使ってクリックするとリンク先までスクロールするアニメーションの実装する

# はじめに
jQueryを使って、クリックするとリンク先までスクロールするアニメーションを実装していきます。

# 完成イメージ
後日添付



# 環境
MacOS 10.15.7
ruby 2.6.5
Ruby on Rails 6.0.0

# 前提条件
- jQueryが導入済みであること

#作業していきます。

##①html.erbの作成

```erb:application.html.erb
...上記一部省略...
<body>
  <header class="header">
    <div class="menus">
      <a href="#0", class="menuLink">Top</a>
      <a href="#1", class="menuLink">Category</a>
      <a href="#2", class="menuLink">Prefecture</a>
      <a href="#3", class="menuLink">New Posts</a>
    </div>
  </header>
</body>
```
hrefにそれぞれ「#0」「#1」「#2」「#3」と設定します。

```erb:○○○.html.erb
<div class='mainWrapper'>
  <div class='menu' id="0">
    <p class='headMessage'>
      menu1
    </p>
  </div>
  <div class='menu' id="1">
    <p class='headMessage'>
      menu2
    </p>
  </div>
  <div class='menu' id="2">
    <p class='headMessage'>
      menu3
    </p>
  </div>
  <div class='menu' id="3">
    <p class='headMessage'>
      menu4
    </p>
  </div>
</div>
```
menuごとにそれぞれidを付与します。

## ②jsファイルの作成

```javascript:○○○.js
$(function(){
  $('a[href^="#"]').click(function(){
    let speed = 500; /* 数値を変更することでスクロールスピードが変化 */
    let href= $(this).attr("href");
    let target = $(href == "#" || href == "" ? 'html' : href);
    let position = target.offset().top;
    $("html, body").animate({scrollTop:position}, speed, "swing");
    return false;
  });
});
```

`$('a[href^="#"]').click(function()`でhrefに「#」が付与されているもの全てをクリックするとスクロールイベントが発火するようにして、クリックされたmenuの場所にスクロールアニメーションが発動します。

これで完成です。
（CSSは適宜設定をしてください）

# 終わりに
ご覧いただきありがとうございました。
PL-900 PowerPlatform Fundamentalsについて

#PL-900 PowerPlatform Fundamentalsとは？
この試験の受験者は、Power Platform の機能を理解し、Power Automate で基本的なビジネス プロセスを自動化し、Power BI で基本的なデータ分析を実行し、シンプルな Power App を作成することでより効果的に行動し、Power Virtual Agents を使用して強力なチャット ボットを作成することで、生産性の向上を目指します。
引用元：試験 PL-900: Microsoft Power Platform Fundamentals 
#####まあ要は、PowerPlatformの入門試験ですよね!

#PL-900の試験範囲
Power Platform のビジネス価値について説明する (15-20%)
Power Platform のコア コンポーネントを特定する (15-20%)
Power BI の機能を実証する (15-20%)
Power App の機能について説明する (15-20%)
Power Automate の機能を実証する (15-20%)
Power Virtual Agents のビジネス価値を実証 (10-15%)
引用元：試験 PL-900: Microsoft Power Platform Fundamentals

#####受けた感じでは、PowerAppsの問題が圧倒的に多いように感じました。

#試験対策これだけはしておけ!
1,Microsoft Power Platform の基本
これで、Power Platformの全体像を掴みます。
https://docs.microsoft.com/ja-jp/learn/paths/power-plat-fundamentals/

2,ハンズオンの実施(PowerApps,Power Automate)
第1回〜13回まであります。
https://www.youtube.com/watch?v=VtshHNXUn6c&list=PL1RqQ3kddIpa0plPbFZ2ExF-hCnazx-Rd

3，Power BI
Udemyの教材でお金が掛かりますが、仕事で役立てるならやるべきです。資格だけで良い人はしなくても大丈夫だと思います。
https://www.udemy.com/course/masukawa_015/

4,Power Virtual Agents 
decode2020の動画です。
https://www.youtube.com/watch?v=Wu5UlOzXAMo&list=PL1RqQ3kddIpYHMWVlenT3cf_w5Pr3oYke&index=34

5,その他オススメコンテンツ
Power BI Udemy
https://www.udemy.com/user/shigeru2/

PowerBi記事(清水 優吾さんの記事)
https://qiita.com/yugoes1021

およそ資格は、10~20時間ほどで取得できると思います。基本１・2だけで取得できると思いますが、せっかくなら知識の幅を増やしましょう。

#最後に
入門試験で、日本語対応しているので受ける敷居は低いと思います。PowerPlatformは面白いので、少しでも気になる人は受けてみるべきだと思います。

![7485A969-4B0D-460D-BC8F-E108590EBDA8.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629294/f54f65f8-f9af-0f5a-95ba-0b433af97292.jpeg)
ct.jsでキー入力の判定を時間軸で解説。

ボタンが押された瞬間なのか、押され続けているのか、離された瞬間なのかを判定したい。

# どんな時に必要か？

毎フレーム、キャラクターの座標を加減算するとゲームによっては違和感のある移動になることがある。
例えばマス目を利用した移動を行いたいとき。
隣のマスに移動したい場合、「1マス移動（座標の加減算）する」という処理が毎フレーム実行されると、
**1フレームだけキーを押さなくてはならない。30fpsであれば、1フレームは0.03秒である**
そんな神業をユーザーに求めるわけにはいかないのでそういう場合に**押された瞬間**の判定が欲しい。

# ct.jsならばメソッドが用意されている。

press,down,releaseが用意されている。
それぞれがtrueを返す場合を下記にまとめてみた。

![無題の図形描画.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482410/1e6bdb4a-5ba5-0881-c957-e1c38693112e.jpeg)

これを認識してif分岐することで自分の望む移動を実装しよう。

# あとがき

ct.jsってタグがないことに今気づいた。
今後紹介記事も簡単に書ければと考えている。
ハンドトラッキングとは


今回はハンドトラッキングについて、説明します。
# ハンドトラッキングとは
ハンドトラッキングとは、
VR空間でコントローラーを使わずに、素手で操作できるようにする機能を指します。

一般的にOculus Questを操作するには、
コントローラーを使用しないといけないですが、
コントローラーを使せず、VR空間で自然に自分の手を使うことができます。

Oculus Questは2020年春頃のアップデートで、
ハンドトラッキング機能が実装されました。
新しい技術なので、まだ発展途中です。
# 設定方法
![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541380/ad209be2-f3d2-9b87-bd86-0aac20a8386c.jpeg)
まず、ハンドトラッキング機能を使用する為、
Oculusのバージョンは（Ver12）にアップデートする必要があります。

現在のバージョンは「設定」→「情報」から確認することができます。

アップする必要あれば、Wi-Fiに接続されて、
本体の充電が十分にある状態で放置（スリープ）すれば、されます。

![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541380/c2258544-a671-3a0b-b5bc-d803b1b49faf.jpeg)
バージョン問題なかったら、
「設定」→「テスト機能」で、ハンドトラッキングの起動ボタンをONにします。

ちなみに「手またはコントローラーを自動で有効にする」をONにすると、
ハンドトラッキングの切り替えを自動になります。

自動選択してない場合は、
下のメニューにある「設定」から、「手を使用」と「コントローラーを使用」をクリックすれば、
ハンドトラッキングとコントローラーの切り替えができます。
# 現状
新しい技術なので、まだ未熟です。

現在にある（私が知る限り）ハンドトラッキング使用可のゲームは、
ゲーム性はまだ弱く、ハンドトラッキング体験出来る、ぐらいの感じでした。

物を触る、掴む、何を書くなどの基本操作ができますが、
精度がそこまで高くないので、うまく操作できない可能性が低くないです。

面白い機能ですが、
まだまだ発展する必要があるという事ですね。
【Java】Javaで作れるもの

#プログラミング勉強日記
2020年11月20日
最近はずっとJavaを勉強しているが、Javaで作れるものを調べてみた。

#Javaの特徴

- プラットフォームに依存しない
- 開発効率と保守性が高い
- ライブラリが充実している

　Javaは動く環境を気にしない言語で、Javaでコードを書けばJVM（Java Virtual Machine：Java仮想マシン）が入っていればWindowsでもLinuxでもMac上でも動く。また、動作が早く、動作速度が要求されるような場合でも用いられる。

#Javaで作れるもの
　Javaは「なんでもできる」言語であり、TwitterやEvemoteといったWebサービスはもちろん、三菱UFJ銀行でも採用されるような大規模金融システム、Androidアプリといった幅広くいろいろなものを作れる。具体的に紹介する。

##1. Webサービス
　Javaはインターネットと相性が良く、私たちの想像できるWebサービスは大体Javaを使えば作れる。TwitterはJavaを利用している。(以前はRubyを使っていたが、動作が早いということでJavaに変えた)

##2. Webサイト
　Webサービスと意味合い的には変わらない。いろいろなWebサイトのデザイン的な面ではなく裏側もJavaで作ることができる。ECサイトや旅行予約サイト、掲示板、SNSといったなんでも作ることができる。楽天の裏側もJavaが使われている。

##3. デスクトップアプリ
　PCをインストールして動かすソフトウェアでもJavaが使われているOpenOfficeはJavaで作られているオープンソースソフトで、Eclipseも開発環境はJavaで作られている。
　Javaで作られているゲームあり、MINECRAFTもJavaで作られている。

##4. 組込みシステム
　Javaは組込み系のために開発されたプログラムで、色々なマシンに使われている。ガラケーもJavaで動いていた。

##5. Androidアプリ
　AndroidアプリのほとんどはJavaで書かれている。

##6. 商用システム
　銀行のシステムといった商用システムはJavaで書かれている。みずほ銀行のシステム案件はJavaが多く用いられている。






#参考文献
[【初心者向け】これもJava？ Javaで作れるものまとめてみた](https://eng-entrance.com/java_product_summary)
[Java入門からアプリ開発まで未経験者が知っておくべき基礎を総ざらい](https://www.sejuku.net/blog/curriculums-java)
【Swift】セルの間に余白を入れたい ＆ 複数の画像の位置を条件によって調整したい

# 画面構成
**正面図**
![スクリーンショット 2020-11-20 19.28.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502701/c98a2a6b-e6f6-ba61-568e-d1f35dbdd7f0.png)
**立体図**
![スクリーンショット 2020-11-20 17.13.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502701/e6c913ae-8a6a-d64e-cdae-fb5c93853367.png)


# セルの構成
## 背景のUIView
- **UIView①**を背景と見立てて、上下左右に**AutoLayout**をつける
- これにより、セルとセルの間に余白ができる
- また、*UIView.layout.cornerRadius*を調整することで角丸にできる

## UIViewの中のUIView
- 複数の画像の位置を調整するときは、UIViewのなかに入れ込むのが良い（図ではUIView②のなかにUIView③を入れている）
- この構造を親子関係と言う（図では②が親、③が子）
- UIViewの位置をコードで調整するときは、*UIView.frame = CGRect(x: 8, y: 8, width: 45, height: 45)*などで調整できる
- **CGRect**はUIViewの位置をを調整できる
- この関数はAutoLayoutよりも優先されるので、storyboardで設定した制約を上書きしてしまうため、扱いには注意が必要
- パラメーターはx, y, width, height
- 例えばこの記事では、ラベルに代入される値に応じて、赤黄青のViewの位置を変えている
![スクリーンショット 2020-11-20 19.28.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502701/c98a2a6b-e6f6-ba61-568e-d1f35dbdd7f0.png)


### なぜUIViewのなかにいれる？
- UIViewのなかに入れることで、バラバラなViewを**１つのグループ**としてまとめることができる
- 親子関係になったパーツは位置の基準が親のViewの位置になる
- storyboardから、そのパーツの位置は数字で確認できる
![スクリーンショット 2020-11-20 19.11.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502701/6eb85599-064b-f983-95b4-1d876d969a7c.png)

## セルの更新について
- 画面が読み込まれたタイミング（viewDidload）では、セルの中身はstoryboardによって決められているので、このままではコードによってセルの内容を制御できない
- これを解消するためには、viewDidAppearと言う関数を用いて、tableの内容をreloadする

```swift:hoge.swift
override func viewDidAppear(_ animated: Bool) {
    table.reloadData()
}
```
- viewDidAppearは、全ての画面のレイアウトの処理が正常に終わった後、呼ばれる関数
- viewDidloadとかviewDidAppearは書けば自動的に呼んでくれるが、呼ばれる順番は決まっているので、詳しくは[UIViewControllerのライフサイクル](https://qiita.com/motokiee/items/0ca628b4cc74c8c5599d)を参照
- *reloadData()*はUITableViewの関数
- セルの内容を更新し、表示する内容を変更したいときはこの関数を呼ぶとUITableViewをリロードして、値を更新してくれる

# 改めて完成図
![スクリーンショット 2020-11-20 19.28.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502701/c98a2a6b-e6f6-ba61-568e-d1f35dbdd7f0.png)
Laravel の FormRequest を全体的に、実態に近く自動テストする

## はじめに

Laravel の FormRequest のテストの話は rules() のテストだけなのが多いので、rules() 以外も含む FormRequest 全体を、より実態に近くテストする話をする


## テスト

以降は次を use する前提

```php
use App\Http\Requests\HogeRequest;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
```

全体なので FormRequest の passedValidation() や failedValidation() の実装の影響を受ける
以降はこれらがデフォルトの実装の前提。上書くときはその処理に従う。

### 成功することをテストする

FormRequest がサービスコンテナによる解決によって効果を得ることをテストする

```php
public function testPass()
{
    $attributes = ['key' => 'value'];
    // FormRequest が依存する Request に入力値をセット
    $this->app->make(Request::class)->replace($attributes);
    // Controller で DI するのと同じ効果を得る
    $request = $this->app->make(HogeRequest::class);
    // risky になるので assert
    $this->assertInstanceOf(HogeRequest::class, $request);
}
```

### 失敗することをテストする

```php
public function testFail()
{
    $attributes = ['key' => null];
    // FormRequest が依存する Request に入力値をセット
    $this->app->make(Request::class)->replace($attributes);
    // Controller で DI すると例外が投げられるのと同じ効果を得る
    $this->expectException(ValidationException::class);
    $this->app->make(HogeRequest::class);
}
```


## おわりに

サービスコンテナによる解決によって、rules() 以外も含む FormRequest 全体を、より実態に近くテストできる
MacOS(Catalina)でHeimdallを使いたい

そのままだとcatalinaに対応していないので、パッチを当ててビルドします。

libusb,qt5,cmakeが必要なので、インストールしていない場合はbrewでインストールします。

```
brew install libusb
brew install qt5
brew install cmake
```

#ビルドとインストール

```bash
git clone https://gitlab.com/BenjaminDobell/Heimdall.git
cd Heimdall
wget https://gitlab.com/BenjaminDobell/Heimdall/-/merge_requests/468.diff
git apply 468.diff
mkdir build
cd build
cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DQt5Widgets_DIR=/usr/local/opt/qt5/lib/cmake/Qt5Widgets ..
make
sudo cp bin/heimdall /usr/local/bin
```

#参考
https://gitlab.com/BenjaminDobell/Heimdall/-/issues/513
Swift の割り算の順序に気をつけろ 〜なぜそうなった〜

<b>追記：@En3_HClさんからコメントをいただきました。元は色々な変数が入れ子になったコードの除算順序がおかしくなっていて、すでにそのコードが残っていないので分からないのですがもしかしたら普通に自分のミスだったかもしれません。すみません！</b>

こんにちは、@Zhalen です。

さっき、今作ってるアプリの中で

```swift:超簡略
a / b * c
```

という計算をしました。しかし、表示されるのは

```swift
a/(bc)
```

という結果のみ...



#はて？

私は、

```swift

ac/b
```

という結果を望んでいました。そうです。だってやっていることは

```math

a / b * c
```

という操作。これはつまり、特別な記述がない限り

```math

\frac{a}{b} * c
```

に他なりません。もし、上の例で、上の結果を出力するのならば本来は

```swift
a / (b * c)
```
と記述した時でなければならないはずです。

#解決法

```swift
(a / b) * c
```

もしくは

```swift
a * c / b
```

と書きましょう。

#結論：郷に入れば郷に従え
AtCoder 茶色(400)になるまでにやったこと

こんにちは、yukad2です。
この記事では私がAtCoderでRating:400になるまでに勉強したことをまとめています。

# 0.初めてのコンテスト前
中学生の頃にC++ゲームプログラミングに挑戦しましたが、if, forが理解できる程度の知識でした。
大学1年で学習したRubyが(Cと比べて)非常に書きやすかったので、プログラミングの練習も兼ねて競技プログラミングを始めました。
1. [chokudaiさんの記事](http://chokudai.hatenablog.com/entry/2019/02/11/155904)を読んで、就活まで(2年以内)に緑～水色を目標にしました。
2. コードテストで入出力の確認をしました。
3. 過去問を何度か解きました。

# 1. コンテスト
<dl>
  <dt>1回目</dt>
  <dd>3完 Perf:681</dd>
  <dt>2回目</dt>
  <dd>2完 Perf:244</dd>
  <dt>3回目</dt>
  <dd>2完 Perf:196</dd>
</dl>

全然できない、と焦りを感じて過去問でアルゴリズムとデータ構造の基礎を勉強しました。

# 2. 勉強したこと

## for 2重 3重
```rb
h = 3; w = 3;
arr=[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
h.times{|i|
    w.times{|j|
        puts arr[i][j]
    }
}
```
勉強したわけはないですが、必須なので。Rubyなので`Array#each`の方をよく使っていました。
## bit全探索
Rubyでは`Array#combination`を使って実装しました。ベンチマークは取っていませんがABCの300点相当だとそこまで時間がキツイ問題は無いと思うので...

```rb
n = 5
arr=[1, 2, 3, 4, 5]
(n+1).times{|i|
     arr.combination(i){|item|
        p item
    }
}

```

## 最大公約数(GCD)

```rb
a = 3
b = 6
p 3.gcd(6)
```
最大公約数を求めるメソッドが標準にあります。(2020/11/21 追記)

## 約数列挙

```rb
n = 30
ans = []
(1..Math.sqrt(n).to_i).each{|i|
    if n % i == 0
        ans << i
        ans << n / i
    end
}
p ans.uniq.sort
```
$O(log(n))$
上記のコードは$\\sqrt n$が整数の場合は$\\sqrt n$が重複するので注意が必要です。（`uniq`で重複を消して出力）

## Hash(連想配列)
```rb
all = Hash.new
all["hoge"] = 1
all["huga"] = 3
p all
```
知らなかったので全く戦えなかった問題がありました。

## その他過去問
6問になってからのC問題を確実に解けるように練習しました。
過去問を解く際に、AtCoderProblemsを参考に上から順番に解いてました。
[AtCoder Problems](https://kenkoooo.com/atcoder/#/table/)

# 3. 結果
9回目のコンテストで茶色になりました。間のブランクは大学とバイトが忙しすぎてほとんど問題は解いていなかったです。
次は緑目指してガンバリマス！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499004/d7eb3a46-6f2b-410f-aea0-2d609c0f623a.png)
【Python】スクレイピングでデータを取得し、リストに入れる時の注意点

スクレイピングをするときの注意点
自分が沼にはまった時の対応です。

```test.py
for s in name:
  name_list=[]
  name_list.append(s.string)

```

このコードの問題点はname_listの位置です。
この位置だと毎回name_listの中身が更新されます。
つまりforで回しているが、結局nameの一番最後の要素しか
name_listにappendされません。

ということで、name_listの位置を変えましょう。

```test.py
name_list=[]
for s in name:
  name_list.append(s.string)
```
name_listをforの外に出すことで、nameの要素を順番に取得して、
appendするというコードになります。

特に私はまず1P、1要素スクレイピングできるか試してから、全体のスクレイピングを
行うので、そもそもテスト段階ではforをほとんど使いません。

その為、いざ全体のスクレイピングを行う際に空のリストの位置を間違えると
このようなことになります。
【JavaScript】数値範囲による分岐2

[【JavaScript】数値範囲による分岐](https://qiita.com/noenture/items/ea2bbb076c36f790559b)
過去に書いた記事のコードを少しスッキリ（？）させただけです。


#コード

```javascript

//Object.entriesだけでも動作はする
const generations = new Map(Object.entries({
	12: 'under 12',
	20: 'teenager',
	30: '20s',
	40: '30s',
	50: '40s',
	60: '50s',
	70: '60s',
	80: '70s',
	90: '80s',
	100: '90s',
}));

const getGeneration = age => {
	if (!Number.isFinite(age) || age < 0) return; 
	
	for (const [key, value] of generations) {
		if (age < key) return value;
	}
	
	return 'over 100';
};

console.log( getGeneration(-1) );		// undefined
console.log( getGeneration('14') );		// undefined
console.log( getGeneration(14) );		// 'teenager'
console.log( getGeneration(28) );		// '20s'
console.log( getGeneration(200) );		// 'over 100'

```
【javascript】配列をN個で分割（前方開始・後方開始）

[【JavaScript】自分なりのワンライナー（配列操作）](https://qiita.com/noenture/items/59b13069fc325b2ff18c)
過去に書いた上記記事で、配列の分割をワンライナーで載せましたが、そうじゃない書き方をしたかったので書きました。

それだけじゃつまらないので後方から分割するものも書いてみました。

**（追記）**ご指摘がありました、第2引数検査を追加しました。

#コード（前方から）

```javascript

const splitArray = (arr, n = 1) => {
	if (!Number.isFinite(n) || n < 1) return arr;		//追記
	
	const result = new Array();
	for (let i = 0, len = arr.length; i < len; i += n) {
		result.push( arr.slice(i, i + n) );
	}
	//n個未満の配列を除外したい時に追加
	//if (result.slice(-1)[0].length < n) result.pop();
	return result;
};

const array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

console.log ( splitArray(array, 3) );      //[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]
console.log ( splitArray(array, 4) );      //[[0, 1, 2, 3], [4, 5, 6, 7], [8, 9]]

```

#コード（後方から）

```javascript

const splitArrayBack = (arr, n = 1) => {
	if (!Number.isFinite(n) || n < 1) return arr;		//追記
	
	const result = new Array();
	for (let i = arr.length, len = i + n; i > 0; i -= n) {
		result.unshift( arr.slice(i - len, i) );
	}
	//n個未満の配列を除外したい時に追加
	//if (result[0].length < n) result.shift();
	return result;
};

const array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

console.log ( splitArrayBack(array, 3) );      //[[0], [1, 2, 3], [4, 5, 6], [7, 8, 9]]
console.log ( splitArrayBack(array, 4) );      //[[0, 1], [2, 3, 4, 5], [6, 7, 8, 9]]

```
Homebrewを複数ユーザーで使おうとすると、パーミッションエラー

すでにHomebrewをインストールして使っていたMacに新ユーザーを追加して、そちらでもHomebrewを使おうとしたら、パーミッションエラーが起こった。

せっかくなので、対処法とともに残します。

# 環境
* MacBook Pro (13-inch, 2020)
* macOS Catalina 10.15.7
* 新ユーザーは管理者として作成している

# 経緯
## `brew install`でパーミッションエラー発生
`brew install`でパッケージをインストールしようとしたところ、パーミッションエラーが出た。

エラーメッセージでは `sudo chown -R $(whoami) /usr/local/Cellar` を実行するようにアナウンスされる。

が、これだとオーナーを新ユーザーに変更するだけなので、現行ユーザー側で`brew install`などを実行しようとすると、きっと同じエラーが発生する。

### 現状のパーミッション
`/user/local`ディレクトリと、その配下の各ディレクトリの所有者は、下記の通り。

| ディレクトリ | パーミッション | ユーザー | グループ |
| :-- | :-- | :-- | :-- |
| /user/local | drwxr-xr-x | root | wheel |
| /user/local/配下 | drwxr-xr-x | 現行ユーザー | admin |
| /user/local/Cellar | drwxr-xr-x | 現行ユーザー | admin |
| /user/local/Homebrew | drwxr-xr-x | 現行ユーザー | admin |

# 対応

新ユーザーは管理者として作成しているので、adminグループに属している。しかし、`/user/local/`配下の各ディレクトリにはadminグループへの書き込み権限が無かった。

そこで、adminグループへの書き込み権限を与える。

```
$ sudo chmod -R g+w /user/local/*
```

これで、ひとまず`brew install`は完了できた。`brew doctor`の内容も、概ね問題なさそう。

### `/usr/local`自体への権限付与はできなかった
「Homebrew 複数ユーザー」などで検索すると、 `/usr/local` 自体のグループと書き込み権限を変更しようとする記事がいくつかあった。

```
$ sudo chgrp admin /usr/local
$ chmod -R g+w /usr/local
```

しかし、実行しようとするとエラーになってしまった。

```
~ $ sudo chgrp admin /usr/local
chgrp: /usr/local: Operation not permitted
```

Homebrewの再インストールでも解決できるようだが、すでにインストール済みのパッケージの再インストールも必要になるので、あまりやりたくなかった。

なので、この方法は見送った。

# 残る問題

## 都度、権限のメンテナンスが必要そう
どちらかのユーザーで新しいパッケージをインストールすると、`/user/local/Cellar/パッケージ`, `/user/local/Homebrew/配下`の権限がまた変わってしまうので、なにか書き込み必要なときには、再度上記コマンドの実行が必要そう。

## そもそもホームディレクトリにインストールしたい
本当は、各ユーザーのホームディレクトリにHomebrewをインストールしたい。以下の記事あたりが参考になりそう。

* [複数人で使用しているPCでのhomebrewの正しい使い方 - Qiita](https://qiita.com/rinchsan/items/de021e32fc3967741f67)
* [Homebrewを管理者エリアからアンインストールし、ユーザーのホームディレクトリにインストールする - GOOTA TECH](https://tech.gootablog.com/article/homebrew-userhomedir/)
* [homebrew ディレクトリを home ディレクトリ以下に移動したメモ - handlename's blog](http://handlename.hatenablog.jp/entry/2013/01/27/165104)
    * こちらの記事では、結局`/usr/local`に戻した、との追記あり