OmniAICreator/Qiita-1.07M huggingface dataset:
コロナワクチン予約システムに自動ログインして予約可能会場があったら音を鳴らす

#ログインしてチェックボックスにチェックを入れるだけの簡単なコード
- こんなURLの自治体じゃないと対応してないと思います
  - https://vaccines.sciseed.jp/${市とか区が入るっぽい}
  - [澁谷だとこんな感じの予約サイト](https://vaccines.sciseed.jp/shibuya/login)
    - これをurl1に入れてね 
    
- 終了したら予約画面になるので頑張って予約確保してください 


##コード

```python
import time
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import chromedriver_binary

# 接種券番号とか
account = ''
password = ''
# 自治体によってURLが違う
url1 = ''
url2 = f'{url1}department/search'

def login_kakunin():
    driver.get(url1)
    time.sleep(5)
    # login
    id = driver.find_elements_by_class_name("validate-input_input")
    id[0].send_keys(account)
    id[1].send_keys(password)
    chk = driver.find_element_by_xpath("//input[@type='checkbox']")
    chk.click()
    btn = driver.find_element_by_xpath("//button[@type='submit']")
    btn.click()
    iftxt = ""
    while iftxt == "":
        # 接種会場
        driver.get(url2)
        time.sleep(5)
        chk = driver.find_element_by_xpath("//input[@type='checkbox']")
        chk.click()
        time.sleep(5)
        ifText = driver.find_element_by_class_name(
            "page-department-search_nav-header__count")
        if ifText.text == "会場表示: 0件":
            print("空いている会場なし")
            time.sleep(5)
        else:
            iftxt = ifText.text
            print("空いてる会場あり")
   
driver = webdriver.Chrome()

login_kakunin()
```

##実行
- 他に方法いくらでもあると思うけど思いついたのだけ

### Win

- else句に入れて音をならす

```python
import winsound
winsound.beep(800, 1000)
```

## Mac

- シェルで処理する

```bash
python hoge.py; say Done
```
アローダイアグラム

最早開始日
前の作業が終わって、その作業を最も早く始められる日

最早終了日
最も早く完了する日
つまり、<b>最早開始日+１</b>


最遅開始日
後続作業に影響せず最も遅く作業を始められる日
(遅くとも開始しなければいけない日)

最遅終了日
最も遅く作業を終える日
(遅くとも終了しなければならない日)
ARM MacへのTensorflow のインストール 


* 2022/4/14 ソース元記事の内容に合わせてコマンド等を2.6用に更新しました．
下記のApple公式の手順にしたがい， TensorFlow v2.6 と tensorflow-metal PluggableDevice　をARM mac (M1プロセッサ以降搭載のmac)にインストールし，GPUを利用してtensorflowを動かせるようにします．


https://developer.apple.com/metal/tensorflow-plugin/

## Step 1: 環境のセットアップ

### Miniforge
Miniforgeのインストーラをダウンロードして実行する．

https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-MacOSX-arm64.sh

```sh
chmod +x ~/Downloads/Miniforge3-MacOSX-arm64.sh
sh ~/Downloads/Miniforge3-MacOSX-arm64.sh
source ~/miniforge3/bin/activate
```
1行目は実行権限の追加．2行目でインストーラスクリプトを実行しインストール．3行目の代わりに端末を閉じて新規に開いても良い．
MiniforgeはAnacondaのオープンソース版で，多くのCPUへの対応を行っているパッケージ．詳しくは下記．

https://github.com/conda-forge/miniforge/

### Tensorflowが依存するパッケージのインストール

新しい環境を作る（好みで)

```sh
conda create -n tf26
conda activate tf26
```
依存パッケージのインストール

```sh
conda install -c apple tensorflow-deps==2.6.0
```

pyothon, pip, numpy, scipy等がインストールされる．他に必要なパッケージ(matplotlibなど)は後から追加する．

## Step 2: Tensorflow本体のインストール

`tensorflow-macos` と指定することに注意．

```sh
python -m pip install tensorflow-macos
```

## Step 3:  tensorflow-metal plugin のインストール

```sh
python -m pip install tensorflow-metal
```

後はcondaを使ってmatplotlibやjupyter, pandas など各々が必要なものをインストールすればよい．
ADR: 自サーバの死活監視をする

Date: 2021-09-01
Status: implemented

# Context
上流からグローバルIPアドレスが動的に割り当てられる WiFi ルーターにぶら下げた Raspberry Pi にポートマッピングしてサーバを運用している。

グローバルIPをDNSのAレコードに登録して https://x.optgeo.org/hrlulc として運用しているところ、グローバルIPアドレスが変動してサービスにアクセスできなくなる可能性があるので、簡単に死活監視を書きたい。

# Decision
`curl` と Slack の incoming webhook を用いて、使い捨てに近い死活監視スクリプトを作り、`cron`で定期的に実行する。

[スクリプト](https://github.com/optgeo/x-health-check/blob/main/health-check.rb)は次の通り。

```ruby
#!/usr/bin/env ruby
require 'time'
DST = "https://hooks.slack.com/services/----/----/-----------" # incoming webhook
SRC = "https://x.optgeo.org/hrlulc/index.html"

msg = `curl -o /dev/null -s -w %{http_code} #{SRC}`
msg = "#{Time.now.iso8601} #{msg}"
system <<-EOS
  curl -X POST -H 'Content-type: application/json' --data '{"text":"#{msg}"}' #{DST}
EOS
```

# Consequences
定期的に Slack にステータスが投稿されることを確認できている。

次のレベルでは、単に死活監視するのではなく、DNS Aレコードを書き換えて dynamic DNS っぽく運用できるようにした方が良い。
JSTL の使用手順を易しく解説

# 自主学習エンジニアがJSTLを使用するにあたって
Eclipseとかもそうですが
パソコンに疎い人間にはインストール方法でさえ、英語多いし何かとめんどくさいことが多いと感じました...
今回、JSTLを導入するにあたって少し手間取ってしまいました。
#####図を用いた解説し、わかりやすい記載となるよう心掛けてますので、参考になれば幸いです。

## JSTLとは
JSTLは「JSP Standard Tag Library」の略で、JSP内でよく使われる機能をタグライブラリとしてまとめたもの

## インストール手順
JSTLをインストールするには、2つの異なるJARをダウンロードします。
・Maven RepositoryのJSTL-APIダウンロード先
https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl-api/1.2 
![pic2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556334/9914e709-5045-b463-df53-cd22b0647bd7.png)
ダウンロードの記載がないので混乱してしまいましたが、fileのjarをクリックするとダウンロードができました

・Maven RepositoryのJSTL実装ダウンロード先
![pic1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556334/28b375bb-5e4c-926d-3275-ede23d52799e.png)
JSTL-APIのダウンロード同様の個所を選択します

####なお、Microsoft Edge バージョン 92.0.902.84 (公式ビルド) (64 ビット)ではブロックされてしまう場合があるため、他のブラウザで行ってください。（私はGoogleを使用してダウンロードができました。）

## JARファイルの配置手順
ダウンロードしたJARファイルをプロジェクトの以下に位置します。ドラックアンドドロップで可能です。
WebContent/WEB-INF/lib
![pic3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556334/4b915c93-7130-01ef-6979-7e7da88368f8.png)
次に、ファイルをコピーするを選択しOKをクリックします。
![pic4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556334/e307d896-d02e-4dd4-8450-ffd50ddfc463.png)
完了画面がこちらです
![pic5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556334/551e9bb4-54a7-fb61-0abc-75198dc8d7e7.png)

導入自体は難しくないのですが、ダウンロード先でどこでダウンロードできるか非常にわかりにくかったので記事にしました。

ご覧頂きありがとうございました、以上です。
【Laravel】入力フォームの値の複合バリデーション

## やりたいこと

* Laravel で 生年月日が 年、月、日でバラバラにPOSTされるケース。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21391/c030e098-1eef-1b5e-21fc-38081dc1d38e.png)

* 以下のように、単純にバリデーションすると 日付として成立しているかの検証ができない。
* 年、月、日 を 合わせて、日付として成立しているか評価したい！


```php:example
// リクエスト例
request()->birthday_year;
request()->birthday_month;
request()->birthday_day;

// それぞれバリデーションする場合
'birthday_year' => 'required|integer|date_format:Y',
'birthday_month' => 'required|between:1,12',
'birthday_day' => 'required|between:1,31',
```



## 方法

* `withValidator()` を使うと、通常のバリデーションルールを通過したあとに、柔軟にルール追加ができた。
* `$this->input('birthday_xxx')` のように項目ごとに入力内容が取得できるので、`checkdate()` で 日付として成立しているか評価する。
* `$validator->errors()->add($key, $message)` で、 特定のキーに対して、エラーメッセージを追加することが可能

```php:BirthdayRequest.php
<?php

namespace App\Http\Requests;

use App\Http\Requests\Request;

class BirthdayRequest extends Request
{
    protected $rules = [
        'birthday_year' => 'required|integer|date_format:Y',
        'birthday_month' => 'required|between:1,12',
        'birthday_day' => 'required|between:1,31',
    ];

    protected function withValidator($validator): void
    {
        $validator->after(function ($validator) {
            if (!checkdate($this->input('birthday_month'), $this->input('birthday_day'), $this->input('birthday_year'))) {
                $validator->errors()->add('birthday_day', '正しい日付を入力してください');
            }
        });
    }
}
```





## あとがき
* 詳しくは...
    * https://readouble.com/laravel/8.x/ja/validation.html
    * フォームリクエストへのAfterフックを追加
*  `withValidator()` 使わなくても、デフォルトのバリデーションルールだけで、できると嬉しいな。(パット見なさそう？)
* Laravel5.5 あたりから、 `withValidator()` ありそうです。
DOMについて

DOMとは、HTMLとJSをつなぐAPIのことをいう。
JSからHTMLを書き換えるときなどにこのAPIを使うことによって変更が可能になる。
ツリー構造になっており、プログラミング言語からHTMLを扱う仕組みのこと。
ツリー構造自体でも、ツリー構造を形成している仕組みのこと。
Netlifyで公開しているSPAアプリにGoogle Analyticsを導入する方法

Netlifyで公開しているSPAアプリにGoogle Analyticsを導入したので、そのときのメモです。
今回の方法では、以下のような人にはおすすめかと思います。

- ページごとの統計は不要でサイトにアクセスされた情報が取得できれば良い
- 既にサイトは公開されていてソースの修正は面倒くさい
- 自分のトラッキングIDを埋め込みたくない

# その方法とは
NetlifyのSnippet Injectionを使う方法です。
Snippet Injectionについては以下の公式サイトを参照していただきたいですが、簡単に言うと`<head>`タグもしくは`<body>`タグ内に、Netlify上で`<script>`タグを埋め込める機能です。

https://docs.netlify.com/site-deploys/post-processing/snippet-injection/

# やり方
※事前にGoogle Analyticsの設定等は済ませておいてください。

Site settings > Build & Deploy > Post processingに遷移します。
![image1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123678/d666c9a0-96bb-be98-6c7a-f601e7b3256c.png)

`Add snippet`を選択すると入力欄が出てくるので、`Insert before </head>`を選択します。
Script Name欄にGAなど適当な名前を入力します。
そして、HTML欄にGoogle Analyticsで設定した、以下のようなグローバル サイトタグ（gtag.js）をコピペしSaveするだけです。

```html
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'G-XXXXXXXXXX');
</script>
```

# 終わりに
設定したあとに、サイトを表示してGoogle Analyticsを見てもカウントされていなかったので、正しく設定できていないのかと戸惑いましたが、プライベートモードでサイトを表示したとこを無事カウントされていました。
SPAだとページごとの細かい設定は取れませんがデフォルトでも色々取得できるので、まだ導入していない方は是非導入してみては！
Jupyter Labで起きた「code editor out of sync」エラーの解決

#結論
VSCodeで編集したipynbファイルをJupyterLabで編集しようとしたのが問題．
VSCodeでテキストエディタ―を用いてファイルを開いたら「\r\n」を全て「\n」に置換しましょう．
今後VSCodeでの行末文字を\nにすれば同じ問題は起きないと思います．多分．

#なんで起きたか
今まではipynbの編集をVSCodeで行っていたものの，突如VSCodeが鬼のように重くなり使い物にならなくなったためとりあえずJupyterLabに避難．その後編集中にタイトルのような「code editor out of sync」というエラーが表示され始めた．

本当はVSCodeが重たいのをどうにかしたいけどどうにも治らないのでしばらくJupyterLabで我慢します．

#参考サイト
[How can I fix a JupyterLab “Code Editor out of Sync” error message?](https://stackoverflow.com/questions/65673839/how-can-i-fix-a-jupyterlab-code-editor-out-of-sync-error-message)
WebpackerでHotReloadは動くが、コンパイル結果が反映されない 

# はじめに

最近は仕事でWebアプリケーションを作成しています。
本日もいつも通りWebページを作成し、Javascriptを書いたのですが、なぜかリロードしてもJavascriptが反応しませんでした。
色々調べたのですが、同じ現象の方がいなかったようなので、簡単にメモしていきます。

また、この解決に会社の上司の方が手助けをしてくれました。
タイトルも上司の方につけていただきました。

# 環境

- Docker Desktop for Windows
- WSL2
- VSCode

# 問題
Docker(WSL2)環境で以下の問題がいきなり発生しました。

ローカルとコンテナをマウントしている状態で、JavaScriptのファイルを編集しましたが、なぜか反映さません。

JavaScriptは`webpacker`のコンテナをDockerで立ち上げて管理しています。
JavaScriptを編集した後に保存(Ctrl+s)をすると、ホットリロードが働いていることはターミナルから確認ができます。

そして、ターミナルではCompling....と走っていました。

しかし、変更内容が反映していません。

久しぶりにJavaScriptを書き、以前はこのような事象にはなりませんでした。
また、最近Hyper-VからWSLに環境を変更したので、それが問題化と思いましたが先輩の環境でも同じ事象になりました。

おそらく何かしらの設定がおかしいようでした。
また、時々コンテナの立ち上げの問題でWebページのスタイルがつかないことがあるのですが、今回は`F5`でリロードしてもスタイルがつくことがありませんでした。

始めにスタイルがついていないとそれ以降はつくことはありませんでした。

# 解決方法

以下の記事を確認して解決できました。

[[Rails] Webpacker の使い方](https://noknow.info/it/ruby/rails/how_to_use_webpacker?lang=ja)

webpacker/development.ymlの以下の箇所が問題になっていました。

```webpack.yml
# developmet
cache_manifest: true
```

この設定をいつ増やしたのかは忘れてしまいましたが、何かあって追加したのでしょう。
`cache_manifest`を`true`にすると初めにコンパイルした内容がCacheとして保存されるためそれ以降の変更が効かなくなります。これが原因でJavaScriptが反映されていませんでした。


以下のように修正します。

```webpack.yml
# development
cache_manifest: false
```

また、該当行を削除することで、デフォルトの`false`に設定されます。行ごと削除したほうがよいです。

# おわりに

かなり沼ってしまい、時間がかかってしまいました。
とりあえず原因特定としては別の環境で同じことを確かめたほうがいいと思いました。

詳細にコードを載せたいところでしたが手元に環境がないためメモ程度にまとめてみました。
明日からやっと仕事が再開できます。先輩ありがとうございました。


# 参考
- [[Rails] Webpacker の使い方](https://noknow.info/it/ruby/rails/how_to_use_webpacker?lang=ja)
Ubuntu 20.04 で imaxima を動かす方法



wxMaxima も悪くないのですが、やはり Emacs の方が使い慣れています。Emacs 上で綺麗な数式表示を見るには imaxima を使えばよいそうなのですが、手元の Ubuntu 20.04 ではうまく動きませんでした。

調べたところ、imaxima.el を修正すれば Ubuntu 20.04 でも動くという情報を見つけたので記録しておきます。

手順
----

1. maxima-emacs をインストールします。
    
    ```shell
$ apt-get -y install texlive texlive-science maxima maxima-emacs
    ```
2. /usr/share/emacs/site-lisp/maxima/imaxima.el があるので、ホームディレクトリの下の適当なディレクトリにコピーします。
    当方の場合は ~/.emacs.d/maxima/ というディレクトリを作ってその下にコピーしました：
    
    ```shell
$ mkdir ~/.emacs.d/maxima
$ cp /usr/share/emacs/site-lisp/maxima/imaxima.el ~/.emacs.d/maxima/
    ```
3. flexisym の前に amsmath をロードするように、コピーしたファイルを修正します:
    
    ```diff
--- /usr/share/emacs/site-lisp/maxima/imaxima.el	2020-02-21 06:13:41.000000000 +0900
+++ /home/xxx/.emacs.d/maxima/imaxima.el	2021-09-01 20:25:38.507329964 +0900
@@ -827,6 +827,7 @@
      imaxima-latex-preamble
      "\\usepackage{color}\n"
      "\\usepackage{exscale}\n"
+     "\\usepackage{amsmath}\n"
      "\\usepackage[cmbase]{flexisym}\n"
      "\\usepackage{breqn}\n"
      "\\setkeys{breqn}{compact}\n"
    ```
4. 修正した imaxima.el を読み込むように、コピー先ディレクトリを Emacs ロードパスに追加します。
    例えば、以下のようなものを init.el などに追加します：
    
    ```elisp
(setq load-path 
      (append (list (concat (getenv "HOME") "/.emacs.d/maxima"))
			  load-path))
    ```
5. Emacs を再起動して imaxima を動かし、$\LaTeX$ で整形された数式が表示されれば完了です。


参考にした文書
------------

https://otoomet.github.io/imaxima-ubuntu20.html
AthenaでWAFログからHTTP headerを取得しJWTの内容も取得する

## 前提

#### WAF のログを Kinesis Data Firehose 経由で S3 に記録していること

https://aws.amazon.com/jp/premiumsupport/knowledge-center/waf-configure-comprehensive-logging/

#### Athena に WAF ログのテーブルを作成ずみであること

https://docs.aws.amazon.com/ja_jp/athena/latest/ug/waf-logs.html

まとめると、大体ここらへん

https://dev.classmethod.jp/articles/waf-athena-excel/

## HTTP headerの内容を取得したい

Stack Overflowの記事の様に、`UNNEST`と`MAP_AGG`で、`header['name'] = value`で扱える様にする。

https://stackoverflow.com/questions/68455939/searching-athena-aws-waf-logs-by-http-header

例えば、`header['user-agent']`でUser-Agentが取得できる

## JWTをデコードし内容を取得したい

Amazon Athena は [Presto](https://prestodb.io/)/[Trino](https://trino.io/) (Presto SQL is now Trino) ベースなので、 Trino の Issue に SQL で JWT アクセスしたいというのがあがってる。JWT自体をデコードする関数等はないが、とりあえず次の方法で取得できる（暗号化されてないもの)

1. `Authorization`ヘッダーから`Bearer `を[削除し](https://prestodb.io/docs/current/functions/string.html#replace)てJWTだけにする
1. ドットをデリミタとして分割してペイロード部分を[抜き出し](https://prestodb.io/docs/current/functions/string.html#split)
1. [Base64デコードし](https://prestodb.io/docs/current/functions/binary.html#from_base64)
1. [UTF-8文字列化し](https://prestodb.io/docs/current/functions/string.html#from_utf8)
1. [JSONとして返す](https://prestodb.io/docs/current/functions/json.html#json_parse)
1. [JSONPath](https://prestodb.io/docs/current/functions/json.html#json_extract)で目的の値を取り出し（例: subクレーム=ユーザーの一意識別子)
1. JSONから文字列にキャスト

https://github.com/trinodb/trino/issues/2643

## クエリー例

### SQL例

`LOWER(f.name)`なのはクライアント実装によって異なるってのもあるけど、なぜかWAFのログ上同じブラウザーでも`User-Agent`だったり`user-agent`だったり(原因は追及してない)なので同一で扱うため。

```sql
WITH access_log AS (
  SELECT
    timestamp,
    action,
    httprequest.clientip,
    httprequest.country,
    MAP_AGG(LOWER(f.name), f.value) AS header
  FROM waf_logs,
  UNNEST(httprequest.headers) AS t(f)
  GROUP BY 1, 2, 3, 4
)
SELECT
  FROM_UNIXTIME(timestamp/1000) AS timestamp,
  header['user-agent'] AS ua,
  CAST(
    JSON_EXTRACT(
      JSON_PARSE(
        FROM_UTF8(
          FROM_BASE64(
            SPLIT_PART(REPLACE(header['authorization'], 'Bearer '), '.', 2)
          )
        )
      ),
      '$.sub'
    )
    AS VARCHAR
  ) AS subject
FROM access_log;
```
### 結果例

|timestamp|ua|subject|
|-----------------------|-----|---|
|2021-09-01 01:23:45.000|Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36|248289761001|
PodmanでGUIアプリを起動させる

# はじめに
DockerでGUIアプリを立ち上げる記事があるがPodmanでやった記事がなかったので、
実行できるか試してみる。

# Dockerfileについて
以下のDockerfileを作成して、xtermがインストールしたコンテナを作成します。

```Dockerfile
FROM debian:8.6

RUN apt-get update
RUN apt-get install xterm -y

CMD ["/bin/bash"]
```

以下のコマンドでビルド

```bash
podman build -t debian-xterm .
```

# 起動
以下のコマンドを実行するとxtermのGUIが起動する。

```bash
podman run -it --rm -e DISPLAY=${DISPLAY} -v /tmp/.X11-unix:/tmp/.X11-unix localhost/debian-xterm xterm
```

起動すると以下のような図が表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425374/a10fada7-cbcc-68eb-a5cb-0b0e6ac90b1b.png)

特定ユーザでGUIアプリを立ち上げたい場合は以下のコマンドを実行する。

```bash
sudo podman run -it --rm -e DISPLAY=${DISPLAY} -v /tmp/.X11-unix:/tmp/.X11-unix -u 1000 localhost/debian-xterm xterm
```


Podmanの特徴として、作成したり、pullを行ったコンテナをユーザごとに独立しているため
Dockerのように同じPCないならば、どのユーザも同じように使えないため、
RootユーザでPodmanを実行する場合はRootユーザでコンテナを作成する。

# まとめ

一応、GUIアプリを立ち上げることは可能であることを確認した。
今後は、トランプゲームがコンテナで動いて遊べることを確認したい
[Ruby] AtCoder過去問　B - Card Game for Two

##はじめに
AtCoderのB問題をRubyで解いて見ました。
いろんな考え方や書き方が自分の中でもたくさんあって、どの書き方を記事にしようか迷いましたが、一番自分がわかりやすいコードを載せることにしました！

よろしくお願いします。

問題は以下から確認してください。

https://atcoder.jp/contests/abc088/tasks/abc088_b


## B - Card Game for Two

まずは入力受け取りの記述を書きます。

```ruby
n = gets.to_i
points = gets.split.map(&:to_i)
```

続きまして、2行目で受け取った配列の順番を後々、処理がしやすいように降順に並べ替えます。
sort.reverseを使います。この使い方は以前記事にしていますのでそちらも見ていただければと思います。↓

https://qiita.com/minhee/items/c5897831ed718ee6011b

こちら、破壊的メソッドではないのでもう一度pointsに入れ直すような書き方をしておきます。
これで配列の先頭から数字が大きい順に並んでいます。つまりAliceとBob達は最善のカード取っていくので配列の先頭からとっていくことになります。

```ruby
n = gets.to_i
points = gets.split.map(&:to_i)
points = points.sort.reverse
```

次にAliceとBobのポイントを用意します。
そのあと、繰り返し処理を行うのでcountも用意しておきます。

```ruby
n = gets.to_i
points = gets.split.map(&:to_i)

points = points.sort.reverse

alice = 0
bob = 0
count = 0
```

ここからはtimesメソッドを使ってn回処理を行なっていきます。（n枚のカードしか存在しないので）

```ruby
n = gets.to_i
points = gets.split.map(&:to_i)

points = points.sort.reverse
alice = 0
bob = 0
count = 0

n.times do
  if count == 0 || count % 2 == 0
    alice += points.shift
  elsif count == 1 || count % 2 == 1
    bob += points.shift
  end
  count += 1
end
```

このような繰り返し処理をします。
最初のif文の```if count == 0 || count % 2 == 0```はcountが０または偶数のときに実行させる条件分岐の条件式です。

その中の```alice += points.shift```ですが、このshiftメソッドがキーとなります。
これは配列の先頭を取り出して、削除してくれます。

つまりここで行なっている処理は、今存在するカードの中から最も大きい数を取り出してAliceのポイントに加算した後、配列pointsからは削除されます。

elsif以下の処理は、Bob版の処理ということになります。Aliceの時と同じです。

最後にAliceからBobのポイントを引いたものを出力すれば完成です。

```ruby
n = gets.to_i
points = gets.split.map(&:to_i)

points = points.sort.reverse

alice = 0
bob = 0
count = 0

n.times do
  if count == 0 || count % 2 == 0
    alice += points.shift
  elsif count == 1 || count % 2 == 1
    bob += points.shift
  end
  count += 1
end

puts alice - bob
```
マウンター=完璧主義者。現実、不完全だからこそ、互いにフォローするべきでは？

# ソフトウェア界隈のマウンター

「～であるべき！」、「～していないのはおかしい！」

分かります。おっしゃるとおりです。
でも、世の中、そんな論理で動いてないです。

得ている知識もまばら、専門分野も違う。

あなたの世界が、すべての世界ではない。
それなのに、「俺知っている事、世界の常識、知らないやつは、バカで愚民」
みたいなマウントとられても、受け手によっては困ります。

ただ、「求められるべき水準」はあると思います。
そこにギャップがある他者がいたとき、どう振る舞うのか？
チーム内でいたら、フォローするのが「人」の対応でしょう。


# 完璧は求められるべき、でも、現実は違う。

ネットの世界は、知識偏重のきらいはあります。
けれど、人の経歴、専門によっては、知らないことも当然あります。

知ってて当たり前という認識も、理解はできますが、
現実的には、そうもいきません。

千差万別。経歴、守備範囲。

一人で仕事してるなら、その人が完璧であるべきかもしれません。

でも、多くは、チームでしています。
それは、単純に作業分担をするために、チームであることもありますが、
現実的な意味では、異なるスキル、経験を前提にしています。

つまり、足らない部分は互いに補完すればいいわけです。
マウントとる意味なんてないわけです。

相手が足りないなら、それをあなたが補えばいいわけです。


# チームプレーでシステムは作られる

業務システムなんて、一人で完結するのは不可能に近いです。
チームでしかつくれません。

長い年月、すべての機能を一人でつくれますか？
無理です。
ていうか、作っているとすれば、よほど小規模でしょう。
でも、その人に依存している事自体、リスクなわけです。

いろんな立場の人が、引き継いでいけるシステムこそ、
リスク分散ができているシステムです。

チームで作るシステムは当たり前といっても過言ではないでしょう。

であれば、チームメイトに不足があれば、知っている人が補ってあげる。
それは当然のことです。

それができない人、チームは普通に考えておかしいと思います。

すべての人間が完璧であることは望ましいことかもしれませんが、
現実は違います。

だからこそ、互いを補っていくべきだと思います。
その補う過程を通じて、チームが完璧になればいいと思います。
AWS ローカルPCからEC2にファイルをデプロイ

ローカルのPC上からAWSのEC2にファイルをデプロイする

##大まかな手順
* パブリックサブネットにEC2を配置する
[WEBサーバー用EC2の起動からWEBページの表示まで](https://qiita.com/ebtiag/items/c75140c59d59a620f89e)
* EC2に「git」をインストール
[AWS EC2 AmazonLinux2 Gitをインストールする - Qiita](https://qiita.com/miriwo/items/8d5b35950232c1126d36#%E8%A9%B3%E7%B4%B0)
* githubのアカウント登録をし、空のリポジトリを作成する
* githubのリポジトリにローカルのファイルをpushする
（ローカルのファイルをコピーしてネット上に配備する）
* Tera TermでEC2インスタンスSSH接続を行う
* ```git clone [リポジトリURL]``` で対象のリポジトリをダウンロードする

#参考
Git hubで、リポジトリ画面右の「Code」をクリックすると、
対象リポジトリのURLが表示される
M5Stack Core2: UDP 送信

M5Stack Core2 で JSON データを UDP で送信する方法です。

```text:udp_test/udp_test.ino
// ---------------------------------------------------------------
/*
	udp_test.ino

						Sep/01/2021
*/
// ---------------------------------------------------------------
#include <M5Core2.h>
#include <WiFiMulti.h>
#include <WiFiUdp.h>
#include <ArduinoJson.h>

const char *ssid = "some-ssid";
const char *password = "some-password";

const char *udpAddress = "192.168.1.8";
const int udpPort = 8092;

WiFiUDP udp;
int count = 0;

WiFiMulti wifiMulti;

float tt_aa[] = {20.1, 22.3, 24.8, 25.6, 26.7, 26.1, 26.2, 25.3, 24.8, 23.6, 22.7, 22.0, 21.5, 20.9, 20.7, 20.3};
float hh_aa[] = {50.2, 62.4, 64.8, 75.6, 76.7, 75.9, 74.3, 72.3, 64.6, 60.5, 56.2, 53.2, 51.8, 51.2, 50.9, 50.4};
// ---------------------------------------------------------------
void setup()
{
	M5.begin();
	delay(2000);
	Serial.println("*** setup *** aaa ***");
	delay(1000);

	wifiMulti.addAP(ssid, password);
	M5.Lcd.print("\nConnecting Wifi...\n");
        Serial.println("*** setup *** end ***");
}

// ---------------------------------------------------------------
void loop()
{
	Serial.println("*** loop *** " + String(count));
	if((wifiMulti.run() == WL_CONNECTED))
		{
		Serial.println("*** connected *** ");
		udp_out_proc();
		}

	delay(10000);
	count++;
}

// ---------------------------------------------------------------
void udp_out_proc()
{
	DynamicJsonDocument doc(128);
	char data_json[128];

	udp.beginPacket(udpAddress,udpPort);

	int jt = count % 16;
	float temp = tt_aa[jt];
	float humi = hh_aa[jt];
	doc["name"] = "aaa";
	doc["count"] = count;
        doc["temperature"] = temp;
        doc["humidity"] = humi;
	serializeJson(doc, data_json);

	udp.printf(data_json);
	udp.endPacket();

	Serial.println(data_json);
}

// ---------------------------------------------------------------
```

受信確認をするプログラムはこちら
[Python3: UDP を受信](https://qiita.com/ekzemplaro/items/4d65001547ec8825479e)
httpdイメージに指定されているコマンド「httpd-foreground」って何だ

apache(httpdデーモン)の起動はserviceコマンドやsystemctlコマンドで起動する事が多いと思いますが`docker container ls`でhttpdイメージのCOMMANDの欄を見た時にhttpd-foregroundが指定されていてこれ何だろうと思ったので調べてみました。

大前提としてコンテナはCMDコマンドやENTRYPOINTコマンドで指定したコマンドが終了したらコンテナ自体も終了する仕組みです(下記の記事が分かりやすかったです)
参考:https://architecting.hateblo.jp/entry/2020/08/13/153842

## 結論：`httpd -DFOREGROUND`コマンドを実行する事によってhttpdデーモンをフォアグラウンドで起動している。

実際にhttpdイメージのリポジトリを見ていきます。

https://github.com/docker-library/httpd

httpdイメージのdockerfileのCMDコマンドがこの様な指定されていました。

```docker
~省略~
COPY httpd-foreground /usr/local/bin/

EXPOSE 80
CMD ["httpd-foreground"]
```

COPYコマンドでhttpd-foregroundが/usr/local/bin/にコピーされています。CMDコマンドで指定されているhttpd-foregroundを見てみます。

```shell
#!/bin/sh
set -e

# Apache gets grumpy about PID files pre-existing
rm -f /usr/local/apache2/logs/httpd.pid

exec httpd -DFOREGROUND "$@"
```

`httpd -DFOREGROUND`が実行されています。これはhttpdデーモンをフォアグラウンドで起動する事を意味しています。

serviceコマンドを使うとバックグラウンドで実行した後serviceコマンド自体は終了する為コンテナも終了してしまいますが、この方法ならhttpdデーモンがフォアグランドで起動されてコンテナが終了しません。





## 実際に試してみる

### httpd-foreground
まずは普通にapacheイメージを起動してみます

```docker
docker run -dit -p 8080:80 httpd:2.4
```

コンテナが起動しているか確認してみます

`docker conteiner ls`
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555286/b85a1ac6-5648-6258-63e0-f386ff9e795c.png" width="900px"/>

コンテナを起動して時間がたってもコンテナは起動したままです。

### service httpd start
次に先程のdocker run　コマンドに`service httpd start`コマンドを引数として渡してあげます。

```
docker run -dit -p 8080:80 httpd:2.4 service httpd start
```

コンテナを見てみます

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555286/ec875c43-235d-b5de-66ae-72c290d24b76.png" width="900px"/>

COMMANDの欄が`service httpd start`になっていてstatusがすぐにExitedになりました。serviceコマンドが終了したとほぼ同時にコンテナが停止しました。　

### おまけ

`-DFOREGROUND`オプションをつけずに`httpd`コマンドのみでコンテナを起動してみます

```
docker run -dit -p 8080:80 httpd:2.4 httpd
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555286/d49e8870-ab60-fb88-93d1-d5e9bceb2e2c.png" width="900px"/>

こちらもすぐにコンテナが終了しています


何か間違いなどがありました遠慮なくご指摘ください。
RのSave workspace image? [y/n/c]: y は何処へ？


RのSave workspace image? [y/n/c]でy（はい）とするとどこに保存されるのか気になったので調べてみました。

```:R
> q()
Save workspace image? [y/n/c]: 
```
y（はい）と答えた場合、
作業スペースの内容がRのworking directoryの .RData というファイルに保存され，次回の起動時に自動的に読み込まれる。y でも n でも，打ち込んだコマンドの履歴が作業ディレクトリの .Rhistory というファイルに入る。

```Terminal
% ls
% ls -a
.		..		.RData		.Rhistory
```
.RDataと.Rhistoryファイルは隠しファイルなので、通常は見えない。

MacのFinderで隠しファイルを表示するショートカットキーは
「command」＋「shift」＋「.」
これでFinderでも可視化することができる。

プロジェクトごとに異なる作業ディレクトリを指定すれば、ディレクトリごとに異なる .RData と .Rhistoryファイルが作成される。Rで読み込むと作業スペースに保存された作業内容が継続利用できるらしい。

##以下は覚書

y（はい） → 作業スペース（現在の状態）を保存して終了
n（いいえ） → 保存しないで終了
c（キャンセル） → 終了をキャンセルする（終了しない）

通常は n（いいえ）でOK.

####作業スペース .RData と履歴 .Rhistory の使い方
起動時に作業ディレクトリの作業スペース .RData と履歴 .Rhistory を読み込むと前回の状態が復元できる。

以上です。
【Unityメモ】The script don't inherit a native class that can manage a script.

Unity上で新しい C#スクリプトを作成し、オブジェクトにアタッチしようとしたら以下のエラーが出た。

```
The script don't inherit a native class that can manage a script.
```

調べると、スクリプト名とクラス名が一致していないことが原因とわかったが、何度確認しても二つが一致している。

```c#:Hoge.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Hoge : MonoBehaviour
{
    private void Start()
    {
        Debug.Log("Start");
    }
}
```

スクリプトの作り直しやアタッチし直しをしても治らず。

結果、全く別のスクリプトのエラー（セミコロンつけ忘れ）が原因だった。

エラーを読んでも修正箇所がわからなかったのでメモ。
[備忘録]フロント側の対応だけでNginxでキャッシュされた古い画像が表示されないようにする

Nginxで画像ファイルをキャッシュするようにしていたのですが、同じ名前で画像を更新した場合に古い画像がしばらく表示されてしまいます。
かといって、まれにしか更新されない画像のためにキャッシュを無効にするのもイケてないので、解決策を調べてみました。


# 結論

imgタグのsrcに`/path/image.jpg?xxxxx`のようにパスの後にランダムな値を指定する

※右クリックで「名前を付けて画像を保存」しても?以降は認識されません。


# 具体例

参考にした投稿だとランダム値を指定してましたが、それだと常にキャッシュがスルーされてしまうのでレコードの更新日時を指定することにしました。

サーバーから以下のようなテーブルのデータを取得して、imageUrlの後ろに更新日時を指定することで、同名のファイルで更新して画像ファイルのURLが同じだったとしても更新日時が異なるためキャッシュから読み込まれず、最新の画像を表示することができます。

論理名|物理名|型
--|--|--
id|ID|
画像URL|imageUrl|string
更新日時|updatedAt|string

```test.vue
<template>
  <div>
    <img :src="imageUrl" />
  </div>
</template>
<script lang="ts">
  item;
  get imageUrl() {
    // 更新時に新しい画像が表示されるようにするため、更新日時をファイル名の後ろに付与
    return `${this.item.imageUrl}?${moment(this.item.updatedAt).format('YYYYMMDDHHmmss')}`;
  }
```

ただ、これだと画像URL以外のカラムが更新された場合でも画像を読み直してしまうので、頻繁に更新するようなテーブルの場合は要検討ですね。


# 参考

https://stackoverflow.com/questions/126772/how-to-force-a-web-browser-not-to-cache-images
MT ページタイプによる分岐

忘れるからのメモ。

```html
<mt:IfWebsite><mt:Ignore> ===== 親サイト ===== </mt:Ignore>
  <mt:If name="main_index"><mt:Ignore> ===== 親サイトのメインページ ===== </mt:Ignore>
    <link rel="stylesheet" href="/css/parent_index.css">
  <mt:Elseif name="page_archive"><mt:Ignore> ===== 親サイトのウェブページ ===== </mt:Ignore>
    <link rel="stylesheet" href="/css/parent_page.css">
  <mt:Elseif name="entry_archive"><mt:Ignore> ===== 親サイトの記事 ===== </mt:Ignore>
    <link rel="stylesheet" href="/css/parent_entry.css">
  <mt:Elseif name="category_archive"><mt:Ignore> ===== 親サイトのカテゴリアーカイブ ===== </mt:Ignore>
    <link rel="stylesheet" href="/css/parent_category.css">
  <mt:Else><mt:Ignore> ===== 親サイトの上記以外のテンプレート ===== </mt:Ignore>
    <link rel="stylesheet" href="/css/parent_other.css">
  </mt:If>
<mt:Else><mt:Ignore> ===== 子サイト ===== </mt:Ignore>
  <mt:If name="main_index"><mt:Ignore> ===== 子サイトのメインページ ===== </mt:Ignore>
    <link rel="stylesheet" href="/css/child_index.css">
  <mt:Elseif name="page_archive"><mt:Ignore> ===== 子サイトのウェブページ ===== </mt:Ignore>
    <link rel="stylesheet" href="/css/child_page.css">
  <mt:Elseif name="entry_archive"><mt:Ignore> ===== 子サイトの記事 ===== </mt:Ignore>
    <link rel="stylesheet" href="/css/child_entry.css">
  <mt:Elseif name="category_archive"><mt:Ignore> ===== 子サイトのカテゴリアーカイブ ===== </mt:Ignore>
    <link rel="stylesheet" href="/css/child_category.css">
  <mt:Else><mt:Ignore> ===== 子サイトの上記以外のテンプレート ===== </mt:Ignore>
    <link rel="stylesheet" href="/css/child_other.css">
  </mt:If>
</mt:IfWebsite>
```

引用元：https://tadabi.tokyo/2021/mt-variable/
Githubにpushできなくなった

<h2>ポートフォリオ作成中に起きたことです。</h2>
この前までは普通にpushできていたのでびっくりしました。
また同じエラーに遭遇しても対処できるようにメモとして残します。

<h2>起こったこと</h2>
githubにてローカルの変更をリモートにプッシュしようとしたら、以下のエラー文が。

```
remote: Support for password authentication was removed on August 13, 2021. Please use a personal access token instead.
```
passwordとかremoveとか書いてあって焦りました。
気になっていろいろ調べてみたら似たような記事が結構出てました
参考にさせていただいた記事を貼っときます

https://qiita.com/isaatsu0131/items/4a134cc9b296c00e6751

<h1>対処</h1>
結果から言うとgithubのアクセスの方法が変わるみたいですね。
個人のアクセストークンが必要とのこと

ちなみに僕はMacでやってます
GitHubで
Settings → Developer settings → Personal access tokens　

generate tokenを押して、repoを選択します
ページ上部にnoteって欄があるのでそこに自分でわかりやすいワードを入れます

全て終わったらtokenを作って作成されたパスワードをキーチェーンに保存します。

Command⌘ + spaceキーでSpotlightを開き、キーチェーンアクセスに遷移します

検索窓でgithubと打ち、出てくる項目のインターネットパスワードと書いてある項目を開きます
![スクリーンショット 2021-09-01 19.51.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1541345/c0fc8dc0-3a5e-c845-7263-47afd16b04a1.png)

これですね
パスワードを表示を押すと、macのパスワードを入力するフィールドが出てきます。そこで入力するとパスワードが表示されます。
そのパスワードを消去して先ほど作成したトークンを貼り付けます。
これで完了です！
![スクリーンショット 2021-09-01 19.54.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1541345/5a6991e2-84fb-f9d3-2583-533b056e1c94.png)
試験するときにで便利なこと

試験するときに便利だったことまとめます。

##Google Chromeのシークレットウィンドウ
こちらは使用している方も多いのでは。
chromeを履歴や Cookie がまっさらの状態で使用できるので、
２ユーザでログインしたい場合などに便利です。
社内システムのようなシステムでは役職や部署などによって実行権限が異なることが多いかと思います。
そのような場合に動作を確認するのに、ログイン→実行→ログアウト→別ユーザでログインといった手順で
確認するのはかなりの手間になります。
違うブラウザでログインすれば同様のことができますが、
やはり同じブラウザで確認したいことも多いのでそういった場合に活用できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234640/9cf4c2b7-2890-dc59-624c-ea7aeb3644bb.png)




##権限者ごとのユーザ情報をまとめる
実際上記でもあるように、試験では様々な役職・部署の方で試験をしたい場合があるのですが、
多くなってくると頭では覚えてられないので、あると非常に助かりました。



#日付基準のバッチは引数で実行する
日付基準の処理は試験が難しいです。
DBの値を使用して処理している場合は、その値を変えるだけなので良いですが
システム日付を取得して処理するといったバッチも多いはず。
そういったプログラム内部で日付取得し、後続処理とすると
いざ試験するときに非常にやりにくくなります。
なので基本的にはバッチに引数として日付を渡してあげることで試験しやすくなります。
引数なしの場合は現在日を取得し、ありの場合そちらの日付が優先されるイメージです。
この辺りはテスト容易設計にもつながる？

```
LaravelのCommandクラスの場合、こんな感じになる
php artisan command:test 20210721
```

##正常系にもログ出力を埋め込む
よくあるパターンとして、プログラムで例外などの異常系が発生した場合にログを出力をする
という実装があると思います。
担当システムでもこの形で基本的には実装をしています。
ところがいざ実運用に入ってバグに悩まされた場合などには、調査用のログがあると調査が捗ります。
一旦リリースしてから調査用のログの埋め込むのは、コード変更・デプロイに結構工数がかかるので心理的な負担が重い。。。
今後は重要なユースケースやパフォーマンス面などで不安がある箇所などではログを入れてもよいかなと感じています。
具体的にはメソッドの開始、終了、DB処理、条件分岐周辺の部分にログ出力用のコードを埋め込んで
おくと便利そうです。
ただ、毎回処理ごとにログを吐くのは量が膨大になるため、ログレベルなどを活用し、
後から設定しだいで出す出さないで切り分けるのが良いかと思います。

```php
public function execute()
{
    Log::debug('処理開始');

    if ( $obj->isTest() ) {
        // 今は固定文字列ですが、周辺のObject情報を詰めても良さそう
        Log::info( '条件に入りました。' );
        return;
    }

    Log::debug('処理終了');
}
```
Algorithmためのデータ構造をPythonで実現しましょう。


Data Structureはいろいろありまして、それはどうやってPythonで実現できますかをシェアしていきます。
あまりにも多くて、これからどんどん更新していきたいと思っています。

今回はLinear Structureについて、(簡便のため今後LSと書きます。)

LSは簡単に言うと、電車や新幹線みたいな感じですね。また、LSには4種類に分けられて、
- Stack
- Queue
- Deque
- List
があります。今後一個一個で説明しますが、ざっくりって言うと、dataの増減方式が違います。どんなイメージというと、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1729963/3a13bfdd-c8ea-55ab-198d-83796494c22c.png)

例えば、あるデータがこのLSの頭からしか入れない、またはtailしか入れないなどがあります。

では、今回はStackというデータ構造、そしてpythonならどうやって実現するのかを説明します。

## Stackとは？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1729963/90110688-52df-5103-2076-54e0361bf7d0.png)

簡単に説明すると、最初から入ったデータは最後でしか取り出せない。図のように4が一番早くStackに入り、そしてdog, True,8.4はどんどん上に重ねていきます。取り出し場合は、最後に入れた8.4は最初に取り出します。ようするにLast In First Out (LIFO)のこと。雑ですが、こういう感じですね。

## じゃpythonならどうやってStackを実現できるでしょう。
pythonのlist objectでStackを実現します。

```python
class Stack(object):  
    def __init__(self):  
        self.items = []  
  
    def isEmpty(self):  
        return self.items == []  
  
    def push(self, item):  
        self.items.append(item)  
  
    def pop(self):  
        return self.items.pop()  
  
    def peek(self):  
        return self.items[len(self.items) - 1]  
  
    def size(self):  
        return len(self.items)  

```
StackはLS構造なので、新たな空なListを作って、一番右の要素は`head`とし、一番左の要素は`tail`とします。

`push`について、Stackは`head`しか入れないため、pythonのappendメソッドを採用します。

`pop`もそのままpython自分のメソッドを利用します。

その他のメソッドについて、Stackを利用した応用問題のために追加しましたものです。

## 応用問題：左カッコと右カッコののマッチ問題
ある`str`型`{()[]}`がありまして、左カッコと左カッコは一体マッチしているかどうかをチェックしてくれるプログラムを書きましょう。

答えは以下になります。[説明はまた後日で(多分:eyes:)]

```python
def check_quotation(symbol):  
    obj = Stack()  
    pos = 0  
    result = True  
    while pos < len(symbol) and result:  
        if symbol[pos] in '([{':  
            obj.push(symbol[pos])  
        else:  
            if obj.isEmpty():  
                result = False  
 
            else:  
                top = obj.pop()  
                if not match(top, symbol[pos]):  
                    result = False  
  
        pos += 1  
    if result and obj.isEmpty():  
        return True  
    else:  
        return False  
  
def match(s1, s2):  
    a_1 ='([{'  
 a_2 =')]}'  
 return a_1.index(s1) == a_2.index(s2)  
  
print(check_quotation('[][][][]{[]'))
```

次回はQueueについて更新していきたいと思っています。
では、最後まで見ていただき、ありがとうございました。
public private protected の違いを調べてみた。（備忘録）

##それぞれの違いを簡単にまとめてみる。
|メソッド|呼び出し可能範囲|
|------|-------------------------|
|public|クラス内外**どこからでも**呼び出し可能。|
|private|クラス、同じインスタンス内から**のみ**呼び出し可能。|
|protected|クラス、同じインスタンス内に**加え、**同じクラスの他のインスタンスからも呼び出し可能。|

rubyのデフォルトが、publicで他の二つとの違いは、わかりやすいのですが、他の２つ（privateとprotected）の違いがよくわからなかったので調べてみました。

##privateとprotectedの具体的な違いを調べてみた。

* private<br>privateメソッドを呼び出す時は、レシーバは指定**できない**。
* protected<br>protectedメソッドを呼び出す時は、レシーバは指定**できる**。

この***呼び出し時にレシーバを指定できるかできないかの違い***がこの２つを理解する**ポイント**になります。

:::note info
レシーバとは
レシーバーは特に Ruby の用語というわけではなく、オブジェクト指向一般に使われる用語です。
下記コードのrunメソッドを呼び出している、car1がレシーバーです。
:::
~~~ruby
class Car
 def run
  print run
 end
end

car1=Car.new
car1.run     #左側がレシーバー
~~~

参照：[rubyのレシーバとは](https://qiita.com/you8/items/e5f5c27cfed60a23fa75)

##具体的にprivateメソッドをコードで確認してみる
~~~ruby
class Sample1

  def s1_call_private
    s1_private    # 通常の呼び出し
  end

  def s1_call_private_with_receiver
    self.s1_private    # あえてレシーバ（self）を明示して指定
  end

  private

    def s1_private
      p "Welcome to my private room!"
    end

end

s1 = Sample1.new

s1.s1_call_private
=> "Welcome to my private room!"

s1.s1_call_private_with_receiver
=> NoMethodError: private method `s1_private' called for..
~~~
引用：[[Ruby] privateメソッドの本質とそれを理解するメリット](https://qiita.com/kidach1/items/055021ce42fe2a49fd66)

このように、privateメソッドは、呼び出し時にレシーバーを指定できないルールとなっています。
次に、protectedメソッドもコードで確認してみましょう。

##具体的にprotectedメソッドをコードで確認してみる
~~~ruby
class Sample2

  def s2_call_protected
    s2_protected   # 通常の呼び出し
  end

  def s2_call_protected_with_receiver
    self.s2_protected  # あえてレシーバ（self）を明示して指定
  end

  protected

    def s2_protected
      p "Welcome to my protected room!"
    end

end

s2 = Sample2.new

s2.s2_call_protected
=> "Welcome to my protected room!"

s2.s2_call_protected_with_receiver
=> "Welcome to my protected room!"
~~~
参照：[[Ruby] privateメソッドの本質とそれを理解するメリット](https://qiita.com/kidach1/items/055021ce42fe2a49fd66)

このように、protectedメソッドは、呼び出し時にレシーバーを指定できます。

##まとめ(public,private,protectedの使い分け）
1. どのレベルでメソッドを外部から隠蔽したいのか
1. 機能実装のために他のインスタンスを参照する必要があるのか

で使い分けをするのが良さそう。

* 他のクラスからもメソッドを使用したい場合は、publicメソッドを使う。

* 基本的にメソッドを定義したクラスやインスタンスでのみそのメソッドを使用したい場合は、privateメソッドを使う。

* 2項演算子の実装にその他のインスタンス（オブジェクト）の状態を参照する必要がある、もしくは、調べる必要があり、そのクラス内でのみメソッドを使用したい（他のクラスから隠蔽したい）場合は、protectedを使う。

##参照
* [Ruby の private と protected 。歴史と使い分け](https://qiita.com/tbpgr/items/6f1c0c7b77218f74c63e)
* [rubyのレシーバとは](https://qiita.com/you8/items/e5f5c27cfed60a23fa75)
* [[Ruby] privateメソッドの本質とそれを理解するメリット](https://qiita.com/kidach1/items/055021ce42fe2a49fd66)
* [Rubyのメーリングリストのやりとりより。](http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-list/7669)
CSharpZxScriptでbatファイルからの脱出

# はじめに
**心地よく書ける**C#スクリプトとして[CSharpZxScript](https://github.com/harayuu9/CSharpZxScript)を作ってみました。
dotnet tool経由で簡単に導入出来ます。

![image](https://user-images.githubusercontent.com/24310162/130572603-f13cf336-43c4-4e29-93ed-75b132e5718a.png)
![image](https://user-images.githubusercontent.com/24310162/130572747-50e37590-ac34-4ea6-a389-d78af796fb5a.png)

# 心地よく書ける
C#でスクリプトが書ける物で公式のcsxがありますがVisualStudioでコード補完が効きにくかったり書きにくいです。
そこで内部でこっそり.csproj を生成したりします。
C#9.0のTop Level Statementと[ProcessX](https://github.com/Cysharp/ProcessX)を組み合わせると中々良い感じに書けます。
デバッガーも繋げます。

# 動作環境

必要な環境は.NET5.0 (C#9.0 が必要なため) WindowsでもMacでもLinuxでも動きます。
CLIによる各種操作の実行
GUI操作での実行(Windowsのみ

# 導入方法

dotnet toolコマンドで導入を行います。

```
dotnet tool install --global CSharpZxScript
```

cszx コマンドが使えるようになります。
各種cszxコマンドは helpを見てください。
installをしてダブルクリックや右クリックメニューから動かせるようにします。

```
cszx install
```

消すときは cszx uninstall で消えます

# 使い方
.csファイルを右クリックしてEdit or Run します。
![image](https://user-images.githubusercontent.com/24310162/130572603-f13cf336-43c4-4e29-93ed-75b132e5718a.png)

.cszxに拡張子を変えるとダブルクリックで実行出来るようになります。
**ただし.cszxにしてしまうとコード補完が効かなくなり編集しにくいです**

コマンドからの起動は拡張子を明示しないほうがおすすめです。
編集時は.cs、Fixするときに.cszxとやりやすいので。
cszxスクリプトからcszxスクリプトを呼び出す時の面倒回避にもなります。

```
cszx test
```

# おわり
私のプロジェクトはCSharpZxScriptをインストールするbatファイル以外全て置き換えました。

本来の用途ではないんですが単純なアプリケーションをこいつで書くのが結構便利でした。
「FileServerとClientを両方Core.csproj参照してExe作っている」という状況があったのでスクリプト化するとスッキリしました。
初めてのproxmox～インストール編～

**実施日　2021年9月1日**

余っているPC(DELL optiplex 9020)にproxmoxVe7.0をインストールしたので、微妙にわかりにくかった点の備忘録です。基本的には公式のドキュメントとインストール時に表示される案内に従っておけばインストール出来ると思います。

## bootデバイスの作成
[ここ](https://www.proxmox.com/en/downloads/category/iso-images-pve)からISOイメージをダウンロードし、通常のLinuxのLinuxのようにUSBに書き込んでboot deviceを作成します。

なお、bootデバイスの作成にRufusを使う場合、ddモードで書き込みをしないとbootした時にgrub rescureなる画面が出て詰みます。

https://forum.proxmox.com/threads/grub-error-booting-installation-usb-stick-5-4-1-error-unknown-filesystems.55077/

## bootする
作成したbootデバイスをPCに挿して、F2を押して起動してBIOSを開きboot sequenceでUSBを1番目に設定し、exitするとbootが始まります。

一度、test memoryを選択すると真っ黒なウインドウが出て何もできなくなりましたが、電源ブチ切りして再立ち上げ後、install proxmox veを選択して画面の案内に従って設定すると無事にインストールが出来ました。

## 管理画面へのアクセス
インストールが完了するとログインするか、ネットワーク越しにアクセスするかの2択が表示され、その際にログインを求められます。その時に使うパスワードはインストール時に設定したもので、ユーザー名はrootです。
【TypeScript入門】InterfaceとType Aliasの違い

# はじめに
TypeScriptを学んでて、InterfaceとType Aliasの違いがわからなかったので、まとめてみました。

# 簡潔にまとめると
* Type Aliasは拡張しにくい
* Interfaceは拡張しやすい
* 開発したものを拡張して使ってもらいたい場合（ライブラリ開発など）は、Interfaceを使うと良い
* アプリ開発は、バグを生みづらいType Aliasを使うと良い
* 基本的には、Case by caseで決める

|  | Type Alias | Interface |
|-----------|------------|------------|
| 用途 |複数の場所で再利用する<br>型に名前をつけるため|オブジェクト・クラス・関数の構造を定義するため |
| 拡張性| 同名のtypeを宣言するとエラー| 同名のinterfaceを宣言するとマージされる|
| 継承| 継承はできないが、交差型で新しいエイリアスを作る事ができる|extendsによる継承ができる|
| 使用できる型 | オブジェクトや関数以外のプリミティブ、配列、タプルも宣言可能|オブジェクトと関数の方のみ宣言できる |
| 考慮事項| 拡張しにくい不便さがある| 拡張できることによりバグを生む可能性がある |
| いつ使う| アプリ開発ではType Alias| ライブラリ開発ではInterface |

## Interfaceの基本用法と宣言のマージ
* Interface宣言子で定義
* Type Aliasと違って「=」は不要
* 同名のinterfaceを宣言すると型が追加（マージ）される
* 宣言のマージ：同じ名前を共有すること複数の宣言を自動的に結合


```typescript:インターフェースの場合
// 宣言のマージ
interface Bread {
  calories: number
}

interface Bread {
  type: string
}

const francePan: Bread = {
  calories: 350,
  type: 'hard', // プロパティがないとエラーになる
}
```


```typescript:型エイリアスの場合
type Tamago = {
  calories: number
  spicyLevel: number
}

type Rice = {
  calories: number
  gram: number
}

type Oyakodon = Tamago & Rice // 交差型(union)を使う

// OyakodonとRice両方の型を持つ変数を定義
const oyakoDon: Oyakodon = {
  calories: 500,
  gram: 100,
  spicyLevel: 5,
}
``` 

## Interfaceの拡張
* 　extendsを使うことで継承したサブインターフェースを作ることができる
* 　Type Aliasをextendsすることもできる

```typescript:インターフェースの拡張
interface Book {
  page: number
  title: string
}

interface Magazine extends Book {
  cycle: 'daily' | 'weekly' | 'monthly' | 'yearly'
}

const jump: Magazine = {
  cycle: 'weekly',
  page: 300,
  title: '漫画',
}
```

```typescript:インターフェースは型エイリアスも拡張できる
type BookType = {
  page: number
  title: string
}

interface HandBook extends BookType {
  theme: string
}

const cotrip: HandBook = {
  page: 120,
  theme: '旅行',
  title: '旅行雑誌',
}
```

## Interfaceでclassに型を定義できる

```typescript:インターフェースでクラスに型を定義する

interface Book {
  page: number
  title: string
}

class Comic implements Book {
  page: number
  title: string

  constructor(page: number, title: string, private publishYear: string) {
    this.page = page
    this.title = title
  }

  getPublishYear() {
    return this.title + 'が発売されたのは' + this.publishYear + '年です。'
  }
}
```
先出しセンドバック とは

## 勉強前イメージ

保守の形態って感じするけど、知らない・・・・

## 調査

### センドバック とは

センドバックとは、故障した製品をメーカーの窓口に送ると
修理したり、代替品と交換して送り返してくれる保守サービスの方式。
`先出し` と `後出し` がある。

- 先出し

先にメーカーが代替品を送り、利用者が入れ替わりに故障した機械をメーカーに送る方式を `先出しセンドバック` という

- 後出し

利用者が先に故障した機械を送ってから、メーカーが送り返す方式を `後出しセンドバック` という

### オンサイト

センドバックの他にオンサイトという保守の方式で
機械が故障したら修理担当が機械の場所に出向き、修理を行うサービスの方式である。

### センドバックのとオンサイトの違い

保守を行う機械が トラブルが発生した場合できるだけ早く修理しなければいけない や 郵送するのが大変な大きいもの である場合には
`オンサイト保守` を受ける場合が多いです。
オンサイトは緊急性が高い場合、すぐに修理してもらえるのがメリットです。

## 勉強後イメージ

なかなか止めれないサービスで使用されてたら基本的にはオンサイトになるのかな・・・
センドバックでも、先出しのほうが費用高いことが多いらしい。

## 参考

- [センドバック保守 【send-back maintenance】](https://e-words.jp/w/%E3%82%BB%E3%83%B3%E3%83%89%E3%83%90%E3%83%83%E3%82%AF%E4%BF%9D%E5%AE%88.html)
- [センドバック保守とは？オンサイト保守との違いや委託時の留意点](https://www.axis-comtech.com/column/maintenance/what-is-sendback-maintenance/)
Sophos UTM Home Edition のライセンス更新する際の手順

# 概要
無料で利用できるUTMソフトウエア「Sophos UTM Home Edition」のライセンス更新する際の手順が分かりにくかったので次回も同じ様に混乱しない様にメモしておきます。

# ポイント
答えが分かれば何も難しくないのですが、
ライセンス管理のMyUTM Licensing Portalで



**①古いライセンスの削除する**
**②すると新しいライセンスの作成ボタンが出る**
**③新しいライセンスを作成する**

Home用ライセンスは１アカウント１個までしか作成できないので、先に古いライセンスを削除する。
それだけ覚えておけばいい。

MyUTM Licensing Portal
https://myutm.sophos.com/

# 参考ページ
Sphos UTM Home Editionのライセンス更新手順 2021年版

https://tech.yuzuyu.mobi/archives/195


Sphos UTM Home Editionのライセンス更新手順 2024年版
※更新手順は変わっていなかったので一安心
※更新作業時のスクショをたくさん撮りました。

https://tech.yuzuyu.mobi/archives/522
スムーススクロール PC/SP高さそれぞれ調整

スムーススクロール PC/SP高さそれぞれ調整

```
  // スムーススクロール
  if ((navigator.userAgent.indexOf('iPhone') > 0) || navigator.userAgent.indexOf('iPod') > 0 || navigator.userAgent.indexOf('Android') > 0)
    {
			jQuery(document).ready(function(){
				var adjust = -25;
				var time = 500;
				var urlHash = location.hash;
				if(urlHash) {
					jQuery('body,html').stop().scrollTop(0);
					setTimeout(function () {
						scrollToAnker(urlHash) ;
					}, 100);
				}
				jQuery('a[href^="#"]').on('click', function(event) {
					event.preventDefault();
							var decodedHash = decodeURI(this.hash);
					console.log(decodedHash);
					var hash = decodedHash == "#" || decodedHash == "" ? 'html' : decodedHash;
					scrollToAnker(hash);
					return false;
				});
				function scrollToAnker(hash) {
					var target = jQuery(hash);
					var position = target.offset().top + adjust;
					jQuery('body,html').stop().animate({scrollTop:position}, time, 'swing');
				}
			})
	}
	else {
		jQuery(document).ready(function(){
			var adjust = 0;
			var time = 500;
			var urlHash = location.hash;
			if(urlHash) {
				jQuery('body,html').stop().scrollTop(0);
				setTimeout(function () {
					scrollToAnker(urlHash) ;
				}, 100);
			}

			jQuery('a[href^="#"]').on('click', function(event) {
				event.preventDefault();
						var decodedHash = decodeURI(this.hash);
				console.log(decodedHash);
				var hash = decodedHash == "#" || decodedHash == "" ? 'html' : decodedHash;
				scrollToAnker(hash);
				return false;
			});
			function scrollToAnker(hash) {
				var target = jQuery(hash);
				var position = target.offset().top + adjust;
				jQuery('body,html').stop().animate({scrollTop:position}, time, 'swing');
			}
		})
	}
```
Python を Selenium の ChromeDriver でドロップダウンリストを指定する

## スクレイピングでドロップダウンリストを指定したい
### 1. 環境

| 内容 | バージョン |
|:-|:-|
| OS  | Windows 10 Pro (64bit)  |
| Chrome  | 92.0.4515.159  |
| ChromeDriver  | 92.0.4515.107  |
| Python  | 3.9.0  |
| selenium  | 3.141.0  |

+ Visual Studio Code

| アイテム | バージョン |
|:-|:-|
| バージョン  | 1.59.1 (user setup)  |
| コミット  | 3866c3553be8b268c8a7f8c0482c0c0177aa8bfa  |
| 日付  | 2021-08-19T11:56:46.957Z  |
| Electron  | 13.1.7  |
| Chrome  | 91.0.4472.124  |
| Node.js  | 14.16.0  |
| V8  | 9.1.269.36-electron.0  |
| OS  | Windows_NT x64 10.0.19042  |
| Python | 3.9.0 64bit  |

### 2. Select モジュールを使う
以下の様な HTML コードのとき、

```html
<html>
 
<select name="test" id="Dropdown">
    <option value="1">1番目</option>
    <option value="2">2番目</option>
    <option value="3">3番目</option>
    <option value="4">4番目</option>
    <option value="5">5番目</option>
    <option value="6">6番目</option>
</select>

</html>
```

まず、Select モジュールをインポート
`from selenium.webdriver.support.select import Select`

```Python
# ドロップダウンリストを取得するために
dropdown = driver.find_element_by_id('Dropdown')
# で、id:Dropdown の要素を取得。
# Select オブジェクトを生成。
select = Select(Dropdown)

# select_by_xxx( )というメソッドで特定の選択肢(option)を選択状態にできる

# 3番目のoptionタグを選択状態に
# インデックスなので1つ目の選択肢は0からスタート。
select.select_by_index(2)  
# 最後のoptionタグを選択状態に
select.select_by_index(len(select.options)-1)  
```
`Select.options`とすると、全てのoptionタグがWebElementのリストで返ってくるので`len()`関数で選択肢の数を数えることができる。
今回は中身の値で選択したいので、
`select.select_by_value('3')`
テキストで指定する場合は
`select.select_by_visible_text('3番目')`

### 3. 参考にさせて頂いたサイト

https://yuki.world/selenium-select/
clojureの環境構築


# はじめに

最近、clojureと言う言語を聞いたので、その環境構築を行いました。
clojureはLISPをJVM仮装マシン上で動けるようにしたものです。

レポジトリはこちら

https://github.com/sugiyama404/clojure_ini.git

# dockerのビルド

ディレクトリ構成

初回インストールを行うために以下の構成にしてあります。
後で、変更します。

```console
├── Dockerfile
├── docker-compose.yaml
```

```dockerfile:Dockerfile
FROM clojure:openjdk-8
WORKDIR /usr/src/app

# bashは入れても入れなくてもどっちでもいいです。
RUN apt-get update && apt-get install --no-install-recommends -y bash=5.0-4 \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*
```

```dockerfile:docker-compose.yaml
version: '3'
services:
  clojure:
    build: .
    tty: true # 後で、コンテナ内に入るため。終わったら消す。
```

# インストールと永続化

```console
docker-compose exec clojure bash -c "lein new app workspace"
docker cp `docker-compose ps -q clojure`:/usr/src/app/workspace/ ./
```

docker-compose.yamlを書き換える。

```dockerfile:docker-compose.yaml
version: '3'
services:
  clojure:
    build: .
    command: 'lein run'
    working_dir: /usr/src/app/workspace
    volumes:
      - ./workspace:/usr/src/app/workspace
```

最終的なディレクトリ構成

作られたディレクトリの中身は完全にjavaですね。

```console
├── Dockerfile
├── docker-compose.yaml
└── workspace
    ├── CHANGELOG.md
    ├── LICENSE
    ├── README.md
    ├── doc
    │   └── intro.md
    ├── project.clj
    ├── resources
    ├── src
    │   └── workspace
    │       └── core.clj
    ├── target
    │   └── default
    │       ├── classes
    │       │   └── META-INF
    │       │       └── maven
    │       │           └── workspace
    │       │               └── workspace
    │       │                   └── pom.properties
    │       └── stale
    │           └── leiningen.core.classpath.extract-native-dependencies
    └── test
        └── workspace
            └── core_test.clj
```

# Hello, World!

最後に、docker compose up!!!

```console
> docker compose up
Attaching to clojure_1
clojure_1  | Retrieving org/clojure/clojure/1.10.1/clojure-1.10.1.pom from central
clojure_1  | Retrieving org/clojure/spec.alpha/0.2.176/spec.alpha-0.2.176.pom from central
clojure_1  | Retrieving org/clojure/pom.contrib/0.2.2/pom.contrib-0.2.2.pom from central
clojure_1  | Retrieving org/clojure/core.specs.alpha/0.2.44/core.specs.alpha-0.2.44.pom from central
clojure_1  | Retrieving org/clojure/clojure/1.10.1/clojure-1.10.1.jar from central
clojure_1  | Retrieving org/clojure/spec.alpha/0.2.176/spec.alpha-0.2.176.jar from central
clojure_1  | Retrieving org/clojure/core.specs.alpha/0.2.44/core.specs.alpha-0.2.44.jar from central
clojure_1  | Hello, World!
clojure_1 exited with code 0
```

ビルドしていなければ、勝手にビルドしてくれるみたいですね。
ここは、go,javaよりも便利ですね。


```clojure:workspace/src/workspace/core.clj
(ns workspace.core
  (:gen-class))

(defn -main
  "I don't do a whole lot ... yet."
  [& args]
  (println "Hello, World!"))
```

このファイルを書くかえれば、コーディングが行えます。