OmniAICreator/Qiita-1.07M huggingface dataset:
バッチファイルでzip圧縮する（PowerShellを使用）

Y子です。
今日はファイルを圧縮してみます。

# 概要・用途
PowerShellを使って、zip圧縮します。
自動処理の中で、圧縮してサイズを小さくしたり、複数ファイルを1ファイルにまとめたり、等の用途を想定します。
_【[確認環境：Windows 10 Home (Bld. 19042.928)](https://qiita.com/koiwaiwaiko/items/ef2d457ae1e1a7c8b698 "Windows10のバージョンを確認・表記する")】_

# コード
## (1) 1ファイルを圧縮する
1つのファイルを圧縮して、1つのzipファイルを作ります。
zipファイルの置き場所は、元ファイルと同じフォルダとします。
zipファイルのファイル名は、元ファイルの末尾に「.zip」を追加しただけとします。

```bat:compress_file_s2s.bat
@echo off
setlocal

rem 引数がない場合は終了する
if "%~1"=="" (echo 引数がありません & pause & exit /b)

rem 圧縮前ファイル
set str_file=%~1

rem 圧縮後ファイル
set str_zipfile=%str_file%.zip

rem zip圧縮実行
powershell compress-archive -Path '%str_file%' -DestinationPath '%str_zipfile%' -Force
echo %str_zipfile%

endlocal
pause
```

このバッチファイルに、`C:\work dir\test01.txt`をマウスでドロップした結果は、以下の通りです。

```:実行結果
C:\work dir\test01.txt.zip
続行するには何かキーを押してください . . .
```

なお、半角スペースを含むパスを扱う際、PowerShellでは`'シングルクオート'`で囲まないといけないようですね。
バッチファイルの中では`'シングルクオート'`でも`"ダブルクオート"`でも行けたので、ちょっと悩みました。

## (2) 複数ファイルをそれぞれ圧縮する
n個のファイルを圧縮して、同数のzipファイルを作ります。
zipファイルの置き場所は、元ファイルと同じフォルダとします。
zipファイルのファイル名は、元ファイルの末尾に「.zip」を追加しただけとします。
複数の引数を処理する方法は、[この記事](https://qiita.com/koiwaiwaiko/items/c7d4c76c295944a779c2 "バッチファイルで複数ファイルの拡張子（.zi_等）をリネームする(PPAP)")で確認したやり方です。

```bat:compress_file_m2m.bat
@echo off
setlocal

:label_top

rem 引数がない場合は最後に飛んで終了する
if "%~1"=="" (
  goto :label_bottom
)

rem 圧縮前ファイル
set str_file=%~1

rem 圧縮後ファイル
set str_zipfile=%str_file%.zip

rem zip圧縮実行
powershell compress-archive -Path '%str_file%' -DestinationPath '%str_zipfile%' -Force
echo %str_zipfile%

rem 引数をシフトし、最初に戻る
shift
goto :label_top

:label_bottom
echo 処理を終了しました
endlocal
pause
```

このバッチファイルに、`C:\work dir\`フォルダ中の5個のファイルをマウスでドロップした結果は、以下の通りです。

```:実行結果
C:\work dir\test01.txt.zip
C:\work dir\test02.txt.zip
C:\work dir\test03.zi_.zip
C:\work dir\test04.txt.zip
C:\work dir\test05.zi.zip
処理を終了しました
続行するには何かキーを押してください . . .   
```

## (3) 複数ファイルをひとつに圧縮する
n個のファイルをまとめて圧縮して、1個のzipファイルを作ります。
zipファイルの置き場所は、元ファイルと同じフォルダとします。
zipファイルのファイル名は、「zipfile_日付_時刻.zip」とします。

```bat:compress_file_m2s.bat
@echo off
setlocal

rem 日付「20210402」形式
set str_date=%date:~0,4%%date:~5,2%%date:~8%

rem 時刻「094617」形式
set str_time=%time: =0%
set str_time=%str_time:~0,2%%str_time:~3,2%%str_time:~6,2%

rem 圧縮前ファイル(初期化)
set str_file=

rem 圧縮後ファイル
set str_zipfile=zipfile_%str_date%_%str_time%.zip

:label_top

rem 引数がない場合は最後に飛んで終了する
if "%~1"=="" (
  goto :label_bottom
)

rem 圧縮前ファイル(カンマでつなげる)
if "%str_file%"=="" (
  set str_file='%~1'
) else (
  set str_file=%str_file%,'%~1'
)

rem 引数をシフトし、最初に戻る
shift
goto :label_top

:label_bottom

if not "%str_file%"=="" (
  rem zip圧縮実行
  powershell compress-archive -Path %str_file% -DestinationPath '%str_zipfile%' -Force
  echo %str_zipfile%
)

echo 処理を終了しました
endlocal
pause
```

このバッチファイルに、`C:\work dir\`フォルダ中の5個のファイルをマウスでドロップした結果は、以下の通りです。

```:実行結果
zipfile_20210426_192651.zip
処理を終了しました
続行するには何かキーを押してください . . .
```

# おわりに
小さいファイルがたくさんあると、フォルダの表示やコピーに時間がかかったりします。
バックアップ処理を自動化するような場合、元のファイルのまま保存しておくより、zipファイルにパッキングしてしまった方が扱いやすい場合も多いように思います。
そんな時に、今回のコードが使えそうですね。

ではではー！
PHPの基本操作⑥ 「電子メールの送信」

##参考書籍
よくわかるPHPの教科書 PHP7対応版

##他記事リンク
- [PHPの基本操作①<br>「簡単な出力と構文、配列、連想配列、少数、フォーマット」](https://qiita.com/kunrenyouAcount/items/7a3bb6e5769ba94a7dc5)

- [PHPの基本操作②<br>「ファイルの読み込み、ファイルの書き込み、XMLの読み込み、JSONの読み込み」](https://qiita.com/kunrenyouAcount/items/bec393cae5901e32ec70)

- [PHPの基本操作③<br>「入力欄、ラジオボタン、チェックボックス」](https://qiita.com/kunrenyouAcount/items/1c66ccee97c33f320fb2)

- [PHPの基本操作④<br>「数字かどうかの判定、正規表現、別ページにジャンプ」](https://qiita.com/kunrenyouAcount/items/5b292d8481a76386fd1e)

- [PHPの基本操作⑤<br>「クッキーとセッションの保存と取得」](https://qiita.com/kunrenyouAcount/items/7324fad1d3d1845de075)

- [PHPの基本操作⑥<br>「電子メールの送信」](https://qiita.com/kunrenyouAcount/items/2172f03af0d8d8a32cc6)

- [PHPの基本操作⑦<br>「ファイルアップロードの受信をする」](https://qiita.com/kunrenyouAcount/items/dece31f962472fb23610)


##電子メールを送信する

PHPを使って、電子メールを送信する機能を実装します。

日本語でメールを送信する場合**mb_send_mail関数**を使います。戻り値として、成功の可否が返されます。

```php
mb_send_mail(送り先のメールアドレス,　件名, 本文, 送り元のメールアドレス等)
```

このファンクションを使う場合、PHPの設定で言語や文字コードを以下のように設定することで正しく動作します。

```php
mb_language('japanese');
mb_internal_encoding('UTF-8');
```

戻り値などを利用し、表示を変更するように実装すると以下のようになります。(メールサーバーの稼働やNDSサーバーの稼働が必要となるため、以下実行してもメールは送信されません。)

```php:電子メールを送信する
<?php
  $email = 'receive@example.com';

  mb_language('japanese');
  mb_internal_encoding('UTF-8');

  $from = 'submit@example.com';
  $subject = 'PHPの基本操作の練習';
  $body = 'このメールは、「PHPの基本操作の練習」から送信しています';

  $success = mb_send_mail($email, $subject, $body, 'From: ' . $from);
?>
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>PHPの基本操作の練習</title>
</head>
<body>
  <pre>
    <?php if($success) : ?>
    電子メールを送信しました。メールボックスを確認してみてください。
    <?php else : ?>
    電子メールの送信に失敗しました。Webサーバーの設定などをご確認ください。
    <?php endif; ?>
  </pre>
</body>
</html>
```

　
##２種類のトップページをランダムに表示する

ランダムな整数を生成するにはrand関数を使います

```php:ランダム関数の使い方
ランダムな値 = rand(最小の整数, 最大の整数);
```

これを条件に用いたif文を使い、header関数を呼び出すことで、2種類のトップページをランダムに表示します。

```php:2種類のトップページをランダムに表示します
<?php
  if(rand(0, 1) == 0) {
    header('Location: a.html');
  } else {
    header('Location: b.html');
  }
?>
```

```html:a.html
このページは、Aのページです。もう一度、ページを読み込んでみましょう。
```

```html:b.html
このページは、Bのページです。もう一度、ページを読み込んでみましょう。
```
MAMPでCakePHPを使う(2021年版)

会社の研修がきっかけでPHPを学習し始め、推奨されたフレームワークがCakePHPだった。CakePHPはMVCモデルを採用しているウェブアプリケーションフレームワークであり、Ruby on Railsの概念が取り入れられているらしい。

CakePHPについてググってみるだけでは不明点多しだったため、メルカリで「CakePHP超入門」という本を購入し早速ハンズオンしてみた。CakePHP用のDockerのimageを持っていたが、本に倣いcomposerを使った環境構築をした。だが三年前に出版された本ということもあり動かなかった点もあったため、備忘録ということで環境構築までの流れをまとめた。

## 環境

* macOS Big Sur: 11.2.3
* MAMP: 6.3
* PHP: 7.4.12
* CakePHP: 4.2.5

## MAMPのインストール

MAMP PROでない無料のMAMPをインストール。

https://www.mamp.info/en/mac/



## composerのコマンドをターミナルで入力

ターミナルでディレクトリ位置をDesktopに移動。composerホームページでトップページ→Download内にコマンドが公開されているので入力。するとDesktopにcomposer.pharというファイルが作成される。

```
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === '756890a4488ce9024fc62c56153228907f1545c228516cbf63f885e036d37e9a59d27d63f46af1d4d07ee0f76181c7d3') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"
```

https://getcomposer.org/



## ターミナルが見ているPHPの確認

```
$ which php
```

ターミナルが見ているPHPはMacBook本体に入っているものか、MAMPのPHPかの確認。MAMPを起動し上記のコマンドを打つと、おそらく

```
/usr/bin/php
```

という結果が返ってくる。この結果をMAMPのPHPにする必要があるのでパスの指定が必要。



## ちなみに…

```/usr/bin/php``` の状態でこの先進むと

```
  Problem 1
    - cakephp/cakephp[4.2.0, ..., 4.2.5] require ext-intl * -> it is missing from your system. Install or enable PHP's intl extension.
    - Root composer.json requires cakephp/cakephp ~4.2.0 -> satisfiable by cakephp/cakephp[4.2.0, ..., 4.2.5].

```

後のコマンドでintl extensionがないという上記の警告が表示されてしまい動作がおかしくなる。(自分も悩みました)



## MAMPのPHPのパスの指定

```
$ vi ~/.bashrc

$ export PATH=/Applications/MAMP/bin/php/php7.4.12/bin:$PATH
// :wq で保存

$ source ~/.bashrc
// 変更の反映
```

ターミナルで上記コマンドを実行することによってMAMPのPHPのパスが通ります。この設定後に ```$ which php``` の実行で

```
/Applications/MAMP/bin/php/php7.4.12/bin/php
```

通りましたね!



## CakePHPのコマンド実行!

composer.pharがDesktopにある状態かつディレクトリ位置もDesktopの状態で

```
php composer.phar create-project --prefer-dist cakephp/app アプリの名前
```

を実行し、permissionの確認でyを押すと、「アプリの名前」ディレクトリがDesktopに生成されました! その中にはbinやsrcなど多数入っています。そのディレクトリを丸ごと ```user/Applications/MAMP/htdocs``` 内に移動させ、ブラウザ環境で

```
http://localhost:8888/アプリの名前/
```

にアクセスすると、

![Screen Shot 2021-04-26 at 23.03.04 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/829642/954ce3ad-a4a6-6f13-3ea2-14314330be7c.png)

環境構築完了しました! この画面がCakePHPのHello World! のようなものです。Databaseはまだ触っていないのでアイコンが赤くなっています。(Databaseの設定をすればアイコンが緑になる)



## 参考文献
・[【CakePHP3系/MAMP】ComposerでCakePHP3系をインストール実行時、「Your requirements could not be resolved to an installable set of packages.」と怒られた時の解決方法](https://44igarashi.hatenablog.com/entry/cakephp3_install_error)
・[viの基本的な使い方](https://rat.cis.k.hosei.ac.jp/article/rat/serverliteracy/2004/vi.html)
・[viで文字を削除するコマンド【色々な方法まとめました】](https://eng-entrance.com/linux-vi-delete)
プロジェクト・勉強を期限までに終わらせたい！


#はじめに
前回のQiitaで[プロジェクト管理の基本(プロジェクトを始める人へ)](https://qiita.com/Momomomo77777/items/fcc1604fcab30277ff81)を書かせていただきました。

しかし、プロジェクトの管理方法が分かったとしても、プロジェクトの工程を考えて計画のおおよそを決めなければ、完成することはできません。

例えば、学校の課題は4/25 23:55 までと期限が決まっています。
自分がまだ達成できていない状況にいるので、事前に友達から情報を集めたり、<del>直前に焦ったり</del>することができますよね。

そこで、全体を分かりやすく機能別に計画を立てることができる方法を紹介したいと思います。
優しい心で見ていただければ幸いです。

#進捗を管理する
今回は全体の進捗を管理する方法の一つである「**ガンチャート**」を紹介したいとおもいます。

#ガンチャートとは
日程管理で使う図で**予定と実績**の対比に適した図です。

ガンチャートは、職場の監督者が社員の進捗状況を即座に把握できるよう設計したのがはじまりです。


ガンチャートはプロジェクトタイムマネジメント以外に、勉強計画管理にも多く使われます。
プロジェクト管理で使う場合はチーム内のメンバーでタスクの進捗状況を共有することができます。
また、縦軸にタスクをならべて一覧で表現します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502903/c4062dce-2355-d963-a644-fae9260fbcd6.png" width="600px">

#メリット
1.  計画の**全体像を確認**できる

1.  書き出すことで**負荷の高い部分が分かる**

1.  工程やスケジュールをメンバーと**共有**できる

1.  進捗状況が**可視化**できる

#ガンチャートの作り方
以下のページでエクセルのガンチャートテンプレートをダウンロードすることができます。
[エクセル ガントチャートテンプレート](https://bizroute.net/ganttchart_howto.html)

#最後に
プロジェクトを始める前の計画や勉強の計画を立てる時などに、使ってみてはどうでしょうか。
大事なことは、計画は崩れるものなので、崩れた時は落ち込まずにすぐに崩れたことを生かしてすぐ計画を立てましょう！！（経験談）

学生IT団体：[watnow](http://www.watnow.jp/)
**キータカレンダー4月** 26日目ももでした。

#参考文献
TAC　基本情報技術者試験　試験対策テキスト３
令和02年 イメージ&クレバー方式でよくわかる 栢木先生の基本情報技術者教室
キタミ式イラストIT塾 基本情報技術者 令和02年 (情報処理技術者試験)
[エクセルのガントチャートで「プロジェクト管理」する3ステップ](https://www.innopm.com/blog/ganttchart-technique#5-3)
辞書Dictionary型の配列 swift まとめ

#■辞書型の配列にはキーと値がある。型がそれぞれ統一されている。　基本はね...
キーがString型なら全てのキーがStringになる。
値がInt型なら全ての値がInt型になる。

``` swift
var dic1 = ["name":"aoka","age":"28"]
print(dic1)
//結果: ["name":"aoka","age":"28"]


var dic2 = ["apple":100,"banana"200,"orange":300]
print(dic2)
//結果: ["apple":100,"banana"200,"orange":300]


```
後にAny型を使った紹介をするそれを使えば型をバラバラに入れれる。

#■空の辞書型の配列を作ろう

``` swift
//これでキーはString型,値はInt型の空の配列ができる。
var dic3 = Dictionary<String:Int>()

//これをprintすれば空の辞書型配列だとわかる。
print(dic3)
//結果: [:]
```

#■データの代入方法

``` swift
//空の辞書型配列があると仮定する。
var dic3 = Dictionary<String:Int>()

dic3["apple"] = 100
dic3["banana"] = 200

print(dic3)
//結果: ["apple":100,"banana": 200]

```

#■データを取り出してみよう
オプショナルバインディングしないとoptional(値)で返ってくる
optional(値)だと使えない！！！！

``` swift

var dic4 = ["apple":100,"banana"200,"orange":300]
print(dic4["apple"])
//結果: optional(100) となり使えない！！！！！

//オプショナルバインディング
if let price = dic4["apple"] {
 print(price)
}
//結果: 100 となり使える！！！


//デタラメなキー入れたらただのnilになる。
print(dic4["APPLE"])
//結果: nil
```

#■データの上書き

``` swift
var dic4 = ["apple":100,"banana"200,"orange":300]

dic4["banana"] = 999

if let price = dic4["banana"] {
  print(dic4["banan"])
}
//結果: 999


//データの消去もできる。
dic4["aplle"] = nil

if let price = dic4["apple"] {
 print(dic4["apple"])
}  else {
  print("データをnilにして消したからこっちが表示される。")
}

//結果: データをnilにして消したからこっちが表示される。
```


#■Any型を使い色んな型を値に指定してみた！！

``` swift
//値をAny型とする。
var dic5:Dictionary<String:Any> = ["name":"aoka", "age":28, "birthday":Date()]

//値がAny型なのでオプショナルバインディングして確認 これは本当にString型なのか等...
if let name = dic5["name"] as? Stirng {
 print(dic5["name"])
}
//結果: aoka

if let age = dic5[age] as? Int {
 print(dic5["age"])
}
//結果: 28

if let birthDay = dic5["birthday"] as? Date {
    print(birthDay)
}
//結果: 2021-04-26 14:31:50 +0000

```


参考にさせて頂いた動画です！　
https://www.youtube.com/watch?v=IJIJawKJTLc&list=PLQ5rERkGSxF9_soz3Ns-SpURWsy0WmbJQ&index=51
アプリ道場サロン
Django+Herokuで簡単に非同期処理を実装したい

## Herokuに乗ったDjangoに非同期処理をさせたいよ～～
Herokuは30秒レスポンスが返らないとタイムアウトさせてしまいます．
公式ドキュメントでも以下のように時間のかかる処理は非同期で行うことを推奨(というかほぼ強制)しています．

- メールの送信
- リモート API へのアクセス (Twitter への投稿、Flickr の照会など)
- Web スクレイピングまたは Web クローリング
- 画像または PDF のレンダリング
- 大量の計算 (フィボナッチ数列の計算など)
- データベースの大量使用 (時間のかかるクエリまたは多数のクエリ、N+1 クエリ)

## Herokuのドキュメントに沿って作ってみる
Heroku自体がPythonの非同期処理についてまとめているのでそれに沿って作ってみます．
https://devcenter.heroku.com/ja/articles/python-rq

まずworkerを作成します．

```python:worker.py
import os

import redis
from rq import Worker, Queue, Connection

listen = ['high', 'default', 'low']

redis_url = os.environ.get('REDISTOGO_URL', 'redis://localhost:6379')
sys.path.append(os.getcwd())
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myapp.settings')

conn = redis.from_url(redis_url)

if __name__ == '__main__':
    with Connection(conn):
        worker = Worker(map(Queue, listen))
        worker.work()
```

この時，Djangoの設定を読み込みます．
setdefaultで渡すだけだとそんなモジュールないが？って怒られてしまうのでpathも追加してください．

キューを作って投げ込み動かします．
投げ込むジョブはあらかじめUtils.pyにでも外だしで書いておきましょう．

```python:views.py
from django.views import generic
from rq import Queue
from worker import conn
from myapp.utils import myfunc

class myView(generic.View):
    context_object_name = 'myView'

    def get(self, request, *args, **kwargs):
        q = Queue(connection=conn, default_timeout=600)
        r = q.enqueue(myfunc, request.param)    
        context = self.get_context_data()
        return render(request, 'myapp/myView.html', context)
```

あとはQueue作って関数を投げ込むだけです．難しくないですね．

```:Procfile
web: gunicorn myapp.wsgi --log-file -
worker: python worker.py
```

Heroku向けのProcfileにworkerを追加しておきましょう．

```shell
heroku scale worker=1
```

Herokuにデプロイしたらscaleでworkerを増やしましょう．

## Django-rqを使う方法
[こちら](https://leben.mobi/blog/django_rq_hidouki/python/)を参考に実装します．

https://leben.mobi/blog/django_rq_hidouki/python/

Heroku特有の手続きはworkerをProcfileに登録することとsettings.pyをちょっと変えることだけです．

```python:settings.py
RQ_QUEUES = {
    'default': {
        'HOST': 'localhost',
        'PORT': 6379,
        'DB': 0,
        'PASSWORD': '',
        'DEFAULT_TIMEOUT': 7200,
        'URL': os.getenv('REDISTOGO_URL', 'redis://localhost:6379/0'),　#追加
    },
}
```

```:Procfile
web: gunicorn myapp.wsgi --log-file -
worker: python manage.py rqworker
```

こっちの方が固有ライブラリを使っている分すっきりしますね．(settingsに設定まとまるし)

## 終わりに
Herokuでは好きなだけ非同期処理のworkerが増やせますが，料金もworkerの分だけメインのdynoと同じ料金でかかるので個人趣味でやる分には結構負担が大きいです．

大した処理しないのに料金倍にしてworker作るのもなぁ～～ってなっているので良い方法あったら教えてください．
【JavaScript】ホイスティングについて ~復習~

ReactやTypeScriptを学んでる上でJavaScriptの重要性について感じたので復習していきたいと思います！

#ホイスティングについて
よく記事で『宣言の巻き上げ』というワードを目にするんですがよくわからない。。。
コードを見ながらの方がイメージが湧きやすいと思うので実際にコードを書いていきます！

```main.js
hello();

function hello (){
console.log('こんにちは')
}
```

上記の例は関数の定義前に関数の実行を行ってます。
本来コードをは上から読み込まれていくので変な感じがしますよね。。。
コンテキスト内で宣言した関数や変数は実行前にメモリに保存されるので先に実行されても問題なく実行することができます！

##varとlet・constの違い
次にvarを使用した時とlet・constを使った時の挙動の違いについてです！

```main.js
console.log(b); // undifinedが出力
var b= 0 ;
console.log(b);　// 0が出力

console.log(c)　//Uncaught ReferenceError: Cannot access 'c' before initialization
    at
let c = 100
```

何が違うのか
*varはundifinedの初期値が設定されてる為エラーが発生しない*
逆にいうとletとconstに関してはundifindedの初期値が設定されてない為、エラーが表示されるという仕組みです！

基本はletとconstを使用すれば問題ないかと思います！

##無名関数（関数式）の場合
気付いてる方もいるかも知れませんが、無名関数は変数の形をとっていますよね！
`const a = (){} `これって。。。
変数の形と一緒ですよね！
なので関数式を使用する場合はundifinedが初期値と設定されてないので

```main.js
bye() //Uncaught ReferenceError: Cannot access 'bye' before initialization
const bye = function(){
    console.log('byebye')
}
```
エラーが出てしまいますね！
なので`bye()`の位置を関数下で呼び出すことでエラーなく表示することができます！
Webで使われるデータ形式（スクリプト言語,DOM,JSON）

# スクリプト言語
Webサイトの動的処理には**スクリプト言語**が使われる。
Perl（パール）、Ruby（ルビー）、PHP（ピーエイチピー）、Python（パイソン）などの**サーバーサイド・スクリプト**はサーバーのCGIから呼び出すため、HTMLと分離した別ファイルにする。
JavaScriptを主とする**クライアントサイド・スクリプト**は、HTMLと分離したファイルにしても、HTML内に直接書き込んでも動作する。
## ECMAScript
JavaScriptは、当初Mozilla FoundationとMicrosoftが開発していたが、ECMAインターナショナルがJavaScriptを標準化し**ECMAScript(エクマスクリプト)**として定めた。
現在では、JavaScriptというとECMAScriptを指す。
# DOM
**DOM(Document Object Model)**は、HTMLやXML文書を扱うための手法（API）である。DOMを使うことで、プログラムからHTMLやXMLの各要素を容易に参照・制御できる。現在、ほとんどのWebブラウザがDOMを実装している。
![Cookie.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/999125/aac3166c-80a0-b8cc-3096-f9f9df367cb6.jpeg)


DOMでは、対象となる文書の各要素を抽出し、それらを階層構造として扱う。文書の最上位要素を「根」とし、それぞれの下位の要素が木の枝のように分かれていくツリー構造となっている(**DOMツリー**)。
ツリーの枝葉の部分は「**ノード**」と呼ばれ、DOMではこのノードをたどっていくことで目的のデータに到達し、参照や編集を行う。
# JSON
**JSON（JavaScript Object Notation）**は、構造化したデータを表すためのデータ記述言語の一種である。名前に「JavaScript」とあるが書式がそれに従ったものとなっておいるだけで、他のプログラミング言語もJSONの読み書きに対応している。
JSONはXMLと比較して以下のような特徴がある。

. 文字列以外に、数値や空を意味するデータを扱える。
. テキストを[{,:などの括弧で囲んで構造を表すため、データサイズが小さい
. タグがないため、人には読みづらい

JSONは、JavaScriptの書式に従うため、JavasCriptで書かれたプログラムはJSONをそのままJavaScriptとして読み込むことができ、XMLのようにDOMを利用する必要がない。
また、タグがないぶんによりXMLよりデータサイズが小さく、ネットワークの転送速度において優位になる。
これらの利点から、Webでは選択されやすいデータ形式となっている。
# 参考
[イラスト図解式 この一冊で全部わかるWeb技術の基本](https://www.amazon.co.jp/gp/product/B06XNMMC9S/ref=ppx_yo_dt_b_d_asin_title_o05?ie=UTF8&psc=1)
【初心者向け】Winキーを使ってノートPCシングルディスプレイでも楽をする【テレワーク】


※本当に初心者向けです

WindowsのノートPCを使って家で狭い画面一枚で作業させられている方が、少しでも楽になればという記事です。

そのノートPCの大体左下にあるWinキー。
なんか押すとスタートメニューが開くだけですが、使い道あんの？っていう
■ ■
■ ■　　←　これ

です。

実は他のキーと組み合わせると、結構便利なので一部を紹介です。


## Win + ↑
今アクティブなウィンドウが最大化します。
いちいちマウスで右上のほうにカーソル持っていかなくていいです。
最小化しているウィンドウがアクティブな状態で押すと、通常化します。もう一度押すと、最大化します。

## Win + ↓
Win + ↑の逆で、アクティブウィンドウを最小化します。

## Win + → or Win + ←
アクティブな画面を画面半分の大きさにしてどちらかに寄せます。
ブラウザと何かを並べて見るときに便利、、、ですが、見比べるならまだしも実際に作業するときはこれ以降紹介する仮想デスクトップを使ったほうが楽です。

## Win + Tab
仮想デスクトップの一覧表示
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207100/c3e1a4b6-812b-5968-5e9f-57328a71af64.png)
こんな感じです。
マウスでデスクトップを切り替えられる＆新しいデスクトップをクリックでデスクトップを生成できます。

この仮想デスクトップを使うと、各ウィンドウでアプリケーションをフルスクリーンで開いておくことができて、次に紹介する方法で素早くデスクトップを切り替えることができるので、

* ブラウザで翻訳サイトを開きながら
* Wordファイルを編集する

みたいな操作をするときに毎回マウスでアプリケーションを最小化したり最大化したりする必要がないので便利です。


## Win + Ctrl + ← or Win + Ctrl + →
仮想デスクトップを切り替えます。

## Win + Ctrl + d
新しいデスクトップを生成します。

## Win + Ctrl + F4
アクティブなデスクトップを終了します。

シングル画面でも複数アプリを参照しながら作業できるので、これで少しは効率上がってもらえればと思います。
Elasticsearchが起動してくれなかった時の悲しすぎる原因

#問題
Growi導入の為に、elasticsearchを公式の通りubuntuにインストールしていた時の出来事です。

```
sudo systemctl start elasticsearch
```
を実行したところ

```
Job for elasticsearch.service failed because the control process exited with error code.
See "systemctl status elasticsearch.service" and "journalctl -xe" for details.
```
に遭遇しました。

## ググったら解決策は出てきたんだけど・・・

このエラーに関するQ&Aは出てきたんですが全然解決しませんでした。

有力な情報だと思ったのは、[こちら](https://stackoverflow.com/questions/58656747/elasticsearch-job-for-elasticsearch-service-failed)や[こちら](https://akng-engineer.hatenablog.com/entry/2019/06/09/165107)でした。

しかし、この方法をやってもエラーは変わらずに困っていました。

## エラー原因はどこ

上記のエラーに出ていたコマンド2つでは、原因がよく分からずもっと詳細が分かるコマンドはないかと探していたら、`journalctl`のオプション`-u`が使えそうでした。

```
journalctl -u elasticsearch.service
```
すると

```
encountered [2] errors parsing [/etc/elasticsearch/jvm.options]
[1] : encountered improperly formatted JVM option in [/etc/elasticsearch/jvm.options] on line number [31]: [-Xms512m]
[2] : encountered improperly formatted JVM option in [/etc/elasticsearch/jvm.options] on line number [32]: [-Xmx512m]
```
このような情報が表示され、原因は`jvm.options`の`-Xms512m`と`-Xmx512m`の設定にある事までは分かりました。

しかし、今回使用していたのはRAM4GBなのでメモリの割り振りは問題がないはずです。スペルミスも疑いましたが、合ってます。該当部分だけ書き直しもしましたが解決しません。

頭の中に？マークが並んでいた時に、気づいたことがありました。

「そういえば2つの値設定した時に、先頭をスペース1マス分開けてたな」

もしやと思い修正しました。

```
#修正前、先頭が半角スペース1マス分空いている
 -Xms512m
 -Xmx512m

#修正後、先頭のスペース分も詰める
-Xms512m
-Xmx512m
```


再度実行すると、直ぐに出てきたエラー文が出てこなくなりました。そして数十秒程待つと、次の入力待ちになりました。

おそるおそる`status`を確認すると

```
active
```
嬉しかったですが、同時に「おま、ええ・・・」と声が漏れてしまいました。

ちなみにですが、1度`elasticsearch`を止めて、再度`jvm.options`の該当箇所を修正前に戻して実行したところエラー文と再会できました。

# 結果

私が遭遇したパターンでElasticsearchが起動してくれなかった原因は、スペース1マス分空けたのが原因でした。

解決できたのは勿論うれしいですが、謎の敗北感を味わいました。

きっと`jvm.options`の形式を調べていればもっと早く解決したかなーと勉強になりました。

#参考文献

https://stackoverflow.com/questions/58656747/elasticsearch-job-for-elasticsearch-service-failed

https://akng-engineer.hatenablog.com/entry/2019/06/09/165107
gatsby build 時の「WebpackError: TypeError: Cannot read property 'hoge' of undefined」対処法

# 概要
- `gatsby build` 時に `WebpackError: TypeError: Cannot read property 'hoge' of undefined` が発生
- hogeはプロパティ名
- Nelifyへのデブロイ時も発生
- `gatsby develop` では発生せず正常にbuildされる

# 対処法
エラーとなっているプロパティ（この場合はhoge）の前に`?.`を付け、`?.hoge`とすることで解消しました。

## 何をしようとしてエラーになったのか
Gatsby.jsでブログを作成している中で、以下のようなコードを書いていました。

``` js
  const data = useStaticQuery(graphql`
    query{
      allFile {
        nodes {
          name
          publicURL
        }
      }
    }  
  `)

  const eyecatch = data.allFile.nodes.find( file => file.name === category).publicURL // ここがエラー
```

アイキャッチ用の画像ファイルをカテゴリ名と同一名称で特定のディレクリに置いておき、その`publicURL`をGraphQLで取得するという処理です。
上記コードの中のプロパティ`publicURL`が`gatsby build`でエラーになってしまっていました。

冒頭の通り、この部分を

``` js: 
const eyecatch = data.allFile.nodes.find( file => file.name === category)?.publicURL
```

とすることでエラーは解消しました。

## `?.`とは何なのか
調べてみると、[オプショナルチェイング演算子](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Optional_chaining)と呼ばれるものみたいです。

MDNによると、深い入れ子構造になったサブプロパティにアクセスする際は、各プロパティ間の参照を確認する必要があるとのこと。今回のコードで言うと、`data.allFile.nodes`内に`find`でヒットした要素が存在することを確認した上で、`publicURL`を取得する必要があるようです。

これを暗黙的にやってくれるのが、オプショナルチェイング演算子です。

# 残った謎
なぜ、`gatsby develop`ではエラーが発生せず、`gatsby build`のみ発生するのかが不明です…。
PennyLaneのtemplate circuits

# はじめに

量子プログラミング用SDKであるPennyLaneには、template circuitsがいくつも用意されています。
非常に便利な機能です。
PennyLaneの公式APIドキュメントでも説明されています[^1]が、
具体的にパラメータを設定したときにどんな回路になるか想像するのはやや難しいです。
かつ、PennyLaneのデフォルトの回路図示機能はasciiのみで、なかなか見にくいです。

確かにPennyLane自体には高度な図示機能はないですが、qiskitに変換し、qiskitのdraw機能を使うことが出来ます。[^2]
この機能で具体的に図示することで、templateがどうなっているのか納得したいと思います。

# qiskit経由での可視化

pip install

```python
pip install pennylane-qiskit
```

import

```python
import pennylane as qml
from pennylane import numpy as np
```

backend(今回はqiskit)の指定と回路作成

```python
dev = qml.device("qiskit.aer", wires=1)

@qml.qnode(dev)
def f(x):
    qml.RX(x, wires=0)
    return qml.expval(qml.PauliZ(0))

f(0.3)

```

可視化

```python
dev._circuit.draw('mpl')
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878664/62d2069a-4dab-7028-2157-5596d90f32f9.png)


確かに可視化が出来ました。

# templatesを可視化してみる

3 qubits,1 layerとします。

## AngleEmbedding

```python

n_qubits = 3
n_layers = 1

dev = qml.device("qiskit.aer", wires=n_qubits)

weights = np.random.rand(n_layers, n_qubits,3)*(2*np.pi)
x = np.ones(n_qubits)*np.pi

@qml.qnode(dev)
def circ(x):
    qml.templates.AngleEmbedding(x, wires=range(n_qubits),rotation='X')
    return qml.expval(qml.PauliZ(0))

circ(x)

dev._circuit.draw('mpl')
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878664/ebd6136c-3734-1ef6-9d75-108605145f7a.png)

入力パラメータをRXゲートの回転角度とする回路になっていますね。

## AmplitudeEmbedding

```python
x = np.ones(2**n_qubits)*np.pi
qml.templates.embeddings.AmplitudeEmbedding(x, wires=range(n_qubits), normalize='true')
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878664/338c59fa-cfc2-b197-12e8-85a61720de4e.png)


入力パラメータを量子状態振幅としてsetする回路です。

## BasicEntanglerLayers

```python
weights = np.random.rand(n_layers, n_qubits)*(2*np.pi)
qml.templates.layers.BasicEntanglerLayers
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878664/d3f3d370-3ce3-0ea8-9bac-4d3e25c60407.png)

RX→CNOT(あらゆる隣接ビット間)　となっています。

## StronglyEntanglingLayers

```python
weights = np.random.rand(n_layers, n_qubits,3)*(2*np.pi)
qml.templates.StronglyEntanglingLayers(weights, wires=range(n_qubits))
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878664/4f62d6de-2e84-429c-63bf-ad140b37c1e8.png)

RZ→RY→RZ→CNOT(あらゆる隣接ビット間)　となっています。

# まとめ

この応用で、好きな回路を可視化できます。
qiskitの回路図で表示できると、かなり便利ではないでしょうか。
デバッグに大活躍です。


[^1]: https://pennylane.readthedocs.io/en/stable/introduction/templates.html

[^2]: これを探すのに結構苦労しました・・・。
LeetCode日本語修行13日目- [1011-全ての荷物がD日以内到着の能力]

###Capacity To Ship Packages Within D Days
#####参考: https://leetcode.com/problems/capacity-to-ship-packages-within-d-days/
###問題の内容:
D日以内にとある港から別の港に出荷するの荷物があります．
i番目の荷物は、weights[i]という重さを持っています。
毎日、荷物を（重さで指定された順に）船に積み込みます。船の最大積載量以上の重さを積んではいけない。
全ての荷物がD日以内到着になる、船の最小積載量は？

###例:
例1:
Input: weights = [1,2,3,4,5,6,7,8,9,10], D = 5
Output: 15
Explanation:　**Dは:５**の時、つまり、船は五回で全部の荷物を送ります。**順番は固定です** 。船の最小積載量は15。
1st day: 1, 2, 3, 4, 5
2nd day: 6, 7
3rd day: 8
4th day: 9
5th day: 10

例2:
Input: weights = [3,2,2,4,1,4], D = 3
Output: 6
Explanation: **Dは:３**の時、全部の荷物を送ります。**順番は固定です**。
船の最小積載量は6:
1st day: 3, 2
2nd day: 2, 4
3rd day: 1, 4
###ヒント:

1 <= D <= weights.length <= 5 * 104
1 <= weights[i] <= 500

---

この問題は、既定の範囲の中に、一つのvalueを確定です。
範囲とは、
一番左のは、weightsの中に一番重いの荷物です、船の最小積載量はそれより下がると、その荷物を乗らない。。。
一番右のは、全ての荷物の重さです、つまり、D＝１の時、一日で、全部荷物を出荷する事。
weights.max() 〜　weights.sum()から、とあるのvalueを特定する事。
範囲を明確の上、二分探索を使って、解決できる。

```Kotlin
    fun shipWithinDays(weights: IntArray, D: Int): Int {
        var left = weights.max() ?: 0
        var right = weights.sum()

        while(left < right){
            var mid = (left + right) / 2
            var needDay = 1
            var curWeight = 0
            for(weight in weights){
                if(curWeight + weight > mid){
                    ++needDay
                    curWeight = 0
                }
                curWeight += weight
            }
            if(needDay <= D){
                right = mid
            } else {
                left = mid + 1
            }
        }
        return left
    }
```
[Java]特定の半角文字を全角文字に変換

半角記号を全角記号に変換してくれという依頼を受けることがあるため、メモとして残します。

## 方法① 半角文字と全角文字の文字コードの差分を加算する

英数字と一部の記号は全角と半角でコードの並び順が一致しているため、全角と半角の差分の65248を加算することで全角にすることができる。

```java:sample.java
public class Sample {
    // 全角にする文字
	private static final Character[] SYMBOLS = {
			'a', 'b', 'c', '1', '2', '3', '&', '_', '-'
	};

	public static void main(String[] args) {
		String halfWidth = "a1_";
		String fullWidth = "ａ１＿";
        // 文字コードの差分が65248になるか確認
		for (int i = 0;i < halfWidth.length();i++) {
			System.out.println(fullWidth.charAt(i) - halfWidth.charAt(i));
            // 65248
		};

		String target = "abc&123_def-456";
		System.out.println(toFullWidth(target));
        // ａｂｃ＆１２３＿def－456
	}

	private static String toFullWidth(String target) {
		char[] charArray = target.toCharArray();
		StringBuilder sb = new StringBuilder();
		for (char c : charArray) {
			if (Arrays.asList(SYMBOLS).contains(c)) {
                // 半角の文字コードに65248を加算して全角に変換 
				sb.append((char)(c + 65248));
			} else {
				sb.append(c);
			}
		}
		return sb.toString();
	}

}

```

## 方法② 全角にする文字をMapで定義しておく

```java:sample.java
public class Sample {

    // 全角にしたい文字
	private static final Map<String, String> SYMBOL_MAP;
	static {
		Map<String, String> map = new HashMap<>();
		map.put("a", "ａ");
		map.put("b", "ｂ");
		map.put("c", "ｃ");
		map.put("1", "１");
		map.put("2", "２");
		map.put("3", "３");
		map.put("&", "＆");
		map.put("_", "＿");
		map.put("-", "－");
		// 変更不可のマップを生成
		SYMBOL_MAP = Collections.unmodifiableMap(map);
	}

	public static void main(String[] args) {
		String target = "abc&123_def-456";
		System.out.println(toFullWidth(target));
        // ａｂｃ＆１２３＿def－456
	}

	private static String toFullWidth(String target) {
		String[] strArray = target.split("");
		StringBuilder sb = new StringBuilder();
		for (String s : strArray) {
			if (SYMBOL_MAP.containsKey(s)) {
                // Mapから全角文字を取得 
				sb.append(SYMBOL_MAP.get(s));
			} else {
				sb.append(s);
			}
		}
		return sb.toString();
	}

```
【覚書】GoogleフォームからDiscordに匿名投稿する【GAS】

Google フォームにて送信した内容を、
Discord に Webhook 経由で投稿する方法。

匿名チャットを作りたい人用。

## Discord 側の設定

1. サーバー設定 -> 連携サービス
2. ウェブフックを作成
3. 「ウェブフック URL」を控えておく

## Google 側の設定

1. Google ドライブから Google フォームを作成
2. 「発言」という質問名で「記述式」の入力欄だけ作成
3. 「スクリプトエディタ」を開く
4. 以下のコードをコピペ

```js
const WEBHOOK_URL = "ウェブフックURL";

FormApp.getActiveForm();

const onSubmit = (e) => {
  const data = e.response
    .getItemResponses()
    .reduce(
      (p, c) => ({ ...p, [c.getItem().getTitle()]: c.getResponse() }),
      {}
    );
  const request = {
    method: "post",
    "content-type": "application/json",
    payload: {
      content: data["発言"],
    },
  };
  UrlFetchApp.fetch(WEBHOOK_URL, request);
};
```

5. `"ウェブフックURL"` を控えておいた URL に書き換える
6. 新しいデプロイ -> 種類の選択 -> ウェブアプリ
7. 次のユーザーとして実行を「自分」、アクセスできるユーザーを「全員」に設定（目的に応じて変える）
8. onSubmit を実行すると fetch 権限を聞かれるので認証して許可する
9. Google フォームから発言を入力して、問題なく投稿されれば完成。
Docker runでsystemdを起動しつつスクリプトを動かす

# はじめに
Docker上でsystemdを使用したサービスを起動したいと思ったが調べるのに思いのほか苦戦してしまったのでここに残します

※systemdで起動しているものを直接起動してよいのならばsystemdを使用する必要はありません
※この記事ではprivilegedオプションを使用するため権限には十分注意してください

# systemdとは
Linuxカーネルが起動する(PID 1)のinitプロセス。
このsystemdはすべてのプロセスの親となります

# Docker(centos7)上のsystemd
Docker上では基本的にsystemdを有効にされていません。
systemdが起動していないとsystemctlコマンドを使って操作するサービスを使うことができません。
有効にするためにはprivilegedオプションで特権を許可、PID1で/sbin/initを実行する必要があります。
しかし、PID1で起動するためにはDocker run時に/sbin/initを実行しなければならないためユーザースクリプトを起動できません。
ユーザースクリプトを起動しその中で/sbin/initを実行してもPID1にならないためです。

# サービスの自動実行
本来起動時に実行されるサービスは以下のようなコマンドで有効にします

```
systemctl enable <サービス名>
```
しかし、/sbin/init起動前には実行できず、/sbin/init起動後はユーザースクリプトを起動できません。
そのため、手動でsystemctl enableと同じ操作を行います。

# 準備
単純な自作サービスを作成し、自動実行することを目指します。

以下のサービス設定ファイルをmyService.serviceとして保存します

```
[Unit]
Description=自作のテストサービス

[Service]
Type=simple
ExecStart=/test/startup.sh
Restart=no

[Install]
WantedBy=multi-user.target
```
また、startup.shとして以下を保存します。

```
#! /bin/sh
echo "hogehoge"
```

最後にDockerfileを作成します。
自動起動の手動設定としてシンボリックリンクをデフォルトの自動起動ユニット(multi-user.target)の依存関係に追加しています

```dockerfile
FROM centos:7

COPY myService.service /etc/systemd/system/myService.service
RUN ln -s /etc/systemd/system/myService.service /etc/systemd/system/multi-user.target.wants/myService.service
COPY startup.sh /test/startup.sh
RUN chmod +x /test/startup.sh
CMD ["/sbin/init"]
```

# 実行
```
docker build -t systemdtest .
docker run -d --privileged --name systemdtest systemdtest
```
以下のコマンドで動作確認します

```
docker exec systemdTest systemctl status myService
```
実行結果は以下のようになっており、実際に起動し、終了したことがわかります。

```
● myService.service - 自作のテストサービス
  Loaded: loaded (/etc/systemd/system/myService.service; enabled; vendor preset: disabled)
  Active: inactive (dead) since Mon 2021-04-26 13:42:42 UTC; 14s ago
 Process: 53 ExecStart=/test/startup.sh (code=exited, status=0/SUCCESS)
 Main PID: 53 (code=exited, status=0/SUCCESS)
Apr 26 13:42:42 4c44e9ad157e systemd[1]: Started 自作のテストサービス.
Apr 26 13:42:42 4c44e9ad157e startup.sh[53]: hogehoge
```

# おわりに

誤った記述や誤字脱字など指摘あれば是非お願いします
どんな型でも代入できるAny型とは swift

#■Any型とは型の一つで何でも屋さん

IntでもStringでもなんの型も入る

■注意:: 中身取り出す時はオプショナルバインディングで取り出すと安全。

``` swift
var a:Any = 123

//a as? Intで　aはInt型と指定してる。　合っていたら
if let b = a as? Int {
   print(a)
}
//結果: 123

```

#■Any型を指定した変数は後から違う型でも代入できる！！！
上の続き
普通に型推論でvar a = 123にして下記のように文字列型を入れるとエラーになる。
だがAny型やったらなんでも入るから新たに文字列型を入れれるんだよこれが！

``` swift

a = "こんにちわ"
if let b = a as? String {
  print(b)
}
//結果: こんにちわ

```
Cesiumと国土地理院標高タイルで3D地図をつくろう

![mtfuji.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73197/11ff2231-d913-7e3a-62b9-f8acc291f75f.png)

[サンプルサイト](https://kanahiro.github.io/cesium-gsi-terrain/example/)

## はじめに

https://qiita.com/Kanahiro/items/e22594b738655a189c1d

以前にdeck.glと標高タイルで3D地図をつくりました。国土地理院が配信している標高タイルの有用性は上記の記事で述べたところです。今回は3D地図のスタンダードであるCesiumで、同様に標高タイルを活用した3D地形表現に挑戦してみました。

## CesiumのTerrain

CesiumはインストールすればAPI-keyだとかがなくても衛星写真と地形データを使わせてくれます（しかし画面内にAPI-keyが設定されていない旨は表示されます）。なのでそれを使わせてもらえば良いと言えば良い…しかし都市部の精度は高くないし、単一のエコシステムに依存してしまうと、いつまで同じように使えるのかなんて不安もある訳です（どこかで聞いた話ですが）。

CesiumのTerrainは、[何やらむずかしそうなツール](https://github.com/geo-data/cesium-terrain-builder)を使えば作れるみたいです。データ自体は.terrainファイルなるタイル化されたバイナリデータです。なので、DEMがあれば多分この「正攻法」の手法で地形データは生成出来るでしょう。

## 標高タイルが使えるとうれしい

以前の記事の繰り返しですが、<b>既にホスティングされていて、自由に使える標高タイルを使いたい！</b>（当然、出典の明記が必要です）

## cesium-gsi-terrain

https://github.com/Kanahiro/cesium-gsi-terrain

という訳で前回同様作りました、npmからインストールできます。

```sh
npm install cesium-gsi-terrain
```

```javascript
import GsiTerrainProvider from 'cesium-gsi-terrain';

// かなり端折ってます
const viewer = new Viewer(canvas, {
    terrainProvider: new GsiTerrainProvider({}),
});
```

### ホントのところ

[terrain-RGBをCesiumで読み込む神モジュール](https://github.com/davenquinn/cesium-martini)がすでに存在していたので、それをフォークして標高値の計算方法を標高タイルのルールに合わせてあげただけです。先人に感謝…！

## 終わりに
deck.glでは、標高データとテクスチャのズームレベルが常に一定である必要があるらしく、テクスチャの解像度の上限が標高タイルの最大ズームレベル14になってしまっていましたが、Cesiumではそういう事はなく、高解像度のテクスチャを貼ってくれます。カメラの傾きもかなり自由度が高く、こと3D表現に関してはやはりCesiumが強いなぁと思うところです。地図アプリ制作にあっては、それぞれの強みを理解したうえで、適切にライブラリを選定する必要がありますね。
ラマヌジャンの公式で円周率を計算してみる

QuoraにGoogleの ”Jin Yamanaka” 氏が投稿していた、
[ラマヌジャンの公式を使った円周率の計算法](https://bit.ly/3aFIix7)を自分でも動かしてみた。

```math
\cdot \frac{1}{\pi}=\frac{2\sqrt{2}}{99^2}\sum_{n=0}^\infty \frac{(26390n+1103)\cdot(4n)!}{(4^n99^n\cdot n!)^4}
```

普通にmathライブラリをインポートしたpythonを使って計算すると、20桁程度の精度しかない。
しかもラマヌジャンの式は収束が速いようで、ほんの３ループほどで計算値の違いがなくなった。
これなら確かに、NASAが数値演算で"π"として扱っているのが３ループさせた値というのは本当だろう。
1 :  3.141592 ~~7300133056603~~
2 :  3.141592653589793 ~~878~~
3 :  3.1415926535897932385
4 :  3.1415926535897932385
5 :  3.1415926535897932385
6 :  3.1415926535897932385
7 :  3.1415926535897932385
8 :  3.1415926535897932385
9 :  3.1415926535897932385

９ループも実装してあるのに３ループ目から全く同じ数字というのもつまらないので、任意精度の結果が得られるという便利なmpmathライブラリを使って書き直してみた。
もちろん、まだ入れてない場合は追加でのインストールが必要。
精度の値(mpath.mp.prec)は、何度か計算させて十分なビット幅をカット＆トライで調整した値。256では大きすぎたので減らし、224=(128+64+32)という感じで適当に設定した。

```
import mpmath
mpmath.mp.prec = 224

def get_one_over_pie(total_n):
    v = 0
    for n in range(total_n):
        v += mpmath.factorial(4 * n) * (1103 + 26390 * n) / ((mpmath.factorial(n) ** 4) * (396 ** (4 * n) ))
    return mpmath.sqrt(8) / 9801 * v

for n in range(1, 10):
    print(n, ": ", 1 / get_one_over_pie(n))
```

1 :  3.141592 ~~73001330566031399618902521551859958160711003355965653629013~~
2 :  3.141592653589793 ~~87799890582630601309421664502932284887917396379151~~
3 :  3.14159265358979323846264 ~~906570275889815667748046233478116839959564~~
4 :  3.1415926535897932384626433832795 ~~5527315997421042037991121670389601~~
5 :  3.141592653589793238462643383279502884197 ~~663818133030623976165591~~
6 :  3.14159265358979323846264338327950288419716939937 ~~984683274351250728~~
7 :  3.14159265358979323846264338327950288419716939937510582 ~~102093324247~~
8 :  3.141592653589793238462643383279502884197169399375105820974944592 ~~76~~
9 :  3.14159265358979323846264338327950288419716939937510582097494459231

おそろしく収束が速い式だし、なんでこんな式が浮かんだのか想像もつかない。
天才って本当に居るんだな。
go の  write once, run anywhere ではない部分

# これは何？

Go は Java ほど write once, run anywhere ではないことは知っているけど、どこで実装依存になるのかを知らなかったので調べてみた。

まあ unsafe なやつは含めなかった。

情報源はすべて [The Go Programming Language Specification - The Go Programming Language]( https://golang.org/ref/spec ) である。

## int, uint, uintptr のサイズ

まあこれは有名だよね。
C/C++ と違って、`int`, `uint` のサイズは 32 または 64 ビット。
16 ビットだったり 40ビットだったりする可能性はない。
一方、`uintptr` は「ポインタを格納できるサイズ」としか決まっていない。文章を見る限り、40ビットとかの可能性を排除していないように見える。

## 浮動小数点数の周辺

### 浮動小数点数から他の数値型への変換

> In all non-constant conversions involving floating-point or complex values, if the result type cannot represent the value the conversion succeeds but the result value is implementation-dependent.

とあるので、2の100乗などの float64, float32 を整数に変換した場合などの動作が実装依存。

### ゼロ除算の振る舞い

> The result of a floating-point or complex division by zero is not specified beyond the IEEE-754 standard; whether a run-time panic occurs is implementation-specific.

浮動小数点数のゼロ除算で panic になるのかそれ以外のなにか（たぶん、非数）になるのかは実装依存。

非数になっても大丈夫なように対応していたら、特定のアーキテクチャでまれに panic が起こり、手元の環境では再現しないなぁ、みたいな事がありえる模様。

## サイズヒントつきで map を作る場合

> Calling make with a map type and size hint n will create a map with initial space to hold n map elements. The precise behavior is implementation-dependent.

これは、直前の例

```go
m := make(map[string]int, 100)  // map with initial space for approximately 100 elements
```

のような、サイズヒントつき `map` の話。サイズヒントを書くことはできるけど、そのサイズヒントが実際どんな効果をもたらすのかは実装依存ということだと思う。この文を見る限り、サイズヒントを無視する実装があっても許されそうに見える。

## import のパス

> The interpretation of the ImportPath is implementation-dependent but it is typically a substring of the full file name of the compiled package and may be relative to a repository of installed packages.

とある。この文の ImportPath は、

```go
import "fmt"
```

の `"fmt"` の部分。

まあこれは処理系のファイルシステムに依存せざるを得ないので仕方ない。

Windows だと

```go:go?
import "net\\http\\httputil"
```

とか書けたりするのかなぁ（試してない）。

## print の出す文字列

こんな

> print
>     prints all arguments; formatting of arguments is implementation-specific

ことが書いてある。ここでいう `print` は、`fmt.Print` のことではなく go がちゃんと起動するまでに使われる関数のことらしい。普通のユーザは関係ない。

## FMA とか適当に使うので計算結果が実装依存

> some architectures provide a "fused multiply and add" (FMA) instruction that computes x*y + z without rounding the intermediate result x*y. These examples show when a Go implementation can use that instruction:

とある。FMA が使えるなら `x*y+z` を一気にやってから丸めるし、使えないなら `x*y` をやって、それを丸めてから `z` を足して、もう一回丸める。
なので、丸め誤差の出方が変わるかもね、ということらしい。

数値計算の文脈だとわりと痛そう。

# 調べてないこと

ライブラリは調べてない。色々あると思う。`time.Sleep` で寝られる時間とか明らかに実行環境依存。
`chan` や goルーチンのタイミングとかも色々あると思う。

# まとめ

ゼロ除算の振る舞いが実装依存なのはちょっとびっくりした。わりと嫌な罠として機能しそう。

範囲外の値から整数への変換結果が実装依存なのもびっくりした。 C++ みたいな速度に全振りの言語じゃないんだから、そこは振る舞いを揃えたほうが良かったんじゃないの、と思った。

FMA は、まあそうかなとも思うけど、それは困るという人もたくさんいるよね。
ネットワークの範囲

#プログラミング勉強日記
2021年4月26日

#ネットワークの範囲
　ネットワークの範囲はIPアドレスの利用可能な範囲のこと。ネットワークに対してIPアドレスの範囲が付与されていてネットワークの範囲を決めている。(IPアドレスについては[昨日の記事](https://qiita.com/mzmz__02/items/a61088d676c11fea7b56)で説明している。)プライベートネットワークを作成するときは、まずネットワークの範囲を定義する。
　ネットワークの範囲の表記方法は、`10.0.0.0/16`といった形になる。これは、IPアドレス(`10.0.0.0`)とサブネットマスク(`/16`)がIPの範囲(ネットワークの範囲)を決める。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642821/3ee6c129-a0eb-3c34-9e5d-d8acad478748.png)


#AWSのネットワーク構成の例

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642821/7dbec133-2b54-0242-1a0e-b68ed54cc9eb.png)

　`10.0.1.0/16`はIPアドレスではなく、`/16`という範囲がついたIPアドレスの範囲をこのネットワークでは持つという意味。
　ネットワークをさらに細かく分割した単位をサブネットという。パブリックサブネットとプライベートサブネットは、それぞれ`10.0.1.0/24`と`10.0.2.0/24`の新しい範囲を付けることができる。
Proxmoxで異なったファイルシステムでクラスタリングする際の注意点

Proxmox 1号機（ext4, LVM）の既存環境に、新規2号機をZFSで作成しクラスター参加させたところ、問題が発生しました。

・マイグレート先（2号機）にLVM-thinが見つかりませんエラー
・2号機のLVM-thinを削除したところ、1号機のLVM-thinも削除された

この状態で1号機をシャットダウンすると、システムが正常に立ち上がりません。

そこでストレージのコンフィグファイルを変更します。

```
nano /etc/pve/storage.cfg 
dir: local
        path /var/lib/vz
        content iso,vztmpl,backup
        shared 1

lvmthin: local-lvm
        thinpool data
        vgname pve
        content rootdir,images
```
となっているところ、最後の行に

```
nodes 1gouki
```
と加えることで、1号機だけLVM-thinをリストアすることができました。

クラスタ化することでコンフィグファイルも共通になるということが原因でした。

ケースとしてあまり多くはないと思いますが、検証環境やアップグレード環境で、異なったファイルシステムでクラスターを組む場合は注意が必要です。
python のインストール手順

# python のインストール手順
　MacにPythonの３系をインストールするのに、ハマったのでメモ

## phythonのインストール

[こちらの](https://kredo.jp/media/mac-python-installation/)Homebrew + pyenvを使用した手順でインストールを行う
Homebrewとpyenvのインストールは略

ターミナルで下記コマンドを実行して、 
最初にインストール可能なヴァージョンの確認
  
```
$ pyenv install --list
```  

実行結果

```
Available versions:
  2.1.3
  2.2.3
  2.3.7
  2.4.0
  2.4.1
  2.4.2
  2.4.3
  2.4.4
  2.4.5
　・
　・
　・
```  

今回は3.9.4をインストールしたいので、下記を実行

```
$ pyenv install 3.9.４
```  

成功↓

```
python-build: use openssl@1.1 from homebrew
python-build: use readline from homebrew
Downloading Python-3.9.4.tar.xz...
-> https://www.python.org/ftp/python/3.9.4/Python-3.9.4.tar.xz
Installing Python-3.9.4...
python-build: use readline from homebrew
python-build: use zlib from xcode sdk

Installed Python-3.9.4 to {path}
```

念の為、versionsの確認

```
$ pyenv versions
```
↓のようにインストールしたversionsが出ていればよい

```
  system
* 3.9.4 (set by {path})
```

インストールしただけでは、適用されないので、
下記コマンドを実行

```
$ pyenv global 3.9.4
```

実行したら、versionの確認

```
$ python --version  
```

↓mac標準のversionsのまま。なんでさ

```
Python 2.7.16
```

https://github.com/pyenv/pyenv#homebrew-on-mac-os-x
によると以下手順が必要とのこと

```
$ pyenv init  
```
↓実行結果の指示通り、.zshrcに"eval "$(pyenv init -)"を追記または、 
記載していることを確認

```
# Load pyenv automatically by appending
# the following to ~/.zshrc:

eval "$(pyenv init -)"

```
下記、実行してversion確認

```
$ source ~/.bash_profile
```
```
$ python -V
```

↓インストールしたものが適用されました。

```
Python 3.9.4
```

これで、phytonのインストールは完了
スループット とは

## 勉強前イメージ

秒間どれだけ転送できたかというもの・・？

## 調査

### スループットとは

スループットとはデータの転送速度のことで、
毎秒あたりやり取りできるビット数(bps)で表される。

RFC2544では、フレームの損失が生じない最大のデータ量(1秒間あたりのフレーム数)のことになります

### フレームとは？

データリンク層(L2)を流れるパケットのこと。
データリンク層(L2)はOSI参照モデルで下から2番目。
ノード間の通信の決まりがされています


| レイヤー  | 名前                 | 
| --------- | -------------------- | 
| レイヤー7 | アプリケーション層   | 
| レイヤー6 | プレゼンテーション層 | 
| レイヤー5 | セッション層         | 
| レイヤー4 | トランスポート層     | 
| レイヤー3 | ネットワーク層       | 
| レイヤー2 | データリンク層       | 
| レイヤー1 | 物理層               | 

### スループットを測定してみる

- 今回の概要

```
今回はVM
サーバ側 : 192.168.156.121
クライアント側 : 192.168.156.122
```

- [サーバ側/クライアント側]インストール


```
yum install epel-release
yum install iperf
```

- [サーバ側]起動

```
iperf -s
```

- [クライアント側]接続

```
iperf -c 192.168.156.121
```

- 結果

サーバ側

```
[  4] local 192.168.156.121 port 5001 connected with 192.168.156.122 port 57276
[  4]  0.0-10.0 sec  2.83 GBytes  2.43 Gbits/sec
```
2.43 Gbits/sec なので、
0.303 GB/sec 出てることがわかりました。


クライアント側

```
[root@localhost ~]# iperf -c 192.168.156.121
------------------------------------------------------------
Client connecting to 192.168.156.121, TCP port 5001
TCP window size:  434 KByte (default)
------------------------------------------------------------
[  3] local 192.168.156.122 port 57276 connected with 192.168.156.121 port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-10.0 sec  2.83 GBytes  2.43 Gbits/sec
```

2.43 Gbits/sec なので、
こちらも0.303 GB/sec 出てることがわかりました。

## 勉強後イメージ

ニュアンス合ってた？と思う。
結構よく聞くけど、実はきちんと理解できてないんじゃない？シリーズ

## 参考

- [スループットとワイヤースピードは何が違う？](https://active.nikkeibp.co.jp/atclact/active/17/030800250/030800011/)
- [CentOS7上でiperfを使いネットワークの速度を測定](https://blog.reyfox.com/2019/01/centos7%E4%B8%8A%E3%81%A7iperf%E3%82%92%E4%BD%BF%E3%81%84%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E3%81%AE%E9%80%9F%E5%BA%A6%E3%82%92%E6%B8%AC%E5%AE%9A/)
【Google Maps API】本番環境でGoogle Mapが正しく読み込まれなかった原因と解決法

#本番環境でGoogle Mapを表示できない
>
<img width="400" alt="gmap-error.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646452/143037ec-e69f-1a5d-87f6-95080bb19615.jpeg">
このページではGoogleマップが正しく読み込まれませんでした。


#結論
####APIキーを `config/credentials.yml.enc`ファイルで管理する
（`.env`ファイルでなく）

##原因
本番環境にAPIキーを渡せていない

>新しく取得したキー設定の誤りだと思ったら、キーの管理方法という`基礎部分`の誤りでした。。

##経緯
1. `Google Maps API` 導入
1. ローカル環境でマップ表示できた
1. `APIキー`を`.env`ファイルで管理していた
1. `.env`ファイルは外部から見えぬよう、`Git`の対象から外していた
1. `AWSにデプロイ後`、ドメイン取得、HTTPS化してアクセスすると、マップ表示できなくなった
1. 本番環境にAPIキーを渡せていないのかも？（仮説）
1. 本番環境からは`.env`ファイルを参照できない！


##本番環境にも、`APIキー`を隠して渡す
`config.credentials.yml.enc`ファイルに`APIキー`を記述

```r:ローカルのターミナル
EDITOR=vi rails credentials:edit    #vimでファイルを開く
```

```r:config/credentials.yml.enc
google_map_api_key: xxxxxxxxxxxxxxxxxxxxxxxx     #APIキーを追記
```

ビューで、`config/credentials.yml.enc`ファイルの記述を読み取る

```r:map.html.erb
<script src="https://maps.googleapis.com/maps/api/js?key=<%= Rails.application.credentials.google_map_api_key %>&callback=initMap" async defer></script>

#<%= Rails.application.credentials.google_map_api_key %>
#これで「config.credentials.yml.enc」ファイルの「google_map_api_key」を取得できる
```


```r:キーの読み取り方（記述の違い）
<%= Rails.application.credentials.google_map_api_key %>    #credentials.yml.encファイルからキー取得
<%= ENV['google_map_api_key'] %>                           #.envファイルからキー取得
```


#Google Mapが表示されない時の確認事項
- 取得したAPIキーをhtml内に記述しているか
- 支払い情報を登録しているか
 - 請求先アカウントを未設定の場合、マップが1日1回しか表示できないらしい
- 表示回数の制限「割り当て」が1回になっていないか
 - 回数制限がかかっているとMapが表示エラーになる可能性がある
- 請求アカウントとプロジェクトがひも付いているか


#参考
[GoogleMapが表示されないエラーが出た時の対処法](https://web.chichibu-life.com/googlemap-error/)
[Rails5.2から追加された credentials.yml.enc のキホン](https://qiita.com/NaokiIshimura/items/2a179f2ab910992c4d39)


#さいごに
`Google Maps API`導入は比較的スムーズに設定できました。（ローカルで）
マップがうまく読み込まれない主な原因は、`Google Cloud Platform`での設定が多いようですが、
`APIキー`を本番環境に渡せていないのは盲点でした。
キーやパスワードの管理方法について、セキュリティ面を見直すいい機会とはなりました。

間違っている点がありましたら、ご指摘いただけるとありがたいです。
tensorflow 2.x model.predictのメモリーリーク


# はじめに
tensorflow2.xでKerasのModel.predictを繰り返し実行したら、メモリ使用量がもりもり増えていったので、メモ。
Inputサイズが大きいというのもありますが、128Gメモリ、バッチサイズ4000、4回のpreditほどで124G張り付き。。。
ソースまで深追いはしていませんが、現状メモリーリーク(memory leak）があるようです。


```
ubuntu==18.04
python==3.8.5
tensorflow==2.4.1
nvidia-driver==465.19.01
cuda==11.0
```

# 対策：うまく行かなかったパターン

マニュアルにメモリをクリアしてみる。
疑似コードとしては以下のように修正

```python
for x in dataset:
    y_pred = mode.predct(x)

    # 明示的に削除とGC
    del y_pred
    y_pred = None
    gc.collect()
```
結果としては、多少（数ループ）改善したものの8000回のループ回したい要件としてはNG

# 対策：うまく行ったパターン

参考にしたのは、↓にリンクされていたgithubのissueをよく読んでみました。
するとpredict_on_batchでは問題なく動作するとのこと

http://jrf.cocolog-nifty.com/statuses/2020/01/post-fb4a8b.html

https://github.com/keras-team/keras/issues/13118


疑似コードとしては以下のように修正

```python
for x in dataset:
    y_pred = mode.predct_on_batch(x)
```

20〜30Gぐらいで均衡を保つようになりました
Railsルーティング　よく使用するメソッドのまとめ

#はじめに
ルーティングのメソッドについてふわっとした理解のままでいたので、改めて今まで使ってきたもの、プラスそのメソッド周りのオプションをまとめてみた。

・resources
・only(オプション)
・except(オプション)
・collection
・member
・on(オプション)
・namespace
・scope
・as（オプション）
・controller

***

###resources
CRUD機能のルートを一式定義できる

```
resources :blogs
```

####:only
onlyオプションは特定のルーティングを作成

```
resources :blogs, only: [:index]
```

####:except
exceptオプションはonlyの反対で指定したアクションは作成しない

```
resources :blogs, except: [:edit, update]
```
***

###resourcesにブロックを渡す
collection, member

####collection
idを必要としないルーティングの生成`/blogs/confirm`

```
resources :blogs do
  collection do
    get 'confirm'
  end
end
```

####member
idを必要とするルーティングの生成`/blogs/1/preview`

```
resources :blogs do
  member do
    get 'preview'
  end
end
```

####on
onオプションはcollection, memberのブロック内にルーティングが1つしかない場合は省略して書くことができる。

```
resources :blogs do
  get 'confirm', on: :collection
end

resources :blogs do
  get 'preview', on: :member
end
```
***

###namespaceとscope

####namespace
多数のコントローラ群をまとめることができる
ファイル構成も指定される
これによりURL、名前付きルーティングヘルパー（パス）などが生成される

```ruby:controllers/admin/users_controller.rb
namespace :admin do
  resources :users
end
```

例

```
Helper　    HTTP　　URI Pattern　　　　　 　　Controller#Action
admin_users GET    /admin/users(.:format)  admin/users#index 
```

####scope
URLのパスの指定のみ
ファイル構成、ルーティングヘルパーは変わらない


```ruby:controller/articles_controller.rb
scope :blogs do
  resources :articles
end
```

例

```
Helper　 HTTP　　URI Pattern　　　　　　　    Controller#Action
articles GET    /blog/articles(.:format)   articles#index
```
####as
scopeにasオプションを使用すると、ルーティングヘルパーに名前をつけることができる
（他にも:modle, :pathを指定できる）

```ruby:controller/articles_controller.rb
scope :blogs do
  resources :articles, as: 'hoge_articles'
end
```

例　ヘルパーのみ変更されてる

```
Helper　      HTTP　　URI Pattern　　　　　　　     Controller#Action
hoge_articles GET    /blogs/articles(.:format)   articles#index

```

namespaceスコープは:moduleや:pathプレフィックスに加えて:asも自動的に追加される。
***

###controller

コントローラーを指定してコードをまとめることができる。
構造と結びつけて記述することで可読性があがる

```
  controller :blogs do
    scope :blogs do
      resources :articles, as: 'hoge_articles'
    end
  end
```

***

###ネストしたルーティング
親子関係をルーティングで表現できる
親に加えて、ネストされた子のルーティングも生成される

```
resources :admins do
  resources :users
end
```

(namespaceと何が違うの？？ということで上記のnamespaceと同じコントローラー名で比較してみた。)
`URL: /admins/:admin_id/users(.:format)`親のidが追加されていた、以上

```
Helper　      HTTP　　URI Pattern　　　　　　　           Controller#Action
admins_users  GET   /admins/:admin_id/users(.:format)  users#index
```

***※ネストは1回にとどめること、2回以上はルーティングが扱いにくくなる。***
sedコマンド

# テキストファイルを一括編集
※「シス環系女子 season2 第6話」の備忘録です。

以下、テスト用ファイル。

```
$ cat test.log
1,hoge,hogehoge
2,fuga,fugafuga
3,piyo,piyopiyo
4,foo,foofoo
5,bar,barbar
6,bar,barbar
7,baz,bazbaz
```

## sedコマンド
- スクリーンエディタ：geditやvimのように、テキストファイルの内容を表示しながらリアルタイムで対話的に編集できるエディタ。
- ストリームエディタ：テキストをコマンドラインオプションで指定して編集できるエディタ。

### 使い方

```
$ cat test.log | sed -e "s/bar/bora/" > ./test_sed.log

$ cat test_sed.log
1,hoge,hogehoge
2,fuga,fugafuga
3,piyo,piyopiyo
4,foo,foofoo
5,bora,barbar
6,bora,barbar
7,baz,bazbaz
```

※以下のように実行すると、ファイルが消失してしまうので注意。1つのコマンド列の中で、ファイルを開く操作と、そのファイルに書き込む操作を同時にしないこと。

```
$ cat test.log | sed -e "s/bar/bora/" > ./test.log
```

### sedのメリット
 - シェルスクリプトに書けるので、文字列置換を自動化できる点。
 - シェルスクリプトに書けるので、他のコマンド（grep, cu5t, sort, uniq, wc, if, for）などと組み合わせて使える点。

以下のように、index.htmlの部分を空文字に置換して、index.htmlの有無の違いを無視するなどといった使い方もできるみたい。

```
cat access.log | cut -d " " -f 7 | sed -e "s/index.html//" | sort | uniq -c | sort -n
```