OmniAICreator/Qiita-1.07M huggingface dataset:
wfs - Go で書き込み可能な io/fs

## wfs とは

[jarxorg/wfs](https://github.com/jarxorg/wfs) で開発している Go標準 の io/fs を拡張したライブラリです。 現在は以下のファイルシステムをサポートしています。

- osfs
- memfs
- s3fs
- gcsfs

## 開発の動機

Go で S3 や GCS を使うほとんどのプロジェクトで、クラウドストレージにアクセスするためのインタフェースを新しく定義し、開発用にローカルファイルシステムの実装、テスト用にメモリ上での実装をして切り替えれるようなコードを書いてきました。

Go1.16 から登場した io/fs は今のところ読み取り専用で、書き込みについては [proposal: io/fs: add writable interfaces](https://github.com/golang/go/issues/45757) などで議論されていますが簡単には進まなそうです。

その Issue でも紹介されている afero や billy は非常に優秀ですが S3 に対応していなかったりして微妙に私のユースケースにマッチしません。

そこで io/fs を拡張した wfs を開発することにしました。

## 書き込みサンプル

```go
package main

import (
	"fmt"
	"io/fs"
	"log"
	"os"
	"strings"

	"github.com/jarxorg/gcsfs"
	"github.com/jarxorg/s3fs"
	"github.com/jarxorg/wfs"
	"github.com/jarxorg/wfs/memfs"
	"github.com/jarxorg/wfs/osfs"
)

func newFS(dir string) fs.FS {
	if strings.HasPrefix(dir, "s3://") {
		return s3fs.New(strings.TrimLeft(dir, "s3://"))
	}
	if strings.HasPrefix(dir, "gs://") {
		return gcsfs.New(strings.TrimLeft(dir, "s3://"))
	}
	if strings.HasPrefix(dir, "memfs://") {
		return memfs.New()
	}
	return osfs.New(dir)
}

func main() {
	dir := "memfs://dummy"
	if len(os.Args) > 1 {
		dir = os.Args[1]
	}

	name := "example.txt"
	content := []byte(`Hello`)

	fsys := newFS(dir)
	_, err := wfs.WriteFile(fsys, name, content, fs.ModePerm)
	if err != nil {
		log.Fatal(err)
	}

	wrote, err := wfs.ReadFile(fsys, name)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("wrote: %s/%s\n\n%s\n", dir, name, string(wrote))
}
```

## CopyFS サンプル

書き込めるようになったので、便利な CopyFS 関数という副産物も生まれました。

```go
package main

import (
	"log"

	"github.com/jarxorg/s3fs"
	"github.com/jarxorg/wfs"
	"github.com/jarxorg/wfs/osfs"
)

func main() {
	src := s3fs.New("your-bucket")
	dst := osfs.DirFS("local-dir")

	// NOTE: Copy files on s3://your-bucket to local-dir.
	if err := wfs.CopyFS(dst, src, "."); err != nil {
		log.Fatal(err)
	}
}
```

上記は s3 バケットからローカルにコピーするサンプルですが、以下も同じようなコードで簡単にできます。

- gcs バケットから s3 にコピー
- ローカルからメモリにコピー

※ 並列実行などしていないのであまり巨大なバケットのコピーにはご注意ください。

## S3 や GCS の認証

S3 ならば [s3fs.NewWithAPI](https://pkg.go.dev/github.com/jarxorg/s3fs#NewWithAPI) や [s3fs.NewWithSession](https://pkg.go.dev/github.com/jarxorg/s3fs#NewWithSession)、GCS ならば [gcsfs.NewWithClient](https://pkg.go.dev/github.com/jarxorg/gcsfs#NewWithClient) を使うことができます。

## 最後に

いまのところ追加開発の予定はありませんが、バグなどあれば精力的になおしていくつもりです！
【Rails】サブディレクトリで動かす方法

## サブディレクトリで動かす方法

```./config/environments/development.rb
require "active_support/core_ext/integer/time"

Rails.application.configure do
  # Settings specified here will take precedence over those in config/application.rb.

  # In the development environment your application's code is reloaded any time
  # it changes. This slows down response time but is perfect for development
  # since you don't have to restart the web server when you make code changes.
  config.cache_classes = false

  # Do not eager load code on boot.
  config.eager_load = false

  # Show full error reports.
  config.consider_all_requests_local = true

  # Enable server timing
  config.server_timing = true

  # Enable/disable caching. By default caching is disabled.
  # Run rails dev:cache to toggle caching.
  if Rails.root.join("tmp/caching-dev.txt").exist?
    config.cache_store = :memory_store
    config.public_file_server.headers = {
      "Cache-Control" => "public, max-age=#{2.days.to_i}"
    }
  else
    config.action_controller.perform_caching = false

    config.cache_store = :null_store
  end

  # Store uploaded files on the local file system (see config/storage.yml for options).
  config.active_storage.service = :local

  # Don't care if the mailer can't send.
  config.action_mailer.raise_delivery_errors = false

  config.action_mailer.perform_caching = false

  # Print deprecation notices to the Rails logger.
  config.active_support.deprecation = :log

  # Raise exceptions for disallowed deprecations.
  config.active_support.disallowed_deprecation = :raise

  # Tell Active Support which deprecation messages to disallow.
  config.active_support.disallowed_deprecation_warnings = []

  # Raise an error on page load if there are pending migrations.
  config.active_record.migration_error = :page_load

  # Highlight code that triggered database queries in logs.
  config.active_record.verbose_query_logs = true


  # Raises error for missing translations.
  # config.i18n.raise_on_missing_translations = true

  # Annotate rendered view with file names.
  # config.action_view.annotate_rendered_view_with_filenames = true

  # Uncomment if you wish to allow Action Cable access from any origin.
  # config.action_cable.disable_request_forgery_protection = true

  # 以下追記
  Rails.application.config.relative_url_root = "/subdir"

end

```

```./config.ru
# This file is used by Rack-based servers to start the application.

require_relative "config/environment"

# 以下編集
map ActionController::Base.config.relative_url_root || "/" do
  run Rails.application
end

Rails.application.load_server

```

```zsh:ターミナル
$ rails s
```

![スクリーンショット 2022-09-01 17.42.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/14d0d92f-6a6c-0898-1f9a-cbe6930685ec.png)
Log::Debugってobject出力できないのかい

## Log::Debugはobjectを出力できない
中身がobjectの変数を
```php
Log::debug($hoge)
```
という感じにそのまま出力しようとしたら
```
Object of class 〇〇 could not be converted to string
```
ってエラー出た
`laravel.log`でログ見たいのに…

## 解決法
```php
Log::debug(print_r($hoge,true))
```
のように、`print_r()`を挟む事によって解決

trueを忘れると、変数の中身ではなく、中身の有無（boolean）で表示されてしまうので注意
個人的に使っているdocker関連のエイリアスコマンド

# 概要

仕事でDockerコマンド使う際によく使っているものをエイリアスにしていたので、メモ。
完全に個人のメモです。すいません。はい。

```sh
# docker-compose
alias up="docker-compose up"
alias down="docker-compose down"
alias build="docker-compose build"
alias pull="cd ~/Projects/online-exhibition-env/ && oe-login && docker-compose pull && cd -"

# docker remove
alias remove-all-volumes="docker volume ls -q | xargs docker volume rm"
alias remove-all-containers="docker ps -aq | xargs docker rm"
alias remove-all-images="docker images -aq | xargs docker rmi -f"
alias all-docker-remove="remove-all-containers && remove-all-images && remove-all-volumes"
```
外部企業による労働力の提供

一つ一つの仕事によって従業員を増減させるわけにはいけないので人材派遣会社にお願いして人を出してもらい、
足りない部分を補う。

# 請負と派遣で違う、指揮命令系統
### 請負の場合
請負会社雇われている人は```雇われている会社の指揮のもと```、他の会社から```請け負った会社の仕事を行う```。

#### 請負とは？
民法の規定によると、請負とは典型契約の一種であり、```請負人がある仕事の完成を約束```し、発注者が```結果に対して報酬を支払う```ことを約束するものです。ひと口に請負といっても、プログラムやシステムの開発、ホームページ制作、建物の建築・増改築、土木工事など内容は実に多岐にわたります。
出典 https://www.nikken-totalsourcing.jp/business/tsunagu/column/128/

### 派遣の場合
派遣会社に雇われている人は、```派遣先の会社の指揮のもと派遣先の仕事```を行う。

#### 派遣とは？
労働者派遣とは
労働者派遣事業の適正な運営の確保及び派遣労働者の保護等に関する法律（労働者派遣法）に基づき、労働者派遣事業者である```派遣元企業が雇用する労働者に、派遣先企業内で業務を行わせる```ことを指します。つまり```労働者を雇用する企業と、実際に業務に就く企業が異なる```ということです。

クライアント企業からの要請があった場合など、必要に応じて派遣元で労働者を雇用する「登録型」と、その労働者を常時派遣元で雇用する「常用型」の2種類があります。登録型派遣は一般労働者派遣事業（許可制）、乗用型派遣は特定労働者派遣事業（届出制）と分けられていましたが、平成27年の改正法施行によって、すべての派遣事業が許可制になりました。

やはり```請負契約と違って、仕事の完成を目的としていません```。業務自体が目的であり、```派遣スタッフの指揮命令権は派遣元企業から委託を受けた派遣先企業```にあります。```雇用主は派遣元企業なので、賃金の支払いや社会保険の加入、雇用管理などの業務は派遣元企業が担います。```

労働者を派遣する際は、派遣元企業と派遣先企業の間で「労働者派遣契約」を結びます。契約には次のような項目を盛り込まなければなりません。（労働者派遣法第26条）
出典 https://www.nikken-totalsourcing.jp/business/tsunagu/column/128/

# 問題を解いた時の気づき
労働者派遣法において、派遣先の会社から直接派遣社員の休みの変更はできないのか。
突然rails: command not foundと言われてびっくりした時の話。

## おこった事
`rails db:migrate`を（docker環境）をしようとしたら以下のエラーが起こった。

```sh
rbenv: rails: command not found
```

いや、そんなはずないでしょ。`docker`でrailsは立ち上がっているんだし。(↓こんなのは出てた)

```sh
app-name            | Puma starting in single mode...
app-name            | * Version 3.12.1 (ruby 2.4.5-p335), codename: Llamas in Pajamas
app-name            | * Min threads: 5, max threads: 5
app-name            | * Environment: development
app-name            | * Listening on tcp://0.0.0.0:3000
app-name            | Use Ctrl-C to stop
```
## 原因
結論から言うと、直前にRailsをアップデートしていたのが原因で、gem の`rails`へのパスが通らなくなっていた模様。

## 対処法
まず、rails を立ち上げているコンテナの中に入り、以下のコマンドでgemのインストール先を確認。
```sh
docker exec -it app-name bash
# コンテナ内で
gem environment
```
出力結果（の一部）がこちら
```
RubyGems Environment:
  - RUBYGEMS VERSION: 3.0.3
  - RUBY VERSION: 2.4.5 (2018-10-18 patchlevel 335) [x86_64-linux]
  # 中略
  - EXECUTABLE DIRECTORY: /usr/local/bundle/bin
  - SPEC CACHE DIRECTORY: /home/docker/.gem/specs
  # 中略
  - SHELL PATH:
     - /usr/local/bundle/gems/bin
     - /usr/local/sbin
     - /usr/local/bin
     - /usr/sbin
     - /usr/bin
     - /sbin
     - /bin
```

gemを実行する `EXECUTABLE DIRECTORY` が `SHELL PATH`の中に含まれていなかったのが原因でした。
ちゃんと絶対パスを使用すれば`rails` コマンドが使えることを確認して...

```bash
# コンテナ内で
/usr/local/bundle/bin/rails -v
Rails 5.0.7.2
```
パスを通したら解決できました。
```bash
# コンテナ内で
export PATH="/usr/local/bundle/bin:$PATH"
```
を実行したら直りました。
Railsをアップグレードするとこんなことが起こるんですね。。。。

（参考ですが、上記コード内のRailsのバージョン等は、色々なアプリから拾ってきているので適当です。実際にエラーが出たアプリではもっと新しいものを使用しています。）

手前味噌ですがパスを通すコマンドの書き方はこちら。
https://qiita.com/sazumy/items/eb3b26906faeba4ab463
ハンバーガーメニュー最適解（デザインのみ）

## 結論
**個人的**最適解です。
<p class="codepen" data-height="400" data-default-tab="html,result" data-slug-hash="OJZLJpo" data-user="ueda-kio" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/ueda-kio/pen/OJZLJpo">
  hamburgerMenu</a> by Men_Tori (<a href="https://codepen.io/ueda-kio">@ueda-kio</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>


### ポイント
- デザインである横棒は擬似要素で実装
- ボタン内にテキストを持たせ、ボタンの目的を表す
- `type="button"`をしっかり書く


## よくあるやつ
見た目・機能は全く同じです。
<p class="codepen" data-height="400" data-default-tab="html,result" data-slug-hash="abGobGJ" data-user="ueda-kio" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/ueda-kio/pen/abGobGJ">
  hamburgerMenu__notGood</a> by Men_Tori (<a href="https://codepen.io/ueda-kio">@ueda-kio</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>


### よくないポイント
- デザインを空要素（`span`）で実装している
- `button`要素にアクセシブルなテキストがセットされていない
- デフォルトの`type="submit"`になっている



## 気をつけたいポイント
### 1. デザインの実装はCSS or 擬似要素で行う
よくある実装の方では、デザインである横棒を`span`要素で実装しています。が、基本的にデザインの実装はcssのみで行い、それでは実装が難しい場合でも、空要素をおくのではなく擬似要素で実装するようにしましょう。
HTMLの仕様上では、ほぼすべての要素が該当する*パルパブルコンテンツ*は、**空要素ではいけない**という仕様となっています。
[HTML Standard - パルパブルコンテンツ](https://momdo.github.io/html/dom.html#palpable-content)

> …コンテンツ内に少なくとも1つのノードを持つべきである。これがパルパブルコンテンツであり、hidden属性が指定されていない。


ということで、空の`span`要素でデザインを実装することは避けましょう。

<details>
<summary>【余談】</summary>

`div.spacer`みたいな空`div`で余白を取る実装があると考えてみてください。とっても違和感＆奇妙に感じますよね👀
空の`span`でハンバーガーを実装することもこれくらい奇妙に私は感じます。

</details>

### 2. `button`要素にアクセシブルなテキストを挿入する
`button`要素や`a`要素などには、その目的を表すアクセシブルな（識別可能な）テキストが必要です。テキストが含まれていない`button`要素はいけませんよ〜、ということですね。
ということで、**`button`要素内は空っぽにせず「メニューを開く」などのテキストを入れておきましょう**。
（詳細は避けますが、アクセビリティAPIに伝わればよいので、`aria-label`でもよきです）

▼ devtoolによってはおこってくれます
![0D6F31CF-8CE2-4A89-9E13-0E27A4971B46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1157551/637090ab-f85c-8a7f-5eff-19e08ed7fe9f.png)


### 3. `button`の`type`属性を省くと`type="submit"`扱いになる
`button`要素の`type`属性は3種類あり（[参考](https://momdo.github.io/html/form-elements.html#attr-button-type)）、初期値は`submit`となっています。
**ハンバーガーメニューはもちろん送信ボタンではないので、`type="button"`を明示したほうがよい**でしょう。

とはいえ、親要素に`form`要素が存在しない`button`要素の場合は処理が自動で`return`されますが、それでも明示した方がよいと考えています。


> A button element element's activation behavior is:
>1. If element is disabled, then return.
>2. If element does not have a form owner, then return.
>3. If element's node document is not fully active, then return.
>4. Switch on element's type attribute's state:




## おわりに

個人的ベストプラクティスでした。
「**仕様の解釈ちがうぞ！**」「**もっとこっちのほうがいいぞ！**」「**そんなんじゃぜんぜんだめだ！**」
などありましたらどしどしくださいませ。
経営戦略と自社のポジショニング

# 経営戦略の手段
企業同士の提携、他社を買い取ってしまうM&A、他社に業務委託するアウトソーシング、自社製品へのリピーターが増える顧客満足度の向上

## アライアンスとは？
英語で```「提携」「同盟」などの意味```を持つ言葉で、ビジネスの世界では```企業同士が業務提携を交わす経営スタイル```を指します。日本においては、経済のグローバル化が進み、国際的にも企業提携が活発化し出した1990年代後半からアライアンスという言葉が使われるようになりました。
アライアンスを交わることによって、```提携先の技術や資本・人員などのリソースを共有することが可能```となり、自社単独で行うよりも```既存事業の拡大や新規事業のスタート等が容易```になります。また、アライアンスにおいて```当事者間は協力関係にあり、対等な立場```で事業を展開できるのが特徴です。
出典　https://www.mresearch-media.net/column/alliance-overview-understanding/#:~:text=%E3%82%A2%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%82%B9%E3%81%AF%E8%8B%B1%E8%AA%9E%E3%81%A7%E3%80%8C%E6%8F%90%E6%90%BA,%E3%82%88%E3%81%86%E3%81%AB%E3%81%AA%E3%82%8A%E3%81%BE%E3%81%97%E3%81%9F%E3%80%82

# SWOT分析
自社の強みと弱みを分析する手法。
この手法は、自社の現状を```強み（Strength)```、```弱み(Weakness)```、```機会(Opportunity)```、
```脅威(Threat)```の４つの要素がある。

## ４つ要素の関係
### 積極的構成
```自社の強みによって取り込める```事業機会とは？

### 差別化戦略
```自社の強みによって脅威を回避```する方法とは?

### 段階的施作
```自社の弱みによって事業機会を逃さない```ために何をすべき？

### 専守防衛or徹底
```自社の弱みと脅威によって起こりうる最悪の事態```とその回避方法は？

### 図の紹介（説明の言葉は違うけど）　

https://mirasapo-plus.go.jp/hint/16748/

# プロダクトポートフォリオマネジメント
略して```PPM: Product Portfolio Management)```という。

これは```経営資源の配分バランスを分析```する手法のこと。

縦軸に試乗成長率、横軸に市場占有率（シェア)を取る。
各社の製品やサービスを```花形```、```金のなる木```、```問題児```、```負け犬```という４つの分類にする。

それらの分類に対して資源の配分が決まる。

### 花形
現在は```大きな資金の流入をもたらしている```もののそれと同時に```将来にわたっての資源投下も必要```な事業

### 金のなる木
現在は```資源の主たる供給者の機能を果たしている```ものの```新たに資金を投下すべき```ではない事業

### 問題児
```資金投下を費用としている```が、事業としての魅力はあり、```将来の資金供給者となる可能性```のある事業

### 負け犬
事業を成長させるために```資金を投下する必要性が低く```、```将来的に撤退を考えざるを得ない```事業

### 図が書かれています

https://innova-jp.com/product-portfolio-management/

## 気づき
負け犬か。ちょっと...まぁいいか

# コアコンピタンスとベンチマーキング
企業活動を改善する指標となる```コアコンピタンス```と```ベンチマーキング```を紹介する。

### コアコンピタンス
```他社には真似のできない```、その企業独自の```ノウハウや技術などの強み```のこと。
```これらの強みを核として注力```する手法

### ベンチマーキング
```経営目標の際のベストな手法を得るため```に、最強の競合相手または先進企業と```比較することで、製品、サービス、および実践方法を定性的、定量的```に測定すること。

#### 定性的とは？
* 物事の様子または変化などを、```数字では表せない「性質」の部分に着目```して分析するさま
出典 https://www.weblio.jp/content/%E5%AE%9A%E6%80%A7%E7%9A%84

* 物事が```数値化できない要素```のこと。
  ...
  数字を使わない```表現はしばしば抽象的になってしまい、認識がそろわない可能性```があります。ビジネスにおいては、```少しの認識のずれが致命的なトラブルを招く```ことがありますので、話者と聞き手が```共有認識を持つための工夫が必要```ですし、認識が異なっていないか常に注意することが必要です。

出典 https://www.hrbrain.jp/media/evaluation/quantitative-qualitative
* ```数値化出来ない目標```のことです。成果に至るまでのプロセスに注目し、その行動のバリューを測るための目標でもあります。　結果ではなく```「行動価値」に着目した目標```であるため、```「行動目標」とも呼ばれています```。「定性目標」と「行動目標」の意味は同じと考えていいでしょう。
    出典 https://resily.com/blog/15885#anker1
#### 定量的とは？
* ```物事を数値や数量に着目```してとらえること。
  ...
  数値や数量は```共通の概念ですから、お互いに違う認識をする心配がほとんどありません```。
  出典 https://www.hrbrain.jp/media/evaluation/quantitative-qualitative

* 「定量」は```目標にたどり着くためのプロセスを数値化したもの```です。わかり易い例としてダイエットがあります。ただ単に「痩せたい」という目標では、「痩せる」という状態が曖昧になってしまいます。これを定量的にすると、「今の体重からマイナス10キロの状態」というように数値で表すことが出来ます。```数値化することで、進捗状況を客観的に把握```することができるのです。
    出典 https://resily.com/blog/15885#anker1

##### 気づき
* 定性的と定量的は反対の意味なのか。
* 定性的とはどのような行動をしている。
* 定量的は数値で結果を出している。
【vue, nuxt】$listenerでデータ受け渡しを高速でおこなう

# 概要
emitを使って孫コンポーネントから親コンポーネントにデータを渡していきたいことがよくある。これまでは恥ずかしながら、下記のようにしてデータの受け渡し、イベント伝播を行っていた。

※ マークダウンの都合上ファイル拡張子をjsにしている

```grandchild.js
// template
<Button @update="update">

// script
update(value) {
	this.$emit('update', value);
}
```
```child.js
<Button @update="$emit('update')">

// script
update(value) {
	this.$emit('update', value);
}
```
```parent.js
<Button @update="update()">

// script
update(value) {
  console.log(value)
}
```

まだコンポーネントが三つだからいいものの、これが４つ５つ...100個とかになるとかなりめんどくさいことになると気づいた。(ない)
これをなんとかして楽にする方法を考えたときに素晴らしい方法に出会うワイ。

# $listener
ここで出てくるのが$listener。
これをコンポーネントとコンポーネントの間のコンポーネント(この場合はchild.js)で使うとイベントをscriptに登録する手間が省ける！！
これにより可読性もかなり上がること間違いなし

```grandchild.js
// template
<Button @update="update">

// script
update(value) {
	this.$emit('update', value);
}
```
```child.js
<Button @update="$listeners['update']">

// script
// ここが不要になる
// update(value) {
//	this.$emit('update', value);
// }
```
```parent.js
<Button @update="update()">

// script
update(value) {
  console.log(value)
}
```

書き方としては
当コンポーネントの子コンポーネントで登録されたイベント名(今回はupdate)をupdate()としていたものの代わりに$listener['update']とするだけでよい
```javascript
@update="$listeners['update']"
```
@overrideアノテーションについて

# アノテーションの種類

### @override

- **overrideをつけると「必ずオーバーライドしてください」と指定することが可能**
- スペルミスなどが抑制できる

```

public class Test extends TestOverride {
　
           @Override
           public void outputs() {
                            System.out.println(“Hello World!”);
           }
　
           public static void main(String[] args) {
                      TestOverride cl = new TestOverride();
                      cl.output();
           }
}
　
public class TestOverride {
　
           public void output() {}
}
```

```
Documents $ 1java test.java
test.java:3: エラー:メソッドはスーパータイプのメソッドをオーバーライドまたは実装しません
           @override
           ^
エラー1個
エラー:コンパイルが失敗しました
Documents $ 1
```

参考にした記事
> 初心者向け】Javaのアノテーションの使い方を解説！代表例から自作方法まで
> https://www.tech-teacher.jp/blog/java-annotation/#:~:text=%E3%81%AE%E3%81%8A%E5%95%8F%E3%81%84%E5%90%88%E3%82%8F%E3%81%9B-,%E3%82%A2%E3%83%8E%E3%83%86%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%A8%E3%81%AF,%E3%81%AA%E3%81%93%E3%81%A8%E3%81%8C%E8%A1%8C%E3%81%88%E3%81%BE%E3%81%99%E3%80%82
git push で remote: Repository not found. fatal: Authentication failed for ‘xxx’ と言われた

GitHubに`git push`をしたらある日突然エラーになった。VSCode内のターミナルで実行した場合に出たエラーが以下。

```console
$ git push
Missing or invalid credentials.
Error: connect ECONNREFUSED /run/user/1000/vscode-git-c4b2e1d8a0.sock
    at PipeConnectWrap.afterConnect [as oncomplete] (node:net:1161:16) {
  errno: -111,
  code: ‘ECONNREFUSED’,
  syscall: ‘connect’,
  address: ‘/run/user/1000/vscode-git-c4b2e1d8a0.sock’
}
Missing or invalid credentials.
Error: connect ECONNREFUSED /run/user/1000/vscode-git-c4b2e1d8a0.sock
    at PipeConnectWrap.afterConnect [as oncomplete] (node:net:1161:16) {
  errno: -111,
  code: ‘ECONNREFUSED’,
  syscall: ‘connect’,
  address: ‘/run/user/1000/vscode-git-c4b2e1d8a0.sock’
}
remote: Repository not found.
fatal: Authentication failed for ‘https://github.com/xxxx/xxxx.git/’
```

# 解決した方法
`git push` 等をするときにパスワードの代わりに入力するGitHubのPersonal access token(PAT)の期限が切れていた。デフォルトだと数ヶ月で切れるらしい。知らなかった。

以下のリンクの手順に従って新しいトークンを作成する。期限が切れたトークンをそのまま使うことはできないし、期限を延長することもできない。ただし新しいトークンを作成するときに期限を無期限にすることはできる模様。
[https://docs.github.com/ja/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token](https://docs.github.com/ja/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token)
循環する配列で「次のnまでの距離」をシンプルに導く

# 循環配列

```js
const cycle = [0, 1, 2, 3, 4, 5]
>>> 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 0 -> 1 -> 2 -> 3 ...
```
距離は配列内での要素間の絶対値ではなく循環参照時に於いての距離、例えば
>「現在4にいる。次に2を参照するのは何回後か」

を導出したい
以降現在地(例で言う4)を**p**、目的地(例で言う2)を**t**、配列全体の長さを**L**と表記する
なお`p`、`t`は配列内の位置、インデックスである

## 愚直なやり方
### 配列内で p <= t のとき
簡単
```js
t-p
```

### 配列内で p > t のとき
上の例のような場合、`t-p`では距離が負の値になってしまうため1周分を足して
```js
t-p+L
```
とする必要がある。
`p<=t`と`p>t`の場合で条件分岐させるのは面倒。

## 結論
```js
(t-p+L)%L
```
`%`は剰余。`t-p+L`÷`L`の余り。`p<=t`と`p>t`で商が1か0かに変わるだけで、剰余はいずれの場合も同じ

## 使い道
- 曜日を循環配列に格納して「今日の曜日から起算して次の月曜日は何日後」
- 干支を循環配列に以下略

## 注意点
初めに言及した通り現在地と目的地が要素内容ではなくインデックスで判明していることが条件なので「次に内容が〇〇である要素までの距離」などにはそのままでは使えない
【JavaScript】「この変数は値が変わるからconstで変数宣言出来ないな」は間違い？

## はじめに
過去の自分は、**`const`で宣言した変数の値は変えることができない**という理解をしていて
「この変数は値が変わるかもしれないから一応`let`で変数宣言しよ」
と`let`ばかりを使っていました。

しかしこの理解が誤っていることを最近知り、
「あの`let`で宣言してた変数全部`const`でよかったじゃん！」
「定数管理したくて`const`で宣言したけど意味なかったなあ」
と後悔することになったので、反省を込めて`const`についてまとめてみました。

## 結論
結論から言うと、

**`const`は値の参照を読み取り専用で作成します。**
別の言い方をすれば
**`const`で宣言された変数は、あくまでもアドレス(参照先)の変更ができないだけとなります。**


つまりアドレスが変更されない処理であれば、`const`で宣言された変数の値を変えることは可能となります。いきなり言われてもピンと来ない方もいらっしゃると思うので、変数に代入されたデータがミュータブル(変更可能)な場合とイミュータブル(変更不可能)な場合で比較しながら以下で具体的な挙動を説明します。

(※参考資料: [ミュータブルな型とイミュータブルな型の相違を知ろう](https://qiita.com/makotoo2/items/fc3a617882916f9775f5))

## 具体的な挙動
### 変数にミュータブルなデータが代入された場合
```javascript
const array = [1,2,3]
array[0] = 10
console.log(array) //=> [10, 2, 3]
```
上記のように`const`で宣言された変数であっても値は問題なく変更できます。

これは**変数に格納されているデータがミュータブルなものであり、値を変更してもアドレス(参照先)が変更されないからです**。

しかし、例えば以下のような再代入などアドレスが変更されるようなコードは実行できません。
```javascript
const array = [1,2,3]
array = [10,20.30] //=> Uncaught TypeError: Assignment to constant variable.
```

### 変数にイミュータブルなデータが代入された場合
```javascript
const number = 10
number += 10 //=> Uncaught TypeError: Assignment to constant variable.

const str = 'str'
str += 'ing' //=> Uncaught TypeError: Assignment to constant variable.
```
上記のように、値の変更ができません。
これは**イミュータブルなデータの値を変更すると、アドレスも変更されるからです**。

以上のことから、
**「`const`で宣言された変数は、アドレスの変更ができない。」**
だけであり、
変数にミュータブルなデータが格納されている場合値を変更できるため、
「この変数は値が変わるからconstで変数宣言出来ないな」は不十分な表現であったことがわかります。

## 補足
constで宣言された変数の中身がミュータブルなデータであっても値の変更を不可能にしたい場合は、以下のようにすることで実装できます。
```javascript
const array = [1, 2, 3]
Object.freeze(array)
array[0] = 10
console.log(array) //=> [1,2,3]
```

また、凍結したデータの値を変更する処理があった場合に例外を発生させたいのであれば、厳格モードを使うことで以下のような例外を発生させることができます。
```javascript
'use strict' // 厳格モード使用
const array = [1, 2, 3]
Object.freeze(array)
array[0] = 10 //=> Uncaught TypeError: Cannot assign to read only property '0' of object '[object Array]'
```
マルウェアに感染したwordpressを中学生が自力で復活させた時のメモ

## 初めに
マルウェアに感染したwordpressを復活させたった(* -∀-)ﾄﾞﾔｯ♪.


## マルウェアとは

```
マルウェア とは、不正かつ有害に動作させる意図で作成された悪意のあるソフトウェアや悪質なコードの総称。
コンピュータウイルスやワームなどが含まれる。 
悪意のコード 、悪意のソフトウェア 、悪意のある不正ソフトウェア、有害なソフトウェア、不正プログラムとも呼ばれる。
@wikipedia 
```

## 駆除の流れ
1. wordpressのスキャンを行う
2. 感染したwordpressのコアファイルと通常のwordpressのコアファイルの差分を確認する
3. .htaccessやindex.phpを確認
4. スキャン結果を元に、ファイルを見ていく
5. 怪しいコードがあれば削除
6. 完治しているかのテスト


## wordpressのスキャンを行う
wordpressのプラグインを使用して、wordpressのスキャンを行います。
物によりますが、何時間かかかるものが多いので、その間に2番をやりましょう。

## コアファイルの差分を確認
真新しいwordpressを

https://wordpress.org

よりダウンロードしてきます。そして、ドキュメントルートに存在するwordpressコアファイルの差分を確認します。
スパムコードは難読化されていることが多いので、
「このコードめっちゃ読みにくいやん」
てな感じのコードがあれば、要チェックです。
参考に、よく改変されることが多いのは以下のファイルです。
```
wp-config.php
index.php
wp-setting.php
function.php
テーマのfunction.php
テーマのindex.php
```


## .htaccessやindex.phpの確認
次は.htaccess（えっちてぃーあくせす）ファイルを確認しましょう。
デフォルトの.htaccessは、
```
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
```
と、なっています。このほかに自分の書いた覚えがないコードが書かれていたら要注意。


## スキャン結果を元に、ファイルを見ていく

怪しいコードを探します。
難読化されたコードがあれば、要注意です。


## 怪しいファイルは削除

必ずバックアップを取った上で削除しましょう。
githubなんかにprivateでバックアップを取っておいて、いつでも直せるようにしておきましょう。
同時に、DBのバックアップもとっておくとなお良いです。


## 完治しているかのテスト
処置を行ったら、完治しているかのテストを行います。
リダイレクトチェッカーや、wordpressのスキャンサイトなどを活用して行ってください。

### もし治ってなかったら?
もう一度、1から手順を踏んでみてください。
気づいていなかったコードがあるかもしれません。

もし、それでも見つからないようであれば信頼できる業者に頼むことをお勧めします。

## 終わりに
バックアップは命。
アクセスVBAでIDENTITY付きのレコードを削除するとき

    lans = MsgBox("ID:" & id.Value & " を削除してもよろしいですか？", vbYesNo + vbInformation, "確認")
    If lans = vbYes Then
      strSql = "DELETE FROM table WHERE [id] = " & id.Value
      DoCmd.SetWarnings False
      DoCmd.RunSQL (strSql)
      DoCmd.Requery
      DoCmd.SetWarnings True
    End If
[小ネタ] Ansible Playbookでパラメータを安全に受け取りたい場合はJSONを使おう

## TL;DR

- Ansible Playbookで外部パラメータを安全に受け取りたい場合は、 `-e @JSONファイル.json` を使おう。
    - JSONファイルの生成には `jq` コマンドを使おう

## 説明

まず、タイトルのようにAnsible Playbookに外部パラメータを渡したい場合、 [`ansible-playbook` に下記のように引数を指定する](https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html)ことが考えられますが、パラメータに空白や `=` が入る場合などコーナーケースを考えると頭が痛くなってきます。

```bash
$ export var_a="foo bar=baz"

# -e "var_a=foo bar=baz var_b=..." のようになってしまい、 var_a の内容が最後まで渡されず壊れる
$ ansible-playbook -e "var_a=${var_a} var_b=${var_b}" playbook.yml

# => The content of var_a is foo!!
```

```yaml:playbook.yml
- name: Print about parameter var_a
  debug:
    msg: "The content of var_a is {{ var_a }}!!"
```

幸い、このオプションは `-e @my_parameters.json` のようにしてJSONファイルをそのまま渡すことができるので、それを使って空白などを考慮せずに安全にパラメータを受け渡しすることができます。また、JSONファイルの生成は [`jq` コマンド](https://stedolan.github.io/jq/) を使うと安全に生成できます。

```bash
$ export var_a="foo=bar bar=baz"

# JSONの生成
$ jq -n \
    --arg var_a "${var_a}" \
    --arg var_b "${var_b}" \
    '{
      var_a: $var_a,
      var_b: $var_b
    }' > tmp_params.json

# 上記で生成したJSONを参照
$ ansible-playbook -e "@tmp_params.json" playbook.yml

# => The content of var_a is foo bar=baz!!
```
【解説】PSDファイルの仕様（イメージデータセクション）

この記事は[PSDファイルの構造（基本構造編）](https://qiita.com/vram/items/8ac2d7bfd63840267109)からの続きになります。

## イメージデータセクション
各レイヤーごとの画像データを管理するセクションです。

レイヤーとマスクセクションのデータサイズにてレイヤー情報を全て読み込んだ直後のアドレスがイメージデータセクションになります。

このアドレスを基準に各レイヤーのチャンネルごとにイメージデータセクションのアドレスを計算します。
チャンネルが 3の場合は下記の順にイメージデータセクションに格納されています。

レイヤー0のチャンネル0のアドレスはレイヤー情報に続くアドレスが該当し、レイヤー0チャンネル1のアドレスは レイヤー0 のチャンネル0のデータサイズを加算した値が該当するイメージデータのアドレスになります。

| レイヤー | チャンネル |
|:-:|:-:|
|0   |0   |
|0   |1   |
|0   |2   |
|1   |0   |

そのためレイヤー情報を読み込んだ後は、イメージデータセクションのアドレス計算を行う必要があります。

### イメージデータ
セクション内にある1レイヤーの1チャンネルの画像データが格納されてるのがイメージデータです。
イメージデータは先頭2バイトが圧縮方法を表し、それ以降が実際のデータになります。

| 値 | 圧縮方法 |
|:-:|:-:|
|  0| 無圧縮  |
|  1| RLE圧縮  |

#### 無圧縮
圧縮しないデータ管理方法です、小さいサイズのデータの場合に採用されます。
イメージデータが縦32w x 横16h ピクセルで8bitのデータの場合
32w x 16h * 8bit / 8 = 512
512バイトのデータを読み込み画像データとします。

これを3チャンネル RGB分のデータを読み込み 1ピクセルがRGBそれぞれ 8bitの値を持つRGBの画素になります。
#### RLE圧縮
同じデータが繰り返される場合に最適な圧縮方法です。圧縮率はデータによって変わるため処理が完了するまでサイズは不明です。

イメージデータのY座標ごとに読み込むデータのバイト数を取得します。

| size |  |
|:-:|:-:|
|  2| Y=0 のデータバイト数  |
|  2| Y=1 のデータバイト数 |
||中略|
|  2| Y=15 のデータバイト数 |

次に Y=0の座標から順に圧縮データを処理します。
各Y座標毎にX＝0の地点から展開作業を開始します。
データのバイト数分を読み込んで展開処理が終わった後は
次のY座標に処理を移し、またX座標が0から再開します。

展開処理は下記の手順で行います。

1.データを1バイト取得
2.データが128未満であれば処理(3) データが128より大きい場合処理(9)へ
3.取得したデータに1を加算ループ回数とします、つまり 0であれば 1回処理に入ります
4.ループ処理の先頭
5.データを1バイト取得
6.[x,y]座標のデータとして格納
7.x座標を1加算
8.ループ(4)を繰り返す
9.取得したデータを FFhと XORした後 2加算したものをループ回数とします（2の補数）
10.データを1バイト取得
11.ループ処理の先頭
12.[x,y]座標のデータとして格納
13.x座標を1加算
14.ループ(11)を繰り返す
15.次のy座標がある場合は処理(1)からさいかい
【MEMO】Postgresでtable/viewの列定義を取得する

# Postgresでtable/viewの列定義を取得する

キャッシュしといて、定義変わったらときに再取得した良さげ。

``` SQL

SELECT
  t0.table_catalog,
  t0.table_type,
  t0.table_schema,
  t0.table_name,
  t1.column_name,
  t1.data_type,
  t1.is_nullable
FROM information_schema.tables t0
INNER JOIN information_schema.columns t1
  ON t0.table_schema = t1.table_schema
    AND t0.table_name = t1.table_name
WHERE t0.table_schema <> 'information_schema'
  AND t0.table_schema <> 'pg_catalog';

```

目指せ、なんちゃって汎用テーブル。
自前のStable Diffusionを他の人にも使わせる方法

# 未曾有のStable Diffusionブーム!!!
![未曾有の.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75653/240e5150-5ecd-9bee-150e-bf177b54226e.png)
タイトル通り、gradio版Stable Diffusionで生成したタイトル画像です。

いまAI画像生成でStable Diffusionが話題です。試した方は他の人にもオススメしたいくらいでしょう。
ただ、快適な環境は導入するのにひと手間どころでなく面倒。
だけど非エンジニアの人にはもっと楽に使わせてみたい。そんな願望に応えられる環境がありました。

導入をしなくていいだけのパッケージはタケノコのように増えています。これは、あなたの余りあるグラフィック性能を分け与えるのに使えます（私の説明文がヘッタクソな翻訳文なのはこういう文体が好きだからです。ほっといてくれ）。

## Gradio採用版StableDiffusion
Stable Diffusionのforkリポジトリです。 [gradio.app](gradio.app)を採用しており、GUIとサービス公開機能を備えています。
https://github.com/hlky/stable-diffusion

生成した画像をimg2imgやGANでの拡大を行うGUIに転送することもできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75653/c4f71fdb-a6f5-4a83-d398-ae012df961fe.png)


# 導入方法
## 事前条件
- 私はWindows+PowerShellで行っているので、その手順を示します。他の環境では読み替えてみてください。
- CUDA環境とCUDNNが入っている必要があります。
- [Anaconda](https://www.anaconda.com/products/distribution)を導入してください。
- Windowsの場合はGit環境が別途必要です。 [Git for Windows](https://gitforwindows.org/) やクライアントソフトを使用してください。

## Cloneする
1. Anaconda PowerShell Promptを立ち上げます。検索窓からanaと打ち込むと見つけることができます。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75653/1aa68e75-e380-16b1-0b18-63da5ad7c40d.png)
2. プロンプトからStable Diffusion Gradio版をCloneします。
     
    ```bash
    git clone git@github.com:hlky/stable-diffusion.git
    ```
    - すでにStable Diffusionがある場合には名前をつけておきましょう。

    ```bash
    git clone git@github.com:hlky/stable-diffusion.git stable-diffusion-test
    ```

## データセットの導入
1. https://huggingface.co/CompVis/stable-diffusion-v-1-4-original/blob/main/sd-v1-4.ckpt をダウンロードして下さい。
2. ckptファイルを models/ldm/stable-diffusion-v1/model.ckpt にリネームして移動しておいてください。

## セットアップ
3. condaコマンドでセットアップします。conda acitivateコマンドでは設定した環境をアクティブにしています。
    ```bash
    conda env create -f environment.yaml
    conda activate ldm
    ```
4. pipコマンドで追加インストールします。
    ```bash    
    conda install pytorch torchvision -c pytorch
    pip install transformers==4.19.2 diffusers invisible-watermark
    pip install -e .
    ```
## 実行
1. 起動コマンドを入れればこれで動きます。エラーが起こるときは内容を見直してみましょう。アクセスURLはプロンプト内に表示されます。
    ```bash
    python scripts/webui.py
    ```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75653/5fbab60e-1b05-b4bd-d614-8dd2a11c67e0.png)

2. http://localhost:7860/ にアクセスしてGUIが表示されれば成功です。
2. --share オプションでgradio.appへの公開、更に続けて --share-password パスワードをオプション引数にすることででログインパスを設定することができます。
## 私の環境だけかもしれないけど修正したポイント
1. pip install pynvml を実行。
1. stable-diffusion-test\ldm\models\autoencoder.py
    1. from taming.modules.vqvae.quantize import VectorQuantizer2 as VectorQuantizer -> from taming.modules.vqvae.quantize import VectorQuantizer
1. stable-diffusion\scripts\txt2img.py
    1. from torch import autocast　-> from torch.cuda.amp import autocast
1. この手順には画像拡大用のGANのモデル入れ込みがないかもです。
AWS CLI による Lambda Layer (Python) 作成・公開手順

# 手順

`python` という名称でディレクトリを作成します。（`python` でないと Lambda 上でライブラリをインポートできません）

```sh
% mkdir python
```

ターゲットディレクトリを `python/` に指定して、利用したい任意のライブラリをインストールします。

```sh
% pip install -t python/ requests
```

zip で固めます。

```sh
% zip -r layer.zip python
```

S3 上にアップロードします。`${BUCKET_NAME}` およびプロファイルは自身の環境に合わせて読み替えてください。

```sh
% aws s3 cp layer.zip s3://${BUCKET_NAME}/layer.zip --profile main
```

AWS CLI コマンド `publish-lambda-layer` [^1] を利用して Lambda Layer を公開します。


```sh
% aws lambda publish-layer-version 
    --layer-name my-layer 
    --description "My Layer" 
    --license-info "MIT" 
    --content S3Bucket=${BUCKET_NAME},S3Key=layer.zip 
    --compatible-runtimes python3.6 python3.7 python3.8 python3.9 
    --compatible-architectures "arm64" "x86_64" 
    --profile main
```

# 動作確認

対象の Lambda に Layer を追加して、Layer に含まれるライブラリをインポートできれば OK です。

![layer-test.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342646/2e11b4b8-9d9c-734e-2b74-dfff0cc4a9d2.png)

# 参考

* [Lambda レイヤーの作成と共有](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/configuration-layers.html) - AWS Lambda デベロッパーガイド

[^1]: [publish-layer-version](https://docs.aws.amazon.com/cli/latest/reference/lambda/publish-layer-version.htm) - AWS CLI Command Reference
Visual Studio の使い方

AWS の EC2 の Windows Server 2019 で
Visual Studio 2022 を使ってみました。

次のようなプログラムを作成しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/160b410b-6f12-0af6-a74b-fd3f7217796f.png)

Label を 2個
Button を 4個
TextBox を 1個
配置します。

## Visual Studio 2022 で編集

Label や Button をクリックすると、TextBox の表記が変わります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/eeb62009-b209-c76b-5602-af5c9be5d35e.png)



## プログラム

```cs:Form1.cs
namespace WinFormsApp_sep01
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void label1_Click(object sender, EventArgs e)
        {
            textBox1.Text = "4 seasons";
        }

        private void button1_Click(object sender, EventArgs e)
        {
            textBox1.Text = "Spring";
        }

        private void button2_Click(object sender, EventArgs e)
        {
            textBox1.Text = "Summer";
        }

        private void button3_Click(object sender, EventArgs e)
        {
            textBox1.Text = "Autumn";
        }

        private void button4_Click(object sender, EventArgs e)
        {
            textBox1.Text = "Winter";
        }

        private void label2_Click(object sender, EventArgs e)
        {
            textBox1.Text = "";
        }
    }
}
```
DockerのpgAdmin4で初回コンテナ起動時から表示言語を日本語にする

# 2024/4/23 大幅修正
コメントにてPGADMIN_PREFERENCES_JSON_FILEを教えて頂いたため、修正しました。
情報ありがとうございました。

# 画面からの変更の仕方
[dpage/pgadmin4](https://hub.docker.com/r/dpage/pgadmin4)を使用してデスクトップモード(PGADMIN_CONFIG_SERVER_MODE=False)で
コンテナを立ち上げてブラウザでアクセスすると画面の言語が英語になっています。
日本語に変更するには
1. File -> Preferences -> Miscellaneous -> User language
1. Japanese を選択 -> Save
1. Refresh
をすれば良いのですが面倒くさいです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109302/b7787b65-4e6c-e846-7dff-02057695218d.png)

初回のブラウザアクセスから日本語に出来ないか調査したため、投稿します。

# 環境
* image: dpage/pgadmin4:8.5 をデスクトップモード(PGADMIN_CONFIG_SERVER_MODE=False)で使用
* [試した結果](https://github.com/kwhrkzk/pgadmin_docker_default_japanese)

# 確認内容

[pgadmin4:8.4](https://www.pgadmin.org/docs/pgadmin4/8.4/container_deployment.html)からの環境変数でPGADMIN_PREFERENCES_JSON_FILEが追加されました。
PGADMIN_PREFERENCES_JSON_FILEを指定することで環境設定を事前に設定することが出来るようになりました。

```yml: docker-compose.yml 抜粋
  pgadmin:
    build:
      context: ./pgadmin
    image: pgadmin
    container_name: pgadmin
    ports:
      - 5050:80
    environment:
      - PGADMIN_DEFAULT_EMAIL=pgadmin4@pgadmin.org
      - PGADMIN_DEFAULT_PASSWORD=admin
      - PGADMIN_CONFIG_SERVER_MODE=False
      - PGADMIN_SERVER_JSON_FILE=/pgadmin/servers.json
      - PGADMIN_PREFERENCES_JSON_FILE=/pgadmin/preferences.json           <---- これ
      - PGADMIN_CONFIG_MASTER_PASSWORD_REQUIRED=False
      - PGADMIN_CONFIG_UPGRADE_CHECK_ENABLED=False
      - PGADMIN_CONFIG_ENHANCED_COOKIE_PROTECTION=False
    volumes:
      - ./pgadmin/storage:/root/storage
      - ./pgadmin/servers.json:/pgadmin/servers.json
      - ./pgadmin/preferences.json:/pgadmin/preferences.json               <---- ここでホストとコンテナ共有
    user: root
    restart: always
    entrypoint: /entrypoint.sh
    depends_on:
      - postgres
```

```json: preferences.json
{
  "preferences": {
    "misc:user_language:user_language": "ja"
  }
}
```

jsonの書き方は[JSON format](https://www.pgadmin.org/docs/pgadmin4/8.4/preferences.html#json-format)にありました。
key名は環境設定画面でカーソルを合わせると見えるみたいです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109302/fe1214f7-c54d-deaf-b006-b55bf8120db9.png)

# 実施結果
環境は[github](https://github.com/kwhrkzk/pgadmin_docker_default_japanese)に置いています。
以下のようなイメージです。

![image.png](https://github.com/kwhrkzk/pgadmin_docker_default_japanese/raw/main/image.png)

ツリーは↓

```sh
├── README.md
├── image.drawio
├── image.png
└── src
    ├── docker-compose.yml
    ├── pgadmin
    │   ├── Dockerfile
    │   ├── pgpass
    │   ├── preferences.json
    │   ├── servers.json
    │   └── storage
    └── postgres
        ├── Dockerfile
        └── initdb
            ├── eventstore.backup
            └── init.sh
```

## 起動方法

```sh
cd src
docker-compose up -d
```

### pgadminへのアクセスと結果
[http://localhost:5050](http://localhost:5050)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109302/b2540311-2c6a-c63a-2837-2a599ba4d1d8.png)

## 終了方法

```sh
cd src
docker-compose down --volumes
```

# まとめ
pgadmin:8.4からですが、PGADMIN_PREFERENCES_JSON_FILEのおかげで初期起動から表示言語を日本語に出来るようになりました。
[小ネタ] Ansibleで実行するシェルスクリプトにパラメータを渡す時は環境変数を経由しよう

タイトルの通りですが、Ansibleでパラメータが可変なシェルスクリプト等のスクリプトを動かす際は、Jinjaの `{{ テンプレート文字列 }}` を使わず、環境変数を利用しましょう。

たとえば、下記のスクリプトは、 `HOGE=YEAA"AAH!` の場合にエスケープの問題が起きます。(PowerShellを題材にしてますが、bashなどでも同じ）

```yaml
- name: PowerShellの実行
  win_shell: |
    # echo "YEAA"AAH!" になってしまい、ダブルクォートが不一致になる
    echo "{{ HOGE }}"
```

HOGEを渡す前にエスケープ文字列を追加して ``HOGE=YEAA`"AAH`` にしてあげてもいいのですが、そもそもちゃんと元の文字列をそのまま伝送できていないのが問題です。

スクリプト上に文字列を埋め込むのではなく、 **環境変数経由でシェルスクリプトにパラメータを渡しましょう。**

```yaml
- name: PowerShellの実行
  win_shell: |
    # これならダブルクォートが来ようが改行が来ようが問題なし
    echo $env:HOGE
  environment:
    HOGE: "{{ HOGE }}"
```
[PLATEAU入門] 3D都市モデルをダウンロードして内容を簡単に把握しよう！

# はじめに
どうも、べちおです。

山奥の大学で学生エンジニアをしています。
よろしくお願いいたします。

# 今回の内容

今回は、国土交通省が提供している、**PLATEAU** - 3D都市モデルのダウンロードの方法を共有したいと思います。

## 記事の対象者
 - PLATEAUの3D都市モデルに興味がある方


## この記事でできること
 - PLATEAUの3D都市モデルのダウンロード

# ダウンロードしようぜ
## PLATEAU公式ページからG空間情報センターに辿り着こう！

初めに、3Dモデルを用意するために**G空間情報センター**のサイトに行く必要があります。
ここは王道に沿ってPLATEAUの公式ページから行くことにします。

 + まず[PLATEAU公式ページ](https://www.mlit.go.jp/plateau/)に行きます。

https://www.mlit.go.jp/plateau/

 + 上のメニューバーから[「Open Data」](https://www.mlit.go.jp/plateau/opendata/)を選択します。
 + 画面下に「PLATEAUオープンデータポータルサイト（G空間情報センター）」のリンクがあるので、そこから[G空間情報センター](https://www.geospatial.jp/ckan/dataset/plateau)のサイトへ行きます。
 
https://www.geospatial.jp/ckan/dataset/plateau

そこには3D都市データが提供されているエリアが載っているので、ほしい3D都市データのリンクをクリックしてください。
今回は東京都23区のCityGMLをダウンロードします。


## ダウンロードしたフォルダの中を確認する

フォルダの中のを確認すると、
- codelists
- metadata
- specification
- udx
- 13100_indexmap_op.pdf

が入っていることが確認できると思います。

「**udx**」フォルダには、**bldg**、**dem**、などいくつかのフォルダがあり、中には「.gmlファイル」が存在します。こちらが今回使用するファイルになります。
また、フォルダの名前ですが、「bldg」は「建物」を表し、「dem」は「地形」を表します。
このように「udx」フォルダにはモデルを表すフォルダ名がいくつか存在します。

bldgフォルダの中には、
**53392578_bldg_6697_2_op.gml**
のように数字の列でファイル名が表されていますが、このファイル名について解説致します。


## ファイル名の数字の列の意味

ダウンロードしたフォルダには「**13100_indexmap_op.pdf**」が入っているのですが、そちらにはダウンロードしたモデルデータの構築範囲がマップ上に記載されています。

今回の場合「53392578_bldg_6697_2_op.gml」の「53392578」は、このマップ上の値と関連しており、データを使用する場合は、データのほしい地域を示す値をマップ状で探し、その値をもとに「bldg」から対象のファイルを探す必要があります。

また、地域によっては構築されている3D都市モデルの仕様が異なります。
今回の例ですと、マップ上にピンク色で示されている地域は、「LOD2」というデータになります。(通常はLOD1)
仕様の簡単な説明は、本記事[目次：3D都市モデルの仕様について]でご説明いたします。


# 3D都市モデルの仕様について
ここではPLATEAUの3D都市モデルの仕様について簡単にご説明します。

CityGMLは「**LOD**（Level of Detail）」と呼ばれる概念を持っており、LOD1、LOD2のように付与されている情報に違いがあります。

具体的には、以下のように、レベルが上がるほどよりモデルデータが現実に近づいていきます。
 - LOD1 - 箱モデル
 - LOD2 - LOD1 + 屋根形状
 - LOD3 - LOD2 + 窓やドア
 - LOD4 - LOD3 + 室内


CityGMLの詳細については[コチラ](https://www.mlit.go.jp/plateau/learning/)が参考になると思います。


# おわりに

ここまでお読みいただきありがとうございます。

PLATEAUのCityGMLには通常のモデルにはない多くの情報が含まれていますので、扱うのには少々時間がいると思いますが、多くの可能性を秘めたデータには間違いないと思います！

　　

この記事が新たなプロダクトのお役に立てれば幸いです。
ACPI BIOS ErrorとACPI Error奮闘記（未解決）

<details><summary>更新履歴</summary>

- (追記)[こちら](https://qiita.com/t_dragon/items/a61dd67c01cb72b579cd)でデフォルトで起動するカーネルを変更することに成功した。
- (追記)[こちら](https://qiita.com/t_dragon/items/c38f8f6ceea23ed8bf15)でOSをAlmaLinuxに移行し、このエラーが出なくなった。

</details>

ACPI BIOS ErrorとACPI Errorに対する奮闘記を残しておく。
なお、これは未解決問題であり、将来また対処しなければならないと思われる。

(追記)[こちら](https://qiita.com/t_dragon/items/a61dd67c01cb72b579cd)でデフォルトで起動するカーネルを変更することに成功した。
(追記)[こちら](https://qiita.com/t_dragon/items/c38f8f6ceea23ed8bf15)でOSをAlmaLinuxに移行し、このエラーが出なくなった。

# 起動時のエラーと試行

停電のためCentOS8の計算機をシャットダウンした。
その後に電源を入れたところ、このようなエラーが出てきた。

~~~
You are in emergency mode. After logging in, type "journalctl -xb" to view
system logs, "systemctl reboot" to reboot, "systemctl default" or "exit"
to boot into default mode.
■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ root  ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■
(Control-D ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ):
~~~

■はもしかして文字が隠れてる？と思い、[こちら](https://clean-copy-of-onenote.hatenablog.com/entry/ubuntu_mount_error
)を参考にすると"Give root password for maintenance(or type Control-D to continue):" だと思われるので、rootのパスワードを入力。

~~~
# journalctl -xb | grep Error
... ACPI BIOS Error (bug): Failure creating named object ...
... ACPI Error: ...
~~~

[こちら](https://erikspace9.wordpress.com/2021/02/01/linux-mint%E8%B5%B7%E5%8B%95%E6%99%82%E3%81%ABacpi-bios-error/)を参考に対処する。

~~~
# emacs /etc/default/grub
~~~

~~~diff
+ GRUB_CMDLINE_LINUX_DEFAULT=”quiet splash acpi=strict”
~~~

[こちら](https://qiita.com/moukuto/items/c78f29f9bd1221baffca)を参考に変更を適用。

~~~
# grub2-mkconfig -o /boot/grub2/grub.cfg
# exit
~~~

これでもダメだった。

# 結局どう対処したか

電源を入れたあと起動するOSを選ぶときに、今までは一番上を選択していた。
それを2番目に変えた。
ACPI BIOS Errorは出たように見えたし、ログイン画面まではいかなかったが、リモートからsshできるようにはなったので、とりあえずは良しとする。
"A problem has occurred and the system can't recover.
Please log out and try again."という画面のまま放置した。

# 何が原因だったのだろうか

[こちら](https://jp.minitool.com/backup-tips/fix-acpi-bios-error-in-windows.html)を見ると、どうやらハード的な問題の可能性が高そう。
Rails7でImport mapsを使ってjQuery UIを動かす

Rails7にjqueryとjquery-ui-distをセットアップする方法を解説します。

# jqueryとjquery-ui-distをピン留めする
```ruby:config/importmap.rb
pin "jquery", to: "https://ga.jspm.io/npm:jquery@3.6.0/dist/jquery.js"
pin "jquery-ui-dist", to: "https://ga.jspm.io/npm:jquery-ui-dist@1.13.1/jquery-ui.js"
```

# jqueryとjquery-ui-distをインポートする
```ruby:app/javascript/application.js
import jQuery from "jquery";
window.$ = window.jQuery = jQuery;
import("jquery-ui-dist")
```

参考

https://stackoverflow.com/questions/69691718/how-to-use-jqueryui-in-a-rails-6-or-rails-7-alpha-engine

# 同じ要領でJavaScriptファイルを読み込む
```ruby:config/importmap.rb
pin "jquery", to: "https://ga.jspm.io/npm:jquery@3.6.0/dist/jquery.js"
pin "jquery-ui-dist", to: "https://ga.jspm.io/npm:jquery-ui-dist@1.13.1/jquery-ui.js"
+ pin_all_from 'app/javascript/custom', under: 'custom'
```

```ruby:app/javascript/application.js
import jQuery from "jquery";
window.$ = window.jQuery = jQuery;
import("jquery-ui-dist")
+ import("./custom/***.js")
```

app/javascript/custom/***.jsにJavaScriptファイルを置く。

参考

https://zenn.dev/iloveomelette/scraps/4e033878f84b56
AWS App Runnerから外部インターネットへのアクセスを許可する

AWS AppRunnerでVPC内のサービスを利用できるようになりましたが、外部インターネットにアクセスする場合は別途設定が必要。

https://dev.classmethod.jp/articles/aws-app-runner-for-vpc/

今回は、App Runnerのサブネットはプライベートサブネットに配置しているという条件です。

## 手順

App RunnerのVPC Connectorのサブネットに以下のようにNATゲートウェイ(NAT)とインターネットゲートウェイ(IGW)をアタッチしたルートテーブルを割り当てる。

- パブリックサブネットのルートテーブルにIGWをアタッチする
- プライベートサブネットのルートテーブルにNATをアタッチする

## 参考
https://www.skyarch.net/blog/?p=21963

https://jp.magicode.io/Nao/articles/1e8b0057900d47df97ddf5735721a1a4
配列にid的なのつけたいな

## こういう配列
```php
$tests = array(
    array(
        'price' => 100,
        'name' => 'hoge'),

    array(
        'price' => 200,
        'name' => 'huga'),

    array(
        'price' => 300,
        'name' => 'piyo')
        );

var_dump($tests);
```
indexあるけど、1から始まるid付けたい
## こうした
```php
foreach($tests as $index => $test){
    $id = 1 + $index;
    $tests[$index] = array_merge($test,array('id'=>$id));
}

var_dump($tests);
```
実行結果
```
array(3) {
  [0]=>
  array(3) {
    ["price"]=>
    int(100)
    ["name"]=>
    string(4) "hoge"
    ["id"]=>
    int(1)
  }
  [1]=>
  array(3) {
    ["price"]=>
    int(200)
    ["name"]=>
    string(4) "huga"
    ["id"]=>
    int(2)
  }
  [2]=>
  array(3) {
    ["price"]=>
    int(300)
    ["name"]=>
    string(4) "piyo"
    ["id"]=>
    int(3)
  }
}
```

idついたなあ

## そもそも
PHPの公式マニュアル見ると
https://www.php.net/manual/ja/function.array.php

```php
$tests = array(
    1 => array(
        'price' => 100,
        'name' => 'hoge'),

    array(
        'price' => 200,
        'name' => 'huga'),

    array(
        'price' => 300,
        'name' => 'piyo')
        );
```
これで1からindexが始まる配列を作成できるので
foreachの部分はこうなる
```php
foreach($tests as $index => $test){
    $tests[$index] = array_merge($test,array('id'=>$index));
}
```
自分のプロジェクトでは、配列を`$test=array()`みたいな感じで定義するということがなかったので、最初の方式にした

## 連想配列だったらどうすんの
```php
$tests = array(
    'hoo' => array(
        'price' => 100,
        'name' => 'hoge'),

    'ahh'=> array(
        'price' => 200,
        'name' => 'huga'),

    'poo'=> array(
        'price' => 300,
        'name' => 'piyo')
        ); 

foreach($tests as $index => $test){
    $tests[$index] = array_merge($test,array('id'=>$index));
}

var_dump($tests);
```
実行結果
```
array(3) {
  [0]=>
  array(3) {
    ["price"]=>
    int(100)
    ["name"]=>
    string(4) "hoge"
    ["id"]=>
    string(3) "hoo"
  }
  [1]=>
  array(3) {
    ["price"]=>
    int(200)
    ["name"]=>
    string(4) "huga"
    ["id"]=>
    string(3) "ahh"
  }
  [2]=>
  array(3) {
    ["price"]=>
    int(300)
    ["name"]=>
    string(4) "piyo"
    ["id"]=>
    string(3) "poo"
  }
}
```
それはそう

## 解決法
```php
$index=1;
foreach($tests as $key => $test){
    $tests[$key] = array_merge($test,array('id'=>$index));
    $index++;
}

var_dump($tests);
```
実行結果
```
array(3) {
  ["hoo"]=>
  array(3) {
    ["price"]=>
    int(100)
    ["name"]=>
    string(4) "hoge"
    ["id"]=>
    int(1)
  }
  ["ahh"]=>
  array(3) {
    ["price"]=>
    int(200)
    ["name"]=>
    string(4) "huga"
    ["id"]=>
    int(2)
  }
  ["poo"]=>
  array(3) {
    ["price"]=>
    int(300)
    ["name"]=>
    string(4) "piyo"
    ["id"]=>
    int(3)
  }
}
```
なんか他にスマートな方法ありそう

## 終わりに
ベストプラクティスあったら教えて頂きたいです
aws-cliでIAMユーザーの変更ができなかった話

# はじめに
IAMユーザーを新しく作成し、aws-cli上でもIAMユーザーとして設定しようとしたところうまく登録できませんでした。
それまで使用していた古いIAMユーザーが設定されていることが原因で変更できなかったのですが、解決したので備忘録として残したいと思います。
お気付きの点があれば教えてください。

# 課題
新しく作ったIAMユーザーをaws-cliのIAMユーザーとして登録できない。
旧IAMユーザーを上書きできない。

# 手順
まず現状のaws-cliでの権限を確認するために次のコマンドを実行します。
~~~
aws sts get-caller-identity
~~~
すると現状のどの権限で操作をしているかが確認できます。
~~~
{
    "UserId": "AKIA4KB4UX5XPJRUGBIS",
    "Account": "************",
    "Arn": "arn:aws:iam::************:user/Silva-Zoldyck"
}
~~~
旧IAMユーザーの情報が表示されています。

IAMユーザーを新たに作成します。
今回はAWSマネジメントコンソール上で作成します。

IAMユーザー作成の画面からAdd usersをクリックします。
[![Image from Gyazo](https://i.gyazo.com/9287d12aa12e5a227cafc21a602c7efc.png)](https://gyazo.com/9287d12aa12e5a227cafc21a602c7efc)
User nameを入力し、Access keyにチェックをつけます。
[![Image from Gyazo](https://i.gyazo.com/776d597099f6d4e115b29d9492f314cf.png)](https://gyazo.com/776d597099f6d4e115b29d9492f314cf)
Policyを選択します。今回はAWSが準備しているものを利用します。
[![Image from Gyazo](https://i.gyazo.com/4bfaa4c282596674984598ea0d1247e4.png)](https://gyazo.com/4bfaa4c282596674984598ea0d1247e4)
IAMユーザーを作成するとAccess Key IDとSecret access keyが表示されるのでコピーしておきます。
![faaff1f225c6b0bf8e95c868d99213c8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1431393/4085d1fe-7081-1a78-569d-a292ec45862e.png)
aws-cliに設定します。
.awsディレクトリ内のcredentialsファイルを開きます。
~~~
vim ~/.aws/credentials
~~~
先ほどコピーしたAccess Key IDとSecret access keyを変更します。
![9565dc70543c9aad29633386542da61d.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1431393/f30e8997-bc14-553d-f4c9-a9e4c7f9baad.png)


これで設定変更完了！
IAMユーザーがの変更が完了しているはず。
再度コマンドを実行
~~~
aws sts get-caller-identity
~~~
~~~
{
    "UserId": "AKIA4KB4UX5XPJRUGBIS",
    "Account": "************",
    "Arn": "arn:aws:iam::************:user/Silva-Zoldyck"
}
~~~
が、なぜか変わっていない・・・

そうか！以前のAccess Key IDとSecret access keyが環境変数として残っているからだ！
~~~ .zshrc
export AWS_ACCESS_KEY_ID="AKIA4KB4UX5XPJRUGBIS"
export AWS_SECRET_ACCESS_KEY="***************************************"
~~~
これを削除すればうまくいくはず！

 ・・・しかし、削除しても変更されていない。

# 解決
次のコマンドを入力することで解決しました。
~~~
unset AWS_ACCESS_KEY_ID
unset AWS_SECRET_ACCESS_KEY
~~~
unsetは関数や変数を削除してくれるコマンドです。
~~~
{
    "UserId": "AIDA4KB4UX5XLYWOWW4FV",
    "Account": "************",
    "Arn": "arn:aws:iam::************:user/Chrollo-Lucilfer"
}
~~~
無事に変更されています！

- @RubiconLink さんより教えていただいたので補足

https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-quickstart.html

AWSの公式の「構成設定と優先順位」には次のように記されています。
> AWS CLI は、システム環境変数、ユーザー環境変数、ローカルの AWS 設定ファイル、またはコマンドラインでパラメータとして明示的に宣言されたものなど、複数の場所にある認証情報と構成設定を使用します。特定の場所が他の場所よりも優先されます。AWS CLI 認証情報と構成設定は、次の順序で優先されます。
1. コマンドラインオプション
1. 環境変数
1. CLI 認証情報ファイル
1. CLI 設定ファイル
1. コンテナ認証情報
1. Amazon EC2 インスタンスプロファイルの認証情報

今回私が設定値を更新していたcredentialsファイルは3に該当します。
2の環境変数よりも優先順位が低かったため、unsetで削除してあげることで更新することができたということでしょう。

# おわりに
今回のようにIAMユーザーを変更することはなかなかないかもしれませんが、もしもうまくいかないかなかった場合は試してみてください。

# 参考
https://atmarkit.itmedia.co.jp/ait/articles/1905/24/news015.html

https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-quickstart.html

https://www.shonenjump.com/j/rensai/hunter.html
ubuntu20で時刻合わせに失敗する

## timedatectlを利用するのが基本

## 基本
sudo vi /etc/systemd/timesyncd.conf
[Time]
NTP=ntp.nict.jp
sudo systemctl restart systemd-timesyncd.service
で行くはずが、

## エラー
Failed to restart systemd-timesyncd.service: Unit systemd-timesyncd.service is masked.
このエラーになりました。

timedatectl
を打つと
NTP service: active
となっていたり
NTP service: N/A
となっていたり

下記を実行すると
timedatectl set-ntp true

Failed to set ntp: NTP not supported
このエラーになりました。

## 今回解決した方法
sudo apt install systemd-timesyncd
これでインストールをし直して、
sudo timedatectl set-ntp true
sudo systemctl restart systemd-timesyncd.service

これで今回は解決しました。
最初からはインストールされてないのね。。。

参考リンクは[こちら](https://askubuntu.com/questions/1314479/ntp-not-supported)
【C言語】文字や数字を数値に変換する時の考え方

### 〇数字を数値に変換
（例）数字'4'を数値に変換

```c:コード（省略）
    char c = '4';
    int s = c - '0';
    printf("%d\n",s);
    return 0;
```

```text:結果
　4
```

'4' は 数値で表すと 52
'0' は 数値で表すと 48
よって'4'-'0'は52-48で4になる

### 〇文字を数値に変換（問題あり）
（例）文字'A'を数値に変換

```c:コード（省略）
    char c = 'A';
    int s = c - '0';
    printf("%d\n", s);
    return 0;
```

```text:結果
　17
```

'A' は 数値で表すと 65
'0' は 数値で表すと 48
よって'A'-'0'は65-48で17になる

※文字を数値に変換するのは問題がある