OmniAICreator/Qiita-1.07M huggingface dataset:
対象要素までヌルッと自動スクロールするメソッドの書き方！

#まえがき
無限番煎じですが、調べるのに地味に時間がかかったので、自分用を兼ねて残しておきます。

#コード

```js
scrollToTarget() {
    const element = document.getElementById("target-id")
    const rect = element.getBoundingClientRect()
    const currentScrolledHeight = window.pageYOffset || document.documentElement.scrollTop
    const position = window.innerHeight * 0.9
    window.scrollTo({top: rect.bottom + currentScrolledHeight - position, behavior: "smooth"})
}
```

このメソッドが実行された際の動きとしては
idが`target-id`である要素の下部が、ウインドウの上から90%のところに来るようにヌルッとスクロールします。

#理屈

- idが`target-id`である要素の相対座標とサイズを取得する(`rect`)
- すでにスクロールされている高さを取得(`currentScrolledHeight`)
- ウインドウサイズの上から90%の位置取得(`position`)
- `target-id`である要素の下部の**相対座標** + すでにスクロールされている高さ = `target-id`である要素の下部の**絶対座標**
- `window.scrollTo`は、指定座標がウインドウの一番上にくるようにスクロールするため、`position`を引いて位置調整する
- デフォルトだと、一瞬でスクロールするせいで画面がどの位置なのか混乱を招くので、`behavior: "smooth"`を指定することでスクロールアニメーションでヌルッとさせる

#あとがき
scrollToの引数のtopの部分をleftにしたら横スクロールになったり、`rect.bottom`を`rect.top`にすることでターゲットの上部座標を基準にできたりしますので、都度改造して使ってください！
Error: rzc generate exited with code 2

環境：
Visual Studio for Mac Community 8.1.3
.NET Core 2.2
ASP.NET MVC

突然以下のようなエラーになり、手詰まりになる。どこが悪いのかも教えてくれない。
/usr/local/share/dotnet/sdk/NuGetFallbackFolder/microsoft.aspnetcore.razor.design/2.2.0/build/netstandard2.0/Microsoft.AspNetCore.Razor.Design.CodeGeneration.targets(5,5): Error: rzc generate exited with code 2.

Razor View内でコメントを書いただけで上のエラーになる。

これは問題なし(No Problem)

```
@* a *@
```

更に二重にコメントアウト。これが気に入らないらしい。(Error!)

```
@*@* a *@*@
```

こちらで議論されているが解決に至っていない様子。SDKを再インストールだの・・・。
https://developercommunity.visualstudio.com/content/problem/403142/rzc-generate-exited-with-code-2.html

ちなみに、Windows版 Visual Studioはわかりやすいエラーになり、問題なし。
A space or line break was encountered after the "@" character.  Only valid identifiers, keywords, comments, "(" and "{" are valid at the start of a code block and they must occur immediately following "@" with no space in between.
DialogFlowとGoogleカレンダーを同期する方法について

ご覧いただきありがとうございます。

現在Dialogflowでチャットボットを作り、LINEと同期して秘書を作ろうと思っています。
そこで、Googleカレンダーの情報を読み取り、LINEで確認できるようにしたいのですが、具体的にどのような作業をしたらいいのか調べてもわからず止まっています。

もしわかる方がいたら教えていただきたいです！
よろしくお願いします！
[Scala]Await.resultからFutureに乗り換える

# 乗り換えた経緯と説明
とりあえずDBからデータ取ってくる処理を全部 Await.result でやってたのですが、様々な理由でFutureに乗り換えることにしました。
Await.resultがダメな理由としてはこちらの方の記事が参考になります。

[参考) Await.result は避けよう](https://qiita.com/hiroshi-cl/items/efde7af2b184dbd8cfb2)

ざっくり説明すると

* Await.result  : ずっと処理を待ち続けてスレッドが解放されない
* Future : 処理が終わったら処理を再開する。それまでスレッドは解放される

スクリプトの実行が終わるまでずっとPCの前で待ち続けている状態だと思うとイメージしやすいかなと。

##### Await.resultのイメージ
スクリプトが終わるまでずっと画面見て待ってる。
他の作業ができない

使用スレッド数は 2

1. スクリプト実行のプロセス
2. スクリプト返ってくるまでずっと画面見てる人物

<img src="https://4.bp.blogspot.com/-YiybfO2Q7eI/Vw5K0M1LVCI/AAAAAAAA5tc/IUsoF1brRIAoMNHvdsmkAeg4wnM49byDQCLcB/s800/pose_necchuu_computer_man.png" width="300px"> 

##### Futureのイメージ
スクリプト実行が終わってから処理をすればいいとわかってる。
他の事ができる。ラーメンも食べれる

使用スレッド数は 1

1. スクリプト実行のプロセスのみ

<img src="https://3.bp.blogspot.com/-Rs9jHGYI7C0/VY4W19JyVQI/AAAAAAAAuuU/fEBvUL9Flz8/s800/syokuji_computer.png" width="300px"> 

てなことで、ラーメンが食べれるFutureに乗り換えていきましょう。

## DBの取得処理をAwait.resultからFutureに変える

今のコードがこんな感じです。

```scala
def findUser(userId: Int): Try[Option[User]] = {
    val sql =
      sql"""
            SELECT id, name
            FROM   user
            WHERE  user_id = "#${userId}"
      """.as[User]

    Try(Await.result(db.run(sql), Duration.Inf))
  }
```

これをFutureにこんな感じで変えてみます。　`db.run` に変えただけですね。

```scala
  def findUser(userId:Int): Future[Option[User]] = {
    db.run(
      sql"""
            SELECT id, name
            FROM   user
            WHERE  user_id = "#${userId}"
      """.as[User]
    )
  }
```

これでFuture型で返ってくるようになります。他のやり方もあるかと思いますので一例程度に。

## コードの使用側をFutureに変える
余談ですが、 `Await.result` だと処理が終了してから返ってきますので `get` してもOKです。
反対に、 `Future` は処理が終わってない状態のものが返ってくるので直接 `get` とかしてはダメです。
`None.get` になります。（これで1回実装してやらかした）

今のコードがこんな感じです。

* Tryの中身をmatchで取得して、Optionの中身をgetで取得

```scala
  // 返り値 : Try[Option[User]]
  hogeRepository.findUser match {
    case Success(OptionUser) =>
      OptionUser.get
    case Failure(e) => // エラー処理
  }
```

こんな感じで書き換えました。

* mapでFutureが返ってから以降の処理を実行
* Optionの中身をgetで取得

```scala
  // 返り値 : Future[Option[User]]
  hogeRepository.findUser.map { maybeUser =>
    maybeUser.get
  }
```

Futureのエラー処理は `recover` で書けるみたいなので、最終的にはこんな感じです。

```scala
  // 返り値 : Future[Option[User]]
  val futureUser = hogeRepository.findUser.map { maybeUser =>
    maybeUser.get
  }.recover {
    // エラー処理
    case e => {
      println(e)
      System.exit(1)
    }
  }
```

呼び出し側も変えなきゃダメなので途中から移行を考えてる人はちょっと骨が折れるかもしれませんね。

これで大量のアクセスにも耐えれそうなFutureの恩恵を受けれるコードに書き換える事ができました！

### 余談
処理の流れの中で、 `Seq[Future[String]]` みたいになって `Future[Seq[String]]` にしたい！なんて時は `sequence` を使うといい感じに処理できます。

```Scala
    val seqFutureStrings :Seq[Future[String]] = hogeRepository.findStrings
    // Futureの入れ子の順番を逆にする
    val futureSeqStrings :Future[Seq[String]] = Future.sequence(futureNames)

    futureSeqStrings.map { Strings =>
      Strings.mkString(",")
    }
```
lazysizesでRails画像遅延読み込み

# Railsを使った画像遅延読み込み
## 画像遅延読み込みとは
>遅延読み込みという技術は、Webサイトに表示される画像を一度に読み込まず、必要に応じて必要な分だけ読み込むというものです。不必要な画像の読み込みを後回しにして、画像以外のCSSやJSファイルの読み込みが先に行われます。そうすることで、表示速度を速くすることができます。

https://alaki.co.jp/blog/?p=2527

## 目的
lazysizesを使用し画像遅延読み込みさせることでWebサイトの表示速度向上を図ります
今回使用するのはlazysizesです。
<img width="1438" alt="スクリーンショット 2019-10-28 1.48.00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445600/153e3296-adb0-0017-7848-3ac1e1177bc3.png">

[lazysizes](https://github.com/aFarkas/lazysizes)
## lazysizesの導入
## 読み込み

``` app/views/layouts/application.html.erb
<%= javascript_include_tag 'https://cdnjs.cloudflare.com/ajax/libs/lazysizes/5.1.2/lazysizes.min.js' %>
```

## 使い方
下記のように遅延させたいimgタグにclass`lazyload `をつけると画像を遅延読み込みし、読み込むとclassが`lazyload`から`lazyloaded `に変わります

 `data-src`は遅延読み込みさせたい画像パスを入れます

``` .html
<img data-src="画像パス" class="lazyload">
```
ここでrailsで `image_tag`のように使えるようにするためにhelperを作成します
### helper作成
``` app/helpers/application_helper.rb
    def lazysizes_image_tag(source, options={})
      options['data-src'] = source
      if options[:class].blank?
        options[:class] = "lazyload"
      else
        options[:class] = "lazyload #{options[:class]}"
      end
       image_tag("画像を読み込んでない時の軽い画像", options) + ("<noscript>#{image_tag(source, options)}</noscript>").html_safe
    end
```
### SEO対策
`<noscript>`を付け足している理由としてはクローラはスクロールしない＝画像が読み込まれないので対象画像がインデックスされません。
そこで`<noscript>`の中に `<img>`を入れることでインデックス対象にしています。


### 呼び出し
``` .erb
<%= lazysizes_image_tag '画像パス' %>
```
これで画像の遅延読み込みが可能になりました。

#　参考記事
[jQuery Lazyloadプラグインで遅延読み込み](https://qiita.com/ysk_1031/items/36f5c5936a986d394d78)
[lazysizesの使い方を通して学ぶ、画像の遅延読み込みとレスポンシブイメージの基本](https://oxynotes.com/?p=10810)
[noscript内のコンテンツをGoogleは無視するが画像は例外的にインデックスする](https://www.suzukikenichi.com/blog/goolge-ignores-noscript-except-for-images/)
IPoE(IPv6)向けSoftEtherでOpenVPNを構築する

# はじめに
IPoE(IPv6,NGN)のみの環境下において、VPNサーバを構築しようとしても、自由にポートを解放できない性質上、選択肢はOpenVPN以外に無い。
VPNサーバとして一般的なSoftEtherを使い構築を行ったものの、結構はまりまくったので、手順を残しておく。

# サーバ環境
Windows10 Professional
IPoE (PPPoE環境でも可)

# クライアント環境
Windows10 Professional (MS-SSTP経由)
iPhone6s (OpenVPNアプリより)

# 事前準備1 (ポート開放)
IPoEにおいて、解放できるポートは限られている。
一覧はルータで表示可能である為、調べて適当なポート番号(仮に43210とする)をTCP,UDP共に解放しておく。
(NTTのルータであれば、配信済み事業者ソフトウェア一覧 http://ルータのIPアドレス:8888/enabler.ipv4/main など)
この際、「UPnP-IGD設定」などを有効にしておく必要があるかもしれない。

# 事前準備2 (SoftEther導入)
SoftEtherをインストールし、適当に初期導入を済ませる。
ユーザ名の追加程度も行っておく。

# SoftEtherの設定1 (リスナーポートの追加)
SoftEther VPN サーバー管理マネージャより、リスナー一覧(TCP/IP ポート)より、「新規作成」ボタンから、先に開けたポート番号43210を入力して解放を行う。
(はまりポイント1: SoftEtherの設定2でポート番号を設定するが、それとは別にこの手順が必要)

# SoftEtherの設定2 (OpenVPNの有効化)
SoftEther VPN サーバー管理マネージャより、「OpenVPN / MS-SSTP 設定」を開く。
ここの「OpenVPN サーバー機能を有効にする」にチェックを入れ、先に開けたポート番号43210を入力する。
また、「OpenVPN クライアント用のサンプル設定ファイルを生成」から、OpenVPNクライアントで用いるovpnファイルをzip形式で出力し、ファイルに解凍しておく。

# SoftEtherの設定3 (証明書の発行)
SoftEther VPN サーバー管理マネージャより、「暗号化と通信関係の設定」を開く。
ここの、「サーバー証明書」の「証明書の表示」より、「ファイルに保存」からCA証明書(CER)をファイルに保存する。
また、「サーバー証明書」の「エクスポート」より、「X509 証明書ファイル (.CER)と秘密鍵ファイル (.KEY)の組み合わせとして保存する」を選択された状態で、OKを押し、X509 証明書ファイル(CER)と秘密鍵ファイル(KEY)をファイルに保存する。
「SoftEther設定2」で作ったovpnファイル(****_openvpn_remote_access_l3.ovpnなど)をテキストエディタで開き、末尾付近のcert,keyのコメントアウトを解き、certにはX509証明書ファイルの中身を、keyには秘密鍵ファイルの中身を、また、caを新たに追加してその中にCA証明書の中身をコピペする。
(はまりポイント2: iPhoneから接続する際にca証明書が含まれていないとエラーになる)

# クライアントの設定
後はOpenVPNのクライアントを導入し、ovpnファイルを読み込み、疎通確認を行う。
ユーザ名/パスワードの認証の他、証明書による認証も行えるらしいが、そのあたりは省く。

# MS-SSTPの活用
クライアントがWindowsの場合、「SoftEtherの設定2」で「MS-SSTP VPN サーバー機能を有効にする」のチェックを有効にすることで、OpenVPNクライアントを用いず、Windowsに標準搭載されているVPNクライアント機能を用いての接続も可能。
MS-SSTPはOpenVPNと同じポートを用いる為、サーバアドレスの末尾にポート番号を追加する(****.softether.net:43210)ことで、接続が可能となる。
ただし、証明書をクライアントPCでインストールしておく必要がある。

MS-SSTPで接続する際、
「証明書チェーンは処理されましたが、信頼プロバイダーが信頼していないルート証明書で強制終了しました。」
というようなエラーが出て、接続できないことがある。
これは、証明書が正しくインストールされていない場合に起こる。
証明書は、右クリックメニューの「証明書のインストール」から、インポートウィザードを開始し、「保存場所」を「ローカル コンピューター(L)」、「証明書ストア」で「証明書をすべて次のストアに配置する(P)」を選択したうえで「参照(R)...」ボタンから、「信頼されたルート証明機関」を選択し、インストールする必要がある。
警告が出てくるが、自分が作った証明書であり、問題はないはずなので、OKで良い。
ローカルユーザーや、自動でストアなどをすると、上記のエラーとなるので注意が必要な点となる。

# 終わりに
VPNに対して明るいわけではなく、特に証明書の辺りはいい加減にやってうまくいった程度の内容である為、間違いがあるかもしれないが、悪しからず。
リーダブルコード第4章＜美しさ＞

読み手がなれているパターンと一貫性のあるレイアウトを使う
似ているコードは似ているようにみせる
関連するコードをまとめてブロックにする

#なぜ美しさが大切なのか
**見た目が美しいコードの方が、使いやすいから**

#一貫性のある簡潔な改行位置

#メソッドを使った整列
コードの見た目を美しくすると、良い副作用もある

- 重複を排除することで、コードが簡潔になる
- コードの把握がしやすくなる
- テストケースの場合は、テストの追加が容易になる


#縦の線を真っ直ぐにする
見た目がきれいで、読み流ししやすい
タイポを発見しやすい

#一貫性と意味のある並び
意味のある順に並べる
対応するHTMLフォームの<input>フィールドと同じ並びにする
「最重要」なものから重要度順に並べる
アルファベット順に並べる

#宣言をブロックにまとめる

メソッドの概要をすぐに把握できるような配置で記述する
論理的なグループに分ける

#コードを「段落」に分割する
段落ごとに要約したコメントを追加し、流し読みしやすくする。

#個人的な好みと一貫性

#まとめ
- 複数のコードブロックで同じようなことをしていたら、シルエットも同じようにする
- コードの「列」を整列すれば、概要が把握しやすくする
- 意味のある順番を選び、順番を守る
- ブロックを作成し、論理的な「段落」に分ける
OpenVPNでのクライアントのIP固定化

OpenVPNでのクライアントのIP固定化を行う設定について記載。


* クライアント別の設定ディレクトリからの設定の読み込みを有効にする

```bash
$ vim /etc/openvpn/server.conf
    client-config-dir ccd
```

* クライアント名ごとに下記のファイルを作成する

```bash
$ vim /etc/openvpn/ccd/client1

    # 実行コマンド クライアント固定IPアドレス サーバ固定IPアドレスの順に記載
    ifconfig-push 10.10.0.22 10.10.0.23


※ 同様にクライアントごとに同じ形式のファイルを用意する。

$ vim /etc/openvpn/ccd/client2

    ifconfig-push 10.10.0.26 10.10.0.27
```

```bash

systemctl start openvpn@server.service
```

---


etc

https://wiki.archlinux.jp/index.php/ネットワークブリッジ

* https://www.server-memo.net/server-setting/openvpn/openvpn_2_4-tun.html


* https://helog.jp/windows/openvpn-bridge/
Unityメモ：Unityのビルド時に見慣れない警告が出る

#症状
```
Script attached to 'SpawningBase_SpawnableObjectPrefab' in scene '' is missing or no valid script is attached.
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)

Script attached to 'AuthObjPrefab' in scene '' is missing or no valid script is attached.
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)

Script attached to 'GetCurrentRTTCallDoesntCrashWhenUseWebSockets_PlayerPrefab' in scene '' is missing or no valid script is attached.
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)

Script attached to 'SpawningBase_PlayerPrefab' in scene '' is missing or no valid script is attached.
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)

Script attached to 'PlayerWithAuthPrefab' in scene '' is missing or no valid script is attached.
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)

Script attached to 'NoAuthObjPrefab' in scene '' is missing or no valid script is attached.
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)

Script attached to 'PlayerCallbacksOrderOnTheHost_PlayerPrefab' in scene '' is missing or no valid script is attached.
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)
```

#解決方法
PackageManagerから「Multi Player HLAPI」をバージョンアップする。

#参照
[Script attached to 'PlayerWithAuthPrefab' in scene '' is missing or no valid script is attached error when making android build](https://answers.unity.com/questions/1624149/script-attached-to-playerwithauthprefab-in-scene-i.html)
【68日目】「オブジェクト指向でなぜつくるのか」を読んで学んだこと １

パーフェクトPHPで学習を進めているのですが、５章のクラスとオブジェクトからどうも進捗が芳しくない。
サンプルコードを読んでも理解できないことが多くなった気がします。
PHPの文法の知識がないのもありますが、オブジェクト指向の理解ができておらず、クラス、インスタンス、オブジェクトと言った用語に翻弄されている気がしたため、オブジェクト指向を学ぶことにしようと思いました。

そこで学習書籍に選んだのがこちら
[オブジェクト指向でなぜつくるのか](https://www.amazon.co.jp/%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E6%8C%87%E5%90%91%E3%81%A7%E3%81%AA%E3%81%9C%E3%81%A4%E3%81%8F%E3%82%8B%E3%81%AE%E3%81%8B-%E7%AC%AC2%E7%89%88-%E5%B9%B3%E6%BE%A4-%E7%AB%A0/dp/4822284654)
軽く手にとってみたところ、ネットでよく見かける説明とは異なる説明の仕方がされていたため選択。
3日程度で読んでみて、学んだことをまとめていこうと思います。

今日の記事では時間の都合もあり、かけるところまで書いて次回に続きます。

# 1  歴史から理解するオブジェクト指向
　本書は「なぜ」と「なに」に注目した解説書でした。
　私がこれまで触れてきたオブジェクト指向についての教材は、Railsアプリを作成するための動画教材中で「インスタンス変数」とかを使う際にちょっと説明で出てくるもの程度でしたから、「how」に重きが置かれていました。なので、「インスタンス変数はクラス内で『@変数名 = new.Class(引数)』とすれば生成できる」ということは知っていますが、インスタンス変数が何かはあまりわかりません。
　オブジェクト指向では変数も関数も全てオブジェクト = モノとして扱える、と聞いたことはありますがどういう意味かはあまりわかりませんでした。
　本書では、歴史的な経緯から何を求めてオブジェクト指向が開発されたのかを説明してくれます。
　つまり、オブジェクト指向で実現したい目標を理解した上で、コードを見ることができるようになるのです。
　※ただし、私は実際のコードを見た経験が少ないせいもあり、本書を読んでもポリモーフィズムが具体的にどう実装されるのか、実際のコードのイメージがあまり沸いていません。PHPでいうabstractクラスのことでしょうか。

## 1.1 オブジェクト指向以前のプログラミング言語の課題
　プログラミング言語は最初「プログラミング難易度の易化 = 生産性の向上」のために開発されました。
　当時はハードが貧弱だったためプログラムは短命で、改修のたび一から作り直していたようで、簡単に作れるようになることが求められました。また初期の言語は非常に難しく、平易に表現できることが求められました。
　しかしながら、ハードが進化しプログラムの寿命が延びると、プログラムをメンテナンスして使い続けるようになります。すると、言語には「保守性」が求められるようになりました。

　その流れを確認して、オブジェクト指向が解決したい課題について確認します。

### 1.1.1 機械語
　最初のコンピュータは全て２進法の機械語で命令していました。非常に可読性が低く、専門的な知識が必要で難しい作業です。
　今でもコンピュータは機械語しか読めないので、どんなコードもコンパイルされて最後は機械語になるわけですが、当時はコンパイルが存在しません。
　この難易度の高さがこの時代の課題です。

### 1.1.2 アセンブリ言語
　アセンブリというのが最初のプログラミング言語だそうです。
　機械語から、多少人間が読める記号に置き換えて記述できる言語に進化しました。同時にアセンブラというプログラムに読ませて機械語に翻訳する「コンパイル」という技術が生まれました。

### 1.1.3 高級言語　FORTRANやCOBOL
　アセンブリ言語はあくまでコンピュータが理解できる命令である機械語を、そのまま人間のわかる記号に置き換えただけです。
　高級言語ではさらにその命令を命令のままではなく、人間が読みやすい形にまとめました。
　例えば、アセンブリ以前では、Xというデータを送れ、Yというデータを送れ、XとYを合計しろ、合計値Zを送れ、と命令ごとに１行ずつ記載していました。高級言語ではこれを「X + Y = Z」と書くことができわかりやすいです。
　このように高級言語までの進化では、そもそも「プログラムを平易にする」ものでした。

### 1.1.4 構造化言語 C系列
　ここで初めて「構造をわかりやすくする」ことで、より正しく動作し保守性を高めた言語が生まれます。
　大きな改良点は①GOTOレスプログラミングと、②サブルーチン（関数）の独立性強化です。
　具体的には、GOTO文をやめ、「順次進行、条件分岐、繰り返し」の３構造のみで記述しながら、グローバル変数をできるだけ使わないように、ローカル変数と引数の受け渡しでプログラミングするということです。グローバル変数は全てのサブルーチンからアクセスできるので、一度変更するたび、全てサブルーチンへの影響を調べる必要があるのです。
　しかしながら、アプリケーションの規模は巨大化していく一方で、グローバル変数は未だ現存しており、数千のサブルーチンをもつアプリケーションなどにおいては依然として負担となっていましたし、コードの再利用という面でも、サブルーチンまでしか共通部品を作れなかったので、巨大なアプリではまだまだ手書き部分が多く労力がかかっていたのでした。

## 1.2 次世代言語に求められたもの
　もうお分かりだと思いますが、次世代言語とはオブジェクト指向言語のことです。
　そして、求められたものとは
　
　**（１）　【保守性】グローバル変数対策
　　　　　→プログラム全体に影響するため、変更するたびに全ロジックの確認が必要
　　 （２）　【再利用性】サブルーチンよりも大規模なコードの再利用**

　でした。
　オブジェクト指向では「クラス」「ポリモーフィング」、「承継」という3つの要素によって実現されています。

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

今日はだいぶ遅くなってしまったので、中途半端ではありますがここまでとします。
明日以降で上記の3つの目的をどのように解決したのか確認していきます。
potision:fixed したheaderがページ全体のmin-widthを下回った時にスクロールできなくなってしまう

[「position: fixed」でスクロール固定したヘッダーを横にスクロールさせる](https://www.websuccess.jp/blog/archives/2458/)

この記事が参考になる。

```css
.header {
	position: fixed;
	top: 0;
	min-width: 1000px;
}
```
みたいに固定されてて`min-width`指定してあると、`min-width`下回ると普通のコンテンツは横スクロール出来るが、`fixed`のコンテンツは出来ない。
なので、`fixed`してある`header`だけが横スクロールできなくなってしまう。本来は中身のコンテンツを横スクロールしたら`header`も横スクロールしたい。
なので、その時は

```javascript
    $(window).on("scroll", function(){
    	$(".header").css("left", -$(window).scrollLeft());
    });
```

のようにJSで動かしてあげる。
`window`を`scroll`したら、`.header`の`css`に`left`を入れてあげる。
その値は`window`の横スクロールした値の逆。

scrollLeftは右に画面がいった値（左にスクロールした値）なので、その逆をleftに入れてあげる。
100px左にスクロールしたらleftに-100px。

これで実質同じ動きが実現できます。
基本情報2週目(10/28週)

# 目標と結果
### 目標
- 8項目まで参考書の演習問題を正解する。
- できない部分を見つけ、そのままにしない。
- 基礎理論とアルゴリズムを勉強を続ける。
- [基本情報技術者試験ドットコム](https://www.fe-siken.com/)を使う。

### 項目

独習ゼミの項目で言うとFE27まで
4．システム構成要素
(システムの構成・システム評価指標)
5．ソフトウェア
(オペレーティングシステム・ミドルウェア・ファイルシステム・開発ツール・オープンソースソフトウェア)
6．ハードウェア
(ハードウェア全般)
7．ヒューマンインターフェイス
(ヒューマンインターフェイス技術・インターフェイス設計)
8．マルチメディア
(マルチメディア技術・マルチメディア応用)

### 結果
- 2章 ソフトウェアのテストをクリアした。
- FE27までの項目を勉強した。

# 振り返り
### Keep

- 継続的に勉強はできている。

### Problem

- 卒業論文と運転免許取得の作業が重なって思うように基本情報の勉強が出来なかった。
    - 理解ではなく暗記になってしまっている。
    - 特に卒論のための読書や調べる作業に時間を取られてしまう。

### Try
- 優先順位をつける(免許取得を後回しにする？)
切断に至る USB Wi-Fi子機、そして

## 【繋がらない、Wi-Fi】
前回 [USB Wi-Fi子機の自動再接続](https://qiita.com/god19/items/4616df0d92385df24475 "USB Wi-Fi子機の自動再接続") の続き。
動作が不安定になった。Raspberry Pi 3B 起動後、数十秒で切れてしまい、その後まったく繋がらない。（再接続スクリプトが効かない）
流石に Wi-Fi子機を挿し直したり、タスクバーの Wi-Fi メニュー [Turn Off Wi-Fi] -> [Turn On Wi-Fi] とすれば再接続されるが、やはり数秒から数十秒後に切れてしまう。

Wi-Fi子機を接続する USBポートを変えてみたり、アンテナの角度を変えてみたり、Power Off 等の設定を見直してみたり、オンボード Wi-Fi が干渉しているのかと止めてみたり。
色々と試行錯誤するも改善されない。
感覚的に何かが接続を阻害しているというか、干渉している印象。

## 【見知らぬ、接続先】
`/etc/wpa_supplicant/wpa_supplicant.conf` に不正な接続先が先頭に登録されていた。何だこれ？
`SSID` が自宅 Wi-Fi以外のもの（多分隣近所のもの）で、パスワードが自宅Wi-Fi のものという定義。当然繋がらない接続先。
しかしそんなものを書き込んだ覚えはない。GUI上で WI-Fi に手動で接続した場合にもこの設定ファイルに書き込まれるので、誤った操作をした結果なのかもしれない。
何にしても、この不正な設定が悪影響を及ぼしていたようで、この定義を消したら問題も解消された。

## 【Wi-Fiを、君に】
と、分かってしまえば単純な問題だったけど、それが分からず二日ほど悩んだ。

一方でもう一つ問題があった。
折角 5GHz帯に接続する為にUSB Wi-Fi子機を挿しているのに、自動接続ではしばしば 2.4GHz帯に繋ぎに行ってしまう。
優先的に 5GHz帯に接続するような設定はないものかとネットを検索し、前述の設定ファイルの `priority` で指定する方法に辿り着く。
[ラズパイで複数のネットワーク設定をする](https://qiita.com/hxbdy625/items/374394f3dff17bdaf843 "ラズパイで複数のネットワーク設定をする")

早速設定ファイルを開いてみると……。でやっとそこに不正な接続先が定義されていることに気が付いたと。

## 【Wi-Fiのかたち 接続先のかたち】
ただし、まだ不満点はある。
起動時、5GHz帯に優先的に接続されるようにもなったのは良いけど、設定ファイルの優先順位はあくまでもこの初回接続時に適用されるらしい。

自宅 Wi-Fi環境は中継機が不安定で時々接続不能になる。それが原因で接続が切れた場合は親機に接続に行って欲しいのだけど、再接続には前述の優先順位は適用されないようで、あくまでも切断された接続先（最後に繋がっていた接続先）に繋げに行く仕様らしい。
ここら辺の制御方法はないものかね。

しかし、色々と勉強になった。
因みにオンボード Wi-Fi の止め方は以下が参考になった。
[Raspberry Pi 3の無線LAN(内蔵WiFi)をオフにする](https://qiita.com/yyano/items/802da53ad8a4a00d00e1 "Raspberry Pi 3の無線LAN(内蔵WiFi)をオフにする")

それと、Wi-Fi が切れている状態だと、シャットダウン、リブート時、デスクトップ画面が終了し、コマンドモードに戻ってから数十秒固まってしまい、ストレスだった。
あれって何やってるんだろう？
Laravelでabortをつかってjsonを返す

## はじめに

LaravelではabortというHTTP例外を投げるヘルパが存在します
https://readouble.com/laravel/6.0/ja/errors.html#http-exceptions

通常のHTTP例外を返すのによく使われていますが、jsonの例外を投げるのにも使えることを知ったのでそのメモです

### jsonによる例外
結論から言うとresponseインスタンスからjsonを作ってそれをそのままabortに食わっせるだけでおｋです

独自で例外作ってhanderに食わせるのもなーってときに使えるのはとても便利
abort全般で使えます

```php
abort(response()->json(['message' => 'error!'], 400));

abort_if('hoge' === 'hoge', response()->json(['message' => 'error!'], 400));

abort_unless('hoge' !== 'hoge', response()->json(['message' => 'error!'], 400));
```

~~responseで渡すゆえにステータスコードの位置が変わるのがわかりにくい~~

## あとがき
検証したのは6.1ですが、5.6以降でもできるようです
詳しい部分は下記参照で（まるなげ）
https://cpoint-lab.co.jp/article/201903/8753/
homesteadのmigrationでAccess deniedが出たときの対処法

# php artisan migrateでコケた
```
$ php artisan migrate

   Illuminate\Database\QueryException  : SQLSTATE[HY000] [1045] Access denied for user 'homestead'@'localhost' (using password: NO) (SQL: select * from information_schema.tables where table_schema = homestead and table_name = migrations and table_type = 'BASE TABLE')
```
とのこと。
`(using password: YES)`でコケてる記事はいくつか出てくるけど、`(using password: NO)`はあまりヒットしなかったのであとの人のために書きます。

# 先に結論

```
mysql> SET PASSWORD = 'secret'
```
して、.envを`DB_PASSWORD=secret`に変更したのち
`php artisan cache:clear`して`php artisan migrate`
で解決。

# まずは確認
`vagrant ssh`した状態で`mysql`コマンドを打ったらログインできるのが前提。
これができない場合はまずは手動でmysqlログインできる状態まで頑張って持っていきましょう。
mysqlに入れたら
`select USER();`でなんというユーザ名で入れているのかを確認。（おそらく``homestead@localhost'`とか出てくるはず。その場合ユーザ名はhomestead）

次に接続するDBの確認。mysql内で`show databases;`してhomesteadがあることを確認しましょう。

```
mysql> show databases;
+---------------------+
| Database            |
+---------------------+
| information_schema  |
| homestead           |
| #mysql50#lost+found |
| mysql               |
| performance_schema  |
| sys                 |
+---------------------+
6 rows in set (0.00 sec)
```

ここまで確認できたら開発中のLaravelプロジェクト内の`.env`ファイルに

```
DB_DATABASE=homestead
DB_USERNAME=homestead
```
と定義されているかを確認しましょう。

# パスワードを使用するように変更
なんだかパスワードが設定されてないのが原因らしいので、.envファイルで

```
DB_PASSWORD=
```
となっているところを

```
DB_PASSWORD=secret
```
などにして、（必ずしもsecretである必要はないけども）
mysql内で

```
mysql> SET PASSWORD = 'secret'
```
すれば行けるハズ。
androidxでswiperefreshlayoutを使う。

最新の環境でswiperefreshlayoutを使うためのメモ。
gradleに↓を追加。
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.0.0'
使い方は他の記事を参考にしてください。

（古い情報だとandroid.support.v4.widget.SwipeRefreshLayoutを使ったやり方しか見つからなかった。。。）
古いライブラリを使う場合は、migrationを参考にしよう。
https://developer.android.com/jetpack/androidx/migrate
https://github.com/firebase/firebase-android-sdk/issues/742
cronはもはや不要！？lavary/crunzを使って、PHPでタスク管理してみた。

# lavary/crunzを使って、PHPでタスク管理してみた。

## できること
タスク管理は、crontabやcron.dでシェルやファイル毎に時間の指定をすることが多いと思うが、その管理をPHPで制御できるようにする。

## メリット
PHPファイルの中でタスク管理が可能
デプロイ時が楽

## デメリット
日本語の文献が少ない
大元のphpファイルだけはcronの設定が必要

## 準備
### ①ライブラリをcomposerでインストール

インストールしたいアプリケーションディレクトリ上で以下のコマンド。
composerがインストールされていなければ入れる必要がある。

```
composer require lavary/crunz
```

**成功すると、vendor/binフォルダの中に「crunz」ファイルが作成されます。**

※CakePHP3での動作は確認済み


### ②大元のタスク管理ファイルをphpで作成
**ディレクトリの場所は問わないが、ファイル名を必ず「〇〇Tasks.php」とすること**

例：
・DefaultTasks.php
・TestTasks.php
・SimpleTasks.php
など。

### ③大元のタスク管理ファイルの中でlavary/crunzを呼び出す。


```
use Crunz\Schedule;
```


### ④大元のタスク管理ファイルの中にタスクを書く。

```
<?php

use Crunz\Schedule;

$schedule = new Schedule();
$task = $schedule->run('mv /var/www/html/test.php /var/log/test.php');
$task->daily();

return $schedule;

```

以上のサンプルは、1日毎にtest.phpを移動させるスクリプトになります。

```
$schedule->run('')
```
()内に、linuxのコマンドをそのまま書くことができます。


```
$task->daily();
```
以上は1日毎に実行という意味です。

#### 実行のパターン
##### ①毎日10時に実行
```
$task->dailyAt('10:00');
```
##### ②毎分実行
```
$task->everyMinute();
```
##### ③毎週月曜日の5時に実行
```
$task->mondays()->at('5:00');
```
##### ④毎分10分毎に実行
```
$task->everyTenMinute();
```

#### ⑤月の初めの9時に実行
```
$task->monthly()->at('9:00')
```

※もっとパターンがあります。詳しくはgithubを参照ください。
https://github.com/lavary/crunz



#### 複数タスクも勿論可能
```
<?php

use Crunz\Schedule;

$schedule = new Schedule();
$task = $schedule->run('mv /var/www/html/test.php /var/log/test.php');
$task->daily();

$task = $schedule->run('cp test.php{,.20191010}');
$task->mondays()->at('19:00');

//CakePHP3のシェルも、もちろん可能！！
$task = $schedule->run('bin/cake TestShell');
$task->everyMinute();

return $schedule;
```


### ⑤大元のタスク管理ファイルをcronに置く
タイトルにcronはもはや不要！？と書いたのですが、実際は結局必要なのです。
大元のタスク管理ファイルを、cronで毎分（毎秒）実行させることによって、
phpで設定した実行コマンドをタスクとしてそれぞれ実行するのです。

linux CentOS7で動作確認してます。

cron.dに移動

```
cd /etc/cron.d/
```

cron.d内にsampleタスクを作成

```
vi sample
```

毎分に実行するタスクを書く(実行者はサンプルではroot)

```
* * * * * root vendor/bin/crunz schedule:run
```

schedule:runを呼び出すことによって、
先に作ったDefaultTasks.phpを呼ぶ形になるのです。

これでタスクは設定どおりに呼び出されます。


## おまけ
タスク管理ファイルはphpなので勿論、以下のような使い方も可能です。

```
<?php

use Crunz\Schedule;

$environment = 'local'; // or production
$date = date("YmdHis");
$schedule = new Schedule();

//ファイル名をPHPで生成
$task = $schedule->run('mv /var/www/html/test.php /var/log/'.$date.'.php');
$task->daily();

//if文の利用
if($environment == 'local'){
   $task = $schedule->run('mv /var/www/html/test.php /var/log/test.php');
   $task->daily();
}

return $schedule;

```

等々
Git の使い方まとめ的 (最低限) なやつ

友達とかに軽く説明するときに使うかもなーっと思ってメモしておく記事です。
https://git-scm.com/docs
↑ これ読んだほうが早いので読める人はこっちどうぞ

※ 適宜使いそうなコマンドを追加しておきます、知りたい動作あったら気軽にどうぞ


## git を使用する前の準備
*※ Windows、Mac ともに Git が使用できる状態になっていることが前提*
1. `git config --global user.name "Your User Name"`
2. `git config --global user.email Your Account Email Address`  

この 2つのコマンドを実行する

```
(例)
git config --global user.name "John Doe"
git config --global user.email johndoe@example.com
```

## GitHub に Push するまでの流れ (コマンドライン)
1. ターミナルを開いてコミットしたいプロジェクトのディレクトリに移動する
![Git_Commit_01](https://user-images.githubusercontent.com/11432913/67143550-7d783180-f2a7-11e9-8707-15835fb68f5d.png)

2. `git status` で差分や今のブランチを確認する (ここはやらなくてもいい)
![Git_Commit_02](https://user-images.githubusercontent.com/11432913/67143551-7d783180-f2a7-11e9-99c8-703f6b18aab8.png)

3. `git add` でコミットするファイルを指定する
![Git_Commit_03](https://user-images.githubusercontent.com/11432913/67143552-7d783180-f2a7-11e9-9298-a612d8b3fcd1.png)
    * 基本的には `git add .` の全ファイルコミットの指定でOK
    * 個別でファイルをコミットしたいときは `git add 個別にコミットしたいファイル名` で指定する

4. `git commit` でコミットメッセージを指定する
![Git_Commit_04](https://user-images.githubusercontent.com/11432913/67143553-7e10c800-f2a7-11e9-9fd8-b1efdb0067ca.png)
    * 基本的には `git commit -m "コミットメッセージ"` でOK
    * 個人的には `git commit` で vi モードを立ち上げてコミットメッセージを指定する方法が間違えなくて楽かと

5. `git push` でプロジェクトにプッシュする
![Git_Commit_05](https://user-images.githubusercontent.com/11432913/67143554-7e10c800-f2a7-11e9-8580-8bd88252661e.png)
    * master ブランチに push する場合は `git push` のみでOK
    * ブランチをわけて作業している場合は、 `git push origin ブランチ名` でプッシュする
    
## 作業ブランチを変更する場合
1. `git pull` で現状のリポジトリ情報を更新する
    * ファイルの更新を行いたくない場合は `git fetch`
2. `git status` で現状のブランチを確認する
    * `On branch <BranchName>`
3. `git checkout` でブランチを変更する
    * すでに存在しているブランチに変更する場合は `git checkout <BranchName>`
    * 新しくブランチを作成する場合は `git checkout -b <BranchName>`
4. `git status` で `On branch 変更したブランチ名` と表記されていればOK
    * `git branch` でも確認できます

## 他の人が git push したリポジトリデータを自分のリポジトリに反映させる場合
1. `git pull` で反映される
    * master ブランチ以外のデータを反映させたい場合は `git pull origin <BranchName>`
Postgisを使って緯度経度から２点間の距離を計算した

#背景
インターン先のサービス提携先の各店舗の商圏内にいるユーザーIDとその店舗を算出して個別のユーザーアプローチを取ることになったので、やってみました。
最初はmetabaseからユーザーと店舗の位置情報テーブルを個別に二つcsvファイルで用意してpythonで読み込んで計算したんですが、postgresqlを採用してたのでpostgisを使ってmetabase内で計算することにしました。
metabaseは社内で利用している無料のBIツールです。
pythonで計算した時の参考記事は[こちら](https://qiita.com/damyarou/items/9cb633e844c78307134a)

#やりたいこと
各ユーザーと1km以内にある店舗の組み合わせを全て出したい

#データ
・faclility_id,lat,longの３列＊店舗数のfacilitiesテーブル
・user_id,lat,longの３列＊ユーザー数のuserテーブル

#コード
```postgresql:distance
SELECT
    dist.user_id
    dist.facility_id
    dist.distance
FROM
    (SELECT
        users.user_id AS user_id,
        facilities.facility_id AS facility_id,
        st_distance_sphere(st_makepoint(users.long, users.lat),
                           st_makepoint(facilities.long, facilities.lat)) AS distance,
    FROM users
    CROSS JOIN facilities) AS dist
WHERE dist.distance < 1000;
```

CROSSJOINでユーザーレコードと店舗レコードの全組み合わせのレコードを作り、その全部に対してpostgisのst_distance_sphere関数を使うことで全組み合わせの距離を算出しています。

#やってみて
この関数では完全な球形に対して計算しているので回転楕円体である地球により近似するためにはst_distance_spheroid関数を使うとより精密になりますが、今回の計算で算出する距離は長くとも100km程度で、欲しいのは1km以内かどうかなのでこれで十分かと思います。

ちなみに、pythonでやってみた時との誤差は数m程度だったので、この誤差が上記の厳密さに起因しているのかと思いました。

参考にした記事
[postgresql-PostGisの距離計算](https://codeday.me/jp/qa/20190324/473243.html)
オリジナルアプリにパートナー申請機能を実装する

#概要
* オリジナルアプリ作成にあたり、ユーザ(current_user)が他ユーザに対してパートナー申請をする画面をトップページ(toppages#index)に実装したい。
* 申請手順は以下の通りとなる。
  1. 自分(ユーザA)がパートナー(ユーザB)に対して招待を送る。その際にユーザAは「秘密の言葉」を設定しておく。
  2. パートナーのトップページに「招待が届きました」というメッセージが届き、それを「承認」か「拒否」かを選択する。承認する場合にはユーザAが設定した「秘密の言葉」を入力する必要がある。
  3. 承認された場合はユーザAとユーザBはパートナーとなる。
* ユーザと他ユーザがパートナーである事は中間テーブルrelationshipsに定義する。

#手順

### パートナー申請フォーム作成
中間テーブルrelationshipsにて多対多の関係（ユーザと他ユーザがパートナーである状態）を表す。

* 中間テーブルrelationshipsのカラム構成

| id | user_id | partner_id | status | secret_words |
|:--:|:-------:|:----------:|:------:|:------------:|
|  |  |  |  |  |

form_withを用い、relationshipsテーブルにデータが登録されるようにする。
relationshipsのパーシャルでパートナー申請フォームを作成する。

```ruby:relationships/_offer_form.html.erb
<div class="row">
    <div class="col-sm-6 offset-sm-3">
        <%= form_with(model: relationship, local: true) do |f| %>
            <div class="form-group">
                # relationshipテーブルに無いデータの入力の為、"f.~"ではなく"~_tag"を用いる
                # 初期値をテキストボックスに表示しておきたい場合、""内に値を入れる（今回は不要の為、ブランク）
                <%= label_tag :name, "パートナー申請先(ユーザ名)" %>
                <%= text_field_tag :name, "", class: "form-control" %>
            </div>
            <div class="form-group">
                <%= f.label :secret_words, "秘密の言葉" %>
                <%= f.text_field :secret_words, class: "form-control" %>
            </div>
            
            <%= hidden_field_tag :status, "承認待ち" %>
            
            <%= f.submit "招待する", class: "btn btn-primary btn-block" %>
        <% end %>
    </div>
</div>
```

### パートナー申請画面作成
relationshipsのパーシャルで作成した申請フォームをrenderで読み込む。

```ruby:views/toppages/index.html.erb

<div class="text-center">
    <h1>パートナー申請画面</h1>
</div>
# classを跨ぐ場合はインスタンス変数を用いるとclass間で依存関係が出来てしまうので、使用しないほうが良い
<%= render "relationships/offer_form", relationship: @relationship %>
```

### toppages controllerの実装
relationshipsのパーシャルで申請フォームを作成した為、インスタンス変数もRelationshipsControllerで定義するものだと勘違いしやすいが、それは誤りである。仮に別クラスのパーシャルであったとしてもviewに表示されているインスタンス変数はそのアクションを定義しているcontrollerに紐づいている為、今回の場合はインスタンス変数（@relationship）はtoppages#indexで定義する。

```ruby:controllers/toppages_controller.rb
class ToppagesController < ApplicationController
  def index
    if logged_in?
      # インスタンス変数を@relationshipとし、form_withのmodel引数に設定してあげることで
      # action先をRelationshipsController#createに暗に飛ばすことが出来る
      @relationship = current_user.relationships.build
    end
  end
end
```

### (補足情報)
current_userとlogged_in?のメソッドはSessionsHelperにて定義している。

```ruby:helpers/sessions_helper.rb
module SessionsHelper
    def current_user
        @current_user ||= User.find_by(id: session[:user_id])
    end
    
    def logged_in?
        !!current_user
    end
end
```

helperはviewでのみしか機能しないので、controllerで使用したい場合はmix-inをする。
今回、ToppagesControllerで使用したいが、他でも使用する可能性が高い為、全体に適用すべくApplicationControllerにmix-inしておく。

```ruby:controllers/application_contoller.rb
class ApplicationController < ActionController::Base
    # SessionsHelperをmix-in
    include SessionsHelper

    private
    
    def require_user_logged_in
        unless logged_in?
            redirect_to login_url
        end
    end
end
```
ABC143 参加記録

少し日が空いてしまいました。
公式の解説を見る前に記述しています。

# AtCoder Beginner Contest 143

## A - Curtain
[問題](https://atcoder.jp/contests/abc143/tasks/abc143_a)

```c++:Curtain.cpp
int main(void) {

	int A, B;

	cin >> A >> B;

	cout << (A > B * 2 ? A - (B * 2) : 0) << endl;

	return 0;
}
```
カーテン2枚分の長さを窓の長さから引けばヨシ。

## B - TAKOYAKI FESTIVAL 2019
[問題](https://atcoder.jp/contests/abc143/tasks/abc143_b)

```c++:TAKOYAKI_FESTIVAL_2019.cpp
int main(void) {

	int N;
	long long int sum = 0;

	cin >> N;

	vector<int> d(N);

	REP(i, N) cin >> d[i];

	REP(i, N){
		REPA(j, i + 1, N){
			sum += d[i] * d[j];
		}
	}

	cout << sum << endl;

	return 0;
}
```
ご丁寧に総和の数まで出してくれているので全パターン調べればOK。

## C - Slimes
[問題](https://atcoder.jp/contests/abc143/tasks/abc143_c)

```c++:Slimes.cpp
int main(void) {

	int N, sum = 1;
	string S;

	cin >> N >> S;

	char c = S[0];

	REPA(i, 1, N){
		if(c != S[i]){
			sum++;
		}
		c = S[i];
	}

	cout << sum << endl;

	return 0;
}
```
頭から順に調べていき、直前に調べた文字と違う文字が出てきたら総数を+1する。_O(N)_。


## D - Triangles
[問題](https://atcoder.jp/contests/abc143/tasks/abc143_d)
ACできなかった…悔しい

```c++:解けなかった.cpp
int main(void) {

	int N, a, b, c, sum = 0;
	vector<int> l(2001);

	cin >> N;

	vector<int> len(N);

	REP(i, N) {
		cin >> len[i];
		l[len[i]]++;
	}

	sort(ALL(len));

	REP(i, N){
		a = len[i];
		REPA(j, i + 1, N){
			b = len[j];
			int temp_sum = sum;
			for(int k = a + b - 1; k >= b ; k--){
				sum += l[k];
			}
			if(temp_sum != sum) sum -= l[a];
			j += b;
		}
	}

	cout << sum << endl;
	return 0;
}
```

Nが2 * 10^3だったせいか工夫しなければならないという強迫観念に囚われすぎたかもしれない。

最も小さい2本を先に決めておけば残り一本に使える棒の長さが決まるので、
入力を昇順に並び替える→小さい順に1本目を決める→次に小さい棒から一番長い棒の長さ-1本目の棒の長さまでを2本目として選ぶ→1本目＋2本目の長さより小さく、2本目の長さ以上の棒の長さを数える→1本目の棒が一番大きな棒を選ぶまで繰り返す
こんな感じで解けるはずだったが、3本目の棒を数えやすいようにバケットソートしていたら全部同じ長さの棒のときを失念していて、書きづらいコードになり最終的にうまくコードに起こせず時間切れ。。。

初めてレートが下がりました。精進します。

## 補足
載せているコードにREPとか出てくるけどC++にそんなものはなく、自作の競プロ用テンプレートを載せてなかったので一応

```c++:my_template
#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>

#define INF 2e9

#define REP(i,n) for(int i = 0; i < n;++i)
#define REPA(i,a,n) for(int i = a; i < n; ++i)
#define ALL(a) a.begin(), a.end()

using namespace std;
```
Pythonでの数学関数の使い方

こんにちは、~~[未来電子テクノロジー](https://www.miraidenshi-tech.jp/intern-content/program/)でインターンをしている者です~~（2020年1月退社）。
今回は、Pythonでの数学関数の使い方をメモします。

## ライブラリのインポート

まずは、`math`ライブラリをインポートします。

```python:math.py
import math
```

## いろいろな数学関数

次に、様々な数学関数を紹介します。

```python:math.py
import math

print(math.pi)                  #円周率
#3.141592653589793
print(math.sin(0))              #sin
#0.0
print(math.cos(0))              #cos
#1.0
print(math.tan(0))              #tan
#0.0
print(math.asin(0))             #arcsin(sin^-1)
#0.0
print(math.acos(1.0))           #arccos(cos^-1)
#0.0
print(math.atan(1.0))           #arctan(tan^-1)
#0.7853981633974483
print(math.sinh(1.0))           #sinh
#1.1752011936438014
print(math.cosh(1.0))           #cosh
#1.5430806348152437
print(math.tanh(1.0))           #tanh
#0.7615941559557649
print(math.degrees(math.pi))    #弧度法（radian）→度数法（degree）
#180.0
print(math.radians(180.0))      #度数法（degree）→弧度法（radian）
#3.141592653589793
print(math.sqrt(3))             #平方根
#1.7320508075688772
print(math.exp(3))              #ネイピア数（自然対数の底）
#20.085536923187668
print(math.log10(100))          #常用対数
#2.0
print(math.log(100))            #自然対数
#4.605170185988092
print(math.factorial(5))        #階乗（!）
#120                            #5*4*3*2*1
```

## まとめ

今回は、主な数学関数をメモしました。
HackerrankやAtCoderなどで数学の問題を解くときに役立ちそうです。
【Xamarin】C#でAndroidアプリを作ってみる 2 (デバッグ実行)

#概要
前回：[C#でAndroidアプリを作ってみる 1 (Xamarinインストール)](https://qiita.com/plusM/items/c859c5d54ac56a6e80e5)
今回は、ZodiacSignAppを実機でデバッグ実行してみます。

# プロジェクトのプロパティを設定する
1. ZodiacSignAppプロジェクトのプロパティを開きます。
2. 「アプリケーション」の「Androidバージョンを使用したコンパイル：(ターゲットフレームワーク)」を選択します。
![プロパティ1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520699/e0a10cf2-ecca-f947-f4ea-1021bdb95333.png)
※選択したAndroid SDKのバージョンがインストールされていない場合、エラーメッセージに従ってインストールします。

3. 「Androidマニフェスト」の「ターゲットAndroidバージョン」を選択します。
![プロパティ2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520699/334dbd18-86d1-5c2c-28f5-5797c78c9abe.png)

# 実機を設定する
1. 設定メニューの開発者向けオプションをON, USBデバッグをONにします。
![USBデバッグ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520699/178a9d94-0346-887d-a159-e2a40dcef4be.png)
※機種によって異なります。

2. データ転送用のUSBケーブルでPCと接続します。

# デバッグ実行する
1. 実機を選択して実行します。
![デバッグ実行開始.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520699/d1304b9c-bc89-b538-5e39-cda56147da4c.png)
2. 実機で、下図のように表示されれば成功です。<br> 
![デバッグ実行結果.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520699/a7db197a-c537-4b6b-e722-93e432c46e90.png)

# まとめ
今回は、ZodiacSignAppを実機で動かしてみるところまでを行いました。
次回は、ZodiacSignApp(干支×星座算出アプリ)の画面を作ります。
次回分はこちら⇒[C#でAndroidアプリを作ってみる 3 (画面作成1)](https://qiita.com/plusM/items/45ade15a6c9df6471aa4)
AWS CLIでAmazon Cognito（IDプール）を使ってみるサンプルメモ

# 概要

IDプールを用いて認証されたID（Facebook連携）と、認証されていないIDを用いた認証を試す

# メモ

## 認証されたID(Facebook)

### 前提
- Facebook のデベロッパーアカウントでアプリ登録済み
- テスト用のユーザートークン取得済み
- Cognito のIDプールを作成済み（認証プロバイダーはFacebook）
    - 	IDプールのIDを確認済み

### メモ

```sh
> aws cognito-identity get-id --identity-pool-id "[IDプールのID]" --logins "graph.facebook.com=[ユーザートークン]"
{
    "IdentityId": "ap-northeast-1:0cde9dab-cb6d-465e-903f-b339f612609a"
}
# ↑のIDは控えておく
> aws cognito-identity get-credentials-for-identity --identity-id "[取得したID]" --logins "graph.facebook.com=[ユーザートークン]"
{
    "Credentials": {
        "SecretKey": "", 
        "SessionToken": "", 
        "Expiration": , 
        "AccessKeyId": ""
    }, 
    "IdentityId": ""
}
# ↑控えておく

> export AWS_ACCESS_KEY_ID=xxxxx
> export AWS_SECRET_ACCESS_KEY=xxxx
> export AWS_SESSION_TOKEN=xxxxx
# あとはお好きに
```


## 認証されていないID

### 前提
- 「認証されていない ID に対してアクセスを有効にする」にチェックして保存する

![ScreenClip.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50690/7fb9c7a4-4b2b-3648-44c2-e602a5d4e812.png)


### メモ

```sh
> aws cognito-identity get-id --identity-pool-id "[IDプールのID]"
{
    "IdentityId": "ap-northeast-1:0cde9dab-cb6d-465e-903f-b339f612609a"
}
# ↑のIDは控えておく
> aws cognito-identity get-credentials-for-identity --identity-id "[取得したID]"
# あとは同じ
```



# 参考
ID プール (フェデレーティッドアイデンティティ) を使用する - Amazon Cognito https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/identity-pools.html
年末まで毎日webサイトを作り続ける大学生 〜29日目 ナビバーのスライドイン 自作に失敗する〜

##はじめに
こんにちは！@70days_jsです。
先に申し上げておくと、今日はナビバーを横からスライドインさせようとして失敗しました。
1時間あればできると思い、遅い時間から取り組み始めた慢心が原因です。全然できませんでした。

扱う技術レベルは低いですが、同じように悩んでる初心者の方を勇気付けられれば幸いです。
今日は29日目。(2019/11/16)
よろしくお願いします。


##サイトURL
- https://sin2cos21.github.io/day29.html

##やったこと
やろうとしたこと →　ナビバーアイコンをクリックすると、ナビバーのメニューが横からスライドインする
やったこと →　ボタンにホバーすると横から微妙な感じでメニューがスライドインしてくる

gif↓
![test.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/516248/9c0f1899-1424-d520-ad7a-9e689faff6af.gif)


ボタンにhoverするとメニューが横から出ています。
ご覧の通り文字が潰れていたり、色々残念な感じです・・・。


```html
<body>
    <div class="button">ボタン</div>
    <div>
        <div class="test">メニュー1</div>
        <div class="test">メニュー2</div>
        <div class="test">メニュー3</div>
        <div class="test">メニュー4</div>
        <div class="test">メニュー5</div>
    </div>
</body>
```

```css
.button:hover + div > .test {
    width:  7rem;
    color: white;
}


.test {
    width:  0px;
    height: 2rem;
    color: white;
    background-color: rgba(0, 0, 0, .8);
    transition-duration: .5s;
    transition-timing-function: ease;
    transition-property: width color;
}
```

実はホバー前も文字自体はすでに出ています。ですが、colorを白にすることでないように見せかけているだけです。
あと、本当はホバーではなくてactiveでクリックされたら表示という風にやりたかったのですが、うまく動いてくれなくて時間オーバーになってしまいました。


##感想
不甲斐ないの一言です。1時間しか勉強時間を取らなかったのがそもそもの原因で、調子に乗っていたなと反省しております。今回うまくいかなかったことは必ず原因追求して克服します。

最後までお読みいただきありがとうございます。明日も投稿しますのでよろしくお願い致します。
JSをライブラリのjQueryで書くメリット

JavaScriptとjQueryを一緒に勉強したので書いてみた
jQueryの特徴として、DOM操作（DOM要素の取得や追加、削除）などを短く簡単に書く事ができるのが特徴となっている。

JavaScriptでクラスの属性を取得する場合
例)

```js
document.getElmentsByClassName("クラス名");
```
と記入しなくてはならないが、
jQueryを使えば

```js
$(".クラス名");
```

これだけで上記の内容と同じ意味となる。
クラス名の前に . をつけるのを忘れないように！
ちなみに今回の例はクラスの属性の取得だったが、
idの指定だとid名の前に#をつける

```js
$("#id名");
```
要素の場合 要素名そのままでOK

```js

$("h1");
```
【Oracle OCI CLI】Object Storageからダウンロードした複数ファイルを、圧縮してから再アップロードする方法

# 3ステップ

1. Object StorageからComputeにcsvファイルをダウンロードする
2. csvファイルを圧縮する
3. 圧縮済みのcsvファイルをObject Storageに再アップロードする

## 1. Object StorageからComputeにファイルをダウンロードする
複数のcsvファイルをダウンロードする

```bash

oci os object bulk-download -ns {namespace} -bn {backet name} --download-dir . --include '*.csv'
```

## 2. csvファイルを圧縮する
gzip形式で圧縮

```bash

gzip *.csv
```

## 3. 圧縮済みのcsvファイルをObject Storageに再アップロードする

複数の圧縮済みcsvファイルをダウンロードする

```bash
oci os object bulk-upload -ns {namespace} -bn {backet name} --src-dir . --include '*.csv.gz'
```
Nuxt.jsのvue-chartjsでmomentをつかわないようにする

`nuxt build --analyze`してみたら、[vue-chartjs](https://vue-chartjs.org/ja/guide/)でmomentを呼んでいた。。
時刻は使ってなかったので、削除して軽くしてみたときの備忘録


#### nuxt.config.tsのexternalsを使えばOK


これに書いてあったのを参考に、nuxt.config.tsを設定
・ [Standalone chartjs build (don't include moment.js) · Issue #124 · apertureless/vue-chartjs](https://github.com/apertureless/vue-chartjs/issues/124)

```typescript
import NuxtConfiguration from "@nuxt/config";

const config: NuxtConfiguration = {

  build: {
    extend(config, ctx) {
      // externalsにmomentを追加して、読み込まないようにする
      config.externals = {
        moment: "moment"
      };
    }
  }
};

export default config;
```

#### resolve.aliasはダメだった。。

resolve.aliasも試したけど、こっちはダメっぽい。。

```typescript
import NuxtConfiguration from "@nuxt/config";

const config: NuxtConfiguration = {

  build: {
    extend(config, ctx) {
      // momentが含まれていないChart.jsを使うようにする
      if (!!config.resolve && !!config.resolve.alias) {
        config.resolve.alias["chart.js"] = 'chart.js/dist/Chart.js';
      }
    }
  }
};

export default config;
```

以上!!

## こんなのつくってます!!

積読用の読書管理アプリ 『積読ハウマッチ』をリリースしました！
[積読ハウマッチ](https://tsundoku.site)は、Nuxt.js+Firebaseで開発してます!

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/572d4947-f40b-e4dc-1c9c-bc584cd2a66c.png" width="200"/>

もしよかったら、遊んでみてくださいヽ(=´▽`=)ﾉ

要望・感想・アドバイスなどあれば、
公式アカウント([@MemoryLoverz](https://twitter.com/MemoryLoverz))や開発者([@kira_puka](https://twitter.com/kira_puka))まで♪

# 参考にしたサイト様
- [Nuxt.jsでwebpack.configを拡張してaliasを登録する - Qiita](https://qiita.com/soutarrr7/items/1b9a46df604ed78ec747)
- [Standalone chartjs build (don't include moment.js) · Issue #124 · apertureless/vue-chartjs](https://github.com/apertureless/vue-chartjs/issues/124)
ITエンジニアの基礎 検索篇

基本に立ち返って、基礎的で大事なことを備忘録で書こうと思います。

# 検索(データ収集)
わからなかったら検索する。あたりまえのようだけど
何気に知らない要素もあるのでここに書き記します。

## 複数キーワードで検索する
### 文章を単語に分割する
    例:　HTML CSS
### 何に関係のある情報かを含める
    例:　CSS 色　設定
### 意味を調べるときは「とは」をつける
    例:　HTMLとは

## ツールの使用(期間指定で新しい記事を探す)
   Googleには「検索ツール」という機能があります。
   一度普通に検索して図のように「ツール」をクリックすれば設定できます。
　　見ての通り言語や結果も操作できます。
　　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430767/1e7724b0-5b52-b848-cd30-fa93f538dffc.png)

## 英語で検索する
　　世界はやはり英語が世界共通語なので
　　それで検索した方が情報が集まります。
## マイナス検索
　　指定したワードを含まないWebページを検索結果として表示します。
　　マイナス検索で検索するには、除きたいワードの前に「-」をつけます.
### 
    例: html -qiita 　　これでqiita以外のhtmlのページが開けます。

## フレーズ検索
　　指定した検索キーワードに完全に一致するワードを含むWebサイトを検索結果として表示する機能です。
　　完全一致で検索したいワードを「""」で囲みます。
### 
    例1: web開発　　　これでwebまたは開発という単語があるサイトを検索します。
    例2: "web開発"　　こちらだと完全にweb開発という単語があるサイトしか検索されません
Javascriptでデバッグライトを製品版で取り忘れないように

やっていることはありきたりですが、逆引きとしてお役に立てば:shamrock:

# 方式
- webpackの設定ファイルを開発版と製品版で分ける。
- DefinePluginで定義したGlobal constantでデバッグライトのコードを生かすかどうかを決定する。

なお、使用したwebpackは4.41.2です。

## デバッグライトのコード
例えば、develop.jsなどとして、以下のようなデバッグライトのコードを記載しておきます。

```js
export {debug_msg};

function debug_msg(msg) {
    if (DEBUG) {
        console.log(msg);
    } 
}
```

## webpackの設定ファイル
開発版のコードと製品版のコードのビルドは、シンプルに以下のコマンドで行うことにしました。使用する設定ファイルの指定を変えているだけです。

```sh
（開発版）
.node_modules/.bin/webpack —-config webpack.dev.js

（製品版）
.node_modules/.bin/webpack —-config webpack.prod.js
```

設定ファイルは以下のように記載します。開発版と製品版での違いは`mode`と、`DEBUG`がtrueかfalseかだけです。


（開発版:webpack.dev.js）

```js
var webpack = require('webpack');

module.exports = {
    mode: 'development',
    entry: "./src/index.js",
    output: {
        filename: "bundle.js",
        path: __dirname + "/dist"
    },
    plugins: [
        new webpack.DefinePlugin({
            DEBUG: JSON.stringify(true)
        })
    ]
}
```


（製品版:webpack.prod.js）

```js
var webpack = require('webpack');

module.exports = {
    mode: 'production',
    entry: "./src/index.js",
    output: {
        filename: "bundle.js",
        path: __dirname + "/dist"
    },
    plugins: [
        new webpack.DefinePlugin({
            DEBUG: JSON.stringify(false)
        })
    ]
}
```

これで、develop.jsのDEBUGがtrueまたはfalseに置換されます。
さらに、minificationにより、不要なコードが削除されるため、製品版のdebug_msgは中身が空になる（[らしい](https://webpack.js.org/plugins/define-plugin/)）です。
[UE4]iniでログレベルを設定する


#前段
自分の担当部位は自分だけ常にログを出しておきたい
とか
しばらくレアバグのトラッキングのためにチーム全体の対象ログのレベルを上げておきたい
みたいな事ってありますよね。

もちろんコンソールコマンドとかコマンドラインオプションで入力するのもいいのですが、
iniファイルに記述することでも設定を適用することができます。

#エンジンのソースファイルはこの辺り

```c++:LogSuppressionInterface.cpp
	virtual void ProcessConfigAndCommandLine()
	{
		// first we do the config values
		FConfigSection* RefTypes = GConfig->GetSectionPrivate(TEXT("Core.Log"), false, true, GEngineIni);
		if (RefTypes != NULL)
		{
			for( FConfigSectionMap::TIterator It(*RefTypes); It; ++It )
			{
				ProcessCmdString(It.Key().ToString() + TEXT(" ") + It.Value().GetValue(), true);
			}
		}
```

なにかハードコートされた文字列が見えますね！
そうです！
*Engine.iniの `[Core.Log]` セクションに書くことでLogLevelを設定することができます。

#早速やってみよう

```[YourProject]/Config/DefaultEngine.ini

[Core.Log]
LogBlueprintUserMessages=none
LogDerivedDataCache=all
```

起動してみます。

```
Cmd: log list BlueprintUserMessages
LogBlueprintUserMessages                  NoLogging     
Cmd: log list Derived
LogAudioDerivedData                       Log           
LogDerivedDataCache                       VeryVerbose   
LogDerivedDataCacheCommandlet             Log           
```

しっかり適用されているのが確認できました！
今回はDefaultEngine.iniに書いたのでバージョンコントロールを使ってチーム開発している方々はその後に(サブミット|コミット)することで、チーム全体に影響を与えることに注意してください。
もちろん`Saved/Config/Windows/Engine.ini` に追記すれば自分だけに設定を適用可能です！

**DefaultEngine.iniの編集は影響範囲が大きいのでトラブルを避けるためにチームに確認を取って慎重に行いましょう！**
続・ActiveSupport::Callbackを使うのをやめろ

[ActiveSupport::Callbackを使うのをやめろ](https://qiita.com/luccafort/items/69e943b26ef6890b8a30)という話をしたがどうにもスッキリしない部分が残ってしまっていたのがKyoto.rbで話すテーマにしたらシュッと解決できたので共有。

- [Kyoto.rb Meetup 20191116](https://kyotorb.doorkeeper.jp/events/100041)

## 前回からのモヤッと部分

- ActiveRecord::Callbackを使わないほうがいいという結論に達したが本当にそうなのか？
    - だとしたらもっと多くの人が議論してRailsフレームワークから除外しているのではないか？
    - コールバックが本当に悪いのか？悪いのは実装側の都合なだけでは？
- プロダクトやチームのレギュレーションのようなもので縛ることが果たして本当に正しいのか？
    - それは対処療法としての対応でなのでは？
    - railsはMVCフレームワークなのでコールバックがどうしても浮いたものになってしまうがその結果安易になんちゃらServiceにしてしまうのが正しいのか？
    - レビューでコールバック使ってたらリジェクトするというのは1つあるかもしれないがその理由がきちんと説明できるのか？

というような部分で前回の書いたコールバックを使わない方針で大筋は間違っていない(やろうとすることに対する副作用が大きすぎる)と思うもののコールバック自体が絶対に駄目なのか？という点でモヤッと部分が残ってしまったことをKyoto.rbでこれが知りたいというテーマとしてあげさせてもらったら自分の中で腹落ちすることができた。

## コールバックで成し遂げたいこと

- Modelに関するなにかを起因として漏れなくアクションが実行されることを担保したい

なにはともあれコールバックってどんなものがあるの？ということで一覧を確認。
[ActiveRecordのコールバック早見表 | Rails](https://morizyun.github.io/ruby/active-record-callback.html)

矛盾するようだがコールバック関連で問題になるのはこの **漏れなく実行されること** が問題になりやすい。
例えばテストのときには実行されたくない、バッチ処理のときには実行されたくないなど。

コールバックで許せるものとしてあがったのはコールバックが連鎖しないこと、実行されるアクションが単独で完結することという条件があることが話していてわかった。

つまりコールバックを使ってもOKなものとしては

- バリデーション
- ログ出力
- メールやチャットへの通知

の3つはコールバックで実装されていてもよいのではないか？という結論に達した。
他にもあるかもしれないがパッと思いつきはしなかったのでひとまず一例ということでこれらはOKと判断した。

個人的にメールやチャットなどの通知系はOKとするか微妙なところだが、少なくとも問題が起こったとしても書き換えが容易なのでここではOKとして扱っている。
データ作ってメール送信する実装をService Object相当なファイルに実装してデータ作成している箇所の実装をそのService Objectで実装しているメソッド呼ぶようにすればいいだけなので書き換え箇所もそこまで多くならないはず。

そういえば、`associate`　は例外的に連鎖するけどこれは許容するべきという話になった。
Service Objectとしても実装できなくはないがコールバックでもいいんじゃない？元々それを期待して関連性を定義しているのだから、ということでこれだけ少し特殊な扱いになっているかも。

## 最終結論

なので用途を絞った運用上であればコールバックを使うことはやぶさかではないという結論に達した。
レギュレーションとしてコールバック駄目、絶対！とするにしても「これは単独で完結しないのでコールバックで実装すべきでない」や「これをしてしまうとA→B→Cとコールバックが連鎖する可能性があるので実装すべきでない」という自分が「何故駄目なのか？」を自信をもって言える気がする程度には納得できた。

一方で再認識できた点としてはコールバックで実行されるのはどのような条件でも必ず行われるものに限るということ。
テストでは行いたくない、バッチ処理では行われたくないという条件が発生しそうであればそれはコールバックでは実装してはならない。
コールバックを実装するときはどのようなパターンのとき実行されてほしくないかをきちんと議論する必要がある。

## さらなる追記

このエントリを書いたあとでFactoryBotのコールバックが実装されていて「おまえ！！！！」となった。
テストデータをシュッと作るために存在するはずがそのせいでテストデータに強い副作用が生まれてしまっていた。
`associate`は例外と書いたがテストデータに関してはさまざまな状態を考慮したいのでこの場合は少し違うのかなと思う。

最終的に↓の状態から変更を行った。本来は`trait`などを用いて状態を明示的にするべきだと思うのだけど今回はそこまでする必要性がない&そもそも使用箇所が多いところだったので暫定対応として実装を行った。
元のコードが悪いといえば悪いのだけどまあすでに書かれてコミットされている状態でその話をしても意味ないので私はこうしましたよという感じです。


```ruby
# 元のコード
factory :shop do
  name: 'お店の名前'
  after(:create) do |shop|
    FactoryBot.create :staff, shop: shop
  end
end
```

```ruby
# 変更したコード
factory :shop do
  name: 'お店の名前'
  association :staff
end
```

### 教訓

FactoryBotでコールバック使われてたら別の方法で書き直せないか？あるいは本当にそのコールバックが漏れなく実行されなければいけないかを検討するほうがよい。
モデルだけじゃなくてテストデータの作成でも気をつけましょうね。
python でchromedriver使ってスクレイピング

#環境
- macos Sierra ver.10.12.6
- chrome ver.78.0.3904.97

#やりたいこと
スクレイピング対策されているweb記事のスクレイピングの為に
pythonでchrome driverをheadlessで使い、スクレイピングしたい
#前提知識
1. ブラウザのdriverについて
要は、ブラウザをGUIではなく、CUIで扱う為に必要なツールってことみたいです。

2. DNSサーバーとlocalのhostsの関係
私たちがブラウザでドメイン名からアクセスすると、DNSサーバーにその情報を聞いて、IPアドレスとして帰ってきてPCはそれを使ってWEBサイトにアクセスして、ブラウザでサイトが表示されます。
しかし、MacのhostsファイルにドメインとIPアドレスの紐付けを行って置くと、DNSサーバーに接続せずにIPアドレスを取ってくることができます。

参考記事
[SeleniumとGoogle Spreadsheets(4) 「Chrome Driverを使いはじめるまで編](https://bitwave.showcase-tv.com/selenium%E3%81%A8google-spreadsheets4-%E3%80%8Cchrome-driver%E3%82%92%E4%BD%BF%E3%81%84%E3%81%AF%E3%81%98%E3%82%81%E3%82%8B%E3%81%BE%E3%81%A7%E7%B7%A8%E3%80%8D/)
DNSサーバーについてはこの記事、
[【図解】DNSサーバーとは？設定・変更と確認方法](https://www.kagoya.jp/howto/rentalserver/dns-server/)
hostsファイルについてはこの記事がおすすめです。
[Macでhostsファイルを書き換え・編集する方法！反映されないときはどうすれば？](https://aprico-media.com/posts/1392)

#前準備
##hostsファイルの中身確認
ファイルを開きます。

```
$sudo vi /etc/hosts
```

次にhostsファイルの中身がこのようになっていることを確認。

```
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting.  Do not change this entry.
##
127.0.0.1       localhost
255.255.255.255 broadcasthost
::1             localhost
```

あとseleniumのサイトからアプリケーションに入っているchromeのバージョンと同じバージョンのdriverをインストールしましょう。(私の場合は78.0.3904.97でした。)
[ChromeDriver - WebDriver for Chrome](https://chromedriver.chromium.org/downloads)

#ソースコード

```python
# -*- coding:utf-8 -*-
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
if __name__ == '__main__':
    base = "スクレイピングしたサイトのurl"
    options = Options()
    #headless指定
    options.add_argument('--headless')
    driver = webdriver.Chrome(executable_path='chrome driverがあるディレクトリの絶対パス', chrome_options=options)
    driver.get(url)
    #エンコード
    html = driver.page_source.encode('utf-8')
    #インスタンス化
    soup = BeautifulSoup(html, 'html.parser')
```

普段はurllib.requestを使っているのですが
スクレイピング対策しているサイトにはこのseleniumを使うようにすると解決できるかもしれません
！