OmniAICreator/Qiita-1.07M huggingface dataset:
Raspberry Pi で ターミナルで viコマンド を使うためのメモ

# 1. コマンド入力
#####デスクトップにディレクトリを移動

```
cd デスクトップ
```


いきなり入力できない。
まず***「デスクトップ」***とカタカナが打てない。
そもそも***「デスクトップ」***というフォルダがない。
あるのは***「Desktop***」(***「desktop」***も認識しない)

念の為、

```
sudo apt update
sudo apt install ibus-mozc
```

***ibus-mozc*** したんじゃ？と思っていたけれど
右上に無かった気がするアイコンが現れたのでこれで良しとする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637498/1b9e13e0-f237-a8b4-a2be-b77d03bb4bd9.png)

JA をクリックして ***Mozc*** を選択すると日本語入力可能に。
フォルダ名はむしろ皆様日本語(カタカナ)表記をアルファベットに直すようなのでもうこのままで。


##### ファイル作成

```
sudo vi test.py
```

以前この入力モードが全くわからなかったのでメモ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637498/29df8f69-b746-0ee6-291f-4e57a465b4b3.png)
いきなりこの画面。
入力できない。
この状態が ***viエディタのコマンドモード*** になっていて書き込めないとのこと。

**コマンドモード → 入力(挿入)モードに変更が必要**
変更は ***「i」*** キー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637498/9ca3e90c-406d-12ea-5870-b823014cd605.png)
どういうことなの・・・orz

ABCDは矢印キーを打ったせいでした。
これはサボらずviコマンドを学ばないとですね。

>（１）vi ファイル名　で開始。（権限が必要なファイルはsudo viで開く）
（２）コマンドモードと，編集モードがある。
（３）iとかaで編集モードに移れる。
（４）ESCキーでコマンドモードに移れる。
（５）編集モードでは，普通に内容を編集できる。
（６）コマンド　:w　で保存。
（７）コマンド　:q　で終了。

[(参考：今から１分で，viコマンドの使い方を覚えてもらうためのページ)](https://language-and-engineering.hatenablog.jp/entry/20121207/p1)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637498/08bf59f0-c50b-0ca5-2843-f6eebbc26edb.png)
やっとできました。
面倒くさがるとダメですね。
Solidityの勉強で挫折しない 〜初心者向けの勉強法〜

![](https://firebasestorage.googleapis.com/v0/b/hideaki-97c59.appspot.com/o/images%2FKg8fOSQeQSXraUWzyRlub9tFNoF2%2F_psyKIU6W.png?alt=media)  

※2021年11月追記


いつも記事を読んでくださる皆様、ありがとうございます。


このたび本ブログは、[イーサリアムnavi](https://ethereumnavi.com/)へお引越しいたしました。


お手数おかけいたしますが、[こちらのリンク](https://ethereumnavi.com/2021/11/08/solidity-development-beginner/)からアクセスして記事を読んでいただけますと幸いです。


ご不便をおかけしてしまい誠に申し訳ございませんが、ご理解のほど何卒よろしくお願いいたします。


でりおてんちょー
ARCore SDK（Java）の Duplicate class 問題

ARCore の開発を行っていて、困っていた問題が解決したのでメモ

# 発生していた問題
ARCore SDK の内部のクラスが a.a.a という名前となっているため、他の Google ライブラリと競合が発生してしまうことがあった

```gradle:build.gradle
implementation 'com.google.ar:core:1.25.0'
implementation 'com.android.installreferrer:installreferrer:2.2'
```

```
Duplicate class a.a.a found in modules jetified-core-1.25.0-runtime (com.google.ar:core:1.24.5) and jetified-installreferrer-2.2-runtime (com.android.installreferrer:installreferrer:2.2)
```

Github の issue
https://github.com/google-ar/arcore-android-sdk/issues/1140

※ [1.26.0](https://github.com/google-ar/arcore-android-sdk/releases/tag/v1.26.0) で解消を確認

# 対処法（1.25.0まで）
[shadowJar](https://github.com/johnrengelman/shadow) などで無理やり書き換え

```gradle:{project}/build.gradle
buildscript {

    repositories {
        google()
        gradlePluginPortal()
    }
    dependencies {
        classpath fileTree(dir: 'libs', include: '*.jar')
        // Android Studio で使うには Gradle 7以上が必要
        classpath 'com.android.tools.build:gradle:7.0.0'
        classpath 'gradle.plugin.com.github.jengelman.gradle.plugins:shadow:7.0.0'
    }
}
```

build.gradle にタスクを追記

```gradle:build.gradle
assemble.dependsOn {tasks.shadowJar}

task shadowJar(type: com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar) {
    archiveBaseName = 'shadow-com.google.ar'
    relocate 'a.a.a', 'a.a.c'
    from zipTree(project.configurations.shadowMe.singleFile)
}


```

### 注意点
同じ問題は sceneform などでも起きるため、そちらは対応待ちとなる
[google-ar/sceneform-android-sdk](https://github.com/google-ar/sceneform-android-sdk) は更新されていないため、 [ThomasGorisse/sceneform-android-sdk](https://github.com/ThomasGorisse/sceneform-android-sdk) は更新待ちとなる
Chromeはデスクトップのinputmodeで入力制限しない

# `inputmode`とは

htmlの`inpputmode`属性は、バーチャルキーボードの入力で「[ユーザーがコンテンツを入力する際に最も参考になる入力メカニズムの種類を指定](https://html.spec.whatwg.org/multipage/interaction.html#input-modalities:-the-inputmode-attribute "HTML Standard日本語訳より")」してくれる大変便利な属性です。特に数値入力の際はアルファベットを入力できなくなるので、無効な入力をするリスクを減らしてくれるので助かります。

しかしこの属性には弱点があり、それは物理的なキーボードの入力を制限しないことです。変なJSを組まなくても、ブラウザ側で検証と入力制限を肩代わりしてくれる機能があっていいものですが。

# デスクトップ版Chromeで対応済みとなっているけど…？

デスクトップ版Chromeでは`inputmode`はバージョン65で対応済みとなっておりますが、上記の通り物理キーボード入力を一切フィルタリングしません。
しかし、なぜ対応済み扱いとなっているのでしょうか。

なお、FirefoxはフラグをOnにしないと使えず、safariは対応していません。

# Googleの（つれない）返答

この点に関して[ChromeのMonorailで提案](https://bugs.chromium.org/p/chromium/issues/detail?id=1234212)したところ、以下の様な回答が返ってきました。

>Inputmode is a hint for the type of input that is expected that may be used to determine which virtual keyboard is appropriate.  It does not restrict what keys can be entered.  Verified that the selected virtual keyboard changes based on inputmode.  No VK appeared with inputMode=none.  A numeric keypad appeared for decimal and tel, etc.  Verified by enabled the onscreen keyboard in the accessibility settings for ChromeOS.

日本語訳すると以下の通りです。
>「`inputmode`は入力型が期待している値のヒントで、どのバーチャルキーボードが適切かを判断する際に使われることがあります。入力するキーを制限しません。選択したバーチャルキーボードが`inputmode`により変更されるかどうかで検証されました。`inputMode=none`ならキーボードが表示されない、`decimal`ならテンキーが表示されるといった具合です。ChromeOSのアクセシビリティ設定で画面上にキーボードを表示して検証されました。」

確かにChromeOSのPCを持っていない私としては盲点です。ただ、Windowsのスクリーンキーボードでは残念ながらinputmodeが動作しませんでした。Macは実物が手元にないので分かりません。

# WHATWG側の反応

この例に似たような主旨の提案（CSSの`ime-mode`をHTML属性として復活させるべきではないか）を[WHATWGに投げかけた](https://github.com/whatwg/html/issues/6908)ところ、

>This is what `inputmode` is for, no?
>(そのための`inputmode`じゃないの？)

>That kind of feature used to be in the spec as an inputmode, I believe, but there was no implementer interest (and according to @dtapuska was "not possible to implement in current virtual keyboard implementations") so it was removed in #3260.
>In particular there used to be "kana" (full-width kana or romaji), "kana-name", "katakana" (full-width), "half-width-katakana", and "full-width-latin". I'm not sure if that exactly maps to what's requested here.
>（そのような仕様は`inputmode`にあったはずですが、実装者の興味が無く(また、@dtapuskaいわく「現在のバーチャルキーボードの実装では不可能」なため)、(プルリクの)#3260で削除されました。
>（当時検討されていた仕様では）`kana` (全角カナおよびローマ字)、`kana-name`、`katakana` (全角)、`half-width-katakana`、`full-width-latin`というものがありました。要求に沿っているものかはわかりかねますが。）

# モバイルファースト一辺倒で本当に良いのか

ということで、PCに対する熱意はWeb仕様を作ったり、実装する側も持ち合わせていないようです。

PCユーザーはまだまだたくさんいる（特に仕事の現場で）のに、世の中はモバイルファーストだからと言って、スマートフォンを重視しすぎだと感じます。

そうでなくとも、ブラウザ界隈では（W3Cなどで活躍する日本人も多く、皆さん尊敬しておりますが）英語圏の発言力が圧倒的に大きいのが現状です。[2020年のシェア](https://www.statista.com/statistics/262946/share-of-the-most-common-languages-on-the-internet/)を見る限り日本語は8位とかなりつかわれている言語ですが、要望に応えられていないのが現状です。無効な入力に関しては、2位の中国語圏の方も似たような悩みがあるのではと愚考しております。皆さんも声を上げて、変革してみませんか、とやたら大きい述語でこの記事を締めます。
IPAファイルを再署名する方法(Mac)

## はじめに

Xcode 12.4以下で署名したIPAファイルは、どうやらApp StoreやTestFlight以外からではiOS 15の端末にインストールできないようです。

https://twitter.com/the_uhooi/status/1419493775764647937?s=20

そのため、IPAファイルを再署名することにします。

## 環境

- OS：macOS Big Sur 11.5.2

## IPAファイルの再署名

IPAファイルの再署名は、コマンドの実行のみで完結します。

```bash
# IPAファイルを展開する
# `Payload` というフォルダが作成される
# 私の環境ではファイル名が補完されなかったので `unzip *.ipa` で展開した
$ unzip ○○.ipa

# アプリの署名を確認する
$ codesign -dvvvvv ./Payload/××.app

# アプリを再署名する
$ codesign -s "{キーチェーンアクセスに表示されている証明書の名前}" -f --preserve-metadata --generate-entitlement-der ./Payload/××.app

# 再署名したアプリをIPAファイルへ圧縮する
# ファイル名は任意だが、末尾に `_resign` と付けると元のIPAファイルと区別しやすい
$ zip -ru ○○_resign.ipa Payload

# 展開したファイルを削除する
$ rm -rf Payload/
```

## 注意

- 再署名時に以下の警告が発生する  
`Warning: default usage of --preserve-metadata implies "resource-rules" (deprecated in Mac OS X >= 10.10)!`
  - 今回は無視した

## おわりに

これでiOS 15でもXcode 12.4以下で作成したIPAファイルを、Finderなどからインストールできるようになりました :relaxed: 

## 参考リンク

- [Not able to install enterprise bui… | Apple Developer Forums](https://developer.apple.com/forums/thread/682775?answerId=681438022#681438022)
APIサーバが返却する主なHTTPステータスをメモ

# 概要
APIサーバを構築するときに返却する主なHTTPステータス

# 注意点
- あくまで個人的にメモしてるだけなので世の中のスタンダードではない
- 実装方法は載せてない（APIサーバの実装は色々あるから）

# HTTPステータス
## 成功
| ステータス | 説明 |
| --- | --- |
| ``200 OK `` | リクエストの成功 |
| ``201 Created`` | リクエストは成功し、その結果新たなリソースが作成された |
| ``204 No Content``  | リクエストの成功（レスポンスボディなし） |

## 失敗
### クライアントエラー
| ステータス | 説明 | メッセージ |
| --- | --- | --- |
| ``400 Bad Request`` | 不正なリクエストでサーバがリクエストを理解できない | Missing a required parameter. |
| ``401 Unauthorized`` | 認証失敗 | No valid API key(Access Token) provided. |
| ``403 Forbidden`` | 認可失敗 | You do not have access permission. |
| ``404 Not Found`` | 指定したリソースが存在しない | The requested resource doesn't exist. |

## 異常
### サーバエラー
| ステータス | 説明 |
| --- | --- |
| ``500 Internal Server Error`` | 不明なエラーが発生 |
| ``503 Service Unavailable`` |  APIサーバが利用できない状態 |
| ``504 Gateway Timeout`` | リクエストタイムアウトが発生 |
[メモ] Django外のPythonプログラムから Django ORM を使用するコード


|本シリーズのトップページ|
|:--|
|https://qiita.com/robozushi10/items/4559a281d0319eb62c6c|

# 内容

Gunicorn を使った Django 2.x や 3.0系の環境で、
Django 外部の Python プログラムから Django ORM を使用するコード.
logger も含めて記載している.

本コードが必要になった理由は末尾近くに記載している.



# 条件

・Gunicorn を使用している
・次のような構成で settings.py が存在している

```bash
home
|-- foo
    |-- mysite ................... Django プロジェクト
        |-- myapp ................ Django アプリ
        |   |-- models.py
        |   略
        |-- config
            |-- settings.py
            |-- urls.py
            |-- wsgi.py
            略
```

# コード

```python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# import の例. 参考なので不要なものが多々ある.
import sys; sys.dont_write_bytecode = True
import os, json, time, copy, requests, textwrap, socket, pickle, base64
from datetime import datetime
from pprint import pprint

# Django プロジェクトのパスを import 対象に加える 
sys.path.append('/home/foo/mysite')

# Gunicorn なので環境変数を明示的に指定してやる
os.environ.setdefault("DJANGO_SETTINGS_MODULE", 'config.settings')

# myapp/models.py を読み込む
from django.core.wsgi import get_wsgi_application
myapp = get_wsgi_application()
from myapp.models import *

# ロガー設定
from logging import basicConfig, getLogger, DEBUG, ERROR, INFO, WARN, CRITICAL
format = "[%(levelname)s][%(pathname)s:%(lineno)s:%(funcName)s] %(message)s"
basicConfig(level=DEBUG, format=format)
logger = getLogger('django')
 
if __name__ == "__main__":
 
  # ORM を使う. (下記はクラス Hoge に対する操作である)
  objects = Hoge.objects.all()
  logger.error(objects)
```



# 外部プログラムから ORM 操作が必要になった理由

下図のように Jenkins を介した機構が必要になったため.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1246056/4c120d32-6f02-1a12-7930-2d42b48b5ee9.png)


# 参考サイト

|URL|
|:--|
|http://blog.shigepon.info/blog/2015/07/28/use-django-model-outside-django-project/#.YRnQnPv7Tbi|
GKEで/usr/bin/toolboxに入れなかった話

# はじめに
GKEのノードにログインしてちょっと処理を行いたい場合は/usr/bin/toolboxを使用する
https://cloud.google.com/container-optimized-os/docs/how-to/toolbox?hl=ja
しかし二度目以降エラーで入れなくなってしまった。

# エラーメッセージ

```
Please do not use --share-system anymore, use $SYSTEMD_NSPAWN_SHARE_* instead.
Spawning container ***** on /var/lib/toolbox/******.
Press ^] three times within 1s to kill container.
Failed to allocate scope: Unit ***** already exists.
Parent died too early
```

# 原因
以前toolboxを使用した時にバックグラウンドプロセスを残したままtoolboxから出ると発生する。
簡単に再現するにはtoolbox内で`sleep 30 &`としてtoolboxから出ると30秒の間toolboxに入ると上記のエラーが発生する。

# 対処
以前toolbox内で実行したプロセスを`ps aux`などで探してkillする
pythonのyieldを習得

pythonのyieldがわからない自分のためのメモ

### 要するにこう

```python
def for_in_generator():
    for i in range(0, 10, 3):
        yield i

print([x for x in for_in_generator()]) # => [0, 3, 6, 9]
```

returnではなくyieldで値を返す。
返す度に止まります。
もう一度呼ばれると続きから。

### generatorを理解するといいらしい

```python
def my_generator():
    print('before yield')
    yield 1
    print('yielded 1')
    yield 2
    print('yielded 2')
    yield 3
    print('yielded 3, finished')
```

実行してみる

```python
gen = my_generator()
print(type(gen))

v1 = gen.__next__()
print(type(v1))
print(v1)
v2 = gen.__next__()
v3 = gen.__next__()
v4 = gen.__next__()
```

```
<class 'generator'>
before yield
<class 'int'>
1
yielded 1
yielded 2
yielded 3, finished
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
/tmp/ipykernel_101/3825958683.py in <module>
     17 v2 = gen.__next__()
     18 v3 = gen.__next__()
---> 19 v4 = gen.__next__()

StopIteration: 
```

`__next__()`で、最初のyield <val>の<val>が返ってくる。
`gen`はそこで一時停止している状態。
`__next__()`をもう一度呼ぶと続きから次のyieldまでを実行。

### 現実的な使い方

`for`文にgeneratorを与えて、最後までgenerateしてあげること

```python
for v in my_generator():
    print(v)
```
```
before yield
1
yielded 1
2
yielded 2
3
yielded 3, finished
```

#### リスト内包表記にも使う

```python
print([v * 2 for v in my_generator()])  # => [2, 4, 6]
```
Go言語でOS環境変数を取得する

Goではユーザ名とかパスワードなどの設定は環境変数に持たせるのが一般的らしい。

じゃあどうやって取得すれば良いのか？
`os.Getenv（"キー名"）`で取得できます

以下サンプル

### 環境変数の作成
サンプルとして`.env`ファイルをつくります。

```bash
export Test=test_dayo
export TEST=oomoji_dayo
```

### 環境変数の登録
sourceコマンドで読み込みます（環境変数へ登録）

```bash
$ source .env
$ env | grep TEST
TEST=oomoji_dayo
$ env | grep Test
Test=test_dayo
```
ちゃんと入ってますね。

### Goを書く。

main.goを書きます。

```go
package main

import (
	"fmt"
	"os"
)

func main() {
	fmt.Println("test")

	Test := os.Getenv("Test")
	TEST := os.Getenv("TEST")

	fmt.Printf("komoji : %v\n", Test)
	fmt.Printf("oomoji : %v\n", TEST)
}
```


### 実行します

```bash
$ go run main.go
test
komoji : test_dayo
oomoji : oomoji_dayo
```
読み込めてますね。


---

色々と書き方はあるけど、できるだけ単純化して
誰でも使えるような言語になればいいなと思いました。
2進数を16進数に変換する方法

Q: 2進数11011001を16進数に変換
2進数を4桁ずつに分けて、1回10進数に変換し、16進数に置き換える
1101→ 8*1 + 4*1 + 1 = 13(10進数) →D(16進数)
1001→　8*1 + 1 = 9(10進数)→9(16進数)

A: D9

16進数
123456789ABCDEF

0000…0
0001…1
0010…2
0011…3
0100…4
0101…5
0110…6
0111…7
1000…8
1001…9
1010…A
1011…B
1100…C
1101…D
1110…E
1111…F
【メモ】PHP7.3×EC-CUBEでメモリエラーが出る。

すみません、個人的メモです。
記事は4系だけど、3系でも発生。
バージョンを下げればいけるみたい。上げるとどうなる・・・？要検証。

https://xoops.ec-cube.net/modules/newbb/viewtopic.php?topic_id=22321&forum=7&post_id=93318

【追記】
上げてもダメでした。。。
セル内の文字を抽出する_２（左から）

文字の左から抽出する
============
前回の見本と同じようにA1に「あいうえお」と入力してあります。
関数、VBAを使用して今度は左側から指定の文字数を抽出します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1879772/29aa0bff-025b-8058-609b-1065ae83f867.png)

Excel関数
------
関数で抽出する場合の書き方

```rb
=LEFT(対象セル,抽出する文字数)

入力例
=LEFT(A1,1)
```

対象セルと抽出する文字数を指定する事で頭文字等の文字を抜き出せます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1879772/ff4b2dc5-2240-8c07-1107-ea4a887fbde1.png)



RIGHTと同様に例え抽出する文字数が元の文字数より多かったとしてもエラーになる事はありません。

ExcelVBA
------
VBAで抽出する場合の書き方

```rb

結果 = Lrft(対象セル,抽出する文字数)

```

書き方は上記の関数入力とほぼ同じです。

以下の例文ではセルB1に直接結果を出力しています。

```rb

Sub 文字の左から抽出()
    
    'セルA1の左から2文字をセルB1に出力
    Cells(1, 2) = Left(Cells(1, 1), 2)
    
End Sub

```

使用例としては都道府県や苗字などを切り離したい時です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1879772/dffc14f1-bda8-b854-ad7c-30e2cb2e6407.png)

ココで問題なのは、殆どの都道府県は3文字ですが、
神奈川県、和歌山県、鹿児島県等の4文字の場合があります。

この場合は法則性を見つけてそこから改良を考えます。
続きはセル内の文字を抽出する_３（左から指定の文字まで）
で掲載したいと思います。
Universal RP x Visual Effect GraphでDiffuseを実現する


![スクリーンショット 2021-08-16 10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1771055/49ef888c-15e5-df72-b28f-ad651111c964.png)

2021年現在、ARKit x Visual Effect Graphでエフェクトを作る際に、以下のようにiOSデバイスがHDRP(High Definition Rendering Pipeline)をサポートしていないと怒られてしまい、かっこいいエフェクトが作れない問題に直面しました。

```
Platform iOS with graphics API Metal is not supported with HDRP.
```

自分的には、Visual Effect Graph上でLit ShaderによってDiffuseを表現したかったので、Universal Rendering Pipeline上でどうにかLit か Diffuseを再現する必要がありました。そこで以下のブログを参考にShaderGraph上でDiffuseを再現しました。

https://qiita.com/edo_m18/items/1b90932a284fb8e89156

## 手順

### 1. VFX Shader Graph作成

Project内で右クリック -> Create -> Shader -> VFX Shader Graph で作成

![スクリーンショット 2021-08-16 11.03.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1771055/2f2b3dab-de5c-3f75-7ba6-d4d74708d856.png)

### 2. Diffuse shaderを書く

参考にしたブログより少しシンプルにしていますが、以下のように

![スクリーンショット 2021-08-16 11.02.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1771055/acc128a4-2ed8-fba1-25d4-b9abb5ad51d4.png)

```hlsl
fixed diff = saturate(dot(i.normal, i.lightDir));
```

を再現して、それをオブジェクトの色と光源の色に掛け合わせればOKです。ちなみに図のように光源色は掛け合わせなくても、問題ないです。


### 3. Visual Effect GraphでShaderを設定

オブジェクトの色、光源の色、光源の座標を設定できるようにします。

![スクリーンショット 2021-08-16 10.48.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1771055/e1c11787-7489-b2bd-d337-af20e453ec56.png)

Tips: VFX Property Binderで光源の座標を外部から設定をすると便利です。

![スクリーンショット 2021-08-16 10.54.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1771055/3028eada-d1ce-4491-b803-3da187f6834f.png)

ということで、Universal RP x Visual Effect GraphでDiffuseを実現できましたー。これでARKitに入れられます。

- [Twitterアカウント](https://twitter.com/supertask_jp)
- [YouTubeアカウント](https://www.youtube.com/c/TasukuTAKAHASHI)
Springアノテーション

# <span>@</span>SpringBootApplication
昔はXMLで多くの設定を書く必要があったが、この記述でそれらが自動的に行われるようになった

# <span>@</span>Test
UnitTestの対象になる


# <span>@</span>Controller
この表記をしておくと、必要な時に自動的にインスタンス化される
Dependency Injection(DI)という仕組みがあり、インスタンス化したオブジェクトをいつでも使えるように保管している（最後におまけで簡単な解説あり）
後述のComponentと同じ意味合いで、Controllerを付けた場合はComponentは付けない


#<span>@</span>ControllerAdvice
これを書き加えることで、Controllerというクラスを横断した処理を作ることができる

# <span>@</span>Component
以下のAutowiredアノテーションと関連しており、DI対象のクラスになる。対象クラスになることでAutowiredが使えるようになる。

#<span>@</span>Autowired
DIとして実装するのに必要なアノテーション
インスタンスを生成したい変数の前にこのアノテーションを付けることで、Componentアノテーションがついたクラスの中から該当するものを探してくれ、そこでnewしたものを使いまわせる（シングルトン）

#<span>@</span>Configuration
設定を書くのに必要
このアノテーションを付けたクラスが自動的に設定を記述するクラスだと認識される

#<span>@</span>RequestMapping
<span>@</span>RequestMapping("/sample")という書き方をすると、「/sample」というURLにアクセスしたときに処理が行われる
めっちゃ丁寧に説明している記事を見つけたので、参考までにリンクを共有します

https://qiita.com/TEBASAKI/items/267c261db17f178e33eb

#<span>@</span>GetMapping
<span>@</span>GetMapping("/test")という書き方をすると、「/test」というURLにアクセスしたときにGETの場合メソッドの処理が行われる

#<span>@</span>PostMapping
<span>@</span>PostMapping("/test")という書き方をすると、「/test」というURLにアクセスしたときPOSTの場合メソッドの処理が行われる

#<span>@</span>ExceptionHandler
このアノテーションの後に()でエラー内容を書くことで、エラーが起きた時にこのアノテーションを付けたメソッドが呼ばれる。すべてのコントローラで書く際はControllerAdviceアノテーションを付けたクラスで対応できる。

#<span>@</span>Transactional
トランザクション処理として行われる

#バリデーション
##<span>@</span>NotNull
NotNull制約を付けることができる

##<span>@</span>NotBlank
フォームなどでブランク（空欄）のときにエラーが出せる

##<span>@</span>Size
この後に(min = 1, max = 20)などの形で入力のバリデーションを付けることができる


#おまけ：DI(Dependency Injection)
日本語訳すると依存性の注入。
密な結合になると単体テストがしづらくなるが、疎な結合にすることで他とつながるシステムでも機能ごとの単体テストをしやすくする。
具体的には、シングルトンの考え方であり、一度別の場所でインスタンス化したものを様々な場所で使いまわすといった考え方。

#参考リンク（主な出典）
https://learning-collection.com/spring-boot%E3%81%A7%E3%82%88%E3%81%8F%E4%BD%BF%E3%81%86%E3%82%A2%E3%83%8E%E3%83%86%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E4%B8%80%E8%A6%A7/

https://note.com/yukoro/n/nf52f3fc60c17

https://qiita.com/shuntaro_tamura/items/ba5a2e9b3ba305285edd
git管理　メモ

https://speakerdeck.com/brainpadpr/git-hands-on?slide=01

#基本的な用語
**ローカル（自分）
リモート(git.hub)**

ローカル（自分）の環境で編集をして、リモート（ネット上：git.hub）に移す。
そうすることで自分以外の人がコードを見れるようになる。

#git管理を始めるとき

```
＄ gitinit
```

git管理をはじめる、と宣言
ネットにはまだ接続出来ていない状態
→それがmasterブランチになる

リモートリポジトリ設定
→https://qiita.com/aiten/items/cec2a7a78e799170b699

#確認
```
$ git status
```
何のファイルを変更したか確認する
**不安なことがあれば随時確認すること！**

#git add
```
$ git add 変更したディレクトリ
```

addすることで「このディレクトリをgitの管理対象にします！」と宣言しているイメージ
もしくは


```
git add -e
```

→git管理化の変更したファイルだけをadd

```
$ git add . 

```
**※注意**
→カレントディレクトリ以下の、変更があったすべてのファイルがaddされる

https://eng-entrance.com/git-add

#コミット

```
$ git commit -m 'メッセージ（何をしたか書く）' //コミット
```
オフラインで自分の変更点をアップデート

#プッシュ
```
$ git push origin  ディレクトリ名（００） //プッシュ
```
これで初めてネット上に公開される
commitした内容をorigin（リモート）の００に同期


#プルリクエスト
git hub上でpull request（プルリク、PRとも呼ばれる）を出す


#マージ
→プッシュしたブランチをリモートのマスターにマージ
git hub上でmergeする
→マスターに結合

マスターに移動して

```
$　git checkout master
```

リモートのmasterをローカルに同期

```
$　git pull(fetch) origin master
```

新しいブランチを作る

```
$　git checkout -b 新しいブランチ名
```
→元々　ブランチがある場合はそのブランチに移動する

```
$　git checkout ブランチ名
```

マージ

```
$　git merge master
```
masterを作業ブランチにmerge
alredy update...(？？？)


#応用編〜　他人がプッシュした時

最新をpull

```
$　git pull origin ブランチ名
```

もしくは

```
$ git fetch origin ブランチ名
$ git merge origin/ブランチ名
```

コンテナの中に入って

```
$　composer install
```
#addする前に戻す（赤にする）

commit履歴を確認

```
$ git log
```

↓このように表示される（commit番号をここで確認）

```
commit 37bacf39595a9472c689e6ae82a9c28f757e6e63 (HEAD -> feature/CBET-102_post_article_debug, origin/feature/CBET-102_post_article_debug)
Author: aiten <aiten@gmail.com>
Date:   Fri Sep 10 10:18:35 2021 +0900

    デバッグ用

commit 2f085686ff824ee5edf02e9eb5f84f0380396e7d (feature/CBET-102_post_article)
Author: aiten <aiten@gmail.com>
Date:   Fri Sep 10 10:16:07 2021 +0900

    新規投稿フォームの作成

commit 41051d157ed07ec8143b229d437f6b06d2376644
Author: aiten <aiten@gmail.com>
Date:   Fri Sep 10 10:15:34 2021 +0900

    リレーショナルテーブルの作成
```
→commitの取り消し（消したいcommitのcommit番号を指定）

```
git reset --soft 2f085686ff824ee5edf02e9eb5f84f0380396e7d（戻りたいところ：今は新規投稿フォームの作成のコミット）
```

```
git status
```
確認すると↓（緑で表示されている）

```
	modified:   apps/laravel/app/Article.php
	modified:   apps/laravel/app/Http/Controllers/ArticleController.php
	modified:   apps/laravel/resources/views/layout/article_layout.blade.php
	modified:   apps/laravel/routes/web.php
```

git addの取り消し

```
git reset HEAD
```

→赤になる

#最後にコミットした状態に戻す
```
git reset --hard HEAD
```
編集・ステージングいずれの変更内容を取り消し、最後にコミットした状態に戻す
[記事紹介] HTTPSレコードとCNAMEと大失敗

@qualitia_cdevの中の一人、@hirachanさんが書いた記事をみなさまにご紹介します。


### HTTPSレコードとCNAMEと大失敗

https://qiita.com/hirachan/items/c52e79208befa798fe0e
PythonでGmailにExcelファイルを添付する

# はじめに
GmailにExcelファイルを添付してメールを送るというのを自動化したくて試してみました。
Googleのサンプルスクリプトだとファイル添付はできるのですが、ダウンロードするとファイルが壊れてしまいました。
いろいろと調べて、Excelファイルが持つMIMEタイプをそのまま適用するのがよくないようで、この方法にたどり着きました。

# 参考にした投稿
https://qiita.com/muuuuuwa/items/822c6cffedb9b3c27e21

Gmail APIの利用の始め方からスクリプトの書き方までとても参考になりました。ありがとうございました。

# ExcelファイルをGmailに添付して下書きを作るスクリプト
```python

from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
import base64
from email import encoders

def create_message_with_attachment(送信先アドレス, 送信元アドレス, タイトル, CCのアドレス, 本文, 添付ファイルのフルパス):
    message = MIMEMultipart()
    message["to"] = 送信先アドレス
    message["from"] = 送信元アドレス
    message["subject"] = タイトル
    if CCのアドレス:
        message["Cc"] = CCのアドレス
    # attach message text
    enc = "utf-8"
    msg = MIMEText(本文.encode(enc), _charset=enc)
    message.attach(msg)

    #このMIMETypeの書き方にしないと、Excelファイルを添付できてもダウンロードしたあとに、ファイルが壊れて開けない。
    part = MIMEBase('application', "octet-stream")
    part.set_payload(open(添付ファイルのフルパス, "rb").read())
    encoders.encode_base64(part)
    p = Path(添付ファイルのフルパス)
    part.add_header('Content-Disposition', 'attachment', filename=p.name)
    message.attach(part)

    encode_message = base64.urlsafe_b64encode(message.as_bytes())
    return {"raw": encode_message.decode()}

if __name__ == '__main__':

    #API認証を終えて、gmailのサービスオブジェクトを”service”として取得している前提。

    message_body = create_message_with_attachment(送信先アドレス, 送信元アドレス, タイトル, CCのアドレス, 本文, 添付ファイルのフルパス)
    message = {'message': message_body}
    draft = service.users().drafts().create(userId=送信元アドレス, body=message).execute()

```
[シリーズ] docker-compose で influxdb 1.8 + grafana を立ち上げる


docker-compose を使って後述の構成で、
influxdb 1.8 + grafana の立ち上げを試みたときの記録.

|コンテンツ|実践時期|
|:--|:--|
|[[01] docker-compose で influxdb 2.0 + grafana を立ち上げる ... 🔥失敗🔥](https://qiita.com/robozushi10/items/a0e8b3de1b9a9628f751)|2021/08|
|[[02] docker-compose で influxdb 1.8 + grafana を立ち上げる](https://qiita.com/robozushi10/items/d29b255fec94e4fdde2f)|2021/08|
gitコマンド実行時にPasswordじゃなくてPersonal Access Tokenを使えと言われたら


## 出力

```sh
$ git pull
remote: Support for password authentication was removed on August 13, 2021. Please use a personal access token instead.
remote: Please see https://github.blog/2020-12-15-token-authentication-requirements-for-git-operations/ for more information.
fatal: unable to access 'https://github.com/team/repo.git/': The requested URL returned error: 403
```

GitHubの認証にPasswordじゃなくてPersonal Access Tokenを使えと言われています

## やったこと

1. `github.com` の認証情報の削除
    1. MacOSの場合はKeychain Accessの `種類: インターネットパスワード` の項目を削除![スクリーンショット 2021-08-16 10.27.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209400/8dec765a-ee44-6392-7b5a-8def2497945b.png)

    1. Windowsの場合は資格情報マネージャーから削除するみたいです cf. https://webbibouroku.com/Blog/Article/git-logout-win

1. PAT (Personal Access Token) の生成
    1. GitHub > Settings > Developer settings > Personal access tokens
    1. Generate new token から任意の名称で作成します
    1. 権限は `repo` にだけ全振りして、有効期間は90日間としました ![スクリーンショット 2021-08-16 10.23.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209400/eac52ccf-5ebb-c1ee-c16e-41d78cf06895.png)
    1. 生成後、 `ghp_` から始まるトークンが表示されるものを控えておきます（画面遷移すると表示されなくなります）

1. GitHubのユーザー名とパスワードを更新する
    1. `git pull` 等の任意のgitコマンドを実行すると `Username` と `Password` を要求されます
    1. 以前はPasswordにGitHubへのログインパスワードを入力していたと思いますが、そこに今回生成したPATを入力します
    1. そのまま任意のgitコマンドが実行されれば成功です


---
### メモ
`github.com` の認証情報の削除を、Keychain Accessからではなく、次のようにコマンドラインで全て `unset` する方法が出てきましたが私の場合は特に変化がありませんでした。

```sh
git config --global --unset user.name
git config --global --unset user.email
git config --global --unset credential.helper

# - or -

git config --global --unset-all
```
Laravel:テーブルが存在しない

Laravelで.envのDB_DATABASEを変更した際にエラーが発生

# エラー：SQLSTATE[42S02]: Base table or view not found
```
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'laravel_app.sessions' doesn't exist (SQL: select * from `sessions` where `id` = RLyjYTMASaa1TXmEdnnFOGFfHIbooQbcTNM1DZle limit 1)
```

テーブルが存在しないとのこと

# 原因
DB変更後、マイグレーションファイルを作成していない

# 解決策
なにかしらのマイグレーションファイル作成→マイグレーションを行う

```
php artisan make:migration create_records_table
```

ファイル名は複数形にすることを忘れずに。

マイグレーションを実行する

```
% php artisan migrate
Migrating: 2014_10_12_200000_add_two_factor_columns_to_users_table
Migrated:  2014_10_12_200000_add_two_factor_columns_to_users_table (11.12ms)
Migrating: 2019_12_14_000001_create_personal_access_tokens_table
Migrated:  2019_12_14_000001_create_personal_access_tokens_table (8.50ms)
Migrating: 2021_07_10_082038_create_sample_table
Migrated:  2021_07_10_082038_create_sample_table (2.85ms)
Migrating: 2021_07_27_204225_create_sessions_table
Migrated:  2021_07_27_204225_create_sessions_table (10.29ms)
Migrating: 2021_08_10_110140_add_user_id_to_blogs_table
Migrated:  2021_08_10_110140_add_user_id_to_blogs_table (12.29ms)
Migrating: 2021_08_16_102523_create_records_table
Migrated:  2021_08_16_102523_create_records_table (10.12ms)
```


php artisan serveを実行してビューをリロードすれば解決。

```
% php artisan serve
Starting Laravel development server: http://127.0.0.1:8000
[Mon Aug 16 10:34:58 2021] PHP 7.4.20 Development Server (http://127.0.0.1:8000) started
[Mon Aug 16 10:35:03 2021] 127.0.0.1:65418 Accepted
[Mon Aug 16 10:35:03 2021] 127.0.0.1:65419 Accepted
[Mon Aug 16 10:35:03 2021] 127.0.0.1:65420 Accepted
[Mon Aug 16 10:35:03 2021] 127.0.0.1:65420 Closing
[Mon Aug 16 10:35:34 2021] 127.0.0.1:65418 Closed without sending a request; it was probably just an unused speculative preconnection
[Mon Aug 16 10:35:34 2021] 127.0.0.1:65418 Closing
[Mon Aug 16 10:35:34 2021] 127.0.0.1:65419 Closed without sending a request; it was probably just an unused speculative preconnection
```


# まとめ
.envのDB_DATABASEを変更したあとは、マイグレーションファイルを作ること。
[Java] Java Bronze SE の試験に合格した勉強方法

# はじめに

`Java Bronze SE　試験番号1Z0-818`の試験に約１ヶ月で合格したのでその勉強方法をまとめました。
目安としては、Java以外のプログラミング言語の基礎は理解している状態で1日1〜2時間ほど勉強しました。
勉強方法はたくさんあるので自分にあった方法で学ぶことが一番ですが、やる気はあるけど、どう勉強したら良いのか悩んでいる方の手助けになれたら幸いです。

# 合格のためのステップ
## ステップ１
まずは参考書を購入しましょう。
オラクル認定資格教科書と問題集を購入することをお勧めします。

[オラクル認定資格教科書 Javaプログラマ Bronze SE(試験番号1Z0-818) / 山本 道子(著)](https://www.amazon.co.jp/%E3%82%AA%E3%83%A9%E3%82%AF%E3%83%AB%E8%AA%8D%E5%AE%9A%E8%B3%87%E6%A0%BC%E6%95%99%E7%A7%91%E6%9B%B8-Java%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9E-Bronze-SE-%E8%A9%A6%E9%A8%93%E7%95%AA%E5%8F%B71Z0-818/dp/479816206X/ref=pd_lpo_1?pd_rd_i=479816206X&psc=1)
[徹底攻略Java SE Bronze問題集[1Z0-818]対応 / 志賀澄⼈(著),⼭岡敏夫 (著)](https://www.amazon.co.jp/%E5%BE%B9%E5%BA%95%E6%94%BB%E7%95%A5Java-SE-Bronze%E5%95%8F%E9%A1%8C%E9%9B%86-1Z0-818-%E5%AF%BE%E5%BF%9C/dp/4295008958)

メルカリやラクマで出品されていれば、安く手に入るかもしれません。
似たような表紙の参考書や問題集があるため、自分が受けたい試験番号と同じかどうかを購入する前に必ずチェックしましょう。

## ステップ２
`オラクル認定資格教科書`から使用していきます。
まずは第一章の説明を読みます。この時、実際にパソコンで動かしながら進めてください。

そして第一章の練習問題を解きます。ここでポイントなのが、一問解いたらすぐ答え合わせをして、また一問解いたらすぐ答え合わせをして...というのを繰り返します。

なぜなら、例えば10問解いた後にまとめて答え合わせをした場合、「自分がどうやってこの答えを選んだのか」「どの問題が分からなかったのか」が明確でなくなるからです。「答えはたまたま正解していたけれど理解していない」ということになってしまったら問題を解いた意味がなくなってしまいます。

分からなかったり、間違えた問題は解説をしっかり読んだり、説明に戻ったりして理解します。
正解した問題もさらっと解説を読んで理解を深めるとより良いです。
また、分からなかったり、間違えた問題には印をつけておくと復習の時に便利です。

## ステップ３
第一章の練習問題まで終えたら次の章も同じように進めていってください。
（模擬試験はまだやらずにとっておきましょう）
実際にパソコンで動かしてみるのを忘れずに！

その前にここでポイントなのが、新しい章に進むときは、前の章の内容を忘れないために次の日に昨日勉強した章を復習します。

新しく学んだ内容を「覚える」ことと、すでに学んだ内容を「思い出す」という2つをミックスして暗記するのがおすすめです。
完全に忘れてしまわないうちに繰り返し復習することが大切なのです。
これをすることで、短期記憶から長期記憶として脳に定着し、忘れにくくなると言われています。

具体的には、
` 第１章　→ 第１章の復習と第2章　→ 第１章と第2章の復習と第３章　... `
という具合です。
これじゃあ、どんどん復習の量が増えていってすごい時間かかりそうだし大変じゃん、と思われるかもしれませんが、新しい章を学ぶよりも昨日学んだことを思い出しながら復習する方が時間はかからないし、2回目より3回目と回数を重ねるたびに復習にかかる時間は減っていきます。（覚えた、と感じたページはさらっと目を通す程度になる）
復習をしないでどんどん新しい章をにいってしまった場合、第１章の内容はほとんど忘れてしまい、また一から勉強し直すことになります。復習をしたほうが圧倒的に効率が良いのです。

## ステップ４
オラクル認定資格教科書をやり終えたら、`徹底攻略Java SE Bronze問題集`を解いていきます。

問題集も認定資格教科書の練習問題と同様に、一問解いたらすぐ答え合わせをして、また一問解いたらすぐ答え合わせをして...というのを繰り返します。
また、正解した問題でも一度は解説を読むことをお勧めします。
問題集の解説は問題の解説以外にもオラクル認定資格教科書で学んだことにプラスで知識がつくようなことが書いてあるので、より理解が深まります。

間違えた問題やわからなかった問題には印をつけて、2回目は印をつけた問題だけを解きます。
3回目も同様に、2回目に間違えた問題だけを解きます。
これを繰り返すと間違えた問題がなくなっていきます。
そしたら最終ステップにいきましょう。

## ステップ５
最終ステップです。
`オラクル認定資格教科書の模擬試験`や、`徹底攻略Java SE Bronze問題集の総仕上げ問題`を解いていきます。

ここでポイントなのが、本番の試験だと思って時間を測り、見直しもします。
1個目でどれくらいのペースで問題を解けばい良いのかを掴めるようにしましょう。全く問題が分からなくて解けなかった場合は、オラクル認定資格教科書や問題集に戻って復習しなおします。

全ての模擬試験をやり終わった時点で合格ラインの60％を超えていれば自信を持って試験の申し込みをしましょう！

本番当日はここまでやり遂げれたことに誇りを持ち、落ち着いて試験に挑みましょう！
合格できることを祈っています！💪✨
Process Automation Specialist のまとめ


[まとめページに戻る](https://qiita.com/Keiji_otsubo/items/60afc2a8d211b6f7d89f)

# Step 2

**System.NullPointerException: Attempt to de-reference a null object in Process Automation Specialist**

[System.NullPointerException: Attempt to de-reference a null object in Process Automation Specialist](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000HDAnd)
翌日は問題なかったらしい... 環境のバグ？


# Challenge 5 CANNOT_EXECUTE_FLOW_TRIGGER

[Getting this error in 5th step ( Automate Opportunities) of Process Automation Specialist superbadge. :](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000DdAH8SAN)

# Challenge 6 

**There was an unhandled exception. Please reference ID: YRQGUFCA. Error: Restforce::ErrorCode::MalformedQuery. Message: MALFORMED_QUERY: When retrieving results with Metadata or FullName fields, the query qualificatio​ns must specify no more than one row for retrieval. Result size: 2**

Check Setup > Lightning App Builder.
You need only 1 Lightning page for Opportunities. Delete all other pages.

[Error: Restforce::ErrorCode::MalformedQuery. Message: MALFORMED_QUERY:](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000A95t9SAB)

[ FIELD_INTEGRITY_EXCEPTION: Assigned To ID: id value of incorrect type: 0015f00000Cs08EAAR. Y](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000DymFuSAJ)

[Superbadge Process Automation Specialist - Full Solutions](https://salesforcehandle.com/superbadge-process-automation-specialist-help/)

**System.DmlException: Insert failed. First exception on row 0; first error: CANNOT_EXECUTE_FLOW_TRIGGER, We can't save this record because the “Opportunity automation7” process failed. Give your Salesforce admin these details. This error occurred when the flow tried to create records: FIELD_INTEGRITY_EXCEPTION: Assigned To ID: id value of incorrect type**

[#Salesforce Admin #Trailhead Challenges #Trailhead #Automation #Process AutomationSpecialistSuperbadgeこの問題が発生しています。手伝ってもらえますか？](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000G2cVS)

+ [課題＃6プロセス自動化スーパーバッジ：ロボットセットアップカスタムオブジェクトがレコードタイプに表示されない](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000HBreE)
Rまでスクロールダウンした場合は、検索ボックスに「ロボット」と入力して試してください。その奇妙な、しかし時々それは私と一緒に起こりました。それが役に立たない場合は、私が推測するきれいなスレートから始める必要があります。

# その他

**Approval Process.2 failed.The approval request requires the next approver to be determined by the Manager field. This value is empty**

[Process Automation Specialist Superbadge](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000E9jDF)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/181d9774-869a-ee1c-01e7-4a37ba6d9c32.png)

[I am facing this error while checking my challenge Automate Oppotunities on Process Automation Specialist. Please help to overcome from the Problem.](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000HkBLVSA3)

アクティブ化されてないため？
リモートカメラシステム　（クローン部分）

次のシステムを構成するサブシステムです。
[Grove IoT スターターキット for SORACOM で作るリモートカメラシステム](https://qiita.com/ekzemplaro/items/541b82908cec46f6aa7b)

制作開始日

>2021年8月16日
>システムを構築している様子を報告していきます。
>必要な技術については見通しが立っているので、それを組み合わせていきます。

完成日

>2021年8月23日

cron のインストール

```bash
sudo apt install cron
```

実行されていることの確認

```text
$ sudo systemctl status cron
● cron.service - Regular background program processing daemon
   Loaded: loaded (/lib/systemd/system/cron.service; enabled; vendor preset: enab
   Active: active (running) since Mon 2021-08-16 09:52:46 JST; 26s ago
     Docs: man:cron(8)
 Main PID: 1496 (cron)
    Tasks: 1 (limit: 4915)
   Memory: 468.0K
   CGroup: /system.slice/cron.service
           └─1496 /usr/sbin/cron -f
```

クローンで実行するスクリプト

```bash:/var/www/mqtt/shutter_on/shutter_on.sh
#
#	shutter_on.sh
#
#					Aug/22/2021
#
BROKER="example.com"
TOPIC="sample/imageTopic"
#
echo $BROKER
message='{"button": "on"}'
echo ${message}
mosquitto_pub -d -t orz -m "${message}" -h ${BROKER} --topic ${TOPIC}
#
```

クローンの設定

```text
$ crontab -l
# m h  dom mon dow   command
28 * * * * /var/www/mqtt/shutter_on/shutter_on.sh
#
```
Route53, GCE, React, FastAPIを用いて簡単なWebアプリを作製する 【後編】

# なんの記事？
以下の記事の後編になります。

https://qiita.com/izuna385/items/64812520a1f2f79d2154

# GCEでのインスタンス作成、起動

下記に従い今回は進めていきます。

https://cloud.google.com/community/tutorials/docker-compose-on-container-optimized-os

## インスタンスの作成

https://console.cloud.google.com/compute/instancesAdd

からインスタンスを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357766/2bef1cb9-3fcc-2564-e936-f13d11477287.png)

外部からの通信を許可したいので、httpsトラフィックを許可します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357766/5a878721-370b-69aa-893c-e7ae1a551d98.png)


自動再起動はオフにしておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357766/c0865aa1-b5b2-7f60-8bf2-fdfb93325de3.png)

起動したので、VM内にsshします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357766/5f9e2ed4-7d1f-2c55-ceec-679f0a1898d3.png)

# VM内での環境構築

https://dev.to/seattleconsulting/gce-docker-compose-3em

を参考に

* docker-composeの導入
* GitHubからのリポジトリクローン
* https通信の穴あけ

を行います。

```
$ sudo apt update
$ sudo apt install apt-transport-https ca-certificates curl gnupg2 software-properties-common
>> OK

$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable"

$ sudo apt update
$ apt-cache policy docker-ce
$ sudo apt install docker-ce
$ sudo systemctl status docker
$ docker --version
>> Docker version 20.10.8, build 3967b7d
$ sudo usermod -aG docker ${USER}
```

一旦ログアウトし直し、docker-composeの設定を続けます。
今回はdocker-composeのイメージを利用します。

https://qiita.com/gorohash/items/608da9050b32db581802#docker-compose%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B

```
$ docker run docker/compose:1.22.0 version
```

リポジトリをクローンした後、ビルドします。
`--recursive` を行う場合は公開鍵認証が別途必要なので、暫定で対応します。

```
$ git clone https://github.com/izuna385/arxiv-checker.git
$ cd arxiv-checker
$ rm -r -f backend
$ git clone https://github.com/izuna385/arxiv-checker-backend
$ mv arxiv-checker-backend backend
$ docker run --rm \
    -v /var/run/docker.sock:/var/run/docker.sock \
    -v "$PWD:/rootfs/$PWD" \
    -w="/rootfs/$PWD" \
    docker/compose:1.22.0 -f docker-compose.prod.yml up -d --build
```
ここまで行った後、外部IPを見に行きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357766/b888b4bd-c8ce-aa57-95f4-fa15210f49f7.png)

http通信では表示が確認できました。

# Route53を用いたDNS解決
最後にRoute53で接続まで行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357766/7de81481-4925-d6ca-07bc-94cb73f1d405.png)

レコードを作成した後、アドレスにアクセスします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357766/995a6d26-d6a1-6f7d-b9c3-e1e7d2099f70.png)

これにて、デプロイすることが出来ました。（現在はVMを停止しており、アクセスは出来ません。）

# 改善点
* https通信では表示されず、原因を確認中です。分かり次第追記します。
* この構成だと、大量にアクセスが来たときにスケールしません。フロントとバックエンドでそれぞれ、大量アクセスが来た時にスケールするよう構成を見直す必要があります。

# リポジトリ
https://github.com/izuna385/arxiv-checker
next/head

next.jsではhtmlのheadタグの中にmetaタグなど色々を出力したい場合はnext/headコンポーネントを利用する。


## 使い方

Headのchildrenが動的にheadタグに入る。

```jsx
import Head from 'next/head'

function IndexPage() {
  return (
    <div>
      <Head>
        <title>My page title</title>
        <meta name="viewport" content="initial-scale=1.0, width=device-width" />
      </Head>
      <p>Hello world!</p>
    </div>
  )
}
export default IndexPage
```

## 重複をなくす

一意的なkeyを設定すると、後勝ちで１つのみが適応される。

```jsx
import Head from 'next/head'

function IndexPage() {
  return (
    <div>
      <Head>
        <title>My page title</title>
        <meta property="og:title" content="My page title" key="title" />
      </Head>
      <Head>
        <meta property="og:title" content="My new title" key="title" />
      </Head>
      <p>Hello world!</p>
    </div>
  )
}

export default IndexPage
```

上記レンダリングの結果には`My new title`が出力される

```html
<html>
  <head>
    <meta property="og:title" content="My new title" />
  </head>
...
```
【Ruby on Rails】Topに戻るボタンの作成方法


#対象者

*　画面にTopに移動するボタンを作成したい方


#目的

* 下にスクロールしてもすぐに画面の一番上に移動できるようにする

#実際の手順と実例
###1.画像の用意

まず画像を準備します。

何でも大丈夫ですが、下記のファイルを使用して頂いて大丈夫です。

![arrow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1681213/ff3906c7-ea0e-e9df-3bcd-ecc9cd0f157e.png)

こちらの画像を
app/assets/imagesに格納します。


###2.Viewの設定

今回はすべてのページで表示したいので
application.html.erbへ記載します。

```app/views/layout/application.html.erb
<body>
  <%= yield %>
  <span id="back">
    <a href="">
      <%= image_tag asset_path('arrow.png'), data: {"turbolinks"=>false}, class: "arrow" %>
    </a>
  </span>
</body>
```
* 画像の拡張子は画像によって変えてください


###3.CSSファイルの設定

```
#back {
  position: fixed;
  right: 20px;
  bottom: 20px;
}
.arrow{
  width:      50px;
  height:     50px;
}
```
position:fixed;で場所を固定します。
その下でどの位置に固定するかを決めます。

###4.jsファイルの設定

```
gem jquery-rails
```

上記をGemfileに加えて**bundle install**を実行

````app/assets/javascripts/application.js
$(function() {
  $('#back a').on('click',function(event){
    $('body, html').animate({
      scrollTop:0
    }, 800);
    event.preventDefault();
  });
});
````

クリックした際に上記へスクロールします。
0のかh祖は変化値　→　０なので一番上に繊維
800はアニメーション動作時間なので数字を変えると動作スピードが変わります。

####投稿者コメント

最近実装してみたので、改めて復習してみました。
他にもjQueryを使用して色々実装してみたいと思います。

####My Profile
プログラミング学習歴３ヶ月目のアカウントです！
プログラミングスクールで学んだ内容や自分が躓いた箇所等のアウトプットの為に発信しています。
また、プログラミング初学者の方にわかりやすく、簡潔にまとめて情報共有できればと考えています。
もし、投稿した記事の中に誤り等ございましたら、コメント欄でご教授いただけると幸いです。
git hook を使って push時に特定の処理を実行する


# 内容

リモートリポジトリ側で git hook を使って、
push を検知したときに何かしらの処理を行うための設定である.

手順自体は後述のサイトそのままに近いが、何かしらの補足にはなるかと思う.

# 手順

ここでは以下とする.

・サーバサイドの Git リポジトリ置き場を「`${RD}`」とする.
・push を検知したいリポジトリを「`A.git`」とする.


#### 1. ${RD}/A.git/hooks/post-receive を作成する

```bash
$ sudo touch ${RD}/A.git/hooks/post-receive 
$ sudo chmod +x ${RD}/A.git/hooks/post-receive 
```

#### 2. ${RD}/A.git/hooks/post-receive に処理を書いていく

下記のコードは次の処理をする
・「ブランチ」「コミットID」「直前のコミットID」を取得する.
・a.txt が更新されていれば「git diff 〜 a.txt」をする.

なお、push するたびに echo によるログが出るので必要に応じて塞ぐこと.

実際の業務では、push を検知したら Jenkins に対して cURL で非同期による
ジョブ実行をさせている.

```bash
#!/bin/bash

# デバッグ用ログとして表示するリポジトリ名を定義する. 
# 本例だと A.git と表示されるはずである.
BN=`basename $0`

# 標準入力を一行づつ読み出す
while read oldrev newrev refname X Y Z; do
    branch=$(git rev-parse --symbolic --abbrev-ref $refname)
        # push 前のリビジョン
        echo "[`date +"%Y/%m/%d-%H:%M:%S"`][$BN] oldrev=<$oldrev>"
        # push 後のリビジョン
        echo "[`date +"%Y/%m/%d-%H:%M:%S"`][$BN] newrev=<$newrev>"
        # ブランチ名
        echo "[`date +"%Y/%m/%d-%H:%M:%S"`][$BN] BRANCH=<$branch>"
    if [[ $( git diff --name-only $oldrev $newrev -- a.txt ) ]]; then
        # 何か処理をする. ここではリビジョン間での差分を表示しているだけである.
        git diff $oldrev $newrev -- a.txt
    fi
done
```


# 参考にしたサイト

|URL|
|:--|
|https://songmu.jp/riji/entry/2014-08-07-post-receive-branch.html|
|https://stackoverflow.com/questions/7351551/writing-a-git-post-receive-hook-to-deal-with-a-specific-branch/13057643#13057643|
Grove IoT スターターキット for SORACOM で作るリモートカメラシステム

テスト風景
![IMG_20210819_081722.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/ea4dcafe-ab89-3199-5afd-7725a3b43fa3.jpeg)

Web で画像を表示
![mqtt_jpg_aug20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/40b750ef-0a5a-99c9-7a4f-0b360d636d1c.png)


制作開始日
>　2021年8月16日
>　システムを構築している様子を報告していきます。
>　必要な技術については見通しが立っているので、それを組み合わせていきます。

完成日
>　2021年8月23日
>
>当初の予定では、プロトコルは MQTT だけの予定でしたが、画像のアップロードを HTPP POST に変更して完成しました。

必要なハード
>Grove IoT スターターキット for SORACOM
>TTL serial Camera (Adafruit VC0703)

使われる通信プロトコル
>MQTT (Web ページとの通信）
>HTTP (WioLTE との通信）

必要なサーバー
>MQTT ブローカー
>MQTT over WebSocket に対応したもの
>test.mosquitto.org などの public MQTT もテストには使える
>[MQTT over WebSocket に対応した mosquitto の設定](https://qiita.com/ekzemplaro/items/0b863ed76e997ec01f5c)

システムの要件
>定められた時間に自動で撮影する。
>例えば日中は10分毎、夜間は1時間毎という撮影ができる。
>必要な時には、いつでも手動で撮影ができる。


次の6つのサブシステムで構成されます。

1) Arduino
　　MQTT Subscribe でシャッター ON の信号を受け
　　画像を撮影
　　画像を MQTT で Publish する。
[リモートカメラシステム　（Arduino 部分）](https://qiita.com/ekzemplaro/items/4e2a64aa5a3a1e182b7f)

>必要な技術
>>Arduino の TTL Serial カメラで画像を撮影する方法
>>画像を Base64 で変換
>>JSON を作成
>>JSON を MQTT で Publish
>>MQTT の Subscribe を受けて画像を撮影

>考慮が必要な点
>>[Arduino Client for MQTT](https://github.com/SeeedJP/pubsubclient)
>>The maximum message size, including header, is 128 bytes by default. 
>[WioLTE で 大きいデータを MQTT Publish する](https://qiita.com/ekzemplaro/items/7a7cbcfca11c2de28dd1)
 
2) Web ページ
　　MQTT Subscribe で画像を取得して表示
　　ボタンクリックで、シャッター ON を Publish
[リモートカメラシステム　（Web ページ部分）](https://qiita.com/ekzemplaro/items/0ceafae3f0d2c9eaa82c)

>必要な技術
>>MQTT の Subscribe で画像を受信してページに表示
>>ページにあるボタンをクリックして、MQTTのPublish を行う

>検証
>>[MQTT over WebSocket で画像を表示](https://qiita.com/ekzemplaro/items/545260fff37db8b3cc30)

3) クローン設定
　　設定に従い　シャッター ON を Publish
[リモートカメラシステム　（クローン部分）](https://qiita.com/ekzemplaro/items/c613c101b4bbb0ae3925)

>必要な技術
>>クローン設定で MQTTのPublish を行う

4) HTTP POST を MQTT　に変換する API
>http_to_mqtt.py
>プログラムはこちらです。
>[HTTP POST を MQTT Publish に変換する](https://qiita.com/ekzemplaro/items/df8e8eb7b7ee50c18158)

5) HTTP POST を file に変換する API 
>http_to_file.py
>プログラムはこちらです。
>[HTTP POST を file に変換する API](https://qiita.com/ekzemplaro/items/679b4e80f1b421cc33c2)

6) MQTT を file に変換する常駐プログラム
>mqtt_to_file.py
>プログラムはこちらです。
>[MQTT を file に変換するプログラム](https://qiita.com/ekzemplaro/items/e4db9635047029867246)

システム構築で考慮したこと
>Arduino のプログラムをシンプルにする
>撮影タイミングの制御は Arduino で行わない
>Arduino にデータは持たない
>SD カードは使わない

先行テストで確認すべきこと
>画像の受け渡しが MQTT ブローカー経由でできるか。
>画像ファイルは、計測した数値データと較べて、かなり大きい。
[リモートカメラシステム（MQTT ブローカーの検証）](https://qiita.com/ekzemplaro/items/1ac5b1b30c08e414c561)
[リモートカメラシステム （MQTT ブローカーに画像をそのまま送る）](https://qiita.com/ekzemplaro/items/f6da54ffc38b6f6e9c94)
[WioLTE で MQTT Publish できる最大サイズを調べる](https://qiita.com/ekzemplaro/items/f5f4eab42c1b5afcb985)
>[HTTP POST を MQTT Publish に変換する](https://qiita.com/ekzemplaro/items/df8e8eb7b7ee50c18158)
>>画像表示の Web ページの開発に使います。

各サブシステムについては、個々にページを設けます。
[備忘] Git操作例集


Git操作例のメモ.

|コンテンツ|一言|
|:--|:--|
|[これまで運用してきたリポジトリ「A」の履歴を維持して、新規リポジトリ「B」に登録する](https://qiita.com/robozushi10/items/a8771b20d9028a37de22)|git set-url remote <リモート名> <URL> |
|[git hook を使って push時に特定の処理を実行する](https://qiita.com/robozushi10/items/ce439faca44d44fce67b)|Gitリモートリポジトリ側の設定である|
ブルーライトカットは効果がないらしい

パソコンのモニターをのぞきっぱなしのエンジニアにぜひ知ってもらいたい情報です。ブルーライトカットは『目の疲労に関しては効果なし』という情報です。

眼精疲労の原因も実験して紹介してあるので勉強になります。エンジニアの方は1度は読んで損はないかと思います。僕は実際にこの記事の調整を行って目の疲労をかなり抑えることができました。

ブルーライトカットは効果ない？意味ない？パソコンの目の疲労の原因はフリッカー
https://uma-shi.com/archives/13419
Ubuntu(20.04LTS) + Kubernetes(v1.21.3)にmetrics-serverをインストール

#設定

基本は[githubのページ](https://github.com/kubernetes-sigs/metrics-server)の通りに設定していく。
一部追記が必要なため、yamlをダウンロードする。

```bash:
$ wget https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
```

```diff:components.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    k8s-app: metrics-server
  name: metrics-server
  namespace: kube-system
spec:
  selector:
    matchLabels:
      k8s-app: metrics-server
  strategy:
    rollingUpdate:
      maxUnavailable: 0
  template:
    metadata:
      labels:
        k8s-app: metrics-server
    spec:
      containers:
      - args:
        - --cert-dir=/tmp
        - --secure-port=443
        - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
        - --kubelet-use-node-status-port
        - --metric-resolution=15s
        image: k8s.gcr.io/metrics-server/metrics-server:v0.5.0
        imagePullPolicy: IfNotPresent
+        command:
+        - /metrics-server
+        - --kubelet-insecure-tls
+        - --kubelet-preferred-address-types=InternalIP
```

#適用

```
$ kubectl apply -f components.yaml
serviceaccount/metrics-server created
clusterrole.rbac.authorization.k8s.io/system:aggregated-metrics-reader created
clusterrole.rbac.authorization.k8s.io/system:metrics-server created
rolebinding.rbac.authorization.k8s.io/metrics-server-auth-reader created
clusterrolebinding.rbac.authorization.k8s.io/metrics-server:system:auth-delegator created
clusterrolebinding.rbac.authorization.k8s.io/system:metrics-server created
service/metrics-server created
deployment.apps/metrics-server created
apiservice.apiregistration.k8s.io/v1beta1.metrics.k8s.io created
```

#メトリクス収集確認
```
$ kubectl -n kube-system top pods
W0815 23:53:59.483427  528625 top_pod.go:140] Using json format to get metrics. Next release will switch to protocol-buffers, switch early by passing --use-protocol-buffers flag
NAME                                       CPU(cores)   MEMORY(bytes)
calico-kube-controllers-58497c65d5-gjbqc   4m           24Mi
calico-node-pkpbv                          65m          141Mi
coredns-558bd4d5db-8qbv7                   6m           16Mi
coredns-558bd4d5db-qfr55                   6m           15Mi
etcd-xxxxccc                               38m          46Mi
kube-apiserver-caltagx                     103m         479Mi
kube-controller-manager-caltagx            23m          63Mi
kube-proxy-d68mn                           1m           31Mi
kube-scheduler-caltagx                     5m           23Mi
metrics-server-6468fcbb58-kf7mc            5m           19Mi
```
これまで運用してきたリポジトリ「A」の履歴を維持して、新規リポジトリ「B」に登録する


# 内容

これまで運用してきたリポジトリ「A」の履歴を維持して、新規リポジトリ「B」に登録する.
ここでは「A」「B」を次として手順を記す.

リポジトリ「A」... <font color="Orange">GitLab</font>
リポジトリ「B」... <font color="Blue">GitHub</font>


# 手順

##### 1. GitHub に登録したい <font color="Orange">GitLab</font> のリモートリポジトリを clone してくる

```
$ git clone git@gitlab.com:A/B.git
$ cd zzzz
```

##### 2. リモートリポジトリ情報を <font color="Blue">GitHub</font> に書き換える

事前に GitHub 上にリポジトリ「X/Y.git」を作成しておくこと

```
$ git remote set-url origin git@github.com:X/Y.git
```

##### 3. push する

```bash
$ git push origin master
```

以上.
　

# トラブルと対策

##### push すると「error: src refspec main does not match any.」が出てしまう

リモートブランチを間違えている.
下記の場合だと「main」ではなくて、「master」が正解であった.

```bash
$ git push origin main
error: src refspec main does not match any.
error: failed to push some refs to 'git@github.com:X/Y.git'

$ git push origin master
Counting objects: 24, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (18/18), done.
Writing objects: 100% (24/24), 3.51 KiB | 3.51 MiB/s, done.
Total 24 (delta 5), reused 0 (delta 0)
remote: Resolving deltas: 100% (5/5), done.
```

　

# 参考にした情報

・https://deepblue-ts.co.jp/git/git-push-error/